@valentine-efagene/qshelter-common 2.0.118 → 2.0.120

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.
@@ -15,14 +15,14 @@ const config = {
15
15
  "clientVersion": "7.2.0",
16
16
  "engineVersion": "0c8ef2ce45c83248ab3df073180d5eda9e8be7a3",
17
17
  "activeProvider": "mysql",
18
- "inlineSchema": "// =============================================================================\n// QSHELTER UNIFIED DATABASE SCHEMA\n// =============================================================================\n// This schema contains all database models for the QShelter platform\n// Organized by domain for better readability\n// =============================================================================\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../generated/client\"\n engineType = \"client\"\n}\n\ndatasource db {\n provider = \"mysql\"\n}\n\n// =============================================================================\n// ENUMS - Database-enforced value constraints\n// =============================================================================\n\nenum PhaseCategory {\n QUESTIONNAIRE // Configurable form fields with validation\n DOCUMENTATION // Document upload and approval workflow\n PAYMENT // Installment-based payment collection\n}\n\nenum PhaseType {\n // QUESTIONNAIRE phases\n PRE_APPROVAL // Eligibility questionnaire (income, employment, etc.)\n UNDERWRITING // System evaluation of eligibility\n\n // DOCUMENTATION phases\n KYC\n VERIFICATION\n\n // PAYMENT phases\n DOWNPAYMENT\n MORTGAGE\n BALLOON\n\n // Generic\n CUSTOM\n}\n\nenum PaymentFrequency {\n MONTHLY\n BIWEEKLY\n WEEKLY\n ONE_TIME\n CUSTOM\n}\n\nenum ApplicationStatus {\n DRAFT\n PENDING\n ACTIVE\n COMPLETED\n CANCELLED\n TERMINATED\n TRANSFERRED // Application was transferred to a different property\n SUPERSEDED // Another buyer locked the unit - this application was outbid\n}\n\nenum TransferRequestStatus {\n PENDING\n APPROVED\n REJECTED\n IN_PROGRESS\n COMPLETED\n FAILED\n}\n\nenum PhaseStatus {\n PENDING\n IN_PROGRESS\n AWAITING_APPROVAL\n ACTIVE\n COMPLETED\n SKIPPED\n FAILED\n SUPERSEDED // Phase replaced by payment method change\n}\n\nenum StepType {\n UPLOAD\n REVIEW\n SIGNATURE\n APPROVAL\n EXTERNAL_CHECK\n WAIT\n GENERATE_DOCUMENT // Triggers document generation (offer letters, contracts, etc.)\n PRE_APPROVAL // Customer answers eligibility questionnaire\n UNDERWRITING // System evaluates DTI, score, eligibility\n}\n\nenum StepStatus {\n PENDING\n IN_PROGRESS\n COMPLETED\n FAILED\n SKIPPED\n NEEDS_RESUBMISSION // User must re-upload or correct something (after rejection)\n ACTION_REQUIRED // User action needed (generic - check actionReason)\n AWAITING_REVIEW // Submitted, waiting for admin/system review\n}\n\n/// When a step event attachment should trigger\nenum StepTrigger {\n ON_COMPLETE // When step is approved/completed\n ON_REJECT // When step is rejected\n ON_SUBMIT // When step is submitted for review\n ON_RESUBMIT // When step is resubmitted after rejection\n ON_START // When step transitions to IN_PROGRESS\n}\n\n/// When a phase event attachment should trigger\nenum PhaseTrigger {\n ON_ACTIVATE // When phase is activated (becomes current)\n ON_COMPLETE // When phase is completed (all steps/payments done)\n ON_CANCEL // When phase is cancelled\n ON_PAYMENT_RECEIVED // When any payment is received (for PAYMENT phases)\n ON_ALL_PAYMENTS_RECEIVED // When all payments in phase are complete\n}\n\nenum InstallmentStatus {\n PENDING\n PAID\n OVERDUE\n PARTIALLY_PAID\n WAIVED\n}\n\nenum PaymentStatus {\n INITIATED\n PENDING\n COMPLETED\n FAILED\n REFUNDED\n}\n\nenum ApprovalDecision {\n APPROVED\n REJECTED\n REQUEST_CHANGES\n}\n\n// =============================================================================\n// CONTRACT TERMINATION / CANCELLATION ENUMS\n// =============================================================================\n\nenum TerminationType {\n BUYER_WITHDRAWAL // Buyer wants to cancel (voluntary)\n SELLER_WITHDRAWAL // Seller/developer cancels\n MUTUAL_AGREEMENT // Both parties agree to terminate\n PAYMENT_DEFAULT // Buyer failed payment obligations\n DOCUMENT_FAILURE // Buyer failed to provide required documents\n FRAUD // Fraudulent activity detected\n FORCE_MAJEURE // External circumstances (disaster, etc.)\n PROPERTY_UNAVAILABLE // Property no longer available\n REGULATORY // Regulatory/legal requirement\n OTHER // Other reasons (with notes)\n}\n\nenum TerminationStatus {\n REQUESTED // Initial request submitted\n PENDING_REVIEW // Awaiting admin review\n PENDING_REFUND // Approved, awaiting refund processing\n REFUND_IN_PROGRESS // Refund being processed\n REFUND_COMPLETED // Refund completed\n COMPLETED // Termination fully executed (no refund or refund done)\n REJECTED // Termination request rejected\n CANCELLED // Termination request was cancelled\n}\n\nenum TerminationInitiator {\n BUYER\n SELLER\n ADMIN\n SYSTEM\n}\n\nenum CompletionCriterion {\n DOCUMENT_APPROVALS\n PAYMENT_AMOUNT\n STEPS_COMPLETED\n}\n\nenum DocumentStatus {\n DRAFT\n PENDING\n PENDING_SIGNATURE\n SENT\n VIEWED\n SIGNED\n APPROVED\n REJECTED\n EXPIRED\n CANCELLED\n}\n\nenum OfferLetterType {\n PROVISIONAL\n FINAL\n}\n\nenum OfferLetterStatus {\n DRAFT\n GENERATED\n SENT\n VIEWED\n SIGNED\n EXPIRED\n CANCELLED\n}\n\nenum ApplicationEventType {\n APPLICATION_CREATED\n APPLICATION_STATE_CHANGED\n PHASE_ACTIVATED\n PHASE_COMPLETED\n STEP_COMPLETED\n STEP_REJECTED\n DOCUMENT_SUBMITTED\n DOCUMENT_APPROVED\n DOCUMENT_REJECTED\n PAYMENT_INITIATED\n PAYMENT_COMPLETED\n PAYMENT_FAILED\n INSTALLMENTS_GENERATED\n APPLICATION_SIGNED\n APPLICATION_TERMINATED\n APPLICATION_TRANSFERRED\n UNDERWRITING_COMPLETED\n OFFER_LETTER_GENERATED\n}\n\nenum ApplicationEventGroup {\n STATE_CHANGE\n PAYMENT\n DOCUMENT\n NOTIFICATION\n WORKFLOW\n}\n\nenum EventActorType {\n USER\n SYSTEM\n WEBHOOK\n ADMIN\n}\n\nenum RefundStatus {\n PENDING\n APPROVED\n REJECTED\n PROCESSING\n COMPLETED\n FAILED\n CANCELLED\n}\n\n// =============================================================================\n// EVENT-DRIVEN WORKFLOW ENUMS\n// =============================================================================\n\n/// Handler Type - What kind of action the handler performs\n/// These are business-friendly names that admins can understand\nenum EventHandlerType {\n SEND_EMAIL // Send an email notification to recipient(s)\n SEND_SMS // Send an SMS text message\n SEND_PUSH // Send a push notification\n CALL_WEBHOOK // Call an external API/webhook\n ADVANCE_WORKFLOW // Advance or complete a workflow step\n RUN_AUTOMATION // Execute internal business logic\n LOCK_UNIT // Lock the property unit for the applicant, supersede competing applications\n}\n\n/// Actor Type - Who triggered an event\nenum ActorType {\n USER\n API_KEY\n SYSTEM\n WEBHOOK\n}\n\n/// Workflow Event Status\nenum WorkflowEventStatus {\n PENDING\n PROCESSING\n COMPLETED\n FAILED\n SKIPPED\n}\n\n/// Handler Execution Status\nenum ExecutionStatus {\n PENDING\n RUNNING\n COMPLETED\n FAILED\n RETRYING\n SKIPPED\n}\n\n/// Permission effect (Allow/Deny)\nenum PermissionEffect {\n ALLOW\n DENY\n}\n\n// =============================================================================\n// USER & AUTH DOMAIN\n// =============================================================================\n\nmodel User {\n id String @id @default(cuid())\n email String @unique\n password String?\n phone String? @unique\n firstName String?\n lastName String?\n isActive Boolean @default(true)\n isEmailVerified Boolean @default(false)\n googleId String?\n avatar String?\n // Legacy: Optional direct tenant association (for backward compatibility)\n // New: Use tenantMemberships for multi-tenant federation\n tenantId String?\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: SetNull)\n // Federated: User can belong to multiple tenants with different roles\n tenantMemberships TenantMembership[]\n // Legacy: Support multiple roles via explicit join table `UserRole`\n userRoles UserRole[]\n walletId String? @unique\n wallet Wallet? @relation(fields: [walletId], references: [id])\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n emailVerifiedAt DateTime?\n emailVerificationToken String?\n lastLoginAt DateTime?\n refreshTokens RefreshToken[]\n passwordResets PasswordReset[]\n suspensions UserSuspension[]\n emailPreferences EmailPreference[]\n deviceEndpoints DeviceEndpoint[]\n socials Social[]\n\n // Relations to other domains\n properties Property[]\n applications Application[] @relation(\"ApplicationBuyer\")\n soldApplications Application[] @relation(\"ApplicationSeller\")\n applicationPayments ApplicationPayment[] @relation(\"ApplicationPayer\")\n\n // Documentation step assignments and approvals\n assignedSteps DocumentationStep[] @relation(\"DocumentationStepAssignee\")\n stepApprovals DocumentationStepApproval[] @relation(\"DocumentationStepApprover\")\n uploadedDocs ApplicationDocument[] @relation(\"DocumentUploader\")\n\n // Payment method changes\n paymentMethodChangeRequests PaymentMethodChangeRequest[] @relation(\"ChangeRequestor\")\n reviewedChangeRequests PaymentMethodChangeRequest[] @relation(\"ChangeReviewer\")\n\n // Contract terminations\n initiatedTerminations ApplicationTermination[] @relation(\"TerminationInitiator\")\n reviewedTerminations ApplicationTermination[] @relation(\"TerminationReviewer\")\n\n // Offer letters\n offerLettersGenerated OfferLetter[] @relation(\"OfferLetterGenerator\")\n offerLettersSent OfferLetter[] @relation(\"OfferLetterSender\")\n\n // Property transfer requests\n transferRequestsSubmitted PropertyTransferRequest[] @relation(\"TransferRequestor\")\n transferRequestsReviewed PropertyTransferRequest[] @relation(\"TransferReviewer\")\n\n // Unified approval requests\n approvalRequestsSubmitted ApprovalRequest[] @relation(\"ApprovalRequestor\")\n approvalRequestsAssigned ApprovalRequest[] @relation(\"ApprovalAssignee\")\n approvalRequestsReviewed ApprovalRequest[] @relation(\"ApprovalReviewer\")\n\n // Contract refunds\n requestedRefunds ApplicationRefund[] @relation(\"RefundRequester\")\n approvedRefunds ApplicationRefund[] @relation(\"RefundApprover\")\n processedRefunds ApplicationRefund[] @relation(\"RefundProcessor\")\n\n @@index([email])\n @@index([tenantId])\n @@map(\"users\")\n}\n\nmodel Role {\n id String @id @default(cuid())\n name String\n description String?\n // Tenant-scoping: NULL = global template, set = tenant-specific role\n tenantId String?\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n // System roles cannot be deleted (admin, user, etc.)\n isSystem Boolean @default(false)\n isActive Boolean @default(true)\n // Legacy: UserRole for backward compatibility\n userRoles UserRole[]\n // New: TenantMembership for federated users\n memberships TenantMembership[]\n permissions RolePermission[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([name, tenantId]) // Unique name per tenant (null tenantId = global)\n @@index([tenantId])\n @@map(\"roles\")\n}\n\n/// Permission defines a path pattern + HTTP methods + effect\n/// Supports path-based authorization matching the authorizer's policy structure\nmodel Permission {\n id String @id @default(cuid())\n name String // Descriptive name: \"Read Users\", \"Manage Properties\"\n description String?\n // Path pattern: /users, /users/:id, /properties/*, etc.\n path String\n // HTTP methods: [\"GET\"], [\"GET\", \"POST\"], [\"*\"] - stored as JSON\n methods Json @default(\"[]\")\n // Allow or Deny this path/methods\n effect PermissionEffect @default(ALLOW)\n // Tenant-scoping: NULL = global template, set = tenant-specific\n tenantId String?\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n // System permissions cannot be deleted\n isSystem Boolean @default(false)\n roles RolePermission[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([path, tenantId]) // Unique path per tenant\n @@index([tenantId])\n @@map(\"permissions\")\n}\n\nmodel RolePermission {\n roleId String\n permissionId String\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@id([roleId, permissionId])\n @@map(\"role_permissions\")\n}\n\n/// Legacy: Direct user-role assignment (global, not tenant-scoped)\n/// @deprecated Use TenantMembership for tenant-scoped role assignments\nmodel UserRole {\n userId String\n roleId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@id([userId, roleId])\n @@map(\"user_roles\")\n}\n\n/// Tenant Membership: Links users to tenants with specific roles\n/// Enables federated users across multiple tenants with different roles per tenant\nmodel TenantMembership {\n id String @id @default(cuid())\n userId String\n tenantId String\n roleId String\n // Whether this membership is active\n isActive Boolean @default(true)\n // Whether this is the user's default tenant (for login without specifying tenant)\n isDefault Boolean @default(false)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n role Role @relation(fields: [roleId], references: [id], onDelete: Restrict)\n\n @@unique([userId, tenantId]) // User can only have one membership per tenant\n @@index([tenantId])\n @@index([userId])\n @@map(\"tenant_memberships\")\n}\n\nmodel Tenant {\n id String @id @default(cuid())\n name String\n subdomain String @unique\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Back-relations for multitenancy\n users User[]\n properties Property[]\n paymentPlans PaymentPlan[]\n documentationPlans DocumentationPlan[]\n paymentMethods PropertyPaymentMethod[]\n applications Application[]\n\n // RBAC: Tenant-scoped roles and permissions\n roles Role[]\n permissions Permission[]\n // Federated user memberships\n memberships TenantMembership[]\n\n // Payment method changes\n paymentMethodChangeRequests PaymentMethodChangeRequest[]\n documentRequirementRules DocumentRequirementRule[]\n\n // Contract terminations\n contractTerminations ApplicationTermination[]\n\n // Offer letters and templates\n documentTemplates DocumentTemplate[]\n offerLetters OfferLetter[]\n\n // API keys for third-party integrations\n apiKeys ApiKey[]\n\n // Event-driven workflow\n eventChannels EventChannel[]\n eventTypes EventType[]\n eventHandlers EventHandler[]\n workflowEvents WorkflowEvent[]\n\n // Property transfer requests\n propertyTransferRequests PropertyTransferRequest[]\n\n // Unified approval requests\n approvalRequests ApprovalRequest[]\n\n // Contract refunds\n contractRefunds ApplicationRefund[]\n propertyPaymentMethodLinks PropertyPaymentMethodLink[]\n propertyPaymentMethodPhases PropertyPaymentMethodPhase[]\n phaseEventAttachments PhaseEventAttachment[]\n paymentMethodPhaseSteps PaymentMethodPhaseStep[]\n stepEventAttachments StepEventAttachment[]\n paymentMethodPhaseDocuments PaymentMethodPhaseDocument[]\n paymentMethodPhaseFields PaymentMethodPhaseField[]\n applicationPhases ApplicationPhase[]\n questionnairePhases QuestionnairePhase[]\n documentationPhases DocumentationPhase[]\n paymentPhases PaymentPhase[]\n questionnaireFields QuestionnaireField[]\n applicationEvents ApplicationEvent[]\n documentationSteps DocumentationStep[]\n documentationStepDocuments DocumentationStepDocument[]\n documentationStepApprovals DocumentationStepApproval[]\n paymentInstallments PaymentInstallment[]\n applicationPayments ApplicationPayment[]\n applicationDocuments ApplicationDocument[]\n propertyMedia PropertyMedia[]\n propertyDocuments PropertyDocument[]\n propertyVariants PropertyVariant[]\n propertyVariantAmenities PropertyVariantAmenity[]\n propertyVariantMedia PropertyVariantMedia[]\n propertyUnits PropertyUnit[]\n propertyAmenities PropertyAmenity[]\n eventHandlerExecutions EventHandlerExecution[]\n amenities Amenity[]\n socials Social[]\n wallets Wallet[]\n transactions Transaction[]\n settings Settings[]\n domainEvents DomainEvent[]\n workflowBlockers WorkflowBlocker[]\n questionnairePlans QuestionnairePlan[]\n\n @@index([subdomain])\n @@map(\"tenants\")\n}\n\n// =============================================================================\n// API KEYS - Third-party integration credentials\n// =============================================================================\n// ApiKey enables partners/integrations to authenticate via token exchange.\n// \n// Flow:\n// 1. Admin creates API key for a partner (POST /api-keys)\n// 2. System generates secret, stores in Secrets Manager, returns id.secret ONCE\n// 3. Partner calls token endpoint with id.secret (POST /api-keys/:id/token)\n// 4. Token endpoint validates via Secrets Manager, returns short-lived JWT\n// 5. Partner uses JWT for API requests; authorizer validates + resolves scopes\n//\n// Security:\n// - Raw secret stored ONLY in AWS Secrets Manager (secretRef = ARN)\n// - Secret returned only once at creation; admin must rotate if lost\n// - Scopes define allowed operations (e.g., [\"contract:read\", \"payment:read\"])\n// - Short-lived JWTs (5-15 min) minimize exposure on key compromise\n// =============================================================================\n\nmodel ApiKey {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Identification\n name String // Human-readable name (e.g., \"Paystack Integration\")\n description String? @db.Text // Optional description\n provider String // Partner/vendor name (e.g., \"paystack\", \"flutterwave\")\n\n // Secret management (NEVER store raw secret in DB)\n secretRef String // AWS Secrets Manager ARN or name\n\n // Permissions - scopes this API key is allowed to request\n // Examples: [\"contract:read\", \"payment:*\", \"property:read\"]\n scopes Json // JSON array of scope strings\n\n // Lifecycle\n enabled Boolean @default(true)\n expiresAt DateTime? // Optional expiration date\n lastUsedAt DateTime? // Updated on each token exchange\n revokedAt DateTime? // Set when key is revoked\n revokedBy String? // User ID who revoked\n\n // Audit\n createdBy String? // User ID who created\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([provider])\n @@index([enabled])\n @@map(\"api_keys\")\n}\n\nmodel RefreshToken {\n id String @id @default(cuid())\n // Use the JWT `jti` for indexed lookups and keep the raw JWT (optional)\n jti String? @unique @db.VarChar(255)\n token String? @db.LongText\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n expiresAt DateTime\n createdAt DateTime @default(now())\n\n @@index([userId])\n @@index([expiresAt])\n @@map(\"refresh_tokens\")\n}\n\nmodel PasswordReset {\n id String @id @default(cuid())\n token String @unique\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n expiresAt DateTime\n usedAt DateTime?\n createdAt DateTime @default(now())\n\n @@index([userId])\n @@index([expiresAt])\n @@map(\"password_resets\")\n}\n\nmodel UserSuspension {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n reason String\n suspendedAt DateTime @default(now())\n expiresAt DateTime?\n liftedAt DateTime?\n\n @@index([userId])\n @@map(\"user_suspensions\")\n}\n\nmodel EmailPreference {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n marketingEmails Boolean @default(true)\n transactionalEmails Boolean @default(true)\n propertyAlerts Boolean @default(true)\n paymentReminders Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@map(\"email_preferences\")\n}\n\nmodel DeviceEndpoint {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n endpoint String // Push notification endpoint\n platform String // ios, android, web\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@map(\"device_endpoints\")\n}\n\nmodel Social {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n provider String // google, facebook, twitter, etc\n socialId String // ID from the social provider\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([provider, socialId])\n @@index([userId])\n @@index([tenantId])\n @@map(\"socials\")\n}\n\nmodel OAuthState {\n id String @id @default(cuid())\n state String @unique\n expiresAt DateTime\n createdAt DateTime @default(now())\n\n @@index([state])\n @@index([expiresAt])\n @@map(\"oauth_states\")\n}\n\nmodel Wallet {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n balance Float @default(0)\n currency String @default(\"USD\")\n user User?\n transactions Transaction[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@map(\"wallets\")\n}\n\nmodel Transaction {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n walletId String\n wallet Wallet @relation(fields: [walletId], references: [id], onDelete: Cascade)\n amount Float\n type String // CREDIT, DEBIT\n status String // PENDING, COMPLETED, FAILED\n reference String?\n description String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([walletId])\n @@index([tenantId])\n @@map(\"transactions\")\n}\n\nmodel Settings {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n key String\n value String @db.Text\n category String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([tenantId, key])\n @@index([category])\n @@index([tenantId])\n @@map(\"settings\")\n}\n\n// =============================================================================\n// PROPERTY DOMAIN\n// =============================================================================\n// Property = listing/project (e.g., \"Sunrise Estate\")\n// PropertyVariant = configuration with specs & price (e.g., \"3-Bed Corner - Finished\")\n// PropertyUnit = individual sellable unit (e.g., \"Unit A1\")\n// =============================================================================\n\nmodel Property {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n title String\n category String // SALE, RENT, LEASE\n propertyType String // APARTMENT, HOUSE, LAND, COMMERCIAL, ESTATE, TOWNHOUSE\n country String\n currency String // USD, NGN, etc\n city String\n district String?\n zipCode String?\n streetAddress String?\n longitude Float?\n latitude Float?\n status String @default(\"DRAFT\") // DRAFT, PUBLISHED, SOLD_OUT, ARCHIVED\n description String? @db.Text\n displayImageId String?\n displayImage PropertyMedia? @relation(\"DisplayImage\", fields: [displayImageId], references: [id], onDelete: SetNull)\n isPublished Boolean @default(false)\n publishedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n documents PropertyDocument[]\n media PropertyMedia[] @relation(\"PropertyMedia\")\n amenities PropertyAmenity[] // Shared amenities (gym, pool, security)\n paymentMethods PropertyPaymentMethodLink[]\n variants PropertyVariant[]\n\n @@index([tenantId])\n @@index([userId])\n @@index([category])\n @@index([propertyType])\n @@index([city])\n @@index([status])\n @@map(\"properties\")\n}\n\nmodel PropertyMedia {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n propertyId String\n property Property @relation(\"PropertyMedia\", fields: [propertyId], references: [id], onDelete: Cascade)\n url String\n type String // IMAGE, VIDEO\n caption String?\n order Int @default(0)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n displayForProperties Property[] @relation(\"DisplayImage\")\n\n @@index([tenantId])\n @@index([propertyId])\n @@map(\"property_media\")\n}\n\nmodel PropertyDocument {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n propertyId String\n property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)\n name String\n url String\n type String // TITLE_DEED, SURVEY_PLAN, etc\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([propertyId])\n @@map(\"property_documents\")\n}\n\nmodel Amenity {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n name String\n category String? // PROPERTY, VARIANT, BOTH - helps filter which amenities to show\n icon String? // Icon name/URL for UI\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n properties PropertyAmenity[]\n variants PropertyVariantAmenity[]\n\n @@unique([tenantId, name]) // Unique per tenant\n @@index([tenantId])\n @@index([category])\n @@map(\"amenities\")\n}\n\n// =============================================================================\n// PROPERTY VARIANT & UNIT MODELS\n// =============================================================================\n\n// PropertyVariant = specific configuration with its own price and amenities\n// e.g., \"3-Bedroom Corner Piece - Fully Finished\", \"2-Bedroom Standard - Carcass\"\nmodel PropertyVariant {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n propertyId String\n property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)\n\n name String // \"Corner Piece - Finished\", \"Standard - Carcass\"\n description String? @db.Text\n\n // Specifications\n nBedrooms Int?\n nBathrooms Int?\n nParkingSpots Int?\n area Float? // Square meters/feet\n\n // Pricing\n price Float\n pricePerSqm Float? // Computed or set manually\n\n // Inventory counters (denormalized for performance, updated via triggers/service)\n totalUnits Int @default(1)\n availableUnits Int @default(1)\n reservedUnits Int @default(0)\n soldUnits Int @default(0)\n\n // Status\n status String @default(\"AVAILABLE\") // AVAILABLE, LOW_STOCK, SOLD_OUT, ARCHIVED\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n amenities PropertyVariantAmenity[]\n units PropertyUnit[]\n media PropertyVariantMedia[]\n\n @@index([tenantId])\n @@index([propertyId])\n @@index([status])\n @@index([price])\n @@map(\"property_variants\")\n}\n\n// PropertyVariantAmenity = amenities specific to a variant\n// e.g., \"Finished Kitchen\", \"Smart Home System\", \"Private Garden\"\nmodel PropertyVariantAmenity {\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n variantId String\n amenityId String\n variant PropertyVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)\n amenity Amenity @relation(fields: [amenityId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@id([variantId, amenityId])\n @@index([tenantId])\n @@map(\"property_variant_amenities\")\n}\n\n// PropertyVariantMedia = images/videos specific to a variant\nmodel PropertyVariantMedia {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n variantId String\n variant PropertyVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)\n url String\n type String // IMAGE, VIDEO, FLOOR_PLAN, 3D_TOUR\n caption String?\n order Int @default(0)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([variantId])\n @@map(\"property_variant_media\")\n}\n\n// PropertyUnit = individual sellable/rentable unit within a variant\n// e.g., \"Unit A1\", \"Block B - Flat 3\", \"Plot 15\"\nmodel PropertyUnit {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n variantId String\n variant PropertyVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)\n\n unitNumber String // \"A1\", \"B-3\", \"Plot 15\"\n floorNumber Int? // For apartments\n blockName String? // \"Block A\", \"Tower 1\"\n\n // Unit-specific overrides (if different from variant)\n priceOverride Float? // If this specific unit has a different price\n areaOverride Float? // If this specific unit has a different area\n notes String? @db.Text // Internal notes about this unit\n\n // Status tracking\n status String @default(\"AVAILABLE\") // AVAILABLE, RESERVED, SOLD, RENTED, UNAVAILABLE\n\n // Reservation/hold\n reservedAt DateTime?\n reservedUntil DateTime?\n reservedById String?\n\n // Ownership tracking (once sold)\n ownerId String?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n applications Application[]\n\n // Transfer requests targeting this unit\n transferRequests PropertyTransferRequest[]\n\n @@unique([variantId, unitNumber])\n @@index([tenantId])\n @@index([variantId])\n @@index([status])\n @@map(\"property_units\")\n}\n\nmodel PropertyAmenity {\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n propertyId String\n amenityId String\n property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)\n amenity Amenity @relation(fields: [amenityId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@id([propertyId, amenityId])\n @@index([tenantId])\n @@map(\"property_amenities\")\n}\n\n// =============================================================================\n// DOCUMENTATION PLAN DOMAIN - Reusable step workflow templates\n// =============================================================================\n\n// DocumentationPlan = reusable structure for documentation workflows\n// Examples: \"Standard KYC\", \"Quick Verification\", \"Full Underwriting\"\nmodel DocumentationPlan {\n id String @id @default(cuid())\n tenantId String? // NULL = global template available to all tenants\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n name String\n description String? @db.Text\n isActive Boolean @default(true)\n\n // Document requirements for this plan\n requiredDocumentTypes Json? // Array of document type strings, e.g., [\"ID_CARD\", \"BANK_STATEMENT\"]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Steps that make up this plan\n steps DocumentationPlanStep[]\n // Used by property payment method phases (templates)\n methodPhases PropertyPaymentMethodPhase[]\n // Used by instantiated documentation phases\n documentationPhases DocumentationPhase[]\n\n @@unique([tenantId, name]) // Unique per tenant, or globally if tenantId is null\n @@index([tenantId])\n @@map(\"documentation_plans\")\n}\n\n// Step template within a DocumentationPlan\nmodel DocumentationPlanStep {\n id String @id @default(cuid())\n planId String\n plan DocumentationPlan @relation(fields: [planId], references: [id], onDelete: Cascade)\n\n name String\n stepType StepType\n order Int\n\n // Optional: which document type this step handles (for UPLOAD steps)\n documentType String?\n metadata Json?\n\n // Document validation rules (for UPLOAD steps)\n isRequired Boolean @default(true)\n description String? @db.Text // Instructions for the user\n maxSizeBytes Int? // Max file size allowed (e.g., 5242880 for 5MB)\n allowedMimeTypes String? // CSV: application/pdf,image/jpeg,image/png\n expiryDays Int? // Document must not be older than X days\n requiresManualReview Boolean @default(false)\n minFiles Int @default(1) // Minimum number of files required\n maxFiles Int @default(1) // Maximum number of files allowed\n\n // Conditional logic - when is this step required?\n // NULL = always required (unconditional)\n // Examples:\n // { \"questionKey\": \"mortgage_type\", \"operator\": \"EQUALS\", \"value\": \"JOINT\" }\n // { \"questionKey\": \"employment_status\", \"operator\": \"IN\", \"values\": [\"SELF_EMPLOYED\", \"BUSINESS_OWNER\"] }\n // { \"all\": [{ \"questionKey\": \"has_spouse\", \"operator\": \"EQUALS\", \"value\": \"YES\" }, { \"questionKey\": \"spouse_employed\", \"operator\": \"EQUALS\", \"value\": \"YES\" }] }\n condition Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([planId])\n @@map(\"documentation_plan_steps\")\n}\n\n// =============================================================================\n// QUESTIONNAIRE PLAN DOMAIN - Reusable form templates with scoring\n// =============================================================================\n// QuestionnairePlan = reusable structure for prequalification/screening forms\n// Examples: \"Mortgage Prequalification\", \"Affordability Assessment\", \"Risk Screening\"\n// =============================================================================\n\nmodel QuestionnairePlan {\n id String @id @default(cuid())\n tenantId String? // NULL = global template available to all tenants\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n name String\n description String? @db.Text\n version Int @default(1)\n isActive Boolean @default(true)\n\n // Scoring configuration\n passingScore Int? // Minimum score to pass (null = no auto-scoring)\n scoringStrategy ScoringStrategy @default(SUM)\n autoDecisionEnabled Boolean @default(false) // Auto-pass/fail based on score\n\n // Metadata\n estimatedMinutes Int? // Estimated time to complete\n category QuestionnaireCategory @default(PREQUALIFICATION)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Questions that make up this plan\n questions QuestionnairePlanQuestion[]\n\n // Used by property payment method phases (templates)\n methodPhases PropertyPaymentMethodPhase[]\n\n // Used by instantiated questionnaire phases\n questionnairePhases QuestionnairePhase[]\n\n @@unique([tenantId, name, version])\n @@index([tenantId])\n @@index([category])\n @@map(\"questionnaire_plans\")\n}\n\n// Question template within a QuestionnairePlan\nmodel QuestionnairePlanQuestion {\n id String @id @default(cuid())\n questionnairePlanId String\n questionnairePlan QuestionnairePlan @relation(fields: [questionnairePlanId], references: [id], onDelete: Cascade)\n\n // Question identification\n questionKey String // Unique key for this question (e.g., \"annual_income\")\n questionText String @db.Text // The actual question text\n helpText String? @db.Text // Optional help/tooltip text\n\n // Field configuration\n questionType QuestionType\n order Int\n\n // Validation\n isRequired Boolean @default(true)\n validationRules Json? // { min: 0, max: 1000000, pattern: \"^[0-9]+$\" }\n\n // Options for SELECT/MULTI_SELECT/RADIO\n // [{ value: \"employed\", label: \"Employed\", score: 10 }, ...]\n options Json?\n\n // Scoring\n scoreWeight Int @default(1) // Multiplier for this question's score\n scoringRules Json? // { \"employed\": 10, \"self_employed\": 7, \"unemployed\": 0 } or ranges\n\n // Conditional logic (branching)\n // { \"questionKey\": \"employment_status\", \"equals\": \"employed\" }\n showIf Json?\n\n // Metadata for grouping\n category String? // Group questions (e.g., \"income\", \"employment\", \"property\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([questionnairePlanId, questionKey])\n @@index([questionnairePlanId])\n @@map(\"questionnaire_plan_questions\")\n}\n\n// =============================================================================\n// PAYMENT PLAN DOMAIN - Reusable installment structure templates\n// =============================================================================\n\n// PaymentPlan = reusable structure for how payments are scheduled\n// Examples: \"Monthly360\" (360 monthly payments), \"Weekly52\", \"OneTime\"\nmodel PaymentPlan {\n id String @id @default(cuid())\n tenantId String? // NULL = global template available to all tenants\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n name String\n description String? @db.Text\n isActive Boolean @default(true)\n\n // Structure configuration\n paymentFrequency PaymentFrequency\n customFrequencyDays Int?\n numberOfInstallments Int? // Fixed number (1 for one-time, 360 for 30yr monthly) - NULL if flexible\n calculateInterestDaily Boolean @default(false)\n gracePeriodDays Int @default(0)\n\n // Flexible term configuration (for user-selectable duration like mortgages)\n // If these are set, numberOfInstallments is ignored and user selects within range\n allowFlexibleTerm Boolean @default(false) // true = user can select term within range\n minTermMonths Int? // e.g., 60 (5 years minimum)\n maxTermMonths Int? // e.g., 360 (30 years maximum)\n termStepMonths Int? // e.g., 12 (increments of 1 year) - NULL = any month allowed\n\n // Age-based constraints (for mortgage eligibility)\n maxAgeAtMaturity Int? // e.g., 65 - user's age + term cannot exceed this\n\n // Fund collection behavior\n // true = we collect funds via wallet/gateway (e.g., downpayment)\n // false = external payment, we only track/reconcile (e.g., bank mortgage)\n collectFunds Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Used by property payment method phases (templates)\n methodPhases PropertyPaymentMethodPhase[]\n // Used by instantiated payment phases\n paymentPhases PaymentPhase[]\n\n @@unique([tenantId, name]) // Unique per tenant, or globally if tenantId is null\n @@index([tenantId])\n @@map(\"payment_plans\")\n}\n\n// =============================================================================\n// PROPERTY PAYMENT METHOD DOMAIN - Product offerings per property\n// =============================================================================\n\n// PropertyPaymentMethod = how a property can be purchased (e.g., \"Standard Mortgage\", \"Cash\", \"Rent-to-Own\")\nmodel PropertyPaymentMethod {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n name String // \"Standard Mortgage\", \"Flexible Payment\", \"Cash Purchase\"\n description String? @db.Text\n isActive Boolean @default(true)\n\n // Global method configuration\n allowEarlyPayoff Boolean @default(true)\n earlyPayoffPenaltyRate Float?\n autoActivatePhases Boolean @default(true)\n requiresManualApproval Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Many-to-many with properties\n properties PropertyPaymentMethodLink[]\n // Phases that make up this method (templates)\n phases PropertyPaymentMethodPhase[]\n // Contracts using this method\n applications Application[]\n\n // Payment method change tracking\n changeRequestsFrom PaymentMethodChangeRequest[] @relation(\"ChangeFromMethod\")\n changeRequestsTo PaymentMethodChangeRequest[] @relation(\"ChangeToMethod\")\n\n // Document requirement rules\n documentRules DocumentRequirementRule[] @relation(\"RulePaymentMethod\")\n changeRulesFrom DocumentRequirementRule[] @relation(\"RuleFromMethod\")\n changeRulesTo DocumentRequirementRule[] @relation(\"RuleToMethod\")\n\n @@unique([tenantId, name]) // Unique per tenant\n @@index([tenantId])\n @@map(\"property_payment_methods\")\n}\n\n// Many-to-many link between Property and PaymentMethod\nmodel PropertyPaymentMethodLink {\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n propertyId String\n property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)\n paymentMethodId String\n paymentMethod PropertyPaymentMethod @relation(fields: [paymentMethodId], references: [id], onDelete: Cascade)\n\n // Method-specific overrides for this property\n isDefault Boolean @default(false)\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n\n @@id([propertyId, paymentMethodId])\n @@index([tenantId])\n @@map(\"property_payment_method_links\")\n}\n\n// Phase template within a PropertyPaymentMethod (e.g., documentation, downpayment, mortgage)\n// phaseCategory determines the FSM type: DOCUMENTATION or PAYMENT\nmodel PropertyPaymentMethodPhase {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n paymentMethodId String\n paymentMethod PropertyPaymentMethod @relation(fields: [paymentMethodId], references: [id], onDelete: Cascade)\n\n // Plan references (only one should be set based on phaseCategory)\n paymentPlanId String? // Only for PAYMENT phases\n paymentPlan PaymentPlan? @relation(fields: [paymentPlanId], references: [id])\n documentationPlanId String? // Only for DOCUMENTATION phases\n documentationPlan DocumentationPlan? @relation(fields: [documentationPlanId], references: [id])\n questionnairePlanId String? // Only for QUESTIONNAIRE phases\n questionnairePlan QuestionnairePlan? @relation(fields: [questionnairePlanId], references: [id])\n\n name String\n description String? @db.Text\n\n // Phase classification (DB-enforced enums)\n phaseCategory PhaseCategory\n phaseType PhaseType\n order Int\n\n // Financial configuration (for PAYMENT phases)\n interestRate Float?\n percentOfPrice Float? // e.g., 10.0 for 10% downpayment\n\n // Fund collection behavior (inherited from PaymentPlan if not set)\n // true = we collect funds via wallet/gateway (e.g., downpayment)\n // false = external payment, we only track/reconcile (e.g., bank mortgage)\n collectFunds Boolean? // null = inherit from PaymentPlan\n\n // Activation rules\n requiresPreviousPhaseCompletion Boolean @default(true)\n minimumCompletionPercentage Float?\n completionCriterion CompletionCriterion?\n\n // Unit locking configuration\n // If true, completing this phase locks the unit for the applicant\n // Only one phase per payment method should have this enabled\n lockUnitOnComplete Boolean @default(false)\n\n // Snapshots for audit (original config at creation time)\n // These are still needed for inline definitions (backward compatibility)\n stepDefinitionsSnapshot Json?\n requiredDocumentSnapshot Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Normalized child tables (for DOCUMENTATION phases - inline definitions)\n steps PaymentMethodPhaseStep[]\n requiredDocuments PaymentMethodPhaseDocument[]\n // Normalized child tables (for QUESTIONNAIRE phases)\n questionnaireFields PaymentMethodPhaseField[]\n // Event attachments - handlers that fire on phase transitions\n eventAttachments PhaseEventAttachment[]\n // Application phases created from this template\n applicationPhases ApplicationPhase[]\n\n @@index([tenantId])\n @@index([paymentMethodId])\n @@index([paymentPlanId])\n @@index([documentationPlanId])\n @@index([questionnairePlanId])\n @@index([phaseCategory])\n @@map(\"property_payment_method_phases\")\n}\n\n/// Phase Event Attachment - Links event handlers to phase template triggers\n/// When a phase transitions (complete, payment received, etc.), attached handlers fire\nmodel PhaseEventAttachment {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String\n phase PropertyPaymentMethodPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n /// When this handler should fire\n trigger PhaseTrigger\n\n /// The event handler to execute\n handlerId String\n handler EventHandler @relation(fields: [handlerId], references: [id], onDelete: Cascade)\n\n /// Order of execution (lower = first)\n priority Int @default(100)\n\n /// Whether this attachment is active\n enabled Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([phaseId, handlerId, trigger])\n @@index([tenantId])\n @@index([phaseId])\n @@index([handlerId])\n @@map(\"phase_event_attachments\")\n}\n\n// Step template within a DOCUMENTATION phase\nmodel PaymentMethodPhaseStep {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String\n phase PropertyPaymentMethodPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n name String\n stepType StepType\n order Int\n\n metadata Json?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Event attachments - handlers that fire on step transitions\n eventAttachments StepEventAttachment[]\n\n @@index([tenantId])\n @@index([phaseId])\n @@map(\"payment_method_phase_steps\")\n}\n\n/// Step Event Attachment - Links event handlers to step template triggers\n/// When a step transitions (complete, reject, etc.), attached handlers fire\nmodel StepEventAttachment {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n stepId String\n step PaymentMethodPhaseStep @relation(fields: [stepId], references: [id], onDelete: Cascade)\n\n /// When this handler should fire\n trigger StepTrigger\n\n /// The event handler to execute\n handlerId String\n handler EventHandler @relation(fields: [handlerId], references: [id], onDelete: Cascade)\n\n /// Order of execution (lower = first)\n priority Int @default(100)\n\n /// Whether this attachment is active\n enabled Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([stepId, handlerId, trigger])\n @@index([tenantId])\n @@index([stepId])\n @@index([handlerId])\n @@map(\"step_event_attachments\")\n}\n\n// Required document within a DOCUMENTATION phase\nmodel PaymentMethodPhaseDocument {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String\n phase PropertyPaymentMethodPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n documentType String\n isRequired Boolean @default(true)\n description String? @db.Text\n allowedMimeTypes String? // CSV: application/pdf,image/jpeg\n maxSizeBytes Int?\n\n metadata Json?\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([phaseId, documentType])\n @@map(\"payment_method_phase_documents\")\n}\n\n// =============================================================================\n// QUESTIONNAIRE FIELD TYPES - For QUESTIONNAIRE phases\n// =============================================================================\n\nenum FieldType {\n TEXT // Short text input\n TEXTAREA // Long text input\n NUMBER // Numeric input (with optional min/max)\n CURRENCY // Currency input (validated as money)\n EMAIL // Email validation\n PHONE // Phone number validation\n DATE // Date picker\n SELECT // Dropdown/single select\n MULTI_SELECT // Multiple selection\n CHECKBOX // Boolean yes/no\n RADIO // Radio button group\n FILE // File upload (single)\n}\n\n// =============================================================================\n// QUESTIONNAIRE PLAN ENUMS - For scoring and categorization\n// =============================================================================\n\nenum QuestionType {\n TEXT\n NUMBER\n CURRENCY\n DATE\n SELECT\n MULTI_SELECT\n RADIO\n CHECKBOX\n FILE_UPLOAD\n PHONE\n EMAIL\n ADDRESS\n PERCENTAGE\n YEARS_MONTHS\n}\n\nenum ScoringStrategy {\n SUM // Add up all scores\n AVERAGE // Average of all scores\n WEIGHTED_SUM // Sum with weights (score * weight)\n MIN_ALL // Must meet minimum on all questions\n CUSTOM // Use custom scoring function\n}\n\nenum QuestionnaireCategory {\n PREQUALIFICATION // Initial eligibility screening\n AFFORDABILITY // Income/expense assessment\n PROPERTY_INTENT // What property are they looking for\n RISK_ASSESSMENT // Credit/risk questions\n COMPLIANCE // KYC/AML questions\n CUSTOM\n}\n\n// Questionnaire field template within a QUESTIONNAIRE phase\nmodel PaymentMethodPhaseField {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String\n phase PropertyPaymentMethodPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n // Field identification\n name String // Internal field name (e.g., \"monthly_income\")\n label String // Display label (e.g., \"Monthly Income\")\n description String? @db.Text // Help text for the field\n placeholder String? // Placeholder text\n\n // Field configuration\n fieldType FieldType\n isRequired Boolean @default(true)\n order Int\n\n // Validation rules (JSON schema-like)\n // Examples:\n // NUMBER: { \"min\": 0, \"max\": 1000000 }\n // TEXT: { \"minLength\": 2, \"maxLength\": 100, \"pattern\": \"^[A-Za-z]+$\" }\n // SELECT: { \"options\": [{\"value\": \"employed\", \"label\": \"Employed\"}, ...] }\n // DATE: { \"minDate\": \"now\", \"maxDate\": \"+30d\" }\n validation Json?\n\n // For conditional display (e.g., show if another field has a certain value)\n // { \"field\": \"employment_status\", \"operator\": \"equals\", \"value\": \"employed\" }\n displayCondition Json?\n\n // Default value (JSON to support any type)\n defaultValue Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([phaseId, name])\n @@index([tenantId])\n @@index([phaseId])\n @@map(\"payment_method_phase_fields\")\n}\n\n// =============================================================================\n// CONTRACT DOMAIN - Unified agreement model (replaces Mortgage, PurchasePlan, etc.)\n// =============================================================================\n// Application is the canonical agreement. \"Mortgage\" is just a product configuration\n// that creates an Application with specific phases (documentation, downpayment, long-term payment).\n// Phases can be QUESTIONNAIRE, DOCUMENTATION, or PAYMENT.\n// =============================================================================\n\nmodel Application {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n // Link to specific unit being purchased/rented\n propertyUnitId String\n propertyUnit PropertyUnit @relation(fields: [propertyUnitId], references: [id], onDelete: Cascade)\n buyerId String\n buyer User @relation(\"ApplicationBuyer\", fields: [buyerId], references: [id], onDelete: Cascade)\n sellerId String?\n seller User? @relation(\"ApplicationSeller\", fields: [sellerId], references: [id])\n paymentMethodId String? // PropertyPaymentMethod used to create this contract\n paymentMethod PropertyPaymentMethod? @relation(fields: [paymentMethodId], references: [id])\n\n // Contract identification\n applicationNumber String @unique\n title String\n description String? @db.Text\n applicationType String // Admin-defined: MORTGAGE, INSTALLMENT, RENT_TO_OWN, CASH, LEASE, etc.\n\n // Contract value (negotiated from unit price)\n totalAmount Float\n\n // FSM state (DB-enforced enum)\n status ApplicationStatus @default(DRAFT)\n currentPhaseId String?\n currentPhase ApplicationPhase? @relation(\"CurrentPhase\", fields: [currentPhaseId], references: [id])\n\n // Timing\n nextPaymentDueDate DateTime?\n lastReminderSentAt DateTime?\n startDate DateTime?\n endDate DateTime?\n signedAt DateTime?\n terminatedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n phases ApplicationPhase[]\n documents ApplicationDocument[]\n payments ApplicationPayment[]\n terminations ApplicationTermination[]\n offerLetters OfferLetter[]\n\n // Payment method change requests for this contract\n paymentMethodChangeRequests PaymentMethodChangeRequest[]\n\n // Transfer tracking - when a contract is transferred to a different property\n transferredFromId String? @unique // Source contract if this was created via transfer\n transferredFrom Application? @relation(\"ApplicationTransfer\", fields: [transferredFromId], references: [id])\n transferredTo Application? @relation(\"ApplicationTransfer\")\n\n // Supersede tracking - when another buyer locks the unit\n // If status is SUPERSEDED, this references the application that took the unit\n supersededById String?\n supersededBy Application? @relation(\"ApplicationSuperseded\", fields: [supersededById], references: [id])\n supersededAt DateTime?\n supersededApplications Application[] @relation(\"ApplicationSuperseded\")\n\n // Transfer requests where this contract is the source\n outgoingTransferRequests PropertyTransferRequest[] @relation(\"SourceApplication\")\n // Transfer requests where this contract is the target (created after approval)\n incomingTransferRequests PropertyTransferRequest[] @relation(\"TargetApplication\")\n\n // Audit trail\n events ApplicationEvent[]\n\n // Refund requests\n refunds ApplicationRefund[]\n\n @@index([tenantId])\n @@index([propertyUnitId])\n @@index([buyerId])\n @@index([sellerId])\n @@index([paymentMethodId])\n @@index([status])\n @@index([currentPhaseId])\n @@index([supersededById])\n @@map(\"applications\")\n}\n\n// =============================================================================\n// CONTRACT REFUNDS - Track refund requests for overpayments or cancellations\n// =============================================================================\nmodel ApplicationRefund {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n\n amount Float\n reason String @db.Text\n status RefundStatus @default(PENDING)\n\n // Who requested the refund\n requestedById String\n requestedBy User @relation(\"RefundRequester\", fields: [requestedById], references: [id])\n\n // Who approved/rejected the refund\n approvedById String?\n approvedBy User? @relation(\"RefundApprover\", fields: [approvedById], references: [id])\n\n // Who processed the refund (finance team)\n processedById String?\n processedBy User? @relation(\"RefundProcessor\", fields: [processedById], references: [id])\n\n // Refund payment details\n paymentMethod String? // BANK_TRANSFER, CHEQUE, MOBILE_MONEY, etc.\n referenceNumber String? // Bank/payment reference\n recipientName String?\n recipientAccount String?\n recipientBank String?\n\n // Timestamps\n requestedAt DateTime @default(now())\n approvedAt DateTime?\n rejectedAt DateTime?\n processedAt DateTime?\n\n // Additional notes\n approvalNotes String? @db.Text\n rejectionNotes String? @db.Text\n processingNotes String? @db.Text\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([applicationId])\n @@index([status])\n @@index([tenantId])\n @@index([requestedById])\n @@map(\"application_refunds\")\n}\n\n// Phase within a contract - can be DOCUMENTATION or PAYMENT type\n// Admin names phases freely (e.g., \"KYC Documents\", \"Downpayment\", \"Monthly Mortgage\")\n// =============================================================================\n// CONTRACT PHASE - Base model with polymorphic extensions\n// =============================================================================\n// ApplicationPhase is the base table with shared fields only.\n// Each phase has exactly ONE extension table based on phaseCategory:\n// - QUESTIONNAIRE → QuestionnairePhase\n// - DOCUMENTATION → DocumentationPhase\n// - PAYMENT → PaymentPhase\n// This eliminates nullable field pollution and makes the schema self-documenting.\n// =============================================================================\n\nmodel ApplicationPhase {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n\n // Reference to the phase template this was instantiated from\n phaseTemplateId String?\n phaseTemplate PropertyPaymentMethodPhase? @relation(fields: [phaseTemplateId], references: [id], onDelete: SetNull)\n\n // Admin-defined naming\n name String\n description String? @db.Text\n\n // Phase classification (DB-enforced enums)\n phaseCategory PhaseCategory\n phaseType PhaseType\n order Int\n\n // FSM state for this phase (DB-enforced enum)\n status PhaseStatus @default(PENDING)\n\n // Timing (shared across all phase types)\n dueDate DateTime?\n startDate DateTime?\n endDate DateTime?\n activatedAt DateTime?\n completedAt DateTime?\n\n // Activation rules (shared)\n requiresPreviousPhaseCompletion Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Polymorphic extensions (exactly one will be populated based on phaseCategory)\n questionnairePhase QuestionnairePhase?\n documentationPhase DocumentationPhase?\n paymentPhase PaymentPhase?\n\n // Payments can be linked to any phase type (for tracking)\n payments ApplicationPayment[]\n\n // Back-relation for applications where this is the current phase\n currentForApplications Application[] @relation(\"CurrentPhase\")\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([phaseTemplateId])\n @@index([phaseCategory])\n @@index([status])\n @@index([order])\n @@map(\"application_phases\")\n}\n\n// =============================================================================\n// QUESTIONNAIRE PHASE DATA - Extension for QUESTIONNAIRE phases\n// =============================================================================\n// Collects form data from users (eligibility, pre-approval, underwriting inputs)\n// =============================================================================\n\nmodel QuestionnairePhase {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String @unique\n phase ApplicationPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n // Questionnaire plan reference (if created from a plan)\n questionnairePlanId String?\n questionnairePlan QuestionnairePlan? @relation(fields: [questionnairePlanId], references: [id])\n\n // Progress tracking\n completedFieldsCount Int @default(0)\n totalFieldsCount Int @default(0)\n\n // Scoring results (from QuestionnairePlan scoring)\n totalScore Int?\n passingScore Int? // Copied from plan at creation\n passed Boolean?\n scoredAt DateTime?\n\n // Computed results (for UNDERWRITING phases)\n underwritingScore Float?\n debtToIncomeRatio Float?\n underwritingDecision String? // APPROVED, CONDITIONAL, DECLINED\n underwritingNotes String? @db.Text\n\n // Snapshot of field definitions at creation\n fieldsSnapshot Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Child records\n fields QuestionnaireField[]\n\n @@index([tenantId])\n @@index([phaseId])\n @@index([questionnairePlanId])\n @@map(\"questionnaire_phases\")\n}\n\n// =============================================================================\n// DOCUMENTATION PHASE DATA - Extension for DOCUMENTATION phases\n// =============================================================================\n// Manages document upload/approval workflow with FSM steps\n// =============================================================================\n\nmodel DocumentationPhase {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String @unique\n phase ApplicationPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n // Documentation plan reference (if created from a plan)\n documentationPlanId String?\n documentationPlan DocumentationPlan? @relation(fields: [documentationPlanId], references: [id])\n\n // Current step pointer for UX and orchestration\n currentStepId String?\n currentStep DocumentationStep? @relation(\"CurrentStep\", fields: [currentStepId], references: [id])\n\n // Progress counters\n approvedDocumentsCount Int @default(0)\n requiredDocumentsCount Int @default(0)\n completedStepsCount Int @default(0)\n totalStepsCount Int @default(0)\n\n // Completion criteria\n minimumCompletionPercentage Float?\n completionCriterion CompletionCriterion?\n\n // Snapshots for audit\n stepDefinitionsSnapshot Json?\n requiredDocumentSnapshot Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Child records\n steps DocumentationStep[]\n\n @@index([tenantId])\n @@index([phaseId])\n @@index([currentStepId])\n @@map(\"documentation_phases\")\n}\n\n// =============================================================================\n// PAYMENT PHASE DATA - Extension for PAYMENT phases\n// =============================================================================\n// Manages installment-based payment collection\n// =============================================================================\n\nmodel PaymentPhase {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String @unique\n phase ApplicationPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n // Payment plan reference\n paymentPlanId String?\n paymentPlan PaymentPlan? @relation(fields: [paymentPlanId], references: [id])\n\n // Financial details\n totalAmount Float\n paidAmount Float @default(0)\n interestRate Float @default(0)\n\n // User-selected term (for flexible-term plans like mortgages)\n // These are set when user selects their preferred term at application time\n selectedTermMonths Int? // User's chosen term (e.g., 240 for 20 years)\n numberOfInstallments Int? // Calculated from selectedTermMonths and frequency\n\n // Fund collection behavior\n // true = we collect funds via wallet/gateway (e.g., downpayment)\n // false = external payment, we only track/reconcile (e.g., bank mortgage)\n collectFunds Boolean @default(true)\n\n // Completion criteria\n minimumCompletionPercentage Float?\n\n // Snapshot for audit\n paymentPlanSnapshot Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Child records\n installments PaymentInstallment[]\n\n @@index([tenantId])\n @@index([phaseId])\n @@index([paymentPlanId])\n @@map(\"payment_phases\")\n}\n\n// =============================================================================\n// QUESTIONNAIRE FIELDS - Instantiated fields within QUESTIONNAIRE phases\n// =============================================================================\n// When a contract is created from a payment method template, questionnaire field\n// templates are copied to QuestionnaireField records. Users submit answers here.\n// =============================================================================\n\nmodel QuestionnaireField {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n questionnairePhaseId String\n questionnairePhase QuestionnairePhase @relation(fields: [questionnairePhaseId], references: [id], onDelete: Cascade)\n\n // Field identification (copied from template)\n name String // Internal field name (e.g., \"monthly_income\")\n label String // Display label (e.g., \"Monthly Income\")\n description String? @db.Text\n placeholder String?\n\n // Field configuration (copied from template)\n fieldType FieldType\n isRequired Boolean @default(true)\n order Int\n\n // Validation rules (copied from template)\n validation Json?\n displayCondition Json?\n defaultValue Json?\n\n // User's submitted answer (JSON to support any type)\n // TEXT: \"John Doe\"\n // NUMBER/CURRENCY: 500000\n // SELECT: \"employed\"\n // MULTI_SELECT: [\"option1\", \"option2\"]\n // CHECKBOX: true\n // DATE: \"2024-01-15\"\n answer Json?\n\n // Validation status\n isValid Boolean @default(false)\n validationErrors Json? // Array of error messages if invalid\n\n // Timestamps\n submittedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([questionnairePhaseId, name])\n @@index([tenantId])\n @@index([questionnairePhaseId])\n @@map(\"questionnaire_fields\")\n}\n\n// =============================================================================\n// CONTRACT EVENTS - Audit trail for contract lifecycle\n// =============================================================================\n// Tracks all significant events in a contract's lifecycle for audit, compliance,\n// and debugging. Unlike DomainEvent (which is for inter-service communication),\n// ApplicationEvent is purely for historical tracking and state machine transitions.\n// =============================================================================\nmodel ApplicationEvent {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n\n // Event classification\n eventType ApplicationEventType\n eventGroup ApplicationEventGroup?\n\n // For state transitions (optional - only populated for APPLICATION_STATE_CHANGED events)\n fromState String?\n toState String?\n trigger String?\n\n // Event payload (all event-specific data)\n data Json?\n\n // Actor tracking\n actorId String?\n actorType EventActorType?\n\n // Timing\n occurredAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([eventType])\n @@index([eventGroup])\n @@index([occurredAt])\n @@map(\"application_events\")\n}\n\n// Steps within a DOCUMENTATION phase (FSM for document collection/approval)\nmodel DocumentationStep {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n documentationPhaseId String\n documentationPhase DocumentationPhase @relation(fields: [documentationPhaseId], references: [id], onDelete: Cascade)\n\n name String\n description String? @db.Text\n stepType StepType\n order Int\n\n status StepStatus @default(PENDING)\n\n // =========================================================================\n // USER ACTION TRACKING - For rejection/resubmission flows\n // =========================================================================\n // When status is NEEDS_RESUBMISSION or ACTION_REQUIRED, this explains why.\n // Populated from DocumentationStepApproval.comment on rejection.\n actionReason String? @db.Text\n\n // Number of times this step has been submitted (for tracking resubmissions)\n submissionCount Int @default(0)\n\n // Last submission timestamp (for tracking resubmission timing)\n lastSubmittedAt DateTime?\n\n // Configuration metadata (for GENERATE_DOCUMENT steps, etc.)\n metadata Json?\n\n // Assignment\n assigneeId String?\n assignee User? @relation(\"DocumentationStepAssignee\", fields: [assigneeId], references: [id])\n\n // Required document types for UPLOAD steps (normalized)\n requiredDocuments DocumentationStepDocument[]\n\n // Timing\n dueDate DateTime?\n completedAt DateTime?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n approvals DocumentationStepApproval[]\n currentForPhase DocumentationPhase[] @relation(\"CurrentStep\")\n\n @@index([tenantId])\n @@index([documentationPhaseId])\n @@index([status])\n @@index([order])\n @@map(\"documentation_steps\")\n}\n\n// Required documents for a step (normalized from CSV)\nmodel DocumentationStepDocument {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n stepId String\n step DocumentationStep @relation(fields: [stepId], references: [id], onDelete: Cascade)\n\n documentType String\n isRequired Boolean @default(true)\n\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([stepId, documentType])\n @@map(\"documentation_step_documents\")\n}\n\n// Approvals for documentation steps\nmodel DocumentationStepApproval {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n stepId String\n step DocumentationStep @relation(fields: [stepId], references: [id], onDelete: Cascade)\n approverId String?\n approver User? @relation(\"DocumentationStepApprover\", fields: [approverId], references: [id])\n\n decision ApprovalDecision\n comment String? @db.Text\n decidedAt DateTime @default(now())\n\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([stepId])\n @@map(\"documentation_step_approvals\")\n}\n\n// Installments within a PAYMENT phase\nmodel PaymentInstallment {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n paymentPhaseId String\n paymentPhase PaymentPhase @relation(fields: [paymentPhaseId], references: [id], onDelete: Cascade)\n\n installmentNumber Int\n\n amount Float\n principalAmount Float @default(0)\n interestAmount Float @default(0)\n\n dueDate DateTime\n status InstallmentStatus @default(PENDING)\n\n paidAmount Float @default(0)\n paidDate DateTime?\n\n lateFee Float @default(0)\n lateFeeWaived Boolean @default(false)\n gracePeriodDays Int @default(0)\n gracePeriodEndDate DateTime?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n payments ApplicationPayment[]\n\n @@index([tenantId])\n @@index([paymentPhaseId])\n @@index([dueDate])\n @@index([status])\n @@map(\"payment_installments\")\n}\n\n// Unified payment record for contracts\nmodel ApplicationPayment {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n phaseId String?\n phase ApplicationPhase? @relation(fields: [phaseId], references: [id])\n installmentId String?\n installment PaymentInstallment? @relation(fields: [installmentId], references: [id])\n payerId String?\n payer User? @relation(\"ApplicationPayer\", fields: [payerId], references: [id])\n\n amount Float\n principalAmount Float @default(0)\n interestAmount Float @default(0)\n lateFeeAmount Float @default(0)\n\n paymentMethod String // BANK_TRANSFER, CREDIT_CARD, WALLET, CASH, CHECK\n status PaymentStatus @default(INITIATED)\n\n reference String? @unique\n gatewayResponse String? @db.Text // JSON\n\n processedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([phaseId])\n @@index([installmentId])\n @@index([payerId])\n @@index([status])\n @@index([reference])\n @@map(\"application_payments\")\n}\n\n// Contract documents (owned by contract, linked to phases/steps as needed)\nmodel ApplicationDocument {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n phaseId String? // Optional link to specific phase\n stepId String? // Optional link to specific step\n\n name String\n url String\n type String // ID, BANK_STATEMENT, INCOME_PROOF, TITLE_DEED, SIGNATURE, etc.\n uploadedById String?\n uploadedBy User? @relation(\"DocumentUploader\", fields: [uploadedById], references: [id])\n\n status DocumentStatus @default(PENDING)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([phaseId])\n @@index([stepId])\n @@index([type])\n @@index([status])\n @@map(\"application_documents\")\n}\n\n// =============================================================================\n// OFFER LETTERS - Provisional and Final offer documents\n// =============================================================================\n\nmodel DocumentTemplate {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n name String // \"Provisional Offer Letter\", \"Final Offer Letter\"\n code String // PROVISIONAL_OFFER, FINAL_OFFER\n description String?\n version Int @default(1)\n\n // Template content (Handlebars)\n htmlTemplate String @db.Text\n cssStyles String? @db.Text\n\n // Merge field definitions for UI\n mergeFields Json? // [{name, type, required, description}]\n\n isActive Boolean @default(true)\n isDefault Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n offerLetters OfferLetter[]\n\n @@unique([tenantId, code, version])\n @@index([tenantId])\n @@index([code])\n @@map(\"document_templates\")\n}\n\nmodel OfferLetter {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n\n // Template used (optional - documents-service may handle default selection)\n templateId String?\n template DocumentTemplate? @relation(fields: [templateId], references: [id])\n\n // Letter details\n letterNumber String @unique // OL-XXXXXX\n type OfferLetterType\n status OfferLetterStatus @default(DRAFT)\n\n // Generated document\n htmlContent String? @db.Text // Rendered HTML\n pdfUrl String? // S3 URL of generated PDF\n pdfKey String? // S3 key for deletion/access\n\n // Merge data used (snapshot for audit)\n mergeData Json? // All data merged into template\n\n // Signing workflow\n sentAt DateTime?\n viewedAt DateTime?\n signedAt DateTime?\n signatureIp String?\n signatureData Json? // {method, timestamp, metadata}\n\n // Validity\n expiresAt DateTime?\n expiredAt DateTime?\n cancelledAt DateTime?\n cancelReason String?\n\n // Audit\n generatedById String?\n generatedBy User? @relation(\"OfferLetterGenerator\", fields: [generatedById], references: [id])\n sentById String?\n sentBy User? @relation(\"OfferLetterSender\", fields: [sentById], references: [id])\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([type])\n @@index([status])\n @@map(\"offer_letters\")\n}\n\n// =============================================================================\n// CONTRACT TERMINATION - Full lifecycle for cancellation/termination\n// =============================================================================\n// Tracks termination requests from initiation through refund completion.\n// Industry-standard flow:\n// 1. Request created (by buyer/seller/admin/system)\n// 2. Admin reviews (if required by policy)\n// 3. Financial settlement calculated (refunds, penalties, forfeitures)\n// 4. Refund processed (if applicable)\n// 5. Contract marked terminated, unit released\n// =============================================================================\n\nmodel ApplicationTermination {\n id String @id @default(cuid())\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Request identification\n requestNumber String @unique // TRM-XXXXXX\n\n // Who initiated and why\n initiatedBy TerminationInitiator\n initiatorId String? // userId if BUYER/SELLER/ADMIN\n initiator User? @relation(\"TerminationInitiator\", fields: [initiatorId], references: [id])\n type TerminationType\n reason String? @db.Text\n supportingDocs Json? // [{type, url, uploadedAt}]\n\n // Workflow status\n status TerminationStatus @default(REQUESTED)\n requiresApproval Boolean @default(true)\n autoApproveEligible Boolean @default(false) // Pre-signature, no payments\n\n // Admin review\n reviewedBy String?\n reviewer User? @relation(\"TerminationReviewer\", fields: [reviewedBy], references: [id])\n reviewedAt DateTime?\n reviewNotes String? @db.Text\n rejectionReason String? @db.Text\n\n // Financial snapshot at time of request\n applicationSnapshot Json // Full contract state snapshot\n totalApplicationAmount Float\n totalPaidToDate Float\n outstandingBalance Float\n\n // Settlement calculation\n refundableAmount Float @default(0) // Amount eligible for refund\n penaltyAmount Float @default(0) // Penalties/fees to deduct\n forfeitedAmount Float @default(0) // Amount forfeited (non-refundable deposits)\n adminFeeAmount Float @default(0) // Processing fees\n netRefundAmount Float @default(0) // refundableAmount - penaltyAmount - adminFeeAmount\n settlementNotes String? @db.Text\n\n // Refund processing\n refundStatus RefundStatus @default(PENDING)\n refundReference String? // Payment gateway reference\n refundMethod String? // ORIGINAL_METHOD, BANK_TRANSFER, CHECK, WALLET\n refundAccountDetails Json? // Encrypted bank details if needed\n refundInitiatedAt DateTime?\n refundCompletedAt DateTime?\n refundFailureReason String? @db.Text\n\n // Property unit handling\n unitReleasedAt DateTime?\n unitReservedForId String? // If unit being held for another buyer\n\n // Timing\n requestedAt DateTime @default(now())\n approvedAt DateTime?\n executedAt DateTime?\n completedAt DateTime?\n cancelledAt DateTime?\n\n // Idempotency and audit\n idempotencyKey String? @unique\n metadata Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([applicationId])\n @@index([tenantId])\n @@index([status])\n @@index([type])\n @@index([initiatorId])\n @@index([requestedAt])\n @@map(\"application_terminations\")\n}\n\n// =============================================================================\n// PAYMENT METHOD CHANGE REQUEST - Mid-contract payment method changes\n// =============================================================================\n// When a user wants to change their payment method after contract creation,\n// this aggregate tracks the request, required documentation, approvals, and\n// final execution. Different from-to combinations may require different docs.\n// =============================================================================\n\nenum PaymentMethodChangeStatus {\n PENDING_DOCUMENTS\n DOCUMENTS_SUBMITTED\n UNDER_REVIEW\n APPROVED\n REJECTED\n EXECUTED\n CANCELLED\n}\n\nmodel PaymentMethodChangeRequest {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n\n // The change being requested\n fromPaymentMethodId String\n fromPaymentMethod PropertyPaymentMethod @relation(\"ChangeFromMethod\", fields: [fromPaymentMethodId], references: [id])\n toPaymentMethodId String\n toPaymentMethod PropertyPaymentMethod @relation(\"ChangeToMethod\", fields: [toPaymentMethodId], references: [id])\n\n // Who requested and why\n requestorId String\n requestor User @relation(\"ChangeRequestor\", fields: [requestorId], references: [id])\n reason String? @db.Text\n\n // Documentation requirements (determined by DocumentRequirementRule)\n requiredDocumentTypes String? // CSV: BANK_STATEMENT,INCOME_PROOF,NEW_EMPLOYER_LETTER\n submittedDocuments Json? // [{type, s3Key, uploadedAt, status}]\n\n // Financial impact assessment\n currentOutstanding Float? // Outstanding balance at time of request\n newTermMonths Int? // New term if applicable\n newInterestRate Float? // New rate if applicable\n newMonthlyPayment Float? // Projected new payment\n penaltyAmount Float? // Early change penalty if applicable\n financialImpactNotes String? @db.Text\n\n // Status and workflow\n status PaymentMethodChangeStatus @default(PENDING_DOCUMENTS)\n reviewerId String?\n reviewer User? @relation(\"ChangeReviewer\", fields: [reviewerId], references: [id])\n reviewNotes String? @db.Text\n reviewedAt DateTime?\n\n // Execution details\n executedAt DateTime?\n previousPhaseData Json? // Snapshot of phases before change\n newPhaseData Json? // New phases created after change\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([status])\n @@index([requestorId])\n @@map(\"payment_method_change_requests\")\n}\n\n// =============================================================================\n// DOCUMENT REQUIREMENT RULES - Configurable document requirements\n// =============================================================================\n// Admins can configure which documents are required for specific scenarios:\n// - Prequalification for a payment method type\n// - Contract phases\n// - Payment method changes (from-to combinations)\n// This allows tenants to customize documentation workflows per product.\n// =============================================================================\n\nenum DocumentRequirementContext {\n APPLICATION_PHASE // During a contract phase\n PAYMENT_METHOD_CHANGE // When changing payment method mid-contract\n}\n\nmodel DocumentRequirementRule {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Rule context\n context DocumentRequirementContext\n\n // Scoping (which situations this rule applies to)\n // For PREQUALIFICATION: paymentMethodId\n // For APPLICATION_PHASE: phaseType\n // For PAYMENT_METHOD_CHANGE: fromMethodId + toMethodId\n paymentMethodId String?\n paymentMethod PropertyPaymentMethod? @relation(\"RulePaymentMethod\", fields: [paymentMethodId], references: [id])\n phaseType String? // KYC, VERIFICATION, DOWNPAYMENT, etc.\n fromPaymentMethodId String?\n fromPaymentMethod PropertyPaymentMethod? @relation(\"RuleFromMethod\", fields: [fromPaymentMethodId], references: [id])\n toPaymentMethodId String?\n toPaymentMethod PropertyPaymentMethod? @relation(\"RuleToMethod\", fields: [toPaymentMethodId], references: [id])\n\n // Document requirements\n documentType String // ID_CARD, PASSPORT, BANK_STATEMENT, INCOME_PROOF, etc.\n isRequired Boolean @default(true)\n description String? // Instructions for the user\n maxSizeBytes Int? // Max file size allowed\n allowedMimeTypes String? // CSV: application/pdf,image/jpeg,image/png\n\n // Validation rules\n expiryDays Int? // Document must not be older than X days\n requiresManualReview Boolean @default(false)\n\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([context])\n @@index([paymentMethodId])\n @@index([phaseType])\n @@index([fromPaymentMethodId, toPaymentMethodId])\n @@map(\"document_requirement_rules\")\n}\n\n// =============================================================================\n// EVENT-DRIVEN WORKFLOW CONFIGURATION\n// =============================================================================\n// This system allows admins to configure event channels, types, and handlers\n// for a flexible, configurable event-driven workflow system.\n//\n// Architecture:\n// 1. EventChannel - Logical grouping of events (e.g., \"contracts\", \"payments\")\n// 2. EventType - Specific event types (e.g., \"DOCUMENT_UPLOADED\", \"STEP_COMPLETED\")\n// 3. EventHandler - What to do when an event fires (webhook, internal call, etc.)\n// 4. WorkflowEvent - Actual event instances (audit log)\n// 5. EventHandlerExecution - Log of handler executions\n// =============================================================================\n\n/// Event Channel - A logical grouping of events\n/// Channels help organize events and route them to appropriate handlers\nmodel EventChannel {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n /// Unique code for the channel (e.g., \"CONTRACTS\", \"PAYMENTS\")\n code String\n /// Human-readable name\n name String\n /// Description of what this channel handles\n description String? @db.Text\n\n /// Whether this channel is active\n enabled Boolean @default(true)\n\n /// Event types that belong to this channel\n eventTypes EventType[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([tenantId, code])\n @@index([tenantId])\n @@map(\"event_channels\")\n}\n\n/// Event Type - Defines a type of event that can occur\n/// Each event type belongs to a channel and can have multiple handlers\nmodel EventType {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n /// The channel this event type belongs to\n channelId String\n channel EventChannel @relation(fields: [channelId], references: [id], onDelete: Cascade)\n\n /// Unique code for this event type (e.g., \"DOCUMENT_UPLOADED\")\n code String\n /// Human-readable name\n name String\n /// Description of when this event fires\n description String? @db.Text\n\n /// JSON schema for event payload validation (optional)\n payloadSchema Json?\n\n /// Whether this event type is active\n enabled Boolean @default(true)\n\n /// Handlers subscribed to this event type\n handlers EventHandler[]\n\n /// Actual event instances of this type\n events WorkflowEvent[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([tenantId, code])\n @@unique([channelId, code])\n @@index([tenantId])\n @@index([channelId])\n @@map(\"event_types\")\n}\n\n/// Event Handler - Defines what should happen when an event fires\n/// Handlers can be internal (call a service), external (webhook), or workflow triggers\nmodel EventHandler {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n /// The event type this handler responds to\n eventTypeId String\n eventType EventType @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)\n\n /// Human-readable name\n name String\n /// Description of what this handler does\n description String? @db.Text\n\n /// Handler type determines how the event is processed\n handlerType EventHandlerType\n\n /// Configuration for the handler (JSON, depends on handlerType)\n /// INTERNAL: { \"service\": \"contract\", \"method\": \"completeStep\" }\n /// WEBHOOK: { \"url\": \"https://...\", \"method\": \"POST\", \"headers\": {...} }\n /// WORKFLOW: { \"workflowId\": \"...\", \"action\": \"advance\" }\n /// NOTIFICATION: { \"template\": \"...\", \"channels\": [\"email\", \"sms\"] }\n config Json\n\n /// Order of execution when multiple handlers exist (lower = first)\n priority Int @default(100)\n\n /// Whether this handler is active\n enabled Boolean @default(true)\n\n /// Retry configuration\n maxRetries Int @default(3)\n retryDelayMs Int @default(1000)\n\n /// Filter condition (JSONPath expression) to conditionally run\n /// e.g., \"$.payload.status == 'approved'\"\n filterCondition String? @db.Text\n\n /// Handler execution logs\n executions EventHandlerExecution[]\n\n /// Step attachments - steps that have attached this handler\n stepAttachments StepEventAttachment[]\n\n /// Phase attachments - phases that have attached this handler\n phaseAttachments PhaseEventAttachment[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([eventTypeId])\n @@index([handlerType])\n @@map(\"event_handlers\")\n}\n\n/// Workflow Event - An actual event instance that occurred\n/// This is the audit log of all events in the system\nmodel WorkflowEvent {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n /// The type of this event\n eventTypeId String\n eventType EventType @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)\n\n /// The event payload (actual data)\n payload Json\n\n /// Optional correlation ID to link related events\n correlationId String?\n\n /// Optional causation ID (which event caused this one)\n causationId String?\n\n /// Source of the event (service name, user action, etc.)\n source String\n\n /// Actor who triggered the event (user ID, API key ID, \"system\")\n actorId String?\n actorType ActorType @default(SYSTEM)\n\n /// Event status\n status WorkflowEventStatus @default(PENDING)\n\n /// Error message if processing failed\n error String? @db.Text\n\n /// When the event was processed\n processedAt DateTime?\n\n /// Handler executions for this event\n executions EventHandlerExecution[]\n\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([eventTypeId])\n @@index([correlationId])\n @@index([causationId])\n @@index([status])\n @@index([createdAt])\n @@map(\"workflow_events\")\n}\n\n/// Event Handler Execution - Log of a handler processing an event\nmodel EventHandlerExecution {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n /// The event being processed\n eventId String\n event WorkflowEvent @relation(fields: [eventId], references: [id], onDelete: Cascade)\n\n /// The handler that processed this event\n handlerId String\n handler EventHandler @relation(fields: [handlerId], references: [id], onDelete: Cascade)\n\n /// Execution status\n status ExecutionStatus @default(PENDING)\n\n /// Attempt number (1 for first try, increments on retry)\n attempt Int @default(1)\n\n /// Input to the handler (may be transformed payload)\n input Json?\n\n /// Output from the handler\n output Json?\n\n /// Error details if failed\n error String? @db.Text\n errorCode String?\n\n /// Timing\n startedAt DateTime?\n completedAt DateTime?\n durationMs Int?\n\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([eventId])\n @@index([handlerId])\n @@index([status])\n @@map(\"event_handler_executions\")\n}\n\n// =============================================================================\n// EVENT OUTBOX - For guaranteed event delivery to SQS queues\n// =============================================================================\n\nmodel DomainEvent {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Event identification\n eventType String // MORTGAGE.CREATED, PHASE.ACTIVATED, PAYMENT.COMPLETED, etc\n aggregateType String // Mortgage, MortgagePhase, MortgagePayment, Property, etc\n aggregateId String\n\n // Routing - which queue(s) should receive this\n queueName String // notifications, payments, mortgage-steps, accounting, etc\n\n // Event payload (all data needed by consumers)\n payload String @db.Text // JSON\n\n // Metadata\n occurredAt DateTime @default(now())\n actorId String? // User who triggered the event\n actorRole String? // Role of the actor\n\n // Processing status\n status String @default(\"PENDING\") // PENDING, PROCESSING, SENT, FAILED\n processedAt DateTime?\n sentAt DateTime?\n failureCount Int @default(0)\n lastError String? @db.Text\n nextRetryAt DateTime?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([status, nextRetryAt])\n @@index([eventType])\n @@index([aggregateType, aggregateId])\n @@index([queueName])\n @@index([occurredAt])\n @@map(\"domain_events\")\n}\n\n// =============================================================================\n// Property Transfer Request\n// =============================================================================\n// Allows a buyer to request transferring their contract to a different property.\n// \n// TRANSFER PAYMENT FLOW:\n// 1. All payments from source contract are refunded to buyer's wallet (single credit transaction)\n// 2. Source contract marked TRANSFERRED, unit released\n// 3. New contract created for target unit with zero payments\n// 4. Buyer can optionally apply wallet balance as equity during new mortgage application\n//\n// This ensures clean accounting: each contract has isolated payment history,\n// wallet serves as intermediary, and buyer retains full credit.\n// =============================================================================\n\nmodel PropertyTransferRequest {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Source contract being transferred\n sourceApplicationId String\n sourceApplication Application @relation(\"SourceApplication\", fields: [sourceApplicationId], references: [id], onDelete: Cascade)\n\n // Target property unit\n targetPropertyUnitId String\n targetPropertyUnit PropertyUnit @relation(fields: [targetPropertyUnitId], references: [id])\n\n // Requestor (buyer) and reviewer (admin)\n requestedById String\n requestedBy User @relation(\"TransferRequestor\", fields: [requestedById], references: [id])\n reviewedById String?\n reviewedBy User? @relation(\"TransferReviewer\", fields: [reviewedById], references: [id])\n\n // Status and workflow\n status TransferRequestStatus @default(PENDING)\n\n // Request details\n reason String? @db.Text // Buyer's reason for transfer\n\n // Review details\n reviewNotes String? @db.Text // Admin notes on decision\n priceAdjustmentHandling String? // How to handle price difference: ADD_TO_MORTGAGE, REQUIRE_PAYMENT, CREDIT_BUYER\n\n // Computed values\n sourceTotalAmount Float? // Original contract total\n targetTotalAmount Float? // New contract total (based on target property)\n priceAdjustment Float? // Difference (positive = buyer owes more)\n\n // Wallet refund tracking (payments refunded to wallet, NOT carried over)\n refundedAmount Float? // Total amount refunded to wallet\n refundTransactionId String? // Reference to wallet Transaction record\n refundedAt DateTime?\n\n // Result - new contract created after approval\n targetApplicationId String?\n targetApplication Application? @relation(\"TargetApplication\", fields: [targetApplicationId], references: [id])\n\n // Timestamps\n createdAt DateTime @default(now())\n reviewedAt DateTime?\n completedAt DateTime?\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([sourceApplicationId])\n @@index([targetPropertyUnitId])\n @@index([requestedById])\n @@index([status])\n @@map(\"property_transfer_requests\")\n}\n\n// =============================================================================\n// UNIFIED APPROVAL REQUESTS\n// =============================================================================\n\nenum ApprovalRequestType {\n PROPERTY_TRANSFER // Property unit transfer between contracts\n PROPERTY_UPDATE // Property/unit listing update requiring approval\n USER_WORKFLOW // User workflow step approval\n CREDIT_CHECK // Credit check result review\n APPLICATION_TERMINATION // Contract termination approval\n REFUND_APPROVAL // Refund request approval\n}\n\nenum ApprovalRequestStatus {\n PENDING // Awaiting review\n IN_REVIEW // Assigned to reviewer\n APPROVED // Approved by reviewer\n REJECTED // Rejected by reviewer\n CANCELLED // Cancelled by requestor\n EXPIRED // Auto-expired (if TTL configured)\n}\n\nenum ApprovalRequestPriority {\n LOW\n NORMAL\n HIGH\n URGENT\n}\n\n// Polymorphic approval request model for unified admin dashboard\nmodel ApprovalRequest {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Request type and status\n type ApprovalRequestType\n status ApprovalRequestStatus @default(PENDING)\n priority ApprovalRequestPriority @default(NORMAL)\n\n // Polymorphic reference to the entity requiring approval\n entityType String // e.g., \"PropertyTransferRequest\", \"PropertyUnit\", \"User\"\n entityId String // ID of the referenced entity\n\n // Request metadata\n title String @db.VarChar(255) // Human-readable title for the request\n description String? @db.Text // Detailed description\n\n // Payload for any additional context (JSON)\n payload Json? // Flexible data storage for type-specific details\n\n // Requestor - who created the request\n requestedById String\n requestedBy User @relation(\"ApprovalRequestor\", fields: [requestedById], references: [id])\n\n // Assignee - admin/reviewer assigned to handle this request\n assigneeId String?\n assignee User? @relation(\"ApprovalAssignee\", fields: [assigneeId], references: [id])\n\n // Reviewer - who made the final decision (may differ from assignee)\n reviewedById String?\n reviewedBy User? @relation(\"ApprovalReviewer\", fields: [reviewedById], references: [id])\n\n // Review details\n reviewNotes String? @db.Text // Reviewer's notes/comments\n decision ApprovalDecision? // APPROVED, REJECTED, REQUEST_CHANGES\n\n // Expiration\n expiresAt DateTime? // Optional TTL for auto-expiration\n\n // Timestamps\n createdAt DateTime @default(now())\n assignedAt DateTime? // When assigned to reviewer\n reviewedAt DateTime? // When decision was made\n completedAt DateTime? // When fully processed\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([type])\n @@index([status])\n @@index([priority])\n @@index([entityType, entityId])\n @@index([requestedById])\n @@index([assigneeId])\n @@index([createdAt])\n @@index([type, status]) // Efficient queries for approval dashboard\n @@map(\"approval_requests\")\n}\n\n// =============================================================================\n// WORKFLOW BLOCKER TRACKING - Analytics for workflow delays\n// =============================================================================\n// Tracks who is blocking the workflow at any point, enabling analytics like:\n// - Average time customers take to upload documents\n// - Average time admins take to review/approve\n// - Most common bottleneck steps\n// - SLA compliance tracking\n// - Customer service intervention triggers\n// =============================================================================\n\n/// Who is responsible for the current workflow block\nenum BlockerActor {\n CUSTOMER // Customer action required (upload, sign, pay)\n ADMIN // Admin action required (review, approve, reject)\n SYSTEM // System processing (auto-generation, external checks)\n EXTERNAL // External party (bank, government, third-party verification)\n}\n\n/// Category of action that is blocking workflow\nenum BlockerCategory {\n UPLOAD // Document upload needed\n RESUBMISSION // Document resubmission after rejection\n SIGNATURE // Signature required\n REVIEW // Admin review needed\n APPROVAL // Admin approval needed\n PAYMENT // Payment required\n PROCESSING // System processing\n EXTERNAL_CHECK // External verification\n QUESTIONNAIRE // Form/questionnaire completion\n}\n\n/// Urgency level for prioritization and SLA tracking\nenum BlockerUrgency {\n LOW // No immediate deadline\n NORMAL // Standard processing\n HIGH // Approaching deadline or overdue\n CRITICAL // Significantly overdue or business-critical\n}\n\n/// Workflow Blocker - Records who is blocking workflow and for how long\nmodel WorkflowBlocker {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Reference to the blocked entity\n applicationId String\n phaseId String?\n stepId String?\n\n // Actor and action details\n blockerActor BlockerActor\n blockerCategory BlockerCategory\n urgency BlockerUrgency @default(NORMAL)\n\n // Human-readable descriptions\n actionRequired String @db.VarChar(500) // What action is needed\n context String? @db.Text // Additional context\n\n // SLA tracking\n expectedByDate DateTime? // When this action should be completed\n isOverdue Boolean @default(false)\n overdueAt DateTime? // When it became overdue\n\n // Duration tracking\n startedAt DateTime @default(now()) // When this block started\n resolvedAt DateTime? // When it was resolved\n durationMs Int? // Calculated duration on resolution\n\n // Resolution details\n resolvedByActor String? // Who resolved it (userId or \"SYSTEM\")\n resolutionTrigger String? // What action resolved it (e.g., \"DOCUMENT_UPLOADED\", \"STEP_COMPLETED\")\n\n // Reminder tracking (for customer service)\n reminderCount Int @default(0) // Number of reminders sent\n lastReminderAt DateTime? // Last reminder timestamp\n nextReminderAt DateTime? // Scheduled next reminder\n\n // Metadata for additional analytics\n metadata Json? // Flexible data: { documentType, stepType, phaseType, etc. }\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([phaseId])\n @@index([stepId])\n @@index([blockerActor])\n @@index([blockerCategory])\n @@index([urgency])\n @@index([isOverdue])\n @@index([startedAt])\n @@index([resolvedAt])\n @@index([tenantId, blockerActor, resolvedAt]) // For \"open blockers by actor\" queries\n @@index([tenantId, blockerCategory, resolvedAt]) // For \"open blockers by category\" queries\n @@index([tenantId, isOverdue, blockerActor]) // For SLA violation queries\n @@map(\"workflow_blockers\")\n}\n",
18
+ "inlineSchema": "// =============================================================================\n// QSHELTER UNIFIED DATABASE SCHEMA\n// =============================================================================\n// This schema contains all database models for the QShelter platform\n// Organized by domain for better readability\n// =============================================================================\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../generated/client\"\n engineType = \"client\"\n}\n\ndatasource db {\n provider = \"mysql\"\n}\n\n// =============================================================================\n// ENUMS - Database-enforced value constraints\n// =============================================================================\n\nenum PhaseCategory {\n QUESTIONNAIRE // Configurable form fields with validation\n DOCUMENTATION // Document upload and approval workflow\n PAYMENT // Installment-based payment collection\n}\n\nenum PhaseType {\n // QUESTIONNAIRE phases\n PRE_APPROVAL // Eligibility questionnaire (income, employment, etc.)\n UNDERWRITING // System evaluation of eligibility\n\n // DOCUMENTATION phases\n KYC\n VERIFICATION\n\n // PAYMENT phases\n DOWNPAYMENT\n MORTGAGE\n BALLOON\n\n // Generic\n CUSTOM\n}\n\nenum PaymentFrequency {\n MONTHLY\n BIWEEKLY\n WEEKLY\n ONE_TIME\n CUSTOM\n}\n\nenum ApplicationStatus {\n DRAFT\n PENDING\n ACTIVE\n COMPLETED\n CANCELLED\n TERMINATED\n TRANSFERRED // Application was transferred to a different property\n SUPERSEDED // Another buyer locked the unit - this application was outbid\n}\n\nenum TransferRequestStatus {\n PENDING\n APPROVED\n REJECTED\n IN_PROGRESS\n COMPLETED\n FAILED\n}\n\nenum PhaseStatus {\n PENDING\n IN_PROGRESS\n AWAITING_APPROVAL\n ACTIVE\n COMPLETED\n SKIPPED\n FAILED\n SUPERSEDED // Phase replaced by payment method change\n}\n\nenum StepType {\n UPLOAD\n REVIEW\n SIGNATURE\n APPROVAL\n EXTERNAL_CHECK\n WAIT\n GENERATE_DOCUMENT // Triggers document generation (offer letters, contracts, etc.)\n PRE_APPROVAL // Customer answers eligibility questionnaire\n UNDERWRITING // System evaluates DTI, score, eligibility\n GATE // Explicit human gate requiring action (approve, acknowledge, consent)\n}\n\n/// Who must perform a GATE step action\nenum GateActor {\n ADMIN // Any tenant admin\n CUSTOMER // The application buyer\n SPECIFIC_ROLE // Requires gateRoleId to be set\n}\n\n/// What action is required for a GATE step\nenum GateAction {\n APPROVE // Approve/Reject decision (default)\n ACKNOWLEDGE // Just acknowledge, no reject option\n CONFIRM // Confirm details are correct\n CONSENT // Legal consent (e.g., terms & conditions)\n}\n\n/// What happens when a GATE step is rejected\nenum GateRejectBehavior {\n BLOCK // Block progression, admin must resolve\n RESTART_STEP // Reset this step to pending\n RESTART_PHASE // Reset entire phase\n TERMINATE // Terminate the application\n}\n\nenum StepStatus {\n PENDING\n IN_PROGRESS\n COMPLETED\n FAILED\n SKIPPED\n NEEDS_RESUBMISSION // User must re-upload or correct something (after rejection)\n ACTION_REQUIRED // User action needed (generic - check actionReason)\n AWAITING_REVIEW // Submitted, waiting for admin/system review\n}\n\n/// When a step event attachment should trigger\nenum StepTrigger {\n ON_COMPLETE // When step is approved/completed\n ON_REJECT // When step is rejected\n ON_SUBMIT // When step is submitted for review\n ON_RESUBMIT // When step is resubmitted after rejection\n ON_START // When step transitions to IN_PROGRESS\n}\n\n/// When a phase event attachment should trigger\nenum PhaseTrigger {\n ON_ACTIVATE // When phase is activated (becomes current)\n ON_COMPLETE // When phase is completed (all steps/payments done)\n ON_CANCEL // When phase is cancelled\n ON_PAYMENT_RECEIVED // When any payment is received (for PAYMENT phases)\n ON_ALL_PAYMENTS_RECEIVED // When all payments in phase are complete\n}\n\nenum InstallmentStatus {\n PENDING\n PAID\n OVERDUE\n PARTIALLY_PAID\n WAIVED\n}\n\nenum PaymentStatus {\n INITIATED\n PENDING\n COMPLETED\n FAILED\n REFUNDED\n}\n\nenum ApprovalDecision {\n APPROVED\n REJECTED\n REQUEST_CHANGES\n}\n\n// =============================================================================\n// CONTRACT TERMINATION / CANCELLATION ENUMS\n// =============================================================================\n\nenum TerminationType {\n BUYER_WITHDRAWAL // Buyer wants to cancel (voluntary)\n SELLER_WITHDRAWAL // Seller/developer cancels\n MUTUAL_AGREEMENT // Both parties agree to terminate\n PAYMENT_DEFAULT // Buyer failed payment obligations\n DOCUMENT_FAILURE // Buyer failed to provide required documents\n FRAUD // Fraudulent activity detected\n FORCE_MAJEURE // External circumstances (disaster, etc.)\n PROPERTY_UNAVAILABLE // Property no longer available\n REGULATORY // Regulatory/legal requirement\n OTHER // Other reasons (with notes)\n}\n\nenum TerminationStatus {\n REQUESTED // Initial request submitted\n PENDING_REVIEW // Awaiting admin review\n PENDING_REFUND // Approved, awaiting refund processing\n REFUND_IN_PROGRESS // Refund being processed\n REFUND_COMPLETED // Refund completed\n COMPLETED // Termination fully executed (no refund or refund done)\n REJECTED // Termination request rejected\n CANCELLED // Termination request was cancelled\n}\n\nenum TerminationInitiator {\n BUYER\n SELLER\n ADMIN\n SYSTEM\n}\n\nenum CompletionCriterion {\n DOCUMENT_APPROVALS\n PAYMENT_AMOUNT\n STEPS_COMPLETED\n}\n\nenum DocumentStatus {\n DRAFT\n PENDING\n PENDING_SIGNATURE\n SENT\n VIEWED\n SIGNED\n APPROVED\n REJECTED\n EXPIRED\n CANCELLED\n}\n\nenum OfferLetterType {\n PROVISIONAL\n FINAL\n}\n\nenum OfferLetterStatus {\n DRAFT\n GENERATED\n SENT\n VIEWED\n SIGNED\n EXPIRED\n CANCELLED\n}\n\nenum ApplicationEventType {\n APPLICATION_CREATED\n APPLICATION_STATE_CHANGED\n PHASE_ACTIVATED\n PHASE_COMPLETED\n STEP_COMPLETED\n STEP_REJECTED\n DOCUMENT_SUBMITTED\n DOCUMENT_APPROVED\n DOCUMENT_REJECTED\n PAYMENT_INITIATED\n PAYMENT_COMPLETED\n PAYMENT_FAILED\n INSTALLMENTS_GENERATED\n APPLICATION_SIGNED\n APPLICATION_TERMINATED\n APPLICATION_TRANSFERRED\n UNDERWRITING_COMPLETED\n OFFER_LETTER_GENERATED\n}\n\nenum ApplicationEventGroup {\n STATE_CHANGE\n PAYMENT\n DOCUMENT\n NOTIFICATION\n WORKFLOW\n}\n\nenum EventActorType {\n USER\n SYSTEM\n WEBHOOK\n ADMIN\n}\n\nenum RefundStatus {\n PENDING\n APPROVED\n REJECTED\n PROCESSING\n COMPLETED\n FAILED\n CANCELLED\n}\n\n// =============================================================================\n// EVENT-DRIVEN WORKFLOW ENUMS\n// =============================================================================\n\n/// Handler Type - What kind of action the handler performs\n/// These are business-friendly names that admins can understand\nenum EventHandlerType {\n SEND_EMAIL // Send an email notification to recipient(s)\n SEND_SMS // Send an SMS text message\n SEND_PUSH // Send a push notification\n CALL_WEBHOOK // Call an external API/webhook\n ADVANCE_WORKFLOW // Advance or complete a workflow step\n RUN_AUTOMATION // Execute internal business logic\n LOCK_UNIT // Lock the property unit for the applicant, supersede competing applications\n}\n\n/// Actor Type - Who triggered an event\nenum ActorType {\n USER\n API_KEY\n SYSTEM\n WEBHOOK\n}\n\n/// Workflow Event Status\nenum WorkflowEventStatus {\n PENDING\n PROCESSING\n COMPLETED\n FAILED\n SKIPPED\n}\n\n/// Handler Execution Status\nenum ExecutionStatus {\n PENDING\n RUNNING\n COMPLETED\n FAILED\n RETRYING\n SKIPPED\n}\n\n/// Permission effect (Allow/Deny)\nenum PermissionEffect {\n ALLOW\n DENY\n}\n\n// =============================================================================\n// USER & AUTH DOMAIN\n// =============================================================================\n\nmodel User {\n id String @id @default(cuid())\n email String @unique\n password String?\n phone String? @unique\n firstName String?\n lastName String?\n isActive Boolean @default(true)\n isEmailVerified Boolean @default(false)\n googleId String?\n avatar String?\n // Legacy: Optional direct tenant association (for backward compatibility)\n // New: Use tenantMemberships for multi-tenant federation\n tenantId String?\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: SetNull)\n // Federated: User can belong to multiple tenants with different roles\n tenantMemberships TenantMembership[]\n // Legacy: Support multiple roles via explicit join table `UserRole`\n userRoles UserRole[]\n walletId String? @unique\n wallet Wallet? @relation(fields: [walletId], references: [id])\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n emailVerifiedAt DateTime?\n emailVerificationToken String?\n lastLoginAt DateTime?\n refreshTokens RefreshToken[]\n passwordResets PasswordReset[]\n suspensions UserSuspension[]\n emailPreferences EmailPreference[]\n deviceEndpoints DeviceEndpoint[]\n socials Social[]\n\n // Relations to other domains\n properties Property[]\n applications Application[] @relation(\"ApplicationBuyer\")\n soldApplications Application[] @relation(\"ApplicationSeller\")\n applicationPayments ApplicationPayment[] @relation(\"ApplicationPayer\")\n\n // Documentation step assignments and approvals\n assignedSteps DocumentationStep[] @relation(\"DocumentationStepAssignee\")\n gateActedSteps DocumentationStep[] @relation(\"GateActedBy\")\n stepApprovals DocumentationStepApproval[] @relation(\"DocumentationStepApprover\")\n uploadedDocs ApplicationDocument[] @relation(\"DocumentUploader\")\n\n // Payment method changes\n paymentMethodChangeRequests PaymentMethodChangeRequest[] @relation(\"ChangeRequestor\")\n reviewedChangeRequests PaymentMethodChangeRequest[] @relation(\"ChangeReviewer\")\n\n // Contract terminations\n initiatedTerminations ApplicationTermination[] @relation(\"TerminationInitiator\")\n reviewedTerminations ApplicationTermination[] @relation(\"TerminationReviewer\")\n\n // Offer letters\n offerLettersGenerated OfferLetter[] @relation(\"OfferLetterGenerator\")\n offerLettersSent OfferLetter[] @relation(\"OfferLetterSender\")\n\n // Property transfer requests\n transferRequestsSubmitted PropertyTransferRequest[] @relation(\"TransferRequestor\")\n transferRequestsReviewed PropertyTransferRequest[] @relation(\"TransferReviewer\")\n\n // Unified approval requests\n approvalRequestsSubmitted ApprovalRequest[] @relation(\"ApprovalRequestor\")\n approvalRequestsAssigned ApprovalRequest[] @relation(\"ApprovalAssignee\")\n approvalRequestsReviewed ApprovalRequest[] @relation(\"ApprovalReviewer\")\n\n // Contract refunds\n requestedRefunds ApplicationRefund[] @relation(\"RefundRequester\")\n approvedRefunds ApplicationRefund[] @relation(\"RefundApprover\")\n processedRefunds ApplicationRefund[] @relation(\"RefundProcessor\")\n\n @@index([email])\n @@index([tenantId])\n @@map(\"users\")\n}\n\nmodel Role {\n id String @id @default(cuid())\n name String\n description String?\n // Tenant-scoping: NULL = global template, set = tenant-specific role\n tenantId String?\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n // System roles cannot be deleted (admin, user, etc.)\n isSystem Boolean @default(false)\n isActive Boolean @default(true)\n // Legacy: UserRole for backward compatibility\n userRoles UserRole[]\n // New: TenantMembership for federated users\n memberships TenantMembership[]\n permissions RolePermission[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([name, tenantId]) // Unique name per tenant (null tenantId = global)\n @@index([tenantId])\n @@map(\"roles\")\n}\n\n/// Permission defines a path pattern + HTTP methods + effect\n/// Supports path-based authorization matching the authorizer's policy structure\nmodel Permission {\n id String @id @default(cuid())\n name String // Descriptive name: \"Read Users\", \"Manage Properties\"\n description String?\n // Path pattern: /users, /users/:id, /properties/*, etc.\n path String\n // HTTP methods: [\"GET\"], [\"GET\", \"POST\"], [\"*\"] - stored as JSON\n methods Json @default(\"[]\")\n // Allow or Deny this path/methods\n effect PermissionEffect @default(ALLOW)\n // Tenant-scoping: NULL = global template, set = tenant-specific\n tenantId String?\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n // System permissions cannot be deleted\n isSystem Boolean @default(false)\n roles RolePermission[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([path, tenantId]) // Unique path per tenant\n @@index([tenantId])\n @@map(\"permissions\")\n}\n\nmodel RolePermission {\n roleId String\n permissionId String\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@id([roleId, permissionId])\n @@map(\"role_permissions\")\n}\n\n/// Legacy: Direct user-role assignment (global, not tenant-scoped)\n/// @deprecated Use TenantMembership for tenant-scoped role assignments\nmodel UserRole {\n userId String\n roleId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@id([userId, roleId])\n @@map(\"user_roles\")\n}\n\n/// Tenant Membership: Links users to tenants with specific roles\n/// Enables federated users across multiple tenants with different roles per tenant\nmodel TenantMembership {\n id String @id @default(cuid())\n userId String\n tenantId String\n roleId String\n // Whether this membership is active\n isActive Boolean @default(true)\n // Whether this is the user's default tenant (for login without specifying tenant)\n isDefault Boolean @default(false)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n role Role @relation(fields: [roleId], references: [id], onDelete: Restrict)\n\n @@unique([userId, tenantId]) // User can only have one membership per tenant\n @@index([tenantId])\n @@index([userId])\n @@map(\"tenant_memberships\")\n}\n\nmodel Tenant {\n id String @id @default(cuid())\n name String\n subdomain String @unique\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Back-relations for multitenancy\n users User[]\n properties Property[]\n paymentPlans PaymentPlan[]\n documentationPlans DocumentationPlan[]\n paymentMethods PropertyPaymentMethod[]\n applications Application[]\n\n // RBAC: Tenant-scoped roles and permissions\n roles Role[]\n permissions Permission[]\n // Federated user memberships\n memberships TenantMembership[]\n\n // Payment method changes\n paymentMethodChangeRequests PaymentMethodChangeRequest[]\n documentRequirementRules DocumentRequirementRule[]\n\n // Contract terminations\n contractTerminations ApplicationTermination[]\n\n // Offer letters and templates\n documentTemplates DocumentTemplate[]\n offerLetters OfferLetter[]\n\n // API keys for third-party integrations\n apiKeys ApiKey[]\n\n // Event-driven workflow\n eventChannels EventChannel[]\n eventTypes EventType[]\n eventHandlers EventHandler[]\n workflowEvents WorkflowEvent[]\n\n // Property transfer requests\n propertyTransferRequests PropertyTransferRequest[]\n\n // Unified approval requests\n approvalRequests ApprovalRequest[]\n\n // Contract refunds\n contractRefunds ApplicationRefund[]\n propertyPaymentMethodLinks PropertyPaymentMethodLink[]\n propertyPaymentMethodPhases PropertyPaymentMethodPhase[]\n phaseEventAttachments PhaseEventAttachment[]\n paymentMethodPhaseSteps PaymentMethodPhaseStep[]\n stepEventAttachments StepEventAttachment[]\n paymentMethodPhaseDocuments PaymentMethodPhaseDocument[]\n paymentMethodPhaseFields PaymentMethodPhaseField[]\n applicationPhases ApplicationPhase[]\n questionnairePhases QuestionnairePhase[]\n documentationPhases DocumentationPhase[]\n paymentPhases PaymentPhase[]\n questionnaireFields QuestionnaireField[]\n applicationEvents ApplicationEvent[]\n documentationSteps DocumentationStep[]\n documentationStepDocuments DocumentationStepDocument[]\n documentationStepApprovals DocumentationStepApproval[]\n paymentInstallments PaymentInstallment[]\n applicationPayments ApplicationPayment[]\n applicationDocuments ApplicationDocument[]\n propertyMedia PropertyMedia[]\n propertyDocuments PropertyDocument[]\n propertyVariants PropertyVariant[]\n propertyVariantAmenities PropertyVariantAmenity[]\n propertyVariantMedia PropertyVariantMedia[]\n propertyUnits PropertyUnit[]\n propertyAmenities PropertyAmenity[]\n eventHandlerExecutions EventHandlerExecution[]\n amenities Amenity[]\n socials Social[]\n wallets Wallet[]\n transactions Transaction[]\n settings Settings[]\n domainEvents DomainEvent[]\n workflowBlockers WorkflowBlocker[]\n questionnairePlans QuestionnairePlan[]\n\n @@index([subdomain])\n @@map(\"tenants\")\n}\n\n// =============================================================================\n// API KEYS - Third-party integration credentials\n// =============================================================================\n// ApiKey enables partners/integrations to authenticate via token exchange.\n// \n// Flow:\n// 1. Admin creates API key for a partner (POST /api-keys)\n// 2. System generates secret, stores in Secrets Manager, returns id.secret ONCE\n// 3. Partner calls token endpoint with id.secret (POST /api-keys/:id/token)\n// 4. Token endpoint validates via Secrets Manager, returns short-lived JWT\n// 5. Partner uses JWT for API requests; authorizer validates + resolves scopes\n//\n// Security:\n// - Raw secret stored ONLY in AWS Secrets Manager (secretRef = ARN)\n// - Secret returned only once at creation; admin must rotate if lost\n// - Scopes define allowed operations (e.g., [\"contract:read\", \"payment:read\"])\n// - Short-lived JWTs (5-15 min) minimize exposure on key compromise\n// =============================================================================\n\nmodel ApiKey {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Identification\n name String // Human-readable name (e.g., \"Paystack Integration\")\n description String? @db.Text // Optional description\n provider String // Partner/vendor name (e.g., \"paystack\", \"flutterwave\")\n\n // Secret management (NEVER store raw secret in DB)\n secretRef String // AWS Secrets Manager ARN or name\n\n // Permissions - scopes this API key is allowed to request\n // Examples: [\"contract:read\", \"payment:*\", \"property:read\"]\n scopes Json // JSON array of scope strings\n\n // Lifecycle\n enabled Boolean @default(true)\n expiresAt DateTime? // Optional expiration date\n lastUsedAt DateTime? // Updated on each token exchange\n revokedAt DateTime? // Set when key is revoked\n revokedBy String? // User ID who revoked\n\n // Audit\n createdBy String? // User ID who created\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([provider])\n @@index([enabled])\n @@map(\"api_keys\")\n}\n\nmodel RefreshToken {\n id String @id @default(cuid())\n // Use the JWT `jti` for indexed lookups and keep the raw JWT (optional)\n jti String? @unique @db.VarChar(255)\n token String? @db.LongText\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n expiresAt DateTime\n createdAt DateTime @default(now())\n\n @@index([userId])\n @@index([expiresAt])\n @@map(\"refresh_tokens\")\n}\n\nmodel PasswordReset {\n id String @id @default(cuid())\n token String @unique\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n expiresAt DateTime\n usedAt DateTime?\n createdAt DateTime @default(now())\n\n @@index([userId])\n @@index([expiresAt])\n @@map(\"password_resets\")\n}\n\nmodel UserSuspension {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n reason String\n suspendedAt DateTime @default(now())\n expiresAt DateTime?\n liftedAt DateTime?\n\n @@index([userId])\n @@map(\"user_suspensions\")\n}\n\nmodel EmailPreference {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n marketingEmails Boolean @default(true)\n transactionalEmails Boolean @default(true)\n propertyAlerts Boolean @default(true)\n paymentReminders Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@map(\"email_preferences\")\n}\n\nmodel DeviceEndpoint {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n endpoint String // Push notification endpoint\n platform String // ios, android, web\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@map(\"device_endpoints\")\n}\n\nmodel Social {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n provider String // google, facebook, twitter, etc\n socialId String // ID from the social provider\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([provider, socialId])\n @@index([userId])\n @@index([tenantId])\n @@map(\"socials\")\n}\n\nmodel OAuthState {\n id String @id @default(cuid())\n state String @unique\n expiresAt DateTime\n createdAt DateTime @default(now())\n\n @@index([state])\n @@index([expiresAt])\n @@map(\"oauth_states\")\n}\n\nmodel Wallet {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n balance Float @default(0)\n currency String @default(\"USD\")\n user User?\n transactions Transaction[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@map(\"wallets\")\n}\n\nmodel Transaction {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n walletId String\n wallet Wallet @relation(fields: [walletId], references: [id], onDelete: Cascade)\n amount Float\n type String // CREDIT, DEBIT\n status String // PENDING, COMPLETED, FAILED\n reference String?\n description String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([walletId])\n @@index([tenantId])\n @@map(\"transactions\")\n}\n\nmodel Settings {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n key String\n value String @db.Text\n category String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([tenantId, key])\n @@index([category])\n @@index([tenantId])\n @@map(\"settings\")\n}\n\n// =============================================================================\n// PROPERTY DOMAIN\n// =============================================================================\n// Property = listing/project (e.g., \"Sunrise Estate\")\n// PropertyVariant = configuration with specs & price (e.g., \"3-Bed Corner - Finished\")\n// PropertyUnit = individual sellable unit (e.g., \"Unit A1\")\n// =============================================================================\n\nmodel Property {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n title String\n category String // SALE, RENT, LEASE\n propertyType String // APARTMENT, HOUSE, LAND, COMMERCIAL, ESTATE, TOWNHOUSE\n country String\n currency String // USD, NGN, etc\n city String\n district String?\n zipCode String?\n streetAddress String?\n longitude Float?\n latitude Float?\n status String @default(\"DRAFT\") // DRAFT, PUBLISHED, SOLD_OUT, ARCHIVED\n description String? @db.Text\n displayImageId String?\n displayImage PropertyMedia? @relation(\"DisplayImage\", fields: [displayImageId], references: [id], onDelete: SetNull)\n isPublished Boolean @default(false)\n publishedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n documents PropertyDocument[]\n media PropertyMedia[] @relation(\"PropertyMedia\")\n amenities PropertyAmenity[] // Shared amenities (gym, pool, security)\n paymentMethods PropertyPaymentMethodLink[]\n variants PropertyVariant[]\n\n @@index([tenantId])\n @@index([userId])\n @@index([category])\n @@index([propertyType])\n @@index([city])\n @@index([status])\n @@map(\"properties\")\n}\n\nmodel PropertyMedia {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n propertyId String\n property Property @relation(\"PropertyMedia\", fields: [propertyId], references: [id], onDelete: Cascade)\n url String\n type String // IMAGE, VIDEO\n caption String?\n order Int @default(0)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n displayForProperties Property[] @relation(\"DisplayImage\")\n\n @@index([tenantId])\n @@index([propertyId])\n @@map(\"property_media\")\n}\n\nmodel PropertyDocument {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n propertyId String\n property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)\n name String\n url String\n type String // TITLE_DEED, SURVEY_PLAN, etc\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([propertyId])\n @@map(\"property_documents\")\n}\n\nmodel Amenity {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n name String\n category String? // PROPERTY, VARIANT, BOTH - helps filter which amenities to show\n icon String? // Icon name/URL for UI\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n properties PropertyAmenity[]\n variants PropertyVariantAmenity[]\n\n @@unique([tenantId, name]) // Unique per tenant\n @@index([tenantId])\n @@index([category])\n @@map(\"amenities\")\n}\n\n// =============================================================================\n// PROPERTY VARIANT & UNIT MODELS\n// =============================================================================\n\n// PropertyVariant = specific configuration with its own price and amenities\n// e.g., \"3-Bedroom Corner Piece - Fully Finished\", \"2-Bedroom Standard - Carcass\"\nmodel PropertyVariant {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n propertyId String\n property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)\n\n name String // \"Corner Piece - Finished\", \"Standard - Carcass\"\n description String? @db.Text\n\n // Specifications\n nBedrooms Int?\n nBathrooms Int?\n nParkingSpots Int?\n area Float? // Square meters/feet\n\n // Pricing\n price Float\n pricePerSqm Float? // Computed or set manually\n\n // Inventory counters (denormalized for performance, updated via triggers/service)\n totalUnits Int @default(1)\n availableUnits Int @default(1)\n reservedUnits Int @default(0)\n soldUnits Int @default(0)\n\n // Status\n status String @default(\"AVAILABLE\") // AVAILABLE, LOW_STOCK, SOLD_OUT, ARCHIVED\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n amenities PropertyVariantAmenity[]\n units PropertyUnit[]\n media PropertyVariantMedia[]\n\n @@index([tenantId])\n @@index([propertyId])\n @@index([status])\n @@index([price])\n @@map(\"property_variants\")\n}\n\n// PropertyVariantAmenity = amenities specific to a variant\n// e.g., \"Finished Kitchen\", \"Smart Home System\", \"Private Garden\"\nmodel PropertyVariantAmenity {\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n variantId String\n amenityId String\n variant PropertyVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)\n amenity Amenity @relation(fields: [amenityId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@id([variantId, amenityId])\n @@index([tenantId])\n @@map(\"property_variant_amenities\")\n}\n\n// PropertyVariantMedia = images/videos specific to a variant\nmodel PropertyVariantMedia {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n variantId String\n variant PropertyVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)\n url String\n type String // IMAGE, VIDEO, FLOOR_PLAN, 3D_TOUR\n caption String?\n order Int @default(0)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([variantId])\n @@map(\"property_variant_media\")\n}\n\n// PropertyUnit = individual sellable/rentable unit within a variant\n// e.g., \"Unit A1\", \"Block B - Flat 3\", \"Plot 15\"\nmodel PropertyUnit {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n variantId String\n variant PropertyVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)\n\n unitNumber String // \"A1\", \"B-3\", \"Plot 15\"\n floorNumber Int? // For apartments\n blockName String? // \"Block A\", \"Tower 1\"\n\n // Unit-specific overrides (if different from variant)\n priceOverride Float? // If this specific unit has a different price\n areaOverride Float? // If this specific unit has a different area\n notes String? @db.Text // Internal notes about this unit\n\n // Status tracking\n status String @default(\"AVAILABLE\") // AVAILABLE, RESERVED, SOLD, RENTED, UNAVAILABLE\n\n // Reservation/hold\n reservedAt DateTime?\n reservedUntil DateTime?\n reservedById String?\n\n // Ownership tracking (once sold)\n ownerId String?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n applications Application[]\n\n // Transfer requests targeting this unit\n transferRequests PropertyTransferRequest[]\n\n @@unique([variantId, unitNumber])\n @@index([tenantId])\n @@index([variantId])\n @@index([status])\n @@map(\"property_units\")\n}\n\nmodel PropertyAmenity {\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n propertyId String\n amenityId String\n property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)\n amenity Amenity @relation(fields: [amenityId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@id([propertyId, amenityId])\n @@index([tenantId])\n @@map(\"property_amenities\")\n}\n\n// =============================================================================\n// DOCUMENTATION PLAN DOMAIN - Reusable step workflow templates\n// =============================================================================\n\n// DocumentationPlan = reusable structure for documentation workflows\n// Examples: \"Standard KYC\", \"Quick Verification\", \"Full Underwriting\"\nmodel DocumentationPlan {\n id String @id @default(cuid())\n tenantId String? // NULL = global template available to all tenants\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n name String\n description String? @db.Text\n isActive Boolean @default(true)\n\n // Document requirements for this plan\n requiredDocumentTypes Json? // Array of document type strings, e.g., [\"ID_CARD\", \"BANK_STATEMENT\"]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Steps that make up this plan\n steps DocumentationPlanStep[]\n // Used by property payment method phases (templates)\n methodPhases PropertyPaymentMethodPhase[]\n // Used by instantiated documentation phases\n documentationPhases DocumentationPhase[]\n\n @@unique([tenantId, name]) // Unique per tenant, or globally if tenantId is null\n @@index([tenantId])\n @@map(\"documentation_plans\")\n}\n\n// Step template within a DocumentationPlan\nmodel DocumentationPlanStep {\n id String @id @default(cuid())\n planId String\n plan DocumentationPlan @relation(fields: [planId], references: [id], onDelete: Cascade)\n\n name String\n stepType StepType\n order Int\n\n // Optional: which document type this step handles (for UPLOAD steps)\n documentType String?\n metadata Json?\n\n // Document validation rules (for UPLOAD steps)\n isRequired Boolean @default(true)\n description String? @db.Text // Instructions for the user\n maxSizeBytes Int? // Max file size allowed (e.g., 5242880 for 5MB)\n allowedMimeTypes String? // CSV: application/pdf,image/jpeg,image/png\n expiryDays Int? // Document must not be older than X days\n requiresManualReview Boolean @default(false)\n minFiles Int @default(1) // Minimum number of files required\n maxFiles Int @default(1) // Maximum number of files allowed\n\n // Conditional logic - when is this step required?\n // NULL = always required (unconditional)\n // Examples:\n // { \"questionKey\": \"mortgage_type\", \"operator\": \"EQUALS\", \"value\": \"JOINT\" }\n // { \"questionKey\": \"employment_status\", \"operator\": \"IN\", \"values\": [\"SELF_EMPLOYED\", \"BUSINESS_OWNER\"] }\n // { \"all\": [{ \"questionKey\": \"has_spouse\", \"operator\": \"EQUALS\", \"value\": \"YES\" }, { \"questionKey\": \"spouse_employed\", \"operator\": \"EQUALS\", \"value\": \"YES\" }] }\n condition Json?\n\n // =========================================================================\n // GATE STEP CONFIGURATION (only applicable when stepType = GATE)\n // =========================================================================\n gateActor GateActor? // Who must perform the action\n gateAction GateAction? // What action is required\n gateRoleId String? // If gateActor = SPECIFIC_ROLE, which role\n gateInstructions String? @db.Text // Instructions shown to actor\n allowReject Boolean @default(true) // Can the actor reject?\n rejectBehavior GateRejectBehavior? // What happens on reject\n requiresComment Boolean @default(false) // Must actor provide a comment?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([planId])\n @@map(\"documentation_plan_steps\")\n}\n\n// =============================================================================\n// QUESTIONNAIRE PLAN DOMAIN - Reusable form templates with scoring\n// =============================================================================\n// QuestionnairePlan = reusable structure for prequalification/screening forms\n// Examples: \"Mortgage Prequalification\", \"Affordability Assessment\", \"Risk Screening\"\n// =============================================================================\n\nmodel QuestionnairePlan {\n id String @id @default(cuid())\n tenantId String? // NULL = global template available to all tenants\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n name String\n description String? @db.Text\n version Int @default(1)\n isActive Boolean @default(true)\n\n // Scoring configuration\n passingScore Int? // Minimum score to pass (null = no auto-scoring)\n scoringStrategy ScoringStrategy @default(SUM)\n autoDecisionEnabled Boolean @default(false) // Auto-pass/fail based on score\n\n // Metadata\n estimatedMinutes Int? // Estimated time to complete\n category QuestionnaireCategory @default(PREQUALIFICATION)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Questions that make up this plan\n questions QuestionnairePlanQuestion[]\n\n // Used by property payment method phases (templates)\n methodPhases PropertyPaymentMethodPhase[]\n\n // Used by instantiated questionnaire phases\n questionnairePhases QuestionnairePhase[]\n\n @@unique([tenantId, name, version])\n @@index([tenantId])\n @@index([category])\n @@map(\"questionnaire_plans\")\n}\n\n// Question template within a QuestionnairePlan\nmodel QuestionnairePlanQuestion {\n id String @id @default(cuid())\n questionnairePlanId String\n questionnairePlan QuestionnairePlan @relation(fields: [questionnairePlanId], references: [id], onDelete: Cascade)\n\n // Question identification\n questionKey String // Unique key for this question (e.g., \"annual_income\")\n questionText String @db.Text // The actual question text\n helpText String? @db.Text // Optional help/tooltip text\n\n // Field configuration\n questionType QuestionType\n order Int\n\n // Validation\n isRequired Boolean @default(true)\n validationRules Json? // { min: 0, max: 1000000, pattern: \"^[0-9]+$\" }\n\n // Options for SELECT/MULTI_SELECT/RADIO\n // [{ value: \"employed\", label: \"Employed\", score: 10 }, ...]\n options Json?\n\n // Scoring\n scoreWeight Int @default(1) // Multiplier for this question's score\n scoringRules Json? // { \"employed\": 10, \"self_employed\": 7, \"unemployed\": 0 } or ranges\n\n // Conditional logic (branching)\n // { \"questionKey\": \"employment_status\", \"equals\": \"employed\" }\n showIf Json?\n\n // Metadata for grouping\n category String? // Group questions (e.g., \"income\", \"employment\", \"property\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([questionnairePlanId, questionKey])\n @@index([questionnairePlanId])\n @@map(\"questionnaire_plan_questions\")\n}\n\n// =============================================================================\n// PAYMENT PLAN DOMAIN - Reusable installment structure templates\n// =============================================================================\n\n// PaymentPlan = reusable structure for how payments are scheduled\n// Examples: \"Monthly360\" (360 monthly payments), \"Weekly52\", \"OneTime\"\nmodel PaymentPlan {\n id String @id @default(cuid())\n tenantId String? // NULL = global template available to all tenants\n tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n name String\n description String? @db.Text\n isActive Boolean @default(true)\n\n // Structure configuration\n paymentFrequency PaymentFrequency\n customFrequencyDays Int?\n numberOfInstallments Int? // Fixed number (1 for one-time, 360 for 30yr monthly) - NULL if flexible\n calculateInterestDaily Boolean @default(false)\n gracePeriodDays Int @default(0)\n\n // Flexible term configuration (for user-selectable duration like mortgages)\n // If these are set, numberOfInstallments is ignored and user selects within range\n allowFlexibleTerm Boolean @default(false) // true = user can select term within range\n minTermMonths Int? // e.g., 60 (5 years minimum)\n maxTermMonths Int? // e.g., 360 (30 years maximum)\n termStepMonths Int? // e.g., 12 (increments of 1 year) - NULL = any month allowed\n\n // Age-based constraints (for mortgage eligibility)\n maxAgeAtMaturity Int? // e.g., 65 - user's age + term cannot exceed this\n\n // Fund collection behavior\n // true = we collect funds via wallet/gateway (e.g., downpayment)\n // false = external payment, we only track/reconcile (e.g., bank mortgage)\n collectFunds Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Used by property payment method phases (templates)\n methodPhases PropertyPaymentMethodPhase[]\n // Used by instantiated payment phases\n paymentPhases PaymentPhase[]\n\n @@unique([tenantId, name]) // Unique per tenant, or globally if tenantId is null\n @@index([tenantId])\n @@map(\"payment_plans\")\n}\n\n// =============================================================================\n// PROPERTY PAYMENT METHOD DOMAIN - Product offerings per property\n// =============================================================================\n\n// PropertyPaymentMethod = how a property can be purchased (e.g., \"Standard Mortgage\", \"Cash\", \"Rent-to-Own\")\nmodel PropertyPaymentMethod {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n name String // \"Standard Mortgage\", \"Flexible Payment\", \"Cash Purchase\"\n description String? @db.Text\n isActive Boolean @default(true)\n\n // Global method configuration\n allowEarlyPayoff Boolean @default(true)\n earlyPayoffPenaltyRate Float?\n autoActivatePhases Boolean @default(true)\n requiresManualApproval Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Many-to-many with properties\n properties PropertyPaymentMethodLink[]\n // Phases that make up this method (templates)\n phases PropertyPaymentMethodPhase[]\n // Contracts using this method\n applications Application[]\n\n // Payment method change tracking\n changeRequestsFrom PaymentMethodChangeRequest[] @relation(\"ChangeFromMethod\")\n changeRequestsTo PaymentMethodChangeRequest[] @relation(\"ChangeToMethod\")\n\n // Document requirement rules\n documentRules DocumentRequirementRule[] @relation(\"RulePaymentMethod\")\n changeRulesFrom DocumentRequirementRule[] @relation(\"RuleFromMethod\")\n changeRulesTo DocumentRequirementRule[] @relation(\"RuleToMethod\")\n\n @@unique([tenantId, name]) // Unique per tenant\n @@index([tenantId])\n @@map(\"property_payment_methods\")\n}\n\n// Many-to-many link between Property and PaymentMethod\nmodel PropertyPaymentMethodLink {\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n propertyId String\n property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)\n paymentMethodId String\n paymentMethod PropertyPaymentMethod @relation(fields: [paymentMethodId], references: [id], onDelete: Cascade)\n\n // Method-specific overrides for this property\n isDefault Boolean @default(false)\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n\n @@id([propertyId, paymentMethodId])\n @@index([tenantId])\n @@map(\"property_payment_method_links\")\n}\n\n// Phase template within a PropertyPaymentMethod (e.g., documentation, downpayment, mortgage)\n// phaseCategory determines the FSM type: DOCUMENTATION or PAYMENT\nmodel PropertyPaymentMethodPhase {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n paymentMethodId String\n paymentMethod PropertyPaymentMethod @relation(fields: [paymentMethodId], references: [id], onDelete: Cascade)\n\n // Plan references (only one should be set based on phaseCategory)\n paymentPlanId String? // Only for PAYMENT phases\n paymentPlan PaymentPlan? @relation(fields: [paymentPlanId], references: [id])\n documentationPlanId String? // Only for DOCUMENTATION phases\n documentationPlan DocumentationPlan? @relation(fields: [documentationPlanId], references: [id])\n questionnairePlanId String? // Only for QUESTIONNAIRE phases\n questionnairePlan QuestionnairePlan? @relation(fields: [questionnairePlanId], references: [id])\n\n name String\n description String? @db.Text\n\n // Phase classification (DB-enforced enums)\n phaseCategory PhaseCategory\n phaseType PhaseType\n order Int\n\n // Financial configuration (for PAYMENT phases)\n interestRate Float?\n percentOfPrice Float? // e.g., 10.0 for 10% downpayment\n\n // Fund collection behavior (inherited from PaymentPlan if not set)\n // true = we collect funds via wallet/gateway (e.g., downpayment)\n // false = external payment, we only track/reconcile (e.g., bank mortgage)\n collectFunds Boolean? // null = inherit from PaymentPlan\n\n // Activation rules\n requiresPreviousPhaseCompletion Boolean @default(true)\n minimumCompletionPercentage Float?\n completionCriterion CompletionCriterion?\n\n // Unit locking configuration\n // If true, completing this phase locks the unit for the applicant\n // Only one phase per payment method should have this enabled\n lockUnitOnComplete Boolean @default(false)\n\n // Snapshots for audit (original config at creation time)\n // These are still needed for inline definitions (backward compatibility)\n stepDefinitionsSnapshot Json?\n requiredDocumentSnapshot Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Normalized child tables (for DOCUMENTATION phases - inline definitions)\n steps PaymentMethodPhaseStep[]\n requiredDocuments PaymentMethodPhaseDocument[]\n // Normalized child tables (for QUESTIONNAIRE phases)\n questionnaireFields PaymentMethodPhaseField[]\n // Event attachments - handlers that fire on phase transitions\n eventAttachments PhaseEventAttachment[]\n // Application phases created from this template\n applicationPhases ApplicationPhase[]\n\n @@index([tenantId])\n @@index([paymentMethodId])\n @@index([paymentPlanId])\n @@index([documentationPlanId])\n @@index([questionnairePlanId])\n @@index([phaseCategory])\n @@map(\"property_payment_method_phases\")\n}\n\n/// Phase Event Attachment - Links event handlers to phase template triggers\n/// When a phase transitions (complete, payment received, etc.), attached handlers fire\nmodel PhaseEventAttachment {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String\n phase PropertyPaymentMethodPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n /// When this handler should fire\n trigger PhaseTrigger\n\n /// The event handler to execute\n handlerId String\n handler EventHandler @relation(fields: [handlerId], references: [id], onDelete: Cascade)\n\n /// Order of execution (lower = first)\n priority Int @default(100)\n\n /// Whether this attachment is active\n enabled Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([phaseId, handlerId, trigger])\n @@index([tenantId])\n @@index([phaseId])\n @@index([handlerId])\n @@map(\"phase_event_attachments\")\n}\n\n// Step template within a DOCUMENTATION phase\nmodel PaymentMethodPhaseStep {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String\n phase PropertyPaymentMethodPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n name String\n stepType StepType\n order Int\n\n metadata Json?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Event attachments - handlers that fire on step transitions\n eventAttachments StepEventAttachment[]\n\n @@index([tenantId])\n @@index([phaseId])\n @@map(\"payment_method_phase_steps\")\n}\n\n/// Step Event Attachment - Links event handlers to step template triggers\n/// When a step transitions (complete, reject, etc.), attached handlers fire\nmodel StepEventAttachment {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n stepId String\n step PaymentMethodPhaseStep @relation(fields: [stepId], references: [id], onDelete: Cascade)\n\n /// When this handler should fire\n trigger StepTrigger\n\n /// The event handler to execute\n handlerId String\n handler EventHandler @relation(fields: [handlerId], references: [id], onDelete: Cascade)\n\n /// Order of execution (lower = first)\n priority Int @default(100)\n\n /// Whether this attachment is active\n enabled Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([stepId, handlerId, trigger])\n @@index([tenantId])\n @@index([stepId])\n @@index([handlerId])\n @@map(\"step_event_attachments\")\n}\n\n// Required document within a DOCUMENTATION phase\nmodel PaymentMethodPhaseDocument {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String\n phase PropertyPaymentMethodPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n documentType String\n isRequired Boolean @default(true)\n description String? @db.Text\n allowedMimeTypes String? // CSV: application/pdf,image/jpeg\n maxSizeBytes Int?\n\n metadata Json?\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([phaseId, documentType])\n @@map(\"payment_method_phase_documents\")\n}\n\n// =============================================================================\n// QUESTIONNAIRE FIELD TYPES - For QUESTIONNAIRE phases\n// =============================================================================\n\nenum FieldType {\n TEXT // Short text input\n TEXTAREA // Long text input\n NUMBER // Numeric input (with optional min/max)\n CURRENCY // Currency input (validated as money)\n EMAIL // Email validation\n PHONE // Phone number validation\n DATE // Date picker\n SELECT // Dropdown/single select\n MULTI_SELECT // Multiple selection\n CHECKBOX // Boolean yes/no\n RADIO // Radio button group\n FILE // File upload (single)\n}\n\n// =============================================================================\n// QUESTIONNAIRE PLAN ENUMS - For scoring and categorization\n// =============================================================================\n\nenum QuestionType {\n TEXT\n NUMBER\n CURRENCY\n DATE\n SELECT\n MULTI_SELECT\n RADIO\n CHECKBOX\n FILE_UPLOAD\n PHONE\n EMAIL\n ADDRESS\n PERCENTAGE\n YEARS_MONTHS\n}\n\nenum ScoringStrategy {\n SUM // Add up all scores\n AVERAGE // Average of all scores\n WEIGHTED_SUM // Sum with weights (score * weight)\n MIN_ALL // Must meet minimum on all questions\n CUSTOM // Use custom scoring function\n}\n\nenum QuestionnaireCategory {\n PREQUALIFICATION // Initial eligibility screening\n AFFORDABILITY // Income/expense assessment\n PROPERTY_INTENT // What property are they looking for\n RISK_ASSESSMENT // Credit/risk questions\n COMPLIANCE // KYC/AML questions\n CUSTOM\n}\n\n// Questionnaire field template within a QUESTIONNAIRE phase\nmodel PaymentMethodPhaseField {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String\n phase PropertyPaymentMethodPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n // Field identification\n name String // Internal field name (e.g., \"monthly_income\")\n label String // Display label (e.g., \"Monthly Income\")\n description String? @db.Text // Help text for the field\n placeholder String? // Placeholder text\n\n // Field configuration\n fieldType FieldType\n isRequired Boolean @default(true)\n order Int\n\n // Validation rules (JSON schema-like)\n // Examples:\n // NUMBER: { \"min\": 0, \"max\": 1000000 }\n // TEXT: { \"minLength\": 2, \"maxLength\": 100, \"pattern\": \"^[A-Za-z]+$\" }\n // SELECT: { \"options\": [{\"value\": \"employed\", \"label\": \"Employed\"}, ...] }\n // DATE: { \"minDate\": \"now\", \"maxDate\": \"+30d\" }\n validation Json?\n\n // For conditional display (e.g., show if another field has a certain value)\n // { \"field\": \"employment_status\", \"operator\": \"equals\", \"value\": \"employed\" }\n displayCondition Json?\n\n // Default value (JSON to support any type)\n defaultValue Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([phaseId, name])\n @@index([tenantId])\n @@index([phaseId])\n @@map(\"payment_method_phase_fields\")\n}\n\n// =============================================================================\n// CONTRACT DOMAIN - Unified agreement model (replaces Mortgage, PurchasePlan, etc.)\n// =============================================================================\n// Application is the canonical agreement. \"Mortgage\" is just a product configuration\n// that creates an Application with specific phases (documentation, downpayment, long-term payment).\n// Phases can be QUESTIONNAIRE, DOCUMENTATION, or PAYMENT.\n// =============================================================================\n\nmodel Application {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n // Link to specific unit being purchased/rented\n propertyUnitId String\n propertyUnit PropertyUnit @relation(fields: [propertyUnitId], references: [id], onDelete: Cascade)\n buyerId String\n buyer User @relation(\"ApplicationBuyer\", fields: [buyerId], references: [id], onDelete: Cascade)\n sellerId String?\n seller User? @relation(\"ApplicationSeller\", fields: [sellerId], references: [id])\n paymentMethodId String? // PropertyPaymentMethod used to create this contract\n paymentMethod PropertyPaymentMethod? @relation(fields: [paymentMethodId], references: [id])\n\n // Contract identification\n applicationNumber String @unique\n title String\n description String? @db.Text\n applicationType String // Admin-defined: MORTGAGE, INSTALLMENT, RENT_TO_OWN, CASH, LEASE, etc.\n\n // Contract value (negotiated from unit price)\n totalAmount Float\n\n // FSM state (DB-enforced enum)\n status ApplicationStatus @default(DRAFT)\n currentPhaseId String?\n currentPhase ApplicationPhase? @relation(\"CurrentPhase\", fields: [currentPhaseId], references: [id])\n\n // Timing\n nextPaymentDueDate DateTime?\n lastReminderSentAt DateTime?\n startDate DateTime?\n endDate DateTime?\n signedAt DateTime?\n terminatedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n phases ApplicationPhase[]\n documents ApplicationDocument[]\n payments ApplicationPayment[]\n terminations ApplicationTermination[]\n offerLetters OfferLetter[]\n\n // Payment method change requests for this contract\n paymentMethodChangeRequests PaymentMethodChangeRequest[]\n\n // Transfer tracking - when a contract is transferred to a different property\n transferredFromId String? @unique // Source contract if this was created via transfer\n transferredFrom Application? @relation(\"ApplicationTransfer\", fields: [transferredFromId], references: [id])\n transferredTo Application? @relation(\"ApplicationTransfer\")\n\n // Supersede tracking - when another buyer locks the unit\n // If status is SUPERSEDED, this references the application that took the unit\n supersededById String?\n supersededBy Application? @relation(\"ApplicationSuperseded\", fields: [supersededById], references: [id])\n supersededAt DateTime?\n supersededApplications Application[] @relation(\"ApplicationSuperseded\")\n\n // Transfer requests where this contract is the source\n outgoingTransferRequests PropertyTransferRequest[] @relation(\"SourceApplication\")\n // Transfer requests where this contract is the target (created after approval)\n incomingTransferRequests PropertyTransferRequest[] @relation(\"TargetApplication\")\n\n // Audit trail\n events ApplicationEvent[]\n\n // Refund requests\n refunds ApplicationRefund[]\n\n @@index([tenantId])\n @@index([propertyUnitId])\n @@index([buyerId])\n @@index([sellerId])\n @@index([paymentMethodId])\n @@index([status])\n @@index([currentPhaseId])\n @@index([supersededById])\n @@map(\"applications\")\n}\n\n// =============================================================================\n// CONTRACT REFUNDS - Track refund requests for overpayments or cancellations\n// =============================================================================\nmodel ApplicationRefund {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n\n amount Float\n reason String @db.Text\n status RefundStatus @default(PENDING)\n\n // Who requested the refund\n requestedById String\n requestedBy User @relation(\"RefundRequester\", fields: [requestedById], references: [id])\n\n // Who approved/rejected the refund\n approvedById String?\n approvedBy User? @relation(\"RefundApprover\", fields: [approvedById], references: [id])\n\n // Who processed the refund (finance team)\n processedById String?\n processedBy User? @relation(\"RefundProcessor\", fields: [processedById], references: [id])\n\n // Refund payment details\n paymentMethod String? // BANK_TRANSFER, CHEQUE, MOBILE_MONEY, etc.\n referenceNumber String? // Bank/payment reference\n recipientName String?\n recipientAccount String?\n recipientBank String?\n\n // Timestamps\n requestedAt DateTime @default(now())\n approvedAt DateTime?\n rejectedAt DateTime?\n processedAt DateTime?\n\n // Additional notes\n approvalNotes String? @db.Text\n rejectionNotes String? @db.Text\n processingNotes String? @db.Text\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([applicationId])\n @@index([status])\n @@index([tenantId])\n @@index([requestedById])\n @@map(\"application_refunds\")\n}\n\n// Phase within a contract - can be DOCUMENTATION or PAYMENT type\n// Admin names phases freely (e.g., \"KYC Documents\", \"Downpayment\", \"Monthly Mortgage\")\n// =============================================================================\n// CONTRACT PHASE - Base model with polymorphic extensions\n// =============================================================================\n// ApplicationPhase is the base table with shared fields only.\n// Each phase has exactly ONE extension table based on phaseCategory:\n// - QUESTIONNAIRE → QuestionnairePhase\n// - DOCUMENTATION → DocumentationPhase\n// - PAYMENT → PaymentPhase\n// This eliminates nullable field pollution and makes the schema self-documenting.\n// =============================================================================\n\nmodel ApplicationPhase {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n\n // Reference to the phase template this was instantiated from\n phaseTemplateId String?\n phaseTemplate PropertyPaymentMethodPhase? @relation(fields: [phaseTemplateId], references: [id], onDelete: SetNull)\n\n // Admin-defined naming\n name String\n description String? @db.Text\n\n // Phase classification (DB-enforced enums)\n phaseCategory PhaseCategory\n phaseType PhaseType\n order Int\n\n // FSM state for this phase (DB-enforced enum)\n status PhaseStatus @default(PENDING)\n\n // Timing (shared across all phase types)\n dueDate DateTime?\n startDate DateTime?\n endDate DateTime?\n activatedAt DateTime?\n completedAt DateTime?\n\n // Activation rules (shared)\n requiresPreviousPhaseCompletion Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Polymorphic extensions (exactly one will be populated based on phaseCategory)\n questionnairePhase QuestionnairePhase?\n documentationPhase DocumentationPhase?\n paymentPhase PaymentPhase?\n\n // Payments can be linked to any phase type (for tracking)\n payments ApplicationPayment[]\n\n // Back-relation for applications where this is the current phase\n currentForApplications Application[] @relation(\"CurrentPhase\")\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([phaseTemplateId])\n @@index([phaseCategory])\n @@index([status])\n @@index([order])\n @@map(\"application_phases\")\n}\n\n// =============================================================================\n// QUESTIONNAIRE PHASE DATA - Extension for QUESTIONNAIRE phases\n// =============================================================================\n// Collects form data from users (eligibility, pre-approval, underwriting inputs)\n// =============================================================================\n\nmodel QuestionnairePhase {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String @unique\n phase ApplicationPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n // Questionnaire plan reference (if created from a plan)\n questionnairePlanId String?\n questionnairePlan QuestionnairePlan? @relation(fields: [questionnairePlanId], references: [id])\n\n // Progress tracking\n completedFieldsCount Int @default(0)\n totalFieldsCount Int @default(0)\n\n // Scoring results (from QuestionnairePlan scoring)\n totalScore Int?\n passingScore Int? // Copied from plan at creation\n passed Boolean?\n scoredAt DateTime?\n\n // Computed results (for UNDERWRITING phases)\n underwritingScore Float?\n debtToIncomeRatio Float?\n underwritingDecision String? // APPROVED, CONDITIONAL, DECLINED\n underwritingNotes String? @db.Text\n\n // Snapshot of field definitions at creation\n fieldsSnapshot Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Child records\n fields QuestionnaireField[]\n\n @@index([tenantId])\n @@index([phaseId])\n @@index([questionnairePlanId])\n @@map(\"questionnaire_phases\")\n}\n\n// =============================================================================\n// DOCUMENTATION PHASE DATA - Extension for DOCUMENTATION phases\n// =============================================================================\n// Manages document upload/approval workflow with FSM steps\n// =============================================================================\n\nmodel DocumentationPhase {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String @unique\n phase ApplicationPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n // Documentation plan reference (if created from a plan)\n documentationPlanId String?\n documentationPlan DocumentationPlan? @relation(fields: [documentationPlanId], references: [id])\n\n // Current step pointer for UX and orchestration\n currentStepId String?\n currentStep DocumentationStep? @relation(\"CurrentStep\", fields: [currentStepId], references: [id])\n\n // Progress counters\n approvedDocumentsCount Int @default(0)\n requiredDocumentsCount Int @default(0)\n completedStepsCount Int @default(0)\n totalStepsCount Int @default(0)\n\n // Completion criteria\n minimumCompletionPercentage Float?\n completionCriterion CompletionCriterion?\n\n // Snapshots for audit\n stepDefinitionsSnapshot Json?\n requiredDocumentSnapshot Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Child records\n steps DocumentationStep[]\n\n @@index([tenantId])\n @@index([phaseId])\n @@index([currentStepId])\n @@map(\"documentation_phases\")\n}\n\n// =============================================================================\n// PAYMENT PHASE DATA - Extension for PAYMENT phases\n// =============================================================================\n// Manages installment-based payment collection\n// =============================================================================\n\nmodel PaymentPhase {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n phaseId String @unique\n phase ApplicationPhase @relation(fields: [phaseId], references: [id], onDelete: Cascade)\n\n // Payment plan reference\n paymentPlanId String?\n paymentPlan PaymentPlan? @relation(fields: [paymentPlanId], references: [id])\n\n // Financial details\n totalAmount Float\n paidAmount Float @default(0)\n interestRate Float @default(0)\n\n // User-selected term (for flexible-term plans like mortgages)\n // These are set when user selects their preferred term at application time\n selectedTermMonths Int? // User's chosen term (e.g., 240 for 20 years)\n numberOfInstallments Int? // Calculated from selectedTermMonths and frequency\n\n // Fund collection behavior\n // true = we collect funds via wallet/gateway (e.g., downpayment)\n // false = external payment, we only track/reconcile (e.g., bank mortgage)\n collectFunds Boolean @default(true)\n\n // Completion criteria\n minimumCompletionPercentage Float?\n\n // Snapshot for audit\n paymentPlanSnapshot Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Child records\n installments PaymentInstallment[]\n\n @@index([tenantId])\n @@index([phaseId])\n @@index([paymentPlanId])\n @@map(\"payment_phases\")\n}\n\n// =============================================================================\n// QUESTIONNAIRE FIELDS - Instantiated fields within QUESTIONNAIRE phases\n// =============================================================================\n// When a contract is created from a payment method template, questionnaire field\n// templates are copied to QuestionnaireField records. Users submit answers here.\n// =============================================================================\n\nmodel QuestionnaireField {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n questionnairePhaseId String\n questionnairePhase QuestionnairePhase @relation(fields: [questionnairePhaseId], references: [id], onDelete: Cascade)\n\n // Field identification (copied from template)\n name String // Internal field name (e.g., \"monthly_income\")\n label String // Display label (e.g., \"Monthly Income\")\n description String? @db.Text\n placeholder String?\n\n // Field configuration (copied from template)\n fieldType FieldType\n isRequired Boolean @default(true)\n order Int\n\n // Validation rules (copied from template)\n validation Json?\n displayCondition Json?\n defaultValue Json?\n\n // User's submitted answer (JSON to support any type)\n // TEXT: \"John Doe\"\n // NUMBER/CURRENCY: 500000\n // SELECT: \"employed\"\n // MULTI_SELECT: [\"option1\", \"option2\"]\n // CHECKBOX: true\n // DATE: \"2024-01-15\"\n answer Json?\n\n // Validation status\n isValid Boolean @default(false)\n validationErrors Json? // Array of error messages if invalid\n\n // Timestamps\n submittedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([questionnairePhaseId, name])\n @@index([tenantId])\n @@index([questionnairePhaseId])\n @@map(\"questionnaire_fields\")\n}\n\n// =============================================================================\n// CONTRACT EVENTS - Audit trail for contract lifecycle\n// =============================================================================\n// Tracks all significant events in a contract's lifecycle for audit, compliance,\n// and debugging. Unlike DomainEvent (which is for inter-service communication),\n// ApplicationEvent is purely for historical tracking and state machine transitions.\n// =============================================================================\nmodel ApplicationEvent {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n\n // Event classification\n eventType ApplicationEventType\n eventGroup ApplicationEventGroup?\n\n // For state transitions (optional - only populated for APPLICATION_STATE_CHANGED events)\n fromState String?\n toState String?\n trigger String?\n\n // Event payload (all event-specific data)\n data Json?\n\n // Actor tracking\n actorId String?\n actorType EventActorType?\n\n // Timing\n occurredAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([eventType])\n @@index([eventGroup])\n @@index([occurredAt])\n @@map(\"application_events\")\n}\n\n// Steps within a DOCUMENTATION phase (FSM for document collection/approval)\nmodel DocumentationStep {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n documentationPhaseId String\n documentationPhase DocumentationPhase @relation(fields: [documentationPhaseId], references: [id], onDelete: Cascade)\n\n name String\n description String? @db.Text\n stepType StepType\n order Int\n\n status StepStatus @default(PENDING)\n\n // =========================================================================\n // USER ACTION TRACKING - For rejection/resubmission flows\n // =========================================================================\n // When status is NEEDS_RESUBMISSION or ACTION_REQUIRED, this explains why.\n // Populated from DocumentationStepApproval.comment on rejection.\n actionReason String? @db.Text\n\n // Number of times this step has been submitted (for tracking resubmissions)\n submissionCount Int @default(0)\n\n // Last submission timestamp (for tracking resubmission timing)\n lastSubmittedAt DateTime?\n\n // Configuration metadata (for GENERATE_DOCUMENT steps, etc.)\n metadata Json?\n\n // Assignment\n assigneeId String?\n assignee User? @relation(\"DocumentationStepAssignee\", fields: [assigneeId], references: [id])\n\n // Required document types for UPLOAD steps (normalized)\n requiredDocuments DocumentationStepDocument[]\n\n // =========================================================================\n // GATE STEP CONFIGURATION (only applicable when stepType = GATE)\n // =========================================================================\n gateActor GateActor? // Who must perform the action\n gateAction GateAction? // What action is required\n gateRoleId String? // If gateActor = SPECIFIC_ROLE, which role\n gateInstructions String? @db.Text // Instructions shown to actor\n allowReject Boolean @default(true) // Can the actor reject?\n rejectBehavior GateRejectBehavior? // What happens on reject\n requiresComment Boolean @default(false) // Must actor provide a comment?\n\n // Gate action tracking\n gateActedAt DateTime? // When the gate action was performed\n gateActedById String? // Who performed the gate action\n gateActedBy User? @relation(\"GateActedBy\", fields: [gateActedById], references: [id])\n gateDecision String? // APPROVED, REJECTED, ACKNOWLEDGED, etc.\n gateComment String? @db.Text // Comment from actor\n\n // Timing\n dueDate DateTime?\n completedAt DateTime?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n approvals DocumentationStepApproval[]\n currentForPhase DocumentationPhase[] @relation(\"CurrentStep\")\n\n @@index([tenantId])\n @@index([documentationPhaseId])\n @@index([status])\n @@index([order])\n @@map(\"documentation_steps\")\n}\n\n// Required documents for a step (normalized from CSV)\nmodel DocumentationStepDocument {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n stepId String\n step DocumentationStep @relation(fields: [stepId], references: [id], onDelete: Cascade)\n\n documentType String\n isRequired Boolean @default(true)\n\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([stepId, documentType])\n @@map(\"documentation_step_documents\")\n}\n\n// Approvals for documentation steps\nmodel DocumentationStepApproval {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n stepId String\n step DocumentationStep @relation(fields: [stepId], references: [id], onDelete: Cascade)\n approverId String?\n approver User? @relation(\"DocumentationStepApprover\", fields: [approverId], references: [id])\n\n decision ApprovalDecision\n comment String? @db.Text\n decidedAt DateTime @default(now())\n\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([stepId])\n @@map(\"documentation_step_approvals\")\n}\n\n// Installments within a PAYMENT phase\nmodel PaymentInstallment {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n paymentPhaseId String\n paymentPhase PaymentPhase @relation(fields: [paymentPhaseId], references: [id], onDelete: Cascade)\n\n installmentNumber Int\n\n amount Float\n principalAmount Float @default(0)\n interestAmount Float @default(0)\n\n dueDate DateTime\n status InstallmentStatus @default(PENDING)\n\n paidAmount Float @default(0)\n paidDate DateTime?\n\n lateFee Float @default(0)\n lateFeeWaived Boolean @default(false)\n gracePeriodDays Int @default(0)\n gracePeriodEndDate DateTime?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n payments ApplicationPayment[]\n\n @@index([tenantId])\n @@index([paymentPhaseId])\n @@index([dueDate])\n @@index([status])\n @@map(\"payment_installments\")\n}\n\n// Unified payment record for contracts\nmodel ApplicationPayment {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n phaseId String?\n phase ApplicationPhase? @relation(fields: [phaseId], references: [id])\n installmentId String?\n installment PaymentInstallment? @relation(fields: [installmentId], references: [id])\n payerId String?\n payer User? @relation(\"ApplicationPayer\", fields: [payerId], references: [id])\n\n amount Float\n principalAmount Float @default(0)\n interestAmount Float @default(0)\n lateFeeAmount Float @default(0)\n\n paymentMethod String // BANK_TRANSFER, CREDIT_CARD, WALLET, CASH, CHECK\n status PaymentStatus @default(INITIATED)\n\n reference String? @unique\n gatewayResponse String? @db.Text // JSON\n\n processedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([phaseId])\n @@index([installmentId])\n @@index([payerId])\n @@index([status])\n @@index([reference])\n @@map(\"application_payments\")\n}\n\n// Contract documents (owned by contract, linked to phases/steps as needed)\nmodel ApplicationDocument {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n phaseId String? // Optional link to specific phase\n stepId String? // Optional link to specific step\n\n name String\n url String\n type String // ID, BANK_STATEMENT, INCOME_PROOF, TITLE_DEED, SIGNATURE, etc.\n uploadedById String?\n uploadedBy User? @relation(\"DocumentUploader\", fields: [uploadedById], references: [id])\n\n status DocumentStatus @default(PENDING)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([phaseId])\n @@index([stepId])\n @@index([type])\n @@index([status])\n @@map(\"application_documents\")\n}\n\n// =============================================================================\n// OFFER LETTERS - Provisional and Final offer documents\n// =============================================================================\n\nmodel DocumentTemplate {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n name String // \"Provisional Offer Letter\", \"Final Offer Letter\"\n code String // PROVISIONAL_OFFER, FINAL_OFFER\n description String?\n version Int @default(1)\n\n // Template content (Handlebars)\n htmlTemplate String @db.Text\n cssStyles String? @db.Text\n\n // Merge field definitions for UI\n mergeFields Json? // [{name, type, required, description}]\n\n isActive Boolean @default(true)\n isDefault Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n offerLetters OfferLetter[]\n\n @@unique([tenantId, code, version])\n @@index([tenantId])\n @@index([code])\n @@map(\"document_templates\")\n}\n\nmodel OfferLetter {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n\n // Template used (optional - documents-service may handle default selection)\n templateId String?\n template DocumentTemplate? @relation(fields: [templateId], references: [id])\n\n // Letter details\n letterNumber String @unique // OL-XXXXXX\n type OfferLetterType\n status OfferLetterStatus @default(DRAFT)\n\n // Generated document\n htmlContent String? @db.Text // Rendered HTML\n pdfUrl String? // S3 URL of generated PDF\n pdfKey String? // S3 key for deletion/access\n\n // Merge data used (snapshot for audit)\n mergeData Json? // All data merged into template\n\n // Signing workflow\n sentAt DateTime?\n viewedAt DateTime?\n signedAt DateTime?\n signatureIp String?\n signatureData Json? // {method, timestamp, metadata}\n\n // Validity\n expiresAt DateTime?\n expiredAt DateTime?\n cancelledAt DateTime?\n cancelReason String?\n\n // Audit\n generatedById String?\n generatedBy User? @relation(\"OfferLetterGenerator\", fields: [generatedById], references: [id])\n sentById String?\n sentBy User? @relation(\"OfferLetterSender\", fields: [sentById], references: [id])\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([type])\n @@index([status])\n @@map(\"offer_letters\")\n}\n\n// =============================================================================\n// CONTRACT TERMINATION - Full lifecycle for cancellation/termination\n// =============================================================================\n// Tracks termination requests from initiation through refund completion.\n// Industry-standard flow:\n// 1. Request created (by buyer/seller/admin/system)\n// 2. Admin reviews (if required by policy)\n// 3. Financial settlement calculated (refunds, penalties, forfeitures)\n// 4. Refund processed (if applicable)\n// 5. Contract marked terminated, unit released\n// =============================================================================\n\nmodel ApplicationTermination {\n id String @id @default(cuid())\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Request identification\n requestNumber String @unique // TRM-XXXXXX\n\n // Who initiated and why\n initiatedBy TerminationInitiator\n initiatorId String? // userId if BUYER/SELLER/ADMIN\n initiator User? @relation(\"TerminationInitiator\", fields: [initiatorId], references: [id])\n type TerminationType\n reason String? @db.Text\n supportingDocs Json? // [{type, url, uploadedAt}]\n\n // Workflow status\n status TerminationStatus @default(REQUESTED)\n requiresApproval Boolean @default(true)\n autoApproveEligible Boolean @default(false) // Pre-signature, no payments\n\n // Admin review\n reviewedBy String?\n reviewer User? @relation(\"TerminationReviewer\", fields: [reviewedBy], references: [id])\n reviewedAt DateTime?\n reviewNotes String? @db.Text\n rejectionReason String? @db.Text\n\n // Financial snapshot at time of request\n applicationSnapshot Json // Full contract state snapshot\n totalApplicationAmount Float\n totalPaidToDate Float\n outstandingBalance Float\n\n // Settlement calculation\n refundableAmount Float @default(0) // Amount eligible for refund\n penaltyAmount Float @default(0) // Penalties/fees to deduct\n forfeitedAmount Float @default(0) // Amount forfeited (non-refundable deposits)\n adminFeeAmount Float @default(0) // Processing fees\n netRefundAmount Float @default(0) // refundableAmount - penaltyAmount - adminFeeAmount\n settlementNotes String? @db.Text\n\n // Refund processing\n refundStatus RefundStatus @default(PENDING)\n refundReference String? // Payment gateway reference\n refundMethod String? // ORIGINAL_METHOD, BANK_TRANSFER, CHECK, WALLET\n refundAccountDetails Json? // Encrypted bank details if needed\n refundInitiatedAt DateTime?\n refundCompletedAt DateTime?\n refundFailureReason String? @db.Text\n\n // Property unit handling\n unitReleasedAt DateTime?\n unitReservedForId String? // If unit being held for another buyer\n\n // Timing\n requestedAt DateTime @default(now())\n approvedAt DateTime?\n executedAt DateTime?\n completedAt DateTime?\n cancelledAt DateTime?\n\n // Idempotency and audit\n idempotencyKey String? @unique\n metadata Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([applicationId])\n @@index([tenantId])\n @@index([status])\n @@index([type])\n @@index([initiatorId])\n @@index([requestedAt])\n @@map(\"application_terminations\")\n}\n\n// =============================================================================\n// PAYMENT METHOD CHANGE REQUEST - Mid-contract payment method changes\n// =============================================================================\n// When a user wants to change their payment method after contract creation,\n// this aggregate tracks the request, required documentation, approvals, and\n// final execution. Different from-to combinations may require different docs.\n// =============================================================================\n\nenum PaymentMethodChangeStatus {\n PENDING_DOCUMENTS\n DOCUMENTS_SUBMITTED\n UNDER_REVIEW\n APPROVED\n REJECTED\n EXECUTED\n CANCELLED\n}\n\nmodel PaymentMethodChangeRequest {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n applicationId String\n application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)\n\n // The change being requested\n fromPaymentMethodId String\n fromPaymentMethod PropertyPaymentMethod @relation(\"ChangeFromMethod\", fields: [fromPaymentMethodId], references: [id])\n toPaymentMethodId String\n toPaymentMethod PropertyPaymentMethod @relation(\"ChangeToMethod\", fields: [toPaymentMethodId], references: [id])\n\n // Who requested and why\n requestorId String\n requestor User @relation(\"ChangeRequestor\", fields: [requestorId], references: [id])\n reason String? @db.Text\n\n // Documentation requirements (determined by DocumentRequirementRule)\n requiredDocumentTypes String? // CSV: BANK_STATEMENT,INCOME_PROOF,NEW_EMPLOYER_LETTER\n submittedDocuments Json? // [{type, s3Key, uploadedAt, status}]\n\n // Financial impact assessment\n currentOutstanding Float? // Outstanding balance at time of request\n newTermMonths Int? // New term if applicable\n newInterestRate Float? // New rate if applicable\n newMonthlyPayment Float? // Projected new payment\n penaltyAmount Float? // Early change penalty if applicable\n financialImpactNotes String? @db.Text\n\n // Status and workflow\n status PaymentMethodChangeStatus @default(PENDING_DOCUMENTS)\n reviewerId String?\n reviewer User? @relation(\"ChangeReviewer\", fields: [reviewerId], references: [id])\n reviewNotes String? @db.Text\n reviewedAt DateTime?\n\n // Execution details\n executedAt DateTime?\n previousPhaseData Json? // Snapshot of phases before change\n newPhaseData Json? // New phases created after change\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([status])\n @@index([requestorId])\n @@map(\"payment_method_change_requests\")\n}\n\n// =============================================================================\n// DOCUMENT REQUIREMENT RULES - Configurable document requirements\n// =============================================================================\n// Admins can configure which documents are required for specific scenarios:\n// - Prequalification for a payment method type\n// - Contract phases\n// - Payment method changes (from-to combinations)\n// This allows tenants to customize documentation workflows per product.\n// =============================================================================\n\nenum DocumentRequirementContext {\n APPLICATION_PHASE // During a contract phase\n PAYMENT_METHOD_CHANGE // When changing payment method mid-contract\n}\n\nmodel DocumentRequirementRule {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Rule context\n context DocumentRequirementContext\n\n // Scoping (which situations this rule applies to)\n // For PREQUALIFICATION: paymentMethodId\n // For APPLICATION_PHASE: phaseType\n // For PAYMENT_METHOD_CHANGE: fromMethodId + toMethodId\n paymentMethodId String?\n paymentMethod PropertyPaymentMethod? @relation(\"RulePaymentMethod\", fields: [paymentMethodId], references: [id])\n phaseType String? // KYC, VERIFICATION, DOWNPAYMENT, etc.\n fromPaymentMethodId String?\n fromPaymentMethod PropertyPaymentMethod? @relation(\"RuleFromMethod\", fields: [fromPaymentMethodId], references: [id])\n toPaymentMethodId String?\n toPaymentMethod PropertyPaymentMethod? @relation(\"RuleToMethod\", fields: [toPaymentMethodId], references: [id])\n\n // Document requirements\n documentType String // ID_CARD, PASSPORT, BANK_STATEMENT, INCOME_PROOF, etc.\n isRequired Boolean @default(true)\n description String? // Instructions for the user\n maxSizeBytes Int? // Max file size allowed\n allowedMimeTypes String? // CSV: application/pdf,image/jpeg,image/png\n\n // Validation rules\n expiryDays Int? // Document must not be older than X days\n requiresManualReview Boolean @default(false)\n\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([context])\n @@index([paymentMethodId])\n @@index([phaseType])\n @@index([fromPaymentMethodId, toPaymentMethodId])\n @@map(\"document_requirement_rules\")\n}\n\n// =============================================================================\n// EVENT-DRIVEN WORKFLOW CONFIGURATION\n// =============================================================================\n// This system allows admins to configure event channels, types, and handlers\n// for a flexible, configurable event-driven workflow system.\n//\n// Architecture:\n// 1. EventChannel - Logical grouping of events (e.g., \"contracts\", \"payments\")\n// 2. EventType - Specific event types (e.g., \"DOCUMENT_UPLOADED\", \"STEP_COMPLETED\")\n// 3. EventHandler - What to do when an event fires (webhook, internal call, etc.)\n// 4. WorkflowEvent - Actual event instances (audit log)\n// 5. EventHandlerExecution - Log of handler executions\n// =============================================================================\n\n/// Event Channel - A logical grouping of events\n/// Channels help organize events and route them to appropriate handlers\nmodel EventChannel {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n /// Unique code for the channel (e.g., \"CONTRACTS\", \"PAYMENTS\")\n code String\n /// Human-readable name\n name String\n /// Description of what this channel handles\n description String? @db.Text\n\n /// Whether this channel is active\n enabled Boolean @default(true)\n\n /// Event types that belong to this channel\n eventTypes EventType[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([tenantId, code])\n @@index([tenantId])\n @@map(\"event_channels\")\n}\n\n/// Event Type - Defines a type of event that can occur\n/// Each event type belongs to a channel and can have multiple handlers\nmodel EventType {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n /// The channel this event type belongs to\n channelId String\n channel EventChannel @relation(fields: [channelId], references: [id], onDelete: Cascade)\n\n /// Unique code for this event type (e.g., \"DOCUMENT_UPLOADED\")\n code String\n /// Human-readable name\n name String\n /// Description of when this event fires\n description String? @db.Text\n\n /// JSON schema for event payload validation (optional)\n payloadSchema Json?\n\n /// Whether this event type is active\n enabled Boolean @default(true)\n\n /// Handlers subscribed to this event type\n handlers EventHandler[]\n\n /// Actual event instances of this type\n events WorkflowEvent[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([tenantId, code])\n @@unique([channelId, code])\n @@index([tenantId])\n @@index([channelId])\n @@map(\"event_types\")\n}\n\n/// Event Handler - Defines what should happen when an event fires\n/// Handlers can be internal (call a service), external (webhook), or workflow triggers\nmodel EventHandler {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n /// The event type this handler responds to\n eventTypeId String\n eventType EventType @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)\n\n /// Human-readable name\n name String\n /// Description of what this handler does\n description String? @db.Text\n\n /// Handler type determines how the event is processed\n handlerType EventHandlerType\n\n /// Configuration for the handler (JSON, depends on handlerType)\n /// INTERNAL: { \"service\": \"contract\", \"method\": \"completeStep\" }\n /// WEBHOOK: { \"url\": \"https://...\", \"method\": \"POST\", \"headers\": {...} }\n /// WORKFLOW: { \"workflowId\": \"...\", \"action\": \"advance\" }\n /// NOTIFICATION: { \"template\": \"...\", \"channels\": [\"email\", \"sms\"] }\n config Json\n\n /// Order of execution when multiple handlers exist (lower = first)\n priority Int @default(100)\n\n /// Whether this handler is active\n enabled Boolean @default(true)\n\n /// Retry configuration\n maxRetries Int @default(3)\n retryDelayMs Int @default(1000)\n\n /// Filter condition (JSONPath expression) to conditionally run\n /// e.g., \"$.payload.status == 'approved'\"\n filterCondition String? @db.Text\n\n /// Handler execution logs\n executions EventHandlerExecution[]\n\n /// Step attachments - steps that have attached this handler\n stepAttachments StepEventAttachment[]\n\n /// Phase attachments - phases that have attached this handler\n phaseAttachments PhaseEventAttachment[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([eventTypeId])\n @@index([handlerType])\n @@map(\"event_handlers\")\n}\n\n/// Workflow Event - An actual event instance that occurred\n/// This is the audit log of all events in the system\nmodel WorkflowEvent {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n /// The type of this event\n eventTypeId String\n eventType EventType @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)\n\n /// The event payload (actual data)\n payload Json\n\n /// Optional correlation ID to link related events\n correlationId String?\n\n /// Optional causation ID (which event caused this one)\n causationId String?\n\n /// Source of the event (service name, user action, etc.)\n source String\n\n /// Actor who triggered the event (user ID, API key ID, \"system\")\n actorId String?\n actorType ActorType @default(SYSTEM)\n\n /// Event status\n status WorkflowEventStatus @default(PENDING)\n\n /// Error message if processing failed\n error String? @db.Text\n\n /// When the event was processed\n processedAt DateTime?\n\n /// Handler executions for this event\n executions EventHandlerExecution[]\n\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([eventTypeId])\n @@index([correlationId])\n @@index([causationId])\n @@index([status])\n @@index([createdAt])\n @@map(\"workflow_events\")\n}\n\n/// Event Handler Execution - Log of a handler processing an event\nmodel EventHandlerExecution {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n /// The event being processed\n eventId String\n event WorkflowEvent @relation(fields: [eventId], references: [id], onDelete: Cascade)\n\n /// The handler that processed this event\n handlerId String\n handler EventHandler @relation(fields: [handlerId], references: [id], onDelete: Cascade)\n\n /// Execution status\n status ExecutionStatus @default(PENDING)\n\n /// Attempt number (1 for first try, increments on retry)\n attempt Int @default(1)\n\n /// Input to the handler (may be transformed payload)\n input Json?\n\n /// Output from the handler\n output Json?\n\n /// Error details if failed\n error String? @db.Text\n errorCode String?\n\n /// Timing\n startedAt DateTime?\n completedAt DateTime?\n durationMs Int?\n\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([eventId])\n @@index([handlerId])\n @@index([status])\n @@map(\"event_handler_executions\")\n}\n\n// =============================================================================\n// EVENT OUTBOX - For guaranteed event delivery to SQS queues\n// =============================================================================\n\nmodel DomainEvent {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Event identification\n eventType String // MORTGAGE.CREATED, PHASE.ACTIVATED, PAYMENT.COMPLETED, etc\n aggregateType String // Mortgage, MortgagePhase, MortgagePayment, Property, etc\n aggregateId String\n\n // Routing - which queue(s) should receive this\n queueName String // notifications, payments, mortgage-steps, accounting, etc\n\n // Event payload (all data needed by consumers)\n payload String @db.Text // JSON\n\n // Metadata\n occurredAt DateTime @default(now())\n actorId String? // User who triggered the event\n actorRole String? // Role of the actor\n\n // Processing status\n status String @default(\"PENDING\") // PENDING, PROCESSING, SENT, FAILED\n processedAt DateTime?\n sentAt DateTime?\n failureCount Int @default(0)\n lastError String? @db.Text\n nextRetryAt DateTime?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([status, nextRetryAt])\n @@index([eventType])\n @@index([aggregateType, aggregateId])\n @@index([queueName])\n @@index([occurredAt])\n @@map(\"domain_events\")\n}\n\n// =============================================================================\n// Property Transfer Request\n// =============================================================================\n// Allows a buyer to request transferring their contract to a different property.\n// \n// TRANSFER PAYMENT FLOW:\n// 1. All payments from source contract are refunded to buyer's wallet (single credit transaction)\n// 2. Source contract marked TRANSFERRED, unit released\n// 3. New contract created for target unit with zero payments\n// 4. Buyer can optionally apply wallet balance as equity during new mortgage application\n//\n// This ensures clean accounting: each contract has isolated payment history,\n// wallet serves as intermediary, and buyer retains full credit.\n// =============================================================================\n\nmodel PropertyTransferRequest {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Source contract being transferred\n sourceApplicationId String\n sourceApplication Application @relation(\"SourceApplication\", fields: [sourceApplicationId], references: [id], onDelete: Cascade)\n\n // Target property unit\n targetPropertyUnitId String\n targetPropertyUnit PropertyUnit @relation(fields: [targetPropertyUnitId], references: [id])\n\n // Requestor (buyer) and reviewer (admin)\n requestedById String\n requestedBy User @relation(\"TransferRequestor\", fields: [requestedById], references: [id])\n reviewedById String?\n reviewedBy User? @relation(\"TransferReviewer\", fields: [reviewedById], references: [id])\n\n // Status and workflow\n status TransferRequestStatus @default(PENDING)\n\n // Request details\n reason String? @db.Text // Buyer's reason for transfer\n\n // Review details\n reviewNotes String? @db.Text // Admin notes on decision\n priceAdjustmentHandling String? // How to handle price difference: ADD_TO_MORTGAGE, REQUIRE_PAYMENT, CREDIT_BUYER\n\n // Computed values\n sourceTotalAmount Float? // Original contract total\n targetTotalAmount Float? // New contract total (based on target property)\n priceAdjustment Float? // Difference (positive = buyer owes more)\n\n // Wallet refund tracking (payments refunded to wallet, NOT carried over)\n refundedAmount Float? // Total amount refunded to wallet\n refundTransactionId String? // Reference to wallet Transaction record\n refundedAt DateTime?\n\n // Result - new contract created after approval\n targetApplicationId String?\n targetApplication Application? @relation(\"TargetApplication\", fields: [targetApplicationId], references: [id])\n\n // Timestamps\n createdAt DateTime @default(now())\n reviewedAt DateTime?\n completedAt DateTime?\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([sourceApplicationId])\n @@index([targetPropertyUnitId])\n @@index([requestedById])\n @@index([status])\n @@map(\"property_transfer_requests\")\n}\n\n// =============================================================================\n// UNIFIED APPROVAL REQUESTS\n// =============================================================================\n\nenum ApprovalRequestType {\n PROPERTY_TRANSFER // Property unit transfer between contracts\n PROPERTY_UPDATE // Property/unit listing update requiring approval\n USER_WORKFLOW // User workflow step approval\n CREDIT_CHECK // Credit check result review\n APPLICATION_TERMINATION // Contract termination approval\n REFUND_APPROVAL // Refund request approval\n}\n\nenum ApprovalRequestStatus {\n PENDING // Awaiting review\n IN_REVIEW // Assigned to reviewer\n APPROVED // Approved by reviewer\n REJECTED // Rejected by reviewer\n CANCELLED // Cancelled by requestor\n EXPIRED // Auto-expired (if TTL configured)\n}\n\nenum ApprovalRequestPriority {\n LOW\n NORMAL\n HIGH\n URGENT\n}\n\n// Polymorphic approval request model for unified admin dashboard\nmodel ApprovalRequest {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Request type and status\n type ApprovalRequestType\n status ApprovalRequestStatus @default(PENDING)\n priority ApprovalRequestPriority @default(NORMAL)\n\n // Polymorphic reference to the entity requiring approval\n entityType String // e.g., \"PropertyTransferRequest\", \"PropertyUnit\", \"User\"\n entityId String // ID of the referenced entity\n\n // Request metadata\n title String @db.VarChar(255) // Human-readable title for the request\n description String? @db.Text // Detailed description\n\n // Payload for any additional context (JSON)\n payload Json? // Flexible data storage for type-specific details\n\n // Requestor - who created the request\n requestedById String\n requestedBy User @relation(\"ApprovalRequestor\", fields: [requestedById], references: [id])\n\n // Assignee - admin/reviewer assigned to handle this request\n assigneeId String?\n assignee User? @relation(\"ApprovalAssignee\", fields: [assigneeId], references: [id])\n\n // Reviewer - who made the final decision (may differ from assignee)\n reviewedById String?\n reviewedBy User? @relation(\"ApprovalReviewer\", fields: [reviewedById], references: [id])\n\n // Review details\n reviewNotes String? @db.Text // Reviewer's notes/comments\n decision ApprovalDecision? // APPROVED, REJECTED, REQUEST_CHANGES\n\n // Expiration\n expiresAt DateTime? // Optional TTL for auto-expiration\n\n // Timestamps\n createdAt DateTime @default(now())\n assignedAt DateTime? // When assigned to reviewer\n reviewedAt DateTime? // When decision was made\n completedAt DateTime? // When fully processed\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([type])\n @@index([status])\n @@index([priority])\n @@index([entityType, entityId])\n @@index([requestedById])\n @@index([assigneeId])\n @@index([createdAt])\n @@index([type, status]) // Efficient queries for approval dashboard\n @@map(\"approval_requests\")\n}\n\n// =============================================================================\n// WORKFLOW BLOCKER TRACKING - Analytics for workflow delays\n// =============================================================================\n// Tracks who is blocking the workflow at any point, enabling analytics like:\n// - Average time customers take to upload documents\n// - Average time admins take to review/approve\n// - Most common bottleneck steps\n// - SLA compliance tracking\n// - Customer service intervention triggers\n// =============================================================================\n\n/// Who is responsible for the current workflow block\nenum BlockerActor {\n CUSTOMER // Customer action required (upload, sign, pay)\n ADMIN // Admin action required (review, approve, reject)\n SYSTEM // System processing (auto-generation, external checks)\n EXTERNAL // External party (bank, government, third-party verification)\n}\n\n/// Category of action that is blocking workflow\nenum BlockerCategory {\n UPLOAD // Document upload needed\n RESUBMISSION // Document resubmission after rejection\n SIGNATURE // Signature required\n REVIEW // Admin review needed\n APPROVAL // Admin approval needed\n PAYMENT // Payment required\n PROCESSING // System processing\n EXTERNAL_CHECK // External verification\n QUESTIONNAIRE // Form/questionnaire completion\n}\n\n/// Urgency level for prioritization and SLA tracking\nenum BlockerUrgency {\n LOW // No immediate deadline\n NORMAL // Standard processing\n HIGH // Approaching deadline or overdue\n CRITICAL // Significantly overdue or business-critical\n}\n\n/// Workflow Blocker - Records who is blocking workflow and for how long\nmodel WorkflowBlocker {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Reference to the blocked entity\n applicationId String\n phaseId String?\n stepId String?\n\n // Actor and action details\n blockerActor BlockerActor\n blockerCategory BlockerCategory\n urgency BlockerUrgency @default(NORMAL)\n\n // Human-readable descriptions\n actionRequired String @db.VarChar(500) // What action is needed\n context String? @db.Text // Additional context\n\n // SLA tracking\n expectedByDate DateTime? // When this action should be completed\n isOverdue Boolean @default(false)\n overdueAt DateTime? // When it became overdue\n\n // Duration tracking\n startedAt DateTime @default(now()) // When this block started\n resolvedAt DateTime? // When it was resolved\n durationMs Int? // Calculated duration on resolution\n\n // Resolution details\n resolvedByActor String? // Who resolved it (userId or \"SYSTEM\")\n resolutionTrigger String? // What action resolved it (e.g., \"DOCUMENT_UPLOADED\", \"STEP_COMPLETED\")\n\n // Reminder tracking (for customer service)\n reminderCount Int @default(0) // Number of reminders sent\n lastReminderAt DateTime? // Last reminder timestamp\n nextReminderAt DateTime? // Scheduled next reminder\n\n // Metadata for additional analytics\n metadata Json? // Flexible data: { documentType, stepType, phaseType, etc. }\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([phaseId])\n @@index([stepId])\n @@index([blockerActor])\n @@index([blockerCategory])\n @@index([urgency])\n @@index([isOverdue])\n @@index([startedAt])\n @@index([resolvedAt])\n @@index([tenantId, blockerActor, resolvedAt]) // For \"open blockers by actor\" queries\n @@index([tenantId, blockerCategory, resolvedAt]) // For \"open blockers by category\" queries\n @@index([tenantId, isOverdue, blockerActor]) // For SLA violation queries\n @@map(\"workflow_blockers\")\n}\n",
19
19
  "runtimeDataModel": {
20
20
  "models": {},
21
21
  "enums": {},
22
22
  "types": {}
23
23
  }
24
24
  };
25
- config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phone\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"firstName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isEmailVerified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"googleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"avatar\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToUser\"},{\"name\":\"tenantMemberships\",\"kind\":\"object\",\"type\":\"TenantMembership\",\"relationName\":\"TenantMembershipToUser\"},{\"name\":\"userRoles\",\"kind\":\"object\",\"type\":\"UserRole\",\"relationName\":\"UserToUserRole\"},{\"name\":\"walletId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"wallet\",\"kind\":\"object\",\"type\":\"Wallet\",\"relationName\":\"UserToWallet\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"emailVerifiedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"emailVerificationToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastLoginAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refreshTokens\",\"kind\":\"object\",\"type\":\"RefreshToken\",\"relationName\":\"RefreshTokenToUser\"},{\"name\":\"passwordResets\",\"kind\":\"object\",\"type\":\"PasswordReset\",\"relationName\":\"PasswordResetToUser\"},{\"name\":\"suspensions\",\"kind\":\"object\",\"type\":\"UserSuspension\",\"relationName\":\"UserToUserSuspension\"},{\"name\":\"emailPreferences\",\"kind\":\"object\",\"type\":\"EmailPreference\",\"relationName\":\"EmailPreferenceToUser\"},{\"name\":\"deviceEndpoints\",\"kind\":\"object\",\"type\":\"DeviceEndpoint\",\"relationName\":\"DeviceEndpointToUser\"},{\"name\":\"socials\",\"kind\":\"object\",\"type\":\"Social\",\"relationName\":\"SocialToUser\"},{\"name\":\"properties\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToUser\"},{\"name\":\"applications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationBuyer\"},{\"name\":\"soldApplications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationSeller\"},{\"name\":\"applicationPayments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationPayer\"},{\"name\":\"assignedSteps\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"DocumentationStepAssignee\"},{\"name\":\"stepApprovals\",\"kind\":\"object\",\"type\":\"DocumentationStepApproval\",\"relationName\":\"DocumentationStepApprover\"},{\"name\":\"uploadedDocs\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"DocumentUploader\"},{\"name\":\"paymentMethodChangeRequests\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"ChangeRequestor\"},{\"name\":\"reviewedChangeRequests\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"ChangeReviewer\"},{\"name\":\"initiatedTerminations\",\"kind\":\"object\",\"type\":\"ApplicationTermination\",\"relationName\":\"TerminationInitiator\"},{\"name\":\"reviewedTerminations\",\"kind\":\"object\",\"type\":\"ApplicationTermination\",\"relationName\":\"TerminationReviewer\"},{\"name\":\"offerLettersGenerated\",\"kind\":\"object\",\"type\":\"OfferLetter\",\"relationName\":\"OfferLetterGenerator\"},{\"name\":\"offerLettersSent\",\"kind\":\"object\",\"type\":\"OfferLetter\",\"relationName\":\"OfferLetterSender\"},{\"name\":\"transferRequestsSubmitted\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"TransferRequestor\"},{\"name\":\"transferRequestsReviewed\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"TransferReviewer\"},{\"name\":\"approvalRequestsSubmitted\",\"kind\":\"object\",\"type\":\"ApprovalRequest\",\"relationName\":\"ApprovalRequestor\"},{\"name\":\"approvalRequestsAssigned\",\"kind\":\"object\",\"type\":\"ApprovalRequest\",\"relationName\":\"ApprovalAssignee\"},{\"name\":\"approvalRequestsReviewed\",\"kind\":\"object\",\"type\":\"ApprovalRequest\",\"relationName\":\"ApprovalReviewer\"},{\"name\":\"requestedRefunds\",\"kind\":\"object\",\"type\":\"ApplicationRefund\",\"relationName\":\"RefundRequester\"},{\"name\":\"approvedRefunds\",\"kind\":\"object\",\"type\":\"ApplicationRefund\",\"relationName\":\"RefundApprover\"},{\"name\":\"processedRefunds\",\"kind\":\"object\",\"type\":\"ApplicationRefund\",\"relationName\":\"RefundProcessor\"}],\"dbName\":\"users\"},\"Role\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"RoleToTenant\"},{\"name\":\"isSystem\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"userRoles\",\"kind\":\"object\",\"type\":\"UserRole\",\"relationName\":\"RoleToUserRole\"},{\"name\":\"memberships\",\"kind\":\"object\",\"type\":\"TenantMembership\",\"relationName\":\"RoleToTenantMembership\"},{\"name\":\"permissions\",\"kind\":\"object\",\"type\":\"RolePermission\",\"relationName\":\"RoleToRolePermission\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"roles\"},\"Permission\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"path\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"methods\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"effect\",\"kind\":\"enum\",\"type\":\"PermissionEffect\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PermissionToTenant\"},{\"name\":\"isSystem\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"roles\",\"kind\":\"object\",\"type\":\"RolePermission\",\"relationName\":\"PermissionToRolePermission\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"permissions\"},\"RolePermission\":{\"fields\":[{\"name\":\"roleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"permissionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"role\",\"kind\":\"object\",\"type\":\"Role\",\"relationName\":\"RoleToRolePermission\"},{\"name\":\"permission\",\"kind\":\"object\",\"type\":\"Permission\",\"relationName\":\"PermissionToRolePermission\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"role_permissions\"},\"UserRole\":{\"fields\":[{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"roleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToUserRole\"},{\"name\":\"role\",\"kind\":\"object\",\"type\":\"Role\",\"relationName\":\"RoleToUserRole\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"user_roles\"},\"TenantMembership\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"roleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TenantMembershipToUser\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToTenantMembership\"},{\"name\":\"role\",\"kind\":\"object\",\"type\":\"Role\",\"relationName\":\"RoleToTenantMembership\"}],\"dbName\":\"tenant_memberships\"},\"Tenant\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"subdomain\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"users\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TenantToUser\"},{\"name\":\"properties\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToTenant\"},{\"name\":\"paymentPlans\",\"kind\":\"object\",\"type\":\"PaymentPlan\",\"relationName\":\"PaymentPlanToTenant\"},{\"name\":\"documentationPlans\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"DocumentationPlanToTenant\"},{\"name\":\"paymentMethods\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"PropertyPaymentMethodToTenant\"},{\"name\":\"applications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToTenant\"},{\"name\":\"roles\",\"kind\":\"object\",\"type\":\"Role\",\"relationName\":\"RoleToTenant\"},{\"name\":\"permissions\",\"kind\":\"object\",\"type\":\"Permission\",\"relationName\":\"PermissionToTenant\"},{\"name\":\"memberships\",\"kind\":\"object\",\"type\":\"TenantMembership\",\"relationName\":\"TenantToTenantMembership\"},{\"name\":\"paymentMethodChangeRequests\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"PaymentMethodChangeRequestToTenant\"},{\"name\":\"documentRequirementRules\",\"kind\":\"object\",\"type\":\"DocumentRequirementRule\",\"relationName\":\"DocumentRequirementRuleToTenant\"},{\"name\":\"contractTerminations\",\"kind\":\"object\",\"type\":\"ApplicationTermination\",\"relationName\":\"ApplicationTerminationToTenant\"},{\"name\":\"documentTemplates\",\"kind\":\"object\",\"type\":\"DocumentTemplate\",\"relationName\":\"DocumentTemplateToTenant\"},{\"name\":\"offerLetters\",\"kind\":\"object\",\"type\":\"OfferLetter\",\"relationName\":\"OfferLetterToTenant\"},{\"name\":\"apiKeys\",\"kind\":\"object\",\"type\":\"ApiKey\",\"relationName\":\"ApiKeyToTenant\"},{\"name\":\"eventChannels\",\"kind\":\"object\",\"type\":\"EventChannel\",\"relationName\":\"EventChannelToTenant\"},{\"name\":\"eventTypes\",\"kind\":\"object\",\"type\":\"EventType\",\"relationName\":\"EventTypeToTenant\"},{\"name\":\"eventHandlers\",\"kind\":\"object\",\"type\":\"EventHandler\",\"relationName\":\"EventHandlerToTenant\"},{\"name\":\"workflowEvents\",\"kind\":\"object\",\"type\":\"WorkflowEvent\",\"relationName\":\"TenantToWorkflowEvent\"},{\"name\":\"propertyTransferRequests\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"PropertyTransferRequestToTenant\"},{\"name\":\"approvalRequests\",\"kind\":\"object\",\"type\":\"ApprovalRequest\",\"relationName\":\"ApprovalRequestToTenant\"},{\"name\":\"contractRefunds\",\"kind\":\"object\",\"type\":\"ApplicationRefund\",\"relationName\":\"ApplicationRefundToTenant\"},{\"name\":\"propertyPaymentMethodLinks\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodLink\",\"relationName\":\"PropertyPaymentMethodLinkToTenant\"},{\"name\":\"propertyPaymentMethodPhases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PropertyPaymentMethodPhaseToTenant\"},{\"name\":\"phaseEventAttachments\",\"kind\":\"object\",\"type\":\"PhaseEventAttachment\",\"relationName\":\"PhaseEventAttachmentToTenant\"},{\"name\":\"paymentMethodPhaseSteps\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseStep\",\"relationName\":\"PaymentMethodPhaseStepToTenant\"},{\"name\":\"stepEventAttachments\",\"kind\":\"object\",\"type\":\"StepEventAttachment\",\"relationName\":\"StepEventAttachmentToTenant\"},{\"name\":\"paymentMethodPhaseDocuments\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseDocument\",\"relationName\":\"PaymentMethodPhaseDocumentToTenant\"},{\"name\":\"paymentMethodPhaseFields\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseField\",\"relationName\":\"PaymentMethodPhaseFieldToTenant\"},{\"name\":\"applicationPhases\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPhaseToTenant\"},{\"name\":\"questionnairePhases\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"QuestionnairePhaseToTenant\"},{\"name\":\"documentationPhases\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"DocumentationPhaseToTenant\"},{\"name\":\"paymentPhases\",\"kind\":\"object\",\"type\":\"PaymentPhase\",\"relationName\":\"PaymentPhaseToTenant\"},{\"name\":\"questionnaireFields\",\"kind\":\"object\",\"type\":\"QuestionnaireField\",\"relationName\":\"QuestionnaireFieldToTenant\"},{\"name\":\"applicationEvents\",\"kind\":\"object\",\"type\":\"ApplicationEvent\",\"relationName\":\"ApplicationEventToTenant\"},{\"name\":\"documentationSteps\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"DocumentationStepToTenant\"},{\"name\":\"documentationStepDocuments\",\"kind\":\"object\",\"type\":\"DocumentationStepDocument\",\"relationName\":\"DocumentationStepDocumentToTenant\"},{\"name\":\"documentationStepApprovals\",\"kind\":\"object\",\"type\":\"DocumentationStepApproval\",\"relationName\":\"DocumentationStepApprovalToTenant\"},{\"name\":\"paymentInstallments\",\"kind\":\"object\",\"type\":\"PaymentInstallment\",\"relationName\":\"PaymentInstallmentToTenant\"},{\"name\":\"applicationPayments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationPaymentToTenant\"},{\"name\":\"applicationDocuments\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"ApplicationDocumentToTenant\"},{\"name\":\"propertyMedia\",\"kind\":\"object\",\"type\":\"PropertyMedia\",\"relationName\":\"PropertyMediaToTenant\"},{\"name\":\"propertyDocuments\",\"kind\":\"object\",\"type\":\"PropertyDocument\",\"relationName\":\"PropertyDocumentToTenant\"},{\"name\":\"propertyVariants\",\"kind\":\"object\",\"type\":\"PropertyVariant\",\"relationName\":\"PropertyVariantToTenant\"},{\"name\":\"propertyVariantAmenities\",\"kind\":\"object\",\"type\":\"PropertyVariantAmenity\",\"relationName\":\"PropertyVariantAmenityToTenant\"},{\"name\":\"propertyVariantMedia\",\"kind\":\"object\",\"type\":\"PropertyVariantMedia\",\"relationName\":\"PropertyVariantMediaToTenant\"},{\"name\":\"propertyUnits\",\"kind\":\"object\",\"type\":\"PropertyUnit\",\"relationName\":\"PropertyUnitToTenant\"},{\"name\":\"propertyAmenities\",\"kind\":\"object\",\"type\":\"PropertyAmenity\",\"relationName\":\"PropertyAmenityToTenant\"},{\"name\":\"eventHandlerExecutions\",\"kind\":\"object\",\"type\":\"EventHandlerExecution\",\"relationName\":\"EventHandlerExecutionToTenant\"},{\"name\":\"amenities\",\"kind\":\"object\",\"type\":\"Amenity\",\"relationName\":\"AmenityToTenant\"},{\"name\":\"socials\",\"kind\":\"object\",\"type\":\"Social\",\"relationName\":\"SocialToTenant\"},{\"name\":\"wallets\",\"kind\":\"object\",\"type\":\"Wallet\",\"relationName\":\"TenantToWallet\"},{\"name\":\"transactions\",\"kind\":\"object\",\"type\":\"Transaction\",\"relationName\":\"TenantToTransaction\"},{\"name\":\"settings\",\"kind\":\"object\",\"type\":\"Settings\",\"relationName\":\"SettingsToTenant\"},{\"name\":\"domainEvents\",\"kind\":\"object\",\"type\":\"DomainEvent\",\"relationName\":\"DomainEventToTenant\"},{\"name\":\"workflowBlockers\",\"kind\":\"object\",\"type\":\"WorkflowBlocker\",\"relationName\":\"TenantToWorkflowBlocker\"},{\"name\":\"questionnairePlans\",\"kind\":\"object\",\"type\":\"QuestionnairePlan\",\"relationName\":\"QuestionnairePlanToTenant\"}],\"dbName\":\"tenants\"},\"ApiKey\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApiKeyToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"provider\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"secretRef\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scopes\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"lastUsedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"revokedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"revokedBy\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdBy\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"api_keys\"},\"RefreshToken\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"jti\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"RefreshTokenToUser\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"refresh_tokens\"},\"PasswordReset\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PasswordResetToUser\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"usedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"password_resets\"},\"UserSuspension\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToUserSuspension\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"suspendedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"liftedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"user_suspensions\"},\"EmailPreference\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EmailPreferenceToUser\"},{\"name\":\"marketingEmails\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"transactionalEmails\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"propertyAlerts\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"paymentReminders\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"email_preferences\"},\"DeviceEndpoint\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DeviceEndpointToUser\"},{\"name\":\"endpoint\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"platform\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"device_endpoints\"},\"Social\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"SocialToTenant\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SocialToUser\"},{\"name\":\"provider\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"socialId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"socials\"},\"OAuthState\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"state\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"oauth_states\"},\"Wallet\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToWallet\"},{\"name\":\"balance\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"currency\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToWallet\"},{\"name\":\"transactions\",\"kind\":\"object\",\"type\":\"Transaction\",\"relationName\":\"TransactionToWallet\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"wallets\"},\"Transaction\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToTransaction\"},{\"name\":\"walletId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"wallet\",\"kind\":\"object\",\"type\":\"Wallet\",\"relationName\":\"TransactionToWallet\"},{\"name\":\"amount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reference\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"transactions\"},\"Settings\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"SettingsToTenant\"},{\"name\":\"key\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"category\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"settings\"},\"Property\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyToTenant\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PropertyToUser\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"category\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"propertyType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"country\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"currency\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"city\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"district\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"zipCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"streetAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"longitude\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"latitude\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayImageId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayImage\",\"kind\":\"object\",\"type\":\"PropertyMedia\",\"relationName\":\"DisplayImage\"},{\"name\":\"isPublished\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"publishedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"documents\",\"kind\":\"object\",\"type\":\"PropertyDocument\",\"relationName\":\"PropertyToPropertyDocument\"},{\"name\":\"media\",\"kind\":\"object\",\"type\":\"PropertyMedia\",\"relationName\":\"PropertyMedia\"},{\"name\":\"amenities\",\"kind\":\"object\",\"type\":\"PropertyAmenity\",\"relationName\":\"PropertyToPropertyAmenity\"},{\"name\":\"paymentMethods\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodLink\",\"relationName\":\"PropertyToPropertyPaymentMethodLink\"},{\"name\":\"variants\",\"kind\":\"object\",\"type\":\"PropertyVariant\",\"relationName\":\"PropertyToPropertyVariant\"}],\"dbName\":\"properties\"},\"PropertyMedia\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyMediaToTenant\"},{\"name\":\"propertyId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"property\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyMedia\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"caption\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"displayForProperties\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"DisplayImage\"}],\"dbName\":\"property_media\"},\"PropertyDocument\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyDocumentToTenant\"},{\"name\":\"propertyId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"property\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToPropertyDocument\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_documents\"},\"Amenity\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"AmenityToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"category\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"icon\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"properties\",\"kind\":\"object\",\"type\":\"PropertyAmenity\",\"relationName\":\"AmenityToPropertyAmenity\"},{\"name\":\"variants\",\"kind\":\"object\",\"type\":\"PropertyVariantAmenity\",\"relationName\":\"AmenityToPropertyVariantAmenity\"}],\"dbName\":\"amenities\"},\"PropertyVariant\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyVariantToTenant\"},{\"name\":\"propertyId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"property\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToPropertyVariant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"nBedrooms\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"nBathrooms\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"nParkingSpots\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"area\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"price\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"pricePerSqm\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"totalUnits\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"availableUnits\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"reservedUnits\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"soldUnits\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"amenities\",\"kind\":\"object\",\"type\":\"PropertyVariantAmenity\",\"relationName\":\"PropertyVariantToPropertyVariantAmenity\"},{\"name\":\"units\",\"kind\":\"object\",\"type\":\"PropertyUnit\",\"relationName\":\"PropertyUnitToPropertyVariant\"},{\"name\":\"media\",\"kind\":\"object\",\"type\":\"PropertyVariantMedia\",\"relationName\":\"PropertyVariantToPropertyVariantMedia\"}],\"dbName\":\"property_variants\"},\"PropertyVariantAmenity\":{\"fields\":[{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyVariantAmenityToTenant\"},{\"name\":\"variantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"amenityId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"variant\",\"kind\":\"object\",\"type\":\"PropertyVariant\",\"relationName\":\"PropertyVariantToPropertyVariantAmenity\"},{\"name\":\"amenity\",\"kind\":\"object\",\"type\":\"Amenity\",\"relationName\":\"AmenityToPropertyVariantAmenity\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_variant_amenities\"},\"PropertyVariantMedia\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyVariantMediaToTenant\"},{\"name\":\"variantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"variant\",\"kind\":\"object\",\"type\":\"PropertyVariant\",\"relationName\":\"PropertyVariantToPropertyVariantMedia\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"caption\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_variant_media\"},\"PropertyUnit\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyUnitToTenant\"},{\"name\":\"variantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"variant\",\"kind\":\"object\",\"type\":\"PropertyVariant\",\"relationName\":\"PropertyUnitToPropertyVariant\"},{\"name\":\"unitNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"floorNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"blockName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"priceOverride\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"areaOverride\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"notes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reservedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reservedUntil\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reservedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ownerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"applications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToPropertyUnit\"},{\"name\":\"transferRequests\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"PropertyTransferRequestToPropertyUnit\"}],\"dbName\":\"property_units\"},\"PropertyAmenity\":{\"fields\":[{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyAmenityToTenant\"},{\"name\":\"propertyId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"amenityId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"property\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToPropertyAmenity\"},{\"name\":\"amenity\",\"kind\":\"object\",\"type\":\"Amenity\",\"relationName\":\"AmenityToPropertyAmenity\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_amenities\"},\"DocumentationPlan\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentationPlanToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"requiredDocumentTypes\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"steps\",\"kind\":\"object\",\"type\":\"DocumentationPlanStep\",\"relationName\":\"DocumentationPlanToDocumentationPlanStep\"},{\"name\":\"methodPhases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"DocumentationPlanToPropertyPaymentMethodPhase\"},{\"name\":\"documentationPhases\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"DocumentationPhaseToDocumentationPlan\"}],\"dbName\":\"documentation_plans\"},\"DocumentationPlanStep\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"planId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"plan\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"DocumentationPlanToDocumentationPlanStep\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stepType\",\"kind\":\"enum\",\"type\":\"StepType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"maxSizeBytes\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"allowedMimeTypes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiryDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"requiresManualReview\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"minFiles\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxFiles\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"condition\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"documentation_plan_steps\"},\"QuestionnairePlan\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"QuestionnairePlanToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"passingScore\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"scoringStrategy\",\"kind\":\"enum\",\"type\":\"ScoringStrategy\"},{\"name\":\"autoDecisionEnabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"estimatedMinutes\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"category\",\"kind\":\"enum\",\"type\":\"QuestionnaireCategory\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"questions\",\"kind\":\"object\",\"type\":\"QuestionnairePlanQuestion\",\"relationName\":\"QuestionnairePlanToQuestionnairePlanQuestion\"},{\"name\":\"methodPhases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PropertyPaymentMethodPhaseToQuestionnairePlan\"},{\"name\":\"questionnairePhases\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"QuestionnairePhaseToQuestionnairePlan\"}],\"dbName\":\"questionnaire_plans\"},\"QuestionnairePlanQuestion\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePlan\",\"kind\":\"object\",\"type\":\"QuestionnairePlan\",\"relationName\":\"QuestionnairePlanToQuestionnairePlanQuestion\"},{\"name\":\"questionKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionText\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"helpText\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionType\",\"kind\":\"enum\",\"type\":\"QuestionType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"validationRules\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"options\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"scoreWeight\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"scoringRules\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"showIf\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"category\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"questionnaire_plan_questions\"},\"PaymentPlan\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentPlanToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"paymentFrequency\",\"kind\":\"enum\",\"type\":\"PaymentFrequency\"},{\"name\":\"customFrequencyDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"numberOfInstallments\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"calculateInterestDaily\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"gracePeriodDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"allowFlexibleTerm\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"minTermMonths\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxTermMonths\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"termStepMonths\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxAgeAtMaturity\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"collectFunds\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"methodPhases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PaymentPlanToPropertyPaymentMethodPhase\"},{\"name\":\"paymentPhases\",\"kind\":\"object\",\"type\":\"PaymentPhase\",\"relationName\":\"PaymentPhaseToPaymentPlan\"}],\"dbName\":\"payment_plans\"},\"PropertyPaymentMethod\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyPaymentMethodToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"allowEarlyPayoff\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"earlyPayoffPenaltyRate\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"autoActivatePhases\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"requiresManualApproval\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"properties\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodLink\",\"relationName\":\"PropertyPaymentMethodToPropertyPaymentMethodLink\"},{\"name\":\"phases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PropertyPaymentMethodToPropertyPaymentMethodPhase\"},{\"name\":\"applications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToPropertyPaymentMethod\"},{\"name\":\"changeRequestsFrom\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"ChangeFromMethod\"},{\"name\":\"changeRequestsTo\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"ChangeToMethod\"},{\"name\":\"documentRules\",\"kind\":\"object\",\"type\":\"DocumentRequirementRule\",\"relationName\":\"RulePaymentMethod\"},{\"name\":\"changeRulesFrom\",\"kind\":\"object\",\"type\":\"DocumentRequirementRule\",\"relationName\":\"RuleFromMethod\"},{\"name\":\"changeRulesTo\",\"kind\":\"object\",\"type\":\"DocumentRequirementRule\",\"relationName\":\"RuleToMethod\"}],\"dbName\":\"property_payment_methods\"},\"PropertyPaymentMethodLink\":{\"fields\":[{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyPaymentMethodLinkToTenant\"},{\"name\":\"propertyId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"property\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToPropertyPaymentMethodLink\"},{\"name\":\"paymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"PropertyPaymentMethodToPropertyPaymentMethodLink\"},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_payment_method_links\"},\"PropertyPaymentMethodPhase\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyPaymentMethodPhaseToTenant\"},{\"name\":\"paymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"PropertyPaymentMethodToPropertyPaymentMethodPhase\"},{\"name\":\"paymentPlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentPlan\",\"kind\":\"object\",\"type\":\"PaymentPlan\",\"relationName\":\"PaymentPlanToPropertyPaymentMethodPhase\"},{\"name\":\"documentationPlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentationPlan\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"DocumentationPlanToPropertyPaymentMethodPhase\"},{\"name\":\"questionnairePlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePlan\",\"kind\":\"object\",\"type\":\"QuestionnairePlan\",\"relationName\":\"PropertyPaymentMethodPhaseToQuestionnairePlan\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phaseCategory\",\"kind\":\"enum\",\"type\":\"PhaseCategory\"},{\"name\":\"phaseType\",\"kind\":\"enum\",\"type\":\"PhaseType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"interestRate\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"percentOfPrice\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"collectFunds\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"requiresPreviousPhaseCompletion\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"minimumCompletionPercentage\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"completionCriterion\",\"kind\":\"enum\",\"type\":\"CompletionCriterion\"},{\"name\":\"lockUnitOnComplete\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"stepDefinitionsSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"requiredDocumentSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"steps\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseStep\",\"relationName\":\"PaymentMethodPhaseStepToPropertyPaymentMethodPhase\"},{\"name\":\"requiredDocuments\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseDocument\",\"relationName\":\"PaymentMethodPhaseDocumentToPropertyPaymentMethodPhase\"},{\"name\":\"questionnaireFields\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseField\",\"relationName\":\"PaymentMethodPhaseFieldToPropertyPaymentMethodPhase\"},{\"name\":\"eventAttachments\",\"kind\":\"object\",\"type\":\"PhaseEventAttachment\",\"relationName\":\"PhaseEventAttachmentToPropertyPaymentMethodPhase\"},{\"name\":\"applicationPhases\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPhaseToPropertyPaymentMethodPhase\"}],\"dbName\":\"property_payment_method_phases\"},\"PhaseEventAttachment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PhaseEventAttachmentToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PhaseEventAttachmentToPropertyPaymentMethodPhase\"},{\"name\":\"trigger\",\"kind\":\"enum\",\"type\":\"PhaseTrigger\"},{\"name\":\"handlerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"handler\",\"kind\":\"object\",\"type\":\"EventHandler\",\"relationName\":\"EventHandlerToPhaseEventAttachment\"},{\"name\":\"priority\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"phase_event_attachments\"},\"PaymentMethodPhaseStep\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentMethodPhaseStepToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PaymentMethodPhaseStepToPropertyPaymentMethodPhase\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stepType\",\"kind\":\"enum\",\"type\":\"StepType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"eventAttachments\",\"kind\":\"object\",\"type\":\"StepEventAttachment\",\"relationName\":\"PaymentMethodPhaseStepToStepEventAttachment\"}],\"dbName\":\"payment_method_phase_steps\"},\"StepEventAttachment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"StepEventAttachmentToTenant\"},{\"name\":\"stepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"step\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseStep\",\"relationName\":\"PaymentMethodPhaseStepToStepEventAttachment\"},{\"name\":\"trigger\",\"kind\":\"enum\",\"type\":\"StepTrigger\"},{\"name\":\"handlerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"handler\",\"kind\":\"object\",\"type\":\"EventHandler\",\"relationName\":\"EventHandlerToStepEventAttachment\"},{\"name\":\"priority\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"step_event_attachments\"},\"PaymentMethodPhaseDocument\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentMethodPhaseDocumentToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PaymentMethodPhaseDocumentToPropertyPaymentMethodPhase\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"allowedMimeTypes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"maxSizeBytes\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"payment_method_phase_documents\"},\"PaymentMethodPhaseField\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentMethodPhaseFieldToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PaymentMethodPhaseFieldToPropertyPaymentMethodPhase\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"label\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"placeholder\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fieldType\",\"kind\":\"enum\",\"type\":\"FieldType\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"validation\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"displayCondition\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"defaultValue\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"payment_method_phase_fields\"},\"Application\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationToTenant\"},{\"name\":\"propertyUnitId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"propertyUnit\",\"kind\":\"object\",\"type\":\"PropertyUnit\",\"relationName\":\"ApplicationToPropertyUnit\"},{\"name\":\"buyerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"buyer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApplicationBuyer\"},{\"name\":\"sellerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"seller\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApplicationSeller\"},{\"name\":\"paymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"ApplicationToPropertyPaymentMethod\"},{\"name\":\"applicationNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"applicationType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"totalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ApplicationStatus\"},{\"name\":\"currentPhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"currentPhase\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"CurrentPhase\"},{\"name\":\"nextPaymentDueDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"lastReminderSentAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"startDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"endDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"signedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"terminatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"phases\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationToApplicationPhase\"},{\"name\":\"documents\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"ApplicationToApplicationDocument\"},{\"name\":\"payments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationToApplicationPayment\"},{\"name\":\"terminations\",\"kind\":\"object\",\"type\":\"ApplicationTermination\",\"relationName\":\"ApplicationToApplicationTermination\"},{\"name\":\"offerLetters\",\"kind\":\"object\",\"type\":\"OfferLetter\",\"relationName\":\"ApplicationToOfferLetter\"},{\"name\":\"paymentMethodChangeRequests\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"ApplicationToPaymentMethodChangeRequest\"},{\"name\":\"transferredFromId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"transferredFrom\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationTransfer\"},{\"name\":\"transferredTo\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationTransfer\"},{\"name\":\"supersededById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"supersededBy\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationSuperseded\"},{\"name\":\"supersededAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"supersededApplications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationSuperseded\"},{\"name\":\"outgoingTransferRequests\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"SourceApplication\"},{\"name\":\"incomingTransferRequests\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"TargetApplication\"},{\"name\":\"events\",\"kind\":\"object\",\"type\":\"ApplicationEvent\",\"relationName\":\"ApplicationToApplicationEvent\"},{\"name\":\"refunds\",\"kind\":\"object\",\"type\":\"ApplicationRefund\",\"relationName\":\"ApplicationToApplicationRefund\"}],\"dbName\":\"applications\"},\"ApplicationRefund\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationRefundToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationRefund\"},{\"name\":\"amount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"RefundStatus\"},{\"name\":\"requestedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"RefundRequester\"},{\"name\":\"approvedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"approvedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"RefundApprover\"},{\"name\":\"processedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"RefundProcessor\"},{\"name\":\"paymentMethod\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"referenceNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"recipientName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"recipientAccount\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"recipientBank\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"approvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"rejectedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"approvalNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"rejectionNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processingNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_refunds\"},\"ApplicationPhase\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationPhaseToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationPhase\"},{\"name\":\"phaseTemplateId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phaseTemplate\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"ApplicationPhaseToPropertyPaymentMethodPhase\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phaseCategory\",\"kind\":\"enum\",\"type\":\"PhaseCategory\"},{\"name\":\"phaseType\",\"kind\":\"enum\",\"type\":\"PhaseType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"PhaseStatus\"},{\"name\":\"dueDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"startDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"endDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"activatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"requiresPreviousPhaseCompletion\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"questionnairePhase\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"ApplicationPhaseToQuestionnairePhase\"},{\"name\":\"documentationPhase\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"ApplicationPhaseToDocumentationPhase\"},{\"name\":\"paymentPhase\",\"kind\":\"object\",\"type\":\"PaymentPhase\",\"relationName\":\"ApplicationPhaseToPaymentPhase\"},{\"name\":\"payments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationPaymentToApplicationPhase\"},{\"name\":\"currentForApplications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"CurrentPhase\"}],\"dbName\":\"application_phases\"},\"QuestionnairePhase\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"QuestionnairePhaseToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPhaseToQuestionnairePhase\"},{\"name\":\"questionnairePlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePlan\",\"kind\":\"object\",\"type\":\"QuestionnairePlan\",\"relationName\":\"QuestionnairePhaseToQuestionnairePlan\"},{\"name\":\"completedFieldsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"totalFieldsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"totalScore\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"passingScore\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"passed\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"scoredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"underwritingScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"debtToIncomeRatio\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"underwritingDecision\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"underwritingNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fieldsSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"fields\",\"kind\":\"object\",\"type\":\"QuestionnaireField\",\"relationName\":\"QuestionnaireFieldToQuestionnairePhase\"}],\"dbName\":\"questionnaire_phases\"},\"DocumentationPhase\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentationPhaseToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPhaseToDocumentationPhase\"},{\"name\":\"documentationPlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentationPlan\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"DocumentationPhaseToDocumentationPlan\"},{\"name\":\"currentStepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"currentStep\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"CurrentStep\"},{\"name\":\"approvedDocumentsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"requiredDocumentsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"completedStepsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"totalStepsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"minimumCompletionPercentage\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"completionCriterion\",\"kind\":\"enum\",\"type\":\"CompletionCriterion\"},{\"name\":\"stepDefinitionsSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"requiredDocumentSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"steps\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"DocumentationPhaseToDocumentationStep\"}],\"dbName\":\"documentation_phases\"},\"PaymentPhase\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentPhaseToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPhaseToPaymentPhase\"},{\"name\":\"paymentPlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentPlan\",\"kind\":\"object\",\"type\":\"PaymentPlan\",\"relationName\":\"PaymentPhaseToPaymentPlan\"},{\"name\":\"totalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"paidAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"interestRate\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"selectedTermMonths\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"numberOfInstallments\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"collectFunds\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"minimumCompletionPercentage\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"paymentPlanSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"installments\",\"kind\":\"object\",\"type\":\"PaymentInstallment\",\"relationName\":\"PaymentInstallmentToPaymentPhase\"}],\"dbName\":\"payment_phases\"},\"QuestionnaireField\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"QuestionnaireFieldToTenant\"},{\"name\":\"questionnairePhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePhase\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"QuestionnaireFieldToQuestionnairePhase\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"label\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"placeholder\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fieldType\",\"kind\":\"enum\",\"type\":\"FieldType\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"validation\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"displayCondition\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"defaultValue\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"answer\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"isValid\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"validationErrors\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"submittedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"questionnaire_fields\"},\"ApplicationEvent\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationEventToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationEvent\"},{\"name\":\"eventType\",\"kind\":\"enum\",\"type\":\"ApplicationEventType\"},{\"name\":\"eventGroup\",\"kind\":\"enum\",\"type\":\"ApplicationEventGroup\"},{\"name\":\"fromState\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"toState\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"trigger\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorType\",\"kind\":\"enum\",\"type\":\"EventActorType\"},{\"name\":\"occurredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_events\"},\"DocumentationStep\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentationStepToTenant\"},{\"name\":\"documentationPhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentationPhase\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"DocumentationPhaseToDocumentationStep\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stepType\",\"kind\":\"enum\",\"type\":\"StepType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"StepStatus\"},{\"name\":\"actionReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"submissionCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"lastSubmittedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"assigneeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"assignee\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DocumentationStepAssignee\"},{\"name\":\"requiredDocuments\",\"kind\":\"object\",\"type\":\"DocumentationStepDocument\",\"relationName\":\"DocumentationStepToDocumentationStepDocument\"},{\"name\":\"dueDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"approvals\",\"kind\":\"object\",\"type\":\"DocumentationStepApproval\",\"relationName\":\"DocumentationStepToDocumentationStepApproval\"},{\"name\":\"currentForPhase\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"CurrentStep\"}],\"dbName\":\"documentation_steps\"},\"DocumentationStepDocument\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentationStepDocumentToTenant\"},{\"name\":\"stepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"step\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"DocumentationStepToDocumentationStepDocument\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"documentation_step_documents\"},\"DocumentationStepApproval\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentationStepApprovalToTenant\"},{\"name\":\"stepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"step\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"DocumentationStepToDocumentationStepApproval\"},{\"name\":\"approverId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"approver\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DocumentationStepApprover\"},{\"name\":\"decision\",\"kind\":\"enum\",\"type\":\"ApprovalDecision\"},{\"name\":\"comment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"decidedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"documentation_step_approvals\"},\"PaymentInstallment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentInstallmentToTenant\"},{\"name\":\"paymentPhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentPhase\",\"kind\":\"object\",\"type\":\"PaymentPhase\",\"relationName\":\"PaymentInstallmentToPaymentPhase\"},{\"name\":\"installmentNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"amount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"principalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"interestAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"dueDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"InstallmentStatus\"},{\"name\":\"paidAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"paidDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"lateFee\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"lateFeeWaived\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"gracePeriodDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"gracePeriodEndDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"payments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationPaymentToPaymentInstallment\"}],\"dbName\":\"payment_installments\"},\"ApplicationPayment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationPaymentToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationPayment\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPaymentToApplicationPhase\"},{\"name\":\"installmentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"installment\",\"kind\":\"object\",\"type\":\"PaymentInstallment\",\"relationName\":\"ApplicationPaymentToPaymentInstallment\"},{\"name\":\"payerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApplicationPayer\"},{\"name\":\"amount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"principalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"interestAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"lateFeeAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"paymentMethod\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"PaymentStatus\"},{\"name\":\"reference\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"gatewayResponse\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_payments\"},\"ApplicationDocument\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationDocumentToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationDocument\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"uploadedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"uploadedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DocumentUploader\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"DocumentStatus\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_documents\"},\"DocumentTemplate\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentTemplateToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"htmlTemplate\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"cssStyles\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"mergeFields\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"offerLetters\",\"kind\":\"object\",\"type\":\"OfferLetter\",\"relationName\":\"DocumentTemplateToOfferLetter\"}],\"dbName\":\"document_templates\"},\"OfferLetter\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"OfferLetterToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToOfferLetter\"},{\"name\":\"templateId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"template\",\"kind\":\"object\",\"type\":\"DocumentTemplate\",\"relationName\":\"DocumentTemplateToOfferLetter\"},{\"name\":\"letterNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"OfferLetterType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"OfferLetterStatus\"},{\"name\":\"htmlContent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"pdfUrl\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"pdfKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"mergeData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"sentAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"viewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"signedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"signatureIp\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"signatureData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cancelledAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cancelReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"generatedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"generatedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OfferLetterGenerator\"},{\"name\":\"sentById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sentBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OfferLetterSender\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"offer_letters\"},\"ApplicationTermination\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationTermination\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationTerminationToTenant\"},{\"name\":\"requestNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"initiatedBy\",\"kind\":\"enum\",\"type\":\"TerminationInitiator\"},{\"name\":\"initiatorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"initiator\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TerminationInitiator\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"TerminationType\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"supportingDocs\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"TerminationStatus\"},{\"name\":\"requiresApproval\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"autoApproveEligible\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"reviewedBy\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TerminationReviewer\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviewNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"rejectionReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"applicationSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"totalApplicationAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"totalPaidToDate\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"outstandingBalance\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"refundableAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"penaltyAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"forfeitedAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"adminFeeAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"netRefundAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"settlementNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refundStatus\",\"kind\":\"enum\",\"type\":\"RefundStatus\"},{\"name\":\"refundReference\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refundMethod\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refundAccountDetails\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"refundInitiatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refundCompletedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refundFailureReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"unitReleasedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"unitReservedForId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"approvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"executedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cancelledAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"idempotencyKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_terminations\"},\"PaymentMethodChangeRequest\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentMethodChangeRequestToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToPaymentMethodChangeRequest\"},{\"name\":\"fromPaymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fromPaymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"ChangeFromMethod\"},{\"name\":\"toPaymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"toPaymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"ChangeToMethod\"},{\"name\":\"requestorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestor\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ChangeRequestor\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requiredDocumentTypes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"submittedDocuments\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"currentOutstanding\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"newTermMonths\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"newInterestRate\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"newMonthlyPayment\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"penaltyAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"financialImpactNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"PaymentMethodChangeStatus\"},{\"name\":\"reviewerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ChangeReviewer\"},{\"name\":\"reviewNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"executedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"previousPhaseData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"newPhaseData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"payment_method_change_requests\"},\"DocumentRequirementRule\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentRequirementRuleToTenant\"},{\"name\":\"context\",\"kind\":\"enum\",\"type\":\"DocumentRequirementContext\"},{\"name\":\"paymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"RulePaymentMethod\"},{\"name\":\"phaseType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fromPaymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fromPaymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"RuleFromMethod\"},{\"name\":\"toPaymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"toPaymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"RuleToMethod\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"maxSizeBytes\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"allowedMimeTypes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiryDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"requiresManualReview\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"document_requirement_rules\"},\"EventChannel\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"EventChannelToTenant\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"eventTypes\",\"kind\":\"object\",\"type\":\"EventType\",\"relationName\":\"EventChannelToEventType\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"event_channels\"},\"EventType\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"EventTypeToTenant\"},{\"name\":\"channelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"channel\",\"kind\":\"object\",\"type\":\"EventChannel\",\"relationName\":\"EventChannelToEventType\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payloadSchema\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"handlers\",\"kind\":\"object\",\"type\":\"EventHandler\",\"relationName\":\"EventHandlerToEventType\"},{\"name\":\"events\",\"kind\":\"object\",\"type\":\"WorkflowEvent\",\"relationName\":\"EventTypeToWorkflowEvent\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"event_types\"},\"EventHandler\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"EventHandlerToTenant\"},{\"name\":\"eventTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventType\",\"kind\":\"object\",\"type\":\"EventType\",\"relationName\":\"EventHandlerToEventType\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"handlerType\",\"kind\":\"enum\",\"type\":\"EventHandlerType\"},{\"name\":\"config\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"priority\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"maxRetries\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"retryDelayMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"filterCondition\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"executions\",\"kind\":\"object\",\"type\":\"EventHandlerExecution\",\"relationName\":\"EventHandlerToEventHandlerExecution\"},{\"name\":\"stepAttachments\",\"kind\":\"object\",\"type\":\"StepEventAttachment\",\"relationName\":\"EventHandlerToStepEventAttachment\"},{\"name\":\"phaseAttachments\",\"kind\":\"object\",\"type\":\"PhaseEventAttachment\",\"relationName\":\"EventHandlerToPhaseEventAttachment\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"event_handlers\"},\"WorkflowEvent\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToWorkflowEvent\"},{\"name\":\"eventTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventType\",\"kind\":\"object\",\"type\":\"EventType\",\"relationName\":\"EventTypeToWorkflowEvent\"},{\"name\":\"payload\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"correlationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"causationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"source\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorType\",\"kind\":\"enum\",\"type\":\"ActorType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"WorkflowEventStatus\"},{\"name\":\"error\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"executions\",\"kind\":\"object\",\"type\":\"EventHandlerExecution\",\"relationName\":\"EventHandlerExecutionToWorkflowEvent\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"workflow_events\"},\"EventHandlerExecution\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"EventHandlerExecutionToTenant\"},{\"name\":\"eventId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"event\",\"kind\":\"object\",\"type\":\"WorkflowEvent\",\"relationName\":\"EventHandlerExecutionToWorkflowEvent\"},{\"name\":\"handlerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"handler\",\"kind\":\"object\",\"type\":\"EventHandler\",\"relationName\":\"EventHandlerToEventHandlerExecution\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ExecutionStatus\"},{\"name\":\"attempt\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"input\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"output\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"error\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"errorCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"startedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"durationMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"event_handler_executions\"},\"DomainEvent\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DomainEventToTenant\"},{\"name\":\"eventType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"aggregateType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"aggregateId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"queueName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payload\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"occurredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorRole\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"sentAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"failureCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"lastError\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"nextRetryAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"domain_events\"},\"PropertyTransferRequest\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyTransferRequestToTenant\"},{\"name\":\"sourceApplicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sourceApplication\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"SourceApplication\"},{\"name\":\"targetPropertyUnitId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetPropertyUnit\",\"kind\":\"object\",\"type\":\"PropertyUnit\",\"relationName\":\"PropertyTransferRequestToPropertyUnit\"},{\"name\":\"requestedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TransferRequestor\"},{\"name\":\"reviewedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TransferReviewer\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"TransferRequestStatus\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"priceAdjustmentHandling\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sourceTotalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"targetTotalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"priceAdjustment\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"refundedAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"refundTransactionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refundedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"targetApplicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetApplication\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"TargetApplication\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_transfer_requests\"},\"ApprovalRequest\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApprovalRequestToTenant\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"ApprovalRequestType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ApprovalRequestStatus\"},{\"name\":\"priority\",\"kind\":\"enum\",\"type\":\"ApprovalRequestPriority\"},{\"name\":\"entityType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"entityId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payload\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"requestedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApprovalRequestor\"},{\"name\":\"assigneeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"assignee\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApprovalAssignee\"},{\"name\":\"reviewedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApprovalReviewer\"},{\"name\":\"reviewNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"decision\",\"kind\":\"enum\",\"type\":\"ApprovalDecision\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"assignedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"approval_requests\"},\"WorkflowBlocker\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToWorkflowBlocker\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"blockerActor\",\"kind\":\"enum\",\"type\":\"BlockerActor\"},{\"name\":\"blockerCategory\",\"kind\":\"enum\",\"type\":\"BlockerCategory\"},{\"name\":\"urgency\",\"kind\":\"enum\",\"type\":\"BlockerUrgency\"},{\"name\":\"actionRequired\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"context\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expectedByDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"isOverdue\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"overdueAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"startedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"resolvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"durationMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"resolvedByActor\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resolutionTrigger\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reminderCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"lastReminderAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"nextReminderAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"workflow_blockers\"}},\"enums\":{},\"types\":{}}");
25
+ config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phone\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"firstName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isEmailVerified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"googleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"avatar\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToUser\"},{\"name\":\"tenantMemberships\",\"kind\":\"object\",\"type\":\"TenantMembership\",\"relationName\":\"TenantMembershipToUser\"},{\"name\":\"userRoles\",\"kind\":\"object\",\"type\":\"UserRole\",\"relationName\":\"UserToUserRole\"},{\"name\":\"walletId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"wallet\",\"kind\":\"object\",\"type\":\"Wallet\",\"relationName\":\"UserToWallet\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"emailVerifiedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"emailVerificationToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastLoginAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refreshTokens\",\"kind\":\"object\",\"type\":\"RefreshToken\",\"relationName\":\"RefreshTokenToUser\"},{\"name\":\"passwordResets\",\"kind\":\"object\",\"type\":\"PasswordReset\",\"relationName\":\"PasswordResetToUser\"},{\"name\":\"suspensions\",\"kind\":\"object\",\"type\":\"UserSuspension\",\"relationName\":\"UserToUserSuspension\"},{\"name\":\"emailPreferences\",\"kind\":\"object\",\"type\":\"EmailPreference\",\"relationName\":\"EmailPreferenceToUser\"},{\"name\":\"deviceEndpoints\",\"kind\":\"object\",\"type\":\"DeviceEndpoint\",\"relationName\":\"DeviceEndpointToUser\"},{\"name\":\"socials\",\"kind\":\"object\",\"type\":\"Social\",\"relationName\":\"SocialToUser\"},{\"name\":\"properties\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToUser\"},{\"name\":\"applications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationBuyer\"},{\"name\":\"soldApplications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationSeller\"},{\"name\":\"applicationPayments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationPayer\"},{\"name\":\"assignedSteps\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"DocumentationStepAssignee\"},{\"name\":\"gateActedSteps\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"GateActedBy\"},{\"name\":\"stepApprovals\",\"kind\":\"object\",\"type\":\"DocumentationStepApproval\",\"relationName\":\"DocumentationStepApprover\"},{\"name\":\"uploadedDocs\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"DocumentUploader\"},{\"name\":\"paymentMethodChangeRequests\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"ChangeRequestor\"},{\"name\":\"reviewedChangeRequests\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"ChangeReviewer\"},{\"name\":\"initiatedTerminations\",\"kind\":\"object\",\"type\":\"ApplicationTermination\",\"relationName\":\"TerminationInitiator\"},{\"name\":\"reviewedTerminations\",\"kind\":\"object\",\"type\":\"ApplicationTermination\",\"relationName\":\"TerminationReviewer\"},{\"name\":\"offerLettersGenerated\",\"kind\":\"object\",\"type\":\"OfferLetter\",\"relationName\":\"OfferLetterGenerator\"},{\"name\":\"offerLettersSent\",\"kind\":\"object\",\"type\":\"OfferLetter\",\"relationName\":\"OfferLetterSender\"},{\"name\":\"transferRequestsSubmitted\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"TransferRequestor\"},{\"name\":\"transferRequestsReviewed\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"TransferReviewer\"},{\"name\":\"approvalRequestsSubmitted\",\"kind\":\"object\",\"type\":\"ApprovalRequest\",\"relationName\":\"ApprovalRequestor\"},{\"name\":\"approvalRequestsAssigned\",\"kind\":\"object\",\"type\":\"ApprovalRequest\",\"relationName\":\"ApprovalAssignee\"},{\"name\":\"approvalRequestsReviewed\",\"kind\":\"object\",\"type\":\"ApprovalRequest\",\"relationName\":\"ApprovalReviewer\"},{\"name\":\"requestedRefunds\",\"kind\":\"object\",\"type\":\"ApplicationRefund\",\"relationName\":\"RefundRequester\"},{\"name\":\"approvedRefunds\",\"kind\":\"object\",\"type\":\"ApplicationRefund\",\"relationName\":\"RefundApprover\"},{\"name\":\"processedRefunds\",\"kind\":\"object\",\"type\":\"ApplicationRefund\",\"relationName\":\"RefundProcessor\"}],\"dbName\":\"users\"},\"Role\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"RoleToTenant\"},{\"name\":\"isSystem\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"userRoles\",\"kind\":\"object\",\"type\":\"UserRole\",\"relationName\":\"RoleToUserRole\"},{\"name\":\"memberships\",\"kind\":\"object\",\"type\":\"TenantMembership\",\"relationName\":\"RoleToTenantMembership\"},{\"name\":\"permissions\",\"kind\":\"object\",\"type\":\"RolePermission\",\"relationName\":\"RoleToRolePermission\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"roles\"},\"Permission\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"path\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"methods\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"effect\",\"kind\":\"enum\",\"type\":\"PermissionEffect\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PermissionToTenant\"},{\"name\":\"isSystem\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"roles\",\"kind\":\"object\",\"type\":\"RolePermission\",\"relationName\":\"PermissionToRolePermission\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"permissions\"},\"RolePermission\":{\"fields\":[{\"name\":\"roleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"permissionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"role\",\"kind\":\"object\",\"type\":\"Role\",\"relationName\":\"RoleToRolePermission\"},{\"name\":\"permission\",\"kind\":\"object\",\"type\":\"Permission\",\"relationName\":\"PermissionToRolePermission\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"role_permissions\"},\"UserRole\":{\"fields\":[{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"roleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToUserRole\"},{\"name\":\"role\",\"kind\":\"object\",\"type\":\"Role\",\"relationName\":\"RoleToUserRole\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"user_roles\"},\"TenantMembership\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"roleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TenantMembershipToUser\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToTenantMembership\"},{\"name\":\"role\",\"kind\":\"object\",\"type\":\"Role\",\"relationName\":\"RoleToTenantMembership\"}],\"dbName\":\"tenant_memberships\"},\"Tenant\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"subdomain\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"users\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TenantToUser\"},{\"name\":\"properties\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToTenant\"},{\"name\":\"paymentPlans\",\"kind\":\"object\",\"type\":\"PaymentPlan\",\"relationName\":\"PaymentPlanToTenant\"},{\"name\":\"documentationPlans\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"DocumentationPlanToTenant\"},{\"name\":\"paymentMethods\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"PropertyPaymentMethodToTenant\"},{\"name\":\"applications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToTenant\"},{\"name\":\"roles\",\"kind\":\"object\",\"type\":\"Role\",\"relationName\":\"RoleToTenant\"},{\"name\":\"permissions\",\"kind\":\"object\",\"type\":\"Permission\",\"relationName\":\"PermissionToTenant\"},{\"name\":\"memberships\",\"kind\":\"object\",\"type\":\"TenantMembership\",\"relationName\":\"TenantToTenantMembership\"},{\"name\":\"paymentMethodChangeRequests\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"PaymentMethodChangeRequestToTenant\"},{\"name\":\"documentRequirementRules\",\"kind\":\"object\",\"type\":\"DocumentRequirementRule\",\"relationName\":\"DocumentRequirementRuleToTenant\"},{\"name\":\"contractTerminations\",\"kind\":\"object\",\"type\":\"ApplicationTermination\",\"relationName\":\"ApplicationTerminationToTenant\"},{\"name\":\"documentTemplates\",\"kind\":\"object\",\"type\":\"DocumentTemplate\",\"relationName\":\"DocumentTemplateToTenant\"},{\"name\":\"offerLetters\",\"kind\":\"object\",\"type\":\"OfferLetter\",\"relationName\":\"OfferLetterToTenant\"},{\"name\":\"apiKeys\",\"kind\":\"object\",\"type\":\"ApiKey\",\"relationName\":\"ApiKeyToTenant\"},{\"name\":\"eventChannels\",\"kind\":\"object\",\"type\":\"EventChannel\",\"relationName\":\"EventChannelToTenant\"},{\"name\":\"eventTypes\",\"kind\":\"object\",\"type\":\"EventType\",\"relationName\":\"EventTypeToTenant\"},{\"name\":\"eventHandlers\",\"kind\":\"object\",\"type\":\"EventHandler\",\"relationName\":\"EventHandlerToTenant\"},{\"name\":\"workflowEvents\",\"kind\":\"object\",\"type\":\"WorkflowEvent\",\"relationName\":\"TenantToWorkflowEvent\"},{\"name\":\"propertyTransferRequests\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"PropertyTransferRequestToTenant\"},{\"name\":\"approvalRequests\",\"kind\":\"object\",\"type\":\"ApprovalRequest\",\"relationName\":\"ApprovalRequestToTenant\"},{\"name\":\"contractRefunds\",\"kind\":\"object\",\"type\":\"ApplicationRefund\",\"relationName\":\"ApplicationRefundToTenant\"},{\"name\":\"propertyPaymentMethodLinks\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodLink\",\"relationName\":\"PropertyPaymentMethodLinkToTenant\"},{\"name\":\"propertyPaymentMethodPhases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PropertyPaymentMethodPhaseToTenant\"},{\"name\":\"phaseEventAttachments\",\"kind\":\"object\",\"type\":\"PhaseEventAttachment\",\"relationName\":\"PhaseEventAttachmentToTenant\"},{\"name\":\"paymentMethodPhaseSteps\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseStep\",\"relationName\":\"PaymentMethodPhaseStepToTenant\"},{\"name\":\"stepEventAttachments\",\"kind\":\"object\",\"type\":\"StepEventAttachment\",\"relationName\":\"StepEventAttachmentToTenant\"},{\"name\":\"paymentMethodPhaseDocuments\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseDocument\",\"relationName\":\"PaymentMethodPhaseDocumentToTenant\"},{\"name\":\"paymentMethodPhaseFields\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseField\",\"relationName\":\"PaymentMethodPhaseFieldToTenant\"},{\"name\":\"applicationPhases\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPhaseToTenant\"},{\"name\":\"questionnairePhases\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"QuestionnairePhaseToTenant\"},{\"name\":\"documentationPhases\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"DocumentationPhaseToTenant\"},{\"name\":\"paymentPhases\",\"kind\":\"object\",\"type\":\"PaymentPhase\",\"relationName\":\"PaymentPhaseToTenant\"},{\"name\":\"questionnaireFields\",\"kind\":\"object\",\"type\":\"QuestionnaireField\",\"relationName\":\"QuestionnaireFieldToTenant\"},{\"name\":\"applicationEvents\",\"kind\":\"object\",\"type\":\"ApplicationEvent\",\"relationName\":\"ApplicationEventToTenant\"},{\"name\":\"documentationSteps\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"DocumentationStepToTenant\"},{\"name\":\"documentationStepDocuments\",\"kind\":\"object\",\"type\":\"DocumentationStepDocument\",\"relationName\":\"DocumentationStepDocumentToTenant\"},{\"name\":\"documentationStepApprovals\",\"kind\":\"object\",\"type\":\"DocumentationStepApproval\",\"relationName\":\"DocumentationStepApprovalToTenant\"},{\"name\":\"paymentInstallments\",\"kind\":\"object\",\"type\":\"PaymentInstallment\",\"relationName\":\"PaymentInstallmentToTenant\"},{\"name\":\"applicationPayments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationPaymentToTenant\"},{\"name\":\"applicationDocuments\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"ApplicationDocumentToTenant\"},{\"name\":\"propertyMedia\",\"kind\":\"object\",\"type\":\"PropertyMedia\",\"relationName\":\"PropertyMediaToTenant\"},{\"name\":\"propertyDocuments\",\"kind\":\"object\",\"type\":\"PropertyDocument\",\"relationName\":\"PropertyDocumentToTenant\"},{\"name\":\"propertyVariants\",\"kind\":\"object\",\"type\":\"PropertyVariant\",\"relationName\":\"PropertyVariantToTenant\"},{\"name\":\"propertyVariantAmenities\",\"kind\":\"object\",\"type\":\"PropertyVariantAmenity\",\"relationName\":\"PropertyVariantAmenityToTenant\"},{\"name\":\"propertyVariantMedia\",\"kind\":\"object\",\"type\":\"PropertyVariantMedia\",\"relationName\":\"PropertyVariantMediaToTenant\"},{\"name\":\"propertyUnits\",\"kind\":\"object\",\"type\":\"PropertyUnit\",\"relationName\":\"PropertyUnitToTenant\"},{\"name\":\"propertyAmenities\",\"kind\":\"object\",\"type\":\"PropertyAmenity\",\"relationName\":\"PropertyAmenityToTenant\"},{\"name\":\"eventHandlerExecutions\",\"kind\":\"object\",\"type\":\"EventHandlerExecution\",\"relationName\":\"EventHandlerExecutionToTenant\"},{\"name\":\"amenities\",\"kind\":\"object\",\"type\":\"Amenity\",\"relationName\":\"AmenityToTenant\"},{\"name\":\"socials\",\"kind\":\"object\",\"type\":\"Social\",\"relationName\":\"SocialToTenant\"},{\"name\":\"wallets\",\"kind\":\"object\",\"type\":\"Wallet\",\"relationName\":\"TenantToWallet\"},{\"name\":\"transactions\",\"kind\":\"object\",\"type\":\"Transaction\",\"relationName\":\"TenantToTransaction\"},{\"name\":\"settings\",\"kind\":\"object\",\"type\":\"Settings\",\"relationName\":\"SettingsToTenant\"},{\"name\":\"domainEvents\",\"kind\":\"object\",\"type\":\"DomainEvent\",\"relationName\":\"DomainEventToTenant\"},{\"name\":\"workflowBlockers\",\"kind\":\"object\",\"type\":\"WorkflowBlocker\",\"relationName\":\"TenantToWorkflowBlocker\"},{\"name\":\"questionnairePlans\",\"kind\":\"object\",\"type\":\"QuestionnairePlan\",\"relationName\":\"QuestionnairePlanToTenant\"}],\"dbName\":\"tenants\"},\"ApiKey\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApiKeyToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"provider\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"secretRef\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scopes\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"lastUsedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"revokedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"revokedBy\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdBy\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"api_keys\"},\"RefreshToken\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"jti\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"RefreshTokenToUser\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"refresh_tokens\"},\"PasswordReset\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PasswordResetToUser\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"usedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"password_resets\"},\"UserSuspension\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToUserSuspension\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"suspendedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"liftedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"user_suspensions\"},\"EmailPreference\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EmailPreferenceToUser\"},{\"name\":\"marketingEmails\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"transactionalEmails\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"propertyAlerts\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"paymentReminders\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"email_preferences\"},\"DeviceEndpoint\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DeviceEndpointToUser\"},{\"name\":\"endpoint\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"platform\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"device_endpoints\"},\"Social\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"SocialToTenant\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SocialToUser\"},{\"name\":\"provider\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"socialId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"socials\"},\"OAuthState\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"state\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"oauth_states\"},\"Wallet\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToWallet\"},{\"name\":\"balance\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"currency\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToWallet\"},{\"name\":\"transactions\",\"kind\":\"object\",\"type\":\"Transaction\",\"relationName\":\"TransactionToWallet\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"wallets\"},\"Transaction\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToTransaction\"},{\"name\":\"walletId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"wallet\",\"kind\":\"object\",\"type\":\"Wallet\",\"relationName\":\"TransactionToWallet\"},{\"name\":\"amount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reference\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"transactions\"},\"Settings\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"SettingsToTenant\"},{\"name\":\"key\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"category\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"settings\"},\"Property\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyToTenant\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PropertyToUser\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"category\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"propertyType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"country\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"currency\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"city\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"district\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"zipCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"streetAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"longitude\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"latitude\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayImageId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayImage\",\"kind\":\"object\",\"type\":\"PropertyMedia\",\"relationName\":\"DisplayImage\"},{\"name\":\"isPublished\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"publishedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"documents\",\"kind\":\"object\",\"type\":\"PropertyDocument\",\"relationName\":\"PropertyToPropertyDocument\"},{\"name\":\"media\",\"kind\":\"object\",\"type\":\"PropertyMedia\",\"relationName\":\"PropertyMedia\"},{\"name\":\"amenities\",\"kind\":\"object\",\"type\":\"PropertyAmenity\",\"relationName\":\"PropertyToPropertyAmenity\"},{\"name\":\"paymentMethods\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodLink\",\"relationName\":\"PropertyToPropertyPaymentMethodLink\"},{\"name\":\"variants\",\"kind\":\"object\",\"type\":\"PropertyVariant\",\"relationName\":\"PropertyToPropertyVariant\"}],\"dbName\":\"properties\"},\"PropertyMedia\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyMediaToTenant\"},{\"name\":\"propertyId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"property\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyMedia\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"caption\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"displayForProperties\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"DisplayImage\"}],\"dbName\":\"property_media\"},\"PropertyDocument\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyDocumentToTenant\"},{\"name\":\"propertyId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"property\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToPropertyDocument\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_documents\"},\"Amenity\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"AmenityToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"category\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"icon\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"properties\",\"kind\":\"object\",\"type\":\"PropertyAmenity\",\"relationName\":\"AmenityToPropertyAmenity\"},{\"name\":\"variants\",\"kind\":\"object\",\"type\":\"PropertyVariantAmenity\",\"relationName\":\"AmenityToPropertyVariantAmenity\"}],\"dbName\":\"amenities\"},\"PropertyVariant\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyVariantToTenant\"},{\"name\":\"propertyId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"property\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToPropertyVariant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"nBedrooms\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"nBathrooms\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"nParkingSpots\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"area\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"price\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"pricePerSqm\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"totalUnits\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"availableUnits\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"reservedUnits\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"soldUnits\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"amenities\",\"kind\":\"object\",\"type\":\"PropertyVariantAmenity\",\"relationName\":\"PropertyVariantToPropertyVariantAmenity\"},{\"name\":\"units\",\"kind\":\"object\",\"type\":\"PropertyUnit\",\"relationName\":\"PropertyUnitToPropertyVariant\"},{\"name\":\"media\",\"kind\":\"object\",\"type\":\"PropertyVariantMedia\",\"relationName\":\"PropertyVariantToPropertyVariantMedia\"}],\"dbName\":\"property_variants\"},\"PropertyVariantAmenity\":{\"fields\":[{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyVariantAmenityToTenant\"},{\"name\":\"variantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"amenityId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"variant\",\"kind\":\"object\",\"type\":\"PropertyVariant\",\"relationName\":\"PropertyVariantToPropertyVariantAmenity\"},{\"name\":\"amenity\",\"kind\":\"object\",\"type\":\"Amenity\",\"relationName\":\"AmenityToPropertyVariantAmenity\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_variant_amenities\"},\"PropertyVariantMedia\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyVariantMediaToTenant\"},{\"name\":\"variantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"variant\",\"kind\":\"object\",\"type\":\"PropertyVariant\",\"relationName\":\"PropertyVariantToPropertyVariantMedia\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"caption\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_variant_media\"},\"PropertyUnit\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyUnitToTenant\"},{\"name\":\"variantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"variant\",\"kind\":\"object\",\"type\":\"PropertyVariant\",\"relationName\":\"PropertyUnitToPropertyVariant\"},{\"name\":\"unitNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"floorNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"blockName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"priceOverride\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"areaOverride\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"notes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reservedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reservedUntil\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reservedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ownerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"applications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToPropertyUnit\"},{\"name\":\"transferRequests\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"PropertyTransferRequestToPropertyUnit\"}],\"dbName\":\"property_units\"},\"PropertyAmenity\":{\"fields\":[{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyAmenityToTenant\"},{\"name\":\"propertyId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"amenityId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"property\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToPropertyAmenity\"},{\"name\":\"amenity\",\"kind\":\"object\",\"type\":\"Amenity\",\"relationName\":\"AmenityToPropertyAmenity\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_amenities\"},\"DocumentationPlan\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentationPlanToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"requiredDocumentTypes\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"steps\",\"kind\":\"object\",\"type\":\"DocumentationPlanStep\",\"relationName\":\"DocumentationPlanToDocumentationPlanStep\"},{\"name\":\"methodPhases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"DocumentationPlanToPropertyPaymentMethodPhase\"},{\"name\":\"documentationPhases\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"DocumentationPhaseToDocumentationPlan\"}],\"dbName\":\"documentation_plans\"},\"DocumentationPlanStep\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"planId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"plan\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"DocumentationPlanToDocumentationPlanStep\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stepType\",\"kind\":\"enum\",\"type\":\"StepType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"maxSizeBytes\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"allowedMimeTypes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiryDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"requiresManualReview\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"minFiles\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxFiles\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"condition\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"gateActor\",\"kind\":\"enum\",\"type\":\"GateActor\"},{\"name\":\"gateAction\",\"kind\":\"enum\",\"type\":\"GateAction\"},{\"name\":\"gateRoleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"gateInstructions\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"allowReject\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"rejectBehavior\",\"kind\":\"enum\",\"type\":\"GateRejectBehavior\"},{\"name\":\"requiresComment\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"documentation_plan_steps\"},\"QuestionnairePlan\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"QuestionnairePlanToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"passingScore\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"scoringStrategy\",\"kind\":\"enum\",\"type\":\"ScoringStrategy\"},{\"name\":\"autoDecisionEnabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"estimatedMinutes\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"category\",\"kind\":\"enum\",\"type\":\"QuestionnaireCategory\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"questions\",\"kind\":\"object\",\"type\":\"QuestionnairePlanQuestion\",\"relationName\":\"QuestionnairePlanToQuestionnairePlanQuestion\"},{\"name\":\"methodPhases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PropertyPaymentMethodPhaseToQuestionnairePlan\"},{\"name\":\"questionnairePhases\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"QuestionnairePhaseToQuestionnairePlan\"}],\"dbName\":\"questionnaire_plans\"},\"QuestionnairePlanQuestion\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePlan\",\"kind\":\"object\",\"type\":\"QuestionnairePlan\",\"relationName\":\"QuestionnairePlanToQuestionnairePlanQuestion\"},{\"name\":\"questionKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionText\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"helpText\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionType\",\"kind\":\"enum\",\"type\":\"QuestionType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"validationRules\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"options\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"scoreWeight\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"scoringRules\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"showIf\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"category\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"questionnaire_plan_questions\"},\"PaymentPlan\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentPlanToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"paymentFrequency\",\"kind\":\"enum\",\"type\":\"PaymentFrequency\"},{\"name\":\"customFrequencyDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"numberOfInstallments\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"calculateInterestDaily\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"gracePeriodDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"allowFlexibleTerm\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"minTermMonths\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxTermMonths\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"termStepMonths\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxAgeAtMaturity\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"collectFunds\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"methodPhases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PaymentPlanToPropertyPaymentMethodPhase\"},{\"name\":\"paymentPhases\",\"kind\":\"object\",\"type\":\"PaymentPhase\",\"relationName\":\"PaymentPhaseToPaymentPlan\"}],\"dbName\":\"payment_plans\"},\"PropertyPaymentMethod\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyPaymentMethodToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"allowEarlyPayoff\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"earlyPayoffPenaltyRate\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"autoActivatePhases\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"requiresManualApproval\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"properties\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodLink\",\"relationName\":\"PropertyPaymentMethodToPropertyPaymentMethodLink\"},{\"name\":\"phases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PropertyPaymentMethodToPropertyPaymentMethodPhase\"},{\"name\":\"applications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToPropertyPaymentMethod\"},{\"name\":\"changeRequestsFrom\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"ChangeFromMethod\"},{\"name\":\"changeRequestsTo\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"ChangeToMethod\"},{\"name\":\"documentRules\",\"kind\":\"object\",\"type\":\"DocumentRequirementRule\",\"relationName\":\"RulePaymentMethod\"},{\"name\":\"changeRulesFrom\",\"kind\":\"object\",\"type\":\"DocumentRequirementRule\",\"relationName\":\"RuleFromMethod\"},{\"name\":\"changeRulesTo\",\"kind\":\"object\",\"type\":\"DocumentRequirementRule\",\"relationName\":\"RuleToMethod\"}],\"dbName\":\"property_payment_methods\"},\"PropertyPaymentMethodLink\":{\"fields\":[{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyPaymentMethodLinkToTenant\"},{\"name\":\"propertyId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"property\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"PropertyToPropertyPaymentMethodLink\"},{\"name\":\"paymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"PropertyPaymentMethodToPropertyPaymentMethodLink\"},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_payment_method_links\"},\"PropertyPaymentMethodPhase\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyPaymentMethodPhaseToTenant\"},{\"name\":\"paymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"PropertyPaymentMethodToPropertyPaymentMethodPhase\"},{\"name\":\"paymentPlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentPlan\",\"kind\":\"object\",\"type\":\"PaymentPlan\",\"relationName\":\"PaymentPlanToPropertyPaymentMethodPhase\"},{\"name\":\"documentationPlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentationPlan\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"DocumentationPlanToPropertyPaymentMethodPhase\"},{\"name\":\"questionnairePlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePlan\",\"kind\":\"object\",\"type\":\"QuestionnairePlan\",\"relationName\":\"PropertyPaymentMethodPhaseToQuestionnairePlan\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phaseCategory\",\"kind\":\"enum\",\"type\":\"PhaseCategory\"},{\"name\":\"phaseType\",\"kind\":\"enum\",\"type\":\"PhaseType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"interestRate\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"percentOfPrice\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"collectFunds\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"requiresPreviousPhaseCompletion\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"minimumCompletionPercentage\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"completionCriterion\",\"kind\":\"enum\",\"type\":\"CompletionCriterion\"},{\"name\":\"lockUnitOnComplete\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"stepDefinitionsSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"requiredDocumentSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"steps\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseStep\",\"relationName\":\"PaymentMethodPhaseStepToPropertyPaymentMethodPhase\"},{\"name\":\"requiredDocuments\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseDocument\",\"relationName\":\"PaymentMethodPhaseDocumentToPropertyPaymentMethodPhase\"},{\"name\":\"questionnaireFields\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseField\",\"relationName\":\"PaymentMethodPhaseFieldToPropertyPaymentMethodPhase\"},{\"name\":\"eventAttachments\",\"kind\":\"object\",\"type\":\"PhaseEventAttachment\",\"relationName\":\"PhaseEventAttachmentToPropertyPaymentMethodPhase\"},{\"name\":\"applicationPhases\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPhaseToPropertyPaymentMethodPhase\"}],\"dbName\":\"property_payment_method_phases\"},\"PhaseEventAttachment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PhaseEventAttachmentToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PhaseEventAttachmentToPropertyPaymentMethodPhase\"},{\"name\":\"trigger\",\"kind\":\"enum\",\"type\":\"PhaseTrigger\"},{\"name\":\"handlerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"handler\",\"kind\":\"object\",\"type\":\"EventHandler\",\"relationName\":\"EventHandlerToPhaseEventAttachment\"},{\"name\":\"priority\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"phase_event_attachments\"},\"PaymentMethodPhaseStep\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentMethodPhaseStepToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PaymentMethodPhaseStepToPropertyPaymentMethodPhase\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stepType\",\"kind\":\"enum\",\"type\":\"StepType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"eventAttachments\",\"kind\":\"object\",\"type\":\"StepEventAttachment\",\"relationName\":\"PaymentMethodPhaseStepToStepEventAttachment\"}],\"dbName\":\"payment_method_phase_steps\"},\"StepEventAttachment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"StepEventAttachmentToTenant\"},{\"name\":\"stepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"step\",\"kind\":\"object\",\"type\":\"PaymentMethodPhaseStep\",\"relationName\":\"PaymentMethodPhaseStepToStepEventAttachment\"},{\"name\":\"trigger\",\"kind\":\"enum\",\"type\":\"StepTrigger\"},{\"name\":\"handlerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"handler\",\"kind\":\"object\",\"type\":\"EventHandler\",\"relationName\":\"EventHandlerToStepEventAttachment\"},{\"name\":\"priority\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"step_event_attachments\"},\"PaymentMethodPhaseDocument\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentMethodPhaseDocumentToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PaymentMethodPhaseDocumentToPropertyPaymentMethodPhase\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"allowedMimeTypes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"maxSizeBytes\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"payment_method_phase_documents\"},\"PaymentMethodPhaseField\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentMethodPhaseFieldToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"PaymentMethodPhaseFieldToPropertyPaymentMethodPhase\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"label\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"placeholder\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fieldType\",\"kind\":\"enum\",\"type\":\"FieldType\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"validation\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"displayCondition\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"defaultValue\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"payment_method_phase_fields\"},\"Application\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationToTenant\"},{\"name\":\"propertyUnitId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"propertyUnit\",\"kind\":\"object\",\"type\":\"PropertyUnit\",\"relationName\":\"ApplicationToPropertyUnit\"},{\"name\":\"buyerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"buyer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApplicationBuyer\"},{\"name\":\"sellerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"seller\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApplicationSeller\"},{\"name\":\"paymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"ApplicationToPropertyPaymentMethod\"},{\"name\":\"applicationNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"applicationType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"totalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ApplicationStatus\"},{\"name\":\"currentPhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"currentPhase\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"CurrentPhase\"},{\"name\":\"nextPaymentDueDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"lastReminderSentAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"startDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"endDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"signedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"terminatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"phases\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationToApplicationPhase\"},{\"name\":\"documents\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"ApplicationToApplicationDocument\"},{\"name\":\"payments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationToApplicationPayment\"},{\"name\":\"terminations\",\"kind\":\"object\",\"type\":\"ApplicationTermination\",\"relationName\":\"ApplicationToApplicationTermination\"},{\"name\":\"offerLetters\",\"kind\":\"object\",\"type\":\"OfferLetter\",\"relationName\":\"ApplicationToOfferLetter\"},{\"name\":\"paymentMethodChangeRequests\",\"kind\":\"object\",\"type\":\"PaymentMethodChangeRequest\",\"relationName\":\"ApplicationToPaymentMethodChangeRequest\"},{\"name\":\"transferredFromId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"transferredFrom\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationTransfer\"},{\"name\":\"transferredTo\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationTransfer\"},{\"name\":\"supersededById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"supersededBy\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationSuperseded\"},{\"name\":\"supersededAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"supersededApplications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationSuperseded\"},{\"name\":\"outgoingTransferRequests\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"SourceApplication\"},{\"name\":\"incomingTransferRequests\",\"kind\":\"object\",\"type\":\"PropertyTransferRequest\",\"relationName\":\"TargetApplication\"},{\"name\":\"events\",\"kind\":\"object\",\"type\":\"ApplicationEvent\",\"relationName\":\"ApplicationToApplicationEvent\"},{\"name\":\"refunds\",\"kind\":\"object\",\"type\":\"ApplicationRefund\",\"relationName\":\"ApplicationToApplicationRefund\"}],\"dbName\":\"applications\"},\"ApplicationRefund\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationRefundToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationRefund\"},{\"name\":\"amount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"RefundStatus\"},{\"name\":\"requestedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"RefundRequester\"},{\"name\":\"approvedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"approvedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"RefundApprover\"},{\"name\":\"processedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"RefundProcessor\"},{\"name\":\"paymentMethod\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"referenceNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"recipientName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"recipientAccount\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"recipientBank\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"approvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"rejectedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"approvalNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"rejectionNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processingNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_refunds\"},\"ApplicationPhase\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationPhaseToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationPhase\"},{\"name\":\"phaseTemplateId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phaseTemplate\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"ApplicationPhaseToPropertyPaymentMethodPhase\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phaseCategory\",\"kind\":\"enum\",\"type\":\"PhaseCategory\"},{\"name\":\"phaseType\",\"kind\":\"enum\",\"type\":\"PhaseType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"PhaseStatus\"},{\"name\":\"dueDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"startDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"endDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"activatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"requiresPreviousPhaseCompletion\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"questionnairePhase\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"ApplicationPhaseToQuestionnairePhase\"},{\"name\":\"documentationPhase\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"ApplicationPhaseToDocumentationPhase\"},{\"name\":\"paymentPhase\",\"kind\":\"object\",\"type\":\"PaymentPhase\",\"relationName\":\"ApplicationPhaseToPaymentPhase\"},{\"name\":\"payments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationPaymentToApplicationPhase\"},{\"name\":\"currentForApplications\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"CurrentPhase\"}],\"dbName\":\"application_phases\"},\"QuestionnairePhase\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"QuestionnairePhaseToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPhaseToQuestionnairePhase\"},{\"name\":\"questionnairePlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePlan\",\"kind\":\"object\",\"type\":\"QuestionnairePlan\",\"relationName\":\"QuestionnairePhaseToQuestionnairePlan\"},{\"name\":\"completedFieldsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"totalFieldsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"totalScore\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"passingScore\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"passed\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"scoredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"underwritingScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"debtToIncomeRatio\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"underwritingDecision\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"underwritingNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fieldsSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"fields\",\"kind\":\"object\",\"type\":\"QuestionnaireField\",\"relationName\":\"QuestionnaireFieldToQuestionnairePhase\"}],\"dbName\":\"questionnaire_phases\"},\"DocumentationPhase\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentationPhaseToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPhaseToDocumentationPhase\"},{\"name\":\"documentationPlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentationPlan\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"DocumentationPhaseToDocumentationPlan\"},{\"name\":\"currentStepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"currentStep\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"CurrentStep\"},{\"name\":\"approvedDocumentsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"requiredDocumentsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"completedStepsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"totalStepsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"minimumCompletionPercentage\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"completionCriterion\",\"kind\":\"enum\",\"type\":\"CompletionCriterion\"},{\"name\":\"stepDefinitionsSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"requiredDocumentSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"steps\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"DocumentationPhaseToDocumentationStep\"}],\"dbName\":\"documentation_phases\"},\"PaymentPhase\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentPhaseToTenant\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPhaseToPaymentPhase\"},{\"name\":\"paymentPlanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentPlan\",\"kind\":\"object\",\"type\":\"PaymentPlan\",\"relationName\":\"PaymentPhaseToPaymentPlan\"},{\"name\":\"totalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"paidAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"interestRate\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"selectedTermMonths\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"numberOfInstallments\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"collectFunds\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"minimumCompletionPercentage\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"paymentPlanSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"installments\",\"kind\":\"object\",\"type\":\"PaymentInstallment\",\"relationName\":\"PaymentInstallmentToPaymentPhase\"}],\"dbName\":\"payment_phases\"},\"QuestionnaireField\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"QuestionnaireFieldToTenant\"},{\"name\":\"questionnairePhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePhase\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"QuestionnaireFieldToQuestionnairePhase\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"label\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"placeholder\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fieldType\",\"kind\":\"enum\",\"type\":\"FieldType\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"validation\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"displayCondition\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"defaultValue\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"answer\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"isValid\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"validationErrors\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"submittedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"questionnaire_fields\"},\"ApplicationEvent\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationEventToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationEvent\"},{\"name\":\"eventType\",\"kind\":\"enum\",\"type\":\"ApplicationEventType\"},{\"name\":\"eventGroup\",\"kind\":\"enum\",\"type\":\"ApplicationEventGroup\"},{\"name\":\"fromState\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"toState\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"trigger\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorType\",\"kind\":\"enum\",\"type\":\"EventActorType\"},{\"name\":\"occurredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_events\"},\"DocumentationStep\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentationStepToTenant\"},{\"name\":\"documentationPhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentationPhase\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"DocumentationPhaseToDocumentationStep\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stepType\",\"kind\":\"enum\",\"type\":\"StepType\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"StepStatus\"},{\"name\":\"actionReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"submissionCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"lastSubmittedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"assigneeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"assignee\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DocumentationStepAssignee\"},{\"name\":\"requiredDocuments\",\"kind\":\"object\",\"type\":\"DocumentationStepDocument\",\"relationName\":\"DocumentationStepToDocumentationStepDocument\"},{\"name\":\"gateActor\",\"kind\":\"enum\",\"type\":\"GateActor\"},{\"name\":\"gateAction\",\"kind\":\"enum\",\"type\":\"GateAction\"},{\"name\":\"gateRoleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"gateInstructions\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"allowReject\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"rejectBehavior\",\"kind\":\"enum\",\"type\":\"GateRejectBehavior\"},{\"name\":\"requiresComment\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"gateActedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"gateActedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"gateActedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"GateActedBy\"},{\"name\":\"gateDecision\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"gateComment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"dueDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"approvals\",\"kind\":\"object\",\"type\":\"DocumentationStepApproval\",\"relationName\":\"DocumentationStepToDocumentationStepApproval\"},{\"name\":\"currentForPhase\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"CurrentStep\"}],\"dbName\":\"documentation_steps\"},\"DocumentationStepDocument\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentationStepDocumentToTenant\"},{\"name\":\"stepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"step\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"DocumentationStepToDocumentationStepDocument\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"documentation_step_documents\"},\"DocumentationStepApproval\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentationStepApprovalToTenant\"},{\"name\":\"stepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"step\",\"kind\":\"object\",\"type\":\"DocumentationStep\",\"relationName\":\"DocumentationStepToDocumentationStepApproval\"},{\"name\":\"approverId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"approver\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DocumentationStepApprover\"},{\"name\":\"decision\",\"kind\":\"enum\",\"type\":\"ApprovalDecision\"},{\"name\":\"comment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"decidedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"documentation_step_approvals\"},\"PaymentInstallment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentInstallmentToTenant\"},{\"name\":\"paymentPhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentPhase\",\"kind\":\"object\",\"type\":\"PaymentPhase\",\"relationName\":\"PaymentInstallmentToPaymentPhase\"},{\"name\":\"installmentNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"amount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"principalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"interestAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"dueDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"InstallmentStatus\"},{\"name\":\"paidAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"paidDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"lateFee\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"lateFeeWaived\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"gracePeriodDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"gracePeriodEndDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"payments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationPaymentToPaymentInstallment\"}],\"dbName\":\"payment_installments\"},\"ApplicationPayment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationPaymentToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationPayment\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phase\",\"kind\":\"object\",\"type\":\"ApplicationPhase\",\"relationName\":\"ApplicationPaymentToApplicationPhase\"},{\"name\":\"installmentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"installment\",\"kind\":\"object\",\"type\":\"PaymentInstallment\",\"relationName\":\"ApplicationPaymentToPaymentInstallment\"},{\"name\":\"payerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApplicationPayer\"},{\"name\":\"amount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"principalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"interestAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"lateFeeAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"paymentMethod\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"PaymentStatus\"},{\"name\":\"reference\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"gatewayResponse\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_payments\"},\"ApplicationDocument\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationDocumentToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationDocument\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"uploadedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"uploadedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DocumentUploader\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"DocumentStatus\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_documents\"},\"DocumentTemplate\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentTemplateToTenant\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"htmlTemplate\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"cssStyles\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"mergeFields\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"offerLetters\",\"kind\":\"object\",\"type\":\"OfferLetter\",\"relationName\":\"DocumentTemplateToOfferLetter\"}],\"dbName\":\"document_templates\"},\"OfferLetter\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"OfferLetterToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToOfferLetter\"},{\"name\":\"templateId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"template\",\"kind\":\"object\",\"type\":\"DocumentTemplate\",\"relationName\":\"DocumentTemplateToOfferLetter\"},{\"name\":\"letterNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"OfferLetterType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"OfferLetterStatus\"},{\"name\":\"htmlContent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"pdfUrl\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"pdfKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"mergeData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"sentAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"viewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"signedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"signatureIp\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"signatureData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cancelledAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cancelReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"generatedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"generatedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OfferLetterGenerator\"},{\"name\":\"sentById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sentBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OfferLetterSender\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"offer_letters\"},\"ApplicationTermination\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationTermination\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationTerminationToTenant\"},{\"name\":\"requestNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"initiatedBy\",\"kind\":\"enum\",\"type\":\"TerminationInitiator\"},{\"name\":\"initiatorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"initiator\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TerminationInitiator\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"TerminationType\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"supportingDocs\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"TerminationStatus\"},{\"name\":\"requiresApproval\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"autoApproveEligible\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"reviewedBy\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TerminationReviewer\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviewNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"rejectionReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"applicationSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"totalApplicationAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"totalPaidToDate\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"outstandingBalance\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"refundableAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"penaltyAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"forfeitedAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"adminFeeAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"netRefundAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"settlementNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refundStatus\",\"kind\":\"enum\",\"type\":\"RefundStatus\"},{\"name\":\"refundReference\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refundMethod\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refundAccountDetails\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"refundInitiatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refundCompletedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refundFailureReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"unitReleasedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"unitReservedForId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"approvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"executedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cancelledAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"idempotencyKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_terminations\"},\"PaymentMethodChangeRequest\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PaymentMethodChangeRequestToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToPaymentMethodChangeRequest\"},{\"name\":\"fromPaymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fromPaymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"ChangeFromMethod\"},{\"name\":\"toPaymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"toPaymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"ChangeToMethod\"},{\"name\":\"requestorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestor\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ChangeRequestor\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requiredDocumentTypes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"submittedDocuments\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"currentOutstanding\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"newTermMonths\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"newInterestRate\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"newMonthlyPayment\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"penaltyAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"financialImpactNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"PaymentMethodChangeStatus\"},{\"name\":\"reviewerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ChangeReviewer\"},{\"name\":\"reviewNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"executedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"previousPhaseData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"newPhaseData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"payment_method_change_requests\"},\"DocumentRequirementRule\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentRequirementRuleToTenant\"},{\"name\":\"context\",\"kind\":\"enum\",\"type\":\"DocumentRequirementContext\"},{\"name\":\"paymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"RulePaymentMethod\"},{\"name\":\"phaseType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fromPaymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fromPaymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"RuleFromMethod\"},{\"name\":\"toPaymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"toPaymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"RuleToMethod\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isRequired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"maxSizeBytes\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"allowedMimeTypes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiryDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"requiresManualReview\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"document_requirement_rules\"},\"EventChannel\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"EventChannelToTenant\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"eventTypes\",\"kind\":\"object\",\"type\":\"EventType\",\"relationName\":\"EventChannelToEventType\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"event_channels\"},\"EventType\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"EventTypeToTenant\"},{\"name\":\"channelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"channel\",\"kind\":\"object\",\"type\":\"EventChannel\",\"relationName\":\"EventChannelToEventType\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payloadSchema\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"handlers\",\"kind\":\"object\",\"type\":\"EventHandler\",\"relationName\":\"EventHandlerToEventType\"},{\"name\":\"events\",\"kind\":\"object\",\"type\":\"WorkflowEvent\",\"relationName\":\"EventTypeToWorkflowEvent\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"event_types\"},\"EventHandler\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"EventHandlerToTenant\"},{\"name\":\"eventTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventType\",\"kind\":\"object\",\"type\":\"EventType\",\"relationName\":\"EventHandlerToEventType\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"handlerType\",\"kind\":\"enum\",\"type\":\"EventHandlerType\"},{\"name\":\"config\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"priority\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"maxRetries\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"retryDelayMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"filterCondition\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"executions\",\"kind\":\"object\",\"type\":\"EventHandlerExecution\",\"relationName\":\"EventHandlerToEventHandlerExecution\"},{\"name\":\"stepAttachments\",\"kind\":\"object\",\"type\":\"StepEventAttachment\",\"relationName\":\"EventHandlerToStepEventAttachment\"},{\"name\":\"phaseAttachments\",\"kind\":\"object\",\"type\":\"PhaseEventAttachment\",\"relationName\":\"EventHandlerToPhaseEventAttachment\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"event_handlers\"},\"WorkflowEvent\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToWorkflowEvent\"},{\"name\":\"eventTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventType\",\"kind\":\"object\",\"type\":\"EventType\",\"relationName\":\"EventTypeToWorkflowEvent\"},{\"name\":\"payload\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"correlationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"causationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"source\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorType\",\"kind\":\"enum\",\"type\":\"ActorType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"WorkflowEventStatus\"},{\"name\":\"error\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"executions\",\"kind\":\"object\",\"type\":\"EventHandlerExecution\",\"relationName\":\"EventHandlerExecutionToWorkflowEvent\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"workflow_events\"},\"EventHandlerExecution\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"EventHandlerExecutionToTenant\"},{\"name\":\"eventId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"event\",\"kind\":\"object\",\"type\":\"WorkflowEvent\",\"relationName\":\"EventHandlerExecutionToWorkflowEvent\"},{\"name\":\"handlerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"handler\",\"kind\":\"object\",\"type\":\"EventHandler\",\"relationName\":\"EventHandlerToEventHandlerExecution\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ExecutionStatus\"},{\"name\":\"attempt\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"input\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"output\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"error\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"errorCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"startedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"durationMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"event_handler_executions\"},\"DomainEvent\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DomainEventToTenant\"},{\"name\":\"eventType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"aggregateType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"aggregateId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"queueName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payload\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"occurredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorRole\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"sentAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"failureCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"lastError\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"nextRetryAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"domain_events\"},\"PropertyTransferRequest\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"PropertyTransferRequestToTenant\"},{\"name\":\"sourceApplicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sourceApplication\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"SourceApplication\"},{\"name\":\"targetPropertyUnitId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetPropertyUnit\",\"kind\":\"object\",\"type\":\"PropertyUnit\",\"relationName\":\"PropertyTransferRequestToPropertyUnit\"},{\"name\":\"requestedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TransferRequestor\"},{\"name\":\"reviewedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TransferReviewer\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"TransferRequestStatus\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"priceAdjustmentHandling\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sourceTotalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"targetTotalAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"priceAdjustment\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"refundedAmount\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"refundTransactionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refundedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"targetApplicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetApplication\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"TargetApplication\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"property_transfer_requests\"},\"ApprovalRequest\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApprovalRequestToTenant\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"ApprovalRequestType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ApprovalRequestStatus\"},{\"name\":\"priority\",\"kind\":\"enum\",\"type\":\"ApprovalRequestPriority\"},{\"name\":\"entityType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"entityId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payload\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"requestedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"requestedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApprovalRequestor\"},{\"name\":\"assigneeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"assignee\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApprovalAssignee\"},{\"name\":\"reviewedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ApprovalReviewer\"},{\"name\":\"reviewNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"decision\",\"kind\":\"enum\",\"type\":\"ApprovalDecision\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"assignedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"approval_requests\"},\"WorkflowBlocker\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"TenantToWorkflowBlocker\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stepId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"blockerActor\",\"kind\":\"enum\",\"type\":\"BlockerActor\"},{\"name\":\"blockerCategory\",\"kind\":\"enum\",\"type\":\"BlockerCategory\"},{\"name\":\"urgency\",\"kind\":\"enum\",\"type\":\"BlockerUrgency\"},{\"name\":\"actionRequired\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"context\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expectedByDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"isOverdue\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"overdueAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"startedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"resolvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"durationMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"resolvedByActor\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resolutionTrigger\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reminderCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"lastReminderAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"nextReminderAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"workflow_blockers\"}},\"enums\":{},\"types\":{}}");
26
26
  async function decodeBase64AsWasm(wasmBase64) {
27
27
  const { Buffer } = await import('node:buffer');
28
28
  const wasmArray = Buffer.from(wasmBase64, 'base64');