fix(M02): 자재 조합 이름 오류 글 — 파일명 · 키 없이 쉬운 말 한 줄 (PLAN 21-10 흠 7 서버)
- 같은 이름 · 60자 넘는 이름을 틀 검사 앞에서 「이름」 한 줄로 막음 - 오류 글에 이름은 30자에서 자름(…) - 시험: 겹침 글 · 긴 이름 자름 · 60자 넘음 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EUypcnp5d1gU2aeKh9F2H7
This commit is contained in:
@@ -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}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user