@spree/docs 0.1.194 → 0.1.195
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -20,10 +20,8 @@ flowchart LR
|
|
|
20
20
|
erDiagram
|
|
21
21
|
Catalog ||--o{ CatalogProduct : "assortment"
|
|
22
22
|
Catalog ||--o{ CatalogAssignment : "audiences"
|
|
23
|
-
Catalog
|
|
24
|
-
CatalogAssignment }o--|| Channel : "one of"
|
|
23
|
+
Catalog ||--o| PriceList : "owns (optional)"
|
|
25
24
|
CatalogAssignment }o--|| CustomerGroup : "one of"
|
|
26
|
-
CatalogAssignment }o--|| Market : "one of"
|
|
27
25
|
CatalogAssignment }o--|| Company : "one of"
|
|
28
26
|
|
|
29
27
|
Catalog {
|
|
@@ -60,6 +58,8 @@ const catalog = await adminClient.catalogs.create({
|
|
|
60
58
|
|
|
61
59
|
The price list is optional. A catalog with an assortment and no price list restricts the range at normal prices; a catalog with a price list and no assortment adjusts prices without hiding anything.
|
|
62
60
|
|
|
61
|
+
A price list is either **standalone** (matched by its own rules) or **owned by exactly one catalog** — attaching a list a catalog already claims moves it. Detaching (`price_list_id: null`) is an explicit act with a real consequence: a released list starts matching by its own rules again, and a rule-less one matches everyone.
|
|
62
|
+
|
|
63
63
|
### Filling the assortment
|
|
64
64
|
|
|
65
65
|
```typescript Admin SDK
|
|
@@ -71,7 +71,7 @@ const { data: products } = await adminClient.catalogs.products.list(catalog.id)
|
|
|
71
71
|
await adminClient.catalogs.products.delete(catalog.id, 'prod_xxx')
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
Membership is all a catalog holds — it decides *what* a buyer sees, never the order they see it in. Presentation order stays with categories and collections.
|
|
75
75
|
|
|
76
76
|
When a catalog should restrict to exactly what its price list covers, there's a shortcut that copies those products in rather than making someone add them by hand:
|
|
77
77
|
|
|
@@ -81,15 +81,15 @@ const { added_count } = await adminClient.catalogs.importProducts(catalog.id)
|
|
|
81
81
|
|
|
82
82
|
## Choosing the audience
|
|
83
83
|
|
|
84
|
-
A catalog is assigned to
|
|
84
|
+
A catalog is assigned to a buyer audience:
|
|
85
85
|
|
|
86
86
|
| Assign to | Meaning |
|
|
87
87
|
|---|---|
|
|
88
|
-
| **[Channel](channels.md)** | Everyone buying through this channel — an app, a retail till |
|
|
89
88
|
| **[Customer group](customers.md)** | A segment — wholesale accounts, staff, a loyalty tier |
|
|
90
|
-
| **[Market](markets.md)** | Everyone in a region |
|
|
91
89
|
| **[Company](companies.md)** | One B2B organization |
|
|
92
90
|
|
|
91
|
+
A [Channel](channels.md) is not assigned — it names its catalog directly via `default_catalog_id`, which applies to everyone buying through it when nothing narrower does.
|
|
92
|
+
|
|
93
93
|
```typescript Admin SDK
|
|
94
94
|
await adminClient.catalogs.assign(catalog.id, {
|
|
95
95
|
assignable_type: 'customer_group',
|
|
@@ -128,9 +128,9 @@ Prices are checked in order, and the first match wins:
|
|
|
128
128
|
|
|
129
129
|
Nearest-first is what lets a subsidiary hold a better-negotiated rate than the group's, without disturbing anyone else.
|
|
130
130
|
|
|
131
|
-
> **WARNING:** A price list
|
|
131
|
+
> **WARNING:** A price list owned by a catalog applies **because the catalog applies** — its own rules are not consulted, and it's excluded from ordinary rule matching.
|
|
132
132
|
>
|
|
133
|
-
> That exclusion is load-bearing: a price list with no rules would otherwise match everyone, and one company's negotiated pricing would leak to the entire storefront.
|
|
133
|
+
> That exclusion is load-bearing: a price list with no rules would otherwise match everyone, and one company's negotiated pricing would leak to the entire storefront. It also means a deactivated catalog's list goes **dormant** — turning the catalog off never releases its pricing to the whole store. Only explicitly detaching the list puts it back into rule matching.
|
|
134
134
|
|
|
135
135
|
## Related
|
|
136
136
|
|
|
@@ -142,7 +142,7 @@ const priceList = await client.priceLists.create({
|
|
|
142
142
|
name: 'EU wholesale',
|
|
143
143
|
match_policy: 'all',
|
|
144
144
|
rules: [
|
|
145
|
-
{ type: '
|
|
145
|
+
{ type: 'market_rule', preferences: { market_ids: ['mkt_xxx'] } },
|
|
146
146
|
],
|
|
147
147
|
prices: [
|
|
148
148
|
{ variant_id: 'variant_xxx', currency: 'EUR', amount: '19.99' },
|
|
@@ -165,16 +165,18 @@ spree api patch /price_lists/pl_xxx/activate
|
|
|
165
165
|
|
|
166
166
|
## Price Rules
|
|
167
167
|
|
|
168
|
-
Price Rules define conditions that must be met for a Price List to apply.
|
|
168
|
+
Price Rules define conditions that must be met for a Price List to apply. Rules describe the *context* of a purchase — where, through what, how much:
|
|
169
169
|
|
|
170
170
|
| Rule | Description | Use Case |
|
|
171
171
|
|------|-------------|----------|
|
|
172
172
|
| **Market Rule** | Matches based on the current [Market](markets.md) | Regional pricing across markets |
|
|
173
173
|
| **Channel Rule** | Matches based on the [Channel](channels.md) the customer is buying through | App-only or in-store pricing |
|
|
174
|
-
| **User Rule** | Matches specific customer accounts | VIP customers, wholesale accounts |
|
|
175
|
-
| **Customer Group Rule** | Matches members of customer groups | Loyalty tiers, membership pricing |
|
|
176
174
|
| **Volume Rule** | Matches based on quantity purchased | Bulk discounts, tiered pricing |
|
|
177
175
|
|
|
176
|
+
*Who* gets a price list is not a rule — it's a [Catalog](catalogs.md): attach the list to a catalog assigned to the customer groups or companies it's for.
|
|
177
|
+
|
|
178
|
+
> **NOTE:** The **User Rule** and **Customer Group Rule** kinds still work and are not going away, but they're no longer offered when adding a rule — targeting an audience through a catalog is the one way to do it now. Nothing needs migrating; rules you already have keep matching exactly as before.
|
|
179
|
+
|
|
178
180
|
### Market Rule
|
|
179
181
|
|
|
180
182
|
Regional pricing. Applies the Price List when the customer is in one of the specified markets.
|
|
@@ -183,15 +185,7 @@ Regional pricing. Applies the Price List when the customer is in one of the spec
|
|
|
183
185
|
|
|
184
186
|
### Channel Rule
|
|
185
187
|
|
|
186
|
-
Applies when the customer is buying through a particular sales channel — a discount that exists only in the mobile app, or a price that only applies at a retail till.
|
|
187
|
-
|
|
188
|
-
### User Rule
|
|
189
|
-
|
|
190
|
-
Limits the Price List to specific customer accounts. Useful for VIP customers, employee pricing, or wholesale accounts.
|
|
191
|
-
|
|
192
|
-
### Customer Group Rule
|
|
193
|
-
|
|
194
|
-
Applies to members of specific customer groups. Useful for wholesale tiers, loyalty programs, or membership-based pricing.
|
|
188
|
+
Applies when the customer is buying through a particular sales channel — a discount that exists only in the mobile app, or a price that only applies at a retail till. For new setups, prefer giving the channel a default [Catalog](catalogs.md) that owns the price list — that is where channel-wide commercial terms live going forward.
|
|
195
189
|
|
|
196
190
|
### Volume Rule
|
|
197
191
|
|
|
@@ -214,7 +208,7 @@ When resolving prices, Spree considers the full context of the request:
|
|
|
214
208
|
| Currency | Market or request header | The currency to price in |
|
|
215
209
|
| Market | Customer's country | The [Market](markets.md) for market-based rules |
|
|
216
210
|
| Channel | The API credential in use | The [Channel](channels.md) for channel-based rules |
|
|
217
|
-
| Customer | Authentication | The signed-in customer for
|
|
211
|
+
| Customer | Authentication | The signed-in customer, for resolving their [Catalogs](catalogs.md) |
|
|
218
212
|
| Quantity | Cart line item | The quantity for volume-based rules |
|
|
219
213
|
| Date | Current time | For time-based Price List scheduling |
|
|
220
214
|
|