Document Obtaining

The largest feature in Renewa One — a complex multi-step workflow for collecting documents from customers. Spans ~64 frontend components, 15+ database tables, and a dedicated backend route directory. Drives the full cycle from requesting documents through customer upload, review, approval, and rejection.

Source Files

LayerPath
Schemabackend/src/db/schema.ts
Routesbackend/src/routes/document-obtaining/ (routes/, dto/, schemas, utils) + document-obtaining-dashboard.ts
Servicesbackend/src/services/document-obtaining/, document-obtaining-dashboard-service.ts, document-request-batch-service.ts, fulfillment-service.ts
Chain Synthesisbackend/src/lib/file-operations/fulfillment-files.ts
Dashboard Pagefrontend/src/pages/internal/DocumentObtainingDashboard.tsx
Detail Pagesfrontend/src/pages/internal/DocumentObtainingSets.tsx, DocumentObtainingDocs.tsx, DocumentObtainingCollections.tsx, DocumentObtainingDetail.tsx
Componentsfrontend/src/components/document-obtaining/ (~64 files)
Filter Contextfrontend/src/contexts/ResponsibilityFilterContext.tsx

Database Tables

TablePurpose
documentObtainingRoot entity = the “collection” (batches reference it as collectionId); holds property/customer/applicant data, optional quoteId
documentObtainingRequestsIndividual document requests within a collection
documentObtainingRequestBatchesGroups of requests sent together to a customer (“sets”)
documentObtainingRequestToLabelsRequest ↔ label junction
documentObtainingRequestFilesPer-request file overrides (replace template files with pre-filled versions)
documentObtainingFulfillmentsCustomer uploads fulfilling a request
documentObtainingNotificationsNotification records (email/SMS sent to customer)
documentObtainingReminderHistoryTracks when reminders were sent
documentObtainingHelpRequests / documentObtainingHelpMessagesCustomer help requests + message threads
documentObtainingActivityLogsComprehensive activity trail
documentObtainingEmailTemplatesConfigurable email templates for notifications
documentObtainingFormDraftsSaved draft state for Forms filled by customers
documentObtainingReviewChecklistResultsReview checklist outcomes per document
documentObtainingRejectionBundlesGroups of rejected documents sent back together
documentObtainingRejectionReasonsPredefined rejection reasons

There is no separate documentObtainingCollections table — the root documentObtaining row is the collection; child tables reference it via collectionId.

Canonical File Chain (PR#2005)

Since PR#2005, every document-obtaining fulfillment is materialized into the collection-canonical Files chain (file_collectionsfile_collection_membersfile_versions):

  • ensureFulfillmentChain (in backend/src/lib/file-operations/fulfillment-files.ts) synthesizes one file_collections row per request, stamped with documentObtainingRequestId — a partial unique index makes the synthesis idempotent and prevents CAS-deduplicated content from resolving to another project’s collection.
  • findUnchainedFulfillments is the read-side mirror; a BullMQ reconciliation job (lib/jobs/processors/fulfillment-chain-reconciliation.ts) sweeps fulfillments whose chain write failed (e.g., lost races on the unique constraint — see isUniqueViolation in lib/db-errors.ts).

Project Linkage (Dual-Path)

documentObtaining.quoteId doubles as the dual-path discriminator (spec 2026-05-19-document-obtaining-projectid-dual-path-design.md): HubSpot-sourced collections always carry a quote (linked by the workflow-package factory); PowerCRM/Dataverse imports never do. The owning projectId is derived from quotes.projectId (or the batch chain → workflow_packages.projectId) so the relationship cannot drift if a quote/package is reassigned in HubSpot.

Core Workflow

  1. Create collection — group document requests for a project (manually, or auto-created by the workflow task factory via workflowTemplatePhaseTasks.documentObtainingId)
  2. Assign documents — select which documents are needed, set due dates
  3. Send to customer — batch requests sent via Portal with email/SMS Notifications
  4. Customer uploads — customer fills Forms or uploads Files through the portal
  5. Review — internal staff review submissions via Document Review checklists
  6. Approve or reject — approved documents are finalized; rejected ones are bundled with reasons and sent back for resubmission

Key Features

  • Batch operations — send, remind, or reject multiple documents at once
  • Reminder system — automated and manual reminders with configurable email templates and history tracking
  • Help requests — customers can flag difficulties (with message threads); staff sees these on the dashboard
  • Rejection bundles — group rejections with structured reasons so customers understand what to fix
  • Per-request file overridesdocumentObtainingRequestFiles lets admins replace template files (e.g., pre-filled Vollmacht) per request
  • Activity logging — every action (send, upload, review, reject) is recorded in documentObtainingActivityLogs
  • Department filtering — dashboard uses ResponsibilityFilterContext to scope views by Departments

Relationships

DocumentObtaining (collection) *──1 Quote ──1 Project (derived)
DocumentObtaining 1──* RequestBatches 1──* Requests
Request 1──* Fulfillments ──> canonical chain (FileCollection → Members → FileVersions → Files)
Request 1──* Notifications / ReminderHistory / RequestFiles
Request *──1 DocumentTemplate

Documents | Document Review | Files | Portal | Forms | Form Builder | Notifications | Departments | Users | Projects | Workflows | Service Layer Pattern