Skip to main content
The order history page lets an authenticated customer view their past orders, check payment and fulfilment status, and review the details of an individual order. This guide walks through resolving the current customer, querying their orders, displaying a paginated order list, and building an order detail page. The examples below use standard Laravel controllers and Blade templates. The same concepts apply whether the storefront is built with Livewire, Inertia, or a headless API.

Resolving the Current Customer

Lunar separates the concept of a Lunar\Core\Models\Customer from Laravel’s User model. An authenticated user is linked to one or more customers through the Lunar\Core\Models\Concerns\IsLunarUser trait (see the Customer Authentication guide). Lunar\Core\Facades\StorefrontSession provides the current customer for the request.
If no customer is resolved for the current session, getCustomer() returns null. Protect account pages with a check for a resolved customer:
StorefrontSession automatically resolves the customer from the authenticated user’s latestCustomer() when no customer is already stored in the session. See the Storefront Session reference for details on how resolution works.

Listing Orders

Query the customer’s orders using the orders relationship. Only orders with a placed_at value should be shown, since a draft order (where placed_at is null) has not been completed and only exists as a checkout-in-progress record.
isDraft() and isPlaced() are also available directly on the Lunar\Core\Models\Order model as a shorthand for checking placed_at.

Displaying the Order List

Order monetary fields (sub_total, discount_total, shipping_total, tax_total, total) are stored as integers in the currency’s minor unit. Call format($field) (from Lunar\Core\Models\Concerns\FormatsPrices) to get a formatted currency string, or decimal($field) for a float.

Order Status

An order does not have a single “status” column. Its lifecycle is read from two independently derived rollups, plus an open/closed archive flag: Both are recomputed automatically whenever the underlying transactions or fulfilments change, so neither is set by hand from the storefront. payment_status->label() and fulfilment_status->label() return a translated, human-readable string for display.
See the Orders reference for the full detail on how these rollups are derived, plus the order’s open/closed and cancelled state.

Order Detail Page

The order detail page shows the full breakdown of a specific order, including line items, addresses, and totals.
Always verify that the order belongs to the current customer. Without this check, a customer could view another customer’s order by guessing the URL.

Displaying Order Lines

Order lines hold a snapshot of each purchased item, taken at the time the order was created. The description field contains the product name at that time, and option holds any variant options.
productLines excludes the shipping line ($order->shippingLines) — see Order lines for the full field list, including requires_shipping and requires_fulfilment.

Displaying Addresses

Each placed order stores a billing address and (for shippable orders) a shipping address as Lunar\Core\Models\OrderAddress records. These are snapshots taken when the order was created, separate from the customer’s saved addresses.

Displaying Order Totals

Tax Breakdown

tax_breakdown is cast to a value object with an amounts collection of Lunar\Core\ValueObjects\Cart\TaxBreakdownAmount, each carrying a Lunar\Core\DataObjects\PriceValue that also exposes format():

Eager Loading for Performance

When displaying an order list, eager load the relationships needed for the list view to avoid N+1 queries:
For the detail page, load everything needed in a single query:

Routes

Putting It All Together

Here is a complete controller for the order history pages:

Next Steps