@valentine-efagene/qshelter-common 2.0.153 → 2.0.154

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 PropertyStatus {\n DRAFT\n PUBLISHED\n SOLD_OUT\n ARCHIVED\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\n/// Triggers that cause application state transitions\nenum ApplicationTrigger {\n SUBMIT // Submit application for review (DRAFT -> PENDING)\n APPROVE // Approve pending application (PENDING -> ACTIVE)\n REJECT // Reject pending application (PENDING -> CANCELLED)\n CANCEL // Cancel application\n COMPLETE // Complete application (all phases done)\n TERMINATE // Terminate active application\n TRANSFER // Transfer to different unit\n SUPERSEDE // Another buyer locked the unit\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/// Operators for conditional step evaluation\nenum ConditionOperator {\n EQUALS // Field value equals expected value\n NOT_EQUALS // Field value does not equal expected value\n IN // Field value is in a list of values\n NOT_IN // Field value is not in a list of values\n GREATER_THAN // Numeric comparison\n LESS_THAN // Numeric comparison\n GREATER_THAN_OR_EQUAL\n LESS_THAN_OR_EQUAL\n EXISTS // Field has any value (not null/undefined)\n NOT_EXISTS // Field is null/undefined\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// ORGANIZATION TYPE - Lookup table for organization types (replaces enum)\n// =============================================================================\n// Organizations can have multiple types via OrganizationTypeAssignment.\n// Example: QShelter can be both PLATFORM and DEVELOPER.\n// System types are seeded during tenant bootstrap and cannot be deleted.\n// =============================================================================\n\nmodel OrganizationType {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n code String // \"PLATFORM\", \"BANK\", \"DEVELOPER\", \"LEGAL\", \"INSURER\", \"GOVERNMENT\"\n name String // Human-readable: \"Platform Operator\", \"Bank/Lender\", etc.\n description String? @db.Text\n\n // System types are seeded during bootstrap and cannot be deleted\n isSystemType Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Organizations with this type\n organizations OrganizationTypeAssignment[]\n\n // Applications assigned to orgs acting as this type\n applicationOrganizations ApplicationOrganization[]\n\n // Approval stages that require this type of organization\n approvalStages ApprovalStage[]\n\n // Document reviews performed by orgs acting as this type (audit snapshot)\n documentReviews DocumentReview[]\n\n // Approval stage progress instances\n approvalStageProgress ApprovalStageProgress[]\n\n // Document approvals\n documentApprovals DocumentApproval[]\n\n @@unique([tenantId, code])\n @@index([tenantId])\n @@index([code])\n @@map(\"organization_types\")\n}\n\n/// Links organizations to their types (many-to-many)\n/// An organization can have multiple types (e.g., QShelter is PLATFORM + DEVELOPER)\nmodel OrganizationTypeAssignment {\n id String @id @default(cuid())\n organizationId String\n organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)\n typeId String\n orgType OrganizationType @relation(fields: [typeId], references: [id], onDelete: Cascade)\n\n // Which type is the primary one for display purposes\n isPrimary Boolean @default(false)\n\n createdAt DateTime @default(now())\n\n @@unique([organizationId, typeId])\n @@index([organizationId])\n @@index([typeId])\n @@map(\"organization_type_assignments\")\n}\n\n/// Status of an organization\nenum OrganizationStatus {\n PENDING // Awaiting approval to operate on platform\n ACTIVE // Fully operational\n SUSPENDED // Temporarily suspended\n INACTIVE // No longer active\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\n// =============================================================================\n// DOCUMENT REVIEW ENUMS\n// =============================================================================\n\nenum ReviewDecision {\n PENDING // Review not yet performed\n APPROVED // Document approved by this party\n REJECTED // Document rejected (permanent)\n CHANGES_REQUESTED // Document needs modifications\n WAIVED // Review not required by this party\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 NEEDS_REUPLOAD // Document rejected, customer must re-upload\n}\n\n// =============================================================================\n// APPROVAL STAGE ENUMS (Multi-stage document workflow)\n// =============================================================================\n\n/// Status of an approval stage in a documentation phase\nenum StageStatus {\n PENDING // Not yet activated\n IN_PROGRESS // Activated, documents being reviewed\n AWAITING_TRANSITION // All docs approved, waiting for explicit stage completion\n COMPLETED // Stage completed, next stage can activate\n}\n\n/// Who uploads a document\nenum UploadedBy {\n CUSTOMER\n LENDER\n DEVELOPER\n LEGAL\n INSURER\n PLATFORM // QShelter staff\n}\n\n/// What happens when a later stage rejects a document\nenum RejectionBehavior {\n CASCADE_BACK // Restart from Stage 1 (default - full re-vetting)\n RESTART_CURRENT // Only current stage re-reviews after re-upload\n RESTART_FROM_STAGE // Restart from specific stage (uses restartFromStageOrder)\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 HANDLER_EXECUTED // Event handler was executed\n}\n\nenum ApplicationEventGroup {\n STATE_CHANGE\n PAYMENT\n DOCUMENT\n NOTIFICATION\n WORKFLOW\n AUTOMATION // Automated handler executions\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/// 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 (new model)\n uploadedDocs ApplicationDocument[] @relation(\"DocumentUploader\")\n documentApprovals DocumentApproval[] @relation(\"DocumentApprovalReviewer\")\n completedStages ApprovalStageProgress[] @relation(\"StageCompletedBy\")\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 // Document reviews by this user\n documentReviews DocumentReview[] @relation(\"DocumentReviewer\")\n\n // Questionnaire phase reviews by this user\n questionnaireReviews QuestionnairePhaseReview[] @relation(\"QuestionnaireReviewer\")\n\n // Organization memberships (user can be employee of banks/developers)\n organizationMemberships OrganizationMember[]\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\n// =============================================================================\n// ORGANIZATIONS (Banks, Developers, etc.)\n// =============================================================================\n// Organizations represent external entities that participate in the platform.\n// Banks provide mortgage financing; Developers build and sell properties.\n// Users can be employees (members) of organizations with specific roles.\n// =============================================================================\n\n/// Organization: Banks, Developers, and other partner entities\nmodel Organization {\n id String @id @default(cuid())\n tenantId String\n name String // e.g., \"Access Bank PLC\", \"Lekki Gardens Ltd\"\n status OrganizationStatus @default(PENDING)\n\n // Organization types (many-to-many via OrganizationTypeAssignment)\n // An org can have multiple types (e.g., QShelter is PLATFORM + DEVELOPER)\n types OrganizationTypeAssignment[]\n\n // Platform organization flag - marks the tenant's own organization\n isPlatformOrg Boolean @default(false)\n\n // Common fields\n email String? // Primary contact email\n phone String? // Primary contact phone\n address String?\n city String?\n state String?\n country String? @default(\"Nigeria\")\n website String?\n logoUrl String?\n description String? @db.Text\n\n // Bank-specific fields\n bankCode String? // CBN bank code (e.g., \"044\" for Access Bank)\n bankLicenseNo String? // Banking license number\n swiftCode String? // SWIFT/BIC code for international transfers\n sortCode String? // Sort code for local transfers\n\n // Developer-specific fields\n cacNumber String? // CAC registration number\n cacCertificateUrl String? // URL to CAC certificate document\n taxId String? // Tax Identification Number\n\n // Approval workflow\n approvedAt DateTime?\n approvedById String?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n members OrganizationMember[]\n\n // Applications where this organization is involved\n applicationAssignments ApplicationOrganization[]\n\n // Bank-specific document requirements (for BANK type organizations)\n documentRequirements BankDocumentRequirement[]\n\n // Document reviews performed by this organization\n documentReviews DocumentReview[]\n\n // Properties developed by this organization (for DEVELOPERs)\n // developedProperties Property[] @relation(\"PropertyDeveloper\")\n\n @@unique([tenantId, bankCode]) // Bank codes unique within tenant\n @@unique([tenantId, cacNumber]) // CAC numbers unique within tenant\n @@index([tenantId])\n @@index([status])\n @@map(\"organizations\")\n}\n\n/// OrganizationMember: Links users to organizations\n/// User's own roles (via UserRole) determine their abilities within the org\nmodel OrganizationMember {\n id String @id @default(cuid())\n organizationId String\n userId String\n\n // Employee details\n title String? // Job title (e.g., \"Loan Officer\", \"Mortgage Operations Officer\")\n department String? // Department within organization\n employeeId String? // Internal employee ID\n\n // Status\n isActive Boolean @default(true)\n\n // Invitation/onboarding tracking\n invitedAt DateTime?\n acceptedAt DateTime?\n invitedBy String? // User ID who invited this member\n joinedAt DateTime @default(now())\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@unique([organizationId, userId]) // User can only be member once per org\n @@index([userId])\n @@index([organizationId])\n @@map(\"organization_members\")\n}\n\n// =============================================================================\n// BANK DOCUMENT REQUIREMENTS - Bank-specific document overlays\n// =============================================================================\n// Banks have different risk appetites and compliance requirements.\n// For a standardized product (e.g., NHF Mortgage), the payment structure is fixed\n// but document requirements vary by bank.\n//\n// This model defines OVERLAY rules:\n// - Base documents come from DocumentationPlan\n// - Bank adds/modifies requirements via BankDocumentRequirement\n//\n// When switching banks mid-application:\n// 1. Keep all existing approved documents\n// 2. Query new bank's requirements\n// 3. Calculate delta (what's missing)\n// 4. Customer uploads only the delta\n// =============================================================================\n\n/// How the bank's requirement modifies the base requirement\nenum BankDocumentModifier {\n REQUIRED // Bank requires this document (add if not in base)\n OPTIONAL // Bank makes this optional (override base if required)\n NOT_REQUIRED // Bank doesn't need this (skip even if in base)\n STRICTER // Bank has stricter version (e.g., 12 months instead of 6)\n}\n\n/// Bank Document Requirement - Bank-specific document rules\nmodel BankDocumentRequirement {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Which bank this applies to\n organizationId String\n organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)\n\n // Which phase type this applies to (e.g., KYC, VERIFICATION)\n phaseType String\n\n // Optional: specific payment method (NULL = applies to all)\n paymentMethodId String?\n paymentMethod PropertyPaymentMethod? @relation(fields: [paymentMethodId], references: [id])\n\n // Document identification\n documentType String // ID_CARD, BANK_STATEMENT, EMPLOYMENT_LETTER, etc.\n documentName String // Human-readable override (e.g., \"12 Months Bank Statement\")\n\n // How this modifies the base requirement\n modifier BankDocumentModifier @default(REQUIRED)\n\n // Bank-specific rules\n description String? @db.Text // Bank's specific instructions\n expiryDays Int? // Bank's validity period (may be stricter than base)\n minFiles Int? // Bank may require more files\n maxFiles Int?\n allowedMimeTypes String? // Bank may restrict file types\n\n // Bank-specific validation (JSON schema)\n // Example: { \"bankStatementMonths\": 12, \"minimumBalance\": 500000 }\n validationRules Json?\n\n // Priority for conflict resolution (higher = takes precedence)\n priority Int @default(100)\n\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([organizationId, phaseType, documentType, paymentMethodId])\n @@index([tenantId])\n @@index([organizationId])\n @@index([phaseType])\n @@index([documentType])\n @@index([paymentMethodId])\n @@map(\"bank_document_requirements\")\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\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 paymentInstallments PaymentInstallment[]\n applicationPayments ApplicationPayment[]\n applicationDocuments ApplicationDocument[]\n documentApprovals DocumentApproval[]\n approvalStageProgress ApprovalStageProgress[]\n propertyMedia PropertyMedia[]\n propertyDocuments PropertyDocument[]\n propertyVariants PropertyVariant[]\n propertyVariantAmenities PropertyVariantAmenity[]\n propertyVariantMedia PropertyVariantMedia[]\n propertyUnits PropertyUnit[]\n propertyAmenities PropertyAmenity[]\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 questionnairePhaseReviews QuestionnairePhaseReview[]\n documentReviews DocumentReview[]\n\n // Bank-specific document requirements\n bankDocumentRequirements BankDocumentRequirement[]\n\n // Organizations (Banks, Developers) operating on this tenant\n organizations Organization[]\n\n // Application organization assignments\n applicationOrganizations ApplicationOrganization[]\n organizationTypes OrganizationType[]\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 PropertyStatus @default(DRAFT)\n description String? @db.Text\n displayImageId String?\n displayImage PropertyMedia? @relation(\"DisplayImage\", fields: [displayImageId], references: [id], onDelete: SetNull)\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 // Optimistic locking for unit reservation race condition\n version Int @default(0)\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 createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Document definitions (what documents to collect)\n documentDefinitions DocumentDefinition[]\n\n // Approval stages (sequential workflow for reviewing documents)\n approvalStages ApprovalStage[]\n\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// =============================================================================\n// DOCUMENT DEFINITION - What documents to collect (template)\n// =============================================================================\n// Defines a document requirement within a documentation plan.\n// This is separate from approval workflow - just defines WHAT to collect.\n// =============================================================================\n\nmodel DocumentDefinition {\n id String @id @default(cuid())\n planId String\n plan DocumentationPlan @relation(fields: [planId], references: [id], onDelete: Cascade)\n\n // Document identification\n documentType String // ID_CARD, BANK_STATEMENT, EMPLOYMENT_LETTER, etc.\n documentName String // Human-readable: \"Valid ID Card\", \"6 Months Bank Statement\"\n\n // Who uploads this document\n uploadedBy UploadedBy @default(CUSTOMER)\n\n // Display order\n order Int\n\n // Validation rules\n isRequired Boolean @default(true)\n description String? @db.Text // Instructions for the uploader\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 minFiles Int @default(1)\n maxFiles Int @default(1)\n\n // Conditional logic (based on questionnaire answers)\n // NULL = always required\n // Example: { \"questionKey\": \"mortgage_type\", \"operator\": \"EQUALS\", \"value\": \"JOINT\" }\n condition Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([planId])\n @@map(\"document_definitions\")\n}\n\n// =============================================================================\n// APPROVAL STAGE - Sequential workflow stages for document review (template)\n// =============================================================================\n// Defines a stage in the approval workflow. Documents flow through stages\n// sequentially. Each stage requires a specific organization type to review.\n// =============================================================================\n\nmodel ApprovalStage {\n id String @id @default(cuid())\n planId String\n plan DocumentationPlan @relation(fields: [planId], references: [id], onDelete: Cascade)\n\n name String // \"QShelter Review\", \"Bank Review\"\n order Int // 1, 2, 3 - sequential order\n organizationTypeId String // Which type of org should review at this stage\n organizationType OrganizationType @relation(fields: [organizationTypeId], references: [id])\n\n // Stage behavior flags\n autoTransition Boolean @default(false) // Auto-complete when all docs approved? Default: require explicit approval\n waitForAllDocuments Boolean @default(true) // Wait for all docs approved before allowing transition\n allowEarlyVisibility Boolean @default(false) // Allow read-only view before stage activates\n\n // Rejection behavior - what happens when this stage rejects a document\n onRejection RejectionBehavior @default(CASCADE_BACK)\n restartFromStageOrder Int? // If onRejection = RESTART_FROM_STAGE, which stage order to restart from\n\n // SLA (optional)\n slaHours Int? // Escalate if not completed within X hours\n\n description String? @db.Text // Instructions for reviewers at this stage\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Runtime instances\n stageProgress ApprovalStageProgress[]\n\n @@unique([planId, order])\n @@index([planId])\n @@index([organizationTypeId])\n @@map(\"approval_stages\")\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 format: Array of { operator: ConditionOperator, value: number, score: number }\n // First matching rule wins. Example:\n // [{ operator: \"GREATER_THAN_OR_EQUAL\", value: 3000000, score: 100 },\n // { operator: \"GREATER_THAN_OR_EQUAL\", value: 2000000, score: 80 }]\n scoringRules Json?\n\n // Conditional logic (branching)\n // { \"questionKey\": \"employment_status\", \"equals\": \"employed\" }\n showIf Json?\n\n // Metadata for grouping\n category QuestionCategory? // Group questions by topic\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 // Bank-specific document requirements for this payment method\n bankDocumentRequirements BankDocumentRequirement[]\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 @@unique([paymentMethodId, order]) // Enforce unique, sequential ordering\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 @@unique([phaseId, order]) // Enforce unique, sequential ordering within phase\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/// Category for individual questions within a questionnaire\n/// Used to group questions by topic for UI/UX and scoring\nenum QuestionCategory {\n ELIGIBILITY // Age, citizenship, legal status\n EMPLOYMENT // Employment status, employer details\n INCOME // Salary, bonuses, other income\n AFFORDABILITY // Income vs expenses, debt-to-income\n EXPENSES // Monthly expenses, existing debts\n APPLICATION_TYPE // Type of mortgage/purchase (single, joint)\n PERSONAL // Marital status, dependents, contact info\n PREFERENCES // Preferred terms, property type preferences\n PROPERTY // Property-related questions\n CREDIT // Credit history, existing loans\n ASSETS // Savings, investments, other assets\n CUSTOM // Custom/uncategorized questions\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: Restrict)\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 // =========================================================================\n // PAYMENT METHOD VERSION SNAPSHOT\n // =========================================================================\n // Captures the payment method configuration at application creation time.\n // This ensures existing applications continue with original terms even if\n // the payment method template is later modified.\n // =========================================================================\n paymentMethodSnapshot Json? // Full snapshot of PropertyPaymentMethod + phases at creation\n paymentMethodSnapshotAt DateTime? // When the snapshot was taken\n paymentMethodSnapshotHash String? // Hash to detect if template changed since snapshot\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 // Organization assignments - which orgs are involved in this application\n organizations ApplicationOrganization[]\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// APPLICATION ORGANIZATION - Binds organizations to specific applications\n// =============================================================================\n// Tracks which organizations (banks, developers, legal firms) are involved\n// in a specific application. This enables:\n// 1. Validation that only assigned developers can upload sales offers\n// 2. Only assigned banks can upload preapproval/mortgage offer letters\n// 3. Flexible type-based assignment (org assigned acting as specific type)\n// =============================================================================\n\n/// Status of organization's involvement in the application\nenum ApplicationOrganizationStatus {\n PENDING // Awaiting organization's response/engagement\n ACTIVE // Organization is actively participating\n COMPLETED // Organization's role is complete\n DECLINED // Organization declined to participate\n WITHDRAWN // Organization withdrew from the application\n}\n\nmodel ApplicationOrganization {\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 // Which organization is involved\n organizationId String\n organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)\n\n // Which type the org is acting as on this application\n // (org must have this type in their OrganizationTypeAssignment)\n assignedAsTypeId String\n assignedAsType OrganizationType @relation(fields: [assignedAsTypeId], references: [id])\n\n status ApplicationOrganizationStatus @default(PENDING)\n\n // Who assigned this organization (admin or system)\n assignedById String?\n assignedAt DateTime @default(now())\n\n // For multi-bank applications: track if this is the selected lender\n // Multiple banks can be PENDING, but only one should be ACTIVE for LENDER role\n isPrimary Boolean @default(false)\n\n // Organization-specific terms (e.g., bank's offered interest rate)\n offeredTerms Json? // { interestRate, termMonths, conditions, etc. }\n termsOfferedAt DateTime?\n termsAcceptedAt DateTime?\n termsDeclinedAt DateTime?\n declineReason String? @db.Text\n\n // Tracking\n activatedAt DateTime?\n completedAt DateTime?\n withdrawnAt DateTime?\n\n // =========================================================================\n // SLA TRACKING - Monitor bank responsiveness\n // =========================================================================\n // When documentation is complete, clock starts for bank to respond.\n // If they're slow, admin can reassign to another bank.\n // =========================================================================\n slaHours Int? // Expected response time (e.g., 48 hours)\n slaStartedAt DateTime? // When clock started (e.g., when docs were complete)\n slaBreachedAt DateTime? // When SLA was breached (set by cron job)\n slaBreachNotified Boolean @default(false) // Was admin notified of breach?\n\n // Reminder tracking\n reminderCount Int @default(0)\n lastReminderSentAt DateTime?\n nextReminderAt DateTime?\n\n // Escalation\n escalatedAt DateTime?\n escalatedToUserId String? // Admin handling the escalation\n escalationNotes String? @db.Text\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([applicationId, assignedAsTypeId]) // One org per type per application\n @@index([tenantId])\n @@index([applicationId])\n @@index([organizationId])\n @@index([assignedAsTypeId])\n @@index([status])\n @@index([isPrimary])\n @@index([slaBreachedAt])\n @@map(\"application_organizations\")\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 // Review audit trail\n reviews QuestionnairePhaseReview[]\n\n // Back-relation: Documentation phases that use this questionnaire's answers for conditions\n dependentDocumentationPhases DocumentationPhase[] @relation(\"SourceQuestionnaire\")\n\n @@index([tenantId])\n @@index([phaseId])\n @@index([questionnairePlanId])\n @@map(\"questionnaire_phases\")\n}\n\n// =============================================================================\n// QUESTIONNAIRE PHASE REVIEW - Audit trail for questionnaire reviews\n// =============================================================================\n// Captures every review decision made on a questionnaire phase.\n// Supports workflows where questionnaire may be rejected → resubmitted → approved.\n// The scoring serves as guidance; reviewer makes the final decision.\n// =============================================================================\n\nmodel QuestionnairePhaseReview {\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 // Review details\n reviewerId String\n reviewer User @relation(\"QuestionnaireReviewer\", fields: [reviewerId], references: [id])\n decision ReviewDecision\n notes String? @db.Text\n\n // Snapshot of scores at time of review (for audit)\n scoreAtReview Int? // The totalScore when this review was made\n passedAtReview Boolean? // The passed flag when this review was made\n\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([questionnairePhaseId])\n @@index([reviewerId])\n @@map(\"questionnaire_phase_reviews\")\n}\n\n// =============================================================================\n// DOCUMENTATION PHASE DATA - Extension for DOCUMENTATION phases\n// =============================================================================\n// Manages document upload/approval workflow with sequential approval stages\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 // Source questionnaire for conditional document evaluation\n // Links to the questionnaire phase whose answers determine which documents are required\n sourceQuestionnairePhaseId String?\n sourceQuestionnairePhase QuestionnairePhase? @relation(\"SourceQuestionnaire\", fields: [sourceQuestionnairePhaseId], references: [id])\n\n // Current approval stage pointer for UX and orchestration\n currentStageOrder Int @default(1)\n\n // Progress counters\n approvedDocumentsCount Int @default(0)\n requiredDocumentsCount Int @default(0)\n\n // Snapshots for audit\n documentDefinitionsSnapshot Json?\n approvalStagesSnapshot Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Approval stage progress (tracks which stages are completed)\n stageProgress ApprovalStageProgress[]\n\n @@index([tenantId])\n @@index([phaseId])\n @@index([sourceQuestionnairePhaseId])\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 // Optimistic locking for concurrent payment protection\n version Int @default(0)\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// 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 // Optimistic locking for concurrent payment protection\n version Int @default(0)\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 // Document info\n documentType String? // ID_CARD, BANK_STATEMENT, etc. (matches DocumentDefinition.documentType)\n documentName String? // Human-readable name (copied from DocumentDefinition.documentName)\n name String // File name\n url String\n type String // ID, BANK_STATEMENT, INCOME_PROOF, TITLE_DEED, SIGNATURE, etc. (legacy, use documentType)\n uploadedById String?\n uploadedBy User? @relation(\"DocumentUploader\", fields: [uploadedById], references: [id])\n\n // =========================================================================\n // UPLOADER VALIDATION - Enforces who can upload this document\n // =========================================================================\n // expectedUploader is set from DocumentDefinition.uploadedBy at phase creation\n // Allows validation that correct party is uploading (e.g., developer uploads sales offer)\n expectedUploader UploadedBy? // CUSTOMER, LENDER, DEVELOPER, LEGAL, PLATFORM, etc.\n // If expectedUploader is LENDER/DEVELOPER, track which org should upload\n expectedOrganizationId String?\n\n // =========================================================================\n // DOCUMENT EXPIRY - Time-sensitive document tracking\n // =========================================================================\n // Documents like bank statements have a shelf life. If application takes too long,\n // documents may need to be re-uploaded.\n // =========================================================================\n documentDate DateTime? // When the document was issued/created (e.g., bank statement date)\n expiresAt DateTime? // When this document expires (computed from documentDate + expiryDays)\n expiryDays Int? // Number of days this document type is valid (copied from DocumentDefinition)\n isExpired Boolean @default(false) // Denormalized flag, updated by cron job\n expiredAt DateTime? // When the document was marked expired\n expiryWarningAt DateTime? // When expiry warning was sent\n revalidatedAt DateTime? // If document was re-uploaded after expiry\n\n status DocumentStatus @default(PENDING)\n\n // NO versioning - document is replaced on re-upload (url is updated)\n // Keep these fields for backward compatibility but don't use for new code\n version Int @default(1)\n replacesDocumentId String? // If this is a revision, points to original\n replacesDocument ApplicationDocument? @relation(\"DocumentRevisions\", fields: [replacesDocumentId], references: [id])\n revisions ApplicationDocument[] @relation(\"DocumentRevisions\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // OLD: Multi-party reviews (deprecated, use approvalTrail)\n reviews DocumentReview[]\n\n // NEW: Full approval trail across all stages\n approvalTrail DocumentApproval[]\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([phaseId])\n @@index([stepId])\n @@index([type])\n @@index([documentType])\n @@index([status])\n @@index([replacesDocumentId])\n @@index([isExpired])\n @@index([expiresAt])\n @@map(\"application_documents\")\n}\n\n// =============================================================================\n// DOCUMENT REVIEW - Multi-party review tracking\n// =============================================================================\n// Tracks reviews by different organizations for the same document.\n// organizationId is NULL for customer self-attestations/signatures.\n// For org reviews, organizationTypeId captures which type the org was acting as.\n// =============================================================================\n\nmodel DocumentReview {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n documentId String\n document ApplicationDocument @relation(fields: [documentId], references: [id], onDelete: Cascade)\n\n // Who is reviewing - NULL organizationId means customer self-review\n organizationId String? // Organization performing the review (null = customer)\n organization Organization? @relation(fields: [organizationId], references: [id])\n organizationTypeId String? // Which type the org was acting as (audit snapshot)\n organizationType OrganizationType? @relation(fields: [organizationTypeId], references: [id])\n reviewerId String? // User who performed the review\n reviewer User? @relation(\"DocumentReviewer\", fields: [reviewerId], references: [id])\n reviewerName String? // Denormalized for audit trail\n\n // Review state\n decision ReviewDecision @default(PENDING)\n comments String? @db.Text // General comments\n\n // Structured concerns for change requests\n // Format: [{ field: \"income_period\", issue: \"Missing months April-June\" }]\n concerns Json?\n\n // Review timing\n requestedAt DateTime @default(now())\n dueAt DateTime? // Optional deadline for this party\n reviewedAt DateTime? // When decision was made\n\n // Review sequence (which order should parties review?)\n reviewOrder Int @default(0) // 0 = parallel, 1/2/3 = sequential\n\n // For review chains (re-reviews after changes)\n parentReviewId String? // If this is a re-review after changes\n parentReview DocumentReview? @relation(\"ReviewChain\", fields: [parentReviewId], references: [id])\n childReviews DocumentReview[] @relation(\"ReviewChain\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Unique: one review per org per doc (null org = customer review)\n @@unique([documentId, organizationId])\n @@index([tenantId])\n @@index([documentId])\n @@index([organizationId])\n @@index([organizationTypeId])\n @@index([decision])\n @@index([reviewerId])\n @@index([parentReviewId])\n @@map(\"document_reviews\")\n}\n\n// =============================================================================\n// APPROVAL STAGE PROGRESS - Runtime tracking of stage completion per phase\n// =============================================================================\n// Tracks the progress of each approval stage within a documentation phase.\n// Created when a documentation phase is instantiated from a plan.\n// =============================================================================\n\nmodel ApprovalStageProgress {\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 // Link to template\n approvalStageId String\n approvalStage ApprovalStage @relation(fields: [approvalStageId], references: [id])\n\n // Stage info (denormalized for convenience)\n name String\n order Int\n organizationTypeId String // Which type of org should review at this stage\n organizationType OrganizationType @relation(fields: [organizationTypeId], references: [id])\n\n // Behavior flags (copied from template)\n autoTransition Boolean @default(false)\n waitForAllDocuments Boolean @default(true)\n allowEarlyVisibility Boolean @default(false)\n\n // Rejection behavior (copied from template)\n onRejection RejectionBehavior @default(CASCADE_BACK)\n restartFromStageOrder Int?\n\n // Status tracking\n status StageStatus @default(PENDING)\n activatedAt DateTime?\n completedAt DateTime?\n\n // Who completed this stage (when autoTransition = false)\n completedById String?\n completedBy User? @relation(\"StageCompletedBy\", fields: [completedById], references: [id])\n transitionComment String? @db.Text // Optional comment when completing stage\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Document approvals made during this stage\n documentApprovals DocumentApproval[]\n\n @@unique([documentationPhaseId, order])\n @@index([tenantId])\n @@index([documentationPhaseId])\n @@index([approvalStageId])\n @@index([status])\n @@map(\"approval_stage_progress\")\n}\n\n// =============================================================================\n// DOCUMENT APPROVAL - Audit trail for document reviews per stage\n// =============================================================================\n// Records every review action taken on a document within a specific stage.\n// Provides full audit trail: who reviewed, what decision, when, with comments.\n// =============================================================================\n\nmodel DocumentApproval {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n documentId String\n document ApplicationDocument @relation(fields: [documentId], references: [id], onDelete: Cascade)\n\n // Which stage this approval belongs to\n stageProgressId String\n stageProgress ApprovalStageProgress @relation(fields: [stageProgressId], references: [id], onDelete: Cascade)\n\n // Reviewer info\n reviewerId String\n reviewer User @relation(\"DocumentApprovalReviewer\", fields: [reviewerId], references: [id])\n organizationTypeId String // Which type the reviewer's org was acting as\n organizationType OrganizationType @relation(fields: [organizationTypeId], references: [id])\n\n // Decision\n decision ReviewDecision // APPROVED, REJECTED, CHANGES_REQUESTED\n comment String? @db.Text // Required on rejection\n\n reviewedAt DateTime @default(now())\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([documentId])\n @@index([stageProgressId])\n @@index([reviewerId])\n @@index([organizationTypeId])\n @@index([decision])\n @@map(\"document_approvals\")\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 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 /// 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// =============================================================================\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\n// =============================================================================\n// DOCUMENT EXPIRY JOB - Scheduled job tracking for document expiration checks\n// =============================================================================\n// Tracks scheduled jobs for checking document expiration across applications.\n// This supports a cron-based approach where a Lambda runs periodically to:\n// 1. Find documents nearing expiry (warning)\n// 2. Mark expired documents\n// 3. Notify customers to re-upload\n// 4. Optionally block phase progression if critical documents expired\n// =============================================================================\n\n/// Job status for scheduled background jobs\nenum ScheduledJobStatus {\n PENDING\n RUNNING\n COMPLETED\n FAILED\n CANCELLED\n}\n\n/// Type of scheduled job\nenum ScheduledJobType {\n DOCUMENT_EXPIRY_CHECK // Check for expired documents\n SLA_BREACH_CHECK // Check for SLA breaches\n PAYMENT_REMINDER // Send payment reminders\n DOCUMENT_EXPIRY_WARNING // Warn about documents nearing expiry\n}\n\n/// Scheduled Job - Tracks execution of background jobs\nmodel ScheduledJob {\n id String @id @default(cuid())\n tenantId String? // NULL = system-wide job, set = tenant-specific\n\n jobType ScheduledJobType\n status ScheduledJobStatus @default(PENDING)\n\n // Scheduling\n scheduledAt DateTime // When the job should run\n startedAt DateTime? // When job started executing\n completedAt DateTime? // When job finished\n durationMs Int? // Execution time\n\n // Job parameters\n parameters Json? // Job-specific configuration\n\n // Results\n itemsProcessed Int @default(0)\n itemsAffected Int @default(0) // Documents expired, SLAs breached, etc.\n errorCount Int @default(0)\n errors Json? // Array of error details\n summary String? @db.Text // Human-readable summary\n\n // Retry handling\n attemptNumber Int @default(1)\n maxAttempts Int @default(3)\n nextRetryAt DateTime?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([jobType])\n @@index([status])\n @@index([scheduledAt])\n @@index([jobType, status, scheduledAt])\n @@map(\"scheduled_jobs\")\n}\n\n/// Document Expiry Warning - Track warnings sent for expiring documents\nmodel DocumentExpiryWarning {\n id String @id @default(cuid())\n tenantId String\n documentId String\n\n // Warning details\n expiresAt DateTime // When document will expire\n daysUntil Int // Days until expiry at time of warning\n warningSent DateTime @default(now())\n\n // Customer notification tracking\n notificationSent Boolean @default(false)\n notificationId String? // Reference to notification service\n\n // Resolution tracking\n resolved Boolean @default(false)\n resolvedAt DateTime?\n resolvedBy String? // User who resolved (re-uploaded document)\n newDocumentId String? // ID of the replacement document\n\n createdAt DateTime @default(now())\n\n @@unique([documentId, daysUntil]) // One warning per document per threshold\n @@index([tenantId])\n @@index([documentId])\n @@index([expiresAt])\n @@index([resolved])\n @@map(\"document_expiry_warnings\")\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 PropertyStatus {\n DRAFT\n PUBLISHED\n SOLD_OUT\n ARCHIVED\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\n/// Triggers that cause application state transitions\nenum ApplicationTrigger {\n SUBMIT // Submit application for review (DRAFT -> PENDING)\n APPROVE // Approve pending application (PENDING -> ACTIVE)\n REJECT // Reject pending application (PENDING -> CANCELLED)\n CANCEL // Cancel application\n COMPLETE // Complete application (all phases done)\n TERMINATE // Terminate active application\n TRANSFER // Transfer to different unit\n SUPERSEDE // Another buyer locked the unit\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/// Operators for conditional step evaluation\nenum ConditionOperator {\n EQUALS // Field value equals expected value\n NOT_EQUALS // Field value does not equal expected value\n IN // Field value is in a list of values\n NOT_IN // Field value is not in a list of values\n GREATER_THAN // Numeric comparison\n LESS_THAN // Numeric comparison\n GREATER_THAN_OR_EQUAL\n LESS_THAN_OR_EQUAL\n EXISTS // Field has any value (not null/undefined)\n NOT_EXISTS // Field is null/undefined\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// ORGANIZATION TYPE - Lookup table for organization types (replaces enum)\n// =============================================================================\n// Organizations can have multiple types via OrganizationTypeAssignment.\n// Example: QShelter can be both PLATFORM and DEVELOPER.\n// System types are seeded during tenant bootstrap and cannot be deleted.\n// =============================================================================\n\nmodel OrganizationType {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n code String // \"PLATFORM\", \"BANK\", \"DEVELOPER\", \"LEGAL\", \"INSURER\", \"GOVERNMENT\"\n name String // Human-readable: \"Platform Operator\", \"Bank/Lender\", etc.\n description String? @db.Text\n\n // System types are seeded during bootstrap and cannot be deleted\n isSystemType Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Organizations with this type\n organizations OrganizationTypeAssignment[]\n\n // Applications assigned to orgs acting as this type\n applicationOrganizations ApplicationOrganization[]\n\n // Approval stages that require this type of organization\n approvalStages ApprovalStage[]\n\n // Document reviews performed by orgs acting as this type (audit snapshot)\n documentReviews DocumentReview[]\n\n // Approval stage progress instances\n approvalStageProgress ApprovalStageProgress[]\n\n // Document approvals\n documentApprovals DocumentApproval[]\n\n @@unique([tenantId, code])\n @@index([tenantId])\n @@index([code])\n @@map(\"organization_types\")\n}\n\n/// Links organizations to their types (many-to-many)\n/// An organization can have multiple types (e.g., QShelter is PLATFORM + DEVELOPER)\nmodel OrganizationTypeAssignment {\n id String @id @default(cuid())\n organizationId String\n organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)\n typeId String\n orgType OrganizationType @relation(fields: [typeId], references: [id], onDelete: Cascade)\n\n // Which type is the primary one for display purposes\n isPrimary Boolean @default(false)\n\n createdAt DateTime @default(now())\n\n @@unique([organizationId, typeId])\n @@index([organizationId])\n @@index([typeId])\n @@map(\"organization_type_assignments\")\n}\n\n/// Status of an organization\nenum OrganizationStatus {\n PENDING // Awaiting approval to operate on platform\n ACTIVE // Fully operational\n SUSPENDED // Temporarily suspended\n INACTIVE // No longer active\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\n// =============================================================================\n// DOCUMENT REVIEW ENUMS\n// =============================================================================\n\nenum ReviewDecision {\n PENDING // Review not yet performed\n APPROVED // Document approved by this party\n REJECTED // Document rejected (permanent)\n CHANGES_REQUESTED // Document needs modifications\n WAIVED // Review not required by this party\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 NEEDS_REUPLOAD // Document rejected, customer must re-upload\n}\n\n// =============================================================================\n// APPROVAL STAGE ENUMS (Multi-stage document workflow)\n// =============================================================================\n\n/// Status of an approval stage in a documentation phase\nenum StageStatus {\n PENDING // Not yet activated\n IN_PROGRESS // Activated, documents being reviewed\n AWAITING_TRANSITION // All docs approved, waiting for explicit stage completion\n COMPLETED // Stage completed, next stage can activate\n}\n\n/// Who uploads a document\nenum UploadedBy {\n CUSTOMER\n LENDER\n DEVELOPER\n LEGAL\n INSURER\n PLATFORM // QShelter staff\n}\n\n/// What happens when a later stage rejects a document\nenum RejectionBehavior {\n CASCADE_BACK // Restart from Stage 1 (default - full re-vetting)\n RESTART_CURRENT // Only current stage re-reviews after re-upload\n RESTART_FROM_STAGE // Restart from specific stage (uses restartFromStageOrder)\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 HANDLER_EXECUTED // Event handler was executed\n}\n\nenum ApplicationEventGroup {\n STATE_CHANGE\n PAYMENT\n DOCUMENT\n NOTIFICATION\n WORKFLOW\n AUTOMATION // Automated handler executions\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/// 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 (new model)\n uploadedDocs ApplicationDocument[] @relation(\"DocumentUploader\")\n documentApprovals DocumentApproval[] @relation(\"DocumentApprovalReviewer\")\n completedStages ApprovalStageProgress[] @relation(\"StageCompletedBy\")\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 // Document reviews by this user\n documentReviews DocumentReview[] @relation(\"DocumentReviewer\")\n\n // Questionnaire phase reviews by this user\n questionnaireReviews QuestionnairePhaseReview[] @relation(\"QuestionnaireReviewer\")\n\n // Organization memberships (user can be employee of banks/developers)\n organizationMemberships OrganizationMember[]\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\n// =============================================================================\n// ORGANIZATIONS (Banks, Developers, etc.)\n// =============================================================================\n// Organizations represent external entities that participate in the platform.\n// Banks provide mortgage financing; Developers build and sell properties.\n// Users can be employees (members) of organizations with specific roles.\n// =============================================================================\n\n/// Organization: Banks, Developers, and other partner entities\nmodel Organization {\n id String @id @default(cuid())\n tenantId String\n name String // e.g., \"Access Bank PLC\", \"Lekki Gardens Ltd\"\n status OrganizationStatus @default(PENDING)\n\n // Organization types (many-to-many via OrganizationTypeAssignment)\n // An org can have multiple types (e.g., QShelter is PLATFORM + DEVELOPER)\n types OrganizationTypeAssignment[]\n\n // Platform organization flag - marks the tenant's own organization\n isPlatformOrg Boolean @default(false)\n\n // Common fields\n email String? // Primary contact email\n phone String? // Primary contact phone\n address String?\n city String?\n state String?\n country String? @default(\"Nigeria\")\n website String?\n logoUrl String?\n description String? @db.Text\n\n // Bank-specific fields\n bankCode String? // CBN bank code (e.g., \"044\" for Access Bank)\n bankLicenseNo String? // Banking license number\n swiftCode String? // SWIFT/BIC code for international transfers\n sortCode String? // Sort code for local transfers\n\n // Developer-specific fields\n cacNumber String? // CAC registration number\n cacCertificateUrl String? // URL to CAC certificate document\n taxId String? // Tax Identification Number\n\n // Approval workflow\n approvedAt DateTime?\n approvedById String?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n members OrganizationMember[]\n\n // Applications where this organization is involved\n applicationAssignments ApplicationOrganization[]\n\n // Bank-specific document requirements (for BANK type organizations)\n documentRequirements BankDocumentRequirement[]\n\n // Document reviews performed by this organization\n documentReviews DocumentReview[]\n\n // Properties owned/developed by this organization\n properties Property[]\n\n @@unique([tenantId, bankCode]) // Bank codes unique within tenant\n @@unique([tenantId, cacNumber]) // CAC numbers unique within tenant\n @@index([tenantId])\n @@index([status])\n @@map(\"organizations\")\n}\n\n/// OrganizationMember: Links users to organizations\n/// User's own roles (via UserRole) determine their abilities within the org\nmodel OrganizationMember {\n id String @id @default(cuid())\n organizationId String\n userId String\n\n // Employee details\n title String? // Job title (e.g., \"Loan Officer\", \"Mortgage Operations Officer\")\n department String? // Department within organization\n employeeId String? // Internal employee ID\n\n // Status\n isActive Boolean @default(true)\n\n // Invitation/onboarding tracking\n invitedAt DateTime?\n acceptedAt DateTime?\n invitedBy String? // User ID who invited this member\n joinedAt DateTime @default(now())\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@unique([organizationId, userId]) // User can only be member once per org\n @@index([userId])\n @@index([organizationId])\n @@map(\"organization_members\")\n}\n\n// =============================================================================\n// BANK DOCUMENT REQUIREMENTS - Bank-specific document overlays\n// =============================================================================\n// Banks have different risk appetites and compliance requirements.\n// For a standardized product (e.g., NHF Mortgage), the payment structure is fixed\n// but document requirements vary by bank.\n//\n// This model defines OVERLAY rules:\n// - Base documents come from DocumentationPlan\n// - Bank adds/modifies requirements via BankDocumentRequirement\n//\n// When switching banks mid-application:\n// 1. Keep all existing approved documents\n// 2. Query new bank's requirements\n// 3. Calculate delta (what's missing)\n// 4. Customer uploads only the delta\n// =============================================================================\n\n/// How the bank's requirement modifies the base requirement\nenum BankDocumentModifier {\n REQUIRED // Bank requires this document (add if not in base)\n OPTIONAL // Bank makes this optional (override base if required)\n NOT_REQUIRED // Bank doesn't need this (skip even if in base)\n STRICTER // Bank has stricter version (e.g., 12 months instead of 6)\n}\n\n/// Bank Document Requirement - Bank-specific document rules\nmodel BankDocumentRequirement {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n\n // Which bank this applies to\n organizationId String\n organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)\n\n // Which phase type this applies to (e.g., KYC, VERIFICATION)\n phaseType String\n\n // Optional: specific payment method (NULL = applies to all)\n paymentMethodId String?\n paymentMethod PropertyPaymentMethod? @relation(fields: [paymentMethodId], references: [id])\n\n // Document identification\n documentType String // ID_CARD, BANK_STATEMENT, EMPLOYMENT_LETTER, etc.\n documentName String // Human-readable override (e.g., \"12 Months Bank Statement\")\n\n // How this modifies the base requirement\n modifier BankDocumentModifier @default(REQUIRED)\n\n // Bank-specific rules\n description String? @db.Text // Bank's specific instructions\n expiryDays Int? // Bank's validity period (may be stricter than base)\n minFiles Int? // Bank may require more files\n maxFiles Int?\n allowedMimeTypes String? // Bank may restrict file types\n\n // Bank-specific validation (JSON schema)\n // Example: { \"bankStatementMonths\": 12, \"minimumBalance\": 500000 }\n validationRules Json?\n\n // Priority for conflict resolution (higher = takes precedence)\n priority Int @default(100)\n\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([organizationId, phaseType, documentType, paymentMethodId])\n @@index([tenantId])\n @@index([organizationId])\n @@index([phaseType])\n @@index([documentType])\n @@index([paymentMethodId])\n @@map(\"bank_document_requirements\")\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\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 paymentInstallments PaymentInstallment[]\n applicationPayments ApplicationPayment[]\n applicationDocuments ApplicationDocument[]\n documentApprovals DocumentApproval[]\n approvalStageProgress ApprovalStageProgress[]\n propertyMedia PropertyMedia[]\n propertyDocuments PropertyDocument[]\n propertyVariants PropertyVariant[]\n propertyVariantAmenities PropertyVariantAmenity[]\n propertyVariantMedia PropertyVariantMedia[]\n propertyUnits PropertyUnit[]\n propertyAmenities PropertyAmenity[]\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 questionnairePhaseReviews QuestionnairePhaseReview[]\n documentReviews DocumentReview[]\n\n // Bank-specific document requirements\n bankDocumentRequirements BankDocumentRequirement[]\n\n // Organizations (Banks, Developers) operating on this tenant\n organizations Organization[]\n\n // Application organization assignments\n applicationOrganizations ApplicationOrganization[]\n organizationTypes OrganizationType[]\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\n // Optional organization ownership\n // If set, any member of this organization with DEVELOPER role can manage the property\n // If null, only the userId owner can manage it (individual seller)\n organizationId String?\n organization Organization? @relation(fields: [organizationId], references: [id], onDelete: SetNull)\n\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 PropertyStatus @default(DRAFT)\n description String? @db.Text\n displayImageId String?\n displayImage PropertyMedia? @relation(\"DisplayImage\", fields: [displayImageId], references: [id], onDelete: SetNull)\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([organizationId])\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 // Optimistic locking for unit reservation race condition\n version Int @default(0)\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 createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Document definitions (what documents to collect)\n documentDefinitions DocumentDefinition[]\n\n // Approval stages (sequential workflow for reviewing documents)\n approvalStages ApprovalStage[]\n\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// =============================================================================\n// DOCUMENT DEFINITION - What documents to collect (template)\n// =============================================================================\n// Defines a document requirement within a documentation plan.\n// This is separate from approval workflow - just defines WHAT to collect.\n// =============================================================================\n\nmodel DocumentDefinition {\n id String @id @default(cuid())\n planId String\n plan DocumentationPlan @relation(fields: [planId], references: [id], onDelete: Cascade)\n\n // Document identification\n documentType String // ID_CARD, BANK_STATEMENT, EMPLOYMENT_LETTER, etc.\n documentName String // Human-readable: \"Valid ID Card\", \"6 Months Bank Statement\"\n\n // Who uploads this document\n uploadedBy UploadedBy @default(CUSTOMER)\n\n // Display order\n order Int\n\n // Validation rules\n isRequired Boolean @default(true)\n description String? @db.Text // Instructions for the uploader\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 minFiles Int @default(1)\n maxFiles Int @default(1)\n\n // Conditional logic (based on questionnaire answers)\n // NULL = always required\n // Example: { \"questionKey\": \"mortgage_type\", \"operator\": \"EQUALS\", \"value\": \"JOINT\" }\n condition Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([planId])\n @@map(\"document_definitions\")\n}\n\n// =============================================================================\n// APPROVAL STAGE - Sequential workflow stages for document review (template)\n// =============================================================================\n// Defines a stage in the approval workflow. Documents flow through stages\n// sequentially. Each stage requires a specific organization type to review.\n// =============================================================================\n\nmodel ApprovalStage {\n id String @id @default(cuid())\n planId String\n plan DocumentationPlan @relation(fields: [planId], references: [id], onDelete: Cascade)\n\n name String // \"QShelter Review\", \"Bank Review\"\n order Int // 1, 2, 3 - sequential order\n organizationTypeId String // Which type of org should review at this stage\n organizationType OrganizationType @relation(fields: [organizationTypeId], references: [id])\n\n // Stage behavior flags\n autoTransition Boolean @default(false) // Auto-complete when all docs approved? Default: require explicit approval\n waitForAllDocuments Boolean @default(true) // Wait for all docs approved before allowing transition\n allowEarlyVisibility Boolean @default(false) // Allow read-only view before stage activates\n\n // Rejection behavior - what happens when this stage rejects a document\n onRejection RejectionBehavior @default(CASCADE_BACK)\n restartFromStageOrder Int? // If onRejection = RESTART_FROM_STAGE, which stage order to restart from\n\n // SLA (optional)\n slaHours Int? // Escalate if not completed within X hours\n\n description String? @db.Text // Instructions for reviewers at this stage\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Runtime instances\n stageProgress ApprovalStageProgress[]\n\n @@unique([planId, order])\n @@index([planId])\n @@index([organizationTypeId])\n @@map(\"approval_stages\")\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 format: Array of { operator: ConditionOperator, value: number, score: number }\n // First matching rule wins. Example:\n // [{ operator: \"GREATER_THAN_OR_EQUAL\", value: 3000000, score: 100 },\n // { operator: \"GREATER_THAN_OR_EQUAL\", value: 2000000, score: 80 }]\n scoringRules Json?\n\n // Conditional logic (branching)\n // { \"questionKey\": \"employment_status\", \"equals\": \"employed\" }\n showIf Json?\n\n // Metadata for grouping\n category QuestionCategory? // Group questions by topic\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 // Bank-specific document requirements for this payment method\n bankDocumentRequirements BankDocumentRequirement[]\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 @@unique([paymentMethodId, order]) // Enforce unique, sequential ordering\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 @@unique([phaseId, order]) // Enforce unique, sequential ordering within phase\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/// Category for individual questions within a questionnaire\n/// Used to group questions by topic for UI/UX and scoring\nenum QuestionCategory {\n ELIGIBILITY // Age, citizenship, legal status\n EMPLOYMENT // Employment status, employer details\n INCOME // Salary, bonuses, other income\n AFFORDABILITY // Income vs expenses, debt-to-income\n EXPENSES // Monthly expenses, existing debts\n APPLICATION_TYPE // Type of mortgage/purchase (single, joint)\n PERSONAL // Marital status, dependents, contact info\n PREFERENCES // Preferred terms, property type preferences\n PROPERTY // Property-related questions\n CREDIT // Credit history, existing loans\n ASSETS // Savings, investments, other assets\n CUSTOM // Custom/uncategorized questions\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: Restrict)\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 // =========================================================================\n // PAYMENT METHOD VERSION SNAPSHOT\n // =========================================================================\n // Captures the payment method configuration at application creation time.\n // This ensures existing applications continue with original terms even if\n // the payment method template is later modified.\n // =========================================================================\n paymentMethodSnapshot Json? // Full snapshot of PropertyPaymentMethod + phases at creation\n paymentMethodSnapshotAt DateTime? // When the snapshot was taken\n paymentMethodSnapshotHash String? // Hash to detect if template changed since snapshot\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 // Organization assignments - which orgs are involved in this application\n organizations ApplicationOrganization[]\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// APPLICATION ORGANIZATION - Binds organizations to specific applications\n// =============================================================================\n// Tracks which organizations (banks, developers, legal firms) are involved\n// in a specific application. This enables:\n// 1. Validation that only assigned developers can upload sales offers\n// 2. Only assigned banks can upload preapproval/mortgage offer letters\n// 3. Flexible type-based assignment (org assigned acting as specific type)\n// =============================================================================\n\n/// Status of organization's involvement in the application\nenum ApplicationOrganizationStatus {\n PENDING // Awaiting organization's response/engagement\n ACTIVE // Organization is actively participating\n COMPLETED // Organization's role is complete\n DECLINED // Organization declined to participate\n WITHDRAWN // Organization withdrew from the application\n}\n\nmodel ApplicationOrganization {\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 // Which organization is involved\n organizationId String\n organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)\n\n // Which type the org is acting as on this application\n // (org must have this type in their OrganizationTypeAssignment)\n assignedAsTypeId String\n assignedAsType OrganizationType @relation(fields: [assignedAsTypeId], references: [id])\n\n status ApplicationOrganizationStatus @default(PENDING)\n\n // Who assigned this organization (admin or system)\n assignedById String?\n assignedAt DateTime @default(now())\n\n // For multi-bank applications: track if this is the selected lender\n // Multiple banks can be PENDING, but only one should be ACTIVE for LENDER role\n isPrimary Boolean @default(false)\n\n // Organization-specific terms (e.g., bank's offered interest rate)\n offeredTerms Json? // { interestRate, termMonths, conditions, etc. }\n termsOfferedAt DateTime?\n termsAcceptedAt DateTime?\n termsDeclinedAt DateTime?\n declineReason String? @db.Text\n\n // Tracking\n activatedAt DateTime?\n completedAt DateTime?\n withdrawnAt DateTime?\n\n // =========================================================================\n // SLA TRACKING - Monitor bank responsiveness\n // =========================================================================\n // When documentation is complete, clock starts for bank to respond.\n // If they're slow, admin can reassign to another bank.\n // =========================================================================\n slaHours Int? // Expected response time (e.g., 48 hours)\n slaStartedAt DateTime? // When clock started (e.g., when docs were complete)\n slaBreachedAt DateTime? // When SLA was breached (set by cron job)\n slaBreachNotified Boolean @default(false) // Was admin notified of breach?\n\n // Reminder tracking\n reminderCount Int @default(0)\n lastReminderSentAt DateTime?\n nextReminderAt DateTime?\n\n // Escalation\n escalatedAt DateTime?\n escalatedToUserId String? // Admin handling the escalation\n escalationNotes String? @db.Text\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([applicationId, assignedAsTypeId]) // One org per type per application\n @@index([tenantId])\n @@index([applicationId])\n @@index([organizationId])\n @@index([assignedAsTypeId])\n @@index([status])\n @@index([isPrimary])\n @@index([slaBreachedAt])\n @@map(\"application_organizations\")\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 // Review audit trail\n reviews QuestionnairePhaseReview[]\n\n // Back-relation: Documentation phases that use this questionnaire's answers for conditions\n dependentDocumentationPhases DocumentationPhase[] @relation(\"SourceQuestionnaire\")\n\n @@index([tenantId])\n @@index([phaseId])\n @@index([questionnairePlanId])\n @@map(\"questionnaire_phases\")\n}\n\n// =============================================================================\n// QUESTIONNAIRE PHASE REVIEW - Audit trail for questionnaire reviews\n// =============================================================================\n// Captures every review decision made on a questionnaire phase.\n// Supports workflows where questionnaire may be rejected → resubmitted → approved.\n// The scoring serves as guidance; reviewer makes the final decision.\n// =============================================================================\n\nmodel QuestionnairePhaseReview {\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 // Review details\n reviewerId String\n reviewer User @relation(\"QuestionnaireReviewer\", fields: [reviewerId], references: [id])\n decision ReviewDecision\n notes String? @db.Text\n\n // Snapshot of scores at time of review (for audit)\n scoreAtReview Int? // The totalScore when this review was made\n passedAtReview Boolean? // The passed flag when this review was made\n\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([questionnairePhaseId])\n @@index([reviewerId])\n @@map(\"questionnaire_phase_reviews\")\n}\n\n// =============================================================================\n// DOCUMENTATION PHASE DATA - Extension for DOCUMENTATION phases\n// =============================================================================\n// Manages document upload/approval workflow with sequential approval stages\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 // Source questionnaire for conditional document evaluation\n // Links to the questionnaire phase whose answers determine which documents are required\n sourceQuestionnairePhaseId String?\n sourceQuestionnairePhase QuestionnairePhase? @relation(\"SourceQuestionnaire\", fields: [sourceQuestionnairePhaseId], references: [id])\n\n // Current approval stage pointer for UX and orchestration\n currentStageOrder Int @default(1)\n\n // Progress counters\n approvedDocumentsCount Int @default(0)\n requiredDocumentsCount Int @default(0)\n\n // Snapshots for audit\n documentDefinitionsSnapshot Json?\n approvalStagesSnapshot Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Approval stage progress (tracks which stages are completed)\n stageProgress ApprovalStageProgress[]\n\n @@index([tenantId])\n @@index([phaseId])\n @@index([sourceQuestionnairePhaseId])\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 // Optimistic locking for concurrent payment protection\n version Int @default(0)\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// 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 // Optimistic locking for concurrent payment protection\n version Int @default(0)\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 // Document info\n documentType String? // ID_CARD, BANK_STATEMENT, etc. (matches DocumentDefinition.documentType)\n documentName String? // Human-readable name (copied from DocumentDefinition.documentName)\n name String // File name\n url String\n type String // ID, BANK_STATEMENT, INCOME_PROOF, TITLE_DEED, SIGNATURE, etc. (legacy, use documentType)\n uploadedById String?\n uploadedBy User? @relation(\"DocumentUploader\", fields: [uploadedById], references: [id])\n\n // =========================================================================\n // UPLOADER VALIDATION - Enforces who can upload this document\n // =========================================================================\n // expectedUploader is set from DocumentDefinition.uploadedBy at phase creation\n // Allows validation that correct party is uploading (e.g., developer uploads sales offer)\n expectedUploader UploadedBy? // CUSTOMER, LENDER, DEVELOPER, LEGAL, PLATFORM, etc.\n // If expectedUploader is LENDER/DEVELOPER, track which org should upload\n expectedOrganizationId String?\n\n // =========================================================================\n // DOCUMENT EXPIRY - Time-sensitive document tracking\n // =========================================================================\n // Documents like bank statements have a shelf life. If application takes too long,\n // documents may need to be re-uploaded.\n // =========================================================================\n documentDate DateTime? // When the document was issued/created (e.g., bank statement date)\n expiresAt DateTime? // When this document expires (computed from documentDate + expiryDays)\n expiryDays Int? // Number of days this document type is valid (copied from DocumentDefinition)\n isExpired Boolean @default(false) // Denormalized flag, updated by cron job\n expiredAt DateTime? // When the document was marked expired\n expiryWarningAt DateTime? // When expiry warning was sent\n revalidatedAt DateTime? // If document was re-uploaded after expiry\n\n status DocumentStatus @default(PENDING)\n\n // NO versioning - document is replaced on re-upload (url is updated)\n // Keep these fields for backward compatibility but don't use for new code\n version Int @default(1)\n replacesDocumentId String? // If this is a revision, points to original\n replacesDocument ApplicationDocument? @relation(\"DocumentRevisions\", fields: [replacesDocumentId], references: [id])\n revisions ApplicationDocument[] @relation(\"DocumentRevisions\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // OLD: Multi-party reviews (deprecated, use approvalTrail)\n reviews DocumentReview[]\n\n // NEW: Full approval trail across all stages\n approvalTrail DocumentApproval[]\n\n @@index([tenantId])\n @@index([applicationId])\n @@index([phaseId])\n @@index([stepId])\n @@index([type])\n @@index([documentType])\n @@index([status])\n @@index([replacesDocumentId])\n @@index([isExpired])\n @@index([expiresAt])\n @@map(\"application_documents\")\n}\n\n// =============================================================================\n// DOCUMENT REVIEW - Multi-party review tracking\n// =============================================================================\n// Tracks reviews by different organizations for the same document.\n// organizationId is NULL for customer self-attestations/signatures.\n// For org reviews, organizationTypeId captures which type the org was acting as.\n// =============================================================================\n\nmodel DocumentReview {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n documentId String\n document ApplicationDocument @relation(fields: [documentId], references: [id], onDelete: Cascade)\n\n // Who is reviewing - NULL organizationId means customer self-review\n organizationId String? // Organization performing the review (null = customer)\n organization Organization? @relation(fields: [organizationId], references: [id])\n organizationTypeId String? // Which type the org was acting as (audit snapshot)\n organizationType OrganizationType? @relation(fields: [organizationTypeId], references: [id])\n reviewerId String? // User who performed the review\n reviewer User? @relation(\"DocumentReviewer\", fields: [reviewerId], references: [id])\n reviewerName String? // Denormalized for audit trail\n\n // Review state\n decision ReviewDecision @default(PENDING)\n comments String? @db.Text // General comments\n\n // Structured concerns for change requests\n // Format: [{ field: \"income_period\", issue: \"Missing months April-June\" }]\n concerns Json?\n\n // Review timing\n requestedAt DateTime @default(now())\n dueAt DateTime? // Optional deadline for this party\n reviewedAt DateTime? // When decision was made\n\n // Review sequence (which order should parties review?)\n reviewOrder Int @default(0) // 0 = parallel, 1/2/3 = sequential\n\n // For review chains (re-reviews after changes)\n parentReviewId String? // If this is a re-review after changes\n parentReview DocumentReview? @relation(\"ReviewChain\", fields: [parentReviewId], references: [id])\n childReviews DocumentReview[] @relation(\"ReviewChain\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Unique: one review per org per doc (null org = customer review)\n @@unique([documentId, organizationId])\n @@index([tenantId])\n @@index([documentId])\n @@index([organizationId])\n @@index([organizationTypeId])\n @@index([decision])\n @@index([reviewerId])\n @@index([parentReviewId])\n @@map(\"document_reviews\")\n}\n\n// =============================================================================\n// APPROVAL STAGE PROGRESS - Runtime tracking of stage completion per phase\n// =============================================================================\n// Tracks the progress of each approval stage within a documentation phase.\n// Created when a documentation phase is instantiated from a plan.\n// =============================================================================\n\nmodel ApprovalStageProgress {\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 // Link to template\n approvalStageId String\n approvalStage ApprovalStage @relation(fields: [approvalStageId], references: [id])\n\n // Stage info (denormalized for convenience)\n name String\n order Int\n organizationTypeId String // Which type of org should review at this stage\n organizationType OrganizationType @relation(fields: [organizationTypeId], references: [id])\n\n // Behavior flags (copied from template)\n autoTransition Boolean @default(false)\n waitForAllDocuments Boolean @default(true)\n allowEarlyVisibility Boolean @default(false)\n\n // Rejection behavior (copied from template)\n onRejection RejectionBehavior @default(CASCADE_BACK)\n restartFromStageOrder Int?\n\n // Status tracking\n status StageStatus @default(PENDING)\n activatedAt DateTime?\n completedAt DateTime?\n\n // Who completed this stage (when autoTransition = false)\n completedById String?\n completedBy User? @relation(\"StageCompletedBy\", fields: [completedById], references: [id])\n transitionComment String? @db.Text // Optional comment when completing stage\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Document approvals made during this stage\n documentApprovals DocumentApproval[]\n\n @@unique([documentationPhaseId, order])\n @@index([tenantId])\n @@index([documentationPhaseId])\n @@index([approvalStageId])\n @@index([status])\n @@map(\"approval_stage_progress\")\n}\n\n// =============================================================================\n// DOCUMENT APPROVAL - Audit trail for document reviews per stage\n// =============================================================================\n// Records every review action taken on a document within a specific stage.\n// Provides full audit trail: who reviewed, what decision, when, with comments.\n// =============================================================================\n\nmodel DocumentApproval {\n id String @id @default(cuid())\n tenantId String\n tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)\n documentId String\n document ApplicationDocument @relation(fields: [documentId], references: [id], onDelete: Cascade)\n\n // Which stage this approval belongs to\n stageProgressId String\n stageProgress ApprovalStageProgress @relation(fields: [stageProgressId], references: [id], onDelete: Cascade)\n\n // Reviewer info\n reviewerId String\n reviewer User @relation(\"DocumentApprovalReviewer\", fields: [reviewerId], references: [id])\n organizationTypeId String // Which type the reviewer's org was acting as\n organizationType OrganizationType @relation(fields: [organizationTypeId], references: [id])\n\n // Decision\n decision ReviewDecision // APPROVED, REJECTED, CHANGES_REQUESTED\n comment String? @db.Text // Required on rejection\n\n reviewedAt DateTime @default(now())\n createdAt DateTime @default(now())\n\n @@index([tenantId])\n @@index([documentId])\n @@index([stageProgressId])\n @@index([reviewerId])\n @@index([organizationTypeId])\n @@index([decision])\n @@map(\"document_approvals\")\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 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 /// 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// =============================================================================\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\n// =============================================================================\n// DOCUMENT EXPIRY JOB - Scheduled job tracking for document expiration checks\n// =============================================================================\n// Tracks scheduled jobs for checking document expiration across applications.\n// This supports a cron-based approach where a Lambda runs periodically to:\n// 1. Find documents nearing expiry (warning)\n// 2. Mark expired documents\n// 3. Notify customers to re-upload\n// 4. Optionally block phase progression if critical documents expired\n// =============================================================================\n\n/// Job status for scheduled background jobs\nenum ScheduledJobStatus {\n PENDING\n RUNNING\n COMPLETED\n FAILED\n CANCELLED\n}\n\n/// Type of scheduled job\nenum ScheduledJobType {\n DOCUMENT_EXPIRY_CHECK // Check for expired documents\n SLA_BREACH_CHECK // Check for SLA breaches\n PAYMENT_REMINDER // Send payment reminders\n DOCUMENT_EXPIRY_WARNING // Warn about documents nearing expiry\n}\n\n/// Scheduled Job - Tracks execution of background jobs\nmodel ScheduledJob {\n id String @id @default(cuid())\n tenantId String? // NULL = system-wide job, set = tenant-specific\n\n jobType ScheduledJobType\n status ScheduledJobStatus @default(PENDING)\n\n // Scheduling\n scheduledAt DateTime // When the job should run\n startedAt DateTime? // When job started executing\n completedAt DateTime? // When job finished\n durationMs Int? // Execution time\n\n // Job parameters\n parameters Json? // Job-specific configuration\n\n // Results\n itemsProcessed Int @default(0)\n itemsAffected Int @default(0) // Documents expired, SLAs breached, etc.\n errorCount Int @default(0)\n errors Json? // Array of error details\n summary String? @db.Text // Human-readable summary\n\n // Retry handling\n attemptNumber Int @default(1)\n maxAttempts Int @default(3)\n nextRetryAt DateTime?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([tenantId])\n @@index([jobType])\n @@index([status])\n @@index([scheduledAt])\n @@index([jobType, status, scheduledAt])\n @@map(\"scheduled_jobs\")\n}\n\n/// Document Expiry Warning - Track warnings sent for expiring documents\nmodel DocumentExpiryWarning {\n id String @id @default(cuid())\n tenantId String\n documentId String\n\n // Warning details\n expiresAt DateTime // When document will expire\n daysUntil Int // Days until expiry at time of warning\n warningSent DateTime @default(now())\n\n // Customer notification tracking\n notificationSent Boolean @default(false)\n notificationId String? // Reference to notification service\n\n // Resolution tracking\n resolved Boolean @default(false)\n resolvedAt DateTime?\n resolvedBy String? // User who resolved (re-uploaded document)\n newDocumentId String? // ID of the replacement document\n\n createdAt DateTime @default(now())\n\n @@unique([documentId, daysUntil]) // One warning per document per threshold\n @@index([tenantId])\n @@index([documentId])\n @@index([expiresAt])\n @@index([resolved])\n @@map(\"document_expiry_warnings\")\n}\n",
19
19
  "runtimeDataModel": {
20
20
  "models": {},
21
21
  "enums": {},
22
22
  "types": {}
23
23
  }
24
24
  };
25
- config.runtimeDataModel = JSON.parse("{\"models\":{\"OrganizationType\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"OrganizationTypeToTenant\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isSystemType\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"organizations\",\"kind\":\"object\",\"type\":\"OrganizationTypeAssignment\",\"relationName\":\"OrganizationTypeToOrganizationTypeAssignment\"},{\"name\":\"applicationOrganizations\",\"kind\":\"object\",\"type\":\"ApplicationOrganization\",\"relationName\":\"ApplicationOrganizationToOrganizationType\"},{\"name\":\"approvalStages\",\"kind\":\"object\",\"type\":\"ApprovalStage\",\"relationName\":\"ApprovalStageToOrganizationType\"},{\"name\":\"documentReviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"DocumentReviewToOrganizationType\"},{\"name\":\"approvalStageProgress\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"ApprovalStageProgressToOrganizationType\"},{\"name\":\"documentApprovals\",\"kind\":\"object\",\"type\":\"DocumentApproval\",\"relationName\":\"DocumentApprovalToOrganizationType\"}],\"dbName\":\"organization_types\"},\"OrganizationTypeAssignment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToOrganizationTypeAssignment\"},{\"name\":\"typeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"orgType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"OrganizationTypeToOrganizationTypeAssignment\"},{\"name\":\"isPrimary\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"organization_type_assignments\"},\"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\":\"uploadedDocs\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"DocumentUploader\"},{\"name\":\"documentApprovals\",\"kind\":\"object\",\"type\":\"DocumentApproval\",\"relationName\":\"DocumentApprovalReviewer\"},{\"name\":\"completedStages\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"StageCompletedBy\"},{\"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\"},{\"name\":\"documentReviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"DocumentReviewer\"},{\"name\":\"questionnaireReviews\",\"kind\":\"object\",\"type\":\"QuestionnairePhaseReview\",\"relationName\":\"QuestionnaireReviewer\"},{\"name\":\"organizationMemberships\",\"kind\":\"object\",\"type\":\"OrganizationMember\",\"relationName\":\"OrganizationMemberToUser\"}],\"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\"},\"Organization\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"OrganizationStatus\"},{\"name\":\"types\",\"kind\":\"object\",\"type\":\"OrganizationTypeAssignment\",\"relationName\":\"OrganizationToOrganizationTypeAssignment\"},{\"name\":\"isPlatformOrg\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phone\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"address\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"city\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"state\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"country\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"website\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"logoUrl\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"bankCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"bankLicenseNo\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"swiftCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sortCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"cacNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"cacCertificateUrl\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"taxId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"approvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"approvedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"OrganizationToTenant\"},{\"name\":\"members\",\"kind\":\"object\",\"type\":\"OrganizationMember\",\"relationName\":\"OrganizationToOrganizationMember\"},{\"name\":\"applicationAssignments\",\"kind\":\"object\",\"type\":\"ApplicationOrganization\",\"relationName\":\"ApplicationOrganizationToOrganization\"},{\"name\":\"documentRequirements\",\"kind\":\"object\",\"type\":\"BankDocumentRequirement\",\"relationName\":\"BankDocumentRequirementToOrganization\"},{\"name\":\"documentReviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"DocumentReviewToOrganization\"}],\"dbName\":\"organizations\"},\"OrganizationMember\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"department\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"employeeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"invitedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"acceptedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"invitedBy\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"joinedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToOrganizationMember\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrganizationMemberToUser\"}],\"dbName\":\"organization_members\"},\"BankDocumentRequirement\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"BankDocumentRequirementToTenant\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"BankDocumentRequirementToOrganization\"},{\"name\":\"phaseType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"BankDocumentRequirementToPropertyPaymentMethod\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modifier\",\"kind\":\"enum\",\"type\":\"BankDocumentModifier\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiryDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"minFiles\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxFiles\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"allowedMimeTypes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"validationRules\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"priority\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"bank_document_requirements\"},\"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\":\"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\":\"paymentInstallments\",\"kind\":\"object\",\"type\":\"PaymentInstallment\",\"relationName\":\"PaymentInstallmentToTenant\"},{\"name\":\"applicationPayments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationPaymentToTenant\"},{\"name\":\"applicationDocuments\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"ApplicationDocumentToTenant\"},{\"name\":\"documentApprovals\",\"kind\":\"object\",\"type\":\"DocumentApproval\",\"relationName\":\"DocumentApprovalToTenant\"},{\"name\":\"approvalStageProgress\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"ApprovalStageProgressToTenant\"},{\"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\":\"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\"},{\"name\":\"questionnairePhaseReviews\",\"kind\":\"object\",\"type\":\"QuestionnairePhaseReview\",\"relationName\":\"QuestionnairePhaseReviewToTenant\"},{\"name\":\"documentReviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"DocumentReviewToTenant\"},{\"name\":\"bankDocumentRequirements\",\"kind\":\"object\",\"type\":\"BankDocumentRequirement\",\"relationName\":\"BankDocumentRequirementToTenant\"},{\"name\":\"organizations\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToTenant\"},{\"name\":\"applicationOrganizations\",\"kind\":\"object\",\"type\":\"ApplicationOrganization\",\"relationName\":\"ApplicationOrganizationToTenant\"},{\"name\":\"organizationTypes\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"OrganizationTypeToTenant\"}],\"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\":\"enum\",\"type\":\"PropertyStatus\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayImageId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayImage\",\"kind\":\"object\",\"type\":\"PropertyMedia\",\"relationName\":\"DisplayImage\"},{\"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\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"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\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"documentDefinitions\",\"kind\":\"object\",\"type\":\"DocumentDefinition\",\"relationName\":\"DocumentDefinitionToDocumentationPlan\"},{\"name\":\"approvalStages\",\"kind\":\"object\",\"type\":\"ApprovalStage\",\"relationName\":\"ApprovalStageToDocumentationPlan\"},{\"name\":\"methodPhases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"DocumentationPlanToPropertyPaymentMethodPhase\"},{\"name\":\"documentationPhases\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"DocumentationPhaseToDocumentationPlan\"}],\"dbName\":\"documentation_plans\"},\"DocumentDefinition\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"planId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"plan\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"DocumentDefinitionToDocumentationPlan\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"uploadedBy\",\"kind\":\"enum\",\"type\":\"UploadedBy\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"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\":\"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\":\"document_definitions\"},\"ApprovalStage\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"planId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"plan\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"ApprovalStageToDocumentationPlan\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"organizationTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"ApprovalStageToOrganizationType\"},{\"name\":\"autoTransition\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"waitForAllDocuments\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"allowEarlyVisibility\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"onRejection\",\"kind\":\"enum\",\"type\":\"RejectionBehavior\"},{\"name\":\"restartFromStageOrder\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"slaHours\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"stageProgress\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"ApprovalStageToApprovalStageProgress\"}],\"dbName\":\"approval_stages\"},\"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\":\"enum\",\"type\":\"QuestionCategory\"},{\"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\"},{\"name\":\"bankDocumentRequirements\",\"kind\":\"object\",\"type\":\"BankDocumentRequirement\",\"relationName\":\"BankDocumentRequirementToPropertyPaymentMethod\"}],\"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\":\"paymentMethodSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"paymentMethodSnapshotAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"paymentMethodSnapshotHash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"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\"},{\"name\":\"organizations\",\"kind\":\"object\",\"type\":\"ApplicationOrganization\",\"relationName\":\"ApplicationToApplicationOrganization\"}],\"dbName\":\"applications\"},\"ApplicationOrganization\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationOrganizationToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationOrganization\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"ApplicationOrganizationToOrganization\"},{\"name\":\"assignedAsTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"assignedAsType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"ApplicationOrganizationToOrganizationType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ApplicationOrganizationStatus\"},{\"name\":\"assignedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"assignedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"isPrimary\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"offeredTerms\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"termsOfferedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"termsAcceptedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"termsDeclinedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"declineReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"activatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"withdrawnAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"slaHours\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"slaStartedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"slaBreachedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"slaBreachNotified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"reminderCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"lastReminderSentAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"nextReminderAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"escalatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"escalatedToUserId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"escalationNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_organizations\"},\"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\"},{\"name\":\"reviews\",\"kind\":\"object\",\"type\":\"QuestionnairePhaseReview\",\"relationName\":\"QuestionnairePhaseToQuestionnairePhaseReview\"},{\"name\":\"dependentDocumentationPhases\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"SourceQuestionnaire\"}],\"dbName\":\"questionnaire_phases\"},\"QuestionnairePhaseReview\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"QuestionnairePhaseReviewToTenant\"},{\"name\":\"questionnairePhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePhase\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"QuestionnairePhaseToQuestionnairePhaseReview\"},{\"name\":\"reviewerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"QuestionnaireReviewer\"},{\"name\":\"decision\",\"kind\":\"enum\",\"type\":\"ReviewDecision\"},{\"name\":\"notes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scoreAtReview\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"passedAtReview\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"questionnaire_phase_reviews\"},\"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\":\"sourceQuestionnairePhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sourceQuestionnairePhase\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"SourceQuestionnaire\"},{\"name\":\"currentStageOrder\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"approvedDocumentsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"requiredDocumentsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"documentDefinitionsSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"approvalStagesSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"stageProgress\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"ApprovalStageProgressToDocumentationPhase\"}],\"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\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"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\"},\"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\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"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\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentName\",\"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\":\"expectedUploader\",\"kind\":\"enum\",\"type\":\"UploadedBy\"},{\"name\":\"expectedOrganizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiryDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"isExpired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"expiredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiryWarningAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"revalidatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"DocumentStatus\"},{\"name\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"replacesDocumentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"replacesDocument\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"DocumentRevisions\"},{\"name\":\"revisions\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"DocumentRevisions\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"ApplicationDocumentToDocumentReview\"},{\"name\":\"approvalTrail\",\"kind\":\"object\",\"type\":\"DocumentApproval\",\"relationName\":\"ApplicationDocumentToDocumentApproval\"}],\"dbName\":\"application_documents\"},\"DocumentReview\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentReviewToTenant\"},{\"name\":\"documentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"document\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"ApplicationDocumentToDocumentReview\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"DocumentReviewToOrganization\"},{\"name\":\"organizationTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"DocumentReviewToOrganizationType\"},{\"name\":\"reviewerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DocumentReviewer\"},{\"name\":\"reviewerName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"decision\",\"kind\":\"enum\",\"type\":\"ReviewDecision\"},{\"name\":\"comments\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"concerns\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"requestedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"dueAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviewOrder\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parentReviewId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"parentReview\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"ReviewChain\"},{\"name\":\"childReviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"ReviewChain\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"document_reviews\"},\"ApprovalStageProgress\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApprovalStageProgressToTenant\"},{\"name\":\"documentationPhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentationPhase\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"ApprovalStageProgressToDocumentationPhase\"},{\"name\":\"approvalStageId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"approvalStage\",\"kind\":\"object\",\"type\":\"ApprovalStage\",\"relationName\":\"ApprovalStageToApprovalStageProgress\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"organizationTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"ApprovalStageProgressToOrganizationType\"},{\"name\":\"autoTransition\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"waitForAllDocuments\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"allowEarlyVisibility\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"onRejection\",\"kind\":\"enum\",\"type\":\"RejectionBehavior\"},{\"name\":\"restartFromStageOrder\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"StageStatus\"},{\"name\":\"activatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"completedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"StageCompletedBy\"},{\"name\":\"transitionComment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"documentApprovals\",\"kind\":\"object\",\"type\":\"DocumentApproval\",\"relationName\":\"ApprovalStageProgressToDocumentApproval\"}],\"dbName\":\"approval_stage_progress\"},\"DocumentApproval\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentApprovalToTenant\"},{\"name\":\"documentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"document\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"ApplicationDocumentToDocumentApproval\"},{\"name\":\"stageProgressId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stageProgress\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"ApprovalStageProgressToDocumentApproval\"},{\"name\":\"reviewerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DocumentApprovalReviewer\"},{\"name\":\"organizationTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"DocumentApprovalToOrganizationType\"},{\"name\":\"decision\",\"kind\":\"enum\",\"type\":\"ReviewDecision\"},{\"name\":\"comment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"document_approvals\"},\"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\":\"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\":\"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\"},\"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\"},\"ScheduledJob\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"jobType\",\"kind\":\"enum\",\"type\":\"ScheduledJobType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ScheduledJobStatus\"},{\"name\":\"scheduledAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"startedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"durationMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parameters\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"itemsProcessed\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"itemsAffected\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"errorCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"errors\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"summary\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"attemptNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxAttempts\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"nextRetryAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"scheduled_jobs\"},\"DocumentExpiryWarning\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"daysUntil\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"warningSent\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"notificationSent\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"notificationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resolved\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"resolvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"resolvedBy\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"newDocumentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"document_expiry_warnings\"}},\"enums\":{},\"types\":{}}");
25
+ config.runtimeDataModel = JSON.parse("{\"models\":{\"OrganizationType\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"OrganizationTypeToTenant\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isSystemType\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"organizations\",\"kind\":\"object\",\"type\":\"OrganizationTypeAssignment\",\"relationName\":\"OrganizationTypeToOrganizationTypeAssignment\"},{\"name\":\"applicationOrganizations\",\"kind\":\"object\",\"type\":\"ApplicationOrganization\",\"relationName\":\"ApplicationOrganizationToOrganizationType\"},{\"name\":\"approvalStages\",\"kind\":\"object\",\"type\":\"ApprovalStage\",\"relationName\":\"ApprovalStageToOrganizationType\"},{\"name\":\"documentReviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"DocumentReviewToOrganizationType\"},{\"name\":\"approvalStageProgress\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"ApprovalStageProgressToOrganizationType\"},{\"name\":\"documentApprovals\",\"kind\":\"object\",\"type\":\"DocumentApproval\",\"relationName\":\"DocumentApprovalToOrganizationType\"}],\"dbName\":\"organization_types\"},\"OrganizationTypeAssignment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToOrganizationTypeAssignment\"},{\"name\":\"typeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"orgType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"OrganizationTypeToOrganizationTypeAssignment\"},{\"name\":\"isPrimary\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"organization_type_assignments\"},\"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\":\"uploadedDocs\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"DocumentUploader\"},{\"name\":\"documentApprovals\",\"kind\":\"object\",\"type\":\"DocumentApproval\",\"relationName\":\"DocumentApprovalReviewer\"},{\"name\":\"completedStages\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"StageCompletedBy\"},{\"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\"},{\"name\":\"documentReviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"DocumentReviewer\"},{\"name\":\"questionnaireReviews\",\"kind\":\"object\",\"type\":\"QuestionnairePhaseReview\",\"relationName\":\"QuestionnaireReviewer\"},{\"name\":\"organizationMemberships\",\"kind\":\"object\",\"type\":\"OrganizationMember\",\"relationName\":\"OrganizationMemberToUser\"}],\"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\"},\"Organization\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"OrganizationStatus\"},{\"name\":\"types\",\"kind\":\"object\",\"type\":\"OrganizationTypeAssignment\",\"relationName\":\"OrganizationToOrganizationTypeAssignment\"},{\"name\":\"isPlatformOrg\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phone\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"address\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"city\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"state\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"country\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"website\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"logoUrl\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"bankCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"bankLicenseNo\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"swiftCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sortCode\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"cacNumber\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"cacCertificateUrl\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"taxId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"approvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"approvedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"OrganizationToTenant\"},{\"name\":\"members\",\"kind\":\"object\",\"type\":\"OrganizationMember\",\"relationName\":\"OrganizationToOrganizationMember\"},{\"name\":\"applicationAssignments\",\"kind\":\"object\",\"type\":\"ApplicationOrganization\",\"relationName\":\"ApplicationOrganizationToOrganization\"},{\"name\":\"documentRequirements\",\"kind\":\"object\",\"type\":\"BankDocumentRequirement\",\"relationName\":\"BankDocumentRequirementToOrganization\"},{\"name\":\"documentReviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"DocumentReviewToOrganization\"},{\"name\":\"properties\",\"kind\":\"object\",\"type\":\"Property\",\"relationName\":\"OrganizationToProperty\"}],\"dbName\":\"organizations\"},\"OrganizationMember\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"department\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"employeeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"invitedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"acceptedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"invitedBy\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"joinedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToOrganizationMember\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrganizationMemberToUser\"}],\"dbName\":\"organization_members\"},\"BankDocumentRequirement\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"BankDocumentRequirementToTenant\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"BankDocumentRequirementToOrganization\"},{\"name\":\"phaseType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethodId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"paymentMethod\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethod\",\"relationName\":\"BankDocumentRequirementToPropertyPaymentMethod\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modifier\",\"kind\":\"enum\",\"type\":\"BankDocumentModifier\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiryDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"minFiles\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxFiles\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"allowedMimeTypes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"validationRules\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"priority\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"bank_document_requirements\"},\"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\":\"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\":\"paymentInstallments\",\"kind\":\"object\",\"type\":\"PaymentInstallment\",\"relationName\":\"PaymentInstallmentToTenant\"},{\"name\":\"applicationPayments\",\"kind\":\"object\",\"type\":\"ApplicationPayment\",\"relationName\":\"ApplicationPaymentToTenant\"},{\"name\":\"applicationDocuments\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"ApplicationDocumentToTenant\"},{\"name\":\"documentApprovals\",\"kind\":\"object\",\"type\":\"DocumentApproval\",\"relationName\":\"DocumentApprovalToTenant\"},{\"name\":\"approvalStageProgress\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"ApprovalStageProgressToTenant\"},{\"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\":\"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\"},{\"name\":\"questionnairePhaseReviews\",\"kind\":\"object\",\"type\":\"QuestionnairePhaseReview\",\"relationName\":\"QuestionnairePhaseReviewToTenant\"},{\"name\":\"documentReviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"DocumentReviewToTenant\"},{\"name\":\"bankDocumentRequirements\",\"kind\":\"object\",\"type\":\"BankDocumentRequirement\",\"relationName\":\"BankDocumentRequirementToTenant\"},{\"name\":\"organizations\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToTenant\"},{\"name\":\"applicationOrganizations\",\"kind\":\"object\",\"type\":\"ApplicationOrganization\",\"relationName\":\"ApplicationOrganizationToTenant\"},{\"name\":\"organizationTypes\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"OrganizationTypeToTenant\"}],\"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\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToProperty\"},{\"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\":\"enum\",\"type\":\"PropertyStatus\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayImageId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayImage\",\"kind\":\"object\",\"type\":\"PropertyMedia\",\"relationName\":\"DisplayImage\"},{\"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\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"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\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"documentDefinitions\",\"kind\":\"object\",\"type\":\"DocumentDefinition\",\"relationName\":\"DocumentDefinitionToDocumentationPlan\"},{\"name\":\"approvalStages\",\"kind\":\"object\",\"type\":\"ApprovalStage\",\"relationName\":\"ApprovalStageToDocumentationPlan\"},{\"name\":\"methodPhases\",\"kind\":\"object\",\"type\":\"PropertyPaymentMethodPhase\",\"relationName\":\"DocumentationPlanToPropertyPaymentMethodPhase\"},{\"name\":\"documentationPhases\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"DocumentationPhaseToDocumentationPlan\"}],\"dbName\":\"documentation_plans\"},\"DocumentDefinition\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"planId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"plan\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"DocumentDefinitionToDocumentationPlan\"},{\"name\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"uploadedBy\",\"kind\":\"enum\",\"type\":\"UploadedBy\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"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\":\"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\":\"document_definitions\"},\"ApprovalStage\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"planId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"plan\",\"kind\":\"object\",\"type\":\"DocumentationPlan\",\"relationName\":\"ApprovalStageToDocumentationPlan\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"organizationTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"ApprovalStageToOrganizationType\"},{\"name\":\"autoTransition\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"waitForAllDocuments\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"allowEarlyVisibility\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"onRejection\",\"kind\":\"enum\",\"type\":\"RejectionBehavior\"},{\"name\":\"restartFromStageOrder\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"slaHours\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"stageProgress\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"ApprovalStageToApprovalStageProgress\"}],\"dbName\":\"approval_stages\"},\"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\":\"enum\",\"type\":\"QuestionCategory\"},{\"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\"},{\"name\":\"bankDocumentRequirements\",\"kind\":\"object\",\"type\":\"BankDocumentRequirement\",\"relationName\":\"BankDocumentRequirementToPropertyPaymentMethod\"}],\"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\":\"paymentMethodSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"paymentMethodSnapshotAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"paymentMethodSnapshotHash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"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\"},{\"name\":\"organizations\",\"kind\":\"object\",\"type\":\"ApplicationOrganization\",\"relationName\":\"ApplicationToApplicationOrganization\"}],\"dbName\":\"applications\"},\"ApplicationOrganization\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApplicationOrganizationToTenant\"},{\"name\":\"applicationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"application\",\"kind\":\"object\",\"type\":\"Application\",\"relationName\":\"ApplicationToApplicationOrganization\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"ApplicationOrganizationToOrganization\"},{\"name\":\"assignedAsTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"assignedAsType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"ApplicationOrganizationToOrganizationType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ApplicationOrganizationStatus\"},{\"name\":\"assignedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"assignedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"isPrimary\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"offeredTerms\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"termsOfferedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"termsAcceptedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"termsDeclinedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"declineReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"activatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"withdrawnAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"slaHours\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"slaStartedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"slaBreachedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"slaBreachNotified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"reminderCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"lastReminderSentAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"nextReminderAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"escalatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"escalatedToUserId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"escalationNotes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"application_organizations\"},\"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\"},{\"name\":\"reviews\",\"kind\":\"object\",\"type\":\"QuestionnairePhaseReview\",\"relationName\":\"QuestionnairePhaseToQuestionnairePhaseReview\"},{\"name\":\"dependentDocumentationPhases\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"SourceQuestionnaire\"}],\"dbName\":\"questionnaire_phases\"},\"QuestionnairePhaseReview\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"QuestionnairePhaseReviewToTenant\"},{\"name\":\"questionnairePhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"questionnairePhase\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"QuestionnairePhaseToQuestionnairePhaseReview\"},{\"name\":\"reviewerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"QuestionnaireReviewer\"},{\"name\":\"decision\",\"kind\":\"enum\",\"type\":\"ReviewDecision\"},{\"name\":\"notes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scoreAtReview\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"passedAtReview\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"questionnaire_phase_reviews\"},\"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\":\"sourceQuestionnairePhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sourceQuestionnairePhase\",\"kind\":\"object\",\"type\":\"QuestionnairePhase\",\"relationName\":\"SourceQuestionnaire\"},{\"name\":\"currentStageOrder\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"approvedDocumentsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"requiredDocumentsCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"documentDefinitionsSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"approvalStagesSnapshot\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"stageProgress\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"ApprovalStageProgressToDocumentationPhase\"}],\"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\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"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\"},\"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\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"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\":\"documentType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentName\",\"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\":\"expectedUploader\",\"kind\":\"enum\",\"type\":\"UploadedBy\"},{\"name\":\"expectedOrganizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentDate\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiryDays\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"isExpired\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"expiredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiryWarningAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"revalidatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"DocumentStatus\"},{\"name\":\"version\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"replacesDocumentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"replacesDocument\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"DocumentRevisions\"},{\"name\":\"revisions\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"DocumentRevisions\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"ApplicationDocumentToDocumentReview\"},{\"name\":\"approvalTrail\",\"kind\":\"object\",\"type\":\"DocumentApproval\",\"relationName\":\"ApplicationDocumentToDocumentApproval\"}],\"dbName\":\"application_documents\"},\"DocumentReview\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentReviewToTenant\"},{\"name\":\"documentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"document\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"ApplicationDocumentToDocumentReview\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"DocumentReviewToOrganization\"},{\"name\":\"organizationTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"DocumentReviewToOrganizationType\"},{\"name\":\"reviewerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DocumentReviewer\"},{\"name\":\"reviewerName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"decision\",\"kind\":\"enum\",\"type\":\"ReviewDecision\"},{\"name\":\"comments\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"concerns\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"requestedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"dueAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"reviewOrder\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parentReviewId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"parentReview\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"ReviewChain\"},{\"name\":\"childReviews\",\"kind\":\"object\",\"type\":\"DocumentReview\",\"relationName\":\"ReviewChain\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"document_reviews\"},\"ApprovalStageProgress\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"ApprovalStageProgressToTenant\"},{\"name\":\"documentationPhaseId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentationPhase\",\"kind\":\"object\",\"type\":\"DocumentationPhase\",\"relationName\":\"ApprovalStageProgressToDocumentationPhase\"},{\"name\":\"approvalStageId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"approvalStage\",\"kind\":\"object\",\"type\":\"ApprovalStage\",\"relationName\":\"ApprovalStageToApprovalStageProgress\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"order\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"organizationTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"ApprovalStageProgressToOrganizationType\"},{\"name\":\"autoTransition\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"waitForAllDocuments\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"allowEarlyVisibility\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"onRejection\",\"kind\":\"enum\",\"type\":\"RejectionBehavior\"},{\"name\":\"restartFromStageOrder\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"StageStatus\"},{\"name\":\"activatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"completedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"StageCompletedBy\"},{\"name\":\"transitionComment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"documentApprovals\",\"kind\":\"object\",\"type\":\"DocumentApproval\",\"relationName\":\"ApprovalStageProgressToDocumentApproval\"}],\"dbName\":\"approval_stage_progress\"},\"DocumentApproval\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenant\",\"kind\":\"object\",\"type\":\"Tenant\",\"relationName\":\"DocumentApprovalToTenant\"},{\"name\":\"documentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"document\",\"kind\":\"object\",\"type\":\"ApplicationDocument\",\"relationName\":\"ApplicationDocumentToDocumentApproval\"},{\"name\":\"stageProgressId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stageProgress\",\"kind\":\"object\",\"type\":\"ApprovalStageProgress\",\"relationName\":\"ApprovalStageProgressToDocumentApproval\"},{\"name\":\"reviewerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewer\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"DocumentApprovalReviewer\"},{\"name\":\"organizationTypeId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationType\",\"kind\":\"object\",\"type\":\"OrganizationType\",\"relationName\":\"DocumentApprovalToOrganizationType\"},{\"name\":\"decision\",\"kind\":\"enum\",\"type\":\"ReviewDecision\"},{\"name\":\"comment\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reviewedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"document_approvals\"},\"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\":\"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\":\"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\"},\"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\"},\"ScheduledJob\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"jobType\",\"kind\":\"enum\",\"type\":\"ScheduledJobType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"ScheduledJobStatus\"},{\"name\":\"scheduledAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"startedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"durationMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parameters\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"itemsProcessed\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"itemsAffected\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"errorCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"errors\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"summary\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"attemptNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxAttempts\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"nextRetryAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"scheduled_jobs\"},\"DocumentExpiryWarning\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tenantId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"documentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"daysUntil\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"warningSent\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"notificationSent\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"notificationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resolved\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"resolvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"resolvedBy\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"newDocumentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":\"document_expiry_warnings\"}},\"enums\":{},\"types\":{}}");
26
26
  async function decodeBase64AsWasm(wasmBase64) {
27
27
  const { Buffer } = await import('node:buffer');
28
28
  const wasmArray = Buffer.from(wasmBase64, 'base64');