From 90e478fe0bcb5cb0c507024432816575daeab0ea Mon Sep 17 00:00:00 2001 From: umsangdon Date: Tue, 29 Sep 2026 13:31:59 +0900 Subject: [PATCH] =?UTF-8?q?fix(M02):=20=EC=9E=90=EC=9E=AC=20=EC=A1=B0?= =?UTF-8?q?=ED=95=A9=20=EC=9D=B4=EB=A6=84=20=EC=98=A4=EB=A5=98=20=EA=B8=80?= =?UTF-8?q?=20=E2=80=94=20=ED=8C=8C=EC=9D=BC=EB=AA=85=20=C2=B7=20=ED=82=A4?= =?UTF-8?q?=20=EC=97=86=EC=9D=B4=20=EC=89=AC=EC=9A=B4=20=EB=A7=90=20?= =?UTF-8?q?=ED=95=9C=20=EC=A4=84=20(PLAN=2021-10=20=ED=9D=A0=207=20?= =?UTF-8?q?=EC=84=9C=EB=B2=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 같은 이름 · 60자 넘는 이름을 틀 검사 앞에서 「이름」 한 줄로 막음 - 오류 글에 이름은 30자에서 자름(…) - 시험: 겹침 글 · 긴 이름 자름 · 60자 넘음 Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01EUypcnp5d1gU2aeKh9F2H7 --- M02_MasterTemplete/M02_MasterTemplete_Matset.py | 16 ++++++++++++++++ resources/tester/test_m02_matset.py | 10 +++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/M02_MasterTemplete/M02_MasterTemplete_Matset.py b/M02_MasterTemplete/M02_MasterTemplete_Matset.py index df87e2fc..09788153 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Matset.py +++ b/M02_MasterTemplete/M02_MasterTemplete_Matset.py @@ -91,6 +91,20 @@ def _clean(row: Any, key: str, keep: dict | None = None) -> dict[str, Any]: } +def _short(name: str, at: int = 30) -> str: + return name if len(name) <= at else name[:at] + "…" + + +def _check_name(rows: list, key: str, name: str) -> None: + """이름 겹침 · 긴 이름 — 틀 검사(파일명 · 키가 섞인 글) 앞에서 쉬운 말 한 줄로 막음.""" + if len(name) > mmc.MAX_이름: + raise store.StoreError(422, {"errors": [f"이름이 너무 김 — {mmc.MAX_이름}자까지"]}) + if any(r.get("키") != key and str(r.get("이름", "")).strip() == name for r in rows): + raise store.StoreError( + 422, {"errors": [f"「{_short(name)}」 이름의 자재 조합이 이미 있음 — 다른 이름으로"]} + ) + + def _save(doc: dict, version: str) -> str: """틀 검사 → 판이 같을 때만 씀 → 새 판.""" if errors := mmc.check_form(FILE, doc): @@ -111,6 +125,7 @@ def create(row: Any, version: str | None = None) -> dict[str, Any]: fixed = _clean(row, key) if fixed["본뜬키"] and fixed["본뜬키"] not in {r.get("키") for r in doc["줄"]}: raise store.StoreError(400, f"본뜬키 「{fixed['본뜬키']}」 — 있는 다른 자재 조합 키여야 함") + _check_name(doc["줄"], key, fixed["이름"]) doc = {**doc, "다음": int(doc.get("다음") or 1) + 1, "줄": [*doc["줄"], fixed]} return {"키": key, "판": _save(doc, have if version is None else version), "줄": fixed} @@ -118,6 +133,7 @@ def create(row: Any, version: str | None = None) -> dict[str, Any]: def edit(key: str, row: Any, version: str) -> dict[str, Any]: doc, _ = _load() fixed = _clean(row, key, keep=_find(doc, key)) + _check_name(doc["줄"], key, fixed["이름"]) doc = {**doc, "줄": [fixed if r.get("키") == key else r for r in doc["줄"]]} return {"키": key, "판": _save(doc, version), "줄": fixed} diff --git a/resources/tester/test_m02_matset.py b/resources/tester/test_m02_matset.py index 7c4589c0..c38addf7 100644 --- a/resources/tester/test_m02_matset.py +++ b/resources/tester/test_m02_matset.py @@ -83,7 +83,15 @@ def test_없는_자재_두_번_이름_본뜬키는_막는다(client) -> None: ok = _new(client, "원본", [M1]).json()["키"] copy = _new(client, "본뜬 것", [M1, M2], 본뜬키=ok).json() assert copy["줄"]["본뜬키"] == ok and copy["키"] != ok - assert _new(client, "원본", [M2]).status_code == 422 # 이름 겹침 + dup = _new(client, "원본", [M2]) # 이름 겹침 — 파일명 · 키 없이 쉬운 말 한 줄 + assert dup.status_code == 422 and dup.json()["detail"]["errors"] == [ + "「원본」 이름의 자재 조합이 이미 있음 — 다른 이름으로" + ] + long = "긴" * 40 + assert _new(client, long, [M1]).status_code == 200 + cut = _new(client, long, [M2]).json()["detail"]["errors"][0] + assert cut.startswith("「" + "긴" * 30 + "…」") and matset.FILE not in cut and "UM0" not in cut + assert _new(client, "긴" * 61, [M1]).json()["detail"]["errors"] == ["이름이 너무 김 — 60자까지"] assert _new(client, "낡은 판", [M2], 판="0000").status_code == 409