@valentine-efagene/qshelter-common 2.0.72 → 2.0.73

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.
@@ -51,4 +51,5 @@ export type * from './models/EventHandler.js';
51
51
  export type * from './models/WorkflowEvent.js';
52
52
  export type * from './models/EventHandlerExecution.js';
53
53
  export type * from './models/DomainEvent.js';
54
+ export type * from './models/PropertyTransferRequest.js';
54
55
  export type * from './commonInputTypes.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valentine-efagene/qshelter-common",
3
- "version": "2.0.72",
3
+ "version": "2.0.73",
4
4
  "description": "Shared database schemas and utilities for QShelter services",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -0,0 +1,22 @@
1
+ -- CreateTable
2
+ CREATE TABLE `step_event_attachments` (
3
+ `id` VARCHAR(191) NOT NULL,
4
+ `stepId` VARCHAR(191) NOT NULL,
5
+ `trigger` ENUM('ON_COMPLETE', 'ON_REJECT', 'ON_SUBMIT', 'ON_RESUBMIT', 'ON_START') NOT NULL,
6
+ `handlerId` VARCHAR(191) NOT NULL,
7
+ `priority` INTEGER NOT NULL DEFAULT 100,
8
+ `enabled` BOOLEAN NOT NULL DEFAULT true,
9
+ `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
10
+ `updatedAt` DATETIME(3) NOT NULL,
11
+
12
+ INDEX `step_event_attachments_stepId_idx`(`stepId`),
13
+ INDEX `step_event_attachments_handlerId_idx`(`handlerId`),
14
+ UNIQUE INDEX `step_event_attachments_stepId_handlerId_trigger_key`(`stepId`, `handlerId`, `trigger`),
15
+ PRIMARY KEY (`id`)
16
+ ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
17
+
18
+ -- AddForeignKey
19
+ ALTER TABLE `step_event_attachments` ADD CONSTRAINT `step_event_attachments_stepId_fkey` FOREIGN KEY (`stepId`) REFERENCES `payment_method_phase_steps`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
20
+
21
+ -- AddForeignKey
22
+ ALTER TABLE `step_event_attachments` ADD CONSTRAINT `step_event_attachments_handlerId_fkey` FOREIGN KEY (`handlerId`) REFERENCES `event_handlers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,64 @@
1
+ /*
2
+ Warnings:
3
+
4
+ - A unique constraint covering the columns `[transferredFromId]` on the table `contracts` will be added. If there are existing duplicate values, this will fail.
5
+
6
+ */
7
+ -- AlterTable
8
+ ALTER TABLE `contracts` ADD COLUMN `transferredFromId` VARCHAR(191) NULL,
9
+ MODIFY `status` ENUM('DRAFT', 'PENDING', 'ACTIVE', 'COMPLETED', 'CANCELLED', 'TERMINATED', 'TRANSFERRED') NOT NULL DEFAULT 'DRAFT',
10
+ MODIFY `state` ENUM('DRAFT', 'PENDING', 'ACTIVE', 'COMPLETED', 'CANCELLED', 'TERMINATED', 'TRANSFERRED') NOT NULL DEFAULT 'DRAFT';
11
+
12
+ -- CreateTable
13
+ CREATE TABLE `property_transfer_requests` (
14
+ `id` VARCHAR(191) NOT NULL,
15
+ `tenantId` VARCHAR(191) NOT NULL,
16
+ `sourceContractId` VARCHAR(191) NOT NULL,
17
+ `targetPropertyUnitId` VARCHAR(191) NOT NULL,
18
+ `requestedById` VARCHAR(191) NOT NULL,
19
+ `reviewedById` VARCHAR(191) NULL,
20
+ `status` ENUM('PENDING', 'APPROVED', 'REJECTED', 'IN_PROGRESS', 'COMPLETED', 'FAILED') NOT NULL DEFAULT 'PENDING',
21
+ `reason` TEXT NULL,
22
+ `reviewNotes` TEXT NULL,
23
+ `priceAdjustmentHandling` VARCHAR(191) NULL,
24
+ `sourceTotalAmount` DOUBLE NULL,
25
+ `targetTotalAmount` DOUBLE NULL,
26
+ `priceAdjustment` DOUBLE NULL,
27
+ `paymentsMigrated` INTEGER NULL,
28
+ `targetContractId` VARCHAR(191) NULL,
29
+ `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
30
+ `reviewedAt` DATETIME(3) NULL,
31
+ `completedAt` DATETIME(3) NULL,
32
+ `updatedAt` DATETIME(3) NOT NULL,
33
+
34
+ INDEX `property_transfer_requests_tenantId_idx`(`tenantId`),
35
+ INDEX `property_transfer_requests_sourceContractId_idx`(`sourceContractId`),
36
+ INDEX `property_transfer_requests_targetPropertyUnitId_idx`(`targetPropertyUnitId`),
37
+ INDEX `property_transfer_requests_requestedById_idx`(`requestedById`),
38
+ INDEX `property_transfer_requests_status_idx`(`status`),
39
+ PRIMARY KEY (`id`)
40
+ ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
41
+
42
+ -- CreateIndex
43
+ CREATE UNIQUE INDEX `contracts_transferredFromId_key` ON `contracts`(`transferredFromId`);
44
+
45
+ -- AddForeignKey
46
+ ALTER TABLE `contracts` ADD CONSTRAINT `contracts_transferredFromId_fkey` FOREIGN KEY (`transferredFromId`) REFERENCES `contracts`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
47
+
48
+ -- AddForeignKey
49
+ ALTER TABLE `property_transfer_requests` ADD CONSTRAINT `property_transfer_requests_tenantId_fkey` FOREIGN KEY (`tenantId`) REFERENCES `tenants`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
50
+
51
+ -- AddForeignKey
52
+ ALTER TABLE `property_transfer_requests` ADD CONSTRAINT `property_transfer_requests_sourceContractId_fkey` FOREIGN KEY (`sourceContractId`) REFERENCES `contracts`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
53
+
54
+ -- AddForeignKey
55
+ ALTER TABLE `property_transfer_requests` ADD CONSTRAINT `property_transfer_requests_targetPropertyUnitId_fkey` FOREIGN KEY (`targetPropertyUnitId`) REFERENCES `property_units`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
56
+
57
+ -- AddForeignKey
58
+ ALTER TABLE `property_transfer_requests` ADD CONSTRAINT `property_transfer_requests_requestedById_fkey` FOREIGN KEY (`requestedById`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
59
+
60
+ -- AddForeignKey
61
+ ALTER TABLE `property_transfer_requests` ADD CONSTRAINT `property_transfer_requests_reviewedById_fkey` FOREIGN KEY (`reviewedById`) REFERENCES `users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
62
+
63
+ -- AddForeignKey
64
+ ALTER TABLE `property_transfer_requests` ADD CONSTRAINT `property_transfer_requests_targetContractId_fkey` FOREIGN KEY (`targetContractId`) REFERENCES `contracts`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
@@ -48,6 +48,16 @@ enum ContractStatus {
48
48
  COMPLETED
49
49
  CANCELLED
50
50
  TERMINATED
51
+ TRANSFERRED // Contract was transferred to a different property
52
+ }
53
+
54
+ enum TransferRequestStatus {
55
+ PENDING
56
+ APPROVED
57
+ REJECTED
58
+ IN_PROGRESS
59
+ COMPLETED
60
+ FAILED
51
61
  }
52
62
 
53
63
  enum PhaseStatus {
@@ -292,6 +302,10 @@ model User {
292
302
  offerLettersGenerated OfferLetter[] @relation("OfferLetterGenerator")
293
303
  offerLettersSent OfferLetter[] @relation("OfferLetterSender")
294
304
 
305
+ // Property transfer requests
306
+ transferRequestsSubmitted PropertyTransferRequest[] @relation("TransferRequestor")
307
+ transferRequestsReviewed PropertyTransferRequest[] @relation("TransferReviewer")
308
+
295
309
  @@index([email])
296
310
  @@index([tenantId])
297
311
  @@map("users")
@@ -381,6 +395,9 @@ model Tenant {
381
395
  eventHandlers EventHandler[]
382
396
  workflowEvents WorkflowEvent[]
383
397
 
398
+ // Property transfer requests
399
+ propertyTransferRequests PropertyTransferRequest[]
400
+
384
401
  @@index([subdomain])
385
402
  @@map("tenants")
386
403
  }
@@ -779,6 +796,9 @@ model PropertyUnit {
779
796
  // Relations
780
797
  contracts Contract[]
781
798
 
799
+ // Transfer requests targeting this unit
800
+ transferRequests PropertyTransferRequest[]
801
+
782
802
  @@unique([variantId, unitNumber])
783
803
  @@index([variantId])
784
804
  @@index([status])
@@ -1083,6 +1103,16 @@ model Contract {
1083
1103
  // Payment method change requests for this contract
1084
1104
  paymentMethodChangeRequests PaymentMethodChangeRequest[]
1085
1105
 
1106
+ // Transfer tracking - when a contract is transferred to a different property
1107
+ transferredFromId String? @unique // Source contract if this was created via transfer
1108
+ transferredFrom Contract? @relation("ContractTransfer", fields: [transferredFromId], references: [id])
1109
+ transferredTo Contract? @relation("ContractTransfer")
1110
+
1111
+ // Transfer requests where this contract is the source
1112
+ outgoingTransferRequests PropertyTransferRequest[] @relation("SourceContract")
1113
+ // Transfer requests where this contract is the target (created after approval)
1114
+ incomingTransferRequests PropertyTransferRequest[] @relation("TargetContract")
1115
+
1086
1116
  @@index([tenantId])
1087
1117
  @@index([propertyUnitId])
1088
1118
  @@index([buyerId])
@@ -1974,3 +2004,63 @@ model DomainEvent {
1974
2004
  @@index([occurredAt])
1975
2005
  @@map("domain_events")
1976
2006
  }
2007
+
2008
+ // =============================================================================
2009
+ // Property Transfer Request
2010
+ // =============================================================================
2011
+ // Allows a buyer to request transferring their contract to a different property
2012
+ // while preserving payments, completed workflow steps, and progress.
2013
+ // =============================================================================
2014
+
2015
+ model PropertyTransferRequest {
2016
+ id String @id @default(cuid())
2017
+ tenantId String
2018
+ tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
2019
+
2020
+ // Source contract being transferred
2021
+ sourceContractId String
2022
+ sourceContract Contract @relation("SourceContract", fields: [sourceContractId], references: [id], onDelete: Cascade)
2023
+
2024
+ // Target property unit
2025
+ targetPropertyUnitId String
2026
+ targetPropertyUnit PropertyUnit @relation(fields: [targetPropertyUnitId], references: [id])
2027
+
2028
+ // Requestor (buyer) and reviewer (admin)
2029
+ requestedById String
2030
+ requestedBy User @relation("TransferRequestor", fields: [requestedById], references: [id])
2031
+ reviewedById String?
2032
+ reviewedBy User? @relation("TransferReviewer", fields: [reviewedById], references: [id])
2033
+
2034
+ // Status and workflow
2035
+ status TransferRequestStatus @default(PENDING)
2036
+
2037
+ // Request details
2038
+ reason String? @db.Text // Buyer's reason for transfer
2039
+
2040
+ // Review details
2041
+ reviewNotes String? @db.Text // Admin notes on decision
2042
+ priceAdjustmentHandling String? // How to handle price difference: ADD_TO_MORTGAGE, REQUIRE_PAYMENT, CREDIT_BUYER
2043
+
2044
+ // Computed values
2045
+ sourceTotalAmount Float? // Original contract total
2046
+ targetTotalAmount Float? // New contract total (based on target property)
2047
+ priceAdjustment Float? // Difference (positive = buyer owes more)
2048
+ paymentsMigrated Int? // Number of payments migrated
2049
+
2050
+ // Result - new contract created after approval
2051
+ targetContractId String?
2052
+ targetContract Contract? @relation("TargetContract", fields: [targetContractId], references: [id])
2053
+
2054
+ // Timestamps
2055
+ createdAt DateTime @default(now())
2056
+ reviewedAt DateTime?
2057
+ completedAt DateTime?
2058
+ updatedAt DateTime @updatedAt
2059
+
2060
+ @@index([tenantId])
2061
+ @@index([sourceContractId])
2062
+ @@index([targetPropertyUnitId])
2063
+ @@index([requestedById])
2064
+ @@index([status])
2065
+ @@map("property_transfer_requests")
2066
+ }