- 까닭: 복사본 목록이 사본마다 원본 단가 묶음을 다시 모음(자재 후보 찾기 같은 조건 되풀이 · m01.logic 검사) - 목록 ?folder= = 그 복사본 하나만 원본 대조 · 모달은 고르는 구조물 폴더만 - 재료 후보 찾기 = 마스터 색인 하나에 같은 조건 한 번 · 로직 파일 이름만 찾음 - 모달 한 번 보이는 동안 사본 부분 · 셈 한 번만(카드 · 일위대가 · 상태 줄 공유) - 사본 7개 모달 열기 13.4초 → 처음 0.43초 · 다시 0.06초 · 원본판 · 단가 묶음 전후 같음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JywHxQuWPk6UYXTebyrBoU
129 lines
5.4 KiB
Python
129 lines
5.4 KiB
Python
"""구조물 조합 고르기 모달 로딩 속도 (PLAN 156-2 · 임시 저장소 · 임시 마스터 사본).
|
|
|
|
- 목록 `?folder=` = 그 복사본 하나만(원본 대조도 그 하나만) · 값은 통째 목록의 그 줄과 같음
|
|
- 원본 대조(`build_source`)는 재료 후보 찾기를 같은 조건마다 한 번만 ·
|
|
`m01.logic`(검사 · 단가 미리보기) 안 부름
|
|
- 값은 그대로 — 기억을 비우고 다시 모아도 단가 묶음 · 원본판이 같음
|
|
- 모달 쪽 — 목록은 그 폴더만 · 복사본 부분 · 셈은 한 번 보이는 동안 한 번만
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import time
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.testclient import TestClient
|
|
|
|
from common_util.common_util_auth import verify_session
|
|
from M01_MasterData import M01_MasterData_Store as m01
|
|
from M02_MasterTemplete import M02_Item_Copy as copies
|
|
from M02_MasterTemplete import M02_Item_Prices as prices
|
|
from M02_MasterTemplete import M02_MasterTemplete_Router_Layers as layer_routes
|
|
from M02_MasterTemplete import M02_Project_Items_Router as items_router
|
|
from M02_MasterTemplete.M02_Item_Source import build_source, version_of
|
|
from resources.tester.test_item_copy_complete import ( # noqa: F401 — 고정물
|
|
PIPE,
|
|
_save,
|
|
master_copy,
|
|
world,
|
|
)
|
|
|
|
UI = Path(__file__).resolve().parents[2] / "ui_template"
|
|
WALL = {"layer": "system", "owner": None, "key": "SS000022", "name": "돌쌓기"}
|
|
|
|
|
|
def _two(root: Path) -> None:
|
|
"""관 지점 둘 — 같은 항목 하나 · 다른 항목 하나."""
|
|
_save(
|
|
root,
|
|
[
|
|
{"chainage_m": 40.0, "source": "user", "summary_item": PIPE},
|
|
{"chainage_m": 80.0, "source": "user", "summary_item": WALL},
|
|
],
|
|
)
|
|
|
|
|
|
def test_목록_folder_는_그_하나만_값은_통째와_같음(world, monkeypatch): # noqa: F811
|
|
root = world["root"]
|
|
_two(root)
|
|
whole = {row["폴더"]: row for row in copies.list_items(root)}
|
|
assert set(whole) == {"pipe@40.0", "pipe@80.0"}
|
|
calls: list[Any] = []
|
|
real = copies.source_changed
|
|
monkeypatch.setattr(copies, "source_changed", lambda m: calls.append(m) or real(m))
|
|
assert copies.list_items(root, "pipe@80.0") == [whole["pipe@80.0"]]
|
|
assert len(calls) == 1 # 원본 대조 = 그 하나만
|
|
assert copies.list_items(root, "없음") == []
|
|
|
|
|
|
def test_길_folder_거름(world, monkeypatch): # noqa: F811
|
|
root = world["root"]
|
|
_two(root)
|
|
|
|
async def fake_row(project_id: str) -> dict[str, Any]:
|
|
return {"company_id": 3, "storage_path": str(root)}
|
|
|
|
monkeypatch.setattr(layer_routes, "_project_row", fake_row)
|
|
monkeypatch.setattr(layer_routes, "resolve_stored_project_path", lambda path: path)
|
|
app = FastAPI()
|
|
app.include_router(items_router.router)
|
|
app.dependency_overrides[verify_session] = lambda: {"role": "USER", "company_id": 3}
|
|
client = TestClient(app)
|
|
base = "/api/projects/p1/items"
|
|
assert len(client.get(base).json()["항목"]) == 2
|
|
got = client.get(base, params={"folder": "pipe@40.0"}).json()["항목"]
|
|
assert [row["폴더"] for row in got] == ["pipe@40.0"]
|
|
|
|
|
|
def test_원본_대조는_같은_후보_찾기를_한_번만(world, monkeypatch): # noqa: F811
|
|
found: list[str] = []
|
|
real = prices.mf.candidates
|
|
monkeypatch.setattr(
|
|
prices.mf, "candidates", lambda w, c, *a: found.append(repr(c)) or real(w, c, *a)
|
|
)
|
|
monkeypatch.setattr(prices, "_FOUND", (None, {}))
|
|
|
|
def no_logic(key: str) -> dict:
|
|
raise AssertionError("m01.logic 은 검사 · 단가 미리보기까지 돌아 느림 — 파일 이름만 찾음")
|
|
|
|
monkeypatch.setattr(m01, "logic", no_logic)
|
|
first = build_source(PIPE)
|
|
once = len(found)
|
|
assert once and len(set(found)) == once # 같은 조건은 한 번만
|
|
again = build_source(PIPE)
|
|
assert len(found) == once # 두 번째 대조 = 후보 찾기 안 함
|
|
assert version_of(again) == version_of(first)
|
|
|
|
|
|
def test_기억을_비워도_단가_묶음_원본판_같음(world, monkeypatch): # noqa: F811
|
|
root = world["root"]
|
|
_two(root)
|
|
before = {row["폴더"]: row["원본판"] for row in copies.list_items(root)}
|
|
monkeypatch.setattr(prices, "_FOUND", (None, {}))
|
|
for folder, item in (("pipe@40.0", PIPE), ("pipe@80.0", WALL)):
|
|
assert version_of(build_source(item)) == before[folder]
|
|
assert not any(row["마스터바뀜"] for row in copies.list_items(root))
|
|
|
|
|
|
def test_목록_시간_상한(world): # noqa: F811
|
|
"""복사본 둘 · 두 번째 목록(기억 있음)은 0.5초 안 — 옛 길은 항목마다 2~5초."""
|
|
root = world["root"]
|
|
_two(root)
|
|
copies.list_items(root)
|
|
start = time.perf_counter()
|
|
copies.list_items(root)
|
|
assert time.perf_counter() - start < 0.5
|
|
|
|
|
|
def test_모달은_그_폴더만_읽고_부분_셈은_한_번():
|
|
detail = (UI / "ui_template_item_picker_detail.ts").read_text(encoding="utf-8")
|
|
assert "infos ??= await items.list(folder);" in detail
|
|
assert "copyReads.set(part" in detail and "(copyCalc ??= " in detail
|
|
assert "items.read(" not in detail and "items?.calc(" not in detail # 다 한 번 부름 길로
|
|
show = detail[detail.index("function show(") :]
|
|
assert "copyReads = new Map();" in show and "copyCalc = null;" in show # 보일 때마다 새로
|
|
project = (UI / "ui_template_item_picker_project.ts").read_text(encoding="utf-8")
|
|
assert "folder ? `${base}?folder=${enc(folder)}` : base" in project
|