Implements tester feedback against API Q1 §5.9.1.2 / §6.4.2: - Root Cause field + 6M Root Cause Category lookup (Man/Machine/Method/ Material/Measurement/Environment), separate from Deviation Detail/Category - "Corrective Action Required?" Yes/No gate on every NCR with a required justification - Corrective action plan with owner + due date; owner is notified by email - Effectiveness verification (result, notes, server-stamped verifier/date) required before an NCR can close when corrective action is required — costing returns 409 listing the missing pieces - Recurring-issue flag with bidirectional NCR-to-NCR links; prior NCRs show a warning when later NCRs reference them - Dashboard metrics: % root cause completed, % CAPA verified effective, avg CAPA close time, overdue CAPA count, NCRs by root cause category - CAPA section in the NCR detail UI, printable PDF, CSV export, and the vw_ncr_full Power BI view; admin list manager for root cause categories - Migrations 0003 (schema + seeded 6M lookup) and 0004 (view refresh); demo seed data exercises every metric Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
38 lines
1.2 KiB
Python
38 lines
1.2 KiB
Python
from fastapi import APIRouter, Depends
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.auth.deps import CurrentUser, get_current_user
|
|
from app.database import get_db
|
|
from app.models import Department, DeviationCategory, RootCauseCategory
|
|
from app.schemas.lookup import LookupsOut, NamedLookupOut
|
|
|
|
router = APIRouter(tags=["lookups"])
|
|
|
|
|
|
async def _active(db: AsyncSession, model) -> list[NamedLookupOut]:
|
|
rows = (
|
|
(
|
|
await db.execute(
|
|
select(model).where(model.is_active.is_(True)).order_by(model.name)
|
|
)
|
|
)
|
|
.scalars()
|
|
.all()
|
|
)
|
|
return [NamedLookupOut.model_validate(r) for r in rows]
|
|
|
|
|
|
@router.get("/lookups", response_model=LookupsOut)
|
|
async def get_lookups(
|
|
_: CurrentUser = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
) -> LookupsOut:
|
|
"""Active departments, deviation categories, and root cause categories
|
|
for form dropdowns."""
|
|
return LookupsOut(
|
|
departments=await _active(db, Department),
|
|
deviation_categories=await _active(db, DeviationCategory),
|
|
root_cause_categories=await _active(db, RootCauseCategory),
|
|
)
|