PR #274 · pramaan-io/pramaan-functions · merged 2026-06-08
Free-text 'proceeding types' is a ticking audit failure
What breaks if firms share a global, unprotected list
Free text is never a catalog.
The fix — Number the tabs, lock the drawer, never let a case point to air.
sequenceDiagram autonumber participant app as Firm Admin participant svc as Service participant db as DB + RLS app->>svc: POST create svc->>svc: name conflict check svc->>svc: usage + refs check svc->>db: insert + next PT-NNN db->>db: RLS firm lock db->>svc: view + formatted ref svc->>app: ProceedingTypeView
| Method | in → out | what it does |
|---|---|---|
create_proceeding_type | (session, payload) → ProceedingTypeView | creates a new label and allocates the next PT-NNN for the firm |
archive_proceeding_type | (session, proceeding_type_id) → ProceedingTypeView | moves the label from active drawer to storage pocket without losing references |
delete_proceeding_type | (session, proceeding_type_id) → None | refuses to remove a label that any case still points to |
Service layer for firm-scoped CRUD, archive, unarchive, and delete flows on proceeding types, with usage and name-conflict guards.
| new class | signature |
|---|---|
ProceedingTypeService | (class) |
_current_user_id | (session) → UUID |
_view | (proceeding_type, usage_count) → ProceedingTypeView |
_find_duplicate_name | (session, firm_id, name, excluding_proceeding_type_id) → ProceedingType | None |
_get_visible_proceeding_type | (session, proceeding_type_id) → ProceedingType |
_get_editable_firm_proceeding_type | (session, proceeding_type_id, firm_id) → ProceedingType |
_raise_if_name_conflict | (session, firm_id, name, excluding_proceeding_type_id) → None |
_in_use_references | (proceeding_type_id, firm_id) → tuple[InUseReference, ...] |
_usage_count | (session, proceeding_type_id, firm_id) → int |
list_proceeding_types | (session, include_archived) → ProceedingTypeListResponse |
create_proceeding_type | (session, payload) → ProceedingTypeView |
update_proceeding_type | (session, proceeding_type_id, payload) → ProceedingTypeView |
archive_proceeding_type | (session, proceeding_type_id) → ProceedingTypeView |
unarchive_proceeding_type | (session, proceeding_type_id) → ProceedingTypeView |
delete_proceeding_type | (session, proceeding_type_id) → None |
Migration that creates the proceeding_types table, enables per-firm RLS, adds the soft-delete columns, and installs the updated_at trigger.
| new method | signature |
|---|---|
_replace_reference_kind_constraint | (include_proceeding_type) → None |
_enable_proceeding_type_rls | () → None |
_disable_proceeding_type_rls | () → None |
upgrade | () → None |
downgrade | () → None |
revision : strdown_revision : str | Sequence[str] | Nonebranch_labels : str | Sequence[str] | Nonedepends_on : str | Sequence[str] | NoneRequest, update, view, and list DTOs defining the public proceeding type shape, including the formatted PT-001 reference and delete-safety flags.
| new class | signature |
|---|---|
ProceedingTypeAvailability | (class) |
ProceedingTypeCreateRequest | (class) |
_trim_name | (value) → str | None |
_trim_description | (value) → str | None |
ProceedingTypeUpdateRequest | (class) |
ProceedingTypeView | (class) |
ProceedingTypeListResponse | (class) |
name : strdescription : str | Noneavailability : ProceedingTypeAvailabilityid : UUIDfirm_id : UUIDproceeding_type_number : intproceeding_type_number_formatted : strarchived_at : datetime | Nonearchived_by_user_id : UUID | Noneusage_count : intis_in_use : boolcan_delete : boolcreated_by_user_id : UUID | NoneSQLAlchemy entity mapping the proceeding_types table with firm ownership, per-firm number, archive columns, and soft-delete columns.
| new class | signature |
|---|---|
ProceedingType | (type) |
id : UUIDfirm_id : UUIDproceeding_type_number : intname : strdescription : str | Noneavailability : strcreated_by_user_id : UUID | Nonearchived_at : datetime | Nonearchived_by_user_id : UUID | Nonedeleted_at : datetime | Nonedeleted_by_user_id : UUID | NoneFastAPI routes exposing the create, list, update, archive, unarchive, and delete endpoints for proceeding types under the app API.
| new method | signature |
|---|---|
list_proceeding_types | async def list_proceeding_types( db: AppDbDep, include_archived: Annotated[ bool, Query( alias="includeArchived", description=( "Include archived proceeding type rows for settings management. " "Deleted proceeding type rows are never return |
create_proceeding_type | (req, db, _) → ProceedingTypeView |
update_proceeding_type | (proceeding_type_id, req, db, _) → ProceedingTypeView |
delete_proceeding_type | (proceeding_type_id, db, _) → Response |
archive_proceeding_type | (proceeding_type_id, db, _) → ProceedingTypeView |
unarchive_proceeding_type | (proceeding_type_id, db, _) → ProceedingTypeView |
Shared formatter that renders a per-firm proceeding type number as the standard PT-001 string used in views and references.
| new method | signature |
|---|---|
format_proceeding_type_ref | (proceeding_type_number) → str |