Add conditional localized form definitions
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@@ -11,13 +13,19 @@ from govoplan_forms.backend.schemas import (
|
||||
FormDefinitionHistoryResponse,
|
||||
FormDefinitionListResponse,
|
||||
FormDefinitionWriteRequest,
|
||||
FormPackageImportRequest,
|
||||
FormPackageRequest,
|
||||
)
|
||||
from govoplan_forms.backend.service import (
|
||||
FormDefinitionStoreError,
|
||||
definition_from_mapping,
|
||||
assess_form_definition_fragment,
|
||||
export_form_definition_fragment,
|
||||
form_definition_diagnostics,
|
||||
form_definition_history,
|
||||
get_form_definition,
|
||||
list_form_definitions,
|
||||
import_form_definition_fragment,
|
||||
record_form_definition,
|
||||
)
|
||||
|
||||
@@ -32,9 +40,11 @@ def _require(principal: ApiPrincipal, scope: str) -> None:
|
||||
|
||||
def _error(exc: Exception) -> HTTPException:
|
||||
message = str(exc)
|
||||
code = 409 if any(
|
||||
word in message.casefold() for word in ("conflict", "already", "stale")
|
||||
) else 400
|
||||
code = (
|
||||
409
|
||||
if any(word in message.casefold() for word in ("conflict", "already", "stale"))
|
||||
else 400
|
||||
)
|
||||
return HTTPException(status_code=code, detail=message)
|
||||
|
||||
|
||||
@@ -117,6 +127,95 @@ def api_get_form_definition(
|
||||
return item.to_dict()
|
||||
|
||||
|
||||
@router.get("/definitions/{form_id}/diagnostics", response_model=dict[str, object])
|
||||
def api_form_definition_diagnostics(
|
||||
form_id: str,
|
||||
revision: str | None = Query(default=None, max_length=255),
|
||||
session: Session = Depends(get_session),
|
||||
principal: ApiPrincipal = Depends(get_api_principal),
|
||||
) -> dict[str, object]:
|
||||
_require(principal, READ_SCOPE)
|
||||
item = get_form_definition(session, principal, form_id=form_id, revision=revision)
|
||||
if item is None:
|
||||
raise HTTPException(status_code=404, detail="Form definition not found")
|
||||
diagnostics = form_definition_diagnostics(item)
|
||||
return {
|
||||
"diagnostics": [dict(value) for value in diagnostics],
|
||||
"error_count": sum(value.get("severity") == "error" for value in diagnostics),
|
||||
"warning_count": sum(
|
||||
value.get("severity") == "warning" for value in diagnostics
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@router.get("/definitions/{form_id}/package", response_model=dict[str, object])
|
||||
def api_export_form_definition_package(
|
||||
form_id: str,
|
||||
revision: str | None = Query(default=None, max_length=255),
|
||||
session: Session = Depends(get_session),
|
||||
principal: ApiPrincipal = Depends(get_api_principal),
|
||||
) -> dict[str, object]:
|
||||
_require(principal, READ_SCOPE)
|
||||
item = get_form_definition(session, principal, form_id=form_id, revision=revision)
|
||||
if item is None:
|
||||
raise HTTPException(status_code=404, detail="Form definition not found")
|
||||
actor_id = next(
|
||||
(
|
||||
str(getattr(principal, name))
|
||||
for name in ("account_id", "identity_id", "membership_id")
|
||||
if getattr(principal, name, None)
|
||||
),
|
||||
None,
|
||||
)
|
||||
return export_form_definition_fragment(
|
||||
item,
|
||||
exported_at=datetime.now(UTC),
|
||||
exported_by=actor_id,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/packages/assess", response_model=dict[str, object])
|
||||
def api_assess_form_definition_package(
|
||||
payload: FormPackageRequest,
|
||||
session: Session = Depends(get_session),
|
||||
principal: ApiPrincipal = Depends(get_api_principal),
|
||||
) -> dict[str, object]:
|
||||
_require(principal, WRITE_SCOPE)
|
||||
try:
|
||||
return assess_form_definition_fragment(
|
||||
session,
|
||||
principal,
|
||||
fragment=payload.fragment,
|
||||
)
|
||||
except (FormDefinitionStoreError, InstitutionalContextError) as exc:
|
||||
raise _error(exc) from exc
|
||||
|
||||
|
||||
@router.post("/packages/import", response_model=dict[str, object])
|
||||
def api_import_form_definition_package(
|
||||
payload: FormPackageImportRequest,
|
||||
session: Session = Depends(get_session),
|
||||
principal: ApiPrincipal = Depends(get_api_principal),
|
||||
) -> dict[str, object]:
|
||||
_require(principal, WRITE_SCOPE)
|
||||
try:
|
||||
item = import_form_definition_fragment(
|
||||
session,
|
||||
principal,
|
||||
fragment=payload.fragment,
|
||||
target_form_id=payload.target_form_id,
|
||||
target_key=payload.target_key,
|
||||
expected_revision=payload.expected_revision,
|
||||
change_reason=payload.change_reason,
|
||||
recorded_at=payload.recorded_at,
|
||||
)
|
||||
session.commit()
|
||||
except (FormDefinitionStoreError, InstitutionalContextError) as exc:
|
||||
session.rollback()
|
||||
raise _error(exc) from exc
|
||||
return item.to_dict()
|
||||
|
||||
|
||||
@router.get(
|
||||
"/definitions/{form_id}/history",
|
||||
response_model=FormDefinitionHistoryResponse,
|
||||
|
||||
Reference in New Issue
Block a user