Skip to content

Latest commit

 

History

History
153 lines (111 loc) · 6.24 KB

File metadata and controls

153 lines (111 loc) · 6.24 KB
//////////////////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FILE                                                                  //
// This file is automatically generated by ZenStack CLI and should not be manually updated. //
// Source: schema.zmodel · Generated: 2026-02-23                                            //
//////////////////////////////////////////////////////////////////////////////////////////////

Index / Models / Invoice

🗃️ Invoice Model

An invoice generated for a subscription billing cycle.

Invoices are created automatically by the billing system when a subscription renews. They can also be created manually by admins for one-off charges (e.g. overage fees, professional services).

The paidAt timestamp is set when payment is confirmed via the Stripe invoice.payment_succeeded webhook. Invoices without paidAt are considered outstanding.

Category: Billing · Since: 2.0 · Defined in: billing.zmodel


Declaration · billing.zmodel
model Invoice with Timestamps {
    id                String       @id @default(cuid())
    invoiceNumber     String       @unique @meta('doc:example', 'INV-2025-0042')
    amountCents       Int
    currency          String       @default("usd") @length(3, 3) @lower
    paidAt            DateTime?
    lastPaymentAttempt DateTime?
    paymentAttempts   Int          @default(0)
    stripeInvoiceId   String?      @unique @meta('doc:example', 'in_1NqOBcLkdIwHu7ixBIGPr4Z3')
    memo              String?
    subscription      Subscription @relation(fields: [subscriptionId], references: [id])
    subscriptionId    String

    @@allow('read', subscription.workspace.members?[userId == auth().id])
    @@deny('update', paidAt != null)
    @@deny('delete', true)
    @@index([subscriptionId])
    @@index([invoiceNumber])
    @@validate(amountCents > 0, "Invoice amount must be positive")
    @@validate(paymentAttempts >= 0 && paymentAttempts <= 10, "Payment attempts must be between 0 and 10")
    @@meta('doc:category', 'Billing')
    @@meta('doc:since', '2.0')
}

On this page: Mixins · Fields · Relationships · Access Policies · Indexes · Validation Rules

🧩 Mixins

Reusable field groups mixed into this model.

📋 Fields

All fields defined on this entity, including inherited fields from mixins and parent models.

Field Type Required Default Attributes Source Description
createdAt DateTime Yes now() Timestamps When the record was first created. Immutable after insert.
updatedAt DateTime Yes @updatedAt Timestamps When the record was last modified. Updated automatically.
id String Yes cuid() @id
invoiceNumber String Yes @unique Example: INV-2025-0042 Sequential invoice number within the workspace, formatted as
INV-YYYY-NNNN (e.g. INV-2025-0042).
amountCents Int Yes Invoice amount in the smallest currency unit.
currency String Yes "usd" @length(3, 3), @lower ISO 4217 currency code matching the subscription currency.
paidAt DateTime? No When the invoice was fully paid. Null if outstanding or failed.
lastPaymentAttempt DateTime? No When the invoice payment was last attempted. Used to prevent
retrying too frequently.
paymentAttempts Int Yes 0 Number of times payment has been attempted. Capped at 10 retries.
stripeInvoiceId String? No @unique Example: in_1NqOBcLkdIwHu7ixBIGPr4Z3 Stripe invoice ID for reconciliation.
memo String? No Optional human-readable memo attached to the invoice.
subscription Subscription Yes @relation(fields: [subscriptionId], references: [id])
subscriptionId String Yes

🔗 Relationships

Foreign key relationships to other models in the schema.

Field Related Model Type
subscription Subscription Many→One

diagram

🔐 Access Policies

ZenStack access control rules that determine who can read, create, update, or delete records.

Important

Operations are denied by default. @@allow rules grant access; @@deny rules override any allow.

Operation Rule Effect
read subscription.workspace.members?[userId == auth().id] Allow
update paidAt != null Deny
delete true Deny

📇 Indexes

Database indexes defined on this model for query performance.

Fields Type
[subscriptionId] Index
[invoiceNumber] Index

✅ Validation Rules

Field-level and model-level validation constraints enforced at the ORM layer.

Field Rule
currency @length
currency @lower
Model amountCents > 0Invoice amount must be positive
Model paymentAttempts >= 0 && paymentAttempts <= 10Payment attempts must be between 0 and 10

📚 References


Previous: Comment · Next: Notification