merge(M02): origin/dev(39 통합) 받음 — G1 · G2 지움과 부딪힌 곳 풂
- 남의 새 줄(labor · 일위대가번 SU · 실무문서 · 「전체 항목」 · 수평선 · 알약 켬끔 · 복사해 가져오기)은 살리고 material · 자재조합 · 재료번 · matset 줄만 뺌 - dev 쪽 새 시험(test_m02_item_labor · test_m02_card_sheet_edit)의 재료산출 · 자재조합 자리 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NPJGtfXo6GMbcpiboQC4uK
This commit is contained in:
@@ -27,13 +27,16 @@ from common_util.common_util_storage import resolve_stored_project_path
|
||||
from config.config_db import get_db_pool, run_with_connection
|
||||
from M02_MasterTemplete import M02_Layer_Access as access
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Items as items_store
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Router_Items as items_router
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||||
from M02_MasterTemplete import M02_Table_Fill as fill
|
||||
from M02_MasterTemplete import M02_Template_Layers as layers
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter(prefix="/api/m02", tags=["M02 MasterTemplete Layers"])
|
||||
router = APIRouter(
|
||||
prefix="/api/m02", tags=["M02 MasterTemplete Layers"], route_class=items_router.NotedRoute
|
||||
)
|
||||
|
||||
Layer = Literal["system", "company", "personal", "project"]
|
||||
|
||||
@@ -164,8 +167,10 @@ def _company_of(session: dict[str, Any], project: dict[str, Any] | None) -> int:
|
||||
|
||||
|
||||
async def _same_company_user(session: dict[str, Any], user_id: int, company_id: int) -> None:
|
||||
"""남의 개인 양식 = 그 회사를 맡은 사람만(39-6 · 층 길과 한 규칙) · 그 회사 사람이어야 함."""
|
||||
if user_id == session.get("user_id"):
|
||||
return
|
||||
access.grant(session, "personal", f"{company_id}/{user_id}")
|
||||
if await _user_company(user_id) != company_id:
|
||||
raise HTTPException(status_code=403, detail="같은 회사 사람의 양식만 볼 수 있습니다.")
|
||||
|
||||
@@ -192,7 +197,12 @@ async def _layer_dir(
|
||||
who = session["user_id"] if user_id is None else user_id
|
||||
owner = str(company_id) if layer == "company" else f"{company_id}/{who}"
|
||||
got = access.require(session, layer, owner, write=write)
|
||||
return _ensured(access.folder(got)) if got.mine else access.folder(got)
|
||||
folder = access.folder(got, create=write)
|
||||
if got.mine:
|
||||
return _ensured(folder)
|
||||
if write: # 남의 층 쓰기(맡은 회사 · 39-6) — 구조물 길과 한 벌
|
||||
await items_router.others_write(session, got, folder)
|
||||
return folder
|
||||
|
||||
|
||||
def _ensured(folder: Path) -> Path:
|
||||
@@ -214,9 +224,9 @@ async def list_owners(
|
||||
company: int | None = Query(None),
|
||||
session: dict[str, Any] = Depends(verify_session),
|
||||
) -> list[dict[str, Any]]:
|
||||
"""남의 층 목록(PLAN 27-1c · 펼칠 때 부름) — `[{owner, name}]` · 층 자리가 있는 것만(본인 뺌).
|
||||
회사 = SYSTEM_ADMIN 만 회사 목록 · 개인 = 그 회사 사람(SYSTEM_ADMIN 은 어느 회사나 ·
|
||||
회사 관리자는 자기 회사만)."""
|
||||
"""남의 층 목록(PLAN 27-1c · 펼칠 때 부름) — `[{owner, name}]`.
|
||||
회사 = SYSTEM_ADMIN 만 · 층 자리가 있는 것만(자기 회사는 늘) ·
|
||||
개인 = 그 회사를 맡은 사람(39-6)만 · 회사 사람 전부(나 맨 위 · 집계표 없으면 `비어있음`)."""
|
||||
if layer == "company":
|
||||
if not access.is_system_admin(session):
|
||||
raise HTTPException(status_code=403, detail="회사 목록은 시스템 관리자만 봄.")
|
||||
@@ -225,12 +235,16 @@ async def list_owners(
|
||||
target = session.get("company_id") if company is None else company
|
||||
if target is None:
|
||||
raise HTTPException(status_code=409, detail=access.NO_COMPANY)
|
||||
mine = str(target) == str(session.get("company_id"))
|
||||
if not (access.is_system_admin(session) or (mine and access.is_company_admin(session))):
|
||||
if not access.manages(session, target):
|
||||
raise HTTPException(status_code=403, detail="같은 회사 사람 목록은 회사 관리자만 봄.")
|
||||
me = session.get("user_id")
|
||||
users = await _company_users(int(target))
|
||||
rows = [(f"{target}/{u['user_id']}", u["name"]) for u in users if u["user_id"] != me]
|
||||
users.sort(key=lambda u: u["user_id"] != me) # 나 맨 위
|
||||
return [
|
||||
{"owner": owner, "name": u["name"], "비어있음": _empty(owner)}
|
||||
for u in users
|
||||
for owner in [f"{target}/{u['user_id']}"]
|
||||
]
|
||||
found = []
|
||||
for owner, name in rows:
|
||||
got = access.Grant(layer, owner, False, owner == access.own_owner(session, layer))
|
||||
@@ -242,6 +256,13 @@ async def list_owners(
|
||||
return found
|
||||
|
||||
|
||||
def _empty(owner: str) -> bool:
|
||||
"""개인 층에 집계표가 없음 — 사람 나무 「비어 있음」(폴더를 안 만듦)."""
|
||||
company, user = owner.split("/")
|
||||
table = layers.personal_dir(company, user) / "table" / f"{store.STRUCTURE_TABLE}.json"
|
||||
return not table.is_file()
|
||||
|
||||
|
||||
@router.get("/layers/{layer}/templates")
|
||||
async def list_layer(
|
||||
layer: Layer,
|
||||
@@ -519,7 +540,11 @@ async def list_sources(
|
||||
)
|
||||
return rows
|
||||
|
||||
users = await _company_users(company_id)
|
||||
users = [ # 남의 개인 = 그 회사를 맡은 사람만(39-6)
|
||||
u
|
||||
for u in await _company_users(company_id)
|
||||
if u["user_id"] == session.get("user_id") or access.manages(session, company_id)
|
||||
]
|
||||
projects = await _company_projects(company_id)
|
||||
return {
|
||||
"system": await asyncio.to_thread(layers.list_templates, layers.system_dir()),
|
||||
|
||||
Reference in New Issue
Block a user