fix(751-1): 원화 꼴 흠 — M01 · M02 · 서버 글 — 공용 꼴 갈음 · 율 「4.0」 · 중간 값 · 마법사 콤마 · 서고 금액
- 파이썬 짝을 common_util/common_util_money.py 로 옮김(TS 와 같은 이름 · 서버 어디서나 불러옴) - 시험 계산: 율 글자 「4.0 %」 → 숫자 4(서버 _pct) · 중간 값 경비 · 공구손료 등 비목 이름은 1,000 미만도 돈 꼴(870.2455 → 870) - 기초 편집 단가 = 공용 단가 꼴 · 금액 = 소수 1 · 서고 기준 금액 · 구조물 조합 일위대가 금액 = 공용 정수 꼴(124,419.85 → 124,420) - 마법사(확인 · 고르기 · 별칭 장부 · 엑셀 · 우리 금액): 콤마 없음 · 소수 셋 기본 · 부동소수 꼬리 걷음 · 품 비교 꼬리표 지수 꼴(1.235e+05) 걷음 - 다시 잇기 · 붙여넣기 대조 · 찾아 넣기 금액 열 끝 0 없음(22.9 원이 23 으로 숨지 않음) · 흐름 로직 텍스트 수식 비목 소계 정수 - 낡은 시험 고침: test_m02_hopyo_screen 품 비교 보통인부 0.0364 → 0.03636(수량 꼴 유효숫자 넷 규칙으로 파이썬 · TS 통일) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -266,7 +266,7 @@ def _pct(got: dict, body: CalcBody) -> dict:
|
||||
except store.cm.mf.FormulaError:
|
||||
return got
|
||||
lines = labor_doc.pct_extras(whole, logic, got["lines"], got.get("middle") or {})
|
||||
return {**got, "lines": lines}
|
||||
return {**got, "lines": _num(lines)} # 율 Decimal(4.0) 이 글자 「4.0」 으로 나가지 않게
|
||||
|
||||
|
||||
@router.post("/text")
|
||||
|
||||
@@ -19,6 +19,7 @@ from contextvars import ContextVar
|
||||
from decimal import Decimal, InvalidOperation
|
||||
from typing import Any
|
||||
|
||||
from common_util import common_util_money as mfm
|
||||
from M01_MasterData import M01_MasterData_Store as store
|
||||
from M01_MasterData import M01_MasterData_Store_Make as make
|
||||
from M01_MasterData import M01_MasterData_Store_Revise as revise
|
||||
@@ -265,7 +266,8 @@ def text(key: str, inputs: dict, row: dict | None = None) -> dict | None:
|
||||
groups: dict[str, list] = {}
|
||||
for o in got["outputs"]:
|
||||
value = o["value"]
|
||||
shown = f"{value:,}" if isinstance(value, (int, Decimal)) else str(value)
|
||||
# 비목 소계 = 정수 · 그 밖 = 수량 꼴
|
||||
shown = (mfm.fmt_money if o["cost"] else mfm.fmt)(value)
|
||||
line = {"이름": o["name"], "글": shown, "이름글": o["name"], "금액": value, "조각": []}
|
||||
groups.setdefault(o["cost"] or "값", []).append(line)
|
||||
out = [{"비목": k, "줄": v} for k, v in groups.items()]
|
||||
|
||||
@@ -213,6 +213,9 @@ export function buildCalc(host: HTMLElement, ctx: CalcContext): void {
|
||||
);
|
||||
}
|
||||
|
||||
/** 중간 값 이름이 돈 꼴(경비 · 노무비 · 공구손료 · 금액 · 단가 · 노임) — 1,000 미만이어도 돈 꼴 */
|
||||
const MONEY_NAME = /(비|료|액|가|임)$/;
|
||||
|
||||
/** `money` = 결과가 돈(원) — 그때만 결과 값도 정수 · 수량·비율 결과는 소수 그대로 */
|
||||
export function answerView(answer: CalcAnswer, draft: boolean, money: boolean): HTMLElement[] {
|
||||
const note = draft
|
||||
@@ -303,7 +306,7 @@ export function answerView(answer: CalcAnswer, draft: boolean, money: boolean):
|
||||
el("dt", { text: k }),
|
||||
el("dd", {
|
||||
text:
|
||||
money && typeof v === "number" && Math.abs(v) >= 1000
|
||||
money && typeof v === "number" && (Math.abs(v) >= 1000 || MONEY_NAME.test(k))
|
||||
? formatMoney(v)
|
||||
: formatNumber(v),
|
||||
}),
|
||||
|
||||
@@ -20,7 +20,7 @@ import { tx } from "./M01_MasterData_UI_Logic_Text";
|
||||
import { createBadge } from "@ui/ui_template_badge";
|
||||
import { createText } from "@ui/ui_template_text";
|
||||
import { createIconButton } from "@ui/ui_template_button";
|
||||
import { formatNumber } from "../common_util/common_util_money";
|
||||
import { formatLineMoney, formatNumber, formatPrice } from "../common_util/common_util_money";
|
||||
|
||||
export type PickMode = "element" | "table";
|
||||
export type PickDone = (item: ElementBrief, column?: string) => void;
|
||||
@@ -272,14 +272,14 @@ function inputsSection(
|
||||
|
||||
function priceCell(ctx: EditContext, item: HoLine, i: number): HTMLElement {
|
||||
const line = ctx.lines?.[i];
|
||||
if (line) return el("span", { className: "m01-logic__money", text: formatNumber(line.단가) });
|
||||
if (line) return el("span", { className: "m01-logic__money", text: formatPrice(line.단가) });
|
||||
if (item.종류 === "로직" || item.요소.includes("{")) {
|
||||
return el("span", { className: "ui-text ui-text--muted", text: tx("Ho_PriceLater") });
|
||||
}
|
||||
const brief = ctx.prices[item.요소];
|
||||
if (brief === undefined) return el("span", { className: "ui-text ui-text--muted", text: "" });
|
||||
if (brief === null) return createText(tx("Ho_Missing"), "error");
|
||||
return el("span", { className: "m01-logic__money", text: formatNumber(brief.값) });
|
||||
return el("span", { className: "m01-logic__money", text: formatPrice(brief.값) });
|
||||
}
|
||||
|
||||
function hoSection(
|
||||
@@ -343,7 +343,10 @@ function hoSection(
|
||||
textBox(item.단위 ?? "", (v) => set(() => (item.단위 = v)), "m01-logic__unit"),
|
||||
el("div", { className: "m01-logic__pair", children: [tag, qty, table] }),
|
||||
priceCell(ctx, item, i),
|
||||
el("span", { className: "m01-logic__money", text: formatNumber(ctx.lines?.[i]?.금액 ?? "") }),
|
||||
el("span", {
|
||||
className: "m01-logic__money",
|
||||
text: formatLineMoney(ctx.lines?.[i]?.금액 ?? ""),
|
||||
}),
|
||||
cost,
|
||||
dropButton(() => {
|
||||
list.splice(i, 1);
|
||||
|
||||
Reference in New Issue
Block a user