@valentine-efagene/qshelter-common 2.0.21 → 2.0.22
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 +45 -30
- package/dist/generated/client/client.d.ts +45 -30
- package/dist/generated/client/commonInputTypes.d.ts +40 -0
- package/dist/generated/client/internal/class.d.ts +93 -60
- package/dist/generated/client/internal/class.js +2 -2
- package/dist/generated/client/internal/prismaNamespace.d.ts +1050 -720
- package/dist/generated/client/internal/prismaNamespace.js +313 -190
- package/dist/generated/client/internal/prismaNamespaceBrowser.d.ts +344 -215
- package/dist/generated/client/internal/prismaNamespaceBrowser.js +313 -190
- package/dist/generated/client/models/Amenity.d.ts +168 -1
- package/dist/generated/client/models/Contract.d.ts +2037 -298
- package/dist/generated/client/models/ContractDocument.d.ts +299 -12
- package/dist/generated/client/models/ContractEvent.d.ts +1052 -0
- package/dist/generated/client/models/ContractEvent.js +1 -0
- package/dist/generated/client/models/ContractInstallment.d.ts +1656 -0
- package/dist/generated/client/models/ContractInstallment.js +1 -0
- package/dist/generated/client/models/ContractPayment.d.ts +2026 -0
- package/dist/generated/client/models/ContractPayment.js +1 -0
- package/dist/generated/client/models/ContractPhase.d.ts +2467 -0
- package/dist/generated/client/models/ContractPhase.js +1 -0
- package/dist/generated/client/models/ContractPhaseStep.d.ts +1678 -0
- package/dist/generated/client/models/ContractPhaseStep.js +1 -0
- package/dist/generated/client/models/ContractPhaseStepApproval.d.ts +1249 -0
- package/dist/generated/client/models/ContractPhaseStepApproval.js +1 -0
- package/dist/generated/client/models/ContractTransition.d.ts +1118 -0
- package/dist/generated/client/models/ContractTransition.js +1 -0
- package/dist/generated/client/models/DomainEvent.d.ts +1240 -0
- package/dist/generated/client/models/DomainEvent.js +1 -0
- package/dist/generated/client/models/PaymentPlan.d.ts +325 -1062
- package/dist/generated/client/models/Property.d.ts +154 -684
- package/dist/generated/client/models/PropertyPaymentMethod.d.ts +1498 -0
- package/dist/generated/client/models/PropertyPaymentMethod.js +1 -0
- package/dist/generated/client/models/PropertyPaymentMethodLink.d.ts +1158 -0
- package/dist/generated/client/models/PropertyPaymentMethodLink.js +1 -0
- package/dist/generated/client/models/PropertyPaymentMethodPhase.d.ts +1656 -0
- package/dist/generated/client/models/PropertyPaymentMethodPhase.js +1 -0
- package/dist/generated/client/models/PropertyUnit.d.ts +1598 -0
- package/dist/generated/client/models/PropertyUnit.js +1 -0
- package/dist/generated/client/models/PropertyVariant.d.ts +2079 -0
- package/dist/generated/client/models/PropertyVariant.js +1 -0
- package/dist/generated/client/models/PropertyVariantAmenity.d.ts +1080 -0
- package/dist/generated/client/models/PropertyVariantAmenity.js +1 -0
- package/dist/generated/client/models/PropertyVariantMedia.d.ts +1189 -0
- package/dist/generated/client/models/PropertyVariantMedia.js +1 -0
- package/dist/generated/client/models/User.d.ts +684 -427
- package/dist/generated/client/models/index.d.ts +15 -12
- package/dist/generated/client/models/index.js +15 -12
- package/dist/generated/client/models.d.ts +15 -12
- package/package.json +1 -1
- package/prisma/schema.prisma +541 -267
package/prisma/schema.prisma
CHANGED
|
@@ -49,12 +49,15 @@ model User {
|
|
|
49
49
|
socials Social[]
|
|
50
50
|
|
|
51
51
|
// Relations to other domains
|
|
52
|
-
properties
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
properties Property[]
|
|
53
|
+
contracts Contract[] @relation("ContractBuyer")
|
|
54
|
+
soldContracts Contract[] @relation("ContractSeller")
|
|
55
|
+
contractPayments ContractPayment[] @relation("ContractPayer")
|
|
56
|
+
|
|
57
|
+
// Phase step assignments and approvals
|
|
58
|
+
assignedSteps ContractPhaseStep[] @relation("PhaseStepAssignee")
|
|
59
|
+
stepApprovals ContractPhaseStepApproval[] @relation("PhaseStepApprover")
|
|
60
|
+
uploadedDocs ContractDocument[] @relation("DocumentUploader")
|
|
58
61
|
|
|
59
62
|
@@index([email])
|
|
60
63
|
@@index([tenantId])
|
|
@@ -262,6 +265,10 @@ model Settings {
|
|
|
262
265
|
// =============================================================================
|
|
263
266
|
// PROPERTY DOMAIN
|
|
264
267
|
// =============================================================================
|
|
268
|
+
// Property = listing/project (e.g., "Sunrise Estate")
|
|
269
|
+
// PropertyVariant = configuration with specs & price (e.g., "3-Bed Corner - Finished")
|
|
270
|
+
// PropertyUnit = individual sellable unit (e.g., "Unit A1")
|
|
271
|
+
// =============================================================================
|
|
265
272
|
|
|
266
273
|
model Property {
|
|
267
274
|
id String @id @default(cuid())
|
|
@@ -269,21 +276,16 @@ model Property {
|
|
|
269
276
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
270
277
|
title String
|
|
271
278
|
category String // SALE, RENT, LEASE
|
|
272
|
-
propertyType String // APARTMENT, HOUSE, LAND, COMMERCIAL
|
|
279
|
+
propertyType String // APARTMENT, HOUSE, LAND, COMMERCIAL, ESTATE, TOWNHOUSE
|
|
273
280
|
country String
|
|
274
281
|
currency String // USD, NGN, etc
|
|
275
282
|
city String
|
|
276
283
|
district String?
|
|
277
284
|
zipCode String?
|
|
278
285
|
streetAddress String?
|
|
279
|
-
nBedrooms String
|
|
280
|
-
nBathrooms String
|
|
281
|
-
nParkingSpots String
|
|
282
|
-
price Float
|
|
283
286
|
longitude Float?
|
|
284
287
|
latitude Float?
|
|
285
|
-
|
|
286
|
-
status String @default("DRAFT") // DRAFT, PUBLISHED, SOLD, RENTED
|
|
288
|
+
status String @default("DRAFT") // DRAFT, PUBLISHED, SOLD_OUT, ARCHIVED
|
|
287
289
|
description String? @db.Text
|
|
288
290
|
displayImageId String?
|
|
289
291
|
displayImage PropertyMedia? @relation("DisplayImage", fields: [displayImageId], references: [id], onDelete: SetNull)
|
|
@@ -292,17 +294,18 @@ model Property {
|
|
|
292
294
|
createdAt DateTime @default(now())
|
|
293
295
|
updatedAt DateTime @updatedAt
|
|
294
296
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
297
|
+
// Relations
|
|
298
|
+
documents PropertyDocument[]
|
|
299
|
+
media PropertyMedia[] @relation("PropertyMedia")
|
|
300
|
+
amenities PropertyAmenity[] // Shared amenities (gym, pool, security)
|
|
301
|
+
paymentMethods PropertyPaymentMethodLink[]
|
|
302
|
+
variants PropertyVariant[]
|
|
301
303
|
|
|
302
304
|
@@index([userId])
|
|
303
305
|
@@index([category])
|
|
304
306
|
@@index([propertyType])
|
|
305
307
|
@@index([city])
|
|
308
|
+
@@index([status])
|
|
306
309
|
@@map("properties")
|
|
307
310
|
}
|
|
308
311
|
|
|
@@ -338,15 +341,134 @@ model PropertyDocument {
|
|
|
338
341
|
}
|
|
339
342
|
|
|
340
343
|
model Amenity {
|
|
341
|
-
id String
|
|
342
|
-
name String
|
|
343
|
-
|
|
344
|
-
|
|
344
|
+
id String @id @default(cuid())
|
|
345
|
+
name String @unique
|
|
346
|
+
category String? // PROPERTY, VARIANT, BOTH - helps filter which amenities to show
|
|
347
|
+
icon String? // Icon name/URL for UI
|
|
348
|
+
createdAt DateTime @default(now())
|
|
349
|
+
updatedAt DateTime @updatedAt
|
|
345
350
|
properties PropertyAmenity[]
|
|
351
|
+
variants PropertyVariantAmenity[]
|
|
346
352
|
|
|
353
|
+
@@index([category])
|
|
347
354
|
@@map("amenities")
|
|
348
355
|
}
|
|
349
356
|
|
|
357
|
+
// =============================================================================
|
|
358
|
+
// PROPERTY VARIANT & UNIT MODELS
|
|
359
|
+
// =============================================================================
|
|
360
|
+
|
|
361
|
+
// PropertyVariant = specific configuration with its own price and amenities
|
|
362
|
+
// e.g., "3-Bedroom Corner Piece - Fully Finished", "2-Bedroom Standard - Carcass"
|
|
363
|
+
model PropertyVariant {
|
|
364
|
+
id String @id @default(cuid())
|
|
365
|
+
propertyId String
|
|
366
|
+
property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)
|
|
367
|
+
|
|
368
|
+
name String // "Corner Piece - Finished", "Standard - Carcass"
|
|
369
|
+
description String? @db.Text
|
|
370
|
+
|
|
371
|
+
// Specifications
|
|
372
|
+
nBedrooms Int?
|
|
373
|
+
nBathrooms Int?
|
|
374
|
+
nParkingSpots Int?
|
|
375
|
+
area Float? // Square meters/feet
|
|
376
|
+
|
|
377
|
+
// Pricing
|
|
378
|
+
price Float
|
|
379
|
+
pricePerSqm Float? // Computed or set manually
|
|
380
|
+
|
|
381
|
+
// Inventory counters (denormalized for performance, updated via triggers/service)
|
|
382
|
+
totalUnits Int @default(1)
|
|
383
|
+
availableUnits Int @default(1)
|
|
384
|
+
reservedUnits Int @default(0)
|
|
385
|
+
soldUnits Int @default(0)
|
|
386
|
+
|
|
387
|
+
// Status
|
|
388
|
+
status String @default("AVAILABLE") // AVAILABLE, LOW_STOCK, SOLD_OUT, ARCHIVED
|
|
389
|
+
isActive Boolean @default(true)
|
|
390
|
+
createdAt DateTime @default(now())
|
|
391
|
+
updatedAt DateTime @updatedAt
|
|
392
|
+
|
|
393
|
+
// Relations
|
|
394
|
+
amenities PropertyVariantAmenity[]
|
|
395
|
+
units PropertyUnit[]
|
|
396
|
+
media PropertyVariantMedia[]
|
|
397
|
+
|
|
398
|
+
@@index([propertyId])
|
|
399
|
+
@@index([status])
|
|
400
|
+
@@index([price])
|
|
401
|
+
@@map("property_variants")
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// PropertyVariantAmenity = amenities specific to a variant
|
|
405
|
+
// e.g., "Finished Kitchen", "Smart Home System", "Private Garden"
|
|
406
|
+
model PropertyVariantAmenity {
|
|
407
|
+
variantId String
|
|
408
|
+
amenityId String
|
|
409
|
+
variant PropertyVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)
|
|
410
|
+
amenity Amenity @relation(fields: [amenityId], references: [id], onDelete: Cascade)
|
|
411
|
+
createdAt DateTime @default(now())
|
|
412
|
+
|
|
413
|
+
@@id([variantId, amenityId])
|
|
414
|
+
@@map("property_variant_amenities")
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// PropertyVariantMedia = images/videos specific to a variant
|
|
418
|
+
model PropertyVariantMedia {
|
|
419
|
+
id String @id @default(cuid())
|
|
420
|
+
variantId String
|
|
421
|
+
variant PropertyVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)
|
|
422
|
+
url String
|
|
423
|
+
type String // IMAGE, VIDEO, FLOOR_PLAN, 3D_TOUR
|
|
424
|
+
caption String?
|
|
425
|
+
order Int @default(0)
|
|
426
|
+
createdAt DateTime @default(now())
|
|
427
|
+
updatedAt DateTime @updatedAt
|
|
428
|
+
|
|
429
|
+
@@index([variantId])
|
|
430
|
+
@@map("property_variant_media")
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// PropertyUnit = individual sellable/rentable unit within a variant
|
|
434
|
+
// e.g., "Unit A1", "Block B - Flat 3", "Plot 15"
|
|
435
|
+
model PropertyUnit {
|
|
436
|
+
id String @id @default(cuid())
|
|
437
|
+
variantId String
|
|
438
|
+
variant PropertyVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)
|
|
439
|
+
|
|
440
|
+
unitNumber String // "A1", "B-3", "Plot 15"
|
|
441
|
+
floorNumber Int? // For apartments
|
|
442
|
+
blockName String? // "Block A", "Tower 1"
|
|
443
|
+
|
|
444
|
+
// Unit-specific overrides (if different from variant)
|
|
445
|
+
priceOverride Float? // If this specific unit has a different price
|
|
446
|
+
areaOverride Float? // If this specific unit has a different area
|
|
447
|
+
notes String? @db.Text // Internal notes about this unit
|
|
448
|
+
|
|
449
|
+
// Status tracking
|
|
450
|
+
status String @default("AVAILABLE") // AVAILABLE, RESERVED, SOLD, RENTED, UNAVAILABLE
|
|
451
|
+
|
|
452
|
+
// Reservation/hold
|
|
453
|
+
reservedAt DateTime?
|
|
454
|
+
reservedUntil DateTime?
|
|
455
|
+
reservedById String?
|
|
456
|
+
|
|
457
|
+
// Ownership tracking (once sold)
|
|
458
|
+
ownerId String?
|
|
459
|
+
|
|
460
|
+
createdAt DateTime @default(now())
|
|
461
|
+
updatedAt DateTime @updatedAt
|
|
462
|
+
|
|
463
|
+
// Relations
|
|
464
|
+
contracts Contract[]
|
|
465
|
+
|
|
466
|
+
@@unique([variantId, unitNumber])
|
|
467
|
+
@@index([variantId])
|
|
468
|
+
@@index([status])
|
|
469
|
+
@@map("property_units")
|
|
470
|
+
}
|
|
471
|
+
|
|
350
472
|
model PropertyAmenity {
|
|
351
473
|
propertyId String
|
|
352
474
|
amenityId String
|
|
@@ -359,305 +481,457 @@ model PropertyAmenity {
|
|
|
359
481
|
}
|
|
360
482
|
|
|
361
483
|
// =============================================================================
|
|
362
|
-
//
|
|
484
|
+
// PAYMENT PLAN DOMAIN - Reusable installment structure templates
|
|
363
485
|
// =============================================================================
|
|
364
486
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
interestRate Float
|
|
380
|
-
monthlyPayment Float
|
|
381
|
-
status String @default("DRAFT") // DRAFT, PENDING, ACTIVE, COMPLETED, CANCELLED
|
|
382
|
-
state String @default("DRAFT") // FSM state
|
|
383
|
-
stateMetadata String? @db.Text // JSON metadata
|
|
384
|
-
lastReminderSentAt DateTime?
|
|
385
|
-
createdAt DateTime @default(now())
|
|
386
|
-
updatedAt DateTime @updatedAt
|
|
487
|
+
// PaymentPlan = reusable structure for how payments are scheduled
|
|
488
|
+
// Examples: "Monthly360" (360 monthly payments), "Weekly52", "OneTime"
|
|
489
|
+
model PaymentPlan {
|
|
490
|
+
id String @id @default(cuid())
|
|
491
|
+
name String @unique
|
|
492
|
+
description String? @db.Text
|
|
493
|
+
isActive Boolean @default(true)
|
|
494
|
+
|
|
495
|
+
// Structure configuration
|
|
496
|
+
paymentFrequency String // MONTHLY, BIWEEKLY, WEEKLY, ONE_TIME, CUSTOM
|
|
497
|
+
customFrequencyDays Int?
|
|
498
|
+
numberOfInstallments Int // 1 for one-time, 360 for 30yr monthly, etc
|
|
499
|
+
calculateInterestDaily Boolean @default(false)
|
|
500
|
+
gracePeriodDays Int @default(0)
|
|
387
501
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
transitions MortgageTransition[]
|
|
391
|
-
transitionEvents MortgageTransitionEvent[]
|
|
502
|
+
createdAt DateTime @default(now())
|
|
503
|
+
updatedAt DateTime @updatedAt
|
|
392
504
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
505
|
+
// Used by property payment method phases (templates)
|
|
506
|
+
methodPhases PropertyPaymentMethodPhase[]
|
|
507
|
+
// Used by instantiated contract phases
|
|
508
|
+
contractPhases ContractPhase[]
|
|
509
|
+
|
|
510
|
+
@@map("payment_plans")
|
|
398
511
|
}
|
|
399
512
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
description String? @db.Text
|
|
404
|
-
createdAt DateTime @default(now())
|
|
405
|
-
updatedAt DateTime @updatedAt
|
|
406
|
-
mortgages Mortgage[]
|
|
513
|
+
// =============================================================================
|
|
514
|
+
// PROPERTY PAYMENT METHOD DOMAIN - Product offerings per property
|
|
515
|
+
// =============================================================================
|
|
407
516
|
|
|
408
|
-
|
|
409
|
-
|
|
517
|
+
// PropertyPaymentMethod = how a property can be purchased (e.g., "Standard Mortgage", "Cash", "Rent-to-Own")
|
|
518
|
+
model PropertyPaymentMethod {
|
|
519
|
+
id String @id @default(cuid())
|
|
520
|
+
name String // "Standard Mortgage", "Flexible Payment", "Cash Purchase"
|
|
521
|
+
description String? @db.Text
|
|
522
|
+
isActive Boolean @default(true)
|
|
410
523
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
url String
|
|
417
|
-
type String // INCOME_PROOF, ID, etc
|
|
418
|
-
createdAt DateTime @default(now())
|
|
419
|
-
updatedAt DateTime @updatedAt
|
|
524
|
+
// Global method configuration
|
|
525
|
+
allowEarlyPayoff Boolean @default(true)
|
|
526
|
+
earlyPayoffPenaltyRate Float?
|
|
527
|
+
autoActivatePhases Boolean @default(true)
|
|
528
|
+
requiresManualApproval Boolean @default(false)
|
|
420
529
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
530
|
+
createdAt DateTime @default(now())
|
|
531
|
+
updatedAt DateTime @updatedAt
|
|
424
532
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
order Int
|
|
432
|
-
isCompleted Boolean @default(false)
|
|
433
|
-
completedAt DateTime?
|
|
434
|
-
createdAt DateTime @default(now())
|
|
435
|
-
updatedAt DateTime @updatedAt
|
|
533
|
+
// Many-to-many with properties
|
|
534
|
+
properties PropertyPaymentMethodLink[]
|
|
535
|
+
// Phases that make up this method (templates)
|
|
536
|
+
phases PropertyPaymentMethodPhase[]
|
|
537
|
+
// Contracts using this method
|
|
538
|
+
contracts Contract[]
|
|
436
539
|
|
|
437
|
-
@@
|
|
438
|
-
@@map("mortgage_steps")
|
|
540
|
+
@@map("property_payment_methods")
|
|
439
541
|
}
|
|
440
542
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
endDate DateTime
|
|
448
|
-
createdAt DateTime @default(now())
|
|
449
|
-
updatedAt DateTime @updatedAt
|
|
543
|
+
// Many-to-many link between Property and PaymentMethod
|
|
544
|
+
model PropertyPaymentMethodLink {
|
|
545
|
+
propertyId String
|
|
546
|
+
property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)
|
|
547
|
+
paymentMethodId String
|
|
548
|
+
paymentMethod PropertyPaymentMethod @relation(fields: [paymentMethodId], references: [id], onDelete: Cascade)
|
|
450
549
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
550
|
+
// Method-specific overrides for this property
|
|
551
|
+
isDefault Boolean @default(false)
|
|
552
|
+
isActive Boolean @default(true)
|
|
553
|
+
createdAt DateTime @default(now())
|
|
454
554
|
|
|
455
|
-
@@
|
|
555
|
+
@@id([propertyId, paymentMethodId])
|
|
556
|
+
@@map("property_payment_method_links")
|
|
456
557
|
}
|
|
457
558
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
createdAt DateTime @default(now())
|
|
467
|
-
updatedAt DateTime @updatedAt
|
|
559
|
+
// Phase template within a PropertyPaymentMethod (e.g., documentation, downpayment, mortgage)
|
|
560
|
+
// phaseCategory determines the FSM type: DOCUMENTATION or PAYMENT
|
|
561
|
+
model PropertyPaymentMethodPhase {
|
|
562
|
+
id String @id @default(cuid())
|
|
563
|
+
paymentMethodId String
|
|
564
|
+
paymentMethod PropertyPaymentMethod @relation(fields: [paymentMethodId], references: [id], onDelete: Cascade)
|
|
565
|
+
paymentPlanId String? // Only for PAYMENT phases
|
|
566
|
+
paymentPlan PaymentPlan? @relation(fields: [paymentPlanId], references: [id])
|
|
468
567
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
}
|
|
568
|
+
name String
|
|
569
|
+
description String? @db.Text
|
|
472
570
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
amount Float
|
|
478
|
-
paymentMethod String
|
|
479
|
-
reference String?
|
|
480
|
-
status String @default("PENDING")
|
|
481
|
-
createdAt DateTime @default(now())
|
|
482
|
-
updatedAt DateTime @updatedAt
|
|
571
|
+
// Phase classification
|
|
572
|
+
phaseCategory String // DOCUMENTATION, PAYMENT
|
|
573
|
+
phaseType String // Admin-defined: KYC, VERIFICATION, DOWNPAYMENT, MORTGAGE, BALLOON, CUSTOM, etc.
|
|
574
|
+
order Int
|
|
483
575
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
576
|
+
// Financial configuration (for PAYMENT phases)
|
|
577
|
+
interestRate Float?
|
|
578
|
+
percentOfPrice Float? // e.g., 10.0 for 10% downpayment
|
|
487
579
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
mortgage Mortgage @relation(fields: [mortgageId], references: [id], onDelete: Cascade)
|
|
492
|
-
fromState String
|
|
493
|
-
toState String
|
|
494
|
-
trigger String
|
|
495
|
-
metadata String? @db.Text // JSON
|
|
496
|
-
transitionedAt DateTime @default(now())
|
|
580
|
+
// Activation rules
|
|
581
|
+
requiresPreviousPhaseCompletion Boolean @default(true)
|
|
582
|
+
minimumCompletionPercentage Float?
|
|
497
583
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
}
|
|
584
|
+
// For DOCUMENTATION phases: define required steps
|
|
585
|
+
requiredDocumentTypes String? // CSV: ID,BANK_STATEMENT,INCOME_PROOF
|
|
586
|
+
stepDefinitions String? @db.Text // JSON: [{name, stepType, order}]
|
|
501
587
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
mortgageId String
|
|
505
|
-
mortgage Mortgage @relation(fields: [mortgageId], references: [id], onDelete: Cascade)
|
|
506
|
-
event String
|
|
507
|
-
data String? @db.Text // JSON
|
|
508
|
-
createdAt DateTime @default(now())
|
|
588
|
+
createdAt DateTime @default(now())
|
|
589
|
+
updatedAt DateTime @updatedAt
|
|
509
590
|
|
|
510
|
-
@@index([
|
|
511
|
-
@@
|
|
591
|
+
@@index([paymentMethodId])
|
|
592
|
+
@@index([paymentPlanId])
|
|
593
|
+
@@index([phaseCategory])
|
|
594
|
+
@@map("property_payment_method_phases")
|
|
512
595
|
}
|
|
513
596
|
|
|
514
597
|
// =============================================================================
|
|
515
|
-
//
|
|
598
|
+
// CONTRACT DOMAIN - Unified agreement model (replaces Mortgage, PurchasePlan, etc.)
|
|
599
|
+
// =============================================================================
|
|
600
|
+
// Contract is the canonical agreement. "Mortgage" is just a product configuration
|
|
601
|
+
// that creates a Contract with specific phases (documentation, downpayment, long-term payment).
|
|
602
|
+
// Phases can be DOCUMENTATION (FSM for approvals) or PAYMENT (PaymentPlan-driven installments).
|
|
516
603
|
// =============================================================================
|
|
517
604
|
|
|
518
|
-
model
|
|
519
|
-
id
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
605
|
+
model Contract {
|
|
606
|
+
id String @id @default(cuid())
|
|
607
|
+
// Link to specific unit being purchased/rented
|
|
608
|
+
propertyUnitId String
|
|
609
|
+
propertyUnit PropertyUnit @relation(fields: [propertyUnitId], references: [id], onDelete: Cascade)
|
|
610
|
+
buyerId String
|
|
611
|
+
buyer User @relation("ContractBuyer", fields: [buyerId], references: [id], onDelete: Cascade)
|
|
612
|
+
sellerId String?
|
|
613
|
+
seller User? @relation("ContractSeller", fields: [sellerId], references: [id])
|
|
614
|
+
paymentMethodId String? // PropertyPaymentMethod used to create this contract
|
|
615
|
+
paymentMethod PropertyPaymentMethod? @relation(fields: [paymentMethodId], references: [id])
|
|
616
|
+
|
|
617
|
+
// Contract identification
|
|
618
|
+
contractNumber String @unique
|
|
619
|
+
title String
|
|
620
|
+
description String? @db.Text
|
|
621
|
+
contractType String // Admin-defined: MORTGAGE, INSTALLMENT, RENT_TO_OWN, CASH, LEASE, etc.
|
|
622
|
+
|
|
623
|
+
// Financial summary (computed from phases)
|
|
624
|
+
totalAmount Float // Total contract value (from unit price or negotiated)
|
|
625
|
+
downPayment Float @default(0)
|
|
626
|
+
downPaymentPaid Float @default(0)
|
|
627
|
+
principal Float? // Financed amount (if applicable)
|
|
628
|
+
interestRate Float? // Overall interest rate (if applicable)
|
|
629
|
+
termMonths Int? // Total term (if applicable)
|
|
630
|
+
periodicPayment Float? // Computed periodic payment (if applicable)
|
|
631
|
+
totalPaidToDate Float @default(0)
|
|
632
|
+
totalInterestPaid Float @default(0)
|
|
633
|
+
|
|
634
|
+
// FSM state
|
|
635
|
+
status String @default("DRAFT") // DRAFT, PENDING, ACTIVE, COMPLETED, CANCELLED, TERMINATED
|
|
636
|
+
state String @default("DRAFT") // FSM state for workflow
|
|
637
|
+
currentPhaseId String?
|
|
638
|
+
|
|
639
|
+
// Timing
|
|
640
|
+
nextPaymentDueDate DateTime?
|
|
641
|
+
lastReminderSentAt DateTime?
|
|
642
|
+
startDate DateTime?
|
|
643
|
+
endDate DateTime?
|
|
644
|
+
signedAt DateTime?
|
|
645
|
+
terminatedAt DateTime?
|
|
646
|
+
createdAt DateTime @default(now())
|
|
647
|
+
updatedAt DateTime @updatedAt
|
|
648
|
+
|
|
649
|
+
// Relations
|
|
650
|
+
phases ContractPhase[]
|
|
651
|
+
documents ContractDocument[]
|
|
652
|
+
payments ContractPayment[]
|
|
653
|
+
transitions ContractTransition[]
|
|
654
|
+
events ContractEvent[]
|
|
655
|
+
|
|
656
|
+
@@index([propertyUnitId])
|
|
543
657
|
@@index([buyerId])
|
|
658
|
+
@@index([sellerId])
|
|
659
|
+
@@index([paymentMethodId])
|
|
660
|
+
@@index([status])
|
|
544
661
|
@@index([state])
|
|
545
|
-
@@map("
|
|
662
|
+
@@map("contracts")
|
|
546
663
|
}
|
|
547
664
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
665
|
+
// Phase within a contract - can be DOCUMENTATION or PAYMENT type
|
|
666
|
+
// Admin names phases freely (e.g., "KYC Documents", "Downpayment", "Monthly Mortgage")
|
|
667
|
+
model ContractPhase {
|
|
668
|
+
id String @id @default(cuid())
|
|
669
|
+
contractId String
|
|
670
|
+
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
671
|
+
paymentPlanId String? // Only for PAYMENT phases
|
|
672
|
+
paymentPlan PaymentPlan? @relation(fields: [paymentPlanId], references: [id])
|
|
673
|
+
|
|
674
|
+
// Admin-defined naming
|
|
675
|
+
name String
|
|
676
|
+
description String? @db.Text
|
|
677
|
+
|
|
678
|
+
// Phase classification
|
|
679
|
+
phaseCategory String // DOCUMENTATION, PAYMENT
|
|
680
|
+
phaseType String // Admin-defined: DOWNPAYMENT, MORTGAGE, KYC, VERIFICATION, BALLOON, CUSTOM, etc.
|
|
681
|
+
order Int
|
|
682
|
+
|
|
683
|
+
// FSM state for this phase
|
|
684
|
+
status String @default("PENDING") // PENDING, IN_PROGRESS, AWAITING_APPROVAL, ACTIVE, COMPLETED, SKIPPED, FAILED
|
|
685
|
+
|
|
686
|
+
// Financial details (for PAYMENT phases)
|
|
687
|
+
totalAmount Float?
|
|
688
|
+
paidAmount Float @default(0)
|
|
689
|
+
remainingAmount Float?
|
|
690
|
+
interestRate Float?
|
|
691
|
+
|
|
692
|
+
// Timing
|
|
693
|
+
dueDate DateTime?
|
|
694
|
+
startDate DateTime?
|
|
695
|
+
endDate DateTime?
|
|
696
|
+
activatedAt DateTime?
|
|
697
|
+
completedAt DateTime?
|
|
698
|
+
|
|
699
|
+
// Activation rules
|
|
700
|
+
requiresPreviousPhaseCompletion Boolean @default(true)
|
|
701
|
+
minimumCompletionPercentage Float?
|
|
702
|
+
|
|
703
|
+
createdAt DateTime @default(now())
|
|
704
|
+
updatedAt DateTime @updatedAt
|
|
705
|
+
|
|
706
|
+
// Relations
|
|
707
|
+
installments ContractInstallment[]
|
|
708
|
+
payments ContractPayment[]
|
|
709
|
+
steps ContractPhaseStep[] // For DOCUMENTATION phases (FSM steps)
|
|
710
|
+
|
|
711
|
+
@@index([contractId])
|
|
712
|
+
@@index([paymentPlanId])
|
|
713
|
+
@@index([phaseCategory])
|
|
714
|
+
@@index([status])
|
|
715
|
+
@@index([order])
|
|
716
|
+
@@map("contract_phases")
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Steps within a DOCUMENTATION phase (FSM for document collection/approval)
|
|
720
|
+
model ContractPhaseStep {
|
|
721
|
+
id String @id @default(cuid())
|
|
722
|
+
phaseId String
|
|
723
|
+
phase ContractPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)
|
|
724
|
+
|
|
725
|
+
name String
|
|
726
|
+
description String? @db.Text
|
|
727
|
+
stepType String // UPLOAD, REVIEW, SIGNATURE, APPROVAL, EXTERNAL_CHECK, WAIT
|
|
728
|
+
order Int
|
|
729
|
+
|
|
730
|
+
status String @default("PENDING") // PENDING, IN_PROGRESS, COMPLETED, FAILED, SKIPPED
|
|
731
|
+
|
|
732
|
+
// Assignment
|
|
733
|
+
assigneeId String?
|
|
734
|
+
assignee User? @relation("PhaseStepAssignee", fields: [assigneeId], references: [id])
|
|
735
|
+
|
|
736
|
+
// Required document types for UPLOAD steps
|
|
737
|
+
requiredDocumentTypes String? // CSV: ID,BANK_STATEMENT,INCOME_PROOF
|
|
738
|
+
|
|
739
|
+
// Timing
|
|
740
|
+
dueDate DateTime?
|
|
741
|
+
completedAt DateTime?
|
|
742
|
+
|
|
743
|
+
createdAt DateTime @default(now())
|
|
744
|
+
updatedAt DateTime @updatedAt
|
|
745
|
+
|
|
746
|
+
approvals ContractPhaseStepApproval[]
|
|
747
|
+
|
|
748
|
+
@@index([phaseId])
|
|
749
|
+
@@index([status])
|
|
750
|
+
@@index([order])
|
|
751
|
+
@@map("contract_phase_steps")
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// Approvals for documentation steps
|
|
755
|
+
model ContractPhaseStepApproval {
|
|
756
|
+
id String @id @default(cuid())
|
|
757
|
+
stepId String
|
|
758
|
+
step ContractPhaseStep @relation(fields: [stepId], references: [id], onDelete: Cascade)
|
|
759
|
+
approverId String?
|
|
760
|
+
approver User? @relation("PhaseStepApprover", fields: [approverId], references: [id])
|
|
761
|
+
|
|
762
|
+
decision String // APPROVED, REJECTED, REQUEST_CHANGES
|
|
763
|
+
comment String? @db.Text
|
|
764
|
+
decidedAt DateTime @default(now())
|
|
559
765
|
|
|
560
|
-
|
|
561
|
-
payments Payment[]
|
|
766
|
+
createdAt DateTime @default(now())
|
|
562
767
|
|
|
563
|
-
@@index([
|
|
564
|
-
@@map("
|
|
768
|
+
@@index([stepId])
|
|
769
|
+
@@map("contract_phase_step_approvals")
|
|
565
770
|
}
|
|
566
771
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
772
|
+
// Installments within a PAYMENT phase
|
|
773
|
+
model ContractInstallment {
|
|
774
|
+
id String @id @default(cuid())
|
|
775
|
+
phaseId String
|
|
776
|
+
phase ContractPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)
|
|
777
|
+
|
|
571
778
|
installmentNumber Int
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
779
|
+
|
|
780
|
+
amount Float
|
|
781
|
+
principalAmount Float @default(0)
|
|
782
|
+
interestAmount Float @default(0)
|
|
783
|
+
|
|
784
|
+
dueDate DateTime
|
|
785
|
+
status String @default("PENDING") // PENDING, PAID, OVERDUE, PARTIALLY_PAID, WAIVED
|
|
786
|
+
|
|
787
|
+
paidAmount Float @default(0)
|
|
788
|
+
paidDate DateTime?
|
|
789
|
+
|
|
790
|
+
lateFee Float @default(0)
|
|
791
|
+
lateFeeWaived Boolean @default(false)
|
|
792
|
+
gracePeriodDays Int @default(0)
|
|
793
|
+
gracePeriodEndDate DateTime?
|
|
794
|
+
|
|
795
|
+
createdAt DateTime @default(now())
|
|
796
|
+
updatedAt DateTime @updatedAt
|
|
797
|
+
|
|
798
|
+
payments ContractPayment[]
|
|
799
|
+
|
|
800
|
+
@@index([phaseId])
|
|
586
801
|
@@index([dueDate])
|
|
587
802
|
@@index([status])
|
|
588
|
-
@@map("
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
803
|
+
@@map("contract_installments")
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Unified payment record for contracts
|
|
807
|
+
model ContractPayment {
|
|
808
|
+
id String @id @default(cuid())
|
|
809
|
+
contractId String
|
|
810
|
+
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
811
|
+
phaseId String?
|
|
812
|
+
phase ContractPhase? @relation(fields: [phaseId], references: [id])
|
|
813
|
+
installmentId String?
|
|
814
|
+
installment ContractInstallment? @relation(fields: [installmentId], references: [id])
|
|
815
|
+
payerId String?
|
|
816
|
+
payer User? @relation("ContractPayer", fields: [payerId], references: [id])
|
|
817
|
+
|
|
601
818
|
amount Float
|
|
602
|
-
principalAmount Float
|
|
603
|
-
interestAmount Float
|
|
604
|
-
lateFeeAmount Float
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
819
|
+
principalAmount Float @default(0)
|
|
820
|
+
interestAmount Float @default(0)
|
|
821
|
+
lateFeeAmount Float @default(0)
|
|
822
|
+
|
|
823
|
+
paymentMethod String // BANK_TRANSFER, CREDIT_CARD, WALLET, CASH, CHECK
|
|
824
|
+
status String @default("INITIATED") // INITIATED, PENDING, COMPLETED, FAILED, REFUNDED
|
|
825
|
+
|
|
826
|
+
reference String? @unique
|
|
827
|
+
gatewayResponse String? @db.Text // JSON
|
|
828
|
+
|
|
829
|
+
processedAt DateTime?
|
|
830
|
+
createdAt DateTime @default(now())
|
|
831
|
+
updatedAt DateTime @updatedAt
|
|
832
|
+
|
|
833
|
+
@@index([contractId])
|
|
834
|
+
@@index([phaseId])
|
|
835
|
+
@@index([installmentId])
|
|
614
836
|
@@index([payerId])
|
|
615
837
|
@@index([status])
|
|
616
838
|
@@index([reference])
|
|
617
|
-
@@map("
|
|
839
|
+
@@map("contract_payments")
|
|
618
840
|
}
|
|
619
841
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
buyer User? @relation("ContractBuyer", fields: [buyerId], references: [id])
|
|
628
|
-
sellerId String?
|
|
629
|
-
seller User? @relation("ContractSeller", fields: [sellerId], references: [id])
|
|
630
|
-
contractType String // MORTGAGE, SALE_AGREEMENT, LEASE_AGREEMENT, etc
|
|
631
|
-
contractNumber String @unique
|
|
632
|
-
title String
|
|
633
|
-
description String? @db.Text
|
|
634
|
-
status String @default("DRAFT") // DRAFT, PENDING_SIGNATURE, ACTIVE, COMPLETED, TERMINATED
|
|
635
|
-
startDate DateTime?
|
|
636
|
-
endDate DateTime?
|
|
637
|
-
signedAt DateTime?
|
|
638
|
-
terminatedAt DateTime?
|
|
639
|
-
createdAt DateTime @default(now())
|
|
640
|
-
updatedAt DateTime @updatedAt
|
|
842
|
+
// Contract documents (owned by contract, linked to phases/steps as needed)
|
|
843
|
+
model ContractDocument {
|
|
844
|
+
id String @id @default(cuid())
|
|
845
|
+
contractId String
|
|
846
|
+
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
847
|
+
phaseId String? // Optional link to specific phase
|
|
848
|
+
stepId String? // Optional link to specific step
|
|
641
849
|
|
|
642
|
-
|
|
850
|
+
name String
|
|
851
|
+
url String
|
|
852
|
+
type String // ID, BANK_STATEMENT, INCOME_PROOF, TITLE_DEED, SIGNATURE, etc.
|
|
853
|
+
uploadedById String?
|
|
854
|
+
uploadedBy User? @relation("DocumentUploader", fields: [uploadedById], references: [id])
|
|
643
855
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
856
|
+
status String @default("PENDING") // PENDING, APPROVED, REJECTED
|
|
857
|
+
|
|
858
|
+
createdAt DateTime @default(now())
|
|
859
|
+
updatedAt DateTime @updatedAt
|
|
860
|
+
|
|
861
|
+
@@index([contractId])
|
|
862
|
+
@@index([phaseId])
|
|
863
|
+
@@index([stepId])
|
|
864
|
+
@@index([type])
|
|
647
865
|
@@index([status])
|
|
648
|
-
@@map("
|
|
866
|
+
@@map("contract_documents")
|
|
649
867
|
}
|
|
650
868
|
|
|
651
|
-
|
|
869
|
+
// FSM transitions for audit
|
|
870
|
+
model ContractTransition {
|
|
871
|
+
id String @id @default(cuid())
|
|
872
|
+
contractId String
|
|
873
|
+
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
874
|
+
fromState String
|
|
875
|
+
toState String
|
|
876
|
+
trigger String
|
|
877
|
+
metadata String? @db.Text // JSON
|
|
878
|
+
transitionedAt DateTime @default(now())
|
|
879
|
+
|
|
880
|
+
@@index([contractId])
|
|
881
|
+
@@map("contract_transitions")
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// Domain events for audit and integration
|
|
885
|
+
model ContractEvent {
|
|
652
886
|
id String @id @default(cuid())
|
|
653
887
|
contractId String
|
|
654
888
|
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
type String
|
|
889
|
+
event String
|
|
890
|
+
data String? @db.Text // JSON
|
|
658
891
|
createdAt DateTime @default(now())
|
|
659
|
-
updatedAt DateTime @updatedAt
|
|
660
892
|
|
|
661
893
|
@@index([contractId])
|
|
662
|
-
@@map("
|
|
894
|
+
@@map("contract_events")
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// =============================================================================
|
|
898
|
+
// EVENT OUTBOX - For guaranteed event delivery to SQS queues
|
|
899
|
+
// =============================================================================
|
|
900
|
+
|
|
901
|
+
model DomainEvent {
|
|
902
|
+
id String @id @default(cuid())
|
|
903
|
+
|
|
904
|
+
// Event identification
|
|
905
|
+
eventType String // MORTGAGE.CREATED, PHASE.ACTIVATED, PAYMENT.COMPLETED, etc
|
|
906
|
+
aggregateType String // Mortgage, MortgagePhase, MortgagePayment, Property, etc
|
|
907
|
+
aggregateId String
|
|
908
|
+
|
|
909
|
+
// Routing - which queue(s) should receive this
|
|
910
|
+
queueName String // notifications, payments, mortgage-steps, accounting, etc
|
|
911
|
+
|
|
912
|
+
// Event payload (all data needed by consumers)
|
|
913
|
+
payload String @db.Text // JSON
|
|
914
|
+
|
|
915
|
+
// Metadata
|
|
916
|
+
occurredAt DateTime @default(now())
|
|
917
|
+
actorId String? // User who triggered the event
|
|
918
|
+
actorRole String? // Role of the actor
|
|
919
|
+
|
|
920
|
+
// Processing status
|
|
921
|
+
status String @default("PENDING") // PENDING, PROCESSING, SENT, FAILED
|
|
922
|
+
processedAt DateTime?
|
|
923
|
+
sentAt DateTime?
|
|
924
|
+
failureCount Int @default(0)
|
|
925
|
+
lastError String? @db.Text
|
|
926
|
+
nextRetryAt DateTime?
|
|
927
|
+
|
|
928
|
+
createdAt DateTime @default(now())
|
|
929
|
+
updatedAt DateTime @updatedAt
|
|
930
|
+
|
|
931
|
+
@@index([status, nextRetryAt])
|
|
932
|
+
@@index([eventType])
|
|
933
|
+
@@index([aggregateType, aggregateId])
|
|
934
|
+
@@index([queueName])
|
|
935
|
+
@@index([occurredAt])
|
|
936
|
+
@@map("domain_events")
|
|
663
937
|
}
|