Skip to main content
A region is a market: the currency, language, tax behavior, and countries a storefront presents to a group of buyers.

Overview

A storefront request resolves several independent pieces of market context: which Channel it is trading on, which Currency prices are shown in, which Language content is translated to, and which Tax Zone governs pricing before a shipping address is known. A region groups these into a single record, so a merchant trading in more than one market — for example “UK: GBP, English, UK VAT, prices shown inclusive of tax” versus “US: USD, English, US sales tax, prices shown exclusive of tax” — has one object that expresses each combination. A region belongs to one channel. Channel remains the sales-surface axis (an online store, a B2B portal, a POS) that scopes the catalog; Region is the market axis. The two are orthogonal: a single “Online Store” channel can operate a UK region, a US region, and an EU region.

Fields

Relationships

Scopes

A country maps to at most one region. Lunar seeds a default region from the store’s default channel, currency, language, and tax zone, with no countries assigned — it is the catch-all that specific regions fall back to, so a single-market store gets a working region with no configuration required.

Creating a region

Price display

Whether stored prices already include tax is a global, storage-level concern controlled by config('lunar.pricing.stored_inclusive_of_tax') — this never varies by region, because changing it per region would corrupt tax arithmetic. Whether the storefront shows tax-inclusive or tax-exclusive prices is a separate, region-aware display preference:
This returns the region’s prices_inc_tax flag, falling back to the global storage default when the region does not set one. The tax zone used for that display calculation is the region’s taxZone relationship.
This display tax zone is used to price the catalog before a shipping address is known. Once a cart has a shipping address, checkout tax resolution is unchanged: Lunar\Core\Actions\Taxes\GetTaxZone still resolves postcode → state → country → default. See Taxation → Zone resolution.

Regions on carts and orders

Lunar\Core\Models\Cart and Lunar\Core\Models\Order each carry a nullable region_id and expose a region() relationship. A cart’s channel_id and currency_id stay denormalized alongside region_id — a cart’s channel should match its region’s channel, and its currency defaults from the region but can still be overridden per cart.

Storefront resolution

Lunar\Core\Contracts\StorefrontSession exposes getRegion() and setRegion(). Currency and language can still be set explicitly per session or per cart, but now default from the resolved region instead of each model’s own getDefault().