billing invoice
This commit is contained in:
+493
@@ -0,0 +1,493 @@
|
||||
CREATE TYPE "BillingInvoiceTerms" AS ENUM (
|
||||
'DUE_ON_RECEIPT',
|
||||
'NET_7',
|
||||
'NET_15',
|
||||
'NET_30',
|
||||
'NET_45',
|
||||
'NET_60'
|
||||
);
|
||||
|
||||
CREATE TYPE "BillingInvoiceStatus" AS ENUM (
|
||||
'DRAFT',
|
||||
'OPEN',
|
||||
'PAID',
|
||||
'PARTIALLY_PAID',
|
||||
'PAYMENT_PENDING',
|
||||
'PAST_DUE',
|
||||
'VOID',
|
||||
'UNCOLLECTIBLE',
|
||||
'REFUNDED',
|
||||
'PARTIALLY_REFUNDED'
|
||||
);
|
||||
|
||||
CREATE TYPE "BillingInvoiceType" AS ENUM (
|
||||
'SUBSCRIPTION_INITIAL',
|
||||
'SUBSCRIPTION_RENEWAL',
|
||||
'TRIAL_CONVERSION',
|
||||
'SUBSCRIPTION_UPGRADE',
|
||||
'SUBSCRIPTION_DOWNGRADE_CREDIT',
|
||||
'USAGE_BASED',
|
||||
'ONE_TIME',
|
||||
'MANUAL',
|
||||
'CORRECTION',
|
||||
'CANCELLATION_FEE'
|
||||
);
|
||||
|
||||
CREATE TYPE "BillingLineItemType" AS ENUM (
|
||||
'SUBSCRIPTION_FEE',
|
||||
'SEAT_FEE',
|
||||
'USAGE_FEE',
|
||||
'SETUP_FEE',
|
||||
'DISCOUNT',
|
||||
'TAX',
|
||||
'CREDIT',
|
||||
'PRORATION',
|
||||
'REFUND_ADJUSTMENT',
|
||||
'MANUAL_ADJUSTMENT',
|
||||
'PROFESSIONAL_SERVICES',
|
||||
'CANCELLATION_FEE'
|
||||
);
|
||||
|
||||
CREATE TYPE "BillingPaymentMethodType" AS ENUM (
|
||||
'CARD',
|
||||
'ACH_DEBIT',
|
||||
'BANK_TRANSFER',
|
||||
'WIRE_TRANSFER',
|
||||
'MANUAL_INVOICE',
|
||||
'PURCHASE_ORDER'
|
||||
);
|
||||
|
||||
CREATE TYPE "BillingPaymentIntentStatus" AS ENUM (
|
||||
'REQUIRES_PAYMENT_METHOD',
|
||||
'REQUIRES_CONFIRMATION',
|
||||
'REQUIRES_ACTION',
|
||||
'PROCESSING',
|
||||
'SUCCEEDED',
|
||||
'FAILED',
|
||||
'CANCELED',
|
||||
'REFUNDED',
|
||||
'PARTIALLY_REFUNDED'
|
||||
);
|
||||
|
||||
CREATE TYPE "BillingPaymentAttemptStatus" AS ENUM (
|
||||
'PENDING',
|
||||
'PROCESSING',
|
||||
'SUCCEEDED',
|
||||
'FAILED',
|
||||
'CANCELED',
|
||||
'REFUNDED',
|
||||
'PARTIALLY_REFUNDED'
|
||||
);
|
||||
|
||||
CREATE TYPE "BillingRefundStatus" AS ENUM (
|
||||
'PENDING',
|
||||
'SUCCEEDED',
|
||||
'FAILED'
|
||||
);
|
||||
|
||||
CREATE TYPE "BillingCreditNoteStatus" AS ENUM (
|
||||
'ISSUED',
|
||||
'APPLIED',
|
||||
'VOID'
|
||||
);
|
||||
|
||||
CREATE SEQUENCE "billing_invoice_sequence_seq" START 1;
|
||||
|
||||
CREATE TABLE "billing_accounts" (
|
||||
"id" TEXT NOT NULL,
|
||||
"companyId" TEXT NOT NULL,
|
||||
"isPrimary" BOOLEAN NOT NULL DEFAULT true,
|
||||
"legalName" TEXT NOT NULL,
|
||||
"billingEmail" TEXT NOT NULL,
|
||||
"billingAddress" JSONB,
|
||||
"taxId" TEXT,
|
||||
"taxExempt" BOOLEAN NOT NULL DEFAULT false,
|
||||
"defaultCurrency" TEXT NOT NULL DEFAULT 'MAD',
|
||||
"defaultPaymentMethodId" TEXT,
|
||||
"invoiceTerms" "BillingInvoiceTerms" NOT NULL DEFAULT 'DUE_ON_RECEIPT',
|
||||
"netTermsDays" INTEGER NOT NULL DEFAULT 0,
|
||||
"providerCustomerId" TEXT,
|
||||
"dunningPaused" BOOLEAN NOT NULL DEFAULT false,
|
||||
"dunningPausedAt" TIMESTAMP(3),
|
||||
"dunningPausedBy" TEXT,
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_accounts_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_payment_methods" (
|
||||
"id" TEXT NOT NULL,
|
||||
"billingAccountId" TEXT NOT NULL,
|
||||
"type" "BillingPaymentMethodType" NOT NULL,
|
||||
"providerPaymentMethodId" TEXT,
|
||||
"label" TEXT,
|
||||
"brand" TEXT,
|
||||
"last4" TEXT,
|
||||
"expMonth" INTEGER,
|
||||
"expYear" INTEGER,
|
||||
"isDefault" BOOLEAN NOT NULL DEFAULT false,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_payment_methods_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_invoices" (
|
||||
"id" TEXT NOT NULL,
|
||||
"billingAccountId" TEXT NOT NULL,
|
||||
"companyId" TEXT NOT NULL,
|
||||
"subscriptionId" TEXT,
|
||||
"invoiceNumber" TEXT,
|
||||
"invoiceSequence" INTEGER,
|
||||
"invoiceType" "BillingInvoiceType" NOT NULL,
|
||||
"status" "BillingInvoiceStatus" NOT NULL DEFAULT 'DRAFT',
|
||||
"currency" TEXT NOT NULL DEFAULT 'MAD',
|
||||
"subtotalAmount" INTEGER NOT NULL DEFAULT 0,
|
||||
"discountAmount" INTEGER NOT NULL DEFAULT 0,
|
||||
"creditAmount" INTEGER NOT NULL DEFAULT 0,
|
||||
"taxAmount" INTEGER NOT NULL DEFAULT 0,
|
||||
"totalAmount" INTEGER NOT NULL DEFAULT 0,
|
||||
"amountPaid" INTEGER NOT NULL DEFAULT 0,
|
||||
"amountDue" INTEGER NOT NULL DEFAULT 0,
|
||||
"invoiceDate" TIMESTAMP(3),
|
||||
"dueAt" TIMESTAMP(3),
|
||||
"finalizedAt" TIMESTAMP(3),
|
||||
"paidAt" TIMESTAMP(3),
|
||||
"voidedAt" TIMESTAMP(3),
|
||||
"markedUncollectibleAt" TIMESTAMP(3),
|
||||
"billingName" TEXT,
|
||||
"billingEmail" TEXT,
|
||||
"billingAddress" JSONB,
|
||||
"providerInvoiceId" TEXT,
|
||||
"paymentProvider" "PaymentProvider",
|
||||
"isSubscriptionBlocking" BOOLEAN NOT NULL DEFAULT false,
|
||||
"adminReason" TEXT,
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdByAdminId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_invoices_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_invoice_line_items" (
|
||||
"id" TEXT NOT NULL,
|
||||
"invoiceId" TEXT NOT NULL,
|
||||
"subscriptionId" TEXT,
|
||||
"plan" "Plan",
|
||||
"type" "BillingLineItemType" NOT NULL,
|
||||
"description" TEXT NOT NULL,
|
||||
"quantity" INTEGER NOT NULL DEFAULT 1,
|
||||
"unitAmount" INTEGER NOT NULL,
|
||||
"amount" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'MAD',
|
||||
"periodStart" TIMESTAMP(3),
|
||||
"periodEnd" TIMESTAMP(3),
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_invoice_line_items_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_payment_intents" (
|
||||
"id" TEXT NOT NULL,
|
||||
"invoiceId" TEXT NOT NULL,
|
||||
"billingAccountId" TEXT NOT NULL,
|
||||
"paymentMethodId" TEXT,
|
||||
"providerPaymentIntentId" TEXT,
|
||||
"status" "BillingPaymentIntentStatus" NOT NULL DEFAULT 'REQUIRES_PAYMENT_METHOD',
|
||||
"amount" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'MAD',
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_payment_intents_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_payment_attempts" (
|
||||
"id" TEXT NOT NULL,
|
||||
"invoiceId" TEXT NOT NULL,
|
||||
"billingAccountId" TEXT NOT NULL,
|
||||
"paymentIntentId" TEXT,
|
||||
"paymentMethodId" TEXT,
|
||||
"providerPaymentId" TEXT,
|
||||
"status" "BillingPaymentAttemptStatus" NOT NULL,
|
||||
"amount" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'MAD',
|
||||
"failureCode" TEXT,
|
||||
"failureMessage" TEXT,
|
||||
"attemptedAt" TIMESTAMP(3) NOT NULL,
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_payment_attempts_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_credit_balances" (
|
||||
"id" TEXT NOT NULL,
|
||||
"billingAccountId" TEXT NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'MAD',
|
||||
"balanceAmount" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_credit_balances_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_credit_ledger_entries" (
|
||||
"id" TEXT NOT NULL,
|
||||
"billingAccountId" TEXT NOT NULL,
|
||||
"invoiceId" TEXT,
|
||||
"type" TEXT NOT NULL,
|
||||
"amount" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'MAD',
|
||||
"reason" TEXT NOT NULL,
|
||||
"createdBy" TEXT,
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_credit_ledger_entries_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_credit_notes" (
|
||||
"id" TEXT NOT NULL,
|
||||
"invoiceId" TEXT NOT NULL,
|
||||
"billingAccountId" TEXT NOT NULL,
|
||||
"amount" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'MAD',
|
||||
"reason" TEXT NOT NULL,
|
||||
"status" "BillingCreditNoteStatus" NOT NULL DEFAULT 'ISSUED',
|
||||
"createdBy" TEXT,
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_credit_notes_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_refunds" (
|
||||
"id" TEXT NOT NULL,
|
||||
"invoiceId" TEXT NOT NULL,
|
||||
"paymentAttemptId" TEXT,
|
||||
"billingAccountId" TEXT NOT NULL,
|
||||
"amount" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'MAD',
|
||||
"reason" TEXT NOT NULL,
|
||||
"status" "BillingRefundStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"providerRefundId" TEXT,
|
||||
"createdBy" TEXT,
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_refunds_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_tax_records" (
|
||||
"id" TEXT NOT NULL,
|
||||
"invoiceId" TEXT NOT NULL,
|
||||
"jurisdiction" TEXT,
|
||||
"taxRate" DOUBLE PRECISION,
|
||||
"taxAmount" INTEGER NOT NULL,
|
||||
"taxType" TEXT,
|
||||
"taxExempt" BOOLEAN NOT NULL DEFAULT false,
|
||||
"exemptionReason" TEXT,
|
||||
"providerTaxId" TEXT,
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_tax_records_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "billing_events" (
|
||||
"id" TEXT NOT NULL,
|
||||
"billingAccountId" TEXT,
|
||||
"invoiceId" TEXT,
|
||||
"subscriptionId" TEXT,
|
||||
"companyId" TEXT,
|
||||
"eventType" TEXT NOT NULL,
|
||||
"source" TEXT NOT NULL,
|
||||
"payload" JSONB NOT NULL DEFAULT '{}',
|
||||
"occurredAt" TIMESTAMP(3) NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "billing_events_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
ALTER TABLE "subscription_invoices"
|
||||
ADD COLUMN "billingInvoiceId" TEXT;
|
||||
|
||||
CREATE UNIQUE INDEX "subscription_invoices_billingInvoiceId_key" ON "subscription_invoices"("billingInvoiceId");
|
||||
CREATE UNIQUE INDEX "billing_invoices_invoiceNumber_key" ON "billing_invoices"("invoiceNumber");
|
||||
CREATE UNIQUE INDEX "billing_invoices_invoiceSequence_key" ON "billing_invoices"("invoiceSequence");
|
||||
CREATE UNIQUE INDEX "billing_credit_balances_billingAccountId_currency_key" ON "billing_credit_balances"("billingAccountId", "currency");
|
||||
|
||||
CREATE INDEX "billing_accounts_companyId_idx" ON "billing_accounts"("companyId");
|
||||
CREATE INDEX "billing_accounts_companyId_isPrimary_idx" ON "billing_accounts"("companyId", "isPrimary");
|
||||
CREATE INDEX "billing_payment_methods_billingAccountId_idx" ON "billing_payment_methods"("billingAccountId");
|
||||
CREATE INDEX "billing_invoices_billingAccountId_idx" ON "billing_invoices"("billingAccountId");
|
||||
CREATE INDEX "billing_invoices_companyId_idx" ON "billing_invoices"("companyId");
|
||||
CREATE INDEX "billing_invoices_subscriptionId_idx" ON "billing_invoices"("subscriptionId");
|
||||
CREATE INDEX "billing_invoice_line_items_invoiceId_idx" ON "billing_invoice_line_items"("invoiceId");
|
||||
CREATE INDEX "billing_payment_intents_invoiceId_idx" ON "billing_payment_intents"("invoiceId");
|
||||
CREATE INDEX "billing_payment_intents_billingAccountId_idx" ON "billing_payment_intents"("billingAccountId");
|
||||
CREATE INDEX "billing_payment_attempts_invoiceId_idx" ON "billing_payment_attempts"("invoiceId");
|
||||
CREATE INDEX "billing_payment_attempts_billingAccountId_idx" ON "billing_payment_attempts"("billingAccountId");
|
||||
CREATE INDEX "billing_credit_ledger_entries_billingAccountId_idx" ON "billing_credit_ledger_entries"("billingAccountId");
|
||||
CREATE INDEX "billing_credit_notes_invoiceId_idx" ON "billing_credit_notes"("invoiceId");
|
||||
CREATE INDEX "billing_credit_notes_billingAccountId_idx" ON "billing_credit_notes"("billingAccountId");
|
||||
CREATE INDEX "billing_refunds_invoiceId_idx" ON "billing_refunds"("invoiceId");
|
||||
CREATE INDEX "billing_refunds_billingAccountId_idx" ON "billing_refunds"("billingAccountId");
|
||||
CREATE INDEX "billing_tax_records_invoiceId_idx" ON "billing_tax_records"("invoiceId");
|
||||
CREATE INDEX "billing_events_billingAccountId_idx" ON "billing_events"("billingAccountId");
|
||||
CREATE INDEX "billing_events_invoiceId_idx" ON "billing_events"("invoiceId");
|
||||
CREATE INDEX "billing_events_subscriptionId_idx" ON "billing_events"("subscriptionId");
|
||||
CREATE INDEX "billing_events_companyId_idx" ON "billing_events"("companyId");
|
||||
|
||||
ALTER TABLE "billing_accounts"
|
||||
ADD CONSTRAINT "billing_accounts_companyId_fkey"
|
||||
FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_payment_methods"
|
||||
ADD CONSTRAINT "billing_payment_methods_billingAccountId_fkey"
|
||||
FOREIGN KEY ("billingAccountId") REFERENCES "billing_accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_accounts"
|
||||
ADD CONSTRAINT "billing_accounts_defaultPaymentMethodId_fkey"
|
||||
FOREIGN KEY ("defaultPaymentMethodId") REFERENCES "billing_payment_methods"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_invoices"
|
||||
ADD CONSTRAINT "billing_invoices_billingAccountId_fkey"
|
||||
FOREIGN KEY ("billingAccountId") REFERENCES "billing_accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_invoices"
|
||||
ADD CONSTRAINT "billing_invoices_companyId_fkey"
|
||||
FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_invoices"
|
||||
ADD CONSTRAINT "billing_invoices_subscriptionId_fkey"
|
||||
FOREIGN KEY ("subscriptionId") REFERENCES "subscriptions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "subscription_invoices"
|
||||
ADD CONSTRAINT "subscription_invoices_billingInvoiceId_fkey"
|
||||
FOREIGN KEY ("billingInvoiceId") REFERENCES "billing_invoices"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_invoice_line_items"
|
||||
ADD CONSTRAINT "billing_invoice_line_items_invoiceId_fkey"
|
||||
FOREIGN KEY ("invoiceId") REFERENCES "billing_invoices"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_payment_intents"
|
||||
ADD CONSTRAINT "billing_payment_intents_invoiceId_fkey"
|
||||
FOREIGN KEY ("invoiceId") REFERENCES "billing_invoices"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_payment_intents"
|
||||
ADD CONSTRAINT "billing_payment_intents_billingAccountId_fkey"
|
||||
FOREIGN KEY ("billingAccountId") REFERENCES "billing_accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_payment_intents"
|
||||
ADD CONSTRAINT "billing_payment_intents_paymentMethodId_fkey"
|
||||
FOREIGN KEY ("paymentMethodId") REFERENCES "billing_payment_methods"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_payment_attempts"
|
||||
ADD CONSTRAINT "billing_payment_attempts_invoiceId_fkey"
|
||||
FOREIGN KEY ("invoiceId") REFERENCES "billing_invoices"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_payment_attempts"
|
||||
ADD CONSTRAINT "billing_payment_attempts_billingAccountId_fkey"
|
||||
FOREIGN KEY ("billingAccountId") REFERENCES "billing_accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_payment_attempts"
|
||||
ADD CONSTRAINT "billing_payment_attempts_paymentIntentId_fkey"
|
||||
FOREIGN KEY ("paymentIntentId") REFERENCES "billing_payment_intents"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_payment_attempts"
|
||||
ADD CONSTRAINT "billing_payment_attempts_paymentMethodId_fkey"
|
||||
FOREIGN KEY ("paymentMethodId") REFERENCES "billing_payment_methods"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_credit_balances"
|
||||
ADD CONSTRAINT "billing_credit_balances_billingAccountId_fkey"
|
||||
FOREIGN KEY ("billingAccountId") REFERENCES "billing_accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_credit_ledger_entries"
|
||||
ADD CONSTRAINT "billing_credit_ledger_entries_billingAccountId_fkey"
|
||||
FOREIGN KEY ("billingAccountId") REFERENCES "billing_accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_credit_ledger_entries"
|
||||
ADD CONSTRAINT "billing_credit_ledger_entries_invoiceId_fkey"
|
||||
FOREIGN KEY ("invoiceId") REFERENCES "billing_invoices"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_credit_notes"
|
||||
ADD CONSTRAINT "billing_credit_notes_invoiceId_fkey"
|
||||
FOREIGN KEY ("invoiceId") REFERENCES "billing_invoices"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_credit_notes"
|
||||
ADD CONSTRAINT "billing_credit_notes_billingAccountId_fkey"
|
||||
FOREIGN KEY ("billingAccountId") REFERENCES "billing_accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_refunds"
|
||||
ADD CONSTRAINT "billing_refunds_invoiceId_fkey"
|
||||
FOREIGN KEY ("invoiceId") REFERENCES "billing_invoices"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_refunds"
|
||||
ADD CONSTRAINT "billing_refunds_paymentAttemptId_fkey"
|
||||
FOREIGN KEY ("paymentAttemptId") REFERENCES "billing_payment_attempts"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_refunds"
|
||||
ADD CONSTRAINT "billing_refunds_billingAccountId_fkey"
|
||||
FOREIGN KEY ("billingAccountId") REFERENCES "billing_accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_tax_records"
|
||||
ADD CONSTRAINT "billing_tax_records_invoiceId_fkey"
|
||||
FOREIGN KEY ("invoiceId") REFERENCES "billing_invoices"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_events"
|
||||
ADD CONSTRAINT "billing_events_billingAccountId_fkey"
|
||||
FOREIGN KEY ("billingAccountId") REFERENCES "billing_accounts"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_events"
|
||||
ADD CONSTRAINT "billing_events_invoiceId_fkey"
|
||||
FOREIGN KEY ("invoiceId") REFERENCES "billing_invoices"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_events"
|
||||
ADD CONSTRAINT "billing_events_subscriptionId_fkey"
|
||||
FOREIGN KEY ("subscriptionId") REFERENCES "subscriptions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "billing_events"
|
||||
ADD CONSTRAINT "billing_events_companyId_fkey"
|
||||
FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
INSERT INTO "billing_accounts" (
|
||||
"id",
|
||||
"companyId",
|
||||
"isPrimary",
|
||||
"legalName",
|
||||
"billingEmail",
|
||||
"billingAddress",
|
||||
"taxExempt",
|
||||
"defaultCurrency",
|
||||
"invoiceTerms",
|
||||
"netTermsDays",
|
||||
"metadata"
|
||||
)
|
||||
SELECT
|
||||
'ba_' || c."id",
|
||||
c."id",
|
||||
true,
|
||||
c."name",
|
||||
c."email",
|
||||
c."address",
|
||||
false,
|
||||
COALESCE(a."currency", 'MAD'),
|
||||
'DUE_ON_RECEIPT'::"BillingInvoiceTerms",
|
||||
0,
|
||||
'{}'::jsonb
|
||||
FROM "companies" c
|
||||
LEFT JOIN "accounting_settings" a ON a."companyId" = c."id"
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "billing_accounts" ba
|
||||
WHERE ba."companyId" = c."id" AND ba."isPrimary" = true
|
||||
);
|
||||
@@ -52,6 +52,99 @@ enum InvoiceStatus {
|
||||
VOIDED
|
||||
}
|
||||
|
||||
enum BillingInvoiceTerms {
|
||||
DUE_ON_RECEIPT
|
||||
NET_7
|
||||
NET_15
|
||||
NET_30
|
||||
NET_45
|
||||
NET_60
|
||||
}
|
||||
|
||||
enum BillingInvoiceStatus {
|
||||
DRAFT
|
||||
OPEN
|
||||
PAID
|
||||
PARTIALLY_PAID
|
||||
PAYMENT_PENDING
|
||||
PAST_DUE
|
||||
VOID
|
||||
UNCOLLECTIBLE
|
||||
REFUNDED
|
||||
PARTIALLY_REFUNDED
|
||||
}
|
||||
|
||||
enum BillingInvoiceType {
|
||||
SUBSCRIPTION_INITIAL
|
||||
SUBSCRIPTION_RENEWAL
|
||||
TRIAL_CONVERSION
|
||||
SUBSCRIPTION_UPGRADE
|
||||
SUBSCRIPTION_DOWNGRADE_CREDIT
|
||||
USAGE_BASED
|
||||
ONE_TIME
|
||||
MANUAL
|
||||
CORRECTION
|
||||
CANCELLATION_FEE
|
||||
}
|
||||
|
||||
enum BillingLineItemType {
|
||||
SUBSCRIPTION_FEE
|
||||
SEAT_FEE
|
||||
USAGE_FEE
|
||||
SETUP_FEE
|
||||
DISCOUNT
|
||||
TAX
|
||||
CREDIT
|
||||
PRORATION
|
||||
REFUND_ADJUSTMENT
|
||||
MANUAL_ADJUSTMENT
|
||||
PROFESSIONAL_SERVICES
|
||||
CANCELLATION_FEE
|
||||
}
|
||||
|
||||
enum BillingPaymentMethodType {
|
||||
CARD
|
||||
ACH_DEBIT
|
||||
BANK_TRANSFER
|
||||
WIRE_TRANSFER
|
||||
MANUAL_INVOICE
|
||||
PURCHASE_ORDER
|
||||
}
|
||||
|
||||
enum BillingPaymentIntentStatus {
|
||||
REQUIRES_PAYMENT_METHOD
|
||||
REQUIRES_CONFIRMATION
|
||||
REQUIRES_ACTION
|
||||
PROCESSING
|
||||
SUCCEEDED
|
||||
FAILED
|
||||
CANCELED
|
||||
REFUNDED
|
||||
PARTIALLY_REFUNDED
|
||||
}
|
||||
|
||||
enum BillingPaymentAttemptStatus {
|
||||
PENDING
|
||||
PROCESSING
|
||||
SUCCEEDED
|
||||
FAILED
|
||||
CANCELED
|
||||
REFUNDED
|
||||
PARTIALLY_REFUNDED
|
||||
}
|
||||
|
||||
enum BillingRefundStatus {
|
||||
PENDING
|
||||
SUCCEEDED
|
||||
FAILED
|
||||
}
|
||||
|
||||
enum BillingCreditNoteStatus {
|
||||
ISSUED
|
||||
APPLIED
|
||||
VOID
|
||||
}
|
||||
|
||||
enum PaymentProvider {
|
||||
AMANPAY
|
||||
PAYPAL
|
||||
@@ -340,54 +433,59 @@ model Company {
|
||||
subscriptionPaymentRef String?
|
||||
apiKey String @unique @default(cuid())
|
||||
|
||||
subscription Subscription?
|
||||
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")
|
||||
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")
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
BillingEvent BillingEvent[]
|
||||
|
||||
@@map("companies")
|
||||
}
|
||||
|
||||
model Subscription {
|
||||
id String @id @default(cuid())
|
||||
companyId String @unique
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
plan Plan @default(STARTER)
|
||||
billingPeriod BillingPeriod @default(MONTHLY)
|
||||
status SubscriptionStatus @default(TRIALING)
|
||||
currency String @default("MAD")
|
||||
trialStartAt DateTime?
|
||||
trialEndAt DateTime?
|
||||
trialUsed Boolean @default(false)
|
||||
currentPeriodStart DateTime?
|
||||
currentPeriodEnd DateTime?
|
||||
paymentPendingSince DateTime?
|
||||
paymentDueAt DateTime?
|
||||
pastDueSince DateTime?
|
||||
suspendedAt DateTime?
|
||||
endedAt DateTime?
|
||||
cancelledAt DateTime?
|
||||
cancelAtPeriodEnd Boolean @default(false)
|
||||
retryCount Int @default(0)
|
||||
maxRetryCount Int @default(5)
|
||||
invoices SubscriptionInvoice[]
|
||||
events SubscriptionEvent[]
|
||||
id String @id @default(cuid())
|
||||
companyId String @unique
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
plan Plan @default(STARTER)
|
||||
billingPeriod BillingPeriod @default(MONTHLY)
|
||||
status SubscriptionStatus @default(TRIALING)
|
||||
currency String @default("MAD")
|
||||
trialStartAt DateTime?
|
||||
trialEndAt DateTime?
|
||||
trialUsed Boolean @default(false)
|
||||
currentPeriodStart DateTime?
|
||||
currentPeriodEnd DateTime?
|
||||
paymentPendingSince DateTime?
|
||||
paymentDueAt DateTime?
|
||||
pastDueSince DateTime?
|
||||
suspendedAt DateTime?
|
||||
endedAt DateTime?
|
||||
cancelledAt DateTime?
|
||||
cancelAtPeriodEnd Boolean @default(false)
|
||||
retryCount Int @default(0)
|
||||
maxRetryCount Int @default(5)
|
||||
invoices SubscriptionInvoice[]
|
||||
billingInvoices BillingInvoice[]
|
||||
events SubscriptionEvent[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
BillingEvent BillingEvent[]
|
||||
|
||||
@@map("subscriptions")
|
||||
}
|
||||
@@ -421,6 +519,8 @@ model SubscriptionInvoice {
|
||||
amanpayTransactionId String? @unique
|
||||
paypalCaptureId String? @unique
|
||||
paymentProvider PaymentProvider @default(AMANPAY)
|
||||
billingInvoiceId String? @unique
|
||||
billingInvoice BillingInvoice? @relation(fields: [billingInvoiceId], references: [id])
|
||||
dueAt DateTime?
|
||||
paidAt DateTime?
|
||||
failedAt DateTime?
|
||||
@@ -433,6 +533,314 @@ model SubscriptionInvoice {
|
||||
@@map("subscription_invoices")
|
||||
}
|
||||
|
||||
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
|
||||
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[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([companyId])
|
||||
@@index([companyId, isPrimary])
|
||||
@@map("billing_accounts")
|
||||
}
|
||||
|
||||
model BillingPaymentMethod {
|
||||
id String @id @default(cuid())
|
||||
billingAccountId String
|
||||
billingAccount BillingAccount @relation("BillingAccountPaymentMethods", fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
type BillingPaymentMethodType
|
||||
providerPaymentMethodId String?
|
||||
label String?
|
||||
brand String?
|
||||
last4 String?
|
||||
expMonth Int?
|
||||
expYear Int?
|
||||
isDefault Boolean @default(false)
|
||||
isActive Boolean @default(true)
|
||||
metadata Json @default("{}")
|
||||
defaultForBillingAccounts BillingAccount[] @relation("BillingAccountDefaultPaymentMethod")
|
||||
paymentIntents BillingPaymentIntent[]
|
||||
paymentAttempts BillingPaymentAttempt[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([billingAccountId])
|
||||
@@map("billing_payment_methods")
|
||||
}
|
||||
|
||||
model BillingInvoice {
|
||||
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)
|
||||
subscriptionId String?
|
||||
subscription Subscription? @relation(fields: [subscriptionId], references: [id])
|
||||
legacySubscriptionInvoice SubscriptionInvoice?
|
||||
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)
|
||||
invoiceDate DateTime?
|
||||
dueAt DateTime?
|
||||
finalizedAt DateTime?
|
||||
paidAt DateTime?
|
||||
voidedAt DateTime?
|
||||
markedUncollectibleAt DateTime?
|
||||
billingName String?
|
||||
billingEmail String?
|
||||
billingAddress Json?
|
||||
providerInvoiceId String?
|
||||
paymentProvider PaymentProvider?
|
||||
isSubscriptionBlocking Boolean @default(false)
|
||||
adminReason String?
|
||||
metadata Json @default("{}")
|
||||
createdByAdminId String?
|
||||
lineItems BillingInvoiceLineItem[]
|
||||
paymentIntents BillingPaymentIntent[]
|
||||
paymentAttempts BillingPaymentAttempt[]
|
||||
taxRecords BillingTaxRecord[]
|
||||
creditNotes BillingCreditNote[]
|
||||
refunds BillingRefund[]
|
||||
events BillingEvent[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
BillingCreditLedgerEntry BillingCreditLedgerEntry[]
|
||||
|
||||
@@index([billingAccountId])
|
||||
@@index([companyId])
|
||||
@@index([subscriptionId])
|
||||
@@map("billing_invoices")
|
||||
}
|
||||
|
||||
model BillingInvoiceLineItem {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
invoice BillingInvoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
||||
subscriptionId String?
|
||||
plan Plan?
|
||||
type BillingLineItemType
|
||||
description String
|
||||
quantity Int @default(1)
|
||||
unitAmount Int
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
periodStart DateTime?
|
||||
periodEnd DateTime?
|
||||
metadata Json @default("{}")
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([invoiceId])
|
||||
@@map("billing_invoice_line_items")
|
||||
}
|
||||
|
||||
model BillingPaymentIntent {
|
||||
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)
|
||||
paymentMethodId String?
|
||||
paymentMethod BillingPaymentMethod? @relation(fields: [paymentMethodId], references: [id])
|
||||
providerPaymentIntentId String?
|
||||
status BillingPaymentIntentStatus @default(REQUIRES_PAYMENT_METHOD)
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
metadata Json @default("{}")
|
||||
paymentAttempts BillingPaymentAttempt[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([invoiceId])
|
||||
@@index([billingAccountId])
|
||||
@@map("billing_payment_intents")
|
||||
}
|
||||
|
||||
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[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([invoiceId])
|
||||
@@index([billingAccountId])
|
||||
@@map("billing_payment_attempts")
|
||||
}
|
||||
|
||||
model BillingCreditBalance {
|
||||
id String @id @default(cuid())
|
||||
billingAccountId String
|
||||
billingAccount BillingAccount @relation(fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
currency String @default("MAD")
|
||||
balanceAmount Int @default(0)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([billingAccountId, currency])
|
||||
@@map("billing_credit_balances")
|
||||
}
|
||||
|
||||
model BillingCreditLedgerEntry {
|
||||
id String @id @default(cuid())
|
||||
billingAccountId String
|
||||
billingAccount BillingAccount @relation(fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
invoiceId String?
|
||||
invoice BillingInvoice? @relation(fields: [invoiceId], references: [id], onDelete: SetNull)
|
||||
type String
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
reason String
|
||||
createdBy String?
|
||||
metadata Json @default("{}")
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([billingAccountId])
|
||||
@@map("billing_credit_ledger_entries")
|
||||
}
|
||||
|
||||
model BillingCreditNote {
|
||||
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)
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
reason String
|
||||
status BillingCreditNoteStatus @default(ISSUED)
|
||||
createdBy String?
|
||||
metadata Json @default("{}")
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([invoiceId])
|
||||
@@index([billingAccountId])
|
||||
@@map("billing_credit_notes")
|
||||
}
|
||||
|
||||
model BillingRefund {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
invoice BillingInvoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
||||
paymentAttemptId String?
|
||||
paymentAttempt BillingPaymentAttempt? @relation(fields: [paymentAttemptId], references: [id], onDelete: SetNull)
|
||||
billingAccountId String
|
||||
billingAccount BillingAccount @relation(fields: [billingAccountId], references: [id], onDelete: Cascade)
|
||||
amount Int
|
||||
currency String @default("MAD")
|
||||
reason String
|
||||
status BillingRefundStatus @default(PENDING)
|
||||
providerRefundId String?
|
||||
createdBy String?
|
||||
metadata Json @default("{}")
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([invoiceId])
|
||||
@@index([billingAccountId])
|
||||
@@map("billing_refunds")
|
||||
}
|
||||
|
||||
model BillingTaxRecord {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
invoice BillingInvoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
||||
jurisdiction String?
|
||||
taxRate Float?
|
||||
taxAmount Int
|
||||
taxType String?
|
||||
taxExempt Boolean @default(false)
|
||||
exemptionReason String?
|
||||
providerTaxId String?
|
||||
metadata Json @default("{}")
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([invoiceId])
|
||||
@@map("billing_tax_records")
|
||||
}
|
||||
|
||||
model BillingEvent {
|
||||
id String @id @default(cuid())
|
||||
billingAccountId String?
|
||||
billingAccount BillingAccount? @relation(fields: [billingAccountId], references: [id], onDelete: SetNull)
|
||||
invoiceId String?
|
||||
invoice BillingInvoice? @relation(fields: [invoiceId], references: [id], onDelete: SetNull)
|
||||
subscriptionId String?
|
||||
subscription Subscription? @relation(fields: [subscriptionId], references: [id], onDelete: SetNull)
|
||||
companyId String?
|
||||
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
|
||||
eventType String
|
||||
source String
|
||||
payload Json @default("{}")
|
||||
occurredAt DateTime
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([billingAccountId])
|
||||
@@index([invoiceId])
|
||||
@@index([subscriptionId])
|
||||
@@index([companyId])
|
||||
@@map("billing_events")
|
||||
}
|
||||
|
||||
model PaymentAttempt {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
@@ -450,19 +858,19 @@ model PaymentAttempt {
|
||||
}
|
||||
|
||||
model BrandSettings {
|
||||
id String @id @default(cuid())
|
||||
companyId String @unique
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
id String @id @default(cuid())
|
||||
companyId String @unique
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
displayName String
|
||||
tagline String?
|
||||
logoUrl String?
|
||||
faviconUrl String?
|
||||
heroImageUrl String?
|
||||
primaryColor String @default("#1A56DB")
|
||||
accentColor String @default("#F59E0B")
|
||||
subdomain String @unique
|
||||
customDomain String? @unique
|
||||
customDomainVerified Boolean @default(false)
|
||||
primaryColor String @default("#1A56DB")
|
||||
accentColor String @default("#F59E0B")
|
||||
subdomain String @unique
|
||||
customDomain String? @unique
|
||||
customDomainVerified Boolean @default(false)
|
||||
customDomainAddedAt DateTime?
|
||||
publicEmail String?
|
||||
publicPhone String?
|
||||
@@ -473,17 +881,17 @@ model BrandSettings {
|
||||
whatsappNumber String?
|
||||
facebookUrl String?
|
||||
instagramUrl String?
|
||||
defaultLocale String @default("en")
|
||||
defaultCurrency String @default("MAD")
|
||||
defaultLocale String @default("en")
|
||||
defaultCurrency String @default("MAD")
|
||||
amanpayMerchantId String?
|
||||
amanpaySecretKey String?
|
||||
paypalEmail String?
|
||||
paypalMerchantId String?
|
||||
paymentMethodsEnabled PaymentProvider[]
|
||||
isListedOnMarketplace Boolean @default(true)
|
||||
isListedOnMarketplace Boolean @default(true)
|
||||
marketplaceRating Float?
|
||||
homePageConfig Json? @map("home_page_config")
|
||||
menuConfig Json? @map("menu_config")
|
||||
homePageConfig Json? @map("home_page_config")
|
||||
menuConfig Json? @map("menu_config")
|
||||
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -491,20 +899,20 @@ model BrandSettings {
|
||||
}
|
||||
|
||||
model Employee {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
clerkUserId String @unique
|
||||
firstName String
|
||||
lastName String
|
||||
email String
|
||||
phone String?
|
||||
passwordHash String?
|
||||
passwordResetToken String? @unique
|
||||
passwordResetExpiresAt DateTime?
|
||||
role EmployeeRole @default(AGENT)
|
||||
preferredLanguage String @default("en")
|
||||
isActive Boolean @default(true)
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
clerkUserId String @unique
|
||||
firstName String
|
||||
lastName String
|
||||
email String
|
||||
phone String?
|
||||
passwordHash String?
|
||||
passwordResetToken String? @unique
|
||||
passwordResetExpiresAt DateTime?
|
||||
role EmployeeRole @default(AGENT)
|
||||
preferredLanguage String @default("en")
|
||||
isActive Boolean @default(true)
|
||||
|
||||
notifications Notification[] @relation("EmployeeNotifications")
|
||||
notificationPreferences NotificationPreference[]
|
||||
@@ -517,34 +925,34 @@ model Employee {
|
||||
}
|
||||
|
||||
model Vehicle {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
make String
|
||||
model String
|
||||
year Int
|
||||
color String
|
||||
licensePlate String
|
||||
vin String?
|
||||
category VehicleCategory @default(ECONOMY)
|
||||
seats Int @default(5)
|
||||
transmission Transmission @default(AUTOMATIC)
|
||||
fuelType FuelType @default(GASOLINE)
|
||||
features String[]
|
||||
dailyRate Int
|
||||
status VehicleStatus @default(AVAILABLE)
|
||||
photos String[]
|
||||
mileage Int?
|
||||
notes String?
|
||||
isPublished Boolean @default(true)
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
make String
|
||||
model String
|
||||
year Int
|
||||
color String
|
||||
licensePlate String
|
||||
vin String?
|
||||
category VehicleCategory @default(ECONOMY)
|
||||
seats Int @default(5)
|
||||
transmission Transmission @default(AUTOMATIC)
|
||||
fuelType FuelType @default(GASOLINE)
|
||||
features String[]
|
||||
dailyRate Int
|
||||
status VehicleStatus @default(AVAILABLE)
|
||||
photos String[]
|
||||
mileage Int?
|
||||
notes String?
|
||||
isPublished Boolean @default(true)
|
||||
pickupLocations String[] @default([])
|
||||
allowDifferentDropoff Boolean @default(false)
|
||||
dropoffLocations String[] @default([])
|
||||
|
||||
reservations Reservation[]
|
||||
maintenance MaintenanceLog[]
|
||||
offerVehicles OfferVehicle[]
|
||||
calendarBlocks VehicleCalendarBlock[]
|
||||
reservations Reservation[]
|
||||
maintenance MaintenanceLog[]
|
||||
offerVehicles OfferVehicle[]
|
||||
calendarBlocks VehicleCalendarBlock[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -556,28 +964,28 @@ model Vehicle {
|
||||
}
|
||||
|
||||
model Offer {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
title String
|
||||
description String?
|
||||
termsAndConds String?
|
||||
imageUrl String?
|
||||
type OfferType
|
||||
discountValue Int
|
||||
specialRate Int?
|
||||
appliesToAll Boolean @default(true)
|
||||
categories VehicleCategory[]
|
||||
minRentalDays Int?
|
||||
maxRentalDays Int?
|
||||
promoCode String? @unique
|
||||
maxRedemptions Int?
|
||||
redemptionCount Int @default(0)
|
||||
validFrom DateTime
|
||||
validUntil DateTime
|
||||
isActive Boolean @default(true)
|
||||
isPublic Boolean @default(true)
|
||||
isFeatured Boolean @default(false)
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
title String
|
||||
description String?
|
||||
termsAndConds String?
|
||||
imageUrl String?
|
||||
type OfferType
|
||||
discountValue Int
|
||||
specialRate Int?
|
||||
appliesToAll Boolean @default(true)
|
||||
categories VehicleCategory[]
|
||||
minRentalDays Int?
|
||||
maxRentalDays Int?
|
||||
promoCode String? @unique
|
||||
maxRedemptions Int?
|
||||
redemptionCount Int @default(0)
|
||||
validFrom DateTime
|
||||
validUntil DateTime
|
||||
isActive Boolean @default(true)
|
||||
isPublic Boolean @default(true)
|
||||
isFeatured Boolean @default(false)
|
||||
|
||||
vehicles OfferVehicle[]
|
||||
reservations Reservation[]
|
||||
@@ -621,10 +1029,10 @@ model Renter {
|
||||
phoneVerified Boolean @default(false)
|
||||
isActive Boolean @default(true)
|
||||
|
||||
reservations Reservation[] @relation("RenterReservations")
|
||||
reservations Reservation[] @relation("RenterReservations")
|
||||
savedCompanies RenterSavedCompany[]
|
||||
reviews Review[]
|
||||
notifications Notification[] @relation("RenterNotifications")
|
||||
notifications Notification[] @relation("RenterNotifications")
|
||||
notificationPreferences NotificationPreference[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
@@ -635,7 +1043,7 @@ model Renter {
|
||||
|
||||
model RenterSavedCompany {
|
||||
renterId String
|
||||
renter Renter @relation(fields: [renterId], references: [id], onDelete: Cascade)
|
||||
renter Renter @relation(fields: [renterId], references: [id], onDelete: Cascade)
|
||||
companyId String
|
||||
savedAt DateTime @default(now())
|
||||
|
||||
@@ -684,52 +1092,52 @@ model Customer {
|
||||
}
|
||||
|
||||
model Reservation {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
vehicleId String
|
||||
vehicle Vehicle @relation(fields: [vehicleId], references: [id])
|
||||
customerId String
|
||||
customer Customer @relation(fields: [customerId], references: [id])
|
||||
renterId String?
|
||||
renter Renter? @relation("RenterReservations", fields: [renterId], references: [id])
|
||||
offerId String?
|
||||
offer Offer? @relation(fields: [offerId], references: [id])
|
||||
promoCodeUsed String?
|
||||
vehicleCategory VehicleCategory?
|
||||
source BookingSource @default(DASHBOARD)
|
||||
marketplaceRef String?
|
||||
status ReservationStatus @default(DRAFT)
|
||||
startDate DateTime
|
||||
endDate DateTime
|
||||
pickupLocation String?
|
||||
returnLocation String?
|
||||
dailyRate Int
|
||||
discountAmount Int @default(0)
|
||||
totalDays Int
|
||||
totalAmount Int
|
||||
depositAmount Int @default(0)
|
||||
paymentStatus String @default("UNPAID")
|
||||
paidAmount Int @default(0)
|
||||
checkedInAt DateTime?
|
||||
checkedOutAt DateTime?
|
||||
checkInMileage Int?
|
||||
checkOutMileage Int?
|
||||
notes String?
|
||||
cancelReason String?
|
||||
cancelledBy CancelledBy?
|
||||
contractNumber String? @unique
|
||||
invoiceNumber String? @unique
|
||||
reviewToken String? @unique
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
vehicleId String
|
||||
vehicle Vehicle @relation(fields: [vehicleId], references: [id])
|
||||
customerId String
|
||||
customer Customer @relation(fields: [customerId], references: [id])
|
||||
renterId String?
|
||||
renter Renter? @relation("RenterReservations", fields: [renterId], references: [id])
|
||||
offerId String?
|
||||
offer Offer? @relation(fields: [offerId], references: [id])
|
||||
promoCodeUsed String?
|
||||
vehicleCategory VehicleCategory?
|
||||
source BookingSource @default(DASHBOARD)
|
||||
marketplaceRef String?
|
||||
status ReservationStatus @default(DRAFT)
|
||||
startDate DateTime
|
||||
endDate DateTime
|
||||
pickupLocation String?
|
||||
returnLocation String?
|
||||
dailyRate Int
|
||||
discountAmount Int @default(0)
|
||||
totalDays Int
|
||||
totalAmount Int
|
||||
depositAmount Int @default(0)
|
||||
paymentStatus String @default("UNPAID")
|
||||
paidAmount Int @default(0)
|
||||
checkedInAt DateTime?
|
||||
checkedOutAt DateTime?
|
||||
checkInMileage Int?
|
||||
checkOutMileage Int?
|
||||
notes String?
|
||||
cancelReason String?
|
||||
cancelledBy CancelledBy?
|
||||
contractNumber String? @unique
|
||||
invoiceNumber String? @unique
|
||||
reviewToken String? @unique
|
||||
checkInFuelLevel String?
|
||||
checkOutFuelLevel String?
|
||||
|
||||
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[]
|
||||
@@ -843,9 +1251,9 @@ model NotificationPreference {
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
model MaintenanceLog {
|
||||
id String @id @default(cuid())
|
||||
id String @id @default(cuid())
|
||||
vehicleId String
|
||||
vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
|
||||
type String
|
||||
description String?
|
||||
cost Int?
|
||||
@@ -882,37 +1290,37 @@ model VehicleCalendarBlock {
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
model ContractSettings {
|
||||
id String @id @default(cuid())
|
||||
companyId String @unique
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
legalName String?
|
||||
registrationNumber String?
|
||||
taxId String?
|
||||
terms String @default("")
|
||||
fuelPolicy String @default("The vehicle must be returned with the same fuel level as at pickup.")
|
||||
depositPolicy String @default("The security deposit is refundable within 7 days after return, subject to vehicle inspection.")
|
||||
lateFeePolicy String @default("Late returns will incur a charge of 1 additional day rate per hour of delay.")
|
||||
damagePolicy String @default("The renter is liable for any damage not covered by insurance.")
|
||||
additionalClauses String[] @default([])
|
||||
signatureRequired Boolean @default(true)
|
||||
contractFooterNote String?
|
||||
invoiceFooterNote String?
|
||||
showTax Boolean @default(false)
|
||||
taxRate Float?
|
||||
taxLabel String?
|
||||
contractPrefix String @default("CNT")
|
||||
invoicePrefix String @default("INV")
|
||||
fuelPolicyType FuelPolicyType @default(FULL_TO_FULL)
|
||||
fuelPolicyNote String?
|
||||
fuelChargePerLiter Int?
|
||||
fuelShortfallFee Int?
|
||||
lateFeePerHour Int?
|
||||
taxLines Json?
|
||||
lastContractSeq Int @default(0)
|
||||
lastInvoiceSeq Int @default(0)
|
||||
additionalDriverCharge AdditionalDriverCharge @default(FREE)
|
||||
additionalDriverDailyRate Int @default(0)
|
||||
additionalDriverFlatRate Int @default(0)
|
||||
id String @id @default(cuid())
|
||||
companyId String @unique
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
legalName String?
|
||||
registrationNumber String?
|
||||
taxId String?
|
||||
terms String @default("")
|
||||
fuelPolicy String @default("The vehicle must be returned with the same fuel level as at pickup.")
|
||||
depositPolicy String @default("The security deposit is refundable within 7 days after return, subject to vehicle inspection.")
|
||||
lateFeePolicy String @default("Late returns will incur a charge of 1 additional day rate per hour of delay.")
|
||||
damagePolicy String @default("The renter is liable for any damage not covered by insurance.")
|
||||
additionalClauses String[] @default([])
|
||||
signatureRequired Boolean @default(true)
|
||||
contractFooterNote String?
|
||||
invoiceFooterNote String?
|
||||
showTax Boolean @default(false)
|
||||
taxRate Float?
|
||||
taxLabel String?
|
||||
contractPrefix String @default("CNT")
|
||||
invoicePrefix String @default("INV")
|
||||
fuelPolicyType FuelPolicyType @default(FULL_TO_FULL)
|
||||
fuelPolicyNote String?
|
||||
fuelChargePerLiter Int?
|
||||
fuelShortfallFee Int?
|
||||
lateFeePerHour Int?
|
||||
taxLines Json?
|
||||
lastContractSeq Int @default(0)
|
||||
lastInvoiceSeq Int @default(0)
|
||||
additionalDriverCharge AdditionalDriverCharge @default(FREE)
|
||||
additionalDriverDailyRate Int @default(0)
|
||||
additionalDriverFlatRate Int @default(0)
|
||||
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -1046,16 +1454,16 @@ model DamageInspection {
|
||||
}
|
||||
|
||||
model DamagePoint {
|
||||
id String @id @default(cuid())
|
||||
inspectionId String
|
||||
inspection DamageInspection @relation(fields: [inspectionId], references: [id], onDelete: Cascade)
|
||||
viewType DiagramView
|
||||
x Float
|
||||
y Float
|
||||
damageType DamageType
|
||||
severity DamageSeverity @default(MINOR)
|
||||
description String?
|
||||
isPreExisting Boolean @default(false)
|
||||
id String @id @default(cuid())
|
||||
inspectionId String
|
||||
inspection DamageInspection @relation(fields: [inspectionId], references: [id], onDelete: Cascade)
|
||||
viewType DiagramView
|
||||
x Float
|
||||
y Float
|
||||
damageType DamageType
|
||||
severity DamageSeverity @default(MINOR)
|
||||
description String?
|
||||
isPreExisting Boolean @default(false)
|
||||
|
||||
@@index([inspectionId])
|
||||
@@map("damage_points")
|
||||
@@ -1168,7 +1576,7 @@ model AuditLog {
|
||||
}
|
||||
|
||||
model PricingConfig {
|
||||
id String @id @default(cuid())
|
||||
id String @id @default(cuid())
|
||||
plan String
|
||||
billingPeriod String
|
||||
amount Int
|
||||
@@ -1197,10 +1605,10 @@ model PricingPromotion {
|
||||
code String @unique
|
||||
name String
|
||||
description String?
|
||||
discountType String // 'PERCENTAGE' | 'FIXED'
|
||||
discountValue Int // percentage (1-100) or centimes for FIXED
|
||||
plans String[] // empty array = all plans
|
||||
periods String[] // empty array = all periods
|
||||
discountType String // 'PERCENTAGE' | 'FIXED'
|
||||
discountValue Int // percentage (1-100) or centimes for FIXED
|
||||
plans String[] // empty array = all plans
|
||||
periods String[] // empty array = all periods
|
||||
maxUses Int?
|
||||
usedCount Int @default(0)
|
||||
validFrom DateTime
|
||||
|
||||
Reference in New Issue
Block a user