132 lines
4.4 KiB
Python
132 lines
4.4 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
||
from app.core.database import get_db
|
||
from app.crud import attachment_point as attachment_point_crud
|
||
from app.crud import audit as audit_crud
|
||
from app.deps import require_permission
|
||
from app.models.user import User
|
||
from app.schemas.attachment_point import (
|
||
AttachmentPointCreate,
|
||
AttachmentPointRead,
|
||
AttachmentPointUpdate,
|
||
)
|
||
|
||
router = APIRouter()
|
||
|
||
|
||
def _connection_label(ap) -> str:
|
||
if ap.iso_thread:
|
||
return f"M{ap.iso_thread.diameter_mm}×{ap.iso_thread.pitch_mm}"
|
||
if ap.unc_thread:
|
||
return f"{ap.unc_thread.diameter_fraction}-{ap.unc_thread.tpi} {ap.unc_thread.series}"
|
||
if ap.clamp_connection:
|
||
cc = ap.clamp_connection
|
||
if cc.min_mm is not None:
|
||
return f"{cc.min_mm}–{cc.max_mm} mm"
|
||
return f"{cc.min_in}–{cc.max_in} in"
|
||
if ap.static_connection:
|
||
return f"{ap.static_connection.od_mm} mm OD"
|
||
return "—"
|
||
|
||
|
||
@router.get("", response_model=list[AttachmentPointRead])
|
||
async def list_attachment_points(
|
||
skip: int = 0,
|
||
limit: int = 100,
|
||
db: AsyncSession = Depends(get_db),
|
||
_: User = Depends(require_permission("attachment_points:read")),
|
||
):
|
||
return await attachment_point_crud.list_all(db, skip=skip, limit=limit)
|
||
|
||
|
||
@router.post(
|
||
"", response_model=AttachmentPointRead, status_code=status.HTTP_201_CREATED
|
||
)
|
||
async def create_attachment_point(
|
||
payload: AttachmentPointCreate,
|
||
db: AsyncSession = Depends(get_db),
|
||
actor: User = Depends(require_permission("attachment_points:write")),
|
||
):
|
||
conn_ids = [
|
||
payload.iso_thread_id,
|
||
payload.unc_thread_id,
|
||
payload.clamp_connection_id,
|
||
payload.static_connection_id,
|
||
]
|
||
if sum(v is not None for v in conn_ids) != 1:
|
||
raise HTTPException(
|
||
status_code=400,
|
||
detail="Exactly one connection (iso_thread, unc_thread, clamp_connection, or static_connection) must be provided.",
|
||
)
|
||
ap = await attachment_point_crud.create(db, **payload.model_dump())
|
||
await audit_crud.log(
|
||
db,
|
||
actor=actor,
|
||
action="create",
|
||
resource_type="AttachmentPoint",
|
||
resource_id=ap.id,
|
||
description=audit_crud.describe_create(
|
||
"AttachmentPoint", ap.id, _connection_label(ap)
|
||
),
|
||
)
|
||
return ap
|
||
|
||
|
||
@router.get("/{attachment_point_id}", response_model=AttachmentPointRead)
|
||
async def get_attachment_point(
|
||
attachment_point_id: int,
|
||
db: AsyncSession = Depends(get_db),
|
||
_: User = Depends(require_permission("attachment_points:read")),
|
||
):
|
||
ap = await attachment_point_crud.get(db, attachment_point_id)
|
||
if ap is None:
|
||
raise HTTPException(status_code=404, detail="Attachment point not found")
|
||
return ap
|
||
|
||
|
||
@router.patch("/{attachment_point_id}", response_model=AttachmentPointRead)
|
||
async def update_attachment_point(
|
||
attachment_point_id: int,
|
||
payload: AttachmentPointUpdate,
|
||
db: AsyncSession = Depends(get_db),
|
||
actor: User = Depends(require_permission("attachment_points:write")),
|
||
):
|
||
ap = await attachment_point_crud.get(db, attachment_point_id)
|
||
if ap is None:
|
||
raise HTTPException(status_code=404, detail="Attachment point not found")
|
||
changes = payload.model_dump(exclude_unset=True)
|
||
ap = await attachment_point_crud.update(db, ap, changes)
|
||
await audit_crud.log(
|
||
db,
|
||
actor=actor,
|
||
action="update",
|
||
resource_type="AttachmentPoint",
|
||
resource_id=ap.id,
|
||
description=audit_crud.describe_update("AttachmentPoint", ap.id, changes),
|
||
)
|
||
return ap
|
||
|
||
|
||
@router.delete("/{attachment_point_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||
async def delete_attachment_point(
|
||
attachment_point_id: int,
|
||
db: AsyncSession = Depends(get_db),
|
||
actor: User = Depends(require_permission("attachment_points:delete")),
|
||
):
|
||
ap = await attachment_point_crud.get(db, attachment_point_id)
|
||
if ap is None:
|
||
raise HTTPException(status_code=404, detail="Attachment point not found")
|
||
label = _connection_label(ap)
|
||
await attachment_point_crud.delete(db, ap)
|
||
await audit_crud.log(
|
||
db,
|
||
actor=actor,
|
||
action="delete",
|
||
resource_type="AttachmentPoint",
|
||
resource_id=attachment_point_id,
|
||
description=audit_crud.describe_delete(
|
||
"AttachmentPoint", attachment_point_id, label
|
||
),
|
||
)
|