Files
Aislo/M02_MasterTemplete/M02_MasterTemplete_Router_Combos.py
T
eomsangdonandClaude Opus 5.5 354e6cd029 feat(M02): 일위대가 조합 층 저장소 · 층 길 — 마스터 · 회사 · 개인(PLAN 27-2a · 27-2c 서버)
- 새 M02_MasterTemplete_Combo_Store · Router_Combos — /api/m02/layers/{layer}/combos 목록 · 하나 · 새로 · 고침 · 지움 · 나무 · 알약 · 미리 보기 · /api/m02/combos/all(세 층)
- 키 장부 UC{회사}-###### · UP{사용자}-######(파일 머리 다음 · 지운 번호 안 씀) · 마스터 UA 는 M01 저장 길 그대로
- 나무 = 폴더 [구분, 상세구분] 깊이 2 · 빈 폴더는 머리 폴더 · 쓰는 조합 든 폴더 지우기 409
- 옛 /api/m01/combo* 길 뺌(logic/combos 만 남김) · 조합 화면 Api 는 M02 마스터 층 길로
- use-combo · 갈라 내기 · 항목 이름 · 면적 알약 · 스냅샷 원본이 세 층 조합을 읽음 · 남의 층 조합 403 · 갈라 낸 조합은 그 층에(시스템 관리자 한정 뺌)
- 시험 옮김(test_m01_combo · test_m01_combo_inputs) · 새 test_m02_combo_layers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BU9gbNE3aWFUvE61pS2WGt
2026-09-30 13:15:10 +09:00

141 lines
4.6 KiB
Python

"""M02 일위대가 조합 층 API(PLAN 27-2a) — `/api/m02/layers/{layer}/combos`(옛 `/api/m01/combo*`).
⚠ 등록은 `main.py`(로그인만) · 층 권한은 `Router_Items._root` 한 규칙:
system 읽기 = 로그인 누구나 · 쓰기 = 시스템 관리자(마스터 조합 · 키 UA)
company 읽기 = 같은 회사 · 쓰기 = 회사 관리자(키 UC{회사}-######)
personal 읽기 · 쓰기 = 본인(키 UP{사용자}-######)
저장소 = `M02_MasterTemplete_Combo_Store`.
"""
from __future__ import annotations
from typing import Any
from fastapi import APIRouter, Depends
from pydantic import BaseModel
from common_util.common_util_auth import verify_session
from M02_MasterTemplete import M02_MasterTemplete_Combo_Store as combos
from M02_MasterTemplete.M02_MasterTemplete_Router_Items import (
Layer,
Session,
_call,
_owner,
_root,
)
router = APIRouter(prefix="/api/m02", tags=["M02 MasterTemplete Combos"])
class ComboBody(BaseModel):
combo: dict[str, Any]
판: str | None = None # 새로 만들 때 빈 글 = 지금 판 · 고칠 때 어긋나면 409
class ComboTreeBody(BaseModel):
"""`{op: add-folder|rename|move|delete, 경로?, 이름?, 새경로?, 키?, 판}` — 폴더 깊이 2."""
op: str
경로: list[str] | None = None
이름: str | None = None
새경로: list[str] | None = None
키: str | None = None
판: str
class PreviewBody(BaseModel):
"""저장 전 미리 보기 — `combo` 는 조합 줄 통째 또는 그 층 키 · `inputs` 는 로직마다."""
combo: dict[str, Any] | str
inputs: dict[str, dict[str, Any]] = {}
@router.get("/combos/all")
def get_all(session: Session = Depends(verify_session)) -> list[dict]:
"""고르기(use-combo · 갈라 내기) — 세 층 `[{layer, owner, 판, 폴더, 줄}]` · 회사 없음 빈 층."""
out = []
for layer in ("system", "company", "personal"):
who = None if layer == "system" else _owner(session, layer, None)
if layer != "system" and who is None:
out.append({"layer": layer, "owner": None, "판": "", "폴더": [], "줄": []})
continue
got = _call(_root(session, layer, who), combos.listing)
out.append({"layer": layer, "owner": who, **got})
return out
@router.get("/layers/{layer}/combos")
def get_combos(layer: Layer, owner: str | None = None, session: Session = Depends(verify_session)):
return _call(_root(session, layer, owner), combos.listing)
@router.get("/layers/{layer}/combos/{key}")
def get_combo(
layer: Layer, key: str, owner: str | None = None, session: Session = Depends(verify_session)
):
return _call(_root(session, layer, owner), combos.one, key)
@router.get("/layers/{layer}/combos/{key}/inputs")
def get_combo_inputs(
layer: Layer, key: str, owner: str | None = None, session: Session = Depends(verify_session)
):
"""조합 알약 — 담은 로직 결과단위 분모마다 물량 하나(M02 면적산출이 받음)."""
return _call(_root(session, layer, owner), combos.pills, key)
@router.post("/layers/{layer}/combos")
def post_combo(
layer: Layer,
body: ComboBody,
owner: str | None = None,
session: Session = Depends(verify_session),
):
folder = _root(session, layer, owner, write=True)
return _call(folder, combos.create, body.combo, body.판 or None)
@router.put("/layers/{layer}/combos/{key}")
def put_combo(
layer: Layer,
key: str,
body: ComboBody,
owner: str | None = None,
session: Session = Depends(verify_session),
):
folder = _root(session, layer, owner, write=True)
return _call(folder, combos.edit, key, body.combo, body.판 or "")
@router.delete("/layers/{layer}/combos/{key}")
def delete_combo(
layer: Layer,
key: str,
판: str = "",
owner: str | None = None,
session: Session = Depends(verify_session),
):
return _call(_root(session, layer, owner, write=True), combos.delete, key, 판)
@router.post("/layers/{layer}/combos/tree")
def post_tree(
layer: Layer,
body: ComboTreeBody,
owner: str | None = None,
session: Session = Depends(verify_session),
):
folder = _root(session, layer, owner, write=True)
return _call(folder, combos.edit_tree, body.model_dump())
@router.post("/layers/{layer}/combos/preview")
def post_preview(
layer: Layer,
body: PreviewBody,
owner: str | None = None,
session: Session = Depends(verify_session),
):
"""보기만 — 수량(inputs)은 이 부름에만 실림 · 저장 안 함 · 읽기 권한."""
return _call(_root(session, layer, owner), combos.preview, body.combo, body.inputs)