/* M01 방식 C(흐름 그림) 뼈대 검증 헬퍼 — TS를 그 자리에서 트랜스파일해 Node로 돌린다. * (프론트에 JS 테스트 러너가 없어 pytest가 이 스크립트를 부른다 — test_m01_flow_c.py) * 확장자가 `.cjs` 인 까닭은 helper_b05_patch_skirt.cjs 머리말 참고(루트가 ESM). */ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); const source = fs.readFileSync( path.join(__dirname, "..", "..", "M01_MasterData", "M01_MasterData_UI_Test_C_Model.ts"), "utf8", ); const js = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, }).outputText; const moduleBox = { exports: {} }; new Function("exports", "module", "require", js)(moduleBox.exports, moduleBox, require); const { buildFlow, logicRef } = moduleBox.exports; /** 산림품셈 13-4-1 메쌓기 모양 — 표 찾기 하나 · 인력 두 줄 · 덧줄 하나(할증) */ const 메쌓기 = { 키: "GF000219", 원문번호: "13-4-1", 이름: "돌쌓기 메쌓기(인력)", 결과단위: "원/㎡", 출처: "산림품셈 13-4-1", 입력: [ { 이름: "뒷길이", 단위: "㎝", 고르기: [25, 30] }, { 이름: "높이", 단위: "m" }, ], 중간: [{ 이름: "증가율", 식: "찾기(QF000422, 높이=높이).증가율", 출처: "산림품셈 13-4-1 주③" }], 호표: [ { 종류: "인력", 요소: "LB000033", 이름: "석공", 단위: "인", 수량: "찾기(QF000421, 뒷길이=뒷길이).석공", 비목: "노무비", }, { 종류: "로직", 요소: "로직(GC000268, 기계='2702-0020')", 이름: "굴착기", 단위: "시간", 수량: "1 / N", 비목: "경비", }, ], 덧줄: [{ 이름: "잡재료", 식: "노무비 * 0.03", 비목: "재료비", 출처: "산림품셈 13-4-1 주①" }], 끝수: null, }; const 답 = { ok: true, lines: [ { 이름: "석공", 단위: "인", 수량: 1.2, 단가: 300000, 금액: 360000, 비목: { 노무비: 360000 } }, { 이름: "굴착기", 단위: "시간", 수량: 0.5, 단가: 80000, 금액: 40000, 비목: { 경비: 40000 } }, { 이름: "잡재료", 단위: "식", 수량: 1, 단가: 10800, 금액: 10800, 비목: { 재료비: 10800 } }, ], sums: { 노무비: 360000, 재료비: 10800, 경비: 40000, 계: 410800 }, middle: { 증가율: 15 }, }; /** 돈이 아닌 로직 — 결과 식 하나 */ const 작업량 = { 키: "GF000118", 원문번호: "9-16-1", 이름: "노체포설 시간당 작업량", 결과단위: "㎥/hr", 출처: "산림품셈 9-16-1", 입력: [{ 이름: "토질", 고르기: ["보통토", "암괴"] }], 중간: [{ 이름: "E", 식: "찾기(QF000300, 토질=토질).E" }], 결과: { 식: "3600 * q * E / Cm" }, }; const kinds = (columns) => columns.map((c) => c.kind); const box = (columns, kind, i) => columns.find((c) => c.kind === kind).boxes[i]; const out = { logicRef: [logicRef("로직(GC000268, 기계='2702-0020')"), logicRef("LB000033") ?? null], 칸: kinds(buildFlow(메쌓기, 답, {}, { 뒷길이: "25" })), 칸_계산전: kinds(buildFlow(메쌓기, null, {}, {})), 칸_돈아님: kinds(buildFlow(작업량, { ok: true, result: 42.5, middle: { E: 0.8 } }, {}, {})), }; { const columns = buildFlow(메쌓기, 답, {}, { 뒷길이: "25", 높이: "4" }); const 입력 = box(columns, "입력", 0); const 중간 = box(columns, "중간", 0); const 수량 = box(columns, "수량", 0); const 단가1 = box(columns, "단가", 0); const 단가2 = box(columns, "단가", 1); const 덧줄 = box(columns, "덧줄", 0); const 계 = box(columns, "계", 0); const 비목 = columns.find((c) => c.kind === "비목").boxes; out.값 = { 입력값: 입력.value, 입력출처: 입력.detail, 중간값: 중간.value, 중간식: 중간.detail[0], 수량값: 수량.value, 수량식: 수량.detail[0], 단가노트: 단가1.note, 단가값: 단가1.value, 로직: 단가2.logic ?? null, 로직아님: 단가1.logic ?? null, 덧줄값: 덧줄.value, 덧줄식: 덧줄.detail[0], 비목: 비목.map((b) => [b.label, b.value]), 비목상세: 비목.map((b) => b.detail), 계값: 계.value, 묶음: columns.find((c) => c.kind === "수량").boxes.map((b) => b.cost), id: [수량.id, 단가1.id, 덧줄.id, 계.id], }; } { const columns = buildFlow(메쌓기, null, { LB000033: null }, {}); out.계산전 = { 수량값: box(columns, "수량", 0).value, 수량식: box(columns, "수량", 0).detail[0], 단가막힘: box(columns, "단가", 0).bad === true, 계값: box(columns, "계", 0).value, }; } { const columns = buildFlow(메쌓기, { ok: false, reason: "입력 없음" }, {}, {}); out.멈춤 = { 칸: kinds(columns), 계값: box(columns, "계", 0).value }; } { const columns = buildFlow(작업량, { ok: true, result: 42.5, middle: { E: 0.8 } }, {}, {}); out.돈아님 = { 중간값: box(columns, "중간", 0).value, 결과값: box(columns, "계", 0).value, 결과식: box(columns, "계", 0).detail[0], }; } process.stdout.write(JSON.stringify(out));