fix(M01): 조합 메모·이름 검사 흠 둘 고침
메모 칸이 글자 아닌 값(수량 등)을 받아도 저장되던 것 · 이름이 글자 아니어도 저장되던 것을 막음(sub2 검증 `ref/_검증_조합.md` 일감 24). 메모는 글자·null만, 이름은 서버 400(글자 아님) + check_combo_form 422(빈 이름·60자 넘음·겹침)로 까닭과 함께 거절. _틀.md 10장 갱신 · 재현 시험 포함 4건 추가(21 통과).
This commit is contained in:
@@ -233,6 +233,7 @@ def check_combo_form(name: str, data: dict) -> list[str]:
|
||||
rows_ = data.get("줄")
|
||||
if not isinstance(rows_, list):
|
||||
return out + [f"{name} · 머리 「줄」 목록 없음"]
|
||||
seen_names: dict[str, str] = {}
|
||||
for row in rows_:
|
||||
key = str(row.get("키"))
|
||||
where = f"{name} · {key} {row.get('이름') or ''}".strip()
|
||||
@@ -242,8 +243,16 @@ def check_combo_form(name: str, data: dict) -> list[str]:
|
||||
out.append(f"{where} · 원문번호는 줄에 두지 않음 — 대장에만")
|
||||
if tuple(row) != mcb.COLS:
|
||||
out.append(f"{where} · 열이 한 벌이 아님 — 「{' · '.join(mcb.COLS)}」")
|
||||
if not str(row.get("이름") or "").strip():
|
||||
out.append(f"{where} · 「이름」 없음")
|
||||
name_ = row.get("이름")
|
||||
if not isinstance(name_, str) or not name_.strip():
|
||||
out.append(f"{where} · 「이름」 이 글자 아니거나 없음")
|
||||
else:
|
||||
plain = name_.strip()
|
||||
if len(plain) > mcb.MAX_이름:
|
||||
out.append(f"{where} · 「이름」 이 너무 김({len(plain)}자 — {mcb.MAX_이름}자까지)")
|
||||
if plain in seen_names:
|
||||
out.append(f"{where} · 「이름」 이 같은 조합과 겹침 — {seen_names[plain]}")
|
||||
seen_names.setdefault(plain, key)
|
||||
if row.get("소유") not in mcb.OWNERS:
|
||||
out.append(f"{where} · 소유 「{row.get('소유')}」 — {' · '.join(mcb.OWNERS)} 아님")
|
||||
if not _source_ok(row.get("출처")):
|
||||
|
||||
@@ -17,6 +17,7 @@ GROUP = "일위대가조합"
|
||||
FILE = "일위대가조합.json"
|
||||
TID = "UA"
|
||||
OWNERS = ("현장", "공용")
|
||||
MAX_이름 = 60 # 조합 이름 최대 글자 수 — 관리자가 짓는 짧은 이름이라 이보다 길면 저장 막음
|
||||
# 줄 열 한 벌 — 차례까지 이대로(`_틀.md` 10장)
|
||||
COLS = ("키", "이름", "구분", "상세구분", "단위", "담은로직", "출처", "소유", "비고")
|
||||
ITEM_COLS = ("로직", "메모")
|
||||
@@ -42,7 +43,7 @@ def logic_keys(row: dict) -> list[str]:
|
||||
|
||||
# ── 검사 ──────────────────────────────────────────────────────────────
|
||||
def check_row(whole: mf.Master, row: dict) -> list[str]:
|
||||
"""조합 한 줄 — 빈 조합 · 없는 로직 키 · 같은 로직 두 번 · 조합을 담음(1단만)."""
|
||||
"""조합 한 줄 — 빈 조합 · 없는 로직 키 · 같은 로직 두 번 · 조합을 담음(1단만) · 메모 모양."""
|
||||
where = f"{row.get('키')} {row.get('이름') or ''}".strip()
|
||||
got = items(row)
|
||||
out = [] if got else [f"{where} · 빈 조합 — 담은 로직이 없음"]
|
||||
@@ -56,6 +57,9 @@ def check_row(whole: mf.Master, row: dict) -> list[str]:
|
||||
extra = set(one) - set(ITEM_COLS)
|
||||
if extra:
|
||||
out.append(f"{where} 줄{at} · 모르는 칸 {sorted(extra)}")
|
||||
memo = one.get("메모")
|
||||
if memo is not None and not isinstance(memo, str):
|
||||
out.append(f"{where} 줄{at} · 「메모」 가 글자 아님 「{memo}」 — 수량·계산은 두지 않음")
|
||||
key = str(one.get("로직") or "")
|
||||
if not mk.KEY.fullmatch(key):
|
||||
out.append(f"{where} 줄{at} · 로직 키 모양 아님 「{key}」")
|
||||
|
||||
Reference in New Issue
Block a user