From fce4def9518c62fce398eb1f6bd2e9da159a8b9a Mon Sep 17 00:00:00 2001 From: bicochan Date: Thu, 1 Oct 2026 14:26:22 +0900 Subject: [PATCH] =?UTF-8?q?[as]=20feat:=20=ED=96=89=EC=A0=95=EC=A7=80?= =?UTF-8?q?=EC=9B=90=20=EC=88=AB=EC=9E=90=20=ED=8F=BC=20=EC=86=8C=EC=88=AB?= =?UTF-8?q?=EC=A0=90=20=EC=9E=90=EB=A6=AC=20=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .../entities/cnstp/model/cnstp-interface.ts | 12 ++++ .../lib/configs/cnstp-config.ts | 12 ++++ .../model/cnstp/cnstp-se-grid-types.ts | 2 + .../ui/cnstp-code-tab-panel.tsx | 2 + .../pages/code-management/ui/cnstp-se-row.tsx | 31 ++++++++- .../sections/biz-cst-matrix-form-section.tsx | 6 +- .../ui/sections/outline-form-section.tsx | 19 ++++-- .../ui/sections/tmplnt-form-section.tsx | 35 ++++++---- apps/as/src/widgets/pbadms-sprt/index.ts | 8 ++- .../lib/business-cost-form-utils.ts | 9 ++- .../lib/business-scale-form-utils.ts | 10 +++ .../widgets/pbadms-sprt/lib/format-utils.ts | 12 +++- .../ui/business-cost-form-section.tsx | 66 ++++++++----------- .../ui/business-scale-form-section.tsx | 54 ++++++--------- 15 files changed, 181 insertions(+), 98 deletions(-) diff --git a/.gitignore b/.gitignore index 871b209f0..6eedddd04 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ settings.json .npmrc .cursor .agent +CLAUDE.MD apps/**/tsconfig.tsbuildinfo packages/**/tsconfig.tsbuildinfo diff --git a/apps/as/src/entities/cnstp/model/cnstp-interface.ts b/apps/as/src/entities/cnstp/model/cnstp-interface.ts index eabd12f46..85ec716e5 100644 --- a/apps/as/src/entities/cnstp/model/cnstp-interface.ts +++ b/apps/as/src/entities/cnstp/model/cnstp-interface.ts @@ -14,6 +14,8 @@ export interface CnstpSeMngResponseDto { cnstpSeCdNm: string; upCnstpCd?: string; cdLvNo: number; + numYn: string; + dcptUnitCnt: number; useYn: string; expln?: string; sortSeq?: number; @@ -41,6 +43,8 @@ export interface CnstpSeMngSaveRequestDto { useYn?: string; expln?: string; sortSeq?: number; + numYn?: string; + dcptUnitCnt?: number; } /** PUT /{cnstpSeCd} 요청 (mode는 서비스에서 U로 설정) */ @@ -51,6 +55,8 @@ export interface CnstpSeMngPutRequestDto { cdLvNo?: number; useYn?: string; expln?: string; + numYn?: string; + dcptUnitCnt?: number; } /** 백엔드 CnstpSeMngTreeDto */ @@ -60,8 +66,11 @@ export interface CnstpSeMngTreeDto { cnstpSeCdNm: string; upCnstpCd?: string; useYn: string; + numYn: string; + dcptUnitCnt?: number; treeLevel: number; treePath: string; + sortPath: string; } /** 백엔드 BizSclTreeDto */ @@ -70,8 +79,11 @@ export interface BizSclTreeDto { cnstpSeCd: string; cnstpSeCdNm: string; useYn: string; + numYn: string; + dcptUnitCnt?: number; treeLevel: number; treePath: string; + sortPath: string; bscPlanQty?: number; bgtRfltQty?: number; tstmDesignQty?: number; diff --git a/apps/as/src/pages/code-management/lib/configs/cnstp-config.ts b/apps/as/src/pages/code-management/lib/configs/cnstp-config.ts index 26bcc8000..5e11dc252 100644 --- a/apps/as/src/pages/code-management/lib/configs/cnstp-config.ts +++ b/apps/as/src/pages/code-management/lib/configs/cnstp-config.ts @@ -21,6 +21,8 @@ const buildSavePayload = createSavePayloadBuilder ({ mode: CNSTP_SE_SAVE_MODE.CREATE, @@ -31,6 +33,8 @@ const buildSavePayload = createSavePayloadBuilder ({ mode: CNSTP_SE_SAVE_MODE.UPDATE, @@ -41,6 +45,8 @@ const buildSavePayload = createSavePayloadBuilder ({ @@ -69,6 +77,8 @@ export const cnstpGridConfig: SeGridConfig< ...(patch.cnstpSeCd !== undefined ? { cnstpSeCd: patch.cnstpSeCd } : {}), ...(patch.cnstpSeCdNm !== undefined ? { cnstpSeCdNm: patch.cnstpSeCdNm ?? "" } : {}), ...(patch.expln !== undefined ? { expln: patch.expln ?? "" } : {}), + ...(patch.numYn !== undefined ? { numYn: patch.numYn } : {}), + ...(patch.dcptUnitCnt !== undefined ? { dcptUnitCnt: patch.dcptUnitCnt } : {}), ...(patch.useYn !== undefined ? { useYn: patch.useYn } : {}), ...(patch.sortSeq !== undefined ? { sortSeq: patch.sortSeq } : {}), }), @@ -77,6 +87,8 @@ export const cnstpGridConfig: SeGridConfig< cnstpSeCd: draft.cnstpSeCd, cnstpSeCdNm: draft.cnstpSeCdNm, expln: draft.expln, + numYn: draft.numYn, + dcptUnitCnt: draft.dcptUnitCnt, useYn: draft.useYn, cdLvNo: draft.cdLvNo, upCnstpCd: parentCode, diff --git a/apps/as/src/pages/code-management/model/cnstp/cnstp-se-grid-types.ts b/apps/as/src/pages/code-management/model/cnstp/cnstp-se-grid-types.ts index 9c2d37c5d..ebf1f01a0 100644 --- a/apps/as/src/pages/code-management/model/cnstp/cnstp-se-grid-types.ts +++ b/apps/as/src/pages/code-management/model/cnstp/cnstp-se-grid-types.ts @@ -13,6 +13,8 @@ export interface CnstpSeDraft { cnstpSeCd: string; cnstpSeCdNm: string; expln: string; + numYn: string; + dcptUnitCnt: number; useYn: string; sortSeq?: number; } diff --git a/apps/as/src/pages/code-management/ui/cnstp-code-tab-panel.tsx b/apps/as/src/pages/code-management/ui/cnstp-code-tab-panel.tsx index 2db182456..b915b10fb 100644 --- a/apps/as/src/pages/code-management/ui/cnstp-code-tab-panel.tsx +++ b/apps/as/src/pages/code-management/ui/cnstp-code-tab-panel.tsx @@ -118,6 +118,8 @@ function CnstpCodeTabPanel() { 코드 코드명 설명 + 숫자 여부 + 소숫점 단위 사용 여부 정렬순서 구분 diff --git a/apps/as/src/pages/code-management/ui/cnstp-se-row.tsx b/apps/as/src/pages/code-management/ui/cnstp-se-row.tsx index 299894821..85c69a3d1 100644 --- a/apps/as/src/pages/code-management/ui/cnstp-se-row.tsx +++ b/apps/as/src/pages/code-management/ui/cnstp-se-row.tsx @@ -62,6 +62,33 @@ function CnstpSeRowComponent({ row, depth, onChange, onAddChild, onDelete }: Cns maxLength={1000} /> + + onChange({ numYn: v })} + className="flex justify-center gap-4" + > +
+ + +
+
+ + +
+
+
+ + + onChange({ dcptUnitCnt: e.target.value ? Number(e.target.value) : undefined }) + } + className="w-20" + /> + - {levelLabel} + + {levelLabel} +
- - - handleCostChange(idx, "bgtRfltAmt", e.target.value)} - readOnly={item.readonly} - className={`text-right ${item.readonly ? "bg-muted" : ""}`} - /> - - - - - handleCostChange(idx, "bscPlanAmt", e.target.value)} - readOnly={item.readonly} - className={`text-right ${item.readonly ? "bg-muted" : ""}`} - /> - - - - - handleCostChange(idx, "tstmDesignAmt", e.target.value)} - readOnly={item.readonly} - className={`text-right ${item.readonly ? "bg-muted" : ""}`} - /> - - + {COST_FIELDS.map((fieldKey) => ( + + + handleCostChange(idx, fieldKey, e.target.value)} + readOnly={item.readonly} + className={`text-right ${item.readonly ? "bg-muted" : ""}`} + /> + + + ))}
{diff > 0 ? `+${diff.toLocaleString()}` : diff.toLocaleString()} diff --git a/apps/as/src/widgets/pbadms-sprt/ui/business-scale-form-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/business-scale-form-section.tsx index de479a0cf..4998e4a72 100644 --- a/apps/as/src/widgets/pbadms-sprt/ui/business-scale-form-section.tsx +++ b/apps/as/src/widgets/pbadms-sprt/ui/business-scale-form-section.tsx @@ -18,6 +18,7 @@ import { } from "@common/components"; import { buildCnstpScaleItems, recalculateBzScaleTotals } from "../lib/business-scale-form-utils"; +import { truncateDecimals } from "../lib/format-utils"; interface BusinessScaleFormData { bzScaleList: Array<{ @@ -31,6 +32,8 @@ interface BusinessScaleFormData { type ScaleFieldKey = "bscPl" | "budgetReflct" | "thtiDsgn"; +const SCALE_FIELDS: ScaleFieldKey[] = ["bscPl", "budgetReflct", "thtiDsgn"]; + function isSameBzScaleCodes( current: BusinessScaleFormData["bzScaleList"], next: BusinessScaleFormData["bzScaleList"], @@ -73,7 +76,9 @@ function BusinessScaleFormSection() { }, [scaleItems, getValues, setValue]); function handleScaleChange(index: number, fieldKey: ScaleFieldKey, value: string) { - const numValue = Number(value) || 0; + const item = scaleItems[index]; + const normalized = item?.numYn ? truncateDecimals(value, item.dcptUnitCnt) : value; + const numValue = Number(normalized) || 0; const draft = [...getValues("bzScaleList")]; draft[index] = { ...draft[index], [fieldKey]: numValue }; const next = recalculateBzScaleTotals(draft, scaleItems); @@ -123,39 +128,20 @@ function BusinessScaleFormSection() { {item.label}
- - - handleScaleChange(idx, "bscPl", e.target.value)} - readOnly={item.readonly} - className={`text-right ${item.readonly ? "bg-muted" : ""}`} - /> - - - - - handleScaleChange(idx, "budgetReflct", e.target.value)} - readOnly={item.readonly} - className={`text-right ${item.readonly ? "bg-muted" : ""}`} - /> - - - - - handleScaleChange(idx, "thtiDsgn", e.target.value)} - readOnly={item.readonly} - className={`text-right ${item.readonly ? "bg-muted" : ""}`} - /> - - + {SCALE_FIELDS.map((fieldKey) => ( + + + handleScaleChange(idx, fieldKey, e.target.value)} + readOnly={item.readonly} + className={`text-right ${item.readonly ? "bg-muted" : ""}`} + /> + + + ))}
{diff > 0 ? `+${diff.toLocaleString()}` : diff.toLocaleString()}