@valentine-efagene/qshelter-common 2.0.24 → 2.0.26
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 +15 -0
- package/dist/generated/client/client.d.ts +15 -0
- package/dist/generated/client/commonInputTypes.d.ts +200 -0
- package/dist/generated/client/enums.d.ts +25 -1
- package/dist/generated/client/enums.js +22 -1
- package/dist/generated/client/internal/class.d.ts +33 -0
- package/dist/generated/client/internal/class.js +2 -2
- package/dist/generated/client/internal/prismaNamespace.d.ts +352 -1
- package/dist/generated/client/internal/prismaNamespace.js +120 -0
- package/dist/generated/client/internal/prismaNamespaceBrowser.d.ts +130 -0
- package/dist/generated/client/internal/prismaNamespaceBrowser.js +120 -0
- package/dist/generated/client/models/Contract.d.ts +511 -0
- package/dist/generated/client/models/DocumentRequirementRule.d.ts +2069 -0
- package/dist/generated/client/models/DocumentRequirementRule.js +1 -0
- package/dist/generated/client/models/PaymentMethodChangeRequest.d.ts +2820 -0
- package/dist/generated/client/models/PaymentMethodChangeRequest.js +1 -0
- package/dist/generated/client/models/Prequalification.d.ts +2339 -0
- package/dist/generated/client/models/Prequalification.js +1 -0
- package/dist/generated/client/models/Property.d.ts +211 -0
- package/dist/generated/client/models/PropertyPaymentMethod.d.ts +1139 -131
- package/dist/generated/client/models/Tenant.d.ts +441 -0
- package/dist/generated/client/models/User.d.ts +815 -0
- package/dist/generated/client/models.d.ts +3 -0
- package/dist/src/middleware/tenant.d.ts +15 -0
- package/dist/src/middleware/tenant.js +5 -2
- package/package.json +1 -1
- package/prisma/migrations/20251230231217_add_prequalification_and_payment_method_change/migration.sql +137 -0
- package/prisma/schema.prisma +225 -5
|
@@ -36,5 +36,8 @@ export type * from './models/ContractPayment.js';
|
|
|
36
36
|
export type * from './models/ContractDocument.js';
|
|
37
37
|
export type * from './models/ContractTransition.js';
|
|
38
38
|
export type * from './models/ContractEvent.js';
|
|
39
|
+
export type * from './models/Prequalification.js';
|
|
40
|
+
export type * from './models/PaymentMethodChangeRequest.js';
|
|
41
|
+
export type * from './models/DocumentRequirementRule.js';
|
|
39
42
|
export type * from './models/DomainEvent.js';
|
|
40
43
|
export type * from './commonInputTypes.js';
|
|
@@ -9,6 +9,21 @@ declare global {
|
|
|
9
9
|
interface Request {
|
|
10
10
|
tenantContext?: TenantContext;
|
|
11
11
|
tenantPrisma?: TenantPrismaClient | PrismaClient;
|
|
12
|
+
/**
|
|
13
|
+
* API Gateway context added by serverless-express
|
|
14
|
+
*/
|
|
15
|
+
apiGateway?: {
|
|
16
|
+
event: {
|
|
17
|
+
requestContext: {
|
|
18
|
+
authorizer?: {
|
|
19
|
+
userId?: string;
|
|
20
|
+
email?: string;
|
|
21
|
+
roles?: string;
|
|
22
|
+
tenantId?: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
};
|
|
12
27
|
}
|
|
13
28
|
}
|
|
14
29
|
}
|
|
@@ -20,9 +20,12 @@ export function createTenantMiddleware(options) {
|
|
|
20
20
|
const { prisma, createScopedClient = true } = options;
|
|
21
21
|
return function tenantMiddleware(req, res, next) {
|
|
22
22
|
try {
|
|
23
|
+
// 1. Try Lambda authorizer context first (production)
|
|
24
|
+
const authorizerContext = req.apiGateway?.event?.requestContext?.authorizer;
|
|
25
|
+
// 2. Fall back to headers (local dev or alternative setups)
|
|
23
26
|
const headers = req.headers;
|
|
24
|
-
const tenantId = headers['x-tenant-id'];
|
|
25
|
-
const userId = headers['x-user-id'];
|
|
27
|
+
const tenantId = authorizerContext?.tenantId || headers['x-tenant-id'];
|
|
28
|
+
const userId = authorizerContext?.userId || headers['x-user-id'];
|
|
26
29
|
if (!tenantId) {
|
|
27
30
|
// For now, allow requests without tenant context for development
|
|
28
31
|
// In production, you might want to reject these
|
package/package.json
CHANGED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE `prequalifications` (
|
|
3
|
+
`id` VARCHAR(191) NOT NULL,
|
|
4
|
+
`tenantId` VARCHAR(191) NOT NULL,
|
|
5
|
+
`userId` VARCHAR(191) NOT NULL,
|
|
6
|
+
`propertyId` VARCHAR(191) NOT NULL,
|
|
7
|
+
`paymentMethodId` VARCHAR(191) NOT NULL,
|
|
8
|
+
`answers` JSON NOT NULL,
|
|
9
|
+
`score` DOUBLE NULL,
|
|
10
|
+
`requestedAmount` DOUBLE NULL,
|
|
11
|
+
`monthlyIncome` DOUBLE NULL,
|
|
12
|
+
`monthlyExpenses` DOUBLE NULL,
|
|
13
|
+
`debtToIncomeRatio` DOUBLE NULL,
|
|
14
|
+
`suggestedTermMonths` INTEGER NULL,
|
|
15
|
+
`status` ENUM('DRAFT', 'SUBMITTED', 'UNDER_REVIEW', 'APPROVED', 'REJECTED', 'EXPIRED') NOT NULL DEFAULT 'DRAFT',
|
|
16
|
+
`notes` TEXT NULL,
|
|
17
|
+
`reviewedBy` VARCHAR(191) NULL,
|
|
18
|
+
`reviewedAt` DATETIME(3) NULL,
|
|
19
|
+
`expiresAt` DATETIME(3) NULL,
|
|
20
|
+
`contractId` VARCHAR(191) NULL,
|
|
21
|
+
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
22
|
+
`updatedAt` DATETIME(3) NOT NULL,
|
|
23
|
+
|
|
24
|
+
UNIQUE INDEX `prequalifications_contractId_key`(`contractId`),
|
|
25
|
+
INDEX `prequalifications_tenantId_idx`(`tenantId`),
|
|
26
|
+
INDEX `prequalifications_userId_idx`(`userId`),
|
|
27
|
+
INDEX `prequalifications_propertyId_idx`(`propertyId`),
|
|
28
|
+
INDEX `prequalifications_status_idx`(`status`),
|
|
29
|
+
PRIMARY KEY (`id`)
|
|
30
|
+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
31
|
+
|
|
32
|
+
-- CreateTable
|
|
33
|
+
CREATE TABLE `payment_method_change_requests` (
|
|
34
|
+
`id` VARCHAR(191) NOT NULL,
|
|
35
|
+
`tenantId` VARCHAR(191) NOT NULL,
|
|
36
|
+
`contractId` VARCHAR(191) NOT NULL,
|
|
37
|
+
`fromPaymentMethodId` VARCHAR(191) NOT NULL,
|
|
38
|
+
`toPaymentMethodId` VARCHAR(191) NOT NULL,
|
|
39
|
+
`requestorId` VARCHAR(191) NOT NULL,
|
|
40
|
+
`reason` TEXT NULL,
|
|
41
|
+
`requiredDocumentTypes` VARCHAR(191) NULL,
|
|
42
|
+
`submittedDocuments` JSON NULL,
|
|
43
|
+
`currentOutstanding` DOUBLE NULL,
|
|
44
|
+
`newTermMonths` INTEGER NULL,
|
|
45
|
+
`newInterestRate` DOUBLE NULL,
|
|
46
|
+
`newMonthlyPayment` DOUBLE NULL,
|
|
47
|
+
`penaltyAmount` DOUBLE NULL,
|
|
48
|
+
`financialImpactNotes` TEXT NULL,
|
|
49
|
+
`status` ENUM('PENDING_DOCUMENTS', 'DOCUMENTS_SUBMITTED', 'UNDER_REVIEW', 'APPROVED', 'REJECTED', 'EXECUTED', 'CANCELLED') NOT NULL DEFAULT 'PENDING_DOCUMENTS',
|
|
50
|
+
`reviewerId` VARCHAR(191) NULL,
|
|
51
|
+
`reviewNotes` TEXT NULL,
|
|
52
|
+
`reviewedAt` DATETIME(3) NULL,
|
|
53
|
+
`executedAt` DATETIME(3) NULL,
|
|
54
|
+
`previousPhaseData` JSON NULL,
|
|
55
|
+
`newPhaseData` JSON NULL,
|
|
56
|
+
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
57
|
+
`updatedAt` DATETIME(3) NOT NULL,
|
|
58
|
+
|
|
59
|
+
INDEX `payment_method_change_requests_tenantId_idx`(`tenantId`),
|
|
60
|
+
INDEX `payment_method_change_requests_contractId_idx`(`contractId`),
|
|
61
|
+
INDEX `payment_method_change_requests_status_idx`(`status`),
|
|
62
|
+
INDEX `payment_method_change_requests_requestorId_idx`(`requestorId`),
|
|
63
|
+
PRIMARY KEY (`id`)
|
|
64
|
+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
65
|
+
|
|
66
|
+
-- CreateTable
|
|
67
|
+
CREATE TABLE `document_requirement_rules` (
|
|
68
|
+
`id` VARCHAR(191) NOT NULL,
|
|
69
|
+
`tenantId` VARCHAR(191) NOT NULL,
|
|
70
|
+
`context` ENUM('PREQUALIFICATION', 'CONTRACT_PHASE', 'PAYMENT_METHOD_CHANGE') NOT NULL,
|
|
71
|
+
`paymentMethodId` VARCHAR(191) NULL,
|
|
72
|
+
`phaseType` VARCHAR(191) NULL,
|
|
73
|
+
`fromPaymentMethodId` VARCHAR(191) NULL,
|
|
74
|
+
`toPaymentMethodId` VARCHAR(191) NULL,
|
|
75
|
+
`documentType` VARCHAR(191) NOT NULL,
|
|
76
|
+
`isRequired` BOOLEAN NOT NULL DEFAULT true,
|
|
77
|
+
`description` VARCHAR(191) NULL,
|
|
78
|
+
`maxSizeBytes` INTEGER NULL,
|
|
79
|
+
`allowedMimeTypes` VARCHAR(191) NULL,
|
|
80
|
+
`expiryDays` INTEGER NULL,
|
|
81
|
+
`requiresManualReview` BOOLEAN NOT NULL DEFAULT false,
|
|
82
|
+
`isActive` BOOLEAN NOT NULL DEFAULT true,
|
|
83
|
+
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
84
|
+
`updatedAt` DATETIME(3) NOT NULL,
|
|
85
|
+
|
|
86
|
+
INDEX `document_requirement_rules_tenantId_idx`(`tenantId`),
|
|
87
|
+
INDEX `document_requirement_rules_context_idx`(`context`),
|
|
88
|
+
INDEX `document_requirement_rules_paymentMethodId_idx`(`paymentMethodId`),
|
|
89
|
+
INDEX `document_requirement_rules_phaseType_idx`(`phaseType`),
|
|
90
|
+
INDEX `document_requirement_rules_fromPaymentMethodId_toPaymentMeth_idx`(`fromPaymentMethodId`, `toPaymentMethodId`),
|
|
91
|
+
PRIMARY KEY (`id`)
|
|
92
|
+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
93
|
+
|
|
94
|
+
-- AddForeignKey
|
|
95
|
+
ALTER TABLE `prequalifications` ADD CONSTRAINT `prequalifications_tenantId_fkey` FOREIGN KEY (`tenantId`) REFERENCES `tenants`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
96
|
+
|
|
97
|
+
-- AddForeignKey
|
|
98
|
+
ALTER TABLE `prequalifications` ADD CONSTRAINT `prequalifications_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
99
|
+
|
|
100
|
+
-- AddForeignKey
|
|
101
|
+
ALTER TABLE `prequalifications` ADD CONSTRAINT `prequalifications_propertyId_fkey` FOREIGN KEY (`propertyId`) REFERENCES `properties`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
102
|
+
|
|
103
|
+
-- AddForeignKey
|
|
104
|
+
ALTER TABLE `prequalifications` ADD CONSTRAINT `prequalifications_paymentMethodId_fkey` FOREIGN KEY (`paymentMethodId`) REFERENCES `property_payment_methods`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
105
|
+
|
|
106
|
+
-- AddForeignKey
|
|
107
|
+
ALTER TABLE `prequalifications` ADD CONSTRAINT `prequalifications_contractId_fkey` FOREIGN KEY (`contractId`) REFERENCES `contracts`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
108
|
+
|
|
109
|
+
-- AddForeignKey
|
|
110
|
+
ALTER TABLE `payment_method_change_requests` ADD CONSTRAINT `payment_method_change_requests_tenantId_fkey` FOREIGN KEY (`tenantId`) REFERENCES `tenants`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
111
|
+
|
|
112
|
+
-- AddForeignKey
|
|
113
|
+
ALTER TABLE `payment_method_change_requests` ADD CONSTRAINT `payment_method_change_requests_contractId_fkey` FOREIGN KEY (`contractId`) REFERENCES `contracts`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
114
|
+
|
|
115
|
+
-- AddForeignKey
|
|
116
|
+
ALTER TABLE `payment_method_change_requests` ADD CONSTRAINT `payment_method_change_requests_fromPaymentMethodId_fkey` FOREIGN KEY (`fromPaymentMethodId`) REFERENCES `property_payment_methods`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
117
|
+
|
|
118
|
+
-- AddForeignKey
|
|
119
|
+
ALTER TABLE `payment_method_change_requests` ADD CONSTRAINT `payment_method_change_requests_toPaymentMethodId_fkey` FOREIGN KEY (`toPaymentMethodId`) REFERENCES `property_payment_methods`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
120
|
+
|
|
121
|
+
-- AddForeignKey
|
|
122
|
+
ALTER TABLE `payment_method_change_requests` ADD CONSTRAINT `payment_method_change_requests_requestorId_fkey` FOREIGN KEY (`requestorId`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
123
|
+
|
|
124
|
+
-- AddForeignKey
|
|
125
|
+
ALTER TABLE `payment_method_change_requests` ADD CONSTRAINT `payment_method_change_requests_reviewerId_fkey` FOREIGN KEY (`reviewerId`) REFERENCES `users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
126
|
+
|
|
127
|
+
-- AddForeignKey
|
|
128
|
+
ALTER TABLE `document_requirement_rules` ADD CONSTRAINT `document_requirement_rules_tenantId_fkey` FOREIGN KEY (`tenantId`) REFERENCES `tenants`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
129
|
+
|
|
130
|
+
-- AddForeignKey
|
|
131
|
+
ALTER TABLE `document_requirement_rules` ADD CONSTRAINT `document_requirement_rules_paymentMethodId_fkey` FOREIGN KEY (`paymentMethodId`) REFERENCES `property_payment_methods`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
132
|
+
|
|
133
|
+
-- AddForeignKey
|
|
134
|
+
ALTER TABLE `document_requirement_rules` ADD CONSTRAINT `document_requirement_rules_fromPaymentMethodId_fkey` FOREIGN KEY (`fromPaymentMethodId`) REFERENCES `property_payment_methods`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
135
|
+
|
|
136
|
+
-- AddForeignKey
|
|
137
|
+
ALTER TABLE `document_requirement_rules` ADD CONSTRAINT `document_requirement_rules_toPaymentMethodId_fkey` FOREIGN KEY (`toPaymentMethodId`) REFERENCES `property_payment_methods`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
package/prisma/schema.prisma
CHANGED
|
@@ -59,6 +59,11 @@ model User {
|
|
|
59
59
|
stepApprovals ContractPhaseStepApproval[] @relation("PhaseStepApprover")
|
|
60
60
|
uploadedDocs ContractDocument[] @relation("DocumentUploader")
|
|
61
61
|
|
|
62
|
+
// Prequalification and payment method changes
|
|
63
|
+
prequalifications Prequalification[]
|
|
64
|
+
paymentMethodChangeRequests PaymentMethodChangeRequest[] @relation("ChangeRequestor")
|
|
65
|
+
reviewedChangeRequests PaymentMethodChangeRequest[] @relation("ChangeReviewer")
|
|
66
|
+
|
|
62
67
|
@@index([email])
|
|
63
68
|
@@index([tenantId])
|
|
64
69
|
@@map("users")
|
|
@@ -128,6 +133,11 @@ model Tenant {
|
|
|
128
133
|
paymentMethods PropertyPaymentMethod[]
|
|
129
134
|
contracts Contract[]
|
|
130
135
|
|
|
136
|
+
// Prequalification and payment method changes
|
|
137
|
+
prequalifications Prequalification[]
|
|
138
|
+
paymentMethodChangeRequests PaymentMethodChangeRequest[]
|
|
139
|
+
documentRequirementRules DocumentRequirementRule[]
|
|
140
|
+
|
|
131
141
|
@@index([subdomain])
|
|
132
142
|
@@map("tenants")
|
|
133
143
|
}
|
|
@@ -303,11 +313,12 @@ model Property {
|
|
|
303
313
|
updatedAt DateTime @updatedAt
|
|
304
314
|
|
|
305
315
|
// Relations
|
|
306
|
-
documents
|
|
307
|
-
media
|
|
308
|
-
amenities
|
|
309
|
-
paymentMethods
|
|
310
|
-
variants
|
|
316
|
+
documents PropertyDocument[]
|
|
317
|
+
media PropertyMedia[] @relation("PropertyMedia")
|
|
318
|
+
amenities PropertyAmenity[] // Shared amenities (gym, pool, security)
|
|
319
|
+
paymentMethods PropertyPaymentMethodLink[]
|
|
320
|
+
variants PropertyVariant[]
|
|
321
|
+
prequalifications Prequalification[]
|
|
311
322
|
|
|
312
323
|
@@index([tenantId])
|
|
313
324
|
@@index([userId])
|
|
@@ -552,6 +563,18 @@ model PropertyPaymentMethod {
|
|
|
552
563
|
// Contracts using this method
|
|
553
564
|
contracts Contract[]
|
|
554
565
|
|
|
566
|
+
// Prequalifications for this payment method
|
|
567
|
+
prequalifications Prequalification[]
|
|
568
|
+
|
|
569
|
+
// Payment method change tracking
|
|
570
|
+
changeRequestsFrom PaymentMethodChangeRequest[] @relation("ChangeFromMethod")
|
|
571
|
+
changeRequestsTo PaymentMethodChangeRequest[] @relation("ChangeToMethod")
|
|
572
|
+
|
|
573
|
+
// Document requirement rules
|
|
574
|
+
documentRules DocumentRequirementRule[] @relation("RulePaymentMethod")
|
|
575
|
+
changeRulesFrom DocumentRequirementRule[] @relation("RuleFromMethod")
|
|
576
|
+
changeRulesTo DocumentRequirementRule[] @relation("RuleToMethod")
|
|
577
|
+
|
|
555
578
|
@@unique([tenantId, name]) // Unique per tenant
|
|
556
579
|
@@index([tenantId])
|
|
557
580
|
@@map("property_payment_methods")
|
|
@@ -672,6 +695,11 @@ model Contract {
|
|
|
672
695
|
transitions ContractTransition[]
|
|
673
696
|
events ContractEvent[]
|
|
674
697
|
|
|
698
|
+
// Prequalification that led to this contract (optional)
|
|
699
|
+
prequalification Prequalification?
|
|
700
|
+
// Payment method change requests for this contract
|
|
701
|
+
paymentMethodChangeRequests PaymentMethodChangeRequest[]
|
|
702
|
+
|
|
675
703
|
@@index([tenantId])
|
|
676
704
|
@@index([propertyUnitId])
|
|
677
705
|
@@index([buyerId])
|
|
@@ -914,6 +942,198 @@ model ContractEvent {
|
|
|
914
942
|
@@map("contract_events")
|
|
915
943
|
}
|
|
916
944
|
|
|
945
|
+
// =============================================================================
|
|
946
|
+
// PREQUALIFICATION - Eligibility assessment before contract creation
|
|
947
|
+
// =============================================================================
|
|
948
|
+
// Prequalification is a separate aggregate that evaluates a user's eligibility
|
|
949
|
+
// for a specific product (property + payment method). It captures their answers
|
|
950
|
+
// to eligibility questions and calculates a score. Once approved, it can be
|
|
951
|
+
// linked to a Contract to provide context about how the buyer qualified.
|
|
952
|
+
// =============================================================================
|
|
953
|
+
|
|
954
|
+
enum PrequalificationStatus {
|
|
955
|
+
DRAFT
|
|
956
|
+
SUBMITTED
|
|
957
|
+
UNDER_REVIEW
|
|
958
|
+
APPROVED
|
|
959
|
+
REJECTED
|
|
960
|
+
EXPIRED
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
model Prequalification {
|
|
964
|
+
id String @id @default(cuid())
|
|
965
|
+
tenantId String
|
|
966
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
967
|
+
userId String
|
|
968
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
969
|
+
|
|
970
|
+
// What they're applying for
|
|
971
|
+
propertyId String
|
|
972
|
+
property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)
|
|
973
|
+
paymentMethodId String
|
|
974
|
+
paymentMethod PropertyPaymentMethod @relation(fields: [paymentMethodId], references: [id])
|
|
975
|
+
|
|
976
|
+
// Questionnaire responses and scoring
|
|
977
|
+
answers Json // Array of {questionId, answer, weight, score}
|
|
978
|
+
score Float? // Computed eligibility score (0-100)
|
|
979
|
+
|
|
980
|
+
// Financial assessment
|
|
981
|
+
requestedAmount Float? // How much they want to finance
|
|
982
|
+
monthlyIncome Float? // Self-reported monthly income
|
|
983
|
+
monthlyExpenses Float? // Self-reported monthly expenses
|
|
984
|
+
debtToIncomeRatio Float? // Computed DTI
|
|
985
|
+
suggestedTermMonths Int? // System-suggested term based on affordability
|
|
986
|
+
|
|
987
|
+
// Status tracking
|
|
988
|
+
status PrequalificationStatus @default(DRAFT)
|
|
989
|
+
notes String? @db.Text // Admin notes
|
|
990
|
+
reviewedBy String? // Admin who reviewed
|
|
991
|
+
reviewedAt DateTime?
|
|
992
|
+
expiresAt DateTime? // Prequalification validity period
|
|
993
|
+
|
|
994
|
+
// If approved, may be linked to eventual contract
|
|
995
|
+
contractId String? @unique
|
|
996
|
+
contract Contract? @relation(fields: [contractId], references: [id])
|
|
997
|
+
|
|
998
|
+
createdAt DateTime @default(now())
|
|
999
|
+
updatedAt DateTime @updatedAt
|
|
1000
|
+
|
|
1001
|
+
@@index([tenantId])
|
|
1002
|
+
@@index([userId])
|
|
1003
|
+
@@index([propertyId])
|
|
1004
|
+
@@index([status])
|
|
1005
|
+
@@map("prequalifications")
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
// =============================================================================
|
|
1009
|
+
// PAYMENT METHOD CHANGE REQUEST - Mid-contract payment method changes
|
|
1010
|
+
// =============================================================================
|
|
1011
|
+
// When a user wants to change their payment method after contract creation,
|
|
1012
|
+
// this aggregate tracks the request, required documentation, approvals, and
|
|
1013
|
+
// final execution. Different from-to combinations may require different docs.
|
|
1014
|
+
// =============================================================================
|
|
1015
|
+
|
|
1016
|
+
enum PaymentMethodChangeStatus {
|
|
1017
|
+
PENDING_DOCUMENTS
|
|
1018
|
+
DOCUMENTS_SUBMITTED
|
|
1019
|
+
UNDER_REVIEW
|
|
1020
|
+
APPROVED
|
|
1021
|
+
REJECTED
|
|
1022
|
+
EXECUTED
|
|
1023
|
+
CANCELLED
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
model PaymentMethodChangeRequest {
|
|
1027
|
+
id String @id @default(cuid())
|
|
1028
|
+
tenantId String
|
|
1029
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
1030
|
+
contractId String
|
|
1031
|
+
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
1032
|
+
|
|
1033
|
+
// The change being requested
|
|
1034
|
+
fromPaymentMethodId String
|
|
1035
|
+
fromPaymentMethod PropertyPaymentMethod @relation("ChangeFromMethod", fields: [fromPaymentMethodId], references: [id])
|
|
1036
|
+
toPaymentMethodId String
|
|
1037
|
+
toPaymentMethod PropertyPaymentMethod @relation("ChangeToMethod", fields: [toPaymentMethodId], references: [id])
|
|
1038
|
+
|
|
1039
|
+
// Who requested and why
|
|
1040
|
+
requestorId String
|
|
1041
|
+
requestor User @relation("ChangeRequestor", fields: [requestorId], references: [id])
|
|
1042
|
+
reason String? @db.Text
|
|
1043
|
+
|
|
1044
|
+
// Documentation requirements (determined by DocumentRequirementRule)
|
|
1045
|
+
requiredDocumentTypes String? // CSV: BANK_STATEMENT,INCOME_PROOF,NEW_EMPLOYER_LETTER
|
|
1046
|
+
submittedDocuments Json? // [{type, s3Key, uploadedAt, status}]
|
|
1047
|
+
|
|
1048
|
+
// Financial impact assessment
|
|
1049
|
+
currentOutstanding Float? // Outstanding balance at time of request
|
|
1050
|
+
newTermMonths Int? // New term if applicable
|
|
1051
|
+
newInterestRate Float? // New rate if applicable
|
|
1052
|
+
newMonthlyPayment Float? // Projected new payment
|
|
1053
|
+
penaltyAmount Float? // Early change penalty if applicable
|
|
1054
|
+
financialImpactNotes String? @db.Text
|
|
1055
|
+
|
|
1056
|
+
// Status and workflow
|
|
1057
|
+
status PaymentMethodChangeStatus @default(PENDING_DOCUMENTS)
|
|
1058
|
+
reviewerId String?
|
|
1059
|
+
reviewer User? @relation("ChangeReviewer", fields: [reviewerId], references: [id])
|
|
1060
|
+
reviewNotes String? @db.Text
|
|
1061
|
+
reviewedAt DateTime?
|
|
1062
|
+
|
|
1063
|
+
// Execution details
|
|
1064
|
+
executedAt DateTime?
|
|
1065
|
+
previousPhaseData Json? // Snapshot of phases before change
|
|
1066
|
+
newPhaseData Json? // New phases created after change
|
|
1067
|
+
|
|
1068
|
+
createdAt DateTime @default(now())
|
|
1069
|
+
updatedAt DateTime @updatedAt
|
|
1070
|
+
|
|
1071
|
+
@@index([tenantId])
|
|
1072
|
+
@@index([contractId])
|
|
1073
|
+
@@index([status])
|
|
1074
|
+
@@index([requestorId])
|
|
1075
|
+
@@map("payment_method_change_requests")
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
// =============================================================================
|
|
1079
|
+
// DOCUMENT REQUIREMENT RULES - Configurable document requirements
|
|
1080
|
+
// =============================================================================
|
|
1081
|
+
// Admins can configure which documents are required for specific scenarios:
|
|
1082
|
+
// - Prequalification for a payment method type
|
|
1083
|
+
// - Contract phases
|
|
1084
|
+
// - Payment method changes (from-to combinations)
|
|
1085
|
+
// This allows tenants to customize documentation workflows per product.
|
|
1086
|
+
// =============================================================================
|
|
1087
|
+
|
|
1088
|
+
enum DocumentRequirementContext {
|
|
1089
|
+
PREQUALIFICATION // During prequalification
|
|
1090
|
+
CONTRACT_PHASE // During a contract phase
|
|
1091
|
+
PAYMENT_METHOD_CHANGE // When changing payment method mid-contract
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
model DocumentRequirementRule {
|
|
1095
|
+
id String @id @default(cuid())
|
|
1096
|
+
tenantId String
|
|
1097
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
1098
|
+
|
|
1099
|
+
// Rule context
|
|
1100
|
+
context DocumentRequirementContext
|
|
1101
|
+
|
|
1102
|
+
// Scoping (which situations this rule applies to)
|
|
1103
|
+
// For PREQUALIFICATION: paymentMethodId
|
|
1104
|
+
// For CONTRACT_PHASE: phaseType
|
|
1105
|
+
// For PAYMENT_METHOD_CHANGE: fromMethodId + toMethodId
|
|
1106
|
+
paymentMethodId String?
|
|
1107
|
+
paymentMethod PropertyPaymentMethod? @relation("RulePaymentMethod", fields: [paymentMethodId], references: [id])
|
|
1108
|
+
phaseType String? // KYC, VERIFICATION, DOWNPAYMENT, etc.
|
|
1109
|
+
fromPaymentMethodId String?
|
|
1110
|
+
fromPaymentMethod PropertyPaymentMethod? @relation("RuleFromMethod", fields: [fromPaymentMethodId], references: [id])
|
|
1111
|
+
toPaymentMethodId String?
|
|
1112
|
+
toPaymentMethod PropertyPaymentMethod? @relation("RuleToMethod", fields: [toPaymentMethodId], references: [id])
|
|
1113
|
+
|
|
1114
|
+
// Document requirements
|
|
1115
|
+
documentType String // ID_CARD, PASSPORT, BANK_STATEMENT, INCOME_PROOF, etc.
|
|
1116
|
+
isRequired Boolean @default(true)
|
|
1117
|
+
description String? // Instructions for the user
|
|
1118
|
+
maxSizeBytes Int? // Max file size allowed
|
|
1119
|
+
allowedMimeTypes String? // CSV: application/pdf,image/jpeg,image/png
|
|
1120
|
+
|
|
1121
|
+
// Validation rules
|
|
1122
|
+
expiryDays Int? // Document must not be older than X days
|
|
1123
|
+
requiresManualReview Boolean @default(false)
|
|
1124
|
+
|
|
1125
|
+
isActive Boolean @default(true)
|
|
1126
|
+
createdAt DateTime @default(now())
|
|
1127
|
+
updatedAt DateTime @updatedAt
|
|
1128
|
+
|
|
1129
|
+
@@index([tenantId])
|
|
1130
|
+
@@index([context])
|
|
1131
|
+
@@index([paymentMethodId])
|
|
1132
|
+
@@index([phaseType])
|
|
1133
|
+
@@index([fromPaymentMethodId, toPaymentMethodId])
|
|
1134
|
+
@@map("document_requirement_rules")
|
|
1135
|
+
}
|
|
1136
|
+
|
|
917
1137
|
// =============================================================================
|
|
918
1138
|
// EVENT OUTBOX - For guaranteed event delivery to SQS queues
|
|
919
1139
|
// =============================================================================
|