Price Lists — Reference
The Price Lists surface is the segmented-pricing plane for SGEN commerce. It owns the rules that quote a different price for the same product depending on who is shopping, where they are, how many units they buy, and when the cart is evaluated. Anything other than the catalog's default price traces back to a record managed here.
This page is a reference for platform engineers and integrators who need to understand the surface before extending it, scripting against it, or scoping a tiered-pricing model. Customer-facing how-tos live in the customer docs set; this page describes the shape of the surface, not the steps to drive it.
Overview
Price Lists lives under the Commerce module in SG-Admin. The module renders three primary views — the list of price lists, the price-list create / edit form (with per-list product entries), and the assignment view that ties a list to a customer group, region, or schedule window — and exposes a small set of write operations for create, edit, assign, unassign, schedule, archive, and bulk-import entries.
The module is paired by convention: one half renders the views and prepares the list and entry data, the other half handles writes and returns AJAX responses. Engineers reading the SG-Admin source will see this split across two controller files; the reference below describes the combined surface as it appears to a calling integration.
Price Lists are distinct from Discounts. A discount rule lowers a cart total after the cart's prices have been quoted; a price list rewrites the quoted price itself, before any discount runs. Both surfaces share the underlying pricing pipeline, but the entry points and the order of evaluation are different. Discount rules live under the adjacent Discounts surface; this page covers segmented price quoting only.
Where it lives in SG-Admin:
- Sidebar: SG-Admin → Commerce → Price Lists
- URL prefix:
/sg-admin/price-lists/ - View templates:
application/views/Admin/Commerce/PriceLists/
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Commerce → Price Lists [ + Add list ] │├──────────────────────────────────────────────────────────────────────┤│ Name Scope Entries Status Updated ││ ────────────────── ──────────────── ──────── ──────── ──────────││ Wholesale — Tier 1 group: wholesale 482 active today ││ EU Region region: EU 1,204 active 3d ago ││ Holiday 2026 schedule: Dec 96 scheduled 1w ago ││ Bulk 10+ qty break ≥ 10 312 active today ││ Legacy Q1 prices (no assignment) 58 archived 90d ago ││ ││ Total lists: 12 · Active: 9 · Scheduled: 2 · Archived: 1 ││ [ Edit ] [ Assign ] [ Schedule ] [ Import ] [ Archive ] │└──────────────────────────────────────────────────────────────────────┘Actions
The Price Lists surface exposes the following operations. Each is described by what it does to the data, not by its internal method name.
List price lists
Returns the catalog of price lists visible to the current operator, paginated, with name, scope summary (customer group, region, schedule window, quantity break), entry count, status (active, scheduled, paused, archived), and last-updated timestamp. Supports filter by scope type, by status, and by assignment target. The default view excludes archived lists — they remain queryable via the explicit filter.
View price list
Returns the full record for a single list — name, scope, currency, rounding policy, schedule window, the per-product entry table (product or variant identifier, quoted price, optional quantity break), and the assignment ledger that ties the list to customer groups or regions. The entry table is paginated; total entry count and entry-coverage summary are surfaced at the top.
Create price list
Opens an empty list form. Required fields at minimum: name, currency, scope type. Optional fields cover schedule window (start / end timestamp), rounding policy, fallback behavior when an entry is missing, and a starting set of entries (manual or import). On submit, the surface validates the scope against the available scope vocabulary, persists the record, and returns the new identifier.
Edit price list
Loads an existing record into the same form shape used for create, pre-populated. Submit replaces the stored list with the posted values; fields left blank do not clear server-side values (the form is partial-update by default). Edits to an active list take effect on the next cart evaluation — carts already at checkout retain the previously quoted price.
Add, edit, and remove entries
The per-product entry table is editable inline. Each entry carries a product or variant reference, a quoted price, an optional quantity break, and an optional note. Adding an entry inserts a row; editing rewrites an existing row; removing detaches the product from the list without affecting the underlying catalog record. Bulk operations on the entry table are exposed via Import.
Bulk import entries
Accepts a structured upload (the SGEN-standard CSV shape — product reference, price, optional quantity break) and writes the rows into the entry table in a single transaction. Validation runs row-by-row; rejected rows are returned with the row index and reason, and accepted rows persist regardless of partial failures.
Assign and unassign
Ties a price list to one or more customer groups, regions, or schedule windows. A list with no assignment exists but is never quoted. Multiple assignments are permitted — a list may apply to wholesale customers in EU only, for example. Unassign detaches a single binding without altering the list itself.
Schedule
Sets the start / end window during which the list is eligible for quoting. Scheduled lists move automatically between scheduled, active, and expired status as the window opens and closes. The schedule is evaluated at quote time, not at write time.
Pause and resume
Toggles the list between active and paused without altering its definition or assignments. Paused lists are excluded from cart quoting but retain their entries and remain queryable. Resume restores the list to active.
Archive
Marks the list inactive without removing it from the database. Archived lists disappear from the default list view but remain queryable via the archived filter. Their entries and historical assignments remain attached for audit; the list itself is excluded from cart quoting.
Engineering note. The quote engine resolves a single price-list winner per cart line by evaluating assignments in priority order — group match, then region, then schedule, then quantity break. When multiple lists could apply, the rounding policy is taken from the winning list.
Data model
A price-list record carries the following fields. Field names below are the conceptual shape — the on-disk column names match closely but are not contractually stable across releases.
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. Stable across edits. |
name | string | Operator-facing label. Not unique. |
currency | string | ISO 4217 currency code. |
scope_type | enum | group, region, schedule, quantity, custom. |
rounding_policy | enum | none, nearest_cent, psychological_99, floor, ceiling. |
fallback | enum | catalog_price, block_purchase, next_eligible_list. |
starts_at | timestamp | Optional schedule start. |
ends_at | timestamp | Optional schedule end. |
status | enum | active, scheduled, paused, expired, archived. |
priority | integer | Tiebreak slot when multiple lists could quote a line. |
created_at | timestamp | Set on create, immutable. |
updated_at | timestamp | Touched on any edit or entry change. |
list_id, product_id or variant_id, price, optional min_quantity (for quantity-break tiers), optional note. Each row is independent — the same product may carry several rows with ascending min_quantity for tiered pricing.Assignment row: list_id, target_type (group / region), target_id, optional priority_override. A list with zero assignment rows exists but is never quoted (unless its scope_type is quantity, in which case the list applies globally subject to the quantity threshold).
Quote semantics: at cart-line evaluation, the engine collects all lists whose scope matches the line — customer group, region, active schedule window, item quantity. Among matches, it picks the highest-priority list and uses its quoted price. The rounding policy is applied last. If no list matches, the catalog base price stands.
CART LINE│ product · qty · customer · region · timestamp▼┌───────────────────────────────────────────────┐│ Price-list engine ││ ││ collect lists where: ││ ▶ group / region / schedule matches ││ ▶ list contains this product or variant ││ ▶ list is active (not paused or archived) ││ ▶ if quantity-break, qty ≥ min_quantity ││ ││ if matches → pick highest priority ││ apply rounding_policy ││ if no match → catalog base price │└───────────────────────┬───────────────────────┘│▼QUOTED LINE PRICE│▼(discount engine runs next)Permissions
Access to the Price Lists surface is gated at two layers.
Layer 1 — admin gate. Every action under SG-Admin passes through the platform's standard admin access check at request entry. An unauthenticated request never reaches the Price Lists surface.
Layer 2 — per-action capability. Within SG-Admin, each Price Lists action checks a capability associated with the calling operator's role. The default role configuration ships with three roles — Administrator, Editor, Viewer — and the capability map is:
| Capability | Administrator | Editor | Viewer |
|---|---|---|---|
| List price lists | ✔ | ✔ | ✔ |
| View list | ✔ | ✔ | ✔ |
| Create list | ✔ | ✔ | — |
| Edit list | ✔ | ✔ | — |
| Add / edit / remove entries | ✔ | ✔ | — |
| Bulk import entries | ✔ | ✔ | — |
| Assign / unassign | ✔ | — | — |
| Schedule | ✔ | — | — |
| Pause / resume | ✔ | — | — |
| Archive list | ✔ | — | — |
| Restore archived list | ✔ | — | — |
Self-protection rules. A list assigned to an active customer group cannot be archived without confirmation — the surface returns a structured rejection naming the live assignments. A scheduled list cannot have its start moved earlier than the current quote-cache window; the cache TTL is read from Settings. Currency cannot be edited on a list with non-empty entries; create a fresh list instead.
Audit. Every write — create, edit, entry change, import, assign, unassign, schedule, pause, resume, archive, restore — emits an Activity Log entry. The log records the acting operator, the list identifier, and the change shape (field-level diff for edits, row-count diff for imports). Quote applications also write to a per-line ledger, correlated by list identifier and cart line.
REQUEST│▼┌───────────────────────────┐│ Admin gate │ unauth → reject│ (every /sg-admin/* call) │└─────────────┬─────────────┘│ authed▼┌───────────────────────────┐│ Capability check │ role lacks cap → reject│ (per-action) │ (custom roles override defaults)└─────────────┬─────────────┘│ allowed▼┌───────────────────────────┐│ Self-protection rules │ live-assignment archive /│ │ currency-change-on-entries /│ │ schedule-inside-cache → reject└─────────────┬─────────────┘│ passes▼action executes│▼Activity Log entry + quote ledgerRelated references
- Discounts — Reference. Runs after price-list quoting. Discount rules apply to the already-quoted line price, not to the catalog base.
- Coupons — Reference. Same evaluation order as Discounts — coupons apply on top of quoted prices, never instead of them.
- Products — Reference. Owns the base price and the variant model. Price-list entries reference product or variant identifiers defined here.
- Customers — Reference. Customer-group filters reference the group definitions documented here. A customer in multiple groups gets the highest-priority matching list.
- Settings — Reference. Owns the currency vocabulary, the region vocabulary, the rounding-policy options, and the quote-cache TTL. Changes there reshape the Price Lists evaluation behavior.
- Orders — Reference. Records the quoted price per line plus the price-list identifier that supplied it. Refunds reference the original quote, not the current list.
- Tax — Reference. Tax calculation runs after price quoting and after discount application. Tax rules consume the post-discount line price.
/docs/price-lists.