@valentine-efagene/qshelter-common 2.0.151 → 2.0.152
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 +13 -2
- package/dist/generated/client/client.d.ts +15 -4
- package/dist/generated/client/client.js +2 -2
- package/dist/generated/client/commonInputTypes.d.ts +20 -190
- package/dist/generated/client/enums.d.ts +0 -34
- package/dist/generated/client/enums.js +0 -30
- package/dist/generated/client/internal/class.d.ts +29 -7
- package/dist/generated/client/internal/class.js +2 -2
- package/dist/generated/client/internal/prismaNamespace.d.ts +181 -32
- package/dist/generated/client/internal/prismaNamespace.js +42 -11
- package/dist/generated/client/internal/prismaNamespaceBrowser.d.ts +46 -11
- package/dist/generated/client/internal/prismaNamespaceBrowser.js +42 -11
- package/dist/generated/client/models/ApplicationOrganization.d.ts +308 -67
- package/dist/generated/client/models/ApprovalStage.d.ts +210 -91
- package/dist/generated/client/models/ApprovalStageProgress.d.ts +258 -69
- package/dist/generated/client/models/DocumentApproval.d.ts +196 -65
- package/dist/generated/client/models/DocumentReview.d.ts +475 -86
- package/dist/generated/client/models/Organization.d.ts +424 -52
- package/dist/generated/client/models/OrganizationMember.d.ts +42 -169
- package/dist/generated/client/models/OrganizationType.d.ts +1982 -0
- package/dist/generated/client/models/OrganizationType.js +1 -0
- package/dist/generated/client/models/OrganizationTypeAssignment.d.ts +1159 -0
- package/dist/generated/client/models/OrganizationTypeAssignment.js +1 -0
- package/dist/generated/client/models/Tenant.d.ts +575 -4
- package/dist/generated/client/models/User.d.ts +0 -12
- package/dist/generated/client/models/index.d.ts +2 -0
- package/dist/generated/client/models/index.js +2 -0
- package/dist/generated/client/models.d.ts +2 -0
- package/package.json +1 -1
- package/prisma/migrations/20260125102448_org_types_many_to_many/migration.sql +153 -0
- package/prisma/migrations/20260125103700_20260125102448_org_types_many_to_many_fix/migration.sql +5 -0
- package/prisma/schema.prisma +113 -79
|
@@ -760,18 +760,6 @@ export type UserNullableScalarRelationFilter = {
|
|
|
760
760
|
is?: Prisma.UserWhereInput | null;
|
|
761
761
|
isNot?: Prisma.UserWhereInput | null;
|
|
762
762
|
};
|
|
763
|
-
export type StringFieldUpdateOperationsInput = {
|
|
764
|
-
set?: string;
|
|
765
|
-
};
|
|
766
|
-
export type NullableStringFieldUpdateOperationsInput = {
|
|
767
|
-
set?: string | null;
|
|
768
|
-
};
|
|
769
|
-
export type BoolFieldUpdateOperationsInput = {
|
|
770
|
-
set?: boolean;
|
|
771
|
-
};
|
|
772
|
-
export type DateTimeFieldUpdateOperationsInput = {
|
|
773
|
-
set?: Date | string;
|
|
774
|
-
};
|
|
775
763
|
export type NullableDateTimeFieldUpdateOperationsInput = {
|
|
776
764
|
set?: Date | string | null;
|
|
777
765
|
};
|
|
@@ -30,6 +30,8 @@ export * from './OAuthState';
|
|
|
30
30
|
export * from './OfferLetter';
|
|
31
31
|
export * from './Organization';
|
|
32
32
|
export * from './OrganizationMember';
|
|
33
|
+
export * from './OrganizationType';
|
|
34
|
+
export * from './OrganizationTypeAssignment';
|
|
33
35
|
export * from './PasswordReset';
|
|
34
36
|
export * from './PaymentInstallment';
|
|
35
37
|
export * from './PaymentMethodChangeRequest';
|
|
@@ -30,6 +30,8 @@ export * from './OAuthState';
|
|
|
30
30
|
export * from './OfferLetter';
|
|
31
31
|
export * from './Organization';
|
|
32
32
|
export * from './OrganizationMember';
|
|
33
|
+
export * from './OrganizationType';
|
|
34
|
+
export * from './OrganizationTypeAssignment';
|
|
33
35
|
export * from './PasswordReset';
|
|
34
36
|
export * from './PaymentInstallment';
|
|
35
37
|
export * from './PaymentMethodChangeRequest';
|
package/package.json
CHANGED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Warnings:
|
|
3
|
+
|
|
4
|
+
- You are about to drop the column `role` on the `application_organizations` table. All the data in the column will be lost.
|
|
5
|
+
- You are about to drop the column `reviewParty` on the `approval_stage_progress` table. All the data in the column will be lost.
|
|
6
|
+
- You are about to drop the column `organizationId` on the `approval_stages` table. All the data in the column will be lost.
|
|
7
|
+
- You are about to drop the column `reviewParty` on the `approval_stages` table. All the data in the column will be lost.
|
|
8
|
+
- You are about to drop the column `reviewParty` on the `document_approvals` table. All the data in the column will be lost.
|
|
9
|
+
- You are about to drop the column `reviewParty` on the `document_reviews` table. All the data in the column will be lost.
|
|
10
|
+
- You are about to drop the column `approvalLimit` on the `organization_members` table. All the data in the column will be lost.
|
|
11
|
+
- You are about to drop the column `canApprove` on the `organization_members` table. All the data in the column will be lost.
|
|
12
|
+
- You are about to drop the column `role` on the `organization_members` table. All the data in the column will be lost.
|
|
13
|
+
- You are about to drop the column `type` on the `organizations` table. All the data in the column will be lost.
|
|
14
|
+
- A unique constraint covering the columns `[applicationId,assignedAsTypeId]` on the table `application_organizations` will be added. If there are existing duplicate values, this will fail.
|
|
15
|
+
- A unique constraint covering the columns `[documentId,organizationId]` on the table `document_reviews` will be added. If there are existing duplicate values, this will fail.
|
|
16
|
+
- Added the required column `assignedAsTypeId` to the `application_organizations` table without a default value. This is not possible if the table is not empty.
|
|
17
|
+
- Added the required column `organizationTypeId` to the `approval_stage_progress` table without a default value. This is not possible if the table is not empty.
|
|
18
|
+
- Added the required column `organizationTypeId` to the `approval_stages` table without a default value. This is not possible if the table is not empty.
|
|
19
|
+
- Added the required column `organizationTypeId` to the `document_approvals` table without a default value. This is not possible if the table is not empty.
|
|
20
|
+
|
|
21
|
+
*/
|
|
22
|
+
-- DropForeignKey
|
|
23
|
+
ALTER TABLE `application_organizations` DROP FOREIGN KEY `application_organizations_applicationId_fkey`;
|
|
24
|
+
|
|
25
|
+
-- DropForeignKey
|
|
26
|
+
ALTER TABLE `document_reviews` DROP FOREIGN KEY `document_reviews_documentId_fkey`;
|
|
27
|
+
|
|
28
|
+
-- DropIndex
|
|
29
|
+
DROP INDEX `application_organizations_applicationId_organizationId_role_key` ON `application_organizations`;
|
|
30
|
+
|
|
31
|
+
-- DropIndex
|
|
32
|
+
DROP INDEX `application_organizations_role_idx` ON `application_organizations`;
|
|
33
|
+
|
|
34
|
+
-- DropIndex
|
|
35
|
+
DROP INDEX `document_reviews_documentId_reviewParty_organizationId_key` ON `document_reviews`;
|
|
36
|
+
|
|
37
|
+
-- DropIndex
|
|
38
|
+
DROP INDEX `document_reviews_reviewParty_idx` ON `document_reviews`;
|
|
39
|
+
|
|
40
|
+
-- DropIndex
|
|
41
|
+
DROP INDEX `organization_members_role_idx` ON `organization_members`;
|
|
42
|
+
|
|
43
|
+
-- DropIndex
|
|
44
|
+
DROP INDEX `organizations_type_idx` ON `organizations`;
|
|
45
|
+
|
|
46
|
+
-- AlterTable
|
|
47
|
+
ALTER TABLE `application_organizations` DROP COLUMN `role`,
|
|
48
|
+
ADD COLUMN `assignedAsTypeId` VARCHAR(191) NOT NULL;
|
|
49
|
+
|
|
50
|
+
-- AlterTable
|
|
51
|
+
ALTER TABLE `approval_stage_progress` DROP COLUMN `reviewParty`,
|
|
52
|
+
ADD COLUMN `organizationTypeId` VARCHAR(191) NOT NULL;
|
|
53
|
+
|
|
54
|
+
-- AlterTable
|
|
55
|
+
ALTER TABLE `approval_stages` DROP COLUMN `organizationId`,
|
|
56
|
+
DROP COLUMN `reviewParty`,
|
|
57
|
+
ADD COLUMN `organizationTypeId` VARCHAR(191) NOT NULL;
|
|
58
|
+
|
|
59
|
+
-- AlterTable
|
|
60
|
+
ALTER TABLE `document_approvals` DROP COLUMN `reviewParty`,
|
|
61
|
+
ADD COLUMN `organizationTypeId` VARCHAR(191) NOT NULL;
|
|
62
|
+
|
|
63
|
+
-- AlterTable
|
|
64
|
+
ALTER TABLE `document_reviews` DROP COLUMN `reviewParty`,
|
|
65
|
+
ADD COLUMN `organizationTypeId` VARCHAR(191) NULL;
|
|
66
|
+
|
|
67
|
+
-- AlterTable
|
|
68
|
+
ALTER TABLE `organization_members` DROP COLUMN `approvalLimit`,
|
|
69
|
+
DROP COLUMN `canApprove`,
|
|
70
|
+
DROP COLUMN `role`,
|
|
71
|
+
ADD COLUMN `joinedAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3);
|
|
72
|
+
|
|
73
|
+
-- AlterTable
|
|
74
|
+
ALTER TABLE `organizations` DROP COLUMN `type`;
|
|
75
|
+
|
|
76
|
+
-- CreateTable
|
|
77
|
+
CREATE TABLE `organization_types` (
|
|
78
|
+
`id` VARCHAR(191) NOT NULL,
|
|
79
|
+
`tenantId` VARCHAR(191) NOT NULL,
|
|
80
|
+
`code` VARCHAR(191) NOT NULL,
|
|
81
|
+
`name` VARCHAR(191) NOT NULL,
|
|
82
|
+
`description` TEXT NULL,
|
|
83
|
+
`isSystemType` BOOLEAN NOT NULL DEFAULT false,
|
|
84
|
+
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
85
|
+
`updatedAt` DATETIME(3) NOT NULL,
|
|
86
|
+
|
|
87
|
+
INDEX `organization_types_tenantId_idx`(`tenantId`),
|
|
88
|
+
INDEX `organization_types_code_idx`(`code`),
|
|
89
|
+
UNIQUE INDEX `organization_types_tenantId_code_key`(`tenantId`, `code`),
|
|
90
|
+
PRIMARY KEY (`id`)
|
|
91
|
+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
92
|
+
|
|
93
|
+
-- CreateTable
|
|
94
|
+
CREATE TABLE `organization_type_assignments` (
|
|
95
|
+
`id` VARCHAR(191) NOT NULL,
|
|
96
|
+
`organizationId` VARCHAR(191) NOT NULL,
|
|
97
|
+
`typeId` VARCHAR(191) NOT NULL,
|
|
98
|
+
`isPrimary` BOOLEAN NOT NULL DEFAULT false,
|
|
99
|
+
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
100
|
+
|
|
101
|
+
INDEX `organization_type_assignments_organizationId_idx`(`organizationId`),
|
|
102
|
+
INDEX `organization_type_assignments_typeId_idx`(`typeId`),
|
|
103
|
+
UNIQUE INDEX `organization_type_assignments_organizationId_typeId_key`(`organizationId`, `typeId`),
|
|
104
|
+
PRIMARY KEY (`id`)
|
|
105
|
+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
106
|
+
|
|
107
|
+
-- CreateIndex
|
|
108
|
+
CREATE INDEX `application_organizations_assignedAsTypeId_idx` ON `application_organizations`(`assignedAsTypeId`);
|
|
109
|
+
|
|
110
|
+
-- CreateIndex
|
|
111
|
+
CREATE UNIQUE INDEX `application_organizations_applicationId_assignedAsTypeId_key` ON `application_organizations`(`applicationId`, `assignedAsTypeId`);
|
|
112
|
+
|
|
113
|
+
-- CreateIndex
|
|
114
|
+
CREATE INDEX `approval_stages_organizationTypeId_idx` ON `approval_stages`(`organizationTypeId`);
|
|
115
|
+
|
|
116
|
+
-- CreateIndex
|
|
117
|
+
CREATE INDEX `document_approvals_organizationTypeId_idx` ON `document_approvals`(`organizationTypeId`);
|
|
118
|
+
|
|
119
|
+
-- CreateIndex
|
|
120
|
+
CREATE INDEX `document_reviews_organizationId_idx` ON `document_reviews`(`organizationId`);
|
|
121
|
+
|
|
122
|
+
-- CreateIndex
|
|
123
|
+
CREATE INDEX `document_reviews_organizationTypeId_idx` ON `document_reviews`(`organizationTypeId`);
|
|
124
|
+
|
|
125
|
+
-- CreateIndex
|
|
126
|
+
CREATE UNIQUE INDEX `document_reviews_documentId_organizationId_key` ON `document_reviews`(`documentId`, `organizationId`);
|
|
127
|
+
|
|
128
|
+
-- AddForeignKey
|
|
129
|
+
ALTER TABLE `organization_types` ADD CONSTRAINT `organization_types_tenantId_fkey` FOREIGN KEY (`tenantId`) REFERENCES `tenants`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
130
|
+
|
|
131
|
+
-- AddForeignKey
|
|
132
|
+
ALTER TABLE `organization_type_assignments` ADD CONSTRAINT `organization_type_assignments_organizationId_fkey` FOREIGN KEY (`organizationId`) REFERENCES `organizations`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
133
|
+
|
|
134
|
+
-- AddForeignKey
|
|
135
|
+
ALTER TABLE `organization_type_assignments` ADD CONSTRAINT `organization_type_assignments_typeId_fkey` FOREIGN KEY (`typeId`) REFERENCES `organization_types`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
136
|
+
|
|
137
|
+
-- AddForeignKey
|
|
138
|
+
ALTER TABLE `approval_stages` ADD CONSTRAINT `approval_stages_organizationTypeId_fkey` FOREIGN KEY (`organizationTypeId`) REFERENCES `organization_types`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
139
|
+
|
|
140
|
+
-- AddForeignKey
|
|
141
|
+
ALTER TABLE `application_organizations` ADD CONSTRAINT `application_organizations_assignedAsTypeId_fkey` FOREIGN KEY (`assignedAsTypeId`) REFERENCES `organization_types`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
142
|
+
|
|
143
|
+
-- AddForeignKey
|
|
144
|
+
ALTER TABLE `document_reviews` ADD CONSTRAINT `document_reviews_organizationId_fkey` FOREIGN KEY (`organizationId`) REFERENCES `organizations`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
145
|
+
|
|
146
|
+
-- AddForeignKey
|
|
147
|
+
ALTER TABLE `document_reviews` ADD CONSTRAINT `document_reviews_organizationTypeId_fkey` FOREIGN KEY (`organizationTypeId`) REFERENCES `organization_types`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
148
|
+
|
|
149
|
+
-- AddForeignKey
|
|
150
|
+
ALTER TABLE `approval_stage_progress` ADD CONSTRAINT `approval_stage_progress_organizationTypeId_fkey` FOREIGN KEY (`organizationTypeId`) REFERENCES `organization_types`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
151
|
+
|
|
152
|
+
-- AddForeignKey
|
|
153
|
+
ALTER TABLE `document_approvals` ADD CONSTRAINT `document_approvals_organizationTypeId_fkey` FOREIGN KEY (`organizationTypeId`) REFERENCES `organization_types`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
package/prisma/migrations/20260125103700_20260125102448_org_types_many_to_many_fix/migration.sql
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
-- AddForeignKey
|
|
2
|
+
ALTER TABLE `application_organizations` ADD CONSTRAINT `application_organizations_applicationId_fkey` FOREIGN KEY (`applicationId`) REFERENCES `applications`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
3
|
+
|
|
4
|
+
-- AddForeignKey
|
|
5
|
+
ALTER TABLE `document_reviews` ADD CONSTRAINT `document_reviews_documentId_fkey` FOREIGN KEY (`documentId`) REFERENCES `application_documents`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
package/prisma/schema.prisma
CHANGED
|
@@ -203,17 +203,69 @@ enum ApprovalDecision {
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
// =============================================================================
|
|
206
|
-
// ORGANIZATION
|
|
206
|
+
// ORGANIZATION TYPE - Lookup table for organization types (replaces enum)
|
|
207
207
|
// =============================================================================
|
|
208
|
+
// Organizations can have multiple types via OrganizationTypeAssignment.
|
|
209
|
+
// Example: QShelter can be both PLATFORM and DEVELOPER.
|
|
210
|
+
// System types are seeded during tenant bootstrap and cannot be deleted.
|
|
211
|
+
// =============================================================================
|
|
212
|
+
|
|
213
|
+
model OrganizationType {
|
|
214
|
+
id String @id @default(cuid())
|
|
215
|
+
tenantId String
|
|
216
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
217
|
+
code String // "PLATFORM", "BANK", "DEVELOPER", "LEGAL", "INSURER", "GOVERNMENT"
|
|
218
|
+
name String // Human-readable: "Platform Operator", "Bank/Lender", etc.
|
|
219
|
+
description String? @db.Text
|
|
220
|
+
|
|
221
|
+
// System types are seeded during bootstrap and cannot be deleted
|
|
222
|
+
isSystemType Boolean @default(false)
|
|
223
|
+
|
|
224
|
+
createdAt DateTime @default(now())
|
|
225
|
+
updatedAt DateTime @updatedAt
|
|
226
|
+
|
|
227
|
+
// Organizations with this type
|
|
228
|
+
organizations OrganizationTypeAssignment[]
|
|
229
|
+
|
|
230
|
+
// Applications assigned to orgs acting as this type
|
|
231
|
+
applicationOrganizations ApplicationOrganization[]
|
|
232
|
+
|
|
233
|
+
// Approval stages that require this type of organization
|
|
234
|
+
approvalStages ApprovalStage[]
|
|
235
|
+
|
|
236
|
+
// Document reviews performed by orgs acting as this type (audit snapshot)
|
|
237
|
+
documentReviews DocumentReview[]
|
|
238
|
+
|
|
239
|
+
// Approval stage progress instances
|
|
240
|
+
approvalStageProgress ApprovalStageProgress[]
|
|
241
|
+
|
|
242
|
+
// Document approvals
|
|
243
|
+
documentApprovals DocumentApproval[]
|
|
244
|
+
|
|
245
|
+
@@unique([tenantId, code])
|
|
246
|
+
@@index([tenantId])
|
|
247
|
+
@@index([code])
|
|
248
|
+
@@map("organization_types")
|
|
249
|
+
}
|
|
208
250
|
|
|
209
|
-
///
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
251
|
+
/// Links organizations to their types (many-to-many)
|
|
252
|
+
/// An organization can have multiple types (e.g., QShelter is PLATFORM + DEVELOPER)
|
|
253
|
+
model OrganizationTypeAssignment {
|
|
254
|
+
id String @id @default(cuid())
|
|
255
|
+
organizationId String
|
|
256
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
257
|
+
typeId String
|
|
258
|
+
orgType OrganizationType @relation(fields: [typeId], references: [id], onDelete: Cascade)
|
|
259
|
+
|
|
260
|
+
// Which type is the primary one for display purposes
|
|
261
|
+
isPrimary Boolean @default(false)
|
|
262
|
+
|
|
263
|
+
createdAt DateTime @default(now())
|
|
264
|
+
|
|
265
|
+
@@unique([organizationId, typeId])
|
|
266
|
+
@@index([organizationId])
|
|
267
|
+
@@index([typeId])
|
|
268
|
+
@@map("organization_type_assignments")
|
|
217
269
|
}
|
|
218
270
|
|
|
219
271
|
/// Status of an organization
|
|
@@ -224,14 +276,6 @@ enum OrganizationStatus {
|
|
|
224
276
|
INACTIVE // No longer active
|
|
225
277
|
}
|
|
226
278
|
|
|
227
|
-
/// Role of a member within an organization
|
|
228
|
-
enum OrganizationRole {
|
|
229
|
-
ADMIN // Can manage org settings, members, and full operations
|
|
230
|
-
MANAGER // Can approve transactions within limits (checker)
|
|
231
|
-
OFFICER // Regular employee, can initiate actions (maker)
|
|
232
|
-
VIEWER // Read-only access to organization data
|
|
233
|
-
}
|
|
234
|
-
|
|
235
279
|
// =============================================================================
|
|
236
280
|
// CONTRACT TERMINATION / CANCELLATION ENUMS
|
|
237
281
|
// =============================================================================
|
|
@@ -274,21 +318,9 @@ enum CompletionCriterion {
|
|
|
274
318
|
}
|
|
275
319
|
|
|
276
320
|
// =============================================================================
|
|
277
|
-
//
|
|
278
|
-
// =============================================================================
|
|
279
|
-
// Enables different organizations to review the same document independently
|
|
321
|
+
// DOCUMENT REVIEW ENUMS
|
|
280
322
|
// =============================================================================
|
|
281
323
|
|
|
282
|
-
enum ReviewParty {
|
|
283
|
-
INTERNAL // Your internal team (compliance, underwriting, etc.)
|
|
284
|
-
BANK // Partner bank/lender
|
|
285
|
-
DEVELOPER // Property developer
|
|
286
|
-
LEGAL // Legal team
|
|
287
|
-
GOVERNMENT // Government agencies (e.g., land registry)
|
|
288
|
-
INSURER // Insurance company
|
|
289
|
-
CUSTOMER // Customer acknowledgment/signature
|
|
290
|
-
}
|
|
291
|
-
|
|
292
324
|
enum ReviewDecision {
|
|
293
325
|
PENDING // Review not yet performed
|
|
294
326
|
APPROVED // Document approved by this party
|
|
@@ -623,9 +655,12 @@ model Organization {
|
|
|
623
655
|
id String @id @default(cuid())
|
|
624
656
|
tenantId String
|
|
625
657
|
name String // e.g., "Access Bank PLC", "Lekki Gardens Ltd"
|
|
626
|
-
type OrganizationType // PLATFORM, BANK, DEVELOPER, LEGAL, INSURER, GOVERNMENT
|
|
627
658
|
status OrganizationStatus @default(PENDING)
|
|
628
659
|
|
|
660
|
+
// Organization types (many-to-many via OrganizationTypeAssignment)
|
|
661
|
+
// An org can have multiple types (e.g., QShelter is PLATFORM + DEVELOPER)
|
|
662
|
+
types OrganizationTypeAssignment[]
|
|
663
|
+
|
|
629
664
|
// Platform organization flag - marks the tenant's own organization
|
|
630
665
|
isPlatformOrg Boolean @default(false)
|
|
631
666
|
|
|
@@ -667,41 +702,39 @@ model Organization {
|
|
|
667
702
|
// Bank-specific document requirements (for BANK type organizations)
|
|
668
703
|
documentRequirements BankDocumentRequirement[]
|
|
669
704
|
|
|
705
|
+
// Document reviews performed by this organization
|
|
706
|
+
documentReviews DocumentReview[]
|
|
707
|
+
|
|
670
708
|
// Properties developed by this organization (for DEVELOPERs)
|
|
671
709
|
// developedProperties Property[] @relation("PropertyDeveloper")
|
|
672
710
|
|
|
673
711
|
@@unique([tenantId, bankCode]) // Bank codes unique within tenant
|
|
674
712
|
@@unique([tenantId, cacNumber]) // CAC numbers unique within tenant
|
|
675
713
|
@@index([tenantId])
|
|
676
|
-
@@index([type])
|
|
677
714
|
@@index([status])
|
|
678
715
|
@@map("organizations")
|
|
679
716
|
}
|
|
680
717
|
|
|
681
|
-
/// OrganizationMember: Links users to organizations
|
|
682
|
-
///
|
|
718
|
+
/// OrganizationMember: Links users to organizations
|
|
719
|
+
/// User's own roles (via UserRole) determine their abilities within the org
|
|
683
720
|
model OrganizationMember {
|
|
684
|
-
id String
|
|
721
|
+
id String @id @default(cuid())
|
|
685
722
|
organizationId String
|
|
686
723
|
userId String
|
|
687
|
-
role OrganizationRole @default(OFFICER)
|
|
688
724
|
|
|
689
725
|
// Employee details
|
|
690
|
-
title String? // Job title (e.g., "Loan Officer", "
|
|
726
|
+
title String? // Job title (e.g., "Loan Officer", "Mortgage Operations Officer")
|
|
691
727
|
department String? // Department within organization
|
|
692
728
|
employeeId String? // Internal employee ID
|
|
693
729
|
|
|
694
730
|
// Status
|
|
695
731
|
isActive Boolean @default(true)
|
|
696
732
|
|
|
697
|
-
// Maker-Checker workflow permissions
|
|
698
|
-
canApprove Boolean @default(false) // Can this member approve transactions?
|
|
699
|
-
approvalLimit Decimal? // Maximum amount this member can approve (null = unlimited)
|
|
700
|
-
|
|
701
733
|
// Invitation/onboarding tracking
|
|
702
734
|
invitedAt DateTime?
|
|
703
735
|
acceptedAt DateTime?
|
|
704
736
|
invitedBy String? // User ID who invited this member
|
|
737
|
+
joinedAt DateTime @default(now())
|
|
705
738
|
|
|
706
739
|
createdAt DateTime @default(now())
|
|
707
740
|
updatedAt DateTime @updatedAt
|
|
@@ -712,7 +745,6 @@ model OrganizationMember {
|
|
|
712
745
|
@@unique([organizationId, userId]) // User can only be member once per org
|
|
713
746
|
@@index([userId])
|
|
714
747
|
@@index([organizationId])
|
|
715
|
-
@@index([role])
|
|
716
748
|
@@map("organization_members")
|
|
717
749
|
}
|
|
718
750
|
|
|
@@ -886,6 +918,7 @@ model Tenant {
|
|
|
886
918
|
|
|
887
919
|
// Application organization assignments
|
|
888
920
|
applicationOrganizations ApplicationOrganization[]
|
|
921
|
+
organizationTypes OrganizationType[]
|
|
889
922
|
|
|
890
923
|
@@index([subdomain])
|
|
891
924
|
@@map("tenants")
|
|
@@ -1425,7 +1458,7 @@ model DocumentDefinition {
|
|
|
1425
1458
|
// APPROVAL STAGE - Sequential workflow stages for document review (template)
|
|
1426
1459
|
// =============================================================================
|
|
1427
1460
|
// Defines a stage in the approval workflow. Documents flow through stages
|
|
1428
|
-
// sequentially. Each stage
|
|
1461
|
+
// sequentially. Each stage requires a specific organization type to review.
|
|
1429
1462
|
// =============================================================================
|
|
1430
1463
|
|
|
1431
1464
|
model ApprovalStage {
|
|
@@ -1433,9 +1466,10 @@ model ApprovalStage {
|
|
|
1433
1466
|
planId String
|
|
1434
1467
|
plan DocumentationPlan @relation(fields: [planId], references: [id], onDelete: Cascade)
|
|
1435
1468
|
|
|
1436
|
-
name
|
|
1437
|
-
order
|
|
1438
|
-
|
|
1469
|
+
name String // "QShelter Review", "Bank Review"
|
|
1470
|
+
order Int // 1, 2, 3 - sequential order
|
|
1471
|
+
organizationTypeId String // Which type of org should review at this stage
|
|
1472
|
+
organizationType OrganizationType @relation(fields: [organizationTypeId], references: [id])
|
|
1439
1473
|
|
|
1440
1474
|
// Stage behavior flags
|
|
1441
1475
|
autoTransition Boolean @default(false) // Auto-complete when all docs approved? Default: require explicit approval
|
|
@@ -1446,9 +1480,6 @@ model ApprovalStage {
|
|
|
1446
1480
|
onRejection RejectionBehavior @default(CASCADE_BACK)
|
|
1447
1481
|
restartFromStageOrder Int? // If onRejection = RESTART_FROM_STAGE, which stage order to restart from
|
|
1448
1482
|
|
|
1449
|
-
// Optional: specific organization (e.g., which bank)
|
|
1450
|
-
organizationId String?
|
|
1451
|
-
|
|
1452
1483
|
// SLA (optional)
|
|
1453
1484
|
slaHours Int? // Escalate if not completed within X hours
|
|
1454
1485
|
|
|
@@ -1462,6 +1493,7 @@ model ApprovalStage {
|
|
|
1462
1493
|
|
|
1463
1494
|
@@unique([planId, order])
|
|
1464
1495
|
@@index([planId])
|
|
1496
|
+
@@index([organizationTypeId])
|
|
1465
1497
|
@@map("approval_stages")
|
|
1466
1498
|
}
|
|
1467
1499
|
|
|
@@ -2079,18 +2111,9 @@ model Application {
|
|
|
2079
2111
|
// in a specific application. This enables:
|
|
2080
2112
|
// 1. Validation that only assigned developers can upload sales offers
|
|
2081
2113
|
// 2. Only assigned banks can upload preapproval/mortgage offer letters
|
|
2082
|
-
// 3.
|
|
2114
|
+
// 3. Flexible type-based assignment (org assigned acting as specific type)
|
|
2083
2115
|
// =============================================================================
|
|
2084
2116
|
|
|
2085
|
-
/// Role that an organization plays in an application
|
|
2086
|
-
enum ApplicationOrganizationRole {
|
|
2087
|
-
DEVELOPER // Property developer - uploads sales offer letters
|
|
2088
|
-
LENDER // Bank/financial institution - provides mortgage
|
|
2089
|
-
LEGAL // Legal firm - handles conveyancing
|
|
2090
|
-
INSURER // Insurance company
|
|
2091
|
-
GOVERNMENT // Government agency (land registry, etc.)
|
|
2092
|
-
}
|
|
2093
|
-
|
|
2094
2117
|
/// Status of organization's involvement in the application
|
|
2095
2118
|
enum ApplicationOrganizationStatus {
|
|
2096
2119
|
PENDING // Awaiting organization's response/engagement
|
|
@@ -2111,8 +2134,11 @@ model ApplicationOrganization {
|
|
|
2111
2134
|
organizationId String
|
|
2112
2135
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
2113
2136
|
|
|
2114
|
-
//
|
|
2115
|
-
|
|
2137
|
+
// Which type the org is acting as on this application
|
|
2138
|
+
// (org must have this type in their OrganizationTypeAssignment)
|
|
2139
|
+
assignedAsTypeId String
|
|
2140
|
+
assignedAsType OrganizationType @relation(fields: [assignedAsTypeId], references: [id])
|
|
2141
|
+
|
|
2116
2142
|
status ApplicationOrganizationStatus @default(PENDING)
|
|
2117
2143
|
|
|
2118
2144
|
// Who assigned this organization (admin or system)
|
|
@@ -2159,11 +2185,11 @@ model ApplicationOrganization {
|
|
|
2159
2185
|
createdAt DateTime @default(now())
|
|
2160
2186
|
updatedAt DateTime @updatedAt
|
|
2161
2187
|
|
|
2162
|
-
@@unique([applicationId,
|
|
2188
|
+
@@unique([applicationId, assignedAsTypeId]) // One org per type per application
|
|
2163
2189
|
@@index([tenantId])
|
|
2164
2190
|
@@index([applicationId])
|
|
2165
2191
|
@@index([organizationId])
|
|
2166
|
-
@@index([
|
|
2192
|
+
@@index([assignedAsTypeId])
|
|
2167
2193
|
@@index([status])
|
|
2168
2194
|
@@index([isPrimary])
|
|
2169
2195
|
@@index([slaBreachedAt])
|
|
@@ -2729,8 +2755,9 @@ model ApplicationDocument {
|
|
|
2729
2755
|
// =============================================================================
|
|
2730
2756
|
// DOCUMENT REVIEW - Multi-party review tracking
|
|
2731
2757
|
// =============================================================================
|
|
2732
|
-
// Tracks reviews by different organizations for the same document
|
|
2733
|
-
//
|
|
2758
|
+
// Tracks reviews by different organizations for the same document.
|
|
2759
|
+
// organizationId is NULL for customer self-attestations/signatures.
|
|
2760
|
+
// For org reviews, organizationTypeId captures which type the org was acting as.
|
|
2734
2761
|
// =============================================================================
|
|
2735
2762
|
|
|
2736
2763
|
model DocumentReview {
|
|
@@ -2740,12 +2767,14 @@ model DocumentReview {
|
|
|
2740
2767
|
documentId String
|
|
2741
2768
|
document ApplicationDocument @relation(fields: [documentId], references: [id], onDelete: Cascade)
|
|
2742
2769
|
|
|
2743
|
-
// Who is reviewing
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2770
|
+
// Who is reviewing - NULL organizationId means customer self-review
|
|
2771
|
+
organizationId String? // Organization performing the review (null = customer)
|
|
2772
|
+
organization Organization? @relation(fields: [organizationId], references: [id])
|
|
2773
|
+
organizationTypeId String? // Which type the org was acting as (audit snapshot)
|
|
2774
|
+
organizationType OrganizationType? @relation(fields: [organizationTypeId], references: [id])
|
|
2775
|
+
reviewerId String? // User who performed the review
|
|
2776
|
+
reviewer User? @relation("DocumentReviewer", fields: [reviewerId], references: [id])
|
|
2777
|
+
reviewerName String? // Denormalized for audit trail
|
|
2749
2778
|
|
|
2750
2779
|
// Review state
|
|
2751
2780
|
decision ReviewDecision @default(PENDING)
|
|
@@ -2771,10 +2800,12 @@ model DocumentReview {
|
|
|
2771
2800
|
createdAt DateTime @default(now())
|
|
2772
2801
|
updatedAt DateTime @updatedAt
|
|
2773
2802
|
|
|
2774
|
-
|
|
2803
|
+
// Unique: one review per org per doc (null org = customer review)
|
|
2804
|
+
@@unique([documentId, organizationId])
|
|
2775
2805
|
@@index([tenantId])
|
|
2776
2806
|
@@index([documentId])
|
|
2777
|
-
@@index([
|
|
2807
|
+
@@index([organizationId])
|
|
2808
|
+
@@index([organizationTypeId])
|
|
2778
2809
|
@@index([decision])
|
|
2779
2810
|
@@index([reviewerId])
|
|
2780
2811
|
@@index([parentReviewId])
|
|
@@ -2800,9 +2831,10 @@ model ApprovalStageProgress {
|
|
|
2800
2831
|
approvalStage ApprovalStage @relation(fields: [approvalStageId], references: [id])
|
|
2801
2832
|
|
|
2802
2833
|
// Stage info (denormalized for convenience)
|
|
2803
|
-
name
|
|
2804
|
-
order
|
|
2805
|
-
|
|
2834
|
+
name String
|
|
2835
|
+
order Int
|
|
2836
|
+
organizationTypeId String // Which type of org should review at this stage
|
|
2837
|
+
organizationType OrganizationType @relation(fields: [organizationTypeId], references: [id])
|
|
2806
2838
|
|
|
2807
2839
|
// Behavior flags (copied from template)
|
|
2808
2840
|
autoTransition Boolean @default(false)
|
|
@@ -2856,9 +2888,10 @@ model DocumentApproval {
|
|
|
2856
2888
|
stageProgress ApprovalStageProgress @relation(fields: [stageProgressId], references: [id], onDelete: Cascade)
|
|
2857
2889
|
|
|
2858
2890
|
// Reviewer info
|
|
2859
|
-
reviewerId
|
|
2860
|
-
reviewer
|
|
2861
|
-
|
|
2891
|
+
reviewerId String
|
|
2892
|
+
reviewer User @relation("DocumentApprovalReviewer", fields: [reviewerId], references: [id])
|
|
2893
|
+
organizationTypeId String // Which type the reviewer's org was acting as
|
|
2894
|
+
organizationType OrganizationType @relation(fields: [organizationTypeId], references: [id])
|
|
2862
2895
|
|
|
2863
2896
|
// Decision
|
|
2864
2897
|
decision ReviewDecision // APPROVED, REJECTED, CHANGES_REQUESTED
|
|
@@ -2871,6 +2904,7 @@ model DocumentApproval {
|
|
|
2871
2904
|
@@index([documentId])
|
|
2872
2905
|
@@index([stageProgressId])
|
|
2873
2906
|
@@index([reviewerId])
|
|
2907
|
+
@@index([organizationTypeId])
|
|
2874
2908
|
@@index([decision])
|
|
2875
2909
|
@@map("document_approvals")
|
|
2876
2910
|
}
|