fix billing and 2fa admin
Build & Push / Pipeline Tests (push) Failing after 1m58s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 58s
Test / API Unit Tests (push) Successful in 1m9s
Test / Homepage Unit Tests (push) Successful in 46s
Test / Carplace Unit Tests (push) Successful in 43s
Test / Admin Unit Tests (push) Successful in 41s
Test / Dashboard Unit Tests (push) Successful in 45s
Test / API Integration Tests (push) Failing after 1m9s
Build & Push / Pipeline Tests (push) Failing after 1m58s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 58s
Test / API Unit Tests (push) Successful in 1m9s
Test / Homepage Unit Tests (push) Successful in 46s
Test / Carplace Unit Tests (push) Successful in 43s
Test / Admin Unit Tests (push) Successful in 41s
Test / Dashboard Unit Tests (push) Successful in 45s
Test / API Integration Tests (push) Failing after 1m9s
This commit is contained in:
@@ -134,6 +134,81 @@ enum BillingPaymentAttemptStatus {
|
||||
PARTIALLY_REFUNDED
|
||||
}
|
||||
|
||||
enum SubscriptionCollectionMethod {
|
||||
STRIPE
|
||||
BANK_TRANSFER
|
||||
CHECK
|
||||
}
|
||||
|
||||
enum BillingPaymentChannel {
|
||||
ONLINE
|
||||
OFFLINE
|
||||
}
|
||||
|
||||
enum ManualPaymentMethod {
|
||||
BANK_TRANSFER
|
||||
CHECK
|
||||
}
|
||||
|
||||
enum ManualPaymentSubmissionStatus {
|
||||
DRAFT
|
||||
SUBMITTED
|
||||
UNDER_REVIEW
|
||||
APPROVED
|
||||
REJECTED
|
||||
}
|
||||
|
||||
enum ManualPaymentDocumentKind {
|
||||
BANK_TRANSFER_RECEIPT
|
||||
CHECK_COPY
|
||||
OTHER_SUPPORTING_EVIDENCE
|
||||
}
|
||||
|
||||
enum ManualPaymentDocumentScanStatus {
|
||||
UPLOADED
|
||||
SCANNING
|
||||
CLEAN
|
||||
QUARANTINED
|
||||
SCAN_FAILED
|
||||
}
|
||||
|
||||
enum CollectionsCaseStatus {
|
||||
SCHEDULED
|
||||
PRE_DUE
|
||||
GRACE_PERIOD
|
||||
RESOLVED
|
||||
SUSPENDED
|
||||
}
|
||||
|
||||
enum CollectionsCallTaskType {
|
||||
PRE_EXPIRY_48H_CALL
|
||||
PAYMENT_PROMISE_FOLLOW_UP
|
||||
}
|
||||
|
||||
enum CollectionsCallTaskStatus {
|
||||
OPEN
|
||||
COMPLETED
|
||||
CANCELLED
|
||||
}
|
||||
|
||||
enum CollectionsCallOutcome {
|
||||
CONTACTED
|
||||
NO_ANSWER
|
||||
PAYMENT_PROMISED
|
||||
ISSUE_ESCALATED
|
||||
}
|
||||
|
||||
enum CollectionsOverrideType {
|
||||
PAYMENT_DISPUTE
|
||||
MANUAL_EXTENSION
|
||||
}
|
||||
|
||||
enum CollectionsOverrideStatus {
|
||||
ACTIVE
|
||||
REVOKED
|
||||
EXPIRED
|
||||
}
|
||||
|
||||
enum BillingRefundStatus {
|
||||
PENDING
|
||||
SUCCEEDED
|
||||
@@ -441,6 +516,17 @@ enum NotificationType {
|
||||
REFUND_PROCESSED
|
||||
NEW_OFFER_FROM_SAVED_COMPANY
|
||||
REVIEW_REQUEST
|
||||
SUBSCRIPTION_PAYMENT_DUE_14D
|
||||
SUBSCRIPTION_PAYMENT_DUE_7D
|
||||
SUBSCRIPTION_PAYMENT_DUE_48H
|
||||
SUBSCRIPTION_PAYMENT_DUE_24H
|
||||
SUBSCRIPTION_GRACE_DAILY
|
||||
SUBSCRIPTION_GRACE_FINAL
|
||||
COLLECTIONS_CALL_REQUIRED
|
||||
MANUAL_PAYMENT_EVIDENCE_SUBMITTED
|
||||
SUBSCRIPTION_PAYMENT_CONFIRMED
|
||||
MANUAL_PAYMENT_EVIDENCE_REJECTED
|
||||
COLLECTIONS_OVERRIDE_CHANGED
|
||||
}
|
||||
|
||||
enum FeedbackCategory {
|
||||
@@ -492,6 +578,8 @@ enum NotificationStatus {
|
||||
enum NotificationRecipientType {
|
||||
EMPLOYEE
|
||||
RENTER
|
||||
BILLING_CONTACT
|
||||
ADMIN
|
||||
}
|
||||
|
||||
enum NotificationDeliveryStatus {
|
||||
@@ -529,27 +617,32 @@ model Company {
|
||||
status CompanyStatus @default(PENDING)
|
||||
subscriptionPaymentRef String?
|
||||
|
||||
subscription Subscription?
|
||||
billingAccounts BillingAccount[]
|
||||
billingInvoices BillingInvoice[]
|
||||
brand BrandSettings?
|
||||
employees Employee[]
|
||||
vehicles Vehicle[]
|
||||
offers Offer[]
|
||||
reservations Reservation[]
|
||||
customers Customer[]
|
||||
rentalPayments RentalPayment[]
|
||||
subscriptionInvoices SubscriptionInvoice[]
|
||||
contractSettings ContractSettings?
|
||||
accountingSettings AccountingSettings?
|
||||
insurancePolicies InsurancePolicy[]
|
||||
pricingRules PricingRule[]
|
||||
notifications Notification[] @relation("CompanyNotifications")
|
||||
notificationEvents NotificationEvent[]
|
||||
notificationDefaults CompanyNotificationPreference[]
|
||||
complaints Complaint[]
|
||||
companyMenuItems CompanyMenuItem[]
|
||||
apiKeys CompanyApiKey[]
|
||||
subscription Subscription?
|
||||
billingAccounts BillingAccount[]
|
||||
billingInvoices BillingInvoice[]
|
||||
brand BrandSettings?
|
||||
employees Employee[]
|
||||
vehicles Vehicle[]
|
||||
offers Offer[]
|
||||
reservations Reservation[]
|
||||
customers Customer[]
|
||||
rentalPayments RentalPayment[]
|
||||
subscriptionInvoices SubscriptionInvoice[]
|
||||
contractSettings ContractSettings?
|
||||
accountingSettings AccountingSettings?
|
||||
insurancePolicies InsurancePolicy[]
|
||||
pricingRules PricingRule[]
|
||||
notifications Notification[] @relation("CompanyNotifications")
|
||||
notificationEvents NotificationEvent[]
|
||||
notificationDefaults CompanyNotificationPreference[]
|
||||
billingContacts BillingContact[]
|
||||
manualPaymentSubmissions ManualPaymentSubmission[]
|
||||
manualPaymentDocuments ManualPaymentDocument[]
|
||||
collectionsCases CollectionsCase[]
|
||||
collectionsEvents CollectionsEvent[]
|
||||
complaints Complaint[]
|
||||
companyMenuItems CompanyMenuItem[]
|
||||
apiKeys CompanyApiKey[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -597,6 +690,7 @@ model Subscription {
|
||||
maxRetryCount Int @default(5)
|
||||
invoices SubscriptionInvoice[]
|
||||
billingInvoices BillingInvoice[]
|
||||
collectionsCases CollectionsCase[]
|
||||
events SubscriptionEvent[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
@@ -623,28 +717,28 @@ model SubscriptionEvent {
|
||||
}
|
||||
|
||||
model SubscriptionInvoice {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
subscriptionId String
|
||||
subscription Subscription @relation(fields: [subscriptionId], references: [id])
|
||||
requestedPlan Plan?
|
||||
requestedBillingPeriod BillingPeriod?
|
||||
providerInvoiceId String?
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
status InvoiceStatus
|
||||
amanpayTransactionId String? @unique
|
||||
paypalCaptureId String? @unique
|
||||
stripeCheckoutSessionId String? @unique
|
||||
paymentProvider PaymentProvider @default(AMANPAY)
|
||||
billingInvoiceId String? @unique
|
||||
billingInvoice BillingInvoice? @relation(fields: [billingInvoiceId], references: [id])
|
||||
dueAt DateTime?
|
||||
paidAt DateTime?
|
||||
failedAt DateTime?
|
||||
voidedAt DateTime?
|
||||
attempts PaymentAttempt[]
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
subscriptionId String
|
||||
subscription Subscription @relation(fields: [subscriptionId], references: [id])
|
||||
requestedPlan Plan?
|
||||
requestedBillingPeriod BillingPeriod?
|
||||
providerInvoiceId String?
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
status InvoiceStatus
|
||||
amanpayTransactionId String? @unique
|
||||
paypalCaptureId String? @unique
|
||||
stripeCheckoutSessionId String? @unique
|
||||
paymentProvider PaymentProvider @default(AMANPAY)
|
||||
billingInvoiceId String? @unique
|
||||
billingInvoice BillingInvoice? @relation(fields: [billingInvoiceId], references: [id])
|
||||
dueAt DateTime?
|
||||
paidAt DateTime?
|
||||
failedAt DateTime?
|
||||
voidedAt DateTime?
|
||||
attempts PaymentAttempt[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@ -653,35 +747,44 @@ model SubscriptionInvoice {
|
||||
}
|
||||
|
||||
model BillingAccount {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
isPrimary Boolean @default(true)
|
||||
legalName String
|
||||
billingEmail String
|
||||
preferredLanguage String @default("en")
|
||||
billingAddress Json?
|
||||
taxId String?
|
||||
taxExempt Boolean @default(false)
|
||||
defaultCurrency String @default("MAD")
|
||||
defaultPaymentMethodId String?
|
||||
defaultPaymentMethod BillingPaymentMethod? @relation("BillingAccountDefaultPaymentMethod", fields: [defaultPaymentMethodId], references: [id])
|
||||
invoiceTerms BillingInvoiceTerms @default(DUE_ON_RECEIPT)
|
||||
netTermsDays Int @default(0)
|
||||
providerCustomerId String?
|
||||
dunningPaused Boolean @default(false)
|
||||
dunningPausedAt DateTime?
|
||||
dunningPausedBy String?
|
||||
metadata Json @default("{}")
|
||||
paymentMethods BillingPaymentMethod[] @relation("BillingAccountPaymentMethods")
|
||||
invoices BillingInvoice[]
|
||||
paymentIntents BillingPaymentIntent[]
|
||||
paymentAttempts BillingPaymentAttempt[]
|
||||
creditBalances BillingCreditBalance[]
|
||||
creditLedgerEntries BillingCreditLedgerEntry[]
|
||||
creditNotes BillingCreditNote[]
|
||||
refunds BillingRefund[]
|
||||
events BillingEvent[]
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
isPrimary Boolean @default(true)
|
||||
legalName String
|
||||
billingEmail String
|
||||
preferredLanguage String @default("en")
|
||||
timezone String @default("Africa/Casablanca")
|
||||
reminderLocalTime String @default("09:00")
|
||||
enabledCommunicationLocales String[] @default(["en"])
|
||||
defaultCommunicationLocale String @default("en")
|
||||
collectionsOwnerAdminId String?
|
||||
collectionsOwnerAdmin AdminUser? @relation("BillingAccountCollectionsOwner", fields: [collectionsOwnerAdminId], references: [id], onDelete: SetNull)
|
||||
billingAddress Json?
|
||||
taxId String?
|
||||
taxExempt Boolean @default(false)
|
||||
defaultCurrency String @default("MAD")
|
||||
defaultPaymentMethodId String?
|
||||
defaultPaymentMethod BillingPaymentMethod? @relation("BillingAccountDefaultPaymentMethod", fields: [defaultPaymentMethodId], references: [id])
|
||||
invoiceTerms BillingInvoiceTerms @default(DUE_ON_RECEIPT)
|
||||
netTermsDays Int @default(0)
|
||||
providerCustomerId String?
|
||||
dunningPaused Boolean @default(false)
|
||||
dunningPausedAt DateTime?
|
||||
dunningPausedBy String?
|
||||
metadata Json @default("{}")
|
||||
paymentMethods BillingPaymentMethod[] @relation("BillingAccountPaymentMethods")
|
||||
invoices BillingInvoice[]
|
||||
paymentIntents BillingPaymentIntent[]
|
||||
paymentAttempts BillingPaymentAttempt[]
|
||||
creditBalances BillingCreditBalance[]
|
||||
creditLedgerEntries BillingCreditLedgerEntry[]
|
||||
creditNotes BillingCreditNote[]
|
||||
refunds BillingRefund[]
|
||||
events BillingEvent[]
|
||||
billingContacts BillingContact[]
|
||||
manualPaymentSubmissions ManualPaymentSubmission[]
|
||||
collectionsCases CollectionsCase[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -691,6 +794,31 @@ model BillingAccount {
|
||||
@@map("billing_accounts")
|
||||
}
|
||||
|
||||
model BillingContact {
|
||||
id String @id @default(cuid())
|
||||
billingAccountId String
|
||||
billingAccount BillingAccount @relation(fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
employeeId String?
|
||||
employee Employee? @relation(fields: [employeeId], references: [id], onDelete: SetNull)
|
||||
email String
|
||||
locale String?
|
||||
isPrimary Boolean @default(false)
|
||||
receivePaymentNotices Boolean @default(true)
|
||||
isActive Boolean @default(true)
|
||||
verifiedAt DateTime?
|
||||
notificationRecipients NotificationRecipient[]
|
||||
callTasks CollectionsCallTask[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([billingAccountId, email])
|
||||
@@index([companyId, isActive])
|
||||
@@index([employeeId])
|
||||
@@map("billing_contacts")
|
||||
}
|
||||
|
||||
model BillingPaymentMethod {
|
||||
id String @id @default(cuid())
|
||||
billingAccountId String
|
||||
@@ -717,26 +845,26 @@ model BillingPaymentMethod {
|
||||
}
|
||||
|
||||
model BillingInvoice {
|
||||
id String @id @default(cuid())
|
||||
id String @id @default(cuid())
|
||||
billingAccountId String
|
||||
billingAccount BillingAccount @relation(fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
billingAccount BillingAccount @relation(fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
subscriptionId String?
|
||||
subscription Subscription? @relation(fields: [subscriptionId], references: [id])
|
||||
subscription Subscription? @relation(fields: [subscriptionId], references: [id])
|
||||
legacySubscriptionInvoice SubscriptionInvoice?
|
||||
invoiceNumber String? @unique
|
||||
invoiceSequence Int? @unique
|
||||
invoiceNumber String? @unique
|
||||
invoiceSequence Int? @unique
|
||||
invoiceType BillingInvoiceType
|
||||
status BillingInvoiceStatus @default(DRAFT)
|
||||
currency String @default("MAD")
|
||||
subtotalAmount Int @default(0)
|
||||
discountAmount Int @default(0)
|
||||
creditAmount Int @default(0)
|
||||
taxAmount Int @default(0)
|
||||
totalAmount Int @default(0)
|
||||
amountPaid Int @default(0)
|
||||
amountDue Int @default(0)
|
||||
status BillingInvoiceStatus @default(DRAFT)
|
||||
currency String @default("MAD")
|
||||
subtotalAmount Int @default(0)
|
||||
discountAmount Int @default(0)
|
||||
creditAmount Int @default(0)
|
||||
taxAmount Int @default(0)
|
||||
totalAmount Int @default(0)
|
||||
amountPaid Int @default(0)
|
||||
amountDue Int @default(0)
|
||||
invoiceDate DateTime?
|
||||
dueAt DateTime?
|
||||
finalizedAt DateTime?
|
||||
@@ -748,9 +876,14 @@ model BillingInvoice {
|
||||
billingAddress Json?
|
||||
providerInvoiceId String?
|
||||
paymentProvider PaymentProvider?
|
||||
isSubscriptionBlocking Boolean @default(false)
|
||||
collectionMethod SubscriptionCollectionMethod @default(STRIPE)
|
||||
requestedPlan Plan?
|
||||
requestedBillingPeriod BillingPeriod?
|
||||
checkoutIdempotencyKey String?
|
||||
renewalKey String? @unique
|
||||
isSubscriptionBlocking Boolean @default(false)
|
||||
adminReason String?
|
||||
metadata Json @default("{}")
|
||||
metadata Json @default("{}")
|
||||
createdByAdminId String?
|
||||
lineItems BillingInvoiceLineItem[]
|
||||
paymentIntents BillingPaymentIntent[]
|
||||
@@ -759,14 +892,18 @@ model BillingInvoice {
|
||||
creditNotes BillingCreditNote[]
|
||||
refunds BillingRefund[]
|
||||
events BillingEvent[]
|
||||
manualPaymentSubmissions ManualPaymentSubmission[]
|
||||
collectionsCase CollectionsCase?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
BillingCreditLedgerEntry BillingCreditLedgerEntry[]
|
||||
|
||||
@@unique([billingAccountId, checkoutIdempotencyKey])
|
||||
@@index([billingAccountId])
|
||||
@@index([companyId])
|
||||
@@index([subscriptionId])
|
||||
@@index([collectionMethod, status, dueAt])
|
||||
@@map("billing_invoices")
|
||||
}
|
||||
|
||||
@@ -816,32 +953,217 @@ model BillingPaymentIntent {
|
||||
}
|
||||
|
||||
model BillingPaymentAttempt {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
invoice BillingInvoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
||||
billingAccountId String
|
||||
billingAccount BillingAccount @relation(fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
paymentIntentId String?
|
||||
paymentIntent BillingPaymentIntent? @relation(fields: [paymentIntentId], references: [id])
|
||||
paymentMethodId String?
|
||||
paymentMethod BillingPaymentMethod? @relation(fields: [paymentMethodId], references: [id])
|
||||
providerPaymentId String?
|
||||
status BillingPaymentAttemptStatus
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
failureCode String?
|
||||
failureMessage String?
|
||||
attemptedAt DateTime
|
||||
metadata Json @default("{}")
|
||||
refunds BillingRefund[]
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
invoice BillingInvoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
||||
billingAccountId String
|
||||
billingAccount BillingAccount @relation(fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
paymentIntentId String?
|
||||
paymentIntent BillingPaymentIntent? @relation(fields: [paymentIntentId], references: [id])
|
||||
paymentMethodId String?
|
||||
paymentMethod BillingPaymentMethod? @relation(fields: [paymentMethodId], references: [id])
|
||||
providerPaymentId String?
|
||||
channel BillingPaymentChannel @default(ONLINE)
|
||||
manualMethod ManualPaymentMethod?
|
||||
externalReference String?
|
||||
normalizedExternalReference String?
|
||||
receivedAt DateTime?
|
||||
confirmedAt DateTime?
|
||||
confirmedByAdminId String?
|
||||
confirmedByAdmin AdminUser? @relation("ManualPaymentConfirmingAdmin", fields: [confirmedByAdminId], references: [id], onDelete: SetNull)
|
||||
idempotencyKey String?
|
||||
note String?
|
||||
status BillingPaymentAttemptStatus
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
failureCode String?
|
||||
failureMessage String?
|
||||
attemptedAt DateTime
|
||||
metadata Json @default("{}")
|
||||
refunds BillingRefund[]
|
||||
manualPaymentSubmission ManualPaymentSubmission?
|
||||
resolvedCollectionsCase CollectionsCase? @relation("CollectionsResolutionPayment")
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([billingAccountId, idempotencyKey])
|
||||
@@unique([billingAccountId, manualMethod, normalizedExternalReference])
|
||||
@@index([invoiceId])
|
||||
@@index([billingAccountId])
|
||||
@@map("billing_payment_attempts")
|
||||
}
|
||||
|
||||
model ManualPaymentSubmission {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
invoice BillingInvoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
||||
billingAccountId String
|
||||
billingAccount BillingAccount @relation(fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
method ManualPaymentMethod
|
||||
submittedReference String
|
||||
normalizedSubmittedReference String
|
||||
status ManualPaymentSubmissionStatus @default(DRAFT)
|
||||
submittedByEmployeeId String
|
||||
submittedByEmployee Employee @relation(fields: [submittedByEmployeeId], references: [id])
|
||||
submittedAt DateTime?
|
||||
reviewedByAdminId String?
|
||||
reviewedByAdmin AdminUser? @relation("ManualPaymentReviewingAdmin", fields: [reviewedByAdminId], references: [id], onDelete: SetNull)
|
||||
reviewedAt DateTime?
|
||||
rejectionReason String?
|
||||
idempotencyKey String
|
||||
paymentAttemptId String? @unique
|
||||
paymentAttempt BillingPaymentAttempt? @relation(fields: [paymentAttemptId], references: [id], onDelete: SetNull)
|
||||
documents ManualPaymentDocument[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([billingAccountId, idempotencyKey])
|
||||
@@index([invoiceId, status])
|
||||
@@index([status, submittedAt])
|
||||
@@map("manual_payment_submissions")
|
||||
}
|
||||
|
||||
model ManualPaymentDocument {
|
||||
id String @id @default(cuid())
|
||||
submissionId String
|
||||
submission ManualPaymentSubmission @relation(fields: [submissionId], references: [id], onDelete: Cascade)
|
||||
invoiceId String
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
kind ManualPaymentDocumentKind
|
||||
storageKey String @unique
|
||||
originalFilename String
|
||||
detectedMimeType String
|
||||
detectedExtension String
|
||||
byteSize Int
|
||||
sha256 String
|
||||
scanStatus ManualPaymentDocumentScanStatus @default(UPLOADED)
|
||||
scannerResultCode String?
|
||||
uploadedByEmployeeId String
|
||||
uploadedByEmployee Employee @relation(fields: [uploadedByEmployeeId], references: [id])
|
||||
uploadedAt DateTime @default(now())
|
||||
deletedAt DateTime?
|
||||
|
||||
@@unique([submissionId, sha256])
|
||||
@@index([invoiceId])
|
||||
@@index([companyId])
|
||||
@@index([scanStatus, uploadedAt])
|
||||
@@map("manual_payment_documents")
|
||||
}
|
||||
|
||||
model CollectionsCase {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String @unique
|
||||
invoice BillingInvoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
||||
subscriptionId String
|
||||
subscription Subscription @relation(fields: [subscriptionId], references: [id], onDelete: Cascade)
|
||||
billingAccountId String
|
||||
billingAccount BillingAccount @relation(fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
status CollectionsCaseStatus @default(SCHEDULED)
|
||||
originalExpirationAt DateTime
|
||||
reminder14At DateTime
|
||||
reminder7At DateTime
|
||||
reminder48At DateTime
|
||||
reminder24At DateTime
|
||||
graceStartedAt DateTime?
|
||||
finalSuspensionAt DateTime
|
||||
resolvedAt DateTime?
|
||||
suspendedAt DateTime?
|
||||
nextActionAt DateTime?
|
||||
collectionsOwnerAdminId String?
|
||||
collectionsOwnerAdmin AdminUser? @relation("CollectionsCaseOwner", fields: [collectionsOwnerAdminId], references: [id], onDelete: SetNull)
|
||||
resolutionPaymentAttemptId String? @unique
|
||||
resolutionPaymentAttempt BillingPaymentAttempt? @relation("CollectionsResolutionPayment", fields: [resolutionPaymentAttemptId], references: [id], onDelete: SetNull)
|
||||
processingLeaseUntil DateTime?
|
||||
processingBy String?
|
||||
version Int @default(0)
|
||||
tasks CollectionsCallTask[]
|
||||
overrides CollectionsOverride[]
|
||||
events CollectionsEvent[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([subscriptionId, originalExpirationAt])
|
||||
@@index([status, nextActionAt])
|
||||
@@map("collections_cases")
|
||||
}
|
||||
|
||||
model CollectionsCallTask {
|
||||
id String @id @default(cuid())
|
||||
collectionsCaseId String
|
||||
collectionsCase CollectionsCase @relation(fields: [collectionsCaseId], references: [id], onDelete: Cascade)
|
||||
taskType CollectionsCallTaskType
|
||||
assignedAdminId String
|
||||
assignedAdmin AdminUser @relation("CollectionsTaskAssignee", fields: [assignedAdminId], references: [id])
|
||||
billingContactId String?
|
||||
billingContact BillingContact? @relation(fields: [billingContactId], references: [id], onDelete: SetNull)
|
||||
dueAt DateTime
|
||||
status CollectionsCallTaskStatus @default(OPEN)
|
||||
outcome CollectionsCallOutcome?
|
||||
note String?
|
||||
promisedPaymentAt DateTime?
|
||||
nextFollowUpAt DateTime?
|
||||
completedByAdminId String?
|
||||
completedByAdmin AdminUser? @relation("CollectionsTaskCompleter", fields: [completedByAdminId], references: [id], onDelete: SetNull)
|
||||
completedAt DateTime?
|
||||
cancellationReason String?
|
||||
companyDefaultLocale String
|
||||
contactLocale String
|
||||
customerScript String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([collectionsCaseId, taskType])
|
||||
@@index([assignedAdminId, status, dueAt])
|
||||
@@map("collections_call_tasks")
|
||||
}
|
||||
|
||||
model CollectionsOverride {
|
||||
id String @id @default(cuid())
|
||||
collectionsCaseId String
|
||||
collectionsCase CollectionsCase @relation(fields: [collectionsCaseId], references: [id], onDelete: Cascade)
|
||||
type CollectionsOverrideType
|
||||
status CollectionsOverrideStatus @default(ACTIVE)
|
||||
reason String
|
||||
expiresAt DateTime
|
||||
revisedSuspensionAt DateTime?
|
||||
pauseSuspension Boolean @default(true)
|
||||
pauseNotifications Boolean @default(false)
|
||||
createdByAdminId String
|
||||
createdByAdmin AdminUser @relation("CollectionsOverrideCreator", fields: [createdByAdminId], references: [id])
|
||||
revokedByAdminId String?
|
||||
revokedByAdmin AdminUser? @relation("CollectionsOverrideRevoker", fields: [revokedByAdminId], references: [id], onDelete: SetNull)
|
||||
revokedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([collectionsCaseId, status, expiresAt])
|
||||
@@map("collections_overrides")
|
||||
}
|
||||
|
||||
model CollectionsEvent {
|
||||
id String @id @default(cuid())
|
||||
collectionsCaseId String
|
||||
collectionsCase CollectionsCase @relation(fields: [collectionsCaseId], references: [id], onDelete: Cascade)
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
eventType String
|
||||
idempotencyKey String
|
||||
scheduledFor DateTime?
|
||||
occurredAt DateTime @default(now())
|
||||
actorType String @default("system")
|
||||
actorId String?
|
||||
payload Json @default("{}")
|
||||
|
||||
@@unique([collectionsCaseId, idempotencyKey])
|
||||
@@index([companyId, occurredAt])
|
||||
@@map("collections_events")
|
||||
}
|
||||
|
||||
model BillingCreditBalance {
|
||||
id String @id @default(cuid())
|
||||
billingAccountId String
|
||||
@@ -1008,8 +1330,8 @@ model BrandSettings {
|
||||
paypalEmail String?
|
||||
paypalMerchantId String?
|
||||
paymentMethodsEnabled PaymentProvider[]
|
||||
isListedOnCarplace Boolean @default(true)
|
||||
carplaceRating Float?
|
||||
isListedOnCarplace Boolean @default(true)
|
||||
carplaceRating Float?
|
||||
homePageConfig Json? @map("home_page_config")
|
||||
menuConfig Json? @map("menu_config")
|
||||
|
||||
@@ -1036,10 +1358,13 @@ model Employee {
|
||||
preferredLanguage String @default("en")
|
||||
isActive Boolean @default(true)
|
||||
|
||||
notifications Notification[] @relation("EmployeeNotifications")
|
||||
notificationRecipients NotificationRecipient[]
|
||||
notificationPreferences NotificationPreference[]
|
||||
recordedRentalPayments RentalPayment[] @relation("RecordedRentalPayments")
|
||||
notifications Notification[] @relation("EmployeeNotifications")
|
||||
notificationRecipients NotificationRecipient[]
|
||||
notificationPreferences NotificationPreference[]
|
||||
recordedRentalPayments RentalPayment[] @relation("RecordedRentalPayments")
|
||||
billingContacts BillingContact[]
|
||||
manualPaymentSubmissions ManualPaymentSubmission[]
|
||||
manualPaymentDocuments ManualPaymentDocument[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -1073,10 +1398,10 @@ model Vehicle {
|
||||
allowDifferentDropoff Boolean @default(false)
|
||||
dropoffLocations String[] @default([])
|
||||
|
||||
reservations Reservation[]
|
||||
maintenance MaintenanceLog[]
|
||||
offerVehicles OfferVehicle[]
|
||||
calendarBlocks VehicleCalendarBlock[]
|
||||
reservations Reservation[]
|
||||
maintenance MaintenanceLog[]
|
||||
offerVehicles OfferVehicle[]
|
||||
calendarBlocks VehicleCalendarBlock[]
|
||||
pricingConfiguration VehiclePricingConfiguration?
|
||||
priceHistory VehiclePriceHistory[]
|
||||
|
||||
@@ -1116,11 +1441,11 @@ model VehiclePricingConfiguration {
|
||||
}
|
||||
|
||||
model VehiclePricingRule {
|
||||
id String @id @default(cuid())
|
||||
id String @id @default(cuid())
|
||||
configurationId String
|
||||
configuration VehiclePricingConfiguration @relation(fields: [configurationId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
ruleType VehiclePricingRuleType @default(DATE_RANGE)
|
||||
ruleType VehiclePricingRuleType @default(DATE_RANGE)
|
||||
startDate DateTime
|
||||
endDate DateTime
|
||||
dailyRate Int?
|
||||
@@ -1131,8 +1456,8 @@ model VehiclePricingRule {
|
||||
maxDailyRate Int?
|
||||
automaticAdjustmentPct Int?
|
||||
priceAdjustment Int?
|
||||
isActive Boolean @default(true)
|
||||
sortOrder Int @default(0)
|
||||
isActive Boolean @default(true)
|
||||
sortOrder Int @default(0)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -1143,12 +1468,12 @@ model VehiclePricingRule {
|
||||
}
|
||||
|
||||
model VehiclePriceHistory {
|
||||
id String @id @default(cuid())
|
||||
id String @id @default(cuid())
|
||||
configurationId String
|
||||
configuration VehiclePricingConfiguration @relation(fields: [configurationId], references: [id], onDelete: Cascade)
|
||||
vehicleId String
|
||||
vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
source VehiclePriceChangeSource @default(CONFIG_UPDATE)
|
||||
vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
source VehiclePriceChangeSource @default(CONFIG_UPDATE)
|
||||
changedByEmployeeId String?
|
||||
previousDailyRate Int?
|
||||
nextDailyRate Int?
|
||||
@@ -1156,7 +1481,7 @@ model VehiclePriceHistory {
|
||||
nextWeeklyRate Int?
|
||||
note String?
|
||||
effectiveFrom DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([vehicleId, createdAt])
|
||||
@@index([configurationId, createdAt])
|
||||
@@ -1282,9 +1607,9 @@ model Customer {
|
||||
licenseApprovedAt DateTime?
|
||||
licenseApprovalNote String?
|
||||
|
||||
reservations Reservation[]
|
||||
complaints Complaint[]
|
||||
reviewOptOut Boolean @default(false)
|
||||
reservations Reservation[]
|
||||
complaints Complaint[]
|
||||
reviewOptOut Boolean @default(false)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -1309,7 +1634,7 @@ model Reservation {
|
||||
promoCodeUsed String?
|
||||
vehicleCategory VehicleCategory?
|
||||
source BookingSource @default(DASHBOARD)
|
||||
carplaceRef String?
|
||||
carplaceRef String?
|
||||
status ReservationStatus @default(DRAFT)
|
||||
startDate DateTime
|
||||
endDate DateTime
|
||||
@@ -1342,11 +1667,11 @@ model Reservation {
|
||||
reviewPaused Boolean @default(false)
|
||||
|
||||
insurances ReservationInsurance[]
|
||||
insuranceTotal Int @default(0)
|
||||
insuranceTotal Int @default(0)
|
||||
additionalDrivers AdditionalDriver[]
|
||||
additionalDriverTotal Int @default(0)
|
||||
additionalDriverTotal Int @default(0)
|
||||
pricingRulesApplied Json?
|
||||
pricingRulesTotal Int @default(0)
|
||||
pricingRulesTotal Int @default(0)
|
||||
damageReports DamageReport[]
|
||||
rentalPayments RentalPayment[]
|
||||
inspections DamageInspection[]
|
||||
@@ -1402,7 +1727,6 @@ model CarplaceFunnelEvent {
|
||||
@@map("carplace_funnel_events")
|
||||
}
|
||||
|
||||
|
||||
model WebhookEvent {
|
||||
id String @id @default(cuid())
|
||||
provider String
|
||||
@@ -1420,50 +1744,50 @@ model WebhookEvent {
|
||||
}
|
||||
|
||||
model RentalPayment {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
reservationId String
|
||||
reservation Reservation @relation(fields: [reservationId], references: [id])
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
status PaymentStatus @default(PENDING)
|
||||
type PaymentType @default(CHARGE)
|
||||
paymentProvider PaymentProvider
|
||||
amanpayTransactionId String? @unique
|
||||
paypalCaptureId String? @unique
|
||||
stripeCheckoutSessionId String? @unique
|
||||
stripePaymentIntentId String? @unique
|
||||
paymentMethod String?
|
||||
reference String?
|
||||
note String?
|
||||
receivedAt DateTime?
|
||||
recordedByEmployeeId String?
|
||||
recordedByEmployee Employee? @relation("RecordedRentalPayments", fields: [recordedByEmployeeId], references: [id])
|
||||
idempotencyKey String?
|
||||
paidAt DateTime?
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
reservationId String
|
||||
reservation Reservation @relation(fields: [reservationId], references: [id])
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
status PaymentStatus @default(PENDING)
|
||||
type PaymentType @default(CHARGE)
|
||||
paymentProvider PaymentProvider
|
||||
amanpayTransactionId String? @unique
|
||||
paypalCaptureId String? @unique
|
||||
stripeCheckoutSessionId String? @unique
|
||||
stripePaymentIntentId String? @unique
|
||||
paymentMethod String?
|
||||
reference String?
|
||||
note String?
|
||||
receivedAt DateTime?
|
||||
recordedByEmployeeId String?
|
||||
recordedByEmployee Employee? @relation("RecordedRentalPayments", fields: [recordedByEmployeeId], references: [id])
|
||||
idempotencyKey String?
|
||||
paidAt DateTime?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([companyId, idempotencyKey])
|
||||
@@index([companyId])
|
||||
@@index([reservationId])
|
||||
@@unique([companyId, idempotencyKey])
|
||||
@@map("rental_payments")
|
||||
}
|
||||
|
||||
model Review {
|
||||
id String @id @default(cuid())
|
||||
reservationId String @unique
|
||||
reservation Reservation @relation(fields: [reservationId], references: [id])
|
||||
id String @id @default(cuid())
|
||||
reservationId String @unique
|
||||
reservation Reservation @relation(fields: [reservationId], references: [id])
|
||||
renterId String?
|
||||
renter Renter? @relation(fields: [renterId], references: [id])
|
||||
renter Renter? @relation(fields: [renterId], references: [id])
|
||||
companyId String
|
||||
overallRating Int
|
||||
vehicleRating Int?
|
||||
serviceRating Int?
|
||||
comment String?
|
||||
isPublished Boolean @default(true)
|
||||
isPublished Boolean @default(true)
|
||||
companyReply String?
|
||||
companyRepliedAt DateTime?
|
||||
category FeedbackCategory?
|
||||
@@ -1476,29 +1800,29 @@ model Review {
|
||||
}
|
||||
|
||||
model Complaint {
|
||||
id String @id @default(cuid())
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
reservationId String?
|
||||
reservation Reservation? @relation(fields: [reservationId], references: [id])
|
||||
reservation Reservation? @relation(fields: [reservationId], references: [id])
|
||||
reviewId String?
|
||||
review Review? @relation(fields: [reviewId], references: [id])
|
||||
review Review? @relation(fields: [reviewId], references: [id])
|
||||
customerId String?
|
||||
customer Customer? @relation(fields: [customerId], references: [id])
|
||||
customer Customer? @relation(fields: [customerId], references: [id])
|
||||
|
||||
severity ComplaintSeverity @default(LEVEL_1)
|
||||
status ComplaintStatus @default(OPEN)
|
||||
category FeedbackCategory
|
||||
subject String
|
||||
description String?
|
||||
resolution String?
|
||||
notes String?
|
||||
assignedTo String?
|
||||
resolvedAt DateTime?
|
||||
resolvedBy String?
|
||||
severity ComplaintSeverity @default(LEVEL_1)
|
||||
status ComplaintStatus @default(OPEN)
|
||||
category FeedbackCategory
|
||||
subject String
|
||||
description String?
|
||||
resolution String?
|
||||
notes String?
|
||||
assignedTo String?
|
||||
resolvedAt DateTime?
|
||||
resolvedBy String?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([companyId])
|
||||
@@index([reservationId])
|
||||
@@ -1538,12 +1862,12 @@ model Notification {
|
||||
}
|
||||
|
||||
model NotificationEvent {
|
||||
id String @id @default(cuid())
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
type NotificationType
|
||||
templateKey String?
|
||||
locale String @default("en")
|
||||
locale String @default("en")
|
||||
title String
|
||||
body String
|
||||
data Json?
|
||||
@@ -1552,7 +1876,7 @@ model NotificationEvent {
|
||||
idempotencyKey String
|
||||
recipients NotificationRecipient[]
|
||||
outboxEntries NotificationOutbox[]
|
||||
createdAt DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([companyId, idempotencyKey])
|
||||
@@index([companyId, type, createdAt])
|
||||
@@ -1568,6 +1892,10 @@ model NotificationRecipient {
|
||||
employee Employee? @relation(fields: [employeeId], references: [id], onDelete: Cascade)
|
||||
renterId String?
|
||||
renter Renter? @relation(fields: [renterId], references: [id], onDelete: Cascade)
|
||||
billingContactId String?
|
||||
billingContact BillingContact? @relation(fields: [billingContactId], references: [id], onDelete: Cascade)
|
||||
adminUserId String?
|
||||
adminUser AdminUser? @relation(fields: [adminUserId], references: [id], onDelete: Cascade)
|
||||
readAt DateTime?
|
||||
archivedAt DateTime?
|
||||
deliveries NotificationDelivery[]
|
||||
@@ -1575,6 +1903,8 @@ model NotificationRecipient {
|
||||
|
||||
@@index([employeeId, readAt, createdAt])
|
||||
@@index([renterId, readAt, createdAt])
|
||||
@@index([billingContactId, readAt, createdAt])
|
||||
@@index([adminUserId, readAt, createdAt])
|
||||
@@index([notificationEventId])
|
||||
@@map("notification_recipients")
|
||||
}
|
||||
@@ -1953,9 +2283,19 @@ model AdminUser {
|
||||
passwordResetToken String? @unique
|
||||
passwordResetExpiresAt DateTime?
|
||||
|
||||
auditLogs AuditLog[]
|
||||
permissions AdminPermission[]
|
||||
recoveryCodes AdminRecoveryCode[]
|
||||
auditLogs AuditLog[]
|
||||
permissions AdminPermission[]
|
||||
recoveryCodes AdminRecoveryCode[]
|
||||
preferredLocale String @default("en")
|
||||
ownedBillingAccounts BillingAccount[] @relation("BillingAccountCollectionsOwner")
|
||||
confirmedManualPayments BillingPaymentAttempt[] @relation("ManualPaymentConfirmingAdmin")
|
||||
reviewedManualSubmissions ManualPaymentSubmission[] @relation("ManualPaymentReviewingAdmin")
|
||||
ownedCollectionsCases CollectionsCase[] @relation("CollectionsCaseOwner")
|
||||
assignedCollectionsTasks CollectionsCallTask[] @relation("CollectionsTaskAssignee")
|
||||
completedCollectionsTasks CollectionsCallTask[] @relation("CollectionsTaskCompleter")
|
||||
createdCollectionsOverrides CollectionsOverride[] @relation("CollectionsOverrideCreator")
|
||||
revokedCollectionsOverrides CollectionsOverride[] @relation("CollectionsOverrideRevoker")
|
||||
notificationRecipients NotificationRecipient[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -1974,7 +2314,6 @@ model AdminPermission {
|
||||
@@map("admin_permissions")
|
||||
}
|
||||
|
||||
|
||||
model AdminRecoveryCode {
|
||||
id String @id @default(cuid())
|
||||
adminUserId String
|
||||
@@ -2022,6 +2361,15 @@ model PricingConfig {
|
||||
@@map("pricing_configs")
|
||||
}
|
||||
|
||||
model PlatformBillingSettings {
|
||||
id String @id @default("default")
|
||||
taxRate Float @default(20)
|
||||
updatedAt DateTime @updatedAt
|
||||
updatedBy String?
|
||||
|
||||
@@map("platform_billing_settings")
|
||||
}
|
||||
|
||||
model PlanFeature {
|
||||
id String @id @default(cuid())
|
||||
plan Plan
|
||||
|
||||
Reference in New Issue
Block a user