feat(810-2): 원파일 구조 줄 → 수식 문서 변환 · 원파일 우선 올림 · 전수 대조
- 새 M02_Doc_NativeEst(EST 산근 블록 → 가져온 로직 · 단가 \x03 · 변수 \x11 · 줄참조 \x0c 표지로 정함 · 변수 이름 그대로 · 분수 그림 공식 = 위아래 줄 칸 · 기계 · 산근 · 견적 세 줄 = 로직 값묶음 한 줄 · 소계 61 = 합 밖 · 율 58 · 62 = 덧줄 · 못 읽은 줄 = 보인 값 얼림 + 참고 표지 · 품셈 조건 글 = 추정 표지) - 새 M02_Doc_FromNative(원파일 읽기 · 둘 꼴 · 블록 번 = 엑셀 길과 같음 · STmate = 원문 그대로 M02_San_Emit.stmate · 같은 공사 판정 · EST 일위대가 → 실무자료 호표 꼴) - M02_Sangeun_FromHopyo — 산근 자리 칸 원파일 · 원파일 우선 emit · 안쪽 산근 원파일 코드로 · upload_native(같은 공사 엑셀 HP 에 붙음 · 없으면 새 HP) - M02_Hopyo_Router 올림 — .estx · .stc 이면 upload_native(한 덩이) - M02_Doc_Import — 원파일 문서 소계 덧줄 비목 칸 비움 · 수 하나 변수 출처 원파일 · 머리 원파일 - 수식 문서 셈 짝(master_doc · master_doc_calc ↔ common_util_formula_doc · _calc) — 합밖 + 비목 비움 = 금액만(소계 보임) · 그 밖 그대로 - M02_San_Estx 구조 줄 색인(Index) 칸 · 어디서 왔나 카드 「EST · 원파일」 - 전수 대조 — EST 산근 1,849 · STC 371 블록 수식 문서 셈 = 원파일 저장값(STC 계약단가 82 = 낙찰률 버림 뒤) · 표지 없는 틀린 줄 0 · 목록 docs/raw/요구_1104/_목록_810-2_원파일변환.xlsx - 시험 test_810_2_native_doc(전수 · 꼴 · 문서 셈 거울 · 올림 분기) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -602,7 +602,7 @@ export function check(doc: FormulaDoc): Mark[] {
|
||||
}
|
||||
(doc.금액 ?? []).forEach((l, at) => {
|
||||
const where = `금액 ${l.이름 || at + 1}`;
|
||||
if (![...COSTS, "묶음"].includes(l.비목 as string))
|
||||
if (![...COSTS, "묶음"].includes(l.비목 as string) && !(l.합밖 && !l.비목))
|
||||
out.push(mark("금액 줄", `${where} 비목 「${l.비목}」`));
|
||||
if (l.수량 !== null && l.수량 !== undefined && l.수량 !== "")
|
||||
need(l.수량, `${where} 수량`, true);
|
||||
|
||||
@@ -464,6 +464,7 @@ function money(run: Run, doc: FormulaDoc, rules: Record<string, Rule>) {
|
||||
const price = run.expr(line.단가, where, scope);
|
||||
const kind = line.비목 as string;
|
||||
let parts: Bundle = {};
|
||||
let bare: number | null = null; // 비목 없는 합 밖 줄(소계 보임 · 810-2) — 금액만
|
||||
let why: string | null = null;
|
||||
const stop = (text: string): void => {
|
||||
stopped = true;
|
||||
@@ -474,6 +475,7 @@ function money(run: Run, doc: FormulaDoc, rules: Record<string, Rule>) {
|
||||
why = (qty instanceof Stop ? qty : (price as Stop)).why;
|
||||
} else if (qty instanceof Blank) why = qty.why;
|
||||
else if (!isNum(qty)) stop("수량이 수 아님");
|
||||
else if (qty === 0 && !kind && line.합밖) bare = 0;
|
||||
else if (qty === 0) for (const k of kind === "묶음" ? COSTS : [kind]) parts[k] = 0;
|
||||
else if (price instanceof Blank) why = price.why;
|
||||
else if (kind === "묶음") {
|
||||
@@ -482,11 +484,17 @@ function money(run: Run, doc: FormulaDoc, rules: Record<string, Rule>) {
|
||||
else stop("묶음 줄 단가가 단가산출 묶음 아님");
|
||||
} else if ((COSTS as readonly string[]).includes(kind) && isNum(price))
|
||||
parts[kind] = qty * price;
|
||||
else if (!kind && line.합밖 && isNum(price)) bare = qty * price;
|
||||
else stop(isObj(price) ? "묶음 값 — 칸(.계 · .노무비 …) 필요" : "단가가 수 아님");
|
||||
const rule = line.자리 ?? rules.줄;
|
||||
parts = Object.fromEntries(Object.entries(parts).map(([k, v]) => [k, cut(v, rule) as number]));
|
||||
const keys = Object.keys(parts);
|
||||
const amount = keys.length ? keys.reduce((s, k) => s + parts[k], 0) : null;
|
||||
const amount =
|
||||
bare !== null
|
||||
? (cut(bare, rule) as number)
|
||||
: keys.length
|
||||
? keys.reduce((s, k) => s + parts[k], 0)
|
||||
: null;
|
||||
if (!skip.has(i)) addTo(running, parts);
|
||||
if (line.기호) syms[String(line.기호)] = amount ?? new Blank(why ?? "빈 줄");
|
||||
outs.push({
|
||||
|
||||
Reference in New Issue
Block a user