Skip to content

Order Models

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

Orders are computed records — their totals are calculated from cart items, price rules, tax classes, and shipping methods. Prices are stored per-unit with separate tax-inclusive and tax-exclusive variants to support both pricing modes. Discounts are tracked per-unit (from price rules) with an additional line_discount field for rounding-safe line totals.

Orders are typically accessed through the user relationship (user.orders) or the Checkout component during order placement. For the simpler accounting-oriented model, see Invoice Models.

Order

The Order model represents a completed or in-progress customer order.

Core Properties

PropertyTypeDescription
idintPrimary key
baseidstringBase identifier (used as order_hash)
order_numberintSame as id
order_hashstringSame as baseid
user_ipstringCustomer IP address
user_notesstringCustomer-provided notes
ordered_atCarbonWhen the order was placed
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, before tax and shipping. Formula: sum(qty × original_price - line_discount)
original_subtotalintPre-discount subtotal: subtotal + discount
final_subtotalintDisplay subtotal. Tax-inclusive: subtotal. Tax-exclusive: subtotal + sales_tax
discountintTotal discount amount across all items (excluding tax)
discount_taxintTax portion of the total discount
final_discountintTotal discount with tax: discount + discount_tax
shipping_quoteintShipping cost (excluding tax)
shipping_taxintTax on shipping
final_shipping_quoteintDisplay shipping. Tax-inclusive: shipping_quote. Tax-exclusive: shipping_quote + shipping_tax. Free: 0
shipping_is_freeboolWhether shipping is free (from price rules)
sales_taxintTax on product items (excludes shipping tax)
total_taxintTotal tax: sales_tax + shipping_tax - discount_tax
totalintFinal order total: final_subtotal + final_shipping_quote
total_costintTotal cost of goods: sum(qty × cost)
credit_appliedintStore credit applied to this order (delegated from invoice)
amount_dueintOutstanding amount after credit: max(0, total - credit_applied)

Tax Properties

PropertyTypeDescription
is_tax_exemptboolWhether the order is tax exempt
prices_include_taxboolWhether prices were stored with tax included
sales_taxesarrayBreakdown of sales tax rates
shipping_taxesarrayBreakdown of shipping tax rates
all_taxesarrayCombined sales and shipping tax breakdown

The tax breakdown arrays contain objects with name (tax class name) and amount (tax in cents):

twig
{% for tax in order.all_taxes %}
    <tr>
        <td>{{ tax.name }}</td>
        <td>{{ tax.amount|currency }}</td>
    </tr>
{% endfor %}

Status Properties

PropertyTypeDescription
statusOrderStatusCurrent status model
status_updated_atCarbonWhen status last changed
is_paidboolWhether the order status is "paid" or payment is processed
is_cancelledboolWhether the order status is "cancelled"
is_refundedboolWhether the order status is "refunded"

The status object has these properties:

PropertyTypeDescription
status.namestringStatus display name (e.g., "New", "Paid")
status.codestringStatus code (e.g., new, paid)
status.color_backgroundstringBadge background color
status.color_foregroundstringBadge text color
twig
<span style="background: {{ order.status.color_background }};
             color: {{ order.status.color_foreground }}">
    {{ order.status.name }}
</span>

Payment Properties

PropertyTypeDescription
is_payment_processedboolWhether payment has been received
payment_processed_atCarbon|nullWhen payment was processed
payment_methodPaymentMethodPayment method used
is_finalboolWhether the order is finalized

Shipping Properties

PropertyTypeDescription
shipping_methodShippingMethodShipping method used
shipping_child_optionstringSelected sub-option (e.g., "Express")
is_shippedboolWhether any tracking codes exist

Billing Address

PropertyTypeDescription
billing_first_namestringFirst name
billing_last_namestringLast name
billing_companystringCompany name
billing_emailstringEmail address
billing_phonestringPhone number
billing_address_line1stringStreet address
billing_address_line2stringAddress line 2
billing_street_addressstringCombined line 1 + line 2
billing_citystringCity
billing_zipstringPostal/ZIP code
billing_stateStateState/province model
billing_countryCountryCountry model

Shipping Address

PropertyTypeDescription
shipping_first_namestringFirst name
shipping_last_namestringLast name
shipping_companystringCompany name
shipping_phonestringPhone number
shipping_address_line1stringStreet address
shipping_address_line2stringAddress line 2
shipping_street_addressstringCombined line 1 + line 2
shipping_citystringCity
shipping_zipstringPostal/ZIP code
shipping_stateStateState/province model
shipping_countryCountryCountry model
shipping_is_businessboolBusiness address flag

Relationships

PropertyTypeDescription
userUserCustomer account
itemsCollection<OrderItem>Order line items
status_logCollection<OrderStatusLog>Status change history
notesCollection<OrderNote>Admin and customer notes
tracking_codesCollection<OrderTrackingCode>Shipment tracking codes
invoiceInvoicePrimary invoice (via Responsiv.Pay)
invoicesCollection<Invoice>All invoices
couponCoupon|nullApplied coupon
productsCollection<Product>Products (through items)

Methods

MethodReturnsDescription
isPaymentProcessed($force)boolCheck payment status ($force queries DB directly)
getLatestTrackingCode()OrderTrackingCode|nullMost recent tracking code
getCustomerVisibleNotes()Collection<OrderNote>Notes visible to customer

Static Methods

MethodReturnsDescription
findByOrderHash($hash)Order|nullLook up order by baseid

Complete Example

twig
<div class="order-detail">
    <h2>Order #{{ order.order_number }}</h2>
    <span style="background: {{ order.status.color_background }};
                 color: {{ order.status.color_foreground }};
                 padding: 2px 8px; border-radius: 4px;">
        {{ order.status.name }}
    </span>

    <p>Placed on {{ order.ordered_at|date('M d, Y') }}</p>

    {# Items #}
    <table>
        <thead>
            <tr>
                <th>Product</th>
                <th>Qty</th>
                <th>Price</th>
                <th>Total</th>
            </tr>
        </thead>
        <tbody>
            {% for item in order.items %}
                <tr>
                    <td>{{ item.outputProductName()|raw }}</td>
                    <td>{{ item.quantity }}</td>
                    <td>{{ item.display_price|currency }}</td>
                    <td>{{ item.display_line_price|currency }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>

    {# Totals #}
    <dl>
        <dt>Subtotal</dt>
        <dd>{{ order.final_subtotal|currency }}</dd>

        {% if order.final_discount > 0 %}
            <dt>Discount</dt>
            <dd>-{{ order.final_discount|currency }}</dd>
        {% endif %}

        <dt>Shipping</dt>
        <dd>
            {% if order.shipping_is_free %}
                Free
            {% else %}
                {{ order.final_shipping_quote|currency }}
            {% endif %}
        </dd>

        {% for tax in order.all_taxes %}
            <dt>{{ tax.name }}</dt>
            <dd>{{ tax.amount|currency }}</dd>
        {% endfor %}

        <dt><strong>Total</strong></dt>
        <dd><strong>{{ order.total|currency }}</strong></dd>

        {% if order.credit_applied > 0 %}
            <dt>Store Credit</dt>
            <dd>-{{ order.credit_applied|currency }}</dd>

            <dt><strong>Amount Due</strong></dt>
            <dd><strong>{{ order.amount_due|currency }}</strong></dd>
        {% endif %}
    </dl>

    {# Addresses #}
    <div class="row">
        <div class="col">
            <h4>Billing Address</h4>
            <p>
                {{ order.billing_first_name }} {{ order.billing_last_name }}<br>
                {% if order.billing_company %}{{ order.billing_company }}<br>{% endif %}
                {{ order.billing_street_address }}<br>
                {{ order.billing_city }}, {{ order.billing_state.name }}
                {{ order.billing_zip }}<br>
                {{ order.billing_country.name }}
            </p>
        </div>
        <div class="col">
            <h4>Shipping Address</h4>
            <p>
                {{ order.shipping_first_name }} {{ order.shipping_last_name }}<br>
                {% if order.shipping_company %}{{ order.shipping_company }}<br>{% endif %}
                {{ order.shipping_street_address }}<br>
                {{ order.shipping_city }}, {{ order.shipping_state.name }}
                {{ order.shipping_zip }}<br>
                {{ order.shipping_country.name }}
            </p>
        </div>
    </div>

    {# Tracking #}
    {% if order.is_shipped %}
        <h4>Shipment Tracking</h4>
        {% for code in order.tracking_codes %}
            <div>
                <strong>{{ code.carrier|upper }}</strong>:
                {% if code.tracking_url %}
                    <a href="{{ code.tracking_url }}" target="_blank">
                        {{ code.tracking_number }}
                    </a>
                {% else %}
                    {{ code.tracking_number }}
                {% endif %}
                {% if code.shipped_at %}
                    — shipped {{ code.shipped_at|date('M d, Y') }}
                {% endif %}
            </div>
        {% endfor %}
    {% endif %}

    {# Status History #}
    <h4>Status History</h4>
    {% for log in order.status_log %}
        <div>
            <strong>{{ log.status.name }}</strong>
            <span>{{ log.created_at|date('M d, Y g:ia') }}</span>
            {% if log.comment %}
                <p>{{ log.comment }}</p>
            {% endif %}
        </div>
    {% endfor %}

    {# Pay Now link for unpaid orders #}
    {% if not order.is_payment_processed %}
        <a href="{{ 'shop/payment'|page({ hash: order.order_hash }) }}"
           class="btn btn-primary">
            Pay Now
        </a>
    {% endif %}
</div>

OrderItem

Each line item within an order, representing a purchased product with its quantity, price, options, and extras.

Core Properties

PropertyTypeDescription
idintPrimary key
quantityintQuantity ordered
variant_idint|nullSelected variant ID (null if no variant)

Price Properties (Per-Unit)

All per-unit values represent a single unit. The price field stores the discounted per-unit price. Multiply by quantity for line totals — or use the computed line price properties below.

PropertyTypeDescription
priceintPer-unit price after discount (excluding tax)
price_less_taxintPer-unit price excluding tax
price_with_taxintPer-unit price including tax
discountintPer-unit discount amount (excluding tax)
discount_less_taxintPer-unit discount excluding tax
discount_with_taxintPer-unit discount including tax
line_discountintExact total line discount across all units. Avoids rounding errors when per-unit discount doesn't divide evenly
costintPer-unit cost of goods (for margin reporting)
extras_priceintPer-unit extras price (excluding tax)
extras_price_less_taxintPer-unit extras price excluding tax
extras_price_with_taxintPer-unit extras price including tax

Price Properties (Line-Level)

Line-level values represent the total for the entire row (all units combined).

PropertyTypeDescription
taxintTotal line tax: unit_tax × quantity
subtotalintLine subtotal: quantity × original_price - line_discount
totalintLine total: subtotal + tax

Computed Price Properties

These are calculated on-the-fly and not stored in the database.

Unified Vocabulary

OrderItem supports the same unified price vocabulary as Product, ProductVariant, and CartItem. For Twig templates, prefer display_price, compare_price, on_sale, display_discount, and display_line_price. See Pricing for details.

PropertyTypeDescription
display_priceintCustomer-facing unit price with tax
compare_priceintPre-discount unit price with tax (the "was" price)
on_saleboolWhether the item has a discount
display_discountintAmount saved per unit: compare_price - display_price
display_line_priceintLine total with tax: unit_line_price + tax
original_priceintPre-discount unit price: price + discount
original_line_priceintPre-discount line total: quantity × original_price
unit_priceintAlias for price
unit_line_priceintLine total after discount (no tax): quantity × original_price - line_discount
final_priceintAlias for price_with_tax
final_line_priceintAlias for display_line_price
final_discountintAlias for discount_with_tax
total_costintLine cost: quantity × cost
total_weightfloatLine weight: quantity × product.weight
total_volumefloatLine volume: quantity × product.volume

Options and Extras

PropertyTypeDescription
optionsarray<ProductOption>Selected options as ProductOption objects
extrasarray<ProductExtra>Selected extras as ProductExtra objects
options_dataarrayRaw options JSON
extras_dataarrayRaw extras JSON
discount_dataarrayApplied price rule data

Bundle Properties

PropertyTypeDescription
bundle_master_order_item_idint|nullParent bundle item ID
bundle_master_bundle_item_idint|nullBundle slot definition ID
bundle_master_bundle_item_namestring|nullBundle slot name (e.g., "Processor")

Download Properties

PropertyTypeDescription
download_keystring|nullSecure download token
download_countintNumber of downloads used
download_expires_atCarbon|nullDownload expiration date

Relationships

PropertyTypeDescription
orderOrderParent order
productProductPurchased product
variantProductVariant|nullSelected variant
tax_classTaxClassTax class
uploaded_filesCollection<File>Customer-uploaded files

Methods

MethodReturnsDescription
outputProductName($options)stringFormatted name with options, extras, and bundle info
isBundleItem()boolWhether this is a bundle child item
getMasterBundleOrderItem()OrderItem|nullParent bundle item
listBundleItems()Collection<OrderItem>Child bundle items
isDownloadable()boolWhether product has downloadable files
canDownload()boolWhether download is currently permitted
isDownloadExpired()boolWhether download link has expired
isDownloadLimitReached()boolWhether download limit is exceeded
getDownloadUrl()string|nullPublic download URL
getDownloadableFiles()Collection<File>Available files for download

outputProductName Options

The outputProductName() method accepts an options array:

OptionTypeDefaultDescription
outputNamebooltrueInclude the product name
includeTaxbooltrueShow prices with tax
plainTextboolfalsePlain text instead of HTML
extraDetailsboolfalseInclude event-based details
twig
{# HTML output with formatted options and extras #}
{{ item.outputProductName()|raw }}

{# Plain text for emails #}
{{ item.outputProductName({ plainText: true }) }}

Displaying Options and Extras

twig
{# Selected options #}
{% for option in item.options %}
    <span>{{ option.name }}: {{ option.value }}</span>
{% endfor %}

{# Selected extras #}
{% for extra in item.extras %}
    <span>+ {{ extra.description }}: {{ extra.finalPrice|currency }}</span>
{% endfor %}
twig
{% if item.isDownloadable() %}
    {% if item.canDownload() %}
        <a href="{{ item.getDownloadUrl() }}" class="btn btn-sm btn-success">
            Download
        </a>
        {% if item.download_count > 0 %}
            <small>(downloaded {{ item.download_count }} times)</small>
        {% endif %}
        {% if item.download_expires_at %}
            <small>Expires {{ item.download_expires_at|date('M d, Y') }}</small>
        {% endif %}
    {% elseif item.isDownloadExpired() %}
        <span class="text-muted">Download expired</span>
    {% elseif item.isDownloadLimitReached() %}
        <span class="text-muted">Download limit reached</span>
    {% endif %}
{% endif %}

Displaying Variant and Bundle Info

twig
{% for item in order.items %}
    <div class="{{ item.isBundleItem() ? 'bundle-child-item' }}">
        {# Bundle child slot name #}
        {% if item.bundle_master_bundle_item_name %}
            <em class="text-muted">{{ item.bundle_master_bundle_item_name }}</em>
        {% endif %}

        <strong>{{ item.product.name }}</strong>

        {# Variant name #}
        {% if item.variant_id %}
            <span class="text-muted">{{ item.variant.name }}</span>
        {% endif %}
    </div>
{% endfor %}

OrderStatus

Represents an order status in the workflow system.

Properties

PropertyTypeDescription
idintPrimary key
namestringDisplay name
codestringUnique code identifier
color_backgroundstringBadge background color
color_foregroundstringBadge text color
is_enabledboolWhether status is active

Constants

ConstantValueStock Action
STATUS_NEWnewReserves stock
STATUS_PAIDpaidMarks payment processed (no stock action)
STATUS_SHIPPEDshippedDecrements stock and releases reservation
STATUS_CANCELLEDcancelledReleases reservation
STATUS_REFUNDEDrefundedNo stock action

See Inventory — Stock Lifecycle for details on how status changes trigger stock operations.

Static Helpers

MethodReturnsDescription
getNewStatus()OrderStatusFind the "new" status
getPaidStatus()OrderStatusFind the "paid" status
getShippedStatus()OrderStatusFind the "shipped" status
getCancelledStatus()OrderStatusFind the "cancelled" status
getRefundedStatus()OrderStatusFind the "refunded" status

WARNING

These methods return null if the status record does not exist in the database. The New and Paid statuses are protected from deletion, but other statuses may be removed by store administrators. Always use null-safe access when calling these methods (e.g., OrderStatus::getShippedStatus()?->getKey()).

Displaying Status

twig
<span class="badge" style="background: {{ order.status.color_background }};
                            color: {{ order.status.color_foreground }}">
    {{ order.status.name }}
</span>

OrderStatusLog

A record of each status change on an order.

Properties

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

Relationships

PropertyTypeDescription
statusOrderStatusThe status that was applied
orderOrderThe order

Displaying Status History

twig
{% for log in order.status_log %}
    <div class="status-entry">
        <strong>{{ log.status.name }}</strong>
        <time>{{ log.created_at|date('M d, Y g:ia') }}</time>
        {% if log.comment %}
            <p>{{ log.comment }}</p>
        {% endif %}
    </div>
{% endfor %}

OrderNote

Internal notes attached to an order by administrators, optionally visible to customers.

Properties

PropertyTypeDescription
idintPrimary key
contentstringNote text
is_visible_to_customerboolWhether customer can see this note
created_atCarbonWhen the note was created

Relationships

PropertyTypeDescription
orderOrderParent order
admin_userAdminUserBackend user who wrote the note

Displaying Customer-Visible Notes

twig
{% set notes = order.getCustomerVisibleNotes() %}
{% if notes is not empty %}
    <h4>Notes</h4>
    {% for note in notes %}
        <div class="order-note">
            <p>{{ note.content }}</p>
            <small>{{ note.created_at|date('M d, Y') }}</small>
        </div>
    {% endfor %}
{% endif %}

OrderTrackingCode

Shipment tracking information attached to an order.

Properties

PropertyTypeDescription
idintPrimary key
carrierstringCarrier code
tracking_numberstringTracking number
tracking_urlstring|nullAuto-generated tracking URL
shipped_atCarbon|nullShipment date
created_atCarbonWhen added to order

Carrier Constants

ConstantValueTracking URL
CARRIER_FEDEXfedexfedex.com/fedextrack/
CARRIER_UPSupsups.com/track
CARRIER_USPSuspstools.usps.com/go/TrackConfirmAction
CARRIER_DHLdhldhl.com/en/express/tracking.html
CARRIER_OTHERotherNo automatic URL

Displaying Tracking

twig
{% if order.is_shipped %}
    <h4>Tracking</h4>
    {% for code in order.tracking_codes %}
        <div>
            <strong>{{ code.carrier|upper }}</strong>:
            {% if code.tracking_url %}
                <a href="{{ code.tracking_url }}" target="_blank">
                    {{ code.tracking_number }}
                </a>
            {% else %}
                {{ code.tracking_number }}
            {% endif %}
            {% if code.shipped_at %}
                <span class="text-muted">
                    Shipped {{ code.shipped_at|date('M d, Y') }}
                </span>
            {% endif %}
        </div>
    {% endfor %}
{% endif %}