# Document Schema-to-UI Mapping Purpose: Map the Document schema to the UI, while clearly separating intended target behavior from current implementation. Companion document: user-journey.md Acceptance criteria: acceptance-criteria.md ## 1. Entity Snapshot - Table: Document - Primary key: `id` (UUID) - Related entities: `Source`, `Job`, `DocumentPerson` - Canonical schema references: - `src/transcription/db/models.py` - `docs/schema_v2.md` ## 2. Mapping Rules This document uses three lenses: 1. Intended behavior: what the UX should support. 2. Current behavior: what the code supports today. 3. Gap to target: what must change to align implementation with the intended UX. ## 3. Field Inventory | Field | DB Type | Nullable | Default/Auto Value | Intended UI Treatment | Notes | |---|---|---|---|---|---| | id | UUID | No | `uuid4()` | Hidden, system-managed | Primary key | | name | str | No | None | Shown, editable on create and future edit | Required | | document_type | str | Yes | None | Shown, editable on create and future edit | Required by intended UX | | document_date | date | Yes | None | Shown, editable | Canonical exact date when present | | document_date_raw | str | Yes | None | Shown, editable | Approximate or unknown date text | | location_created | str | Yes | None | Shown, editable | Optional metadata | | notes | str | Yes | None | Shown, editable | Optional metadata | | archive_identifier | str | Yes | None | Shown, editable | Free text in first release | | created_at | datetime | No | `datetime.now(UTC)` | Hidden or read-only | System-managed | | updated_at | datetime | No | `datetime.now(UTC)` | Hidden or read-only | System-managed | ## 4. CREATE Mapping ### 4.1 Intended Create Flow Entry point: Document page User action: Create new document Success destination: new Document detail page | Field | Intended User Input | Required | Visible | Notes | |---|---|---|---|---| | name | Text input | Yes | Yes | Primary identifier used by the user | | document_type | Text input | Yes | Yes | Free text in first release | | document_date | Date input | No | Yes | Structured exact date | | document_date_raw | Text input | No | Yes | Approximate or uncertain date | | location_created | Text input | No | Yes | Optional | | notes | Text area | No | Yes | Optional | | archive_identifier | Text input | No | Yes | Free text | | created_at | None | No | No | System-generated | | updated_at | None | No | No | Not used during initial create | Related records during intended create: - A related person may optionally be selected or created. - If present, the system creates a `DocumentPerson` link. - Jobs are not created during Document create. - Sources are not created during Document create. ### 4.2 Current Implementation Current entry point: upload page Current user action: upload file via upload widget Current backend path: upload page submit callback -> `create_upload_job()` -> `_create_upload_records()` | Field | Current Value at Create | Source | Visible to User | Evidence | |---|---|---|---|---| | id | Generated UUID | System | No | `Document` default factory in `src/transcription/db/models.py` | | name | Basename of uploaded filename | User file name transformed by service | Indirectly | Set in `src/transcription/services/store.py` | | document_type | `None` | Service default | No | Not set in `src/transcription/services/store.py` | | document_date | `None` | Service default | No | Not set in `src/transcription/services/store.py` | | document_date_raw | `None` | Service default | No | Not set in `src/transcription/services/store.py` | | location_created | `None` | Service default | No | Not set in `src/transcription/services/store.py` | | notes | `None` | Service default | No | Not set in `src/transcription/services/store.py` | | archive_identifier | `None` | Service default | No | Not set in `src/transcription/services/store.py` | | created_at | Current UTC timestamp | System | No | Default factory in `src/transcription/db/models.py` | | updated_at | Current UTC timestamp | System | No | Default factory in `src/transcription/db/models.py` | Current related-record behavior: - `Job` is created automatically. - `Source` is created automatically. - `JobSource` is created automatically. - No `Person` or `DocumentPerson` records are created. ### 4.3 Gap to Target To satisfy the intended Create flow, implementation must add: 1. a Document page and dedicated create form 2. user-entered metadata fields for `document_type`, `document_date`, `document_date_raw`, `location_created`, `notes`, and `archive_identifier` 3. optional Person lookup and inline Person creation 4. optional `DocumentPerson` link creation when a person is chosen 5. post-submit routing to a Document detail page 6. removal of the assumption that Document creation always starts with file upload ## 5. READ Mapping ### 5.1 Intended Read Behavior On the Document detail page, the user should be able to see: 1. Document metadata 2. linked people 3. a Sources section with empty-state behavior when no sources exist 4. a Jobs section with empty-state behavior when no jobs exist 5. future links to filtered Jobs and Sources views for the current document ### 5.2 Current Implementation Current Document visibility in the UI is indirect. | Field | Current Rendering | Visible to User | Notes | Evidence | |---|---|---|---|---| | name | Indirect filename context in jobs list and job detail | Yes, indirect | The UI shows source/job filename, not a dedicated Document page | `src/transcription/ui/pages/jobs_page.py`, `src/transcription/ui/components/table/jobs.py` | | id | Not shown as Document id | No | Job id is shown instead | `src/transcription/ui/pages/jobs_page.py` | | document_type | Not rendered | No | Hidden metadata | no current UI field | | document_date | Not rendered | No | Hidden metadata | no current UI field | | document_date_raw | Not rendered | No | Hidden metadata | no current UI field | | location_created | Not rendered | No | Hidden metadata | no current UI field | | notes | Not rendered | No | Hidden metadata | no current UI field | | archive_identifier | Not rendered | No | Hidden metadata | no current UI field | | created_at | Not rendered as Document timestamp | No | Job timestamps are shown instead | `src/transcription/ui/components/table/jobs.py` | | updated_at | Not rendered as Document timestamp | No | Job metadata is shown instead | `src/transcription/ui/components/transcript.py` | ### 5.3 Gap to Target To satisfy the intended Read flow, implementation must add: 1. a Document detail page 2. metadata rendering for Document fields 3. linked people rendering 4. Sources and Jobs sections with empty states 5. filtered navigation from the detail page into document-specific Jobs and Sources views ## 6. UPDATE Mapping ### 6.1 Intended Update Behavior The user should eventually be able to edit Document metadata from the Document detail page or a dedicated edit flow. Intended editable fields: - `name` - `document_type` - `document_date` - `document_date_raw` - `location_created` - `notes` - `archive_identifier` Intended system-managed fields: - `id` - `created_at` - `updated_at` ### 6.2 Current Implementation | Field | Updatable via UI | Updatable via Service | Notes | |---|---|---|---| | id | No | Practically no | Primary key should be treated as immutable | | name | No | Yes | `DocumentService.update_document()` | | document_type | No | Yes | `DocumentService.update_document()` | | document_date | No | Yes | `DocumentService.update_document()` | | document_date_raw | No | Yes | `DocumentService.update_document()` | | location_created | No | Yes | `DocumentService.update_document()` | | notes | No | Yes | `DocumentService.update_document()` | | archive_identifier | No | Yes | `DocumentService.update_document()` | | created_at | No | Technically yes | Should remain system-managed | | updated_at | No | Technically yes | Should remain system-managed | ### 6.3 Gap to Target Implementation must add: 1. Document edit controls in the UI 2. validation and save behavior for Document metadata 3. a consistent `updated_at` update policy if metadata edits are introduced ## 7. DELETE Mapping ### 7.1 Intended Delete Behavior The UI should eventually provide a delete action for Document with guardrails. Rules: 1. A Document can be deleted when it has no attached Jobs and no attached Sources. 2. If dependent Jobs or Sources exist, the UI should block deletion and explain that those related records must be removed first. 3. Delete confirmation should make it clear that the action is permanent. ### 7.2 Current Implementation | Action | UI Exposed | Backend Capability | Notes | |---|---|---|---| | Delete Document | No | Yes | `DocumentService.delete_document()` exists, but no dedicated UI guard flow exists | ### 7.3 Gap to Target Implementation must add: 1. a Document delete control in the UI 2. pre-delete dependency checks for Jobs and Sources 3. user-facing messaging when deletion is blocked 4. confirmation UX for successful delete attempts ## 8. Hidden and System-Managed Fields | Field | Category | Why Hidden or Protected | |---|---|---| | id | System-managed | Internal identifier | | created_at | System-managed | Audit timestamp | | updated_at | System-managed | Audit timestamp | ## 9. Traceability Anchors Schema and models: - `docs/schema_v2.md` - `src/transcription/db/models.py` Current implementation: - `src/transcription/services/documents.py` - `src/transcription/services/store.py` - `src/transcription/ui/pages/upload_page.py` - `src/transcription/ui/pages/jobs_page.py` - `src/transcription/ui/components/table/jobs.py` - `src/transcription/ui/components/transcript.py` Companion UX spec: - `docs/ui/entities/document/user-journey.md` ## 10. Acceptance Checklist Summary - Every Document schema field appears in the field inventory. - Intended Create behavior matches the companion user journey. - Current Create behavior reflects the existing upload-driven implementation. - Gaps between intended and current behavior are explicit. - Read, Update, and Delete sections distinguish target behavior from current code.