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
| Layer | Path |
|---|---|
| Schema | backend/src/db/schema.ts |
| Routes | backend/src/routes/document-obtaining/ (routes/, dto/, schemas, utils) + document-obtaining-dashboard.ts |
| Services | backend/src/services/document-obtaining/, document-obtaining-dashboard-service.ts, document-request-batch-service.ts, fulfillment-service.ts |
| Chain Synthesis | backend/src/lib/file-operations/fulfillment-files.ts |
| Dashboard Page | frontend/src/pages/internal/DocumentObtainingDashboard.tsx |
| Detail Pages | frontend/src/pages/internal/DocumentObtainingSets.tsx, DocumentObtainingDocs.tsx, DocumentObtainingCollections.tsx, DocumentObtainingDetail.tsx |
| Components | frontend/src/components/document-obtaining/ (~64 files) |
| Filter Context | frontend/src/contexts/ResponsibilityFilterContext.tsx |
Database Tables
| Table | Purpose |
|---|---|
documentObtaining | Root entity = the “collection” (batches reference it as collectionId); holds property/customer/applicant data, optional quoteId |
documentObtainingRequests | Individual document requests within a collection |
documentObtainingRequestBatches | Groups of requests sent together to a customer (“sets”) |
documentObtainingRequestToLabels | Request ↔ label junction |
documentObtainingRequestFiles | Per-request file overrides (replace template files with pre-filled versions) |
documentObtainingFulfillments | Customer uploads fulfilling a request |
documentObtainingNotifications | Notification records (email/SMS sent to customer) |
documentObtainingReminderHistory | Tracks when reminders were sent |
documentObtainingHelpRequests / documentObtainingHelpMessages | Customer help requests + message threads |
documentObtainingActivityLogs | Comprehensive activity trail |
documentObtainingEmailTemplates | Configurable email templates for notifications |
documentObtainingFormDrafts | Saved draft state for Forms filled by customers |
documentObtainingReviewChecklistResults | Review checklist outcomes per document |
documentObtainingRejectionBundles | Groups of rejected documents sent back together |
documentObtainingRejectionReasons | Predefined rejection reasons |
There is no separate
documentObtainingCollectionstable — the rootdocumentObtainingrow is the collection; child tables reference it viacollectionId.
Canonical File Chain (PR#2005)
Since PR#2005, every document-obtaining fulfillment is materialized into the collection-canonical Files chain (file_collections → file_collection_members → file_versions):
ensureFulfillmentChain(inbackend/src/lib/file-operations/fulfillment-files.ts) synthesizes onefile_collectionsrow per request, stamped withdocumentObtainingRequestId— a partial unique index makes the synthesis idempotent and prevents CAS-deduplicated content from resolving to another project’s collection.findUnchainedFulfillmentsis 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 — seeisUniqueViolationinlib/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
- Create collection — group document requests for a project (manually, or auto-created by the workflow task factory via
workflowTemplatePhaseTasks.documentObtainingId) - Assign documents — select which documents are needed, set due dates
- Send to customer — batch requests sent via Portal with email/SMS Notifications
- Customer uploads — customer fills Forms or uploads Files through the portal
- Review — internal staff review submissions via Document Review checklists
- 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 overrides —
documentObtainingRequestFileslets 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
ResponsibilityFilterContextto 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
Related Pages
Documents | Document Review | Files | Portal | Forms | Form Builder | Notifications | Departments | Users | Projects | Workflows | Service Layer Pattern