"""산출 조건 [저장]이 운반계획을 다시 세움 — 2026-09-14 브레인 ②(지침 5장 「[저장]·[확정]은 서버가 정본으로 다시 계산」). 구성비·시공법·계수·도쟈 한계거리는 B06 유토곡선(운반계획)의 밑수인데 B08 [저장]이 운반계획을 다시 안 셈 → B06 을 다시 저장하기 전까지 토적표(새 계수) ↔ 운반표(옛 계획)가 갈렸음(계수 칸은 전부터 같은 틈). ⇒ 그 칸이 **바뀐 저장**만 서버 재계산(`recompute_server_side`)을 부름 · 다른 칸 저장은 안 부름(무거움). """ from __future__ import annotations import sys from pathlib import Path import pytest from fastapi import FastAPI from fastapi.testclient import TestClient ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT)) import B08_Quantity.B08_Quantity_Router_Earthwork as earthwork_router # noqa: E402 PROJECT_ID = "56565656-5656-5656-5656-565656565656" URL = f"/api/projects/{PROJECT_ID}/quantity/settings" @pytest.fixture() def calls(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> tuple[TestClient, list]: recorded: list = [] async def fake_run(func, *args): return "project" async def fake_recompute(project_id): recorded.append(str(project_id)) return True monkeypatch.setattr(earthwork_router, "run_with_connection", fake_run) monkeypatch.setattr(earthwork_router, "resolve_stored_project_path", lambda _p: str(tmp_path)) monkeypatch.setattr(earthwork_router, "_recompute_haul_plan", fake_recompute) app = FastAPI() app.include_router(earthwork_router.router) return TestClient(app), recorded def test_운반계획_밑수가_바뀐_저장만_재계산(calls) -> None: client, recorded = calls ratios = {"rock_ratios_pct": {"연암": 60, "보통암": 40}} first = client.put(URL, json=ratios) assert first.status_code == 200 and first.json()["haul_plan_recomputed"] is True assert recorded == [PROJECT_ID] # 같은 값을 다시 저장 — 안 부름 assert client.put(URL, json=ratios).json()["haul_plan_recomputed"] is False # 운반계획과 무관한 칸 — 안 부름 assert ( client.put(URL, json={"topsoil_thickness_m": 0.2}).json()["haul_plan_recomputed"] is False ) assert len(recorded) == 1 for body in ( {"rock_methods": {"연암": "ripping"}}, {"conversion_factors_override": {"soil": {"compacted": 0.85}}}, {"dozer_haul_limit_m": 70}, ): assert client.put(URL, json=body).json()["haul_plan_recomputed"] is True, body assert len(recorded) == 4