feat(728-1): SK 단위 바꿈 환산 순수 함수 · 파이썬 · TS 짝 · 거울 시험

- master_unit.swap · split — 같은 성격 = 배 자동 · 부피 ↔ 무게 = 단위중량 · 그 밖 = 사용자 계수 · 계수 없으면 배 없음 + 까닭 글
- A00_Common/master_unit_swap.ts swapUnit — 같은 답(단위 표 · 별칭 · 분모 읽기 옮김)
- 지킴 시험 test_728_1_unit_swap.py(거울 20 사례)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-02 10:08:02 +09:00
co-authored by Claude Opus 5.5
parent 638d3f446d
commit c201a1269d
4 changed files with 298 additions and 0 deletions
@@ -4,6 +4,7 @@
쓰는 곳: 재료 단가 → 줄 단위(`master_pick`) · 자재 맞대기 별칭(`master_material.plain_unit`) ·
조합 알약 배(`M01_MasterData_Store_Combo`) · 엑셀 맞춤 배(`M02_Hopyo_Ours` · `_Match`) ·
표 기준배(`master_basis`) · 계산서 줄 환산 근거(714-1). 서버 단독(③) — TS 는 서버가 준 글만 씀.
- 단 SK 단위 바꿈 환산(`swap` · 728-1)은 짝(①) — `A00_Common/master_unit_swap.ts` · 거울 시험 `test_728_1_unit_swap.py`.
- 개수 묶음(개 · EA · 본 · 매) = 1 : 1 같은 성격 · 조 · 세트는 묶음 밖(한 조 = 여럿).
- 부피 ↔ 무게 = 단위중량 표 CC000337 에서 고른 줄(`unit_weight`)을 받을 때만 · 기본 줄 없음
(사용자 확인 거리) · 밀도(kg ↔ ℓ) · ㎾h 등은 환산 없이 경고 글만.
@@ -119,3 +120,42 @@ def unit_weight(master, kind: str, shape: str, end: str = "위") -> Decimal | No
got = row.get(end)
return None if got is None else Decimal(str(got))
return None
def split(unit) -> tuple[Decimal, str]:
"""기준단위 앞 수 떼기 — 「100본」 → (100, 본) · 「㎥」 → (1, ㎥) · 결과단위 분모 읽기(`per`) 그대로."""
got = per(f"원/{unit}") if str(unit or "").strip() else []
return got[0] if got else (Decimal(1), str(unit or "").strip())
def swap(have, want, density=None, coef=None) -> dict:
"""SK 단위 `have` → `want` 환산(728-1) — `배` = have 1 개가 want 몇 개(1 단위 당 값은 ÷배 · 수량은 ×배).
같은 성격 = 배 자동 · 부피 ↔ 무게 = 단위중량(㎏/㎥) `density` · 그 밖 성격 다름 = 사용자 `coef`
(have 앞 수 뗀 1 단위 = want 앞 수 뗀 몇 단위 · 0 보다 커야) · 계수 없으면 `배` None + 까닭 글(셈 막음)."""
(na, ua), (nb, ub) = split(have), split(want)
out = {"가": [na, ua], "나": [nb, ub], "성격": [kind_of(ua), kind_of(ub)]}
if not ua or not ub:
return {**out, "배": Decimal(1), "계수": None, "근거": ""}
need = None if same_kind(ua, ub) else ("단위중량" if _weighs(ua, ub) else "사용자")
if need == "사용자":
f = Decimal(str(coef)) if coef and Decimal(str(coef)) > 0 else None
else:
f = factor(ua, ub, density)
if f is None:
why = (
f"단위중량({WEIGHT_TABLE}) 골라야 셈"
if need == "단위중량"
else "성격 다름 · 환산 계수 넣어야 셈"
)
return {**out, "배": None, "계수": need, "근거": f"{have} ↔ {want} — {why}"}
ratio = na * f / nb
how = {
"단위중량": f" · 단위중량 {density}㎏/㎥",
"사용자": f" · 계수 1 {ua} = {coef} {ub}",
}.get(need, "")
if ratio == 1:
step = "" if plain(have) == plain(want) else f"{have} = {want}"
else:
by = f"÷{_num(ratio)}" if ratio > 1 else f"×{_num(1 / ratio)}"
step = f"{have} 당 → {want} 당 {by}"
return {**out, "배": ratio, "계수": need, "근거": step + how}