Skip to content

Invoice Models

This reference documents all Twig-accessible properties and methods for invoice-related models. All prices are stored as integers in base currency units (cents) — use the |currency filter for display.

Invoices are accounting ledgers — they are designed for manual entry and administrative overrides. They can be created manually or generated from orders. Unlike orders, invoices use a simplified pricing model: discounts are stored as line-level totals (like Xero), not per-unit values, and there are no tax-inclusive/exclusive discount variants. This keeps the invoice straightforward for bookkeeping purposes.

For the computed order model with price rules and per-unit tax variants, see Order Models.

Invoice

The Invoice model represents a billable document with line items, tax, and payment tracking.

Core Properties

PropertyTypeDescription
idintPrimary key
hashstringUnique lookup hash
invoice_numberstringFormatted invoice number (with prefix)
user_ipstringCustomer IP address at creation
currency_codestringThree-letter currency code (locked at creation)
is_throwawayboolTemporary invoice (not yet finalized)
invoiced_atCarbonInvoice date (sent_at or created_at)
sent_atCarbon|nullWhen invoice was sent
due_atCarbon|nullPayment due date
created_atCarbonCreation date
updated_atCarbonLast update date

Financial Properties

All prices are stored as integers in base currency units (cents).

PropertyTypeDescription
subtotalintItems subtotal after discounts: sum(qty × price - discount)
original_subtotalintPre-discount subtotal: subtotal + discount
final_subtotalintDisplay subtotal. Tax-inclusive: subtotal. Tax-exclusive: subtotal + tax
discountintTotal discount across all items (excluding tax)
discount_taxintTax portion of the total discount
final_discountintTotal discount with tax: discount + discount_tax
taxintTotal sales tax (gross, before discount adjustment)
total_taxintNet tax: tax - discount_tax
totalintFinal invoice total: final_subtotal
credit_appliedintStore credit applied to this invoice
amount_dueintOutstanding amount after credit: max(0, total - credit_applied)
taxesarrayBreakdown of tax rates applied

Tax Properties

PropertyTypeDescription
is_tax_exemptboolWhether the invoice is tax exempt
prices_include_taxboolWhether prices were entered with tax included

The tax breakdown array contains objects with name (tax class name) and total (tax amount in cents):

twig
{% for tax in invoice.taxes %}
    <tr>
        <td>{{ tax.name }}</td>
        <td>{{ tax.total|currency({ in: invoice.currency_code }) }}</td>
    </tr>
{% endfor %}

Status Properties

PropertyTypeDescription
statusInvoiceStatusCurrent status model
status_codestringStatus code shortcut
status_updated_atCarbonWhen status last changed
is_paidboolWhether payment has been processed
is_payment_submittedboolWhether payment was submitted (paid or pending capture)
is_past_due_dateboolWhether the due date has passed

Contact Properties

PropertyTypeDescription
first_namestringFirst name
last_namestringLast name
emailstringEmail address
phonestringPhone number
companystringCompany name
tax_id_numberstringVAT/Tax ID
address_line1stringStreet address
address_line2stringAddress line 2
street_addressstringCombined line 1 + line 2
citystringCity
zipstringPostal/ZIP code
stateStateState/province model
countryCountryCountry model

Relationships

PropertyTypeDescription
userUserCustomer account
itemsCollection<InvoiceItem>Line items
status_logCollection<InvoiceStatusLog>Status change history
payment_logCollection<InvoicePaymentLog>Payment transaction log
payment_methodPaymentMethodPayment method used
templateInvoiceTemplateInvoice template for rendering
relatedModelPolymorphic related object (e.g., Order)
credit_notes_fromCollection<CreditNote>Credit/debit notes linked to this invoice

Methods

MethodReturnsDescription
isPaymentProcessed()boolCheck if payment is complete
getCurrencyObject()CurrencyCurrency model for this invoice
getTaxableAddress()TaxLocationAddress used for tax calculation
convertToPermanent()voidConvert a throwaway invoice to permanent
submitManualPayment($comment)InvoiceRecord a manual payment

Static Methods

MethodReturnsDescription
findByInvoiceHash($hash)Invoice|nullLook up invoice by hash
makeThrowaway($user)InvoiceCreate a temporary invoice
makeForUser($user)InvoiceCreate an invoice pre-filled with user details

Complete Example

twig
<div class="invoice-detail">
    <h2>Invoice #{{ invoice.invoice_number }}</h2>
    <p>Date: {{ invoice.invoiced_at|date('M d, Y') }}</p>
    {% if invoice.due_at %}
        <p>Due: {{ invoice.due_at|date('M d, Y') }}</p>
    {% endif %}

    {# Items #}
    <table>
        <thead>
            <tr>
                <th>Description</th>
                <th>Qty</th>
                <th>Price</th>
                <th>Discount</th>
                <th>Tax</th>
                <th>Total</th>
            </tr>
        </thead>
        <tbody>
            {% for item in invoice.items %}
                <tr>
                    <td>{{ item.description }}</td>
                    <td>{{ item.quantity }}</td>
                    <td>{{ item.price|currency({ in: invoice.currency_code }) }}</td>
                    <td>{{ item.discount|currency({ in: invoice.currency_code }) }}</td>
                    <td>{{ item.tax|currency({ in: invoice.currency_code }) }}</td>
                    <td>{{ item.total|currency({ in: invoice.currency_code }) }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>

    {# Totals #}
    <dl>
        <dt>Subtotal</dt>
        <dd>{{ invoice.subtotal|currency({ in: invoice.currency_code }) }}</dd>

        {% for tax in invoice.taxes %}
            <dt>{{ tax.name }}</dt>
            <dd>{{ tax.total|currency({ in: invoice.currency_code }) }}</dd>
        {% endfor %}

        <dt><strong>Total</strong></dt>
        <dd>
            <strong>
                {{ invoice.total|currency({ in: invoice.currency_code }) }}
            </strong>
        </dd>

        {% if invoice.credit_applied > 0 %}
            <dt>Store Credit</dt>
            <dd>-{{ invoice.credit_applied|currency({ in: invoice.currency_code }) }}</dd>

            <dt><strong>Amount Due</strong></dt>
            <dd>
                <strong>
                    {{ invoice.amount_due|currency({ in: invoice.currency_code }) }}
                </strong>
            </dd>
        {% endif %}
    </dl>

    {# Payment Status #}
    {% if invoice.is_paid %}
        <span class="badge bg-success">Paid</span>
    {% elseif invoice.is_past_due_date %}
        <span class="badge bg-danger">Past Due</span>
    {% else %}
        <span class="badge bg-warning">Unpaid</span>
    {% endif %}
</div>

InvoiceItem

Each line item within an invoice. Unlike order items, invoice items use a simplified pricing model — discounts are stored as line-level totals (the total discount for the entire row), not per-unit values. This matches the convention used by accounting software like Xero.

Price Properties (Per-Unit)

PropertyTypeDescription
priceintPer-unit price (base price entered by admin)
price_less_taxintPer-unit price excluding tax
price_with_taxintPer-unit price including tax

Price Properties (Line-Level)

PropertyTypeDescription
discountintLine discount — the total discount for the entire row, not per-unit
taxintLine tax: (unit_tax × quantity) - discount_tax
subtotalintLine subtotal: quantity × price - discount
totalintLine total: subtotal + tax

Other Properties

PropertyTypeDescription
idintPrimary key
descriptionstringLine item description
quantityintQuantity
sort_orderintDisplay order
created_atCarbonCreation date
updated_atCarbonLast update date

Relationships

PropertyTypeDescription
invoiceInvoiceParent invoice
tax_classTaxTax class for this item
relatedModelPolymorphic related object

Discount Input

When setting the discount field, special formats are supported:

InputBehavior
500Sets a $5.00 line discount
-500Negative sign is stripped, treated as 500
10%Calculates 10% of quantity × price as the discount

Example: Simple Invoice Table

twig
<table>
    <thead>
        <tr>
            <th>Item</th>
            <th>Price</th>
            <th>Discount</th>
            <th>Tax</th>
            <th>Total</th>
        </tr>
    </thead>
    <tbody>
        {% for item in invoice.items %}
            <tr>
                <td>{{ item.quantity }}x {{ item.description }}</td>
                <td>{{ item.price|currency({ in: invoice.currency_code }) }}</td>
                <td>{{ item.discount|currency({ in: invoice.currency_code }) }}</td>
                <td>{{ item.tax|currency({ in: invoice.currency_code }) }}</td>
                <td>{{ item.total|currency({ in: invoice.currency_code }) }}</td>
            </tr>
        {% endfor %}
    </tbody>
    <tfoot>
        <tr>
            <td colspan="4" class="text-end">Subtotal</td>
            <td>{{ invoice.subtotal|currency({ in: invoice.currency_code }) }}</td>
        </tr>
        {% for tax in invoice.taxes %}
            <tr>
                <td colspan="4" class="text-end">{{ tax.name }}</td>
                <td>{{ tax.total|currency({ in: invoice.currency_code }) }}</td>
            </tr>
        {% endfor %}
        <tr>
            <td colspan="4" class="text-end"><strong>Total</strong></td>
            <td>
                <strong>
                    {{ invoice.total|currency({ in: invoice.currency_code }) }}
                </strong>
            </td>
        </tr>
    </tfoot>
</table>

InvoiceStatus

Represents an invoice status in the payment workflow.

Properties

PropertyTypeDescription
idintPrimary key
namestringDisplay name
codestringUnique code identifier

Constants

ConstantValueDescription
STATUS_DRAFTdraftInvoice created, not yet sent
STATUS_APPROVEDapprovedApproved for payment
STATUS_PAIDpaidPayment received
STATUS_VOIDvoidInvoice voided
STATUS_REFUNDEDrefundedPayment refunded

Static Helpers

MethodReturnsDescription
getNewStatus()InvoiceStatusFind the default status for new invoices

InvoiceStatusLog

A record of each status change on an invoice.

Properties

PropertyTypeDescription
idintPrimary key
commentstring|nullComment added with the status change
created_atCarbonWhen the status change occurred

Relationships

PropertyTypeDescription
statusInvoiceStatusThe status that was applied
invoiceInvoiceThe invoice