Adding scope import

This commit is contained in:
Ian Roddis committed 2026-07-16 20:15:35 -03:00
1 parent cda15df2ed
commit 69cbfa2d3f
18 files changed
+1165 -3

No files matched your search

+78 -3
View File
@@ -3,7 +3,16 @@
import math
import urllib.parse
from fastapi import APIRouter, Depends, Form, HTTPException, Request, status
from fastapi import (
APIRouter,
Depends,
File,
Form,
HTTPException,
Request,
UploadFile,
status,
)
from fastapi.responses import HTMLResponse, RedirectResponse, Response
from sqlalchemy.ext.asyncio import AsyncSession
@@ -34,6 +43,7 @@ from app.models.user import User
from app.services import augmented_part_sync as augmented_part_sync_service
from app.services import fit_matching as fit_matching_service
from app.services import odata as odata_service
from app.services import scope_import as scope_import_service
from app.web.templates import templates
router = APIRouter(prefix="/admin", include_in_schema=False)
@@ -1344,6 +1354,64 @@ async def filter_imported_parts(
)
# --- Scope Import ------------------------------------------------------------
@router.get("/scope-import", response_class=HTMLResponse)
async def scope_import_page(
request: Request,
db: AsyncSession = Depends(get_db),
user: User = Depends(web_require("augmented_parts:write")),
):
return templates.TemplateResponse(
request,
"admin/scope_import.html",
{"user": user, "expected_columns": scope_import_service.EXPECTED_COLUMNS},
)
@router.post("/scope-import", response_class=HTMLResponse)
async def upload_scope_import(
request: Request,
file: UploadFile = File(...),
db: AsyncSession = Depends(get_db),
actor: User = Depends(web_require("augmented_parts:write")),
):
filename = file.filename or ""
if not filename.lower().endswith(".xlsx"):
return templates.TemplateResponse(
request,
"admin/_scope_import_result.html",
{"error": "Expected an .xlsx spreadsheet."},
)
data = await file.read()
try:
result = await scope_import_service.import_from_bytes(db, data)
except Exception as exc: # noqa: BLE001
return templates.TemplateResponse(
request,
"admin/_scope_import_result.html",
{"error": f"Could not read spreadsheet: {exc}"},
)
await audit_crud.log(
db,
actor=actor,
action="update",
resource_type="AugmentedPart",
resource_id=None,
description=(
f"Scope import ({filename}): {result.created} created, "
f"{result.updated} updated, {result.skipped} skipped, "
f"{result.errors} errors"
),
)
return templates.TemplateResponse(
request,
"admin/_scope_import_result.html",
{"result": result},
)
# --- Augmented Parts ---------------------------------------------------------
@@ -2026,7 +2094,12 @@ async def _fit_view(db: AsyncSession, fit, part_id: int) -> dict:
fit.augmented_part_a_id,
)
other_part = await augmented_part_crud.get(db, other_part_id)
return {"fit": fit, "own_ap": own_ap, "other_ap": other_ap, "other_part": other_part}
return {
"fit": fit,
"own_ap": own_ap,
"other_ap": other_ap,
"other_part": other_part,
}
async def _augmented_part_fits_ctx(
@@ -2224,7 +2297,9 @@ async def delete_augmented_part_fit(
):
fit = await fit_crud.get(db, fit_id)
if fit is not None:
label = f"attachment points {fit.attachment_point_a_id}↔{fit.attachment_point_b_id}"
label = (
f"attachment points {fit.attachment_point_a_id}↔{fit.attachment_point_b_id}"
)
await fit_crud.delete(db, fit)
await audit_crud.log(
db,