Files
lcbp3/specs/001-transmittals-circulation/spec.md
T

14 KiB
Raw Blame History

Feature Specification: Transmittals + Circulation Complete Integration (v1.8.7 Post-ADR-021)

Feature Branch: 001-transmittals-circulation Version: 1.8.7 Created: 2026-04-12 Status: Draft Depends On: ADR-021 (Integrated Workflow Context & Step-specific Attachments — in feat/adr-021-integrated-workflow-context) Input: "Transmittals + Circulation (v1.8.7) Post-ADR-021"


Context

ADR-021 introduced the shared IntegratedBanner, WorkflowLifecycle, and use-workflow-action components, and wired them fully for RFA and Correspondence. Both the Transmittal and Circulation detail pages already import these components but pass no workflow data — they are currently stub wired.

This feature delivers the complete, production-ready integration of both modules with the ADR-021 Workflow Engine, fixes known type violations (ADR-019), implements all pending edge cases (EC-RFA-004, EC-CIRC-001003), and adds missing hooks and list-page functionality.


User Scenarios & Testing (mandatory)

User Story 1 — Transmittal Workflow-Wired Detail Page (Priority: P1) 🎯 MVP

A Document Control officer opens an existing Transmittal and immediately sees the document number, subject, workflow state, and available action buttons in the IntegratedBanner. The Workflow tab shows the full vertical timeline with each step's actor, date, comment, and evidence files.

Why this priority: The detail page is the primary touchpoint for reviewing/approving a Transmittal. Without live workflow data, reviewers cannot take action — this is a blocking gap.

Independent Test: Navigate to /transmittals/{uuid}. Verify: (1) IntegratedBanner shows real doc number, status badge, and action buttons (when user is the handler); (2) Workflow tab renders WorkflowLifecycle with at least the creation step; (3) all pnpm tsc --noEmit checks pass.

Acceptance Scenarios:

  1. Given a submitted Transmittal with an active workflow instance, When a Document Control user opens its detail page, Then the IntegratedBanner displays the correct doc number, status, workflowState, and the available action buttons (e.g., APPROVE, REJECT).
  2. Given a Transmittal where the current user is not the assigned handler, When they open the detail page, Then no action buttons are shown in the banner.
  3. Given a Transmittal detail page, When the user clicks the Workflow tab, Then a vertical timeline displays all history steps with actor, date, and comment. The most recent step is highlighted.

User Story 2 — Circulation Workflow-Wired Detail Page (Priority: P1) 🎯 MVP

A Document Control officer opens a Circulation Sheet and sees the circulation number, linked Correspondence, all assignees with their status, a deadline (with Overdue badge if past), and the full workflow timeline — all in one screen. Assignees can mark their task complete via the IntegratedBanner actions.

Why this priority: Circulation drives internal task tracking. Without live data wiring the page is read-only and useless for task management.

Independent Test: Navigate to /circulation/{uuid}. Verify: (1) IntegratedBanner displays circulationNo, statusCode; (2) Assignees card shows all routings with status; (3) Overdue badge appears when deadline_date is past; (4) Workflow tab shows history.

Acceptance Scenarios:

  1. Given an OPEN Circulation with a past deadline, When a user opens the detail page, Then an Overdue badge is displayed and the deadline date is highlighted in red.
  2. Given a Circulation with multiple assignees, When an assignee marks their task complete, Then their routing status updates to COMPLETED and the page refreshes.
  3. Given a Circulation where all Main/Action assignees are COMPLETED, When the Document Control user views the page, Then a "Close Circulation" action is available.

User Story 3 — Transmittal List Page with Search & Filter (Priority: P1)

A Document Control officer browses all Transmittals for a project, filters by purpose (FOR_APPROVAL, FOR_REVIEW, etc.), and searches by document number or subject.

Why this priority: The list page is the entry point for the module. Without working filters it cannot be used in production.

Independent Test: Navigate to /transmittals. Verify: paginated list loads; purpose filter updates results; search input filters by doc number/subject; clicking a row navigates to the detail page.

Acceptance Scenarios:

  1. Given the Transmittals list page, When a user selects purpose "FOR_APPROVAL", Then only Transmittals with that purpose are shown.
  2. Given the Transmittals list page, When a user types in the search box, Then results are filtered to matching document numbers or subjects within 500ms.
  3. Given no Transmittals in the project, When the list page loads, Then an "empty state" message is shown.

User Story 4 — Transmittal EC-RFA-004 Submit Validation (Priority: P2)

A Document Control officer tries to submit a Transmittal whose items include a DRAFT correspondence. The system blocks the submission with a clear, actionable error message.

Why this priority: EC-RFA-004 is a business integrity rule. Submitting a Transmittal with unsubmitted items violates the document lifecycle and must be blocked.

Independent Test: Create a Transmittal with one DRAFT item. Attempt to submit. Verify: 422 response with message "RFA [doc number] ยังอยู่ใน Draft กรุณา Submit ก่อน"; item is highlighted in the UI.

Acceptance Scenarios:

  1. Given a Transmittal containing a DRAFT correspondence, When a user submits the Transmittal, Then the system returns an error identifying which item is in DRAFT status.
  2. Given all Transmittal items are in SUBMITTED/APPROVED status, When a user submits the Transmittal, Then the submission succeeds and the status updates.

User Story 5 — Circulation Edge Cases: Re-assign & Force Close (Priority: P2)

Document Control can re-assign a Circulation when an assignee is deactivated (EC-CIRC-001), and can force-close a Circulation with a mandatory reason when some assignees have not responded (EC-CIRC-002).

Why this priority: Without these controls, Circulations can get permanently stuck, blocking downstream work.

Independent Test: Deactivate an assignee in an OPEN Circulation. Verify: Document Control sees a "Re-assign" button for that routing. Force-close a Circulation with partial responses; verify reason is recorded in audit log.

Acceptance Scenarios:

  1. Given an OPEN Circulation where one assignee has been deactivated, When Document Control opens the page, Then a "Re-assign" action is available for that assignee's routing.
  2. Given an OPEN Circulation where some assignees have not responded, When Document Control performs Force Close with a reason, Then the Circulation status changes to CANCELLED, all pending routings are force-closed, and the reason is logged.

Edge Cases

  • EC-RFA-004: Transmittal with DRAFT items cannot be submitted → 422 Unprocessable Entity with item identification.
  • EC-CIRC-001: Assignee deactivated before responding → Document Control can re-assign.
  • EC-CIRC-002: Multi-assignee, some not responded → Document Control can Force Close with mandatory reason.
  • EC-CIRC-003: Deadline = today 23:59:59; Overdue Badge the following day at 00:00.
  • EC-CORR-001: Cancelling a Correspondence with open Circulations → all Circulations force-closed + audit log.
  • Transmittal workflowInstanceId is null when no workflow has been started (Draft state) → banner shows status only, no action buttons.
  • Circulation data is scoped to the user's organization — users from other organizations must receive a 403 response.
  • Duplicate Idempotency-Key on workflow transition → return cached response, no re-processing.

Requirements (mandatory)

Functional Requirements

Transmittal Module:

  • FR-T01: The Transmittal detail page MUST display workflowState, availableActions, and action buttons via IntegratedBanner using the live workflow instance.
  • FR-T02: The Transmittal detail page Workflow tab MUST render WorkflowLifecycle wired to the workflow history of the Transmittal's workflow instance.
  • FR-T03: The Transmittal list page MUST support pagination, search by document number/subject, and filter by purpose.
  • FR-T04: The Transmittal Transmittal frontend type MUST include workflowInstanceId?: string and workflowState?: string fields (ADR-019: string UUID only).
  • FR-T05: The transmittalService.getByUuid() response MUST include workflowInstanceId from the backend.
  • FR-T06: A dedicated useTransmittal(uuid) TanStack Query hook MUST be created for the detail page.
  • FR-T07: Submitting a Transmittal with DRAFT items MUST return a 422 error identifying the offending item (EC-RFA-004).

Circulation Module:

  • FR-C01: The Circulation detail page MUST display workflowState, availableActions, and action buttons via IntegratedBanner using the live workflow instance.
  • FR-C02: The Circulation detail page Workflow tab MUST render WorkflowLifecycle wired to the workflow history.
  • FR-C03: The Circulation detail page assignee section MUST display deadline per assignee type and an Overdue badge when NOW() > deadline_date + 1 day (EC-CIRC-003).
  • FR-C04: The Circulation Circulation frontend type MUST include workflowInstanceId?: string and workflowState?: string.
  • FR-C05: The circulationService.getByUuid() response MUST include workflowInstanceId from the backend.
  • FR-C06: A dedicated useCirculation(uuid) TanStack Query hook MUST be created for the detail page.
  • FR-C07: Document Control MUST be able to re-assign a routing when the assignee is deactivated (EC-CIRC-001).
  • FR-C08: Document Control MUST be able to Force Close a Circulation with a mandatory reason; all pending routings are force-closed and the reason is logged in the audit trail (EC-CIRC-002).

Cross-Cutting:

  • FR-X01: All new API calls MUST use publicId (UUIDv7 string) — no parseInt on UUID values (ADR-019).
  • FR-X02: All new frontend types MUST NOT use any — strict TypeScript required.
  • FR-X03: All backend responses for these modules MUST include workflowInstanceId?: string in the data shape.
  • FR-X04: All new user-facing strings MUST use i18n keys — no hardcoded Thai/English text in JSX.

Key Entities

  • Transmittal: Extends Correspondence (type_code = 'TRANSMITTAL'). Has purpose, remarks, and a list of transmittal_items. Has one WorkflowInstance via the Unified Workflow Engine.
  • TransmittalItem: Links a Transmittal to the document it carries (correspondences M:N). Has quantity, itemType, remarks.
  • Circulation: Internal task-tracking document linked 1:1 to a Correspondence per organization. Has statusCode, deadline, and a list of routings (assignees with type: Main/Action/Information).
  • CirculationRouting: A single assignee entry in a Circulation. Has assigneeType, status, deadline, comments.

Assumptions

  • ADR-021 backend is fully deployed — workflow_history_id column exists on attachments, workflowInstanceId is exposed from the Workflow Engine module.
  • The backend transmittal module already has a workflowInstance relation or can join it via the Correspondence FK chain.
  • The backend circulation module already has a workflowInstance relation available.
  • The Unified Workflow Engine (WorkflowEngineService) is the single source of truth for state and transitions — Transmittal and Circulation statuses are NOT independently maintained once a workflow is started.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: Both Transmittal and Circulation detail pages display live workflow state and action buttons in under 1 second after page load (TanStack Query with staleTime 60s).
  • SC-002: Submitting a Transmittal with a DRAFT item is rejected 100% of the time with a user-readable error message identifying the offending document.
  • SC-003: Force-closing a Circulation with partial responses succeeds in a single action with the mandatory reason captured in the audit log every time.
  • SC-004: All new TypeScript code passes pnpm tsc --noEmit with zero errors and pnpm lint with zero warnings.
  • SC-005: No hardcoded Thai or English text in any new JSX component — verified by grep.
  • SC-006: Unit test coverage ≥ 80% on new business logic (EC-RFA-004 validation, EC-CIRC-001/002/003 handlers).
  • SC-007: Overdue Badge appears correctly when NOW() > deadline_date + 1 day — verified by unit test with mocked date.

Clarifications

Session 2026-04-12

  • Q: Should the Transmittal "Submit" action go through the Workflow Engine transition (ADR-021 pattern), or does it remain a direct status update on the correspondences table? → A: Submit uses the Workflow Engine transition (action: 'SUBMIT'), consistent with ADR-001 Unified Workflow Engine for all document types. EC-RFA-004 validation fires as a pre-transition check in the service.
  • Q: Should Circulation routings "Complete" action be a Workflow Engine transition or a direct routing status update? → A: Direct routing status update (not a full Workflow Engine transition) because Circulation workflow state is controlled at the Circulation level, not per-routing. The overall Circulation transitions (OPEN → IN_REVIEW → COMPLETED) go through the Workflow Engine.
  • Q: For workflowInstanceId in the Transmittal/Circulation API response — should it be added to the existing response shape or is a dedicated /workflow sub-resource needed? → A: Add workflowInstanceId directly to the existing findOneByUuid response shape (additive, backward-compatible). Consistent with how RFA/Correspondence expose it.