- M02_Library_Same_Router — 733-1a 지문(Same 한 벌 · above) 으로 묶음 · 합칠 때 지문 다시 셈(다르면 409) - main.py 에 라우터 등록(로그인만 · 층 쓰기 권한은 길 안에서) - 새 시험 test_733_3_library_same_merge(합치기 참조 옮김 · 금액 같음 · 되돌림 · 지문 · 판 409 · 권한 밖 남김 · 위 층 키 · 일반 사용자 회사 층 403 · SC 수량만 다름) - 새 시험 test_733_3_library_same_screen(부품만 · 날 색 없음 · 나무 메뉴 · 서버 길 짝) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
192 lines
8.7 KiB
Python
192 lines
8.7 KiB
Python
# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
|
||
"""서고 [중복 찾기] · 합치기 · 되돌림(PLAN 733-3 · 요구서_572 3장 4) — 임시 storage.
|
||
|
||
묶음 = 이 층 + 위 층 같은 지문 · 합치기 = 쓰는 곳 참조 → 남김(금액 같음) · 지운 문서 `_합친것/` ·
|
||
되돌림 = 문서 · 참조 되살림 · 지문 · 판 다르면 409 · 권한 밖 · 같은 참조 두 번 = 그 문서 남김 ·
|
||
위 층과 같은 아래 층 문서 = 남김 = 위 층 키 · 일반 사용자 회사 층 = 403.
|
||
"""
|
||
|
||
import pytest
|
||
from fastapi import FastAPI
|
||
from fastapi.testclient import TestClient
|
||
|
||
from common_util.common_util_auth import verify_session
|
||
from M02_MasterTemplete import M02_Labor_Ref as refs
|
||
from M02_MasterTemplete import M02_Library_Same_Router as same_router
|
||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||
from M02_MasterTemplete import M02_Sangeun_Calc as calc
|
||
from resources.tester.test_m02_labor_ref import COMPANY, MINE, world # noqa: F401
|
||
|
||
PCT = "GC001109" # 원/㎡ · 인력 둘 + 「노무비 * 3 / 100」
|
||
USER = {"user_id": 42, "company_id": 7, "role": "USER", "is_master": False, "name": "갑"}
|
||
ADMIN = {**USER, "role": "ADMIN", "name": "관리"}
|
||
URL = "/api/m02/layers/{}/sangeun-same"
|
||
|
||
|
||
@pytest.fixture()
|
||
def api(world):
|
||
app = FastAPI()
|
||
app.include_router(same_router.router)
|
||
who = dict(USER)
|
||
app.dependency_overrides[verify_session] = lambda: who
|
||
got = TestClient(app)
|
||
got.who = who
|
||
return got
|
||
|
||
|
||
def _make(folder, **doc):
|
||
with store.at(folder):
|
||
return refs.create("sangeun", {"단위": "㎡", "더한줄": [], **doc})["이름"]
|
||
|
||
|
||
def _read(folder, key):
|
||
with store.at(folder):
|
||
return store.read("sangeun", key)["문서"]
|
||
|
||
|
||
def _total(folder, key):
|
||
with store.at(folder):
|
||
return calc.calc_doc(store.read("sangeun", key)["문서"])["기준"]["계"]
|
||
|
||
|
||
def _top(ref_keys, at=MINE):
|
||
return [{"참조": {**at, "키": k}, "수량": 2} for k in ref_keys] + [
|
||
{"고정": {"이름": "운반", "단위": "식", "단가": {"경비": 5000}}, "수량": 1}
|
||
]
|
||
|
||
|
||
def _merge(api, keep, gone, 판, layer="personal"):
|
||
body = {"남김": keep, "지움": gone, "판": 판}
|
||
return api.post(URL.format(layer) + "/merge", json=body)
|
||
|
||
|
||
def test_권한_밖이면_안_지움(api, world, monkeypatch):
|
||
me = world["personal"]
|
||
a = _make(me, 이름="가", 바탕={"로직": PCT})
|
||
c = _make(me, 이름="다", 바탕={"로직": PCT})
|
||
top = _make(me, 이름="위", 단위="식", 바탕=None, 더한줄=_top([c]))
|
||
monkeypatch.setattr(same_router, "_can_write", lambda session, at: False)
|
||
판 = api.get(URL.format("personal")).json()["판"]
|
||
res = _merge(api, {**MINE, "키": a}, [c], 판)
|
||
left = res.json()["남김"]
|
||
assert res.status_code == 200 and left[0]["키"] == c and "권한 밖" in left[0]["쓰는곳"][0]
|
||
assert res.json()["합침"] == [] and (me / "sangeun" / f"{c}.json").is_file()
|
||
assert _read(me, top)["더한줄"][0]["참조"]["키"] == c
|
||
|
||
|
||
def test_합치기_참조_옮김_금액_같음_되돌림(api, world):
|
||
me = world["personal"]
|
||
a = _make(me, 이름="밑", 바탕={"로직": PCT})
|
||
b = _make(me, 이름="다른 이름 같은 내용", 바탕={"로직": PCT})
|
||
_make(me, 이름="다른 내용", 바탕={"로직": PCT}, 더한줄=_top([])[-1:])
|
||
top = _make(me, 이름="위", 단위="식", 바탕=None, 더한줄=_top([b]))
|
||
before = _total(me, top)
|
||
got = api.get(URL.format("personal"))
|
||
assert got.status_code == 200, got.text
|
||
view = got.json()
|
||
assert len(view["묶음"]) == 1
|
||
rows = view["묶음"][0]["문서"]
|
||
assert [r["키"] for r in rows] == [a, b] and view["묶음"][0]["꼬리표"] == "내용 같음"
|
||
assert [r["쓰는곳수"] for r in rows] == [0, 1] and not any(r["위층"] for r in rows)
|
||
|
||
res = _merge(api, {**MINE, "키": a}, [b], view["판"])
|
||
assert res.status_code == 200, res.text
|
||
out = res.json()
|
||
assert out["합침"] == [{"키": b, "옮긴곳수": 1}] and out["남김"] == []
|
||
assert out["묶음"] == [] and [g["키"] for g in out["합친것"]] == [b]
|
||
assert not (me / "sangeun" / f"{b}.json").exists()
|
||
assert (me / same_router.GONE / f"{b}.json").is_file()
|
||
assert _read(me, top)["더한줄"][0]["참조"]["키"] == a
|
||
assert _total(me, top) == pytest.approx(before)
|
||
|
||
back = api.post(URL.format("personal") + "/undo", json={"키": b})
|
||
assert back.status_code == 200, back.text
|
||
assert back.json()["되돌린곳수"] == 1 and back.json()["합친것"] == []
|
||
assert (me / "sangeun" / f"{b}.json").is_file()
|
||
assert not (me / same_router.GONE / f"{b}.json").exists()
|
||
assert _read(me, top)["더한줄"][0]["참조"]["키"] == b
|
||
assert _total(me, top) == pytest.approx(before)
|
||
assert api.post(URL.format("personal") + "/undo", json={"키": b}).status_code == 404
|
||
|
||
|
||
def test_지문_판_다르면_409(api, world):
|
||
me = world["personal"]
|
||
a = _make(me, 이름="가", 바탕={"로직": PCT})
|
||
b = _make(me, 이름="나", 바탕={"로직": PCT})
|
||
판 = api.get(URL.format("personal")).json()["판"]
|
||
assert _merge(api, {**MINE, "키": a}, [b], "옛판").status_code == 409
|
||
with store.at(me): # 그새 b 내용이 바뀜
|
||
doc = store.read("sangeun", b)
|
||
store.write("sangeun", b, doc["판"], {**doc["문서"], "더한줄": _top([])[-1:]})
|
||
res = _merge(api, {**MINE, "키": a}, [b], 판)
|
||
assert res.status_code == 409 and "달라짐" in res.text
|
||
assert (me / "sangeun" / f"{b}.json").is_file()
|
||
assert _merge(api, {**MINE, "키": a}, [a], 판).status_code == 400 # 남김 = 지움
|
||
assert _merge(api, {**MINE, "키": a}, ["SK-000099"], 판).status_code == 404
|
||
|
||
|
||
def test_권한_밖_남김_둘다_담은_문서(api, world, monkeypatch):
|
||
me = world["personal"]
|
||
a = _make(me, 이름="가", 바탕={"로직": PCT})
|
||
b = _make(me, 이름="나", 바탕={"로직": PCT})
|
||
c = _make(me, 이름="다", 바탕={"로직": PCT})
|
||
both = _make(me, 이름="둘 다", 단위="식", 바탕=None, 더한줄=_top([a, b]))
|
||
before = _total(me, both)
|
||
판 = api.get(URL.format("personal")).json()["판"]
|
||
res = _merge(api, {**MINE, "키": a}, [b, c], 판) # 둘 다 담은 문서 = 두 줄 모두 a · 금액 같음
|
||
assert res.status_code == 200, res.text
|
||
assert [r["키"] for r in res.json()["합침"]] == [b, c]
|
||
assert [x["참조"]["키"] for x in _read(me, both)["더한줄"][:2]] == [a, a]
|
||
assert _total(me, both) == pytest.approx(before)
|
||
for key in (b, c):
|
||
assert api.post(URL.format("personal") + "/undo", json={"키": key}).status_code == 200
|
||
|
||
|
||
def test_위층과_같으면_남김_위층_키(api, world):
|
||
me, firm = world["personal"], world["company"]
|
||
up = _make(firm, 이름="회사 것", 바탕={"로직": PCT})
|
||
mine = _make(me, 이름="내 것", 바탕={"로직": PCT})
|
||
top = _make(me, 이름="위", 단위="식", 바탕=None, 더한줄=_top([mine]))
|
||
before = _total(me, top)
|
||
view = api.get(URL.format("personal")).json()
|
||
rows = view["묶음"][0]["문서"]
|
||
assert [(r["층"], r["키"], r["위층"]) for r in rows] == [
|
||
("company", up, True),
|
||
("personal", mine, False),
|
||
]
|
||
res = _merge(api, {**COMPANY, "키": up}, [mine], view["판"])
|
||
assert res.status_code == 200, res.text
|
||
assert _read(me, top)["더한줄"][0]["참조"] == {**COMPANY, "키": up}
|
||
assert _total(me, top) == pytest.approx(before)
|
||
assert (firm / "sangeun" / f"{up}.json").is_file()
|
||
# 위 층 문서는 지울 수 없음 · 일반 사용자는 회사 층 합치기 403
|
||
assert _merge(api, {**MINE, "키": mine}, [up], view["판"]).status_code in (403, 404)
|
||
assert api.get(URL.format("company")).status_code == 403
|
||
api.who.update(ADMIN)
|
||
assert api.get(URL.format("company")).status_code == 200
|
||
|
||
|
||
def test_일위대가_수량만_다름_꼬리표(api, world):
|
||
me = world["personal"]
|
||
line = {"고정": {"이름": "운반", "단위": "식", "단가": {"경비": 5000}}, "수량": None}
|
||
with store.at(me):
|
||
keys = [
|
||
refs.create("precombo", {"이름": n, "단위": "m", "담은로직": [line], "본뜬": src})[
|
||
"이름"
|
||
]
|
||
for n, src in (
|
||
(
|
||
"수로BOX 4.0×2.0",
|
||
{"층": "실무자료", "키": "HP-1 제1호표", "실무수량": {"줄": {"0": 3}}},
|
||
),
|
||
(
|
||
"수로BOX 2.5×2.5",
|
||
{"층": "실무자료", "키": "HP-1 제2호표", "실무수량": {"줄": {"0": 7}}},
|
||
),
|
||
)
|
||
]
|
||
got = api.get("/api/m02/layers/personal/precombo-same")
|
||
assert got.status_code == 200, got.text
|
||
group = got.json()["묶음"][0]
|
||
assert group["꼬리표"] == "수량만 다름" and [r["키"] for r in group["문서"]] == keys
|