@valentine-efagene/qshelter-common 2.0.142 → 2.0.144
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.
- package/dist/generated/client/browser.d.ts +32 -0
- package/dist/generated/client/client.d.ts +32 -0
- package/dist/generated/client/commonInputTypes.d.ts +354 -144
- package/dist/generated/client/enums.d.ts +45 -0
- package/dist/generated/client/enums.js +39 -0
- package/dist/generated/client/internal/class.d.ts +66 -0
- package/dist/generated/client/internal/class.js +2 -2
- package/dist/generated/client/internal/prismaNamespace.d.ts +633 -3
- package/dist/generated/client/internal/prismaNamespace.js +193 -1
- package/dist/generated/client/internal/prismaNamespaceBrowser.d.ts +204 -0
- package/dist/generated/client/internal/prismaNamespaceBrowser.js +193 -1
- package/dist/generated/client/models/Application.d.ts +669 -1
- package/dist/generated/client/models/ApplicationDocument.d.ts +577 -1
- package/dist/generated/client/models/ApplicationOrganization.d.ts +2385 -0
- package/dist/generated/client/models/ApplicationOrganization.js +1 -0
- package/dist/generated/client/models/BankDocumentRequirement.d.ts +1932 -0
- package/dist/generated/client/models/BankDocumentRequirement.js +1 -0
- package/dist/generated/client/models/DocumentExpiryWarning.d.ts +1141 -0
- package/dist/generated/client/models/DocumentExpiryWarning.js +1 -0
- package/dist/generated/client/models/Organization.d.ts +390 -0
- package/dist/generated/client/models/PropertyMedia.d.ts +0 -7
- package/dist/generated/client/models/PropertyPaymentMethod.d.ts +192 -3
- package/dist/generated/client/models/PropertyVariant.d.ts +0 -7
- package/dist/generated/client/models/ScheduledJob.d.ts +1317 -0
- package/dist/generated/client/models/ScheduledJob.js +1 -0
- package/dist/generated/client/models/StateTransitionDefinition.d.ts +1104 -0
- package/dist/generated/client/models/StateTransitionDefinition.js +1 -0
- package/dist/generated/client/models/StateTransitionLog.d.ts +1383 -0
- package/dist/generated/client/models/StateTransitionLog.js +1 -0
- package/dist/generated/client/models/Tenant.d.ts +2535 -798
- package/dist/generated/client/models/index.d.ts +6 -0
- package/dist/generated/client/models/index.js +6 -0
- package/dist/generated/client/models.d.ts +6 -0
- package/dist/src/prisma/tenant.js +4 -0
- package/package.json +1 -1
- package/prisma/migrations/20260120024650_add_questionnaire_phase_review/migration.sql +102 -0
- package/prisma/schema.prisma +423 -2
package/prisma/schema.prisma
CHANGED
|
@@ -679,6 +679,12 @@ model Organization {
|
|
|
679
679
|
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
680
680
|
members OrganizationMember[]
|
|
681
681
|
|
|
682
|
+
// Applications where this organization is involved
|
|
683
|
+
applicationAssignments ApplicationOrganization[]
|
|
684
|
+
|
|
685
|
+
// Bank-specific document requirements (for BANK type organizations)
|
|
686
|
+
documentRequirements BankDocumentRequirement[]
|
|
687
|
+
|
|
682
688
|
// Properties developed by this organization (for DEVELOPERs)
|
|
683
689
|
// developedProperties Property[] @relation("PropertyDeveloper")
|
|
684
690
|
|
|
@@ -728,6 +734,83 @@ model OrganizationMember {
|
|
|
728
734
|
@@map("organization_members")
|
|
729
735
|
}
|
|
730
736
|
|
|
737
|
+
// =============================================================================
|
|
738
|
+
// BANK DOCUMENT REQUIREMENTS - Bank-specific document overlays
|
|
739
|
+
// =============================================================================
|
|
740
|
+
// Banks have different risk appetites and compliance requirements.
|
|
741
|
+
// For a standardized product (e.g., NHF Mortgage), the payment structure is fixed
|
|
742
|
+
// but document requirements vary by bank.
|
|
743
|
+
//
|
|
744
|
+
// This model defines OVERLAY rules:
|
|
745
|
+
// - Base documents come from DocumentationPlan
|
|
746
|
+
// - Bank adds/modifies requirements via BankDocumentRequirement
|
|
747
|
+
//
|
|
748
|
+
// When switching banks mid-application:
|
|
749
|
+
// 1. Keep all existing approved documents
|
|
750
|
+
// 2. Query new bank's requirements
|
|
751
|
+
// 3. Calculate delta (what's missing)
|
|
752
|
+
// 4. Customer uploads only the delta
|
|
753
|
+
// =============================================================================
|
|
754
|
+
|
|
755
|
+
/// How the bank's requirement modifies the base requirement
|
|
756
|
+
enum BankDocumentModifier {
|
|
757
|
+
REQUIRED // Bank requires this document (add if not in base)
|
|
758
|
+
OPTIONAL // Bank makes this optional (override base if required)
|
|
759
|
+
NOT_REQUIRED // Bank doesn't need this (skip even if in base)
|
|
760
|
+
STRICTER // Bank has stricter version (e.g., 12 months instead of 6)
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/// Bank Document Requirement - Bank-specific document rules
|
|
764
|
+
model BankDocumentRequirement {
|
|
765
|
+
id String @id @default(cuid())
|
|
766
|
+
tenantId String
|
|
767
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
768
|
+
|
|
769
|
+
// Which bank this applies to
|
|
770
|
+
organizationId String
|
|
771
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
772
|
+
|
|
773
|
+
// Which phase type this applies to (e.g., KYC, VERIFICATION)
|
|
774
|
+
phaseType String
|
|
775
|
+
|
|
776
|
+
// Optional: specific payment method (NULL = applies to all)
|
|
777
|
+
paymentMethodId String?
|
|
778
|
+
paymentMethod PropertyPaymentMethod? @relation(fields: [paymentMethodId], references: [id])
|
|
779
|
+
|
|
780
|
+
// Document identification
|
|
781
|
+
documentType String // ID_CARD, BANK_STATEMENT, EMPLOYMENT_LETTER, etc.
|
|
782
|
+
documentName String // Human-readable override (e.g., "12 Months Bank Statement")
|
|
783
|
+
|
|
784
|
+
// How this modifies the base requirement
|
|
785
|
+
modifier BankDocumentModifier @default(REQUIRED)
|
|
786
|
+
|
|
787
|
+
// Bank-specific rules
|
|
788
|
+
description String? @db.Text // Bank's specific instructions
|
|
789
|
+
expiryDays Int? // Bank's validity period (may be stricter than base)
|
|
790
|
+
minFiles Int? // Bank may require more files
|
|
791
|
+
maxFiles Int?
|
|
792
|
+
allowedMimeTypes String? // Bank may restrict file types
|
|
793
|
+
|
|
794
|
+
// Bank-specific validation (JSON schema)
|
|
795
|
+
// Example: { "bankStatementMonths": 12, "minimumBalance": 500000 }
|
|
796
|
+
validationRules Json?
|
|
797
|
+
|
|
798
|
+
// Priority for conflict resolution (higher = takes precedence)
|
|
799
|
+
priority Int @default(100)
|
|
800
|
+
|
|
801
|
+
isActive Boolean @default(true)
|
|
802
|
+
createdAt DateTime @default(now())
|
|
803
|
+
updatedAt DateTime @updatedAt
|
|
804
|
+
|
|
805
|
+
@@unique([organizationId, phaseType, documentType, paymentMethodId])
|
|
806
|
+
@@index([tenantId])
|
|
807
|
+
@@index([organizationId])
|
|
808
|
+
@@index([phaseType])
|
|
809
|
+
@@index([documentType])
|
|
810
|
+
@@index([paymentMethodId])
|
|
811
|
+
@@map("bank_document_requirements")
|
|
812
|
+
}
|
|
813
|
+
|
|
731
814
|
model Tenant {
|
|
732
815
|
id String @id @default(cuid())
|
|
733
816
|
name String
|
|
@@ -815,9 +898,18 @@ model Tenant {
|
|
|
815
898
|
questionnairePhaseReviews QuestionnairePhaseReview[]
|
|
816
899
|
documentReviews DocumentReview[]
|
|
817
900
|
|
|
901
|
+
// Bank-specific document requirements
|
|
902
|
+
bankDocumentRequirements BankDocumentRequirement[]
|
|
903
|
+
|
|
818
904
|
// Organizations (Banks, Developers) operating on this tenant
|
|
819
905
|
organizations Organization[]
|
|
820
906
|
|
|
907
|
+
// Application organization assignments
|
|
908
|
+
applicationOrganizations ApplicationOrganization[]
|
|
909
|
+
|
|
910
|
+
// State machine audit
|
|
911
|
+
stateTransitionLogs StateTransitionLog[]
|
|
912
|
+
|
|
821
913
|
@@index([subdomain])
|
|
822
914
|
@@map("tenants")
|
|
823
915
|
}
|
|
@@ -1570,6 +1662,9 @@ model PropertyPaymentMethod {
|
|
|
1570
1662
|
changeRulesFrom DocumentRequirementRule[] @relation("RuleFromMethod")
|
|
1571
1663
|
changeRulesTo DocumentRequirementRule[] @relation("RuleToMethod")
|
|
1572
1664
|
|
|
1665
|
+
// Bank-specific document requirements for this payment method
|
|
1666
|
+
bankDocumentRequirements BankDocumentRequirement[]
|
|
1667
|
+
|
|
1573
1668
|
@@unique([tenantId, name]) // Unique per tenant
|
|
1574
1669
|
@@index([tenantId])
|
|
1575
1670
|
@@map("property_payment_methods")
|
|
@@ -1914,6 +2009,17 @@ model Application {
|
|
|
1914
2009
|
paymentMethodId String? // PropertyPaymentMethod used to create this contract
|
|
1915
2010
|
paymentMethod PropertyPaymentMethod? @relation(fields: [paymentMethodId], references: [id])
|
|
1916
2011
|
|
|
2012
|
+
// =========================================================================
|
|
2013
|
+
// PAYMENT METHOD VERSION SNAPSHOT
|
|
2014
|
+
// =========================================================================
|
|
2015
|
+
// Captures the payment method configuration at application creation time.
|
|
2016
|
+
// This ensures existing applications continue with original terms even if
|
|
2017
|
+
// the payment method template is later modified.
|
|
2018
|
+
// =========================================================================
|
|
2019
|
+
paymentMethodSnapshot Json? // Full snapshot of PropertyPaymentMethod + phases at creation
|
|
2020
|
+
paymentMethodSnapshotAt DateTime? // When the snapshot was taken
|
|
2021
|
+
paymentMethodSnapshotHash String? // Hash to detect if template changed since snapshot
|
|
2022
|
+
|
|
1917
2023
|
// Contract identification
|
|
1918
2024
|
applicationNumber String @unique
|
|
1919
2025
|
title String
|
|
@@ -1971,6 +2077,9 @@ model Application {
|
|
|
1971
2077
|
// Refund requests
|
|
1972
2078
|
refunds ApplicationRefund[]
|
|
1973
2079
|
|
|
2080
|
+
// Organization assignments - which orgs are involved in this application
|
|
2081
|
+
organizations ApplicationOrganization[]
|
|
2082
|
+
|
|
1974
2083
|
@@index([tenantId])
|
|
1975
2084
|
@@index([propertyUnitId])
|
|
1976
2085
|
@@index([buyerId])
|
|
@@ -1982,6 +2091,104 @@ model Application {
|
|
|
1982
2091
|
@@map("applications")
|
|
1983
2092
|
}
|
|
1984
2093
|
|
|
2094
|
+
// =============================================================================
|
|
2095
|
+
// APPLICATION ORGANIZATION - Binds organizations to specific applications
|
|
2096
|
+
// =============================================================================
|
|
2097
|
+
// Tracks which organizations (banks, developers, legal firms) are involved
|
|
2098
|
+
// in a specific application. This enables:
|
|
2099
|
+
// 1. Validation that only assigned developers can upload sales offers
|
|
2100
|
+
// 2. Only assigned banks can upload preapproval/mortgage offer letters
|
|
2101
|
+
// 3. Multi-bank application support (future: apply to multiple banks)
|
|
2102
|
+
// =============================================================================
|
|
2103
|
+
|
|
2104
|
+
/// Role that an organization plays in an application
|
|
2105
|
+
enum ApplicationOrganizationRole {
|
|
2106
|
+
DEVELOPER // Property developer - uploads sales offer letters
|
|
2107
|
+
LENDER // Bank/financial institution - provides mortgage
|
|
2108
|
+
LEGAL // Legal firm - handles conveyancing
|
|
2109
|
+
INSURER // Insurance company
|
|
2110
|
+
GOVERNMENT // Government agency (land registry, etc.)
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
/// Status of organization's involvement in the application
|
|
2114
|
+
enum ApplicationOrganizationStatus {
|
|
2115
|
+
PENDING // Awaiting organization's response/engagement
|
|
2116
|
+
ACTIVE // Organization is actively participating
|
|
2117
|
+
COMPLETED // Organization's role is complete
|
|
2118
|
+
DECLINED // Organization declined to participate
|
|
2119
|
+
WITHDRAWN // Organization withdrew from the application
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
model ApplicationOrganization {
|
|
2123
|
+
id String @id @default(cuid())
|
|
2124
|
+
tenantId String
|
|
2125
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
2126
|
+
applicationId String
|
|
2127
|
+
application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)
|
|
2128
|
+
|
|
2129
|
+
// Which organization is involved
|
|
2130
|
+
organizationId String
|
|
2131
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
2132
|
+
|
|
2133
|
+
// What role does this organization play
|
|
2134
|
+
role ApplicationOrganizationRole
|
|
2135
|
+
status ApplicationOrganizationStatus @default(PENDING)
|
|
2136
|
+
|
|
2137
|
+
// Who assigned this organization (admin or system)
|
|
2138
|
+
assignedById String?
|
|
2139
|
+
assignedAt DateTime @default(now())
|
|
2140
|
+
|
|
2141
|
+
// For multi-bank applications: track if this is the selected lender
|
|
2142
|
+
// Multiple banks can be PENDING, but only one should be ACTIVE for LENDER role
|
|
2143
|
+
isPrimary Boolean @default(false)
|
|
2144
|
+
|
|
2145
|
+
// Organization-specific terms (e.g., bank's offered interest rate)
|
|
2146
|
+
offeredTerms Json? // { interestRate, termMonths, conditions, etc. }
|
|
2147
|
+
termsOfferedAt DateTime?
|
|
2148
|
+
termsAcceptedAt DateTime?
|
|
2149
|
+
termsDeclinedAt DateTime?
|
|
2150
|
+
declineReason String? @db.Text
|
|
2151
|
+
|
|
2152
|
+
// Tracking
|
|
2153
|
+
activatedAt DateTime?
|
|
2154
|
+
completedAt DateTime?
|
|
2155
|
+
withdrawnAt DateTime?
|
|
2156
|
+
|
|
2157
|
+
// =========================================================================
|
|
2158
|
+
// SLA TRACKING - Monitor bank responsiveness
|
|
2159
|
+
// =========================================================================
|
|
2160
|
+
// When documentation is complete, clock starts for bank to respond.
|
|
2161
|
+
// If they're slow, admin can reassign to another bank.
|
|
2162
|
+
// =========================================================================
|
|
2163
|
+
slaHours Int? // Expected response time (e.g., 48 hours)
|
|
2164
|
+
slaStartedAt DateTime? // When clock started (e.g., when docs were complete)
|
|
2165
|
+
slaBreachedAt DateTime? // When SLA was breached (set by cron job)
|
|
2166
|
+
slaBreachNotified Boolean @default(false) // Was admin notified of breach?
|
|
2167
|
+
|
|
2168
|
+
// Reminder tracking
|
|
2169
|
+
reminderCount Int @default(0)
|
|
2170
|
+
lastReminderSentAt DateTime?
|
|
2171
|
+
nextReminderAt DateTime?
|
|
2172
|
+
|
|
2173
|
+
// Escalation
|
|
2174
|
+
escalatedAt DateTime?
|
|
2175
|
+
escalatedToUserId String? // Admin handling the escalation
|
|
2176
|
+
escalationNotes String? @db.Text
|
|
2177
|
+
|
|
2178
|
+
createdAt DateTime @default(now())
|
|
2179
|
+
updatedAt DateTime @updatedAt
|
|
2180
|
+
|
|
2181
|
+
@@unique([applicationId, organizationId, role]) // One org per role per application
|
|
2182
|
+
@@index([tenantId])
|
|
2183
|
+
@@index([applicationId])
|
|
2184
|
+
@@index([organizationId])
|
|
2185
|
+
@@index([role])
|
|
2186
|
+
@@index([status])
|
|
2187
|
+
@@index([isPrimary])
|
|
2188
|
+
@@index([slaBreachedAt])
|
|
2189
|
+
@@map("application_organizations")
|
|
2190
|
+
}
|
|
2191
|
+
|
|
1985
2192
|
// =============================================================================
|
|
1986
2193
|
// CONTRACT REFUNDS - Track refund requests for overpayments or cancellations
|
|
1987
2194
|
// =============================================================================
|
|
@@ -2182,8 +2389,8 @@ model QuestionnairePhaseReview {
|
|
|
2182
2389
|
notes String? @db.Text
|
|
2183
2390
|
|
|
2184
2391
|
// Snapshot of scores at time of review (for audit)
|
|
2185
|
-
scoreAtReview
|
|
2186
|
-
passedAtReview
|
|
2392
|
+
scoreAtReview Int? // The totalScore when this review was made
|
|
2393
|
+
passedAtReview Boolean? // The passed flag when this review was made
|
|
2187
2394
|
|
|
2188
2395
|
createdAt DateTime @default(now())
|
|
2189
2396
|
|
|
@@ -2478,6 +2685,29 @@ model ApplicationDocument {
|
|
|
2478
2685
|
uploadedById String?
|
|
2479
2686
|
uploadedBy User? @relation("DocumentUploader", fields: [uploadedById], references: [id])
|
|
2480
2687
|
|
|
2688
|
+
// =========================================================================
|
|
2689
|
+
// UPLOADER VALIDATION - Enforces who can upload this document
|
|
2690
|
+
// =========================================================================
|
|
2691
|
+
// expectedUploader is set from DocumentDefinition.uploadedBy at phase creation
|
|
2692
|
+
// Allows validation that correct party is uploading (e.g., developer uploads sales offer)
|
|
2693
|
+
expectedUploader UploadedBy? // CUSTOMER, LENDER, DEVELOPER, LEGAL, PLATFORM, etc.
|
|
2694
|
+
// If expectedUploader is LENDER/DEVELOPER, track which org should upload
|
|
2695
|
+
expectedOrganizationId String?
|
|
2696
|
+
|
|
2697
|
+
// =========================================================================
|
|
2698
|
+
// DOCUMENT EXPIRY - Time-sensitive document tracking
|
|
2699
|
+
// =========================================================================
|
|
2700
|
+
// Documents like bank statements have a shelf life. If application takes too long,
|
|
2701
|
+
// documents may need to be re-uploaded.
|
|
2702
|
+
// =========================================================================
|
|
2703
|
+
documentDate DateTime? // When the document was issued/created (e.g., bank statement date)
|
|
2704
|
+
expiresAt DateTime? // When this document expires (computed from documentDate + expiryDays)
|
|
2705
|
+
expiryDays Int? // Number of days this document type is valid (copied from DocumentDefinition)
|
|
2706
|
+
isExpired Boolean @default(false) // Denormalized flag, updated by cron job
|
|
2707
|
+
expiredAt DateTime? // When the document was marked expired
|
|
2708
|
+
expiryWarningAt DateTime? // When expiry warning was sent
|
|
2709
|
+
revalidatedAt DateTime? // If document was re-uploaded after expiry
|
|
2710
|
+
|
|
2481
2711
|
status DocumentStatus @default(PENDING)
|
|
2482
2712
|
|
|
2483
2713
|
// NO versioning - document is replaced on re-upload (url is updated)
|
|
@@ -2504,6 +2734,8 @@ model ApplicationDocument {
|
|
|
2504
2734
|
@@index([documentType])
|
|
2505
2735
|
@@index([status])
|
|
2506
2736
|
@@index([replacesDocumentId])
|
|
2737
|
+
@@index([isExpired])
|
|
2738
|
+
@@index([expiresAt])
|
|
2507
2739
|
@@map("application_documents")
|
|
2508
2740
|
}
|
|
2509
2741
|
|
|
@@ -3504,3 +3736,192 @@ model WorkflowBlocker {
|
|
|
3504
3736
|
@@index([tenantId, isOverdue, blockerActor]) // For SLA violation queries
|
|
3505
3737
|
@@map("workflow_blockers")
|
|
3506
3738
|
}
|
|
3739
|
+
|
|
3740
|
+
// =============================================================================
|
|
3741
|
+
// STATE MACHINE DEFINITION - Explicit state transitions
|
|
3742
|
+
// =============================================================================
|
|
3743
|
+
// Defines valid state transitions for applications and phases.
|
|
3744
|
+
// This makes the state machine configurable and auditable, rather than
|
|
3745
|
+
// being hard-coded in service logic.
|
|
3746
|
+
// =============================================================================
|
|
3747
|
+
|
|
3748
|
+
/// Entity type that has state machine behavior
|
|
3749
|
+
enum StateMachineEntity {
|
|
3750
|
+
APPLICATION
|
|
3751
|
+
APPLICATION_PHASE
|
|
3752
|
+
DOCUMENTATION_STAGE
|
|
3753
|
+
DOCUMENT
|
|
3754
|
+
}
|
|
3755
|
+
|
|
3756
|
+
/// State Machine Transition Definition - Configurable state transitions
|
|
3757
|
+
/// Allows admins to customize workflows without code changes
|
|
3758
|
+
model StateTransitionDefinition {
|
|
3759
|
+
id String @id @default(cuid())
|
|
3760
|
+
tenantId String? // NULL = global template, set = tenant-specific override
|
|
3761
|
+
|
|
3762
|
+
// What entity this transition applies to
|
|
3763
|
+
entityType StateMachineEntity
|
|
3764
|
+
|
|
3765
|
+
// The transition
|
|
3766
|
+
fromState String // e.g., "DRAFT", "PENDING", "IN_PROGRESS"
|
|
3767
|
+
toState String // e.g., "ACTIVE", "COMPLETED"
|
|
3768
|
+
trigger String // e.g., "SUBMIT", "APPROVE", "COMPLETE"
|
|
3769
|
+
|
|
3770
|
+
// Transition constraints
|
|
3771
|
+
isEnabled Boolean @default(true)
|
|
3772
|
+
requiresRole String? // Role required to trigger this transition
|
|
3773
|
+
requiresPhase String? // Phase type required (for APPLICATION transitions)
|
|
3774
|
+
|
|
3775
|
+
// Side effects configuration
|
|
3776
|
+
sideEffects Json? // [{ type: "SEND_EMAIL", config: {...} }, { type: "LOCK_UNIT" }]
|
|
3777
|
+
|
|
3778
|
+
// Audit
|
|
3779
|
+
description String? @db.Text
|
|
3780
|
+
createdAt DateTime @default(now())
|
|
3781
|
+
updatedAt DateTime @updatedAt
|
|
3782
|
+
|
|
3783
|
+
@@unique([tenantId, entityType, fromState, trigger])
|
|
3784
|
+
@@index([entityType])
|
|
3785
|
+
@@index([fromState])
|
|
3786
|
+
@@index([trigger])
|
|
3787
|
+
@@map("state_transition_definitions")
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3790
|
+
/// State Transition Log - Audit trail for all state changes
|
|
3791
|
+
/// Records every state transition for compliance and debugging
|
|
3792
|
+
model StateTransitionLog {
|
|
3793
|
+
id String @id @default(cuid())
|
|
3794
|
+
tenantId String
|
|
3795
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
3796
|
+
|
|
3797
|
+
// What entity changed state
|
|
3798
|
+
entityType StateMachineEntity
|
|
3799
|
+
entityId String // Application ID, Phase ID, Document ID, etc.
|
|
3800
|
+
|
|
3801
|
+
// The transition that occurred
|
|
3802
|
+
fromState String
|
|
3803
|
+
toState String
|
|
3804
|
+
trigger String
|
|
3805
|
+
|
|
3806
|
+
// Who triggered the transition
|
|
3807
|
+
actorId String?
|
|
3808
|
+
actorType EventActorType?
|
|
3809
|
+
|
|
3810
|
+
// Context at time of transition
|
|
3811
|
+
contextSnapshot Json? // Relevant data at time of transition (phase data, payment amounts, etc.)
|
|
3812
|
+
|
|
3813
|
+
// Timing
|
|
3814
|
+
occurredAt DateTime @default(now())
|
|
3815
|
+
durationMs Int? // How long the entity was in fromState
|
|
3816
|
+
|
|
3817
|
+
// Validation
|
|
3818
|
+
wasValid Boolean @default(true) // Was this a valid transition per state machine?
|
|
3819
|
+
errorMessage String? @db.Text // If invalid, why?
|
|
3820
|
+
|
|
3821
|
+
@@index([tenantId])
|
|
3822
|
+
@@index([entityType, entityId])
|
|
3823
|
+
@@index([entityType, fromState])
|
|
3824
|
+
@@index([entityType, toState])
|
|
3825
|
+
@@index([occurredAt])
|
|
3826
|
+
@@index([actorId])
|
|
3827
|
+
@@map("state_transition_logs")
|
|
3828
|
+
}
|
|
3829
|
+
|
|
3830
|
+
// =============================================================================
|
|
3831
|
+
// DOCUMENT EXPIRY JOB - Scheduled job tracking for document expiration checks
|
|
3832
|
+
// =============================================================================
|
|
3833
|
+
// Tracks scheduled jobs for checking document expiration across applications.
|
|
3834
|
+
// This supports a cron-based approach where a Lambda runs periodically to:
|
|
3835
|
+
// 1. Find documents nearing expiry (warning)
|
|
3836
|
+
// 2. Mark expired documents
|
|
3837
|
+
// 3. Notify customers to re-upload
|
|
3838
|
+
// 4. Optionally block phase progression if critical documents expired
|
|
3839
|
+
// =============================================================================
|
|
3840
|
+
|
|
3841
|
+
/// Job status for scheduled background jobs
|
|
3842
|
+
enum ScheduledJobStatus {
|
|
3843
|
+
PENDING
|
|
3844
|
+
RUNNING
|
|
3845
|
+
COMPLETED
|
|
3846
|
+
FAILED
|
|
3847
|
+
CANCELLED
|
|
3848
|
+
}
|
|
3849
|
+
|
|
3850
|
+
/// Type of scheduled job
|
|
3851
|
+
enum ScheduledJobType {
|
|
3852
|
+
DOCUMENT_EXPIRY_CHECK // Check for expired documents
|
|
3853
|
+
SLA_BREACH_CHECK // Check for SLA breaches
|
|
3854
|
+
PAYMENT_REMINDER // Send payment reminders
|
|
3855
|
+
DOCUMENT_EXPIRY_WARNING // Warn about documents nearing expiry
|
|
3856
|
+
}
|
|
3857
|
+
|
|
3858
|
+
/// Scheduled Job - Tracks execution of background jobs
|
|
3859
|
+
model ScheduledJob {
|
|
3860
|
+
id String @id @default(cuid())
|
|
3861
|
+
tenantId String? // NULL = system-wide job, set = tenant-specific
|
|
3862
|
+
|
|
3863
|
+
jobType ScheduledJobType
|
|
3864
|
+
status ScheduledJobStatus @default(PENDING)
|
|
3865
|
+
|
|
3866
|
+
// Scheduling
|
|
3867
|
+
scheduledAt DateTime // When the job should run
|
|
3868
|
+
startedAt DateTime? // When job started executing
|
|
3869
|
+
completedAt DateTime? // When job finished
|
|
3870
|
+
durationMs Int? // Execution time
|
|
3871
|
+
|
|
3872
|
+
// Job parameters
|
|
3873
|
+
parameters Json? // Job-specific configuration
|
|
3874
|
+
|
|
3875
|
+
// Results
|
|
3876
|
+
itemsProcessed Int @default(0)
|
|
3877
|
+
itemsAffected Int @default(0) // Documents expired, SLAs breached, etc.
|
|
3878
|
+
errorCount Int @default(0)
|
|
3879
|
+
errors Json? // Array of error details
|
|
3880
|
+
summary String? @db.Text // Human-readable summary
|
|
3881
|
+
|
|
3882
|
+
// Retry handling
|
|
3883
|
+
attemptNumber Int @default(1)
|
|
3884
|
+
maxAttempts Int @default(3)
|
|
3885
|
+
nextRetryAt DateTime?
|
|
3886
|
+
|
|
3887
|
+
createdAt DateTime @default(now())
|
|
3888
|
+
updatedAt DateTime @updatedAt
|
|
3889
|
+
|
|
3890
|
+
@@index([tenantId])
|
|
3891
|
+
@@index([jobType])
|
|
3892
|
+
@@index([status])
|
|
3893
|
+
@@index([scheduledAt])
|
|
3894
|
+
@@index([jobType, status, scheduledAt])
|
|
3895
|
+
@@map("scheduled_jobs")
|
|
3896
|
+
}
|
|
3897
|
+
|
|
3898
|
+
/// Document Expiry Warning - Track warnings sent for expiring documents
|
|
3899
|
+
model DocumentExpiryWarning {
|
|
3900
|
+
id String @id @default(cuid())
|
|
3901
|
+
tenantId String
|
|
3902
|
+
documentId String
|
|
3903
|
+
|
|
3904
|
+
// Warning details
|
|
3905
|
+
expiresAt DateTime // When document will expire
|
|
3906
|
+
daysUntil Int // Days until expiry at time of warning
|
|
3907
|
+
warningSent DateTime @default(now())
|
|
3908
|
+
|
|
3909
|
+
// Customer notification tracking
|
|
3910
|
+
notificationSent Boolean @default(false)
|
|
3911
|
+
notificationId String? // Reference to notification service
|
|
3912
|
+
|
|
3913
|
+
// Resolution tracking
|
|
3914
|
+
resolved Boolean @default(false)
|
|
3915
|
+
resolvedAt DateTime?
|
|
3916
|
+
resolvedBy String? // User who resolved (re-uploaded document)
|
|
3917
|
+
newDocumentId String? // ID of the replacement document
|
|
3918
|
+
|
|
3919
|
+
createdAt DateTime @default(now())
|
|
3920
|
+
|
|
3921
|
+
@@unique([documentId, daysUntil]) // One warning per document per threshold
|
|
3922
|
+
@@index([tenantId])
|
|
3923
|
+
@@index([documentId])
|
|
3924
|
+
@@index([expiresAt])
|
|
3925
|
+
@@index([resolved])
|
|
3926
|
+
@@map("document_expiry_warnings")
|
|
3927
|
+
}
|