"""B08 좌측 패널 옵션 길(PLAN 122) — 배관 1본 길이 · 연암 / 경암 비율. GET /api/projects/{id}/quantity/options 지금 값 PUT /api/projects/{id}/quantity/options [저장] — 받은 칸만 정본 자리에 씀 1본 길이 = 프로젝트 층 M02 구조물집계표 변수 `파형강관_1본_m` 한 벌(98 `one_pipe_length` 이 읽는 자리 · M02 표 식 `[$파형강관_1본_m]` 도 같은 값) · 프로젝트 사본이 없으면 시스템 층 문서를 바탕으로 깔고 씀 · M02 [초기화]면 같이 되돌아감. 연암 % = `project_settings.json › quantity › rock_ratios_pct`(연암 · 경암 = 100 − 연암) · 기본 90 은 파일에 안 쓰고 읽을 때 채움(`soft_rock_pct`). """ from __future__ import annotations import asyncio from pathlib import Path from typing import Any from uuid import UUID from fastapi import APIRouter, HTTPException from pydantic import BaseModel, Field from B08_Quantity.B08_Quantity_Router_Hydro import _project_root from B08_Quantity.B08_Quantity_Router_Summary import ONE_LENGTH_VAR, TABLE_NAME, one_pipe_length from common_util.common_util_project_settings import quantity_settings, save_section, soft_rock_pct from M02_MasterTemplete import M02_Template_Layers as layers router = APIRouter(prefix="/api/projects", tags=["B08 Options"]) class OptionsSave(BaseModel): """빈칸(None) = 그 칸은 그대로.""" one_pipe_length_m: float | None = Field(default=None, gt=0, le=100) soft_rock_pct: float | None = Field(default=None, ge=0, le=100) def read_options(root: str | Path) -> dict[str, Any]: soft = soft_rock_pct(quantity_settings(root)) return { "one_pipe_length_m": one_pipe_length(root), "rock_ratios_pct": {"연암": soft, "경암": 100.0 - soft}, } def _write_one_pipe(root: str | Path, value: float) -> None: """프로젝트 층 구조물집계표 변수 한 칸 — 판이 그새 바뀌었으면 `StaleTemplate`.""" folder = layers.project_dir(root) found = layers.read_template(folder, "table", TABLE_NAME) version = found["판"] if found else None found = found or layers.read_template(layers.system_dir(), "table", TABLE_NAME) if found is None: raise HTTPException(status_code=404, detail=f"{TABLE_NAME} 양식이 없습니다 — M02 표부터.") document = found["문서"] document["변수"] = {**(document.get("변수") or {}), ONE_LENGTH_VAR: value} layers.write_template( folder, "table", TABLE_NAME, document, version=version, check_version=True ) def save_options(root: str | Path, body: OptionsSave) -> dict[str, Any]: if body.one_pipe_length_m is not None: _write_one_pipe(root, body.one_pipe_length_m) if body.soft_rock_pct is not None: soft = float(body.soft_rock_pct) ratios = { **(quantity_settings(root).get("rock_ratios_pct") or {}), "연암": soft, "경암": 100.0 - soft, } save_section( root, "quantity", {"rock_ratios_pct": ratios}, replace_keys=("rock_ratios_pct",) ) return read_options(root) @router.get("/{project_id}/quantity/options") async def options_read(project_id: UUID) -> dict[str, Any]: root = await _project_root(project_id) return await asyncio.to_thread(read_options, root) @router.put("/{project_id}/quantity/options") async def options_save(project_id: UUID, body: OptionsSave) -> dict[str, Any]: root = await _project_root(project_id) try: return await asyncio.to_thread(save_options, root, body) except layers.StaleTemplate as error: raise HTTPException( status_code=409, detail="구조물집계표가 그새 바뀌었습니다 — 다시 열고 저장하세요." ) from error