Merge remote-tracking branch 'origin/dev' into sub_desktop_1

This commit is contained in:
2026-09-15 21:58:04 +09:00
9 changed files with 929 additions and 325 deletions
+65 -1
View File
@@ -24,9 +24,34 @@ SOURCE = PROJECT_ROOT / "Z01_MasterData" / "Z01_MasterData_UI_Cells.ts"
_RUNNER = """
import { writeFileSync } from "node:fs";
import {
cellText, clampPage, columnTitle, latestOnly, pageCount, rowCells, shownColumns,
cellInfo, cellText, clampPage, columnTitle, latestOnly, pageCount, parseCellInput, rowCells,
shownColumns,
} from "./Z01_MasterData_UI_Cells.js";
// 기초단가 — 표 수준 editable·locked·formula · 줄 수준 @id·@overrides·@formula (2026-09-15 브레인)
const meta = {
editable: ["daily_wage_krw"],
locked: { hourly_krw: "계산으로 나옴" },
formula: { hourly_krw: "기계경비 = 손료 + 연료 + 노무" },
};
const machineRow = {
"@id": "M-001",
daily_wage_krw: 300000,
hourly_krw: 12340,
"@overrides": { daily_wage_krw: { original: 250000, value: 300000 } },
"@formula": { hourly_krw: "12,340 = 8,200 + 2,140 + 2,000" },
};
// 판정은 서버 state 만 — edited · source_changed · orphan (화면이 original≠current 로 따로 안 셈)
const withState = (state, current) => ({
"@id": "M-002",
daily_wage_krw: 300000,
"@overrides": { daily_wage_krw: { original: 250000, value: 300000, current, state } },
});
// 값은 같아도 서버가 바뀜이라 하면 바뀜 · 값이 달라도 서버가 edited 라 하면 edited
const changedRow = withState("source_changed", 250000);
const sameRow = withState("edited", 270000);
const orphanRow = withState("orphan", undefined);
const wait = (ms, value, fail) =>
new Promise((ok, no) => setTimeout(() => (fail ? no(new Error(value)) : ok(value)), ms));
const fetchLatest = latestOnly(wait);
@@ -62,6 +87,21 @@ writeFileSync(process.argv[2], JSON.stringify({
race: race.map((v) => v ?? null),
raceError: raceError.map((v) => v ?? null),
latestError,
info: [
cellInfo(meta, machineRow, "daily_wage_krw"),
cellInfo(meta, machineRow, "hourly_krw"),
cellInfo({}, { name: "x" }, "name"),
cellInfo(meta, changedRow, "daily_wage_krw"),
cellInfo(meta, sameRow, "daily_wage_krw"),
cellInfo(meta, orphanRow, "daily_wage_krw"),
],
parsed: [
parseCellInput("12,340", 100),
parseCellInput("abc", 100),
parseCellInput("", 100),
parseCellInput("보통인부2", "보통인부"),
parseCellInput("3.5", null),
].map((v) => (v === undefined ? "invalid" : v)),
}));
"""
@@ -109,3 +149,27 @@ def test_칸_글자와_숨김_열(tmp_path: Path) -> None:
assert got["race"] == [None, "new"]
assert got["raceError"] == [None, "new"]
assert got["latestError"] == "thrown boom"
# 고칠 수 있는 칸 · 고쳐짐이면 원래 값 · 못 고치는 칸은 까닭과 식 · 줄마다 값 넣은 식
wage, hourly, plain, changed, same, orphan = got["info"]
# state 가 안 온 고친 칸은 화면이 때우지 않고 「missing」으로 드러냄(서버 버그)
assert wage == {
"editable": True,
"reason": None,
"overridden": True,
"original": 250000,
"state": "missing",
"rule": None,
"filled": None,
}
# 원본이 바뀐 고친 칸 — 고친 값은 그대로 쓰되 또렷이 알림 · 지금 원본 값을 곁들임(브레인)
assert changed["state"] == "source_changed" and changed["current"] == 250000
assert same["state"] == "edited" and "current" not in same
assert orphan["state"] == "orphan"
assert hourly["state"] is None and plain["state"] is None
assert hourly["editable"] is False and hourly["reason"] == "계산으로 나옴"
assert hourly["overridden"] is False and "original" not in hourly
assert hourly["rule"] == "기계경비 = 손료 + 연료 + 노무"
assert hourly["filled"] == "12,340 = 8,200 + 2,140 + 2,000"
assert plain["editable"] is False and plain["reason"] is None and plain["rule"] is None
# 수 칸은 쉼표를 떼고 수로 · 못 읽으면 저장 안 함 · 글자 칸은 글자 그대로 · 빈 칸에 수를 적으면 수
assert got["parsed"] == [12340, "invalid", "invalid", "보통인부2", 3.5]