Merge origin/sub_laptop_7 into sub_laptop_8 — PLAN 704-4 규격 표 1차 · M02 일위대가 셈 짝 머리 설명 겹침 양쪽 살림(705-1 고정 줄 · 704-4 규격 열)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,8 @@
|
||||
* 수량(손이 칸보다 앞섬 · 칸 = 알약 키 값) · 반영 = 기준 × 수량 ÷ 배 · 자재 = 재료비만.
|
||||
* 별도계상 자재(222-1 · 빈 칸 = 기본 별도계상) = 반영은 보이되 합에 안 더함(짝 `apart`).
|
||||
* 참조 줄(단가승격 · 사전조합 · 50-3)은 `lineId` = 「참조|층|주인|키」(짝 `M02_Labor_Ref.ref_id`) ·
|
||||
* 고정 줄(705-1)은 「고정|이름|규격|단위」(짝 `M02_Labor_Fixed.fixed_id`) · 기준 = 서버가 낸 줄 단가. */
|
||||
* 고정 줄(705-1)은 「고정|이름|규격|단위」(짝 `M02_Labor_Fixed.fixed_id`) · 기준 = 서버가 낸 줄 단가.
|
||||
* 규격 열(704-4) = 문서 `규격` · 그 열 수량이 있는 줄 = `{손}` 자리(`atSpec` · 짝 `M02_Labor_Spec.at`). */
|
||||
|
||||
import type { CalcLine as LogicLine } from "../M01_MasterData/M01_MasterData_UI_Logic_Api";
|
||||
import type { LogicMat } from "./M02_Labor_LogicMats_Model";
|
||||
@@ -91,10 +92,19 @@ export interface LaborCalc {
|
||||
반영합?: Money;
|
||||
}
|
||||
|
||||
/** 수량만 보는 문서 조각 — 담은 로직 · 자재의 손 값 */
|
||||
/** 규격 열(704-4) — 이름(H · Φ) · 열(화면 차례) · 기본 · 줄 id 마다 열 수량 */
|
||||
export interface LaborSpec {
|
||||
이름: string;
|
||||
열: string[];
|
||||
기본: string;
|
||||
수량: Record<string, Record<string, number>>;
|
||||
}
|
||||
|
||||
/** 수량만 보는 문서 조각 — 담은 로직 · 자재의 손 값 · 규격 열 */
|
||||
export interface LaborQtyDoc {
|
||||
담은로직?: { 로직?: string; 참조?: LaborRef; 고정?: LaborFixed; 수량?: Qty }[];
|
||||
자재?: { 코드: string; 수량?: Qty; 별도계상?: string }[];
|
||||
규격?: LaborSpec | null;
|
||||
}
|
||||
|
||||
function num(raw: unknown): number | null {
|
||||
@@ -116,6 +126,37 @@ export function lineId(one: {
|
||||
return one.로직;
|
||||
}
|
||||
|
||||
/** 쓸 규격 열 — 고른 열이 있으면 그것 · 없으면 기본 · 규격 없음 = null(짝 `M02_Labor_Spec.column`) */
|
||||
export function specColumn(doc: LaborQtyDoc, col?: string | null): string | null {
|
||||
const cols = doc.규격?.열 ?? [];
|
||||
if (!cols.length) return null;
|
||||
return col && cols.includes(col) ? col : doc.규격?.기본 || cols[0];
|
||||
}
|
||||
|
||||
/** 열 끼우기 — 그 열 규격 수량이 있는 줄 · 자재의 수량을 `{손}` 으로(짝 `M02_Labor_Spec.at`) */
|
||||
export function atSpec<D extends LaborQtyDoc>(doc: D, col?: string | null): D {
|
||||
const use = specColumn(doc, col);
|
||||
if (use === null) return doc;
|
||||
const qty = doc.규격?.수량 ?? {};
|
||||
const put = <T extends { 수량?: Qty }>(one: T, id: string | undefined): T => {
|
||||
const v = id !== undefined ? qty[id]?.[use] : undefined;
|
||||
return v !== undefined && v !== null ? { ...one, 수량: { 손: v } } : one;
|
||||
};
|
||||
return {
|
||||
...doc,
|
||||
담은로직: (doc.담은로직 ?? []).map((one) => put(one, lineId(one))),
|
||||
자재: (doc.자재 ?? []).map((one) => put(one, one.코드)),
|
||||
};
|
||||
}
|
||||
|
||||
/** 셈 답에서 칸 값 되살림 `{알약: 수량}` — 열마다 다시 셀 때(짝 `M02_Labor_Spec.given_of`) */
|
||||
export function givenOf(result: LaborCalc): Record<string, number> {
|
||||
const out: Record<string, number> = {};
|
||||
for (const r of [...result.줄, ...result.자재])
|
||||
if (r.수량출처 === "칸" && r.알약 && r.수량 != null) out[r.알약] = r.수량;
|
||||
return out;
|
||||
}
|
||||
|
||||
function zero(): Money {
|
||||
return { 노무비: 0, 재료비: 0, 경비: 0, 계: 0 };
|
||||
}
|
||||
@@ -139,12 +180,15 @@ export function reflect(base: Money, qty: number | null, times: number): Money |
|
||||
return out;
|
||||
}
|
||||
|
||||
/** 기준이 선 계산 답 + 문서 손 값 + 알약 값(`{키: 값}`) → 수량 · 반영 · 합을 새로 채운 답 */
|
||||
/** 기준이 선 계산 답 + 문서 손 값 + 알약 값(`{키: 값}`) → 수량 · 반영 · 합을 새로 채운 답 ·
|
||||
* `col` = 규격 열(없으면 기본 · 704-4) */
|
||||
export function settle(
|
||||
result: LaborCalc,
|
||||
doc: LaborQtyDoc,
|
||||
whole: LaborQtyDoc,
|
||||
given: Record<string, unknown>,
|
||||
col?: string | null,
|
||||
): LaborCalc {
|
||||
const doc = atSpec(whole, col);
|
||||
const have: Record<string, number> = {};
|
||||
for (const [k, raw] of Object.entries(given)) {
|
||||
const v = num(raw);
|
||||
|
||||
Reference in New Issue
Block a user