Merge remote-tracking branches 'origin/main_laptop_1', 'origin/sub_laptop_7' and 'origin/sub_laptop_8' into sub_laptop_6
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
* · 서고 모드(50-3 · `mode`) = 사전조합 — 이름 칸 · 단가산출 로직 표 · 자재목록(175-1) · 원문(면적 · 다이어그램 없음) ·
|
||||
* 정보 칸 구분 · 상세구분(51-12 · 고름) · 일위대가 상세와 같은 [로직 추가] · 표 · 동작(51-11) · 수량 손 입력(기본 1)
|
||||
* · 로직 줄 구분 드롭다운(134-1 · 단가산출 | 단가승격 · 서고 모드엔 없음)
|
||||
* · 맨 위 엑셀 꼴 격자(704-3 · `Labor_Grid`) · 읽기만 카드는 격자만
|
||||
* ========================================================================== */
|
||||
|
||||
import {
|
||||
@@ -64,6 +65,7 @@ import { openLogicPicker, withHopyo } from "./M02_MasterTemplete_Labor_Pick";
|
||||
import { logicMatRows } from "./M02_MasterTemplete_Labor_LogicMats";
|
||||
import { setLogicMark, setMark } from "./M02_MasterTemplete_Labor_MatMarks";
|
||||
import { logicTable, matTable, qtyShort } from "./M02_MasterTemplete_Labor_Rows";
|
||||
import { laborGrid } from "./M02_MasterTemplete_Labor_Grid";
|
||||
import { tc } from "./M02_MasterTemplete_Labor_Text";
|
||||
import { insideKeys, releaseTied } from "./M02_Labor_LogicMats_Model";
|
||||
import { keepKnown } from "./M02_Labor_Values_Model";
|
||||
@@ -135,6 +137,7 @@ export function mountLaborDetail(
|
||||
let pills = new Map<string, { 이름?: string; 단위?: string }>();
|
||||
const dirty = (): boolean => areaDirty || JSON.stringify(cur) !== saved;
|
||||
|
||||
const gridHost = el("div", { attrs: { "data-labor-grid": "" } }); // 704-3 엑셀 꼴 격자(맨 위)
|
||||
const logicHost = el("div");
|
||||
const matHost = el("div");
|
||||
const dgHost = el("div");
|
||||
@@ -215,6 +218,7 @@ export function mountLaborDetail(
|
||||
),
|
||||
);
|
||||
const draw = (): void => {
|
||||
gridHost.replaceChildren(laborGrid(cur, calc ?? last, logics));
|
||||
drawLogic();
|
||||
matHost.replaceChildren(
|
||||
matTable(
|
||||
@@ -642,8 +646,11 @@ export function mountLaborDetail(
|
||||
}),
|
||||
]),
|
||||
// 사전조합 = 같은 [로직 추가](51-11)
|
||||
section(tc("Logics_Title"), opt.card ? null : addLogic, logicHost),
|
||||
section(tc("Labor_Mats"), opt.card ? null : addMat, matHost),
|
||||
section(tc("Grid_Title"), null, gridHost),
|
||||
...[
|
||||
section(tc("Logics_Title"), opt.card ? null : addLogic, logicHost),
|
||||
section(tc("Labor_Mats"), opt.card ? null : addMat, matHost),
|
||||
].filter(() => edit || !opt.card), // 읽기만 카드 = 격자만
|
||||
...(opt.card || lib ? [] : [dgBox]),
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/* =============================================================================
|
||||
* M02_MasterTemplete_Labor_Grid.ts
|
||||
* 일위대가 엑셀 꼴 격자(704-3) — 문서 · 서버 calc 답 → 공용 격자(`ui_template_hopyo_grid` · B09 일위대가표와 같은 꼴).
|
||||
* 일위대가 카드 · 상세(`Labor_Detail`)가 위에 붙임. 값은 calc 답 그대로(여기서 셈하지 않음):
|
||||
* 머리 = 일위대가번 · 단위 · 1 단위 합계(`반영합`)
|
||||
* 로직 줄 = 이름(별칭 앞섬) · 규격(옵션 값 · 켜쌓기) · 수량 · 분모 · 단가 = 기준 ÷ 배 · 금액 = 반영 · 꼬리표 품셈
|
||||
* 자재 줄 = 이름 · 규격 · 수량 · 단위 · 재료비 단가 = 기준단가 · 금액 = 반영 · 별도계상은 비고 「합계 밖」
|
||||
* 빈 줄(금액 모름 · 수량 없음) = 합계 줄 「빈 줄 n」 붉게 — 701-4 경고와 같은 줄
|
||||
* ========================================================================== */
|
||||
|
||||
import {
|
||||
createHopyoGrid,
|
||||
HOPYO_TAG,
|
||||
type HopyoBlock,
|
||||
type HopyoLine,
|
||||
type HopyoMoney,
|
||||
} from "@ui/ui_template_hopyo_grid";
|
||||
import type { ItemLogic } from "./M02_MasterTemplete_Api_Fetch";
|
||||
import type { LaborCalc, LaborCost, LaborDoc } from "./M02_MasterTemplete_Labor_Api";
|
||||
import { lineId } from "./M02_MasterTemplete_Labor_Calc";
|
||||
import { tc } from "./M02_MasterTemplete_Labor_Text";
|
||||
import { valueLine } from "./M02_Labor_Values_Model";
|
||||
|
||||
const money = (m: LaborCost | null | undefined, times = 1): HopyoMoney =>
|
||||
m
|
||||
? {
|
||||
sum: m.계 / times,
|
||||
labor: m.노무비 / times,
|
||||
material: m.재료비 / times,
|
||||
expense: m.경비 / times,
|
||||
}
|
||||
: {};
|
||||
|
||||
/** 문서 + calc 답 → 호표 하나 — calc 없으면(계산 중) 금액 빈 칸 · 빈 줄 0 */
|
||||
export function laborBlock(
|
||||
doc: LaborDoc,
|
||||
calc: LaborCalc | null,
|
||||
logics: ReadonlyMap<string, ItemLogic>,
|
||||
): HopyoBlock {
|
||||
const logicLines = doc.담은로직.map((row): HopyoLine => {
|
||||
const id = lineId(row) ?? "";
|
||||
const line = calc?.줄.find((l) => lineId(l) === id);
|
||||
const logic = logics.get(row.로직);
|
||||
const layer =
|
||||
row.켜쌓기율 != null ? tc("Labor_Layer").replace("{n}", String(row.켜쌓기율)) : "";
|
||||
const qty = line?.수량 ?? null;
|
||||
return {
|
||||
name: row.별칭 || ((row.참조 ? line?.이름 : logic?.이름) ?? row.참조?.키 ?? row.로직),
|
||||
spec: [valueLine(logic?.입력 ?? [], row.입력값).text, layer].filter(Boolean).join(" · "),
|
||||
qty,
|
||||
unit: line?.분모 ?? (row.참조 ? "" : (logic?.결과단위 ?? "")),
|
||||
prices: money(line?.기준, line?.배 || 1),
|
||||
amounts: money(line?.반영),
|
||||
note: line?.까닭 ?? (calc && qty === null ? tc("Grid_NoQty") : (row.참조?.키 ?? row.로직)),
|
||||
tag: HOPYO_TAG.pum,
|
||||
};
|
||||
});
|
||||
const matLines = doc.자재.map((mat): HopyoLine => {
|
||||
const line = calc?.자재.find((m) => m.코드 === mat.코드);
|
||||
const qty = line?.수량 ?? null;
|
||||
const price = line?.기준단가 ?? null;
|
||||
const cost = line?.반영 ?? null;
|
||||
return {
|
||||
name: mat.이름 ?? mat.코드,
|
||||
spec: mat.규격 ?? "",
|
||||
qty,
|
||||
unit: mat.단위 ?? "",
|
||||
prices: { sum: price, material: price },
|
||||
amounts: { sum: cost, material: cost },
|
||||
note:
|
||||
line?.까닭 ??
|
||||
(calc && qty === null
|
||||
? tc("Grid_NoQty")
|
||||
: mat.별도계상 !== "직접계산"
|
||||
? tc("Grid_Apart") // 짝 `settle` 의 aside 와 같은 규칙
|
||||
: mat.코드),
|
||||
};
|
||||
});
|
||||
const lines = [...logicLines, ...matLines];
|
||||
return {
|
||||
key: doc.열,
|
||||
name: doc.일위대가번 || doc.열,
|
||||
unit: doc.단위 ?? "",
|
||||
total: money(calc?.반영합),
|
||||
lines,
|
||||
...(calc ? {} : { blank: 0 }),
|
||||
};
|
||||
}
|
||||
|
||||
/** 격자 하나(읽기 전용) */
|
||||
export const laborGrid = (
|
||||
doc: LaborDoc,
|
||||
calc: LaborCalc | null,
|
||||
logics: ReadonlyMap<string, ItemLogic>,
|
||||
): HTMLElement => createHopyoGrid([laborBlock(doc, calc, logics)]).root;
|
||||
@@ -173,6 +173,10 @@ const TEXT = {
|
||||
Lib_Base: ["기준 금액", "Base amount"],
|
||||
Lib_Date: ["고친 날", "Modified"],
|
||||
// 서고 구분 · 연결(51-12)
|
||||
// 엑셀 꼴 격자(704-3)
|
||||
Grid_Title: ["일위대가표", "Unit-price sheet"],
|
||||
Grid_NoQty: ["수량 없음", "No quantity"],
|
||||
Grid_Apart: ["별도계상 · 합계 밖", "Separate · not in total"],
|
||||
} as const satisfies Record<string, readonly [string, string]>;
|
||||
|
||||
export type ComboTextKey = keyof typeof TEXT;
|
||||
|
||||
Reference in New Issue
Block a user