Merge remote-tracking branch 'origin/dev' into sub_desktop_1
This commit is contained in:
@@ -63,6 +63,7 @@ export const SPEC_KINDS = [
|
||||
"masonry_slope",
|
||||
"masonry_back_length",
|
||||
"stone_kind",
|
||||
"machine_productivity",
|
||||
"masonry_class",
|
||||
] as const;
|
||||
|
||||
|
||||
@@ -344,7 +344,18 @@ def _sorted(rows: list[dict[str, Any]], column: str, desc: bool) -> list[dict[st
|
||||
|
||||
#: 돌쌓기 표준경사는 B06 횡단설계가 같은 값으로 기울기를 그림 — 아홉 중 **그림에도 닿는** 하나(브레인).
|
||||
_SLOPE_NOTICE = "고치면 횡단 도면 모양도 함께 바뀜 — B06 횡단설계가 같은 값으로 벽 기울기를 그림"
|
||||
_EXTRA_NOTICE = {"rate": _RATE_NOTICE, "masonry_slope": _SLOPE_NOTICE}
|
||||
#: 같은 「1:0.3」 이 두 자리에 있음(코덱스 검증 2) — 값은 같으나 **축과 근거가 다름**.
|
||||
#: masonry_slope = 품셈 13-4-4 [주]⑪ 표준경사(직고 · 메/찰 · 성토/절토 축 · 원문표)
|
||||
#: masonry_class.face_slope = 교본 7-3 돌흙막이(구조물 **형식**별 기본값 · 판정이 안 되는 자리의 종전값)
|
||||
_CLASS_NOTICE = (
|
||||
"전면 기울기 기본값은 **교본 7-3 형식별 값** — 품셈 표준경사(직고·성토/절토 축)는 「돌쌓기 표준경사」 표에 따로 있음"
|
||||
" · 같은 1:0.3 이라도 **축과 근거가 다름**(판정이 안 되는 자리에서만 이 값으로 섬)"
|
||||
)
|
||||
_EXTRA_NOTICE = {
|
||||
"rate": _RATE_NOTICE,
|
||||
"masonry_slope": _SLOPE_NOTICE,
|
||||
"masonry_class": _CLASS_NOTICE,
|
||||
}
|
||||
|
||||
|
||||
def notice(kind: str) -> list[str]:
|
||||
@@ -357,12 +368,18 @@ def spec(kind: str, columns: list[str]) -> dict[str, Any]:
|
||||
if kind == "machine":
|
||||
return machine.spec(columns)
|
||||
if kind in base_tables.SPEC:
|
||||
editable = [c for c in base_tables.SPEC[kind]["editable"] if c in columns]
|
||||
spec_of = base_tables.SPEC[kind]
|
||||
editable = [c for c in spec_of["editable"] if c in columns]
|
||||
axis = {a for r in base_rows(kind) for a in r.get("@axis", ())}
|
||||
told = spec_of.get("locked") or {} # 계산값처럼 까닭이 따로인 칸
|
||||
return {
|
||||
"editable": editable,
|
||||
"locked": {c: _KEY if c in axis else _SOURCE for c in columns if c not in editable},
|
||||
"formula": {},
|
||||
"locked": {
|
||||
c: told.get(c) or (_KEY if c in axis else _SOURCE)
|
||||
for c in columns
|
||||
if c not in editable
|
||||
},
|
||||
"formula": {k: v for k, v in (spec_of.get("formula") or {}).items() if k in columns},
|
||||
}
|
||||
editable = {
|
||||
"labor": ["daily_wage_krw"],
|
||||
|
||||
@@ -362,9 +362,17 @@ SPEC: dict[str, dict[str, Any]] = {
|
||||
"editable": ["reuse_count", "ratio_pct", "daily_area_m2"],
|
||||
},
|
||||
"rebar_complexity": {
|
||||
# ⚠ 단가 참고값은 **B09 가 자재 단가로 셈한 값**이라 고칠 칸이 아님(코덱스 검증 1 · 2026-09-16).
|
||||
# 사용자 잣대 「마스터 = 계산으로 나오는 값이 아니라 값 그 자체」와 어긋나 editable 에서 뺌.
|
||||
"file": "rebar_complexity",
|
||||
"build": _rebar_complexity,
|
||||
"editable": ["price_krw_per_ton"],
|
||||
"editable": [],
|
||||
"locked": {
|
||||
"price_krw_per_ton": "계산값 — B09 가 자재 단가로 셈(표시 전용 · 밑값을 고쳐야 바뀜)"
|
||||
},
|
||||
"formula": {
|
||||
"price_krw_per_ton": "갈래별 이형철근 단가 참고값 = B09 가 자재 단가에서 셈 — 표시 전용(B08 계산에 안 듦)"
|
||||
},
|
||||
},
|
||||
"timber_structure_class": {
|
||||
"file": "timber_structure_class",
|
||||
|
||||
@@ -66,9 +66,8 @@ def test_아홉이_기초단가와_같은_길로_섬(client: TestClient) -> None
|
||||
assert table["total"] == len(table["rows"]) > 0, kind
|
||||
ids = _ids(table)
|
||||
assert len(ids) == len(set(ids)), kind # ⭐ 열쇠가 겹치면 덮개가 엉뚱한 줄에 붙음
|
||||
assert table["editable"] and set(table["editable"]) <= {
|
||||
c["key"] for c in table["columns"]
|
||||
}, kind
|
||||
assert set(table["editable"]) <= {c["key"] for c in table["columns"]}, kind
|
||||
assert table["editable"] or kind == "rebar_complexity", kind # 철근은 값이 다 계산·글
|
||||
assert set(table["locked"]) | set(table["editable"]) == set(table["sortable"]), kind
|
||||
axis = {a for r in base_prices.base_rows(kind) for a in r.get("@axis", ())}
|
||||
assert {table["locked"][c] for c in axis if c in table["locked"]} == {
|
||||
@@ -252,3 +251,23 @@ def test_꺼낸_값은_코드가_쓰던_것과_원문과_같음() -> None:
|
||||
for ton, speeds in _DOZER_SPEEDS[track].items():
|
||||
for gear, (forward, reverse) in speeds.items():
|
||||
assert (str(forward), str(reverse)) == original[ton][gear], (track, ton, gear)
|
||||
|
||||
|
||||
def test_계산값은_고칠_칸이_아니고_까닭이_보임(client: TestClient) -> None:
|
||||
"""코덱스 검증 1 — 철근 단가 참고값은 **B09 계산값**인데 고칠 수 있는 마스터 값으로 앉아 있었음."""
|
||||
rebar = _get(client, "rebar_complexity", size=10)
|
||||
assert "price_krw_per_ton" not in rebar["editable"]
|
||||
assert "계산값" in rebar["locked"]["price_krw_per_ton"]
|
||||
assert "표시 전용" in rebar["formula"]["price_krw_per_ton"]
|
||||
machine = _get(client, "machine", size=1) # 기계 계산 넷도 같은 꼴(잠김 + 식)
|
||||
for column in ("hourly_loss_krw", "hourly_fuel_krw", "hourly_operator_krw", "hourly_total_krw"):
|
||||
assert "계산값" in machine["locked"][column] and column in machine["formula"]
|
||||
|
||||
|
||||
def test_같은_기울기가_두_자리인_까닭을_표가_말함(client: TestClient) -> None:
|
||||
"""코덱스 검증 2 — 값은 같은 1:0.3 이나 **축과 근거가 다름**(품셈 직고·성절토 ↔ 교본 형식별)."""
|
||||
notice = _get(client, "masonry_class", size=1)["notice"]
|
||||
assert any("교본 7-3" in line and "돌쌓기 표준경사" in line for line in notice)
|
||||
assert any("축과 근거가 다름" in line for line in notice)
|
||||
slope = _get(client, "masonry_slope", size=1)["notice"]
|
||||
assert any("횡단 도면" in line for line in slope) # 표준경사 쪽 알림은 그대로
|
||||
|
||||
@@ -157,6 +157,7 @@ export const ui_locales_b3 = {
|
||||
Z01_MasterData_Base_masonry_slope: ["돌쌓기 경사", "Masonry slope"],
|
||||
Z01_MasterData_Base_masonry_back_length: ["뒷길이", "Back length"],
|
||||
Z01_MasterData_Base_stone_kind: ["돌종류", "Stone kind"],
|
||||
Z01_MasterData_Base_machine_productivity: ["기계 작업량", "Machine productivity"],
|
||||
Z01_MasterData_Base_masonry_class: ["갈래", "Masonry class"],
|
||||
Z01_MasterData_Overrides: ["고친 것 모아 보기", "Edited values"],
|
||||
Z01_MasterData_Edit_Can: [
|
||||
|
||||
Reference in New Issue
Block a user