Merge remote-tracking branch 'origin/sub_laptop_6' into main_laptop_1

This commit is contained in:
2026-10-01 20:03:32 +09:00
3 changed files with 30 additions and 22 deletions
+15 -16
View File
@@ -2,7 +2,8 @@
* M02_DF_Standards.ts
* 단가산출 흐름도 — 단위 · 금액 표준 표(정함 11 · 12)
* 처음 값 = `_standard/단위표준.json` · `금액단위표준.json`(산림품셈 1-2-2 · 원문 흠 그대로 — 사용자가 고침)
* 서버 = `GET · PUT · DELETE /api/m02/df/standards` → {unit, money, saved} · 고친 것은 `_data`(마스터에 안 씀)
* 서버 = `M02_DF_Api` cfStandards · cfStandardsSave · cfStandardsReset(`/api/m02/df/standards`) → {unit, money, saved} ·
* 고친 것은 `_data`(마스터에 안 씀)
* `renderStandards(host, on)` = 시험판 안 「표준 표」 판(두 표 보기 · 칸 고치기 · 저장 · 처음 값으로)
* `standardsList()` = 단위 고르기 · 끝수 제안이 부르는 목록(동기 · 처음엔 번들 값 · 판이 서버 값을 받으면 그것)
* 이 폴더째 지워도 됨.
@@ -10,7 +11,7 @@
import { currentLanguageIndex } from "@ui/ui_template_locale";
import { createButton, el, showConfirmDialog, showToast } from "@ui/ui_template_elements";
import { API_BASE_URL } from "@config/config_frontend";
import { cfStandards, cfStandardsReset, cfStandardsSave, type CfStandards } from "./M02_DF_Api";
import unitDefault from "./_standard/단위표준.json";
import moneyDefault from "./_standard/금액단위표준.json";
import "./M02_DF_Standards.css";
@@ -148,21 +149,12 @@ export const standardsNow = (): Standards => clone(current);
/* ── 서버 ─────────────────────────────────────────────────────────────── */
async function call(method: "GET" | "PUT" | "DELETE", body?: unknown): Promise<Standards> {
const response = await fetch(`${API_BASE_URL}/m02/df/standards`, {
method,
credentials: "include",
headers: { "Content-Type": "application/json" },
body: body === undefined ? undefined : JSON.stringify(body),
});
const data = (await response.json().catch(() => ({}))) as Standards & { detail?: unknown };
if (!response.ok) throw new Error(String(data.detail ?? response.statusText));
return data;
}
/** 서버 답(`M02_DF_Api` CfStandards) → 이 판의 모양 */
const asStd = (v: CfStandards): Standards => v as unknown as Standards;
/** 서버 표 받기 — 못 받으면 처음 값 */
export async function loadStandards(): Promise<Standards> {
current = await call("GET");
current = asStd(await cfStandards());
return clone(current);
}
@@ -311,7 +303,14 @@ export function renderStandards(host: HTMLElement, on: StandardsOn = {}): void {
async function doSave(): Promise<void> {
save.disabled = true;
try {
take(await call("PUT", { unit: work.unit, money: work.money }));
take(
asStd(
await cfStandardsSave({ unit: work.unit, money: work.money } as unknown as Omit<
CfStandards,
"saved"
>),
),
);
showToast(tx("Saved"), "success");
} catch {
showToast(tx("SaveFailed"), "error");
@@ -322,7 +321,7 @@ export function renderStandards(host: HTMLElement, on: StandardsOn = {}): void {
async function doReset(): Promise<void> {
if (!(await showConfirmDialog(tx("ResetAsk"), tx("Reset")))) return;
try {
take(await call("DELETE"));
take(asStd(await cfStandardsReset()));
} catch {
take(clone(ORIGINAL)); // 서버가 없으면 화면만 처음 값
}
+3 -6
View File
@@ -337,18 +337,15 @@ def _run(lg: dict, master, examples: dict | None = None) -> dict:
def test_값_메쌓기_value_는_calc_와_같음(master) -> None:
from M01_MasterData.LogicBuilder import M01_LB_Calc as lb
from M01_MasterData import M01_MasterData_Store as store
_, files = master
rows = {r["키"]: r for d in files.values() if d.get("그룹") == "로직" for r in d["줄"]}
raw = lambda k: json.loads(json.dumps(rows[k], default=_plain)) # noqa: E731
given = {v["name"]: v["example"] for v in SAMPLES["masonry"]["boxes"][0]["input"]["variables"]}
want = lb.calc(raw("GF000219"), {**given, "초과증가율": 80}, {})
want = store.calc("GF000219", {**given, "초과증가율": 80})
assert abs(_run(SAMPLES["masonry"], master)["노무비"] - float(want["sums"]["계"])) < 1
given = {v["name"]: v["example"] for v in SAMPLES["value"]["boxes"][0]["input"]["variables"]}
given["qt"] = given.pop("q")
assert _run(SAMPLES["value"], master)["시간당 작업량"] == float(
lb.calc(raw("GF000133"), given, {})["result"]
store.calc("GF000133", given)["result"]
)
+12
View File
@@ -143,3 +143,15 @@ def test_standardsList_목록() -> None:
(1, 0, "버림"),
(0.1, 1, "버림"),
]
def test_서버_표준_답이_처음_값과_같음() -> None:
"""서버(`M02_DF_Values.standards`) 답 = `_standard` 처음 값 · 그 답으로 만든 목록 = 번들 처음 값 목록"""
from M02_MasterTemplete.DataFlow import M02_DF_Values as dv
mine = STD.parent / "_data" / "시험-없는-폴더" # 만들지 않음 — 고친 것 없음 → 처음 값
assert not mine.exists()
got = dv.standards(STD, mine)
assert got == {"unit": UNIT, "money": MONEY, "saved": False}
server = _node(f"out(S.standardsList({json.dumps(got, ensure_ascii=False)}));")
assert server == _node("out(S.standardsList());")