Adding Attachment Points

This commit is contained in:
Ian Roddis committed 2026-07-02 14:06:18 -03:00
1 parent 2767fb1c8e
commit ceae27a12e
15 files changed
+729 -3

No files matched your search

+198
View File
@@ -15,6 +15,7 @@ from app.crud import part_colour as part_colour_crud
from app.crud import part_type as part_type_crud
from app.crud import role as role_crud
from app.crud import scope_model as scope_model_crud
from app.crud import attachment_point as attachment_point_crud
from app.crud import attachment_point_name as apn_crud
from app.crud import clamp_connection as clamp_connection_crud
from app.crud import static_connection as static_connection_crud
@@ -1600,6 +1601,203 @@ async def delete_attachment_point_name(
return Response(status_code=status.HTTP_200_OK)
# --- Attachment Points --------------------------------------------------------
async def _attachment_point_form_ctx(db: AsyncSession) -> dict:
return {
"augmented_parts": await augmented_part_crud.list_all(db),
"attachment_point_names": await apn_crud.list_all(db),
"iso_threads": await iso_thread_crud.list_all(db),
"unc_threads": await unc_thread_crud.list_all(db),
"clamp_connections": await clamp_connection_crud.list_all(db),
"static_connections": await static_connection_crud.list_all(db),
}
def _ap_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.value}"
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("/attachment-points", response_class=HTMLResponse)
async def attachment_points_page(
request: Request,
db: AsyncSession = Depends(get_db),
user: User = Depends(web_require("attachment_points:read")),
):
ctx = await _attachment_point_form_ctx(db)
ctx["user"] = user
ctx["attachment_points"] = await attachment_point_crud.list_all(db)
return templates.TemplateResponse(request, "admin/attachment_points.html", ctx)
# Must come before /{attachment_point_id}
@router.get("/attachment-points/connection-options", response_class=HTMLResponse)
async def attachment_point_connection_options(
request: Request,
connection_type: str = "",
db: AsyncSession = Depends(get_db),
_: User = Depends(web_require("attachment_points:write")),
):
ctx = await _attachment_point_form_ctx(db)
ctx["connection_type"] = connection_type
ctx["ap"] = None
return templates.TemplateResponse(
request, "admin/_attachment_point_connection_select.html", ctx
)
@router.post("/attachment-points", response_class=HTMLResponse)
async def create_attachment_point(
request: Request,
augmented_part_id: int = Form(...),
attachment_point_name_id: int = Form(...),
connection_type: str = Form(""),
iso_thread_id: str = Form(""),
unc_thread_id: str = Form(""),
clamp_connection_id: str = Form(""),
static_connection_id: str = Form(""),
db: AsyncSession = Depends(get_db),
actor: User = Depends(web_require("attachment_points:write")),
):
iso_id = int(iso_thread_id) if iso_thread_id else None
unc_id = int(unc_thread_id) if unc_thread_id else None
clamp_id = int(clamp_connection_id) if clamp_connection_id else None
static_id = int(static_connection_id) if static_connection_id else None
ap = await attachment_point_crud.create(
db,
augmented_part_id=augmented_part_id,
attachment_point_name_id=attachment_point_name_id,
iso_thread_id=iso_id,
unc_thread_id=unc_id,
clamp_connection_id=clamp_id,
static_connection_id=static_id,
)
await audit_crud.log(
db, actor=actor, action="create", resource_type="AttachmentPoint",
resource_id=ap.id,
description=audit_crud.describe_create(
"AttachmentPoint", ap.id, _ap_connection_label(ap)
),
)
ctx = await _attachment_point_form_ctx(db)
ctx["attachment_points"] = await attachment_point_crud.list_all(db)
return templates.TemplateResponse(
request, "admin/_attachment_points_table.html", ctx
)
@router.get("/attachment-points/{attachment_point_id}/edit", response_class=HTMLResponse)
async def edit_attachment_point_row(
request: Request,
attachment_point_id: int,
db: AsyncSession = Depends(get_db),
_: User = Depends(web_require("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")
ctx = await _attachment_point_form_ctx(db)
ctx["ap"] = ap
if ap.iso_thread_id:
ctx["connection_type"] = "iso_thread"
elif ap.unc_thread_id:
ctx["connection_type"] = "unc_thread"
elif ap.clamp_connection_id:
ctx["connection_type"] = "clamp_connection"
elif ap.static_connection_id:
ctx["connection_type"] = "static_connection"
else:
ctx["connection_type"] = ""
return templates.TemplateResponse(
request, "admin/_attachment_point_row_edit.html", ctx
)
@router.get("/attachment-points/{attachment_point_id}/row", response_class=HTMLResponse)
async def attachment_point_row(
request: Request,
attachment_point_id: int,
db: AsyncSession = Depends(get_db),
_: User = Depends(web_require("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 templates.TemplateResponse(
request, "admin/_attachment_point_row.html", {"ap": ap}
)
@router.post("/attachment-points/{attachment_point_id}", response_class=HTMLResponse)
async def update_attachment_point(
request: Request,
attachment_point_id: int,
augmented_part_id: int = Form(...),
attachment_point_name_id: int = Form(...),
connection_type: str = Form(""),
iso_thread_id: str = Form(""),
unc_thread_id: str = Form(""),
clamp_connection_id: str = Form(""),
static_connection_id: str = Form(""),
db: AsyncSession = Depends(get_db),
actor: User = Depends(web_require("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 = {
"augmented_part_id": augmented_part_id,
"attachment_point_name_id": attachment_point_name_id,
"iso_thread_id": int(iso_thread_id) if iso_thread_id else None,
"unc_thread_id": int(unc_thread_id) if unc_thread_id else None,
"clamp_connection_id": int(clamp_connection_id) if clamp_connection_id else None,
"static_connection_id": int(static_connection_id) if static_connection_id else None,
}
ap = await attachment_point_crud.update(db, ap, changes)
await audit_crud.log(
db, actor=actor, action="update", resource_type="AttachmentPoint",
resource_id=attachment_point_id,
description=audit_crud.describe_update(
"AttachmentPoint", attachment_point_id, changes
),
)
return templates.TemplateResponse(
request, "admin/_attachment_point_row.html", {"ap": ap}
)
@router.delete("/attachment-points/{attachment_point_id}")
async def delete_attachment_point(
attachment_point_id: int,
db: AsyncSession = Depends(get_db),
actor: User = Depends(web_require("attachment_points:delete")),
):
ap = await attachment_point_crud.get(db, attachment_point_id)
if ap is not None:
label = _ap_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
),
)
return Response(status_code=status.HTTP_200_OK)
# --- Static Connections -------------------------------------------------------