Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
84 lines
3.1 KiB
Python
84 lines
3.1 KiB
Python
"""Z01 마스터 데이터 라우터 — 읽기 + 기초단가 고치기(2026-09-15 브레인).
|
|
|
|
GET /api/master-data/tree 갈래 → 파일 → 표
|
|
GET /api/master-data/rows?file=&table=&page=&size=&q= 표 줄(쪽 나누기 · 검색)
|
|
GET /api/master-data/base-prices/{kind}?page=&size=&q= 기초단가 한 표(labor|machine|material|oil|rate)
|
|
PUT /api/master-data/base-prices/{kind}/{row_id} {values:{열:값}} → 덮개에만 씀 · null = 되돌리기
|
|
GET /api/master-data/overrides 고친 것·원본 바뀐 것·주인 없는 것(서버 정렬)
|
|
⚠ 권한은 등록하는 쪽(`main.py` · 랩탑 서브)이 `dependencies=[verify_session, require_system_admin]` 로 붙임.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Literal
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from fastapi.responses import JSONResponse
|
|
from pydantic import BaseModel
|
|
|
|
from common_util.common_util_auth import verify_session
|
|
from Z01_MasterData import Z01_MasterData_BasePrices as base_prices
|
|
from Z01_MasterData import Z01_MasterData_Tables as tables
|
|
|
|
router = APIRouter(prefix="/api/master-data", tags=["Z01 MasterData"])
|
|
|
|
|
|
class BasePriceEdit(BaseModel):
|
|
values: dict[str, Any]
|
|
|
|
|
|
@router.get("/tree")
|
|
def get_tree() -> dict:
|
|
return tables.tree()
|
|
|
|
|
|
@router.get("/rows")
|
|
def get_rows(
|
|
file: str, table: str, page: int = 1, size: int = tables.DEFAULT_PAGE_SIZE, q: str = ""
|
|
) -> dict:
|
|
result = tables.rows(file, table, page=page, size=size, q=q)
|
|
if result is None:
|
|
raise HTTPException(status_code=404, detail="없는 파일이나 표입니다.")
|
|
return result
|
|
|
|
|
|
def _kind(kind: str) -> str:
|
|
if kind not in base_prices.KINDS:
|
|
raise HTTPException(status_code=404, detail=f"없는 기초단가: {kind}")
|
|
return kind
|
|
|
|
|
|
@router.get("/base-prices/{kind}")
|
|
def get_base_prices(
|
|
kind: str, page: int = 1, size: int = tables.DEFAULT_PAGE_SIZE, q: str = ""
|
|
) -> dict:
|
|
return base_prices.table(_kind(kind), page=page, size=size, q=q)
|
|
|
|
|
|
@router.put("/base-prices/{kind}/{row_id:path}")
|
|
def put_base_price(
|
|
kind: str, row_id: str, body: BasePriceEdit, session: dict = Depends(verify_session)
|
|
) -> JSONResponse:
|
|
status, payload = base_prices.edit(_kind(kind), row_id, body.values, session.get("user_id"))
|
|
if status != 200:
|
|
raise HTTPException(status_code=status, detail=payload["message"])
|
|
return JSONResponse(content=payload)
|
|
|
|
|
|
@router.get("/overrides")
|
|
def get_overrides(
|
|
kind: str = "", state: str = "", page: int = 1, size: int = tables.DEFAULT_PAGE_SIZE
|
|
) -> dict:
|
|
return base_prices.override_items(kind and _kind(kind), state, page=page, size=size)
|
|
|
|
|
|
class OverrideClear(BaseModel):
|
|
kind: str
|
|
state: Literal["edited", "source_changed", "orphan"]
|
|
|
|
|
|
@router.post("/overrides/clear")
|
|
def clear_overrides(body: OverrideClear, _session: dict = Depends(verify_session)) -> dict:
|
|
"""한 kind 의 그 state 덮개를 한꺼번에 뺌 — kind·state 둘 다 있어야 함(통째로 비우기 막음)."""
|
|
return {"removed": base_prices.clear_overrides(_kind(body.kind), body.state)}
|