fix(822-2b): 내 기계 연료 + 전력 둘 다 허용 · 새 식 둘(GC001200 연료 + 전력 · GC001201 + 조종원)

- 내 기계 저장의 「주연료 · 전력은 하나만」 막음 뺌 — 불러오기 자동 생성(경쟁사 파워트로웰 = 손료 + 휘발유 + 잡품 + 전력)이 막히던 것
- 꼴 고름(logic_key) 연료 + 전력 → GC001200 · + 조종원(직종 있음) → GC001201 · 직종 없는 조종원 = 까닭
- 조종원 줄을 한 식에 넣지 않음 — 수식 계산기가 빈 직종 「LB:」 를 못 받음(전력 식 GC001196 · 1197 짝과 같은 꼴)
- 수식 문서 두 줄 더함 · 802-2 대조 목록 다시 씀(두 줄 같음) · M01 정본 기계 · 다른 식 금액 그대로
- 낡은 시험: test_821_4 키대장 다음 번호 수 박은 기대 → 쓴 · 버린 번호보다 뒤(결번 재사용 없음) ·
  test_822_2 연료 + 전력 None · 저장 400 기대 → 새 식 · 미리보기 = 서버 값

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-12 18:57:42 +09:00
co-authored by Claude Opus 5.5
parent 33bf9aa2cc
commit 3eeb7c3cc3
8 changed files with 228 additions and 14 deletions
+7 -5
View File
@@ -12,6 +12,7 @@
이 색인을 읽음 — 층을 모르는 길(`/api/m02/logic-lib/machine-hourly` 등)은 M01 만.
식 고름(채운 칸 · `logic_key` — M01 기계 목록 밖 줄도 같은 규칙 · 822-2) = 연료 + 조종원 GC000268(직종 없음
GC000275) · 연료만 GC000272(손료계수 한 칸 GC001198) · 조종원만 GC000276 · 전력 GC001196(+ 조종원 GC001197) ·
연료 + 전력 GC001200(+ 조종원 GC001201 · 822-2b 경쟁사 기계) ·
없음 GC000273 · 직접 GC001199(시간당 값 = 셈 꼴 값 칸 노무비 · 재료비 · 경비).
권한(본인 개인 층 · 맡은 회사 관리자)은 길(`M02_MyMachine_Router`) 몫.
"""
@@ -46,6 +47,7 @@ LOGIC = {(True, True): "GC000268", (True, False): "GC000272",
(False, True): "GC000276", (False, False): "GC000273"} # fmt: skip
JOB_IN, ONE_FUEL = "GC000275", "GC001198" # 직종 입력 · 손료계수 한 칸 연료
POWER, POWER_CREW, DIRECT_KEY = "GC001196", "GC001197", "GC001199"
FUEL_POWER, FUEL_POWER_CREW = "GC001200", "GC001201" # 연료 + 전력(+ 조종원) — 경쟁사 구성(822-2b)
def mine(key: Any) -> bool:
@@ -136,7 +138,7 @@ def _pos(v: Any) -> bool:
def logic_key(row: dict) -> str | None:
"""꼴(채운 칸) → 시간당 경비 식 키 · 못 고름(직종 없는 조종원만 · 연료 + 전력 · 수 아닌 연료 글) = None ·
"""꼴(채운 칸) → 시간당 경비 식 키 · 못 고름(직종 없는 조종원 · 수 아닌 연료 글) = None ·
계수 셋(상각 · 정비 · 관리) 없음 = 손료계수 한 칸 식(연료만) · 그 밖은 그 식 + 모자란 칸 까닭."""
if row.get("방식") == DIRECT:
return DIRECT_KEY
@@ -144,8 +146,10 @@ def logic_key(row: dict) -> str | None:
fuel, crew, power = (_pos(vals.get(k)) for k in ("주연료", "조종원", "전력"))
job = bool(vals.get("조종원직종"))
three = all(vals.get(k) is not None for k in COEFS)
if vals.get("주연료") not in (None, "", 0) and not fuel or fuel and power:
if vals.get("주연료") not in (None, "", 0) and not fuel:
return None
if fuel and power:
return FUEL_POWER_CREW if crew and job else None if crew else FUEL_POWER
if power:
return POWER_CREW if crew and job else None if crew else POWER
if fuel and not crew:
@@ -181,7 +185,7 @@ def hourly(row: dict, index: Any) -> dict[str, Any]:
mf = m01.cm.mf
key = logic_key(row)
if key is None:
return {"ok": False, **head, "reason": "식 없음 — 연료 · 전력은 하나만"}
return {"ok": False, **head, "reason": "식 없음 — 조종원직종 없음"}
logic = index.logic(key)
given = {i["이름"]: (i.get("고르기") or [""])[0] for i in logic.get("입력") or []}
given["기계"] = str(row.get("원문번호"))
@@ -239,8 +243,6 @@ def clean(raw: Any) -> dict[str, Any]:
need = ("가격", "손료계수") if how == EASY else ("가격", *RATIOS)
if lost := [k for k in need if not vals.get(k)]:
raise _bad(f"빈 칸 — {' · '.join(lost)}")
if vals.get("주연료") and vals.get("전력"):
raise _bad("주연료 · 전력은 하나만(원문 운전경비 표 한 칸)")
drop = (*RATIOS, *COEFS) if how == EASY else ()
vals = {k: v for k, v in vals.items() if k not in drop}
if how == BOOK: