feat(751-3): M01 · M02 셈 끝수 = 품셈 1-2-2 버림 — 줄 0.1 원 · 비목 소계 1 원 · 계 = 셋 합 · B09 와 같은 값

- 끝수 한 곳 `master_cut.py`(B09 `rounddown` 재사용) — 엔진 답에 입힘: 줄 비목마다 0.1 원 버림 · 하위 로직 줄 = 하위 끝수 계 × 수량 · 덧줄 = 버린 줄 합으로 다시 셈 · 비목 합 1 원 버림 · 중간 칸도 버린 값
- 쓰는 곳: M01 시험 계산(`check_master.calc`) · 읽는 식(`master_text.lines`) · 옛 조합 미리보기(`master_combo`) · M02 `run_line`(단가산출 · 일위대가 · 펼침) · 별도계상 뺀 기준 · 켜쌓기율 곱 뒤 · 일위대가 반영 · 반영합 · 비율 줄 · 사전조합 안 줄
- 일위대가 반영 TS 짝(`Labor_Calc.ts`) 같은 끝수 · 거울 헬퍼가 상대 경로 .ts 가져옴
- B09 = `run_line(raw=True)` 엔진 날 값(제 단가로 다시 버림 · % 덧줄 율 비 그대로) — 검증_sub3 B09 247 칸 전후 같음
- `master_text` 꼴 셋 = `common_util_money` 로 갈음(줄 금액 `fmt_line_money` · 식 안 금액 = 버린 0.1 원)
- 화면: 상세 줄 금액 · 시험 계산 줄 · 중간 돈 = `formatLineMoney` · 일위대가 반영 칸 0.1 원 · 상세 바닥 · 박스 · 인력재료경비 비목 소계 = 줄 합 1 원 버림
- 테스트1 네 보기 · 서고 목록 = 124,419(옛 124,420 / 124,419.85) · 재료 줄 11,694.6 + 23,425.6 + 1,404.8 = 소계 36,525
- 새 지킴 시험 test_751_3_money_cut
- 옛 날 금액(끝수 없음)을 대조하던 시험 24 파일 고침 — 까닭 = 금액 규칙이 줄 0.1 원 · 소계 1 원 버림으로 바뀜(고정 값 → 새 값 · 줄 합 = 계 → 줄 합 아래 비목마다 1 원 안 · 곱 비 = 끝수 폭 안) · 실무 xlsx 영월 엑셀 같음 22 → 23 · 이어 붙이는 TS 시험(704_3 · 717_2b)에 `rounddown` 같은 식

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-03 06:16:01 +09:00
co-authored by Claude Opus 5.5
parent d8af573f1c
commit f4be6782a5
40 changed files with 484 additions and 162 deletions
@@ -7,8 +7,7 @@
* 어느 박스도 안 쓰는 입력(공통 옵션)도 모든 박스에 같이(737-3 · 한 값 · 어디서 바꿔도 모두 따라감)
* 「계산식」 열 = 값 든 식(「268,908 × 0.12」 · 서버 `글`) + 표 · 요소 · 로직 알약 + 그 줄 입력 칩 · 변수 이름 식(`이름글`)은 마우스 올리면
* 맨 아래 = 한 줄 4 칸 — 비목 소계 셋(노무비 · 재료비 · 경비 — 장비 노무는 여기서 인력과 더해짐) + 계 · 화면(모달) 바닥에 붙음(737-1)
* 줄 누름 = 그 줄 자료 모달(`_LogicLab_Modal.ts`) · 고침 고리(`edit`) 있으면 모달 안 「그 자리 고침」(`_LogicLab_Cover.ts`)
* 값 = 서버 셈 그대로(박스 소계 · 비목 소계만 줄 금액 합) · 화면에서 다시 셈 안 함
* 줄 누름 = 그 줄 자료 모달(`_LogicLab_Modal.ts`) · 고침 고리(`edit`) 있으면 모달 안 「그 자리 고침」(`_LogicLab_Cover.ts`) · 값 = 서버 셈 그대로(박스 소계 · 비목 소계만 줄 금액 합 1 원 버림 751-3)
* ========================================================================== */
import { createBadge } from "@ui/ui_template_badge";
@@ -30,7 +29,7 @@ import type {
} from "./M01_MasterData_UI_Logic_Api";
import { pctView } from "./M01_MasterData_UI_Logic_Api";
import { formatNumber } from "./M01_MasterData_UI_Logic_Edit";
import { formatMoney, formatPrice } from "./M01_MasterData_UI_Logic_Money";
import { formatLineMoney, formatMoney, formatPrice } from "./M01_MasterData_UI_Logic_Money";
import { tx } from "./M01_MasterData_UI_Logic_Text";
import { pickMaterial } from "./M01_MasterData_UI_Logic_CalcPick";
import { coverForm, type CoverPart, type LineCover } from "./M01_MasterData_UI_LogicLab_Cover";
@@ -44,6 +43,7 @@ import {
type PickCond,
} from "./M01_MasterData_UI_LogicLab_Modal";
import { buildFoot, FOOT_KEYS, type FootKey } from "./M01_MasterData_UI_LogicLab_Foot";
import { rounddown } from "../B09_Estimation/B09_Estimation_Calc_Base";
import { fragmentRow, type Fragment } from "./M01_MasterData_UI_LogicLab_Pill";
import { tl } from "./M01_MasterData_UI_LogicLab_Text";
@@ -428,7 +428,7 @@ const COLS: Column[] = [
{ label: tl("Col_Amount"), width: "13%", align: "end" },
];
const money = (v: number | null): string => (v === null ? "" : formatMoney(v));
const money = (v: number | null): string => (v === null ? "" : formatLineMoney(v)); // 줄 0.1 원(751-3)
/** 계산식 칸 — 값 든 식(계산 뒤) · 계산 전 = 수량 식 · 알약 · 이름 식은 풍선(748-3 옵션 값 꼬리표 없음) */
function formulaCell(e: Entry, text = ""): HTMLElement {
@@ -508,7 +508,7 @@ type Unfoldable = TextLine & { 펼침?: SheetUnfold | null };
function mergedRows(m: HoMerged<Entry>, ctx: HoContext): HTMLTableRowElement[] {
const first = m.몫[0];
const share = (cost: string): string =>
formatMoney(
formatLineMoney(
m.몫
.filter((x) => (x.share ?? COST_OF[x.group]) === cost)
.reduce((s, x) => s + (x.amount ?? 0), 0),
@@ -622,7 +622,7 @@ function boxCard(
);
const sub = tableRow(COLS, [
{ content: `${name} ${tl("Subtotal")}`, colSpan: 5 },
calculated ? formatMoney(b.소계) : "—",
calculated ? formatMoney(rounddown(b.소계, 0)) : "—", // 751-3 소계 1 원 버림
]);
sub.classList.add("m01lab__subtotal");
sub.dataset.box = b.묶음;
@@ -668,10 +668,10 @@ export function buildHo(ctx: HoContext): HTMLElement[] {
const sums = Object.fromEntries(
FOOT_KEYS.map((g) => [
g,
all.filter((e) => e.group === g).reduce((s, e) => s + (e.amount ?? 0), 0),
rounddown(all.filter((e) => e.group === g).reduce((s, e) => s + (e.amount ?? 0), 0)),
]),
) as Record<FootKey, number>;
const total = all.reduce((s, e) => s + (e.amount ?? 0), 0);
) as Record<FootKey, number>; // 751-3 비목 소계 = 줄 합 1 원 버림 · 계 = 셋 합(서버와 같은 값)
const total = FOOT_KEYS.reduce((s, g) => s + sums[g], 0);
return [
...(boxes.length || !common.length ? [] : [commonCard(optionRows(common, ctx))]),
...boxes.map((b) => boxCard(b, ctx, calculated, common)),