@valentine-efagene/qshelter-common 2.0.138 → 2.0.140

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/generated/client/browser.d.ts +17 -17
  2. package/dist/generated/client/client.d.ts +17 -17
  3. package/dist/generated/client/commonInputTypes.d.ts +142 -202
  4. package/dist/generated/client/enums.d.ts +23 -0
  5. package/dist/generated/client/enums.js +21 -1
  6. package/dist/generated/client/internal/class.d.ts +37 -37
  7. package/dist/generated/client/internal/class.js +2 -2
  8. package/dist/generated/client/internal/prismaNamespace.d.ts +348 -377
  9. package/dist/generated/client/internal/prismaNamespace.js +91 -116
  10. package/dist/generated/client/internal/prismaNamespaceBrowser.d.ts +97 -122
  11. package/dist/generated/client/internal/prismaNamespaceBrowser.js +91 -116
  12. package/dist/generated/client/models/ApplicationDocument.d.ts +290 -1
  13. package/dist/generated/client/models/ApprovalStage.d.ts +1605 -0
  14. package/dist/generated/client/models/ApprovalStage.js +1 -0
  15. package/dist/generated/client/models/ApprovalStageProgress.d.ts +2329 -0
  16. package/dist/generated/client/models/ApprovalStageProgress.js +1 -0
  17. package/dist/generated/client/models/DocumentApproval.d.ts +1611 -0
  18. package/dist/generated/client/models/DocumentApproval.js +1 -0
  19. package/dist/generated/client/models/DocumentDefinition.d.ts +1475 -0
  20. package/dist/generated/client/models/DocumentDefinition.js +1 -0
  21. package/dist/generated/client/models/DocumentReview.d.ts +0 -3
  22. package/dist/generated/client/models/DocumentationPhase.d.ts +215 -629
  23. package/dist/generated/client/models/DocumentationPlan.d.ts +188 -57
  24. package/dist/generated/client/models/PaymentMethodPhaseStep.d.ts +3 -0
  25. package/dist/generated/client/models/Tenant.d.ts +640 -1203
  26. package/dist/generated/client/models/User.d.ts +414 -817
  27. package/dist/generated/client/models/index.d.ts +4 -4
  28. package/dist/generated/client/models/index.js +4 -4
  29. package/dist/generated/client/models.d.ts +4 -4
  30. package/dist/src/utils/documentation-enums.d.ts +10 -1
  31. package/dist/src/utils/documentation-enums.js +8 -0
  32. package/package.json +1 -1
  33. package/prisma/migrations/20260119190336_add_document_approval_workflow/migration.sql +134 -0
  34. package/prisma/schema.prisma +229 -214
@@ -301,6 +301,36 @@ enum DocumentStatus {
301
301
  REJECTED
302
302
  EXPIRED
303
303
  CANCELLED
304
+ NEEDS_REUPLOAD // Document rejected, customer must re-upload
305
+ }
306
+
307
+ // =============================================================================
308
+ // APPROVAL STAGE ENUMS (Multi-stage document workflow)
309
+ // =============================================================================
310
+
311
+ /// Status of an approval stage in a documentation phase
312
+ enum StageStatus {
313
+ PENDING // Not yet activated
314
+ IN_PROGRESS // Activated, documents being reviewed
315
+ AWAITING_TRANSITION // All docs approved, waiting for explicit stage completion
316
+ COMPLETED // Stage completed, next stage can activate
317
+ }
318
+
319
+ /// Who uploads a document
320
+ enum UploadedBy {
321
+ CUSTOMER
322
+ LENDER
323
+ DEVELOPER
324
+ LEGAL
325
+ INSURER
326
+ PLATFORM // QShelter staff
327
+ }
328
+
329
+ /// What happens when a later stage rejects a document
330
+ enum RejectionBehavior {
331
+ CASCADE_BACK // Restart from Stage 1 (default - full re-vetting)
332
+ RESTART_CURRENT // Only current stage re-reviews after re-upload
333
+ RESTART_FROM_STAGE // Restart from specific stage (uses restartFromStageOrder)
304
334
  }
305
335
 
306
336
  enum OfferLetterType {
@@ -456,11 +486,10 @@ model User {
456
486
  soldApplications Application[] @relation("ApplicationSeller")
457
487
  applicationPayments ApplicationPayment[] @relation("ApplicationPayer")
458
488
 
459
- // Documentation step assignments and approvals
460
- assignedSteps DocumentationStep[] @relation("DocumentationStepAssignee")
461
- gateActedSteps DocumentationStep[] @relation("GateActedBy")
462
- stepApprovals DocumentationStepApproval[] @relation("DocumentationStepApprover")
463
- uploadedDocs ApplicationDocument[] @relation("DocumentUploader")
489
+ // Documentation (new model)
490
+ uploadedDocs ApplicationDocument[] @relation("DocumentUploader")
491
+ documentApprovals DocumentApproval[] @relation("DocumentApprovalReviewer")
492
+ completedStages ApprovalStageProgress[] @relation("StageCompletedBy")
464
493
 
465
494
  // Payment method changes
466
495
  paymentMethodChangeRequests PaymentMethodChangeRequest[] @relation("ChangeRequestor")
@@ -759,12 +788,11 @@ model Tenant {
759
788
  paymentPhases PaymentPhase[]
760
789
  questionnaireFields QuestionnaireField[]
761
790
  applicationEvents ApplicationEvent[]
762
- documentationSteps DocumentationStep[]
763
- documentationStepDocuments DocumentationStepDocument[]
764
- documentationStepApprovals DocumentationStepApproval[]
765
791
  paymentInstallments PaymentInstallment[]
766
792
  applicationPayments ApplicationPayment[]
767
793
  applicationDocuments ApplicationDocument[]
794
+ documentApprovals DocumentApproval[]
795
+ approvalStageProgress ApprovalStageProgress[]
768
796
  propertyMedia PropertyMedia[]
769
797
  propertyDocuments PropertyDocument[]
770
798
  propertyVariants PropertyVariant[]
@@ -1259,8 +1287,12 @@ model DocumentationPlan {
1259
1287
  createdAt DateTime @default(now())
1260
1288
  updatedAt DateTime @updatedAt
1261
1289
 
1262
- // Steps that make up this plan
1263
- steps DocumentationPlanStep[]
1290
+ // Document definitions (what documents to collect)
1291
+ documentDefinitions DocumentDefinition[]
1292
+
1293
+ // Approval stages (sequential workflow for reviewing documents)
1294
+ approvalStages ApprovalStage[]
1295
+
1264
1296
  // Used by property payment method phases (templates)
1265
1297
  methodPhases PropertyPaymentMethodPhase[]
1266
1298
  // Used by instantiated documentation phases
@@ -1271,68 +1303,91 @@ model DocumentationPlan {
1271
1303
  @@map("documentation_plans")
1272
1304
  }
1273
1305
 
1274
- // Step template within a DocumentationPlan
1275
- model DocumentationPlanStep {
1306
+ // =============================================================================
1307
+ // DOCUMENT DEFINITION - What documents to collect (template)
1308
+ // =============================================================================
1309
+ // Defines a document requirement within a documentation plan.
1310
+ // This is separate from approval workflow - just defines WHAT to collect.
1311
+ // =============================================================================
1312
+
1313
+ model DocumentDefinition {
1276
1314
  id String @id @default(cuid())
1277
1315
  planId String
1278
1316
  plan DocumentationPlan @relation(fields: [planId], references: [id], onDelete: Cascade)
1279
1317
 
1280
- name String
1281
- stepType StepType
1282
- order Int
1318
+ // Document identification
1319
+ documentType String // ID_CARD, BANK_STATEMENT, EMPLOYMENT_LETTER, etc.
1320
+ documentName String // Human-readable: "Valid ID Card", "6 Months Bank Statement"
1283
1321
 
1284
- // Optional: which document type this step handles (for UPLOAD steps)
1285
- documentType String?
1286
- // Human-readable document name (e.g., "Valid ID Card" for ID_CARD)
1287
- // If not provided, step name can be auto-generated: "Upload ${documentName}"
1288
- documentName String?
1289
- metadata Json?
1290
-
1291
- // Document validation rules (for UPLOAD steps)
1292
- isRequired Boolean @default(true)
1293
- description String? @db.Text // Instructions for the user
1294
- maxSizeBytes Int? // Max file size allowed (e.g., 5242880 for 5MB)
1295
- allowedMimeTypes String? // CSV: application/pdf,image/jpeg,image/png
1296
- expiryDays Int? // Document must not be older than X days
1297
- requiresManualReview Boolean @default(false)
1298
- minFiles Int @default(1) // Minimum number of files required
1299
- maxFiles Int @default(1) // Maximum number of files allowed
1322
+ // Who uploads this document
1323
+ uploadedBy UploadedBy @default(CUSTOMER)
1300
1324
 
1301
- // Conditional logic - when is this step required?
1302
- // NULL = always required (unconditional)
1303
- // Examples:
1304
- // { "questionKey": "mortgage_type", "operator": "EQUALS", "value": "JOINT" }
1305
- // { "questionKey": "employment_status", "operator": "IN", "values": ["SELF_EMPLOYED", "BUSINESS_OWNER"] }
1306
- // { "all": [{ "questionKey": "has_spouse", "operator": "EQUALS", "value": "YES" }, { "questionKey": "spouse_employed", "operator": "EQUALS", "value": "YES" }] }
1325
+ // Display order
1326
+ order Int
1327
+
1328
+ // Validation rules
1329
+ isRequired Boolean @default(true)
1330
+ description String? @db.Text // Instructions for the uploader
1331
+ maxSizeBytes Int? // Max file size allowed (e.g., 5242880 for 5MB)
1332
+ allowedMimeTypes String? // CSV: application/pdf,image/jpeg,image/png
1333
+ expiryDays Int? // Document must not be older than X days
1334
+ minFiles Int @default(1)
1335
+ maxFiles Int @default(1)
1336
+
1337
+ // Conditional logic (based on questionnaire answers)
1338
+ // NULL = always required
1339
+ // Example: { "questionKey": "mortgage_type", "operator": "EQUALS", "value": "JOINT" }
1307
1340
  condition Json?
1308
1341
 
1309
- // =========================================================================
1310
- // MULTI-PARTY REVIEW CONFIGURATION (for UPLOAD steps)
1311
- // =========================================================================
1312
- // Defines which parties must review documents uploaded in this step
1313
- // Format: [{ party: "INTERNAL", required: true }, { party: "BANK", required: true }]
1314
- // If null, defaults to single internal review (backward compatible)
1315
- reviewRequirements Json?
1316
-
1317
- // Review order: 'SEQUENTIAL' = parties review in order, 'PARALLEL' = all review simultaneously
1318
- reviewOrder String? // 'SEQUENTIAL' | 'PARALLEL'
1319
-
1320
- // =========================================================================
1321
- // GATE STEP CONFIGURATION (only applicable when stepType = GATE)
1322
- // =========================================================================
1323
- gateActor GateActor? // Who must perform the action
1324
- gateAction GateAction? // What action is required
1325
- gateRoleId String? // If gateActor = SPECIFIC_ROLE, which role
1326
- gateInstructions String? @db.Text // Instructions shown to actor
1327
- allowReject Boolean @default(true) // Can the actor reject?
1328
- rejectBehavior GateRejectBehavior? // What happens on reject
1329
- requiresComment Boolean @default(false) // Must actor provide a comment?
1342
+ createdAt DateTime @default(now())
1343
+ updatedAt DateTime @updatedAt
1344
+
1345
+ @@index([planId])
1346
+ @@map("document_definitions")
1347
+ }
1348
+
1349
+ // =============================================================================
1350
+ // APPROVAL STAGE - Sequential workflow stages for document review (template)
1351
+ // =============================================================================
1352
+ // Defines a stage in the approval workflow. Documents flow through stages
1353
+ // sequentially. Each stage can have different reviewers (INTERNAL, BANK, etc.)
1354
+ // =============================================================================
1355
+
1356
+ model ApprovalStage {
1357
+ id String @id @default(cuid())
1358
+ planId String
1359
+ plan DocumentationPlan @relation(fields: [planId], references: [id], onDelete: Cascade)
1360
+
1361
+ name String // "QShelter Staff Review", "Bank Review"
1362
+ order Int // 1, 2, 3 - sequential order
1363
+ reviewParty ReviewParty // INTERNAL, BANK, DEVELOPER, LEGAL, etc.
1364
+
1365
+ // Stage behavior flags
1366
+ autoTransition Boolean @default(false) // Auto-complete when all docs approved? Default: require explicit approval
1367
+ waitForAllDocuments Boolean @default(true) // Wait for all docs approved before allowing transition
1368
+ allowEarlyVisibility Boolean @default(false) // Allow read-only view before stage activates
1369
+
1370
+ // Rejection behavior - what happens when this stage rejects a document
1371
+ onRejection RejectionBehavior @default(CASCADE_BACK)
1372
+ restartFromStageOrder Int? // If onRejection = RESTART_FROM_STAGE, which stage order to restart from
1373
+
1374
+ // Optional: specific organization (e.g., which bank)
1375
+ organizationId String?
1376
+
1377
+ // SLA (optional)
1378
+ slaHours Int? // Escalate if not completed within X hours
1379
+
1380
+ description String? @db.Text // Instructions for reviewers at this stage
1330
1381
 
1331
1382
  createdAt DateTime @default(now())
1332
1383
  updatedAt DateTime @updatedAt
1333
1384
 
1385
+ // Runtime instances
1386
+ stageProgress ApprovalStageProgress[]
1387
+
1388
+ @@unique([planId, order])
1334
1389
  @@index([planId])
1335
- @@map("documentation_plan_steps")
1390
+ @@map("approval_stages")
1336
1391
  }
1337
1392
 
1338
1393
  // =============================================================================
@@ -2101,7 +2156,7 @@ model QuestionnairePhase {
2101
2156
  // =============================================================================
2102
2157
  // DOCUMENTATION PHASE DATA - Extension for DOCUMENTATION phases
2103
2158
  // =============================================================================
2104
- // Manages document upload/approval workflow with FSM steps
2159
+ // Manages document upload/approval workflow with sequential approval stages
2105
2160
  // =============================================================================
2106
2161
 
2107
2162
  model DocumentationPhase {
@@ -2115,38 +2170,30 @@ model DocumentationPhase {
2115
2170
  documentationPlanId String?
2116
2171
  documentationPlan DocumentationPlan? @relation(fields: [documentationPlanId], references: [id])
2117
2172
 
2118
- // Source questionnaire for conditional step evaluation
2119
- // Links to the questionnaire phase whose answers determine which steps apply
2173
+ // Source questionnaire for conditional document evaluation
2174
+ // Links to the questionnaire phase whose answers determine which documents are required
2120
2175
  sourceQuestionnairePhaseId String?
2121
2176
  sourceQuestionnairePhase QuestionnairePhase? @relation("SourceQuestionnaire", fields: [sourceQuestionnairePhaseId], references: [id])
2122
2177
 
2123
- // Current step pointer for UX and orchestration
2124
- currentStepId String?
2125
- currentStep DocumentationStep? @relation("CurrentStep", fields: [currentStepId], references: [id])
2178
+ // Current approval stage pointer for UX and orchestration
2179
+ currentStageOrder Int @default(1)
2126
2180
 
2127
2181
  // Progress counters
2128
2182
  approvedDocumentsCount Int @default(0)
2129
2183
  requiredDocumentsCount Int @default(0)
2130
- completedStepsCount Int @default(0)
2131
- totalStepsCount Int @default(0)
2132
-
2133
- // Completion criteria
2134
- minimumCompletionPercentage Float?
2135
- completionCriterion CompletionCriterion?
2136
2184
 
2137
2185
  // Snapshots for audit
2138
- stepDefinitionsSnapshot Json?
2139
- requiredDocumentSnapshot Json?
2186
+ documentDefinitionsSnapshot Json?
2187
+ approvalStagesSnapshot Json?
2140
2188
 
2141
2189
  createdAt DateTime @default(now())
2142
2190
  updatedAt DateTime @updatedAt
2143
2191
 
2144
- // Child records
2145
- steps DocumentationStep[]
2192
+ // Approval stage progress (tracks which stages are completed)
2193
+ stageProgress ApprovalStageProgress[]
2146
2194
 
2147
2195
  @@index([tenantId])
2148
2196
  @@index([phaseId])
2149
- @@index([currentStepId])
2150
2197
  @@index([sourceQuestionnairePhaseId])
2151
2198
  @@map("documentation_phases")
2152
2199
  }
@@ -2296,140 +2343,6 @@ model ApplicationEvent {
2296
2343
  @@map("application_events")
2297
2344
  }
2298
2345
 
2299
- // Steps within a DOCUMENTATION phase (FSM for document collection/approval)
2300
- model DocumentationStep {
2301
- id String @id @default(cuid())
2302
- tenantId String
2303
- tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
2304
- documentationPhaseId String
2305
- documentationPhase DocumentationPhase @relation(fields: [documentationPhaseId], references: [id], onDelete: Cascade)
2306
-
2307
- name String
2308
- // Human-readable document name (e.g., "Valid ID Card" for ID_CARD)
2309
- documentName String?
2310
- description String? @db.Text
2311
- stepType StepType
2312
- order Int
2313
-
2314
- status StepStatus @default(PENDING)
2315
-
2316
- // =========================================================================
2317
- // USER ACTION TRACKING - For rejection/resubmission flows
2318
- // =========================================================================
2319
- // When status is NEEDS_RESUBMISSION or ACTION_REQUIRED, this explains why.
2320
- // Populated from DocumentationStepApproval.comment on rejection.
2321
- actionReason String? @db.Text
2322
-
2323
- // Number of times this step has been submitted (for tracking resubmissions)
2324
- submissionCount Int @default(0)
2325
-
2326
- // Last submission timestamp (for tracking resubmission timing)
2327
- lastSubmittedAt DateTime?
2328
-
2329
- // Configuration metadata (for GENERATE_DOCUMENT steps, etc.)
2330
- metadata Json?
2331
-
2332
- // Document validation rules (copied from plan for UPLOAD steps)
2333
- requiresManualReview Boolean @default(false)
2334
-
2335
- // Conditional step logic (copied from plan)
2336
- // When set, this step is only applicable if the condition evaluates to true
2337
- // Format: { "questionKey": "mortgage_type", "operator": "EQUALS", "value": "JOINT" }
2338
- // Or: { "questionKey": "employment_status", "operator": "IN", "values": ["SELF_EMPLOYED", "BUSINESS_OWNER"] }
2339
- condition Json?
2340
-
2341
- // =========================================================================
2342
- // MULTI-PARTY REVIEW CONFIGURATION (for UPLOAD steps)
2343
- // =========================================================================
2344
- // Defines which parties must review documents uploaded in this step
2345
- // Format: [{ party: "INTERNAL", required: true }, { party: "BANK", required: true }]
2346
- // If null, defaults to single internal review (backward compatible)
2347
- reviewRequirements Json?
2348
-
2349
- // Review order: 'SEQUENTIAL' = parties review in order, 'PARALLEL' = all review simultaneously
2350
- reviewOrder String? // 'SEQUENTIAL' | 'PARALLEL'
2351
-
2352
- // Assignment
2353
- assigneeId String?
2354
- assignee User? @relation("DocumentationStepAssignee", fields: [assigneeId], references: [id])
2355
-
2356
- // Required document types for UPLOAD steps (normalized)
2357
- requiredDocuments DocumentationStepDocument[]
2358
-
2359
- // =========================================================================
2360
- // GATE STEP CONFIGURATION (only applicable when stepType = GATE)
2361
- // =========================================================================
2362
- gateActor GateActor? // Who must perform the action
2363
- gateAction GateAction? // What action is required
2364
- gateRoleId String? // If gateActor = SPECIFIC_ROLE, which role
2365
- gateInstructions String? @db.Text // Instructions shown to actor
2366
- allowReject Boolean @default(true) // Can the actor reject?
2367
- rejectBehavior GateRejectBehavior? // What happens on reject
2368
- requiresComment Boolean @default(false) // Must actor provide a comment?
2369
-
2370
- // Gate action tracking
2371
- gateActedAt DateTime? // When the gate action was performed
2372
- gateActedById String? // Who performed the gate action
2373
- gateActedBy User? @relation("GateActedBy", fields: [gateActedById], references: [id])
2374
- gateDecision String? // APPROVED, REJECTED, ACKNOWLEDGED, etc.
2375
- gateComment String? @db.Text // Comment from actor
2376
-
2377
- // Timing
2378
- dueDate DateTime?
2379
- completedAt DateTime?
2380
-
2381
- createdAt DateTime @default(now())
2382
- updatedAt DateTime @updatedAt
2383
-
2384
- approvals DocumentationStepApproval[]
2385
- currentForPhase DocumentationPhase[] @relation("CurrentStep")
2386
-
2387
- @@index([tenantId])
2388
- @@index([documentationPhaseId])
2389
- @@index([status])
2390
- @@index([order])
2391
- @@map("documentation_steps")
2392
- }
2393
-
2394
- // Required documents for a step (normalized from CSV)
2395
- model DocumentationStepDocument {
2396
- id String @id @default(cuid())
2397
- tenantId String
2398
- tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
2399
- stepId String
2400
- step DocumentationStep @relation(fields: [stepId], references: [id], onDelete: Cascade)
2401
-
2402
- documentType String
2403
- isRequired Boolean @default(true)
2404
-
2405
- createdAt DateTime @default(now())
2406
-
2407
- @@index([tenantId])
2408
- @@index([stepId, documentType])
2409
- @@map("documentation_step_documents")
2410
- }
2411
-
2412
- // Approvals for documentation steps
2413
- model DocumentationStepApproval {
2414
- id String @id @default(cuid())
2415
- tenantId String
2416
- tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
2417
- stepId String
2418
- step DocumentationStep @relation(fields: [stepId], references: [id], onDelete: Cascade)
2419
- approverId String?
2420
- approver User? @relation("DocumentationStepApprover", fields: [approverId], references: [id])
2421
-
2422
- decision ApprovalDecision
2423
- comment String? @db.Text
2424
- decidedAt DateTime @default(now())
2425
-
2426
- createdAt DateTime @default(now())
2427
-
2428
- @@index([tenantId])
2429
- @@index([stepId])
2430
- @@map("documentation_step_approvals")
2431
- }
2432
-
2433
2346
  // Installments within a PAYMENT phase
2434
2347
  model PaymentInstallment {
2435
2348
  id String @id @default(cuid())
@@ -2516,15 +2429,19 @@ model ApplicationDocument {
2516
2429
  phaseId String? // Optional link to specific phase
2517
2430
  stepId String? // Optional link to specific step
2518
2431
 
2519
- name String
2432
+ // Document info
2433
+ documentType String? // ID_CARD, BANK_STATEMENT, etc. (matches DocumentDefinition.documentType)
2434
+ documentName String? // Human-readable name (copied from DocumentDefinition.documentName)
2435
+ name String // File name
2520
2436
  url String
2521
- type String // ID, BANK_STATEMENT, INCOME_PROOF, TITLE_DEED, SIGNATURE, etc.
2437
+ type String // ID, BANK_STATEMENT, INCOME_PROOF, TITLE_DEED, SIGNATURE, etc. (legacy, use documentType)
2522
2438
  uploadedById String?
2523
2439
  uploadedBy User? @relation("DocumentUploader", fields: [uploadedById], references: [id])
2524
2440
 
2525
2441
  status DocumentStatus @default(PENDING)
2526
2442
 
2527
- // Document versioning (for re-uploads after changes requested)
2443
+ // NO versioning - document is replaced on re-upload (url is updated)
2444
+ // Keep these fields for backward compatibility but don't use for new code
2528
2445
  version Int @default(1)
2529
2446
  replacesDocumentId String? // If this is a revision, points to original
2530
2447
  replacesDocument ApplicationDocument? @relation("DocumentRevisions", fields: [replacesDocumentId], references: [id])
@@ -2533,14 +2450,18 @@ model ApplicationDocument {
2533
2450
  createdAt DateTime @default(now())
2534
2451
  updatedAt DateTime @updatedAt
2535
2452
 
2536
- // Multi-party reviews for this document
2453
+ // OLD: Multi-party reviews (deprecated, use approvalTrail)
2537
2454
  reviews DocumentReview[]
2538
2455
 
2456
+ // NEW: Full approval trail across all stages
2457
+ approvalTrail DocumentApproval[]
2458
+
2539
2459
  @@index([tenantId])
2540
2460
  @@index([applicationId])
2541
2461
  @@index([phaseId])
2542
2462
  @@index([stepId])
2543
2463
  @@index([type])
2464
+ @@index([documentType])
2544
2465
  @@index([status])
2545
2466
  @@index([replacesDocumentId])
2546
2467
  @@map("application_documents")
@@ -2601,6 +2522,100 @@ model DocumentReview {
2601
2522
  @@map("document_reviews")
2602
2523
  }
2603
2524
 
2525
+ // =============================================================================
2526
+ // APPROVAL STAGE PROGRESS - Runtime tracking of stage completion per phase
2527
+ // =============================================================================
2528
+ // Tracks the progress of each approval stage within a documentation phase.
2529
+ // Created when a documentation phase is instantiated from a plan.
2530
+ // =============================================================================
2531
+
2532
+ model ApprovalStageProgress {
2533
+ id String @id @default(cuid())
2534
+ tenantId String
2535
+ tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
2536
+ documentationPhaseId String
2537
+ documentationPhase DocumentationPhase @relation(fields: [documentationPhaseId], references: [id], onDelete: Cascade)
2538
+
2539
+ // Link to template
2540
+ approvalStageId String
2541
+ approvalStage ApprovalStage @relation(fields: [approvalStageId], references: [id])
2542
+
2543
+ // Stage info (denormalized for convenience)
2544
+ name String
2545
+ order Int
2546
+ reviewParty ReviewParty
2547
+
2548
+ // Behavior flags (copied from template)
2549
+ autoTransition Boolean @default(false)
2550
+ waitForAllDocuments Boolean @default(true)
2551
+ allowEarlyVisibility Boolean @default(false)
2552
+
2553
+ // Rejection behavior (copied from template)
2554
+ onRejection RejectionBehavior @default(CASCADE_BACK)
2555
+ restartFromStageOrder Int?
2556
+
2557
+ // Status tracking
2558
+ status StageStatus @default(PENDING)
2559
+ activatedAt DateTime?
2560
+ completedAt DateTime?
2561
+
2562
+ // Who completed this stage (when autoTransition = false)
2563
+ completedById String?
2564
+ completedBy User? @relation("StageCompletedBy", fields: [completedById], references: [id])
2565
+ transitionComment String? @db.Text // Optional comment when completing stage
2566
+
2567
+ createdAt DateTime @default(now())
2568
+ updatedAt DateTime @updatedAt
2569
+
2570
+ // Document approvals made during this stage
2571
+ documentApprovals DocumentApproval[]
2572
+
2573
+ @@unique([documentationPhaseId, order])
2574
+ @@index([tenantId])
2575
+ @@index([documentationPhaseId])
2576
+ @@index([approvalStageId])
2577
+ @@index([status])
2578
+ @@map("approval_stage_progress")
2579
+ }
2580
+
2581
+ // =============================================================================
2582
+ // DOCUMENT APPROVAL - Audit trail for document reviews per stage
2583
+ // =============================================================================
2584
+ // Records every review action taken on a document within a specific stage.
2585
+ // Provides full audit trail: who reviewed, what decision, when, with comments.
2586
+ // =============================================================================
2587
+
2588
+ model DocumentApproval {
2589
+ id String @id @default(cuid())
2590
+ tenantId String
2591
+ tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
2592
+ documentId String
2593
+ document ApplicationDocument @relation(fields: [documentId], references: [id], onDelete: Cascade)
2594
+
2595
+ // Which stage this approval belongs to
2596
+ stageProgressId String
2597
+ stageProgress ApprovalStageProgress @relation(fields: [stageProgressId], references: [id], onDelete: Cascade)
2598
+
2599
+ // Reviewer info
2600
+ reviewerId String
2601
+ reviewer User @relation("DocumentApprovalReviewer", fields: [reviewerId], references: [id])
2602
+ reviewParty ReviewParty // INTERNAL, BANK, etc.
2603
+
2604
+ // Decision
2605
+ decision ReviewDecision // APPROVED, REJECTED, CHANGES_REQUESTED
2606
+ comment String? @db.Text // Required on rejection
2607
+
2608
+ reviewedAt DateTime @default(now())
2609
+ createdAt DateTime @default(now())
2610
+
2611
+ @@index([tenantId])
2612
+ @@index([documentId])
2613
+ @@index([stageProgressId])
2614
+ @@index([reviewerId])
2615
+ @@index([decision])
2616
+ @@map("document_approvals")
2617
+ }
2618
+
2604
2619
  // =============================================================================
2605
2620
  // OFFER LETTERS - Provisional and Final offer documents
2606
2621
  // =============================================================================