@spree/docs 0.1.230 → 0.1.231
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.
- package/dist/developer/agentic/agent-skills.md +1 -1
- package/dist/developer/cli/quickstart.md +2 -2
- package/dist/developer/core-concepts/addresses.md +13 -0
- package/dist/developer/core-concepts/calculators.md +6 -1
- package/dist/developer/core-concepts/carts.md +19 -1
- package/dist/developer/core-concepts/catalogs.md +51 -2
- package/dist/developer/core-concepts/channels.md +20 -1
- package/dist/developer/core-concepts/commissions.md +70 -1
- package/dist/developer/core-concepts/companies.md +74 -0
- package/dist/developer/core-concepts/customers.md +17 -5
- package/dist/developer/core-concepts/data-privacy.md +20 -7
- package/dist/developer/core-concepts/delivery-setup.md +57 -0
- package/dist/developer/core-concepts/discounts.md +7 -0
- package/dist/developer/core-concepts/events.md +13 -7
- package/dist/developer/core-concepts/fees.md +20 -0
- package/dist/developer/core-concepts/fulfillments.md +3 -3
- package/dist/developer/core-concepts/imports-exports.md +21 -5
- package/dist/developer/core-concepts/inventory.md +73 -1
- package/dist/developer/core-concepts/markets.md +5 -6
- package/dist/developer/core-concepts/media.md +66 -1
- package/dist/developer/core-concepts/metafields.md +1 -1
- package/dist/developer/core-concepts/order-totals.md +18 -1
- package/dist/developer/core-concepts/orders.md +2 -1
- package/dist/developer/core-concepts/payments.md +100 -20
- package/dist/developer/core-concepts/pricing.md +13 -8
- package/dist/developer/core-concepts/products.md +52 -1
- package/dist/developer/core-concepts/reporting.md +5 -5
- package/dist/developer/core-concepts/returns-exchanges-claims.md +41 -2
- package/dist/developer/core-concepts/search-filtering.md +1 -2
- package/dist/developer/core-concepts/sellers.md +109 -2
- package/dist/developer/core-concepts/slugs.md +1 -1
- package/dist/developer/core-concepts/staff-roles.md +23 -3
- package/dist/developer/core-concepts/stores.md +21 -0
- package/dist/developer/core-concepts/taxes.md +43 -0
- package/dist/developer/core-concepts/translations.md +9 -0
- package/dist/developer/core-concepts/webhooks.md +45 -3
- package/dist/developer/create-spree-app/quickstart.md +10 -10
- package/dist/developer/dashboard/deployment.md +4 -4
- package/dist/developer/dashboard/recipes/attribute-end-to-end.md +1 -1
- package/dist/developer/deployment/docker.md +2 -2
- package/dist/developer/how-to/custom-promotion.md +33 -13
- package/dist/developer/multi-tenant/quickstart.md +6 -6
- package/dist/developer/storefront/nextjs/testing.md +2 -2
- package/package.json +1 -1
|
@@ -22,13 +22,13 @@ The official image contains the *stock* dashboard. Once you've customized yours
|
|
|
22
22
|
spree build --production # optionally --tag registry/repo:tag
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
The Dockerfile normalizes its own build context: built from the project root it detects the layout (`
|
|
25
|
+
The Dockerfile normalizes its own build context: built from the project root it detects the layout (`server/` = the Rails app, `apps/dashboard/` = your dashboard) and builds *your* dashboard into the image — no flags, no named contexts. Without the CLI, the equivalent is:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
docker build . -f
|
|
28
|
+
docker build . -f server/Dockerfile -t my-shop-spree:latest
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
Inside the dashboard stage the build runs with `VITE_BASE_PATH=/dashboard/` (asset URLs resolve under the mount) and `VITE_SPREE_API_URL` unset (API calls stay origin-relative); the Node toolchain lives only in that throw-away stage. Projects **without** `apps/dashboard/` get the stock dashboard baked instead — and if your `
|
|
31
|
+
Inside the dashboard stage the build runs with `VITE_BASE_PATH=/dashboard/` (asset URLs resolve under the mount) and `VITE_SPREE_API_URL` unset (API calls stay origin-relative); the Node toolchain lives only in that throw-away stage. Projects **without** `apps/dashboard/` get the stock dashboard baked instead — and if your `server/Dockerfile` predates this layout support, the command warns instead of silently shipping the stock dashboard over your customized one (update it from the spree-starter template).
|
|
32
32
|
|
|
33
33
|
## Static host / CDN — the alternative
|
|
34
34
|
|
|
@@ -53,7 +53,7 @@ The Blueprint that `create-spree-app` places at the project root deploys the bac
|
|
|
53
53
|
|
|
54
54
|
```yaml
|
|
55
55
|
runtime: docker
|
|
56
|
-
dockerfilePath: ./
|
|
56
|
+
dockerfilePath: ./server/Dockerfile
|
|
57
57
|
dockerContext: .
|
|
58
58
|
```
|
|
59
59
|
|
|
@@ -28,7 +28,7 @@ Lead time is a column because its whole point is the query: *"show me everything
|
|
|
28
28
|
|
|
29
29
|
## 1. Backend
|
|
30
30
|
|
|
31
|
-
Four small pieces — each one unlocks a specific frontend capability. In a host app these live in `
|
|
31
|
+
Four small pieces — each one unlocks a specific frontend capability. In a host app these live in `server/` (or `api/`); in a distributed plugin, in the Rails engine half.
|
|
32
32
|
|
|
33
33
|
**The column** (with an index — you're adding it *because* it will be queried):
|
|
34
34
|
|
|
@@ -13,7 +13,7 @@ If you haven't ejected yet, do that first:
|
|
|
13
13
|
spree eject
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
This generates the app source — including its production `Dockerfile` — in `
|
|
16
|
+
This generates the app source — including its production `Dockerfile` — in `server/`. Make your customizations, then build:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
spree build --production # → <project>-spree:latest
|
|
@@ -23,7 +23,7 @@ spree build --production --tag registry.example.com/my-store:v42
|
|
|
23
23
|
Or with plain Docker, from the project root:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
docker build . -f
|
|
26
|
+
docker build . -f server/Dockerfile -t my-store
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Both produce the same image — and it's exactly what Render and Railway build from your repository. Migrations run automatically on boot.
|
|
@@ -21,7 +21,7 @@ Rules determine whether a promotion is eligible for a given order. Each rule imp
|
|
|
21
21
|
|
|
22
22
|
Create a new class inheriting from `Spree::PromotionRule`:
|
|
23
23
|
|
|
24
|
-
```ruby app/models/spree/promotion/rules/minimum_quantity.rb
|
|
24
|
+
```ruby server/app/models/spree/promotion/rules/minimum_quantity.rb
|
|
25
25
|
module Spree
|
|
26
26
|
class Promotion
|
|
27
27
|
module Rules
|
|
@@ -67,7 +67,7 @@ The `options` hash passed to `eligible?` can include `:user`, `:email`, and othe
|
|
|
67
67
|
|
|
68
68
|
Rules use Spree's preference system for configuration. Each preference creates getter/setter methods automatically:
|
|
69
69
|
|
|
70
|
-
```ruby
|
|
70
|
+
```ruby server/app/models/spree/promotion/rules/minimum_quantity.rb
|
|
71
71
|
preference :amount, :decimal, default: 100.00
|
|
72
72
|
preference :operator, :string, default: 'gte'
|
|
73
73
|
preference :category_ids, :array, default: []
|
|
@@ -82,7 +82,7 @@ Available types: `:string`, `:integer`, `:decimal`, `:boolean`, `:array`.
|
|
|
82
82
|
|
|
83
83
|
### Step 2: Register the Rule
|
|
84
84
|
|
|
85
|
-
```ruby config/initializers/spree.rb
|
|
85
|
+
```ruby server/config/initializers/spree.rb
|
|
86
86
|
Rails.application.config.after_initialize do
|
|
87
87
|
Spree.promotions.rules << Spree::Promotion::Rules::MinimumQuantity
|
|
88
88
|
end
|
|
@@ -90,11 +90,31 @@ end
|
|
|
90
90
|
|
|
91
91
|
Registered rules are discoverable at `/api/v3/admin/promotion_rules/types` together with their preference schema, and the dashboard's promotion editor is built on that endpoint — your rule appears there with a generated preferences form, no UI work needed.
|
|
92
92
|
|
|
93
|
+
The API names your rule by its **shorthand** — the class name demodulized and underscored, so `Spree::Promotion::Rules::MinimumQuantity` is `minimum_quantity`. That is what `/types` returns, what a promotion payload sends, and what the locale key below is named after. The Ruby class name is never accepted on the wire:
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
```typescript Admin SDK
|
|
97
|
+
await adminClient.promotions.rules.create('promo_xxx', {
|
|
98
|
+
type: 'minimum_quantity',
|
|
99
|
+
preferences: { amount: 3 },
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```bash cURL
|
|
104
|
+
curl -X POST 'https://api.mystore.com/api/v3/admin/promotions/promo_xxx/promotion_rules' \
|
|
105
|
+
-H 'X-Spree-API-Key: sk_xxx' \
|
|
106
|
+
-H 'Content-Type: application/json' \
|
|
107
|
+
-d '{ "type": "minimum_quantity", "preferences": { "amount": 3 } }'
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
Override `self.api_type` on the class when you need the wire value to stay put across a rename.
|
|
112
|
+
|
|
93
113
|
### Step 3: Add Translations
|
|
94
114
|
|
|
95
115
|
The rule's display name and description in the dashboard come from your locale file:
|
|
96
116
|
|
|
97
|
-
```yaml config/locales/en.yml
|
|
117
|
+
```yaml server/config/locales/en.yml
|
|
98
118
|
en:
|
|
99
119
|
spree:
|
|
100
120
|
promotion_rule_types:
|
|
@@ -107,7 +127,7 @@ en:
|
|
|
107
127
|
|
|
108
128
|
When your rule targets specific line items (not the whole order), implement `actionable?` so that item-level actions only discount matching items:
|
|
109
129
|
|
|
110
|
-
```ruby app/models/spree/promotion/rules/brand.rb
|
|
130
|
+
```ruby server/app/models/spree/promotion/rules/brand.rb
|
|
111
131
|
module Spree
|
|
112
132
|
class Promotion
|
|
113
133
|
module Rules
|
|
@@ -153,7 +173,7 @@ Three declarations make a discount action:
|
|
|
153
173
|
| `compute_amount(adjustable)` | The discount for one adjustable — a line item, fulfillment, or the order, matching your scope. Return a **negative** amount, or zero for "no discount". |
|
|
154
174
|
| `perform(options = {})` | Called when the promotion is activated. For discount actions, delegate to `apply_via_adjuster(options)`. |
|
|
155
175
|
|
|
156
|
-
```ruby app/models/spree/promotion/actions/tiered_discount.rb
|
|
176
|
+
```ruby server/app/models/spree/promotion/actions/tiered_discount.rb
|
|
157
177
|
module Spree
|
|
158
178
|
class Promotion
|
|
159
179
|
module Actions
|
|
@@ -195,7 +215,7 @@ With `discount_scope :order`, the winning amount is shared out proportionally ac
|
|
|
195
215
|
|
|
196
216
|
For actions that don't create discounts (awarding points, sending notifications), implement `perform` alone:
|
|
197
217
|
|
|
198
|
-
```ruby app/models/spree/promotion/actions/add_loyalty_points.rb
|
|
218
|
+
```ruby server/app/models/spree/promotion/actions/add_loyalty_points.rb
|
|
199
219
|
module Spree
|
|
200
220
|
class Promotion
|
|
201
221
|
module Actions
|
|
@@ -219,13 +239,13 @@ end
|
|
|
219
239
|
|
|
220
240
|
### Register and Translate
|
|
221
241
|
|
|
222
|
-
```ruby config/initializers/spree.rb
|
|
242
|
+
```ruby server/config/initializers/spree.rb
|
|
223
243
|
Rails.application.config.after_initialize do
|
|
224
244
|
Spree.promotions.actions << Spree::Promotion::Actions::TieredDiscount
|
|
225
245
|
end
|
|
226
246
|
```
|
|
227
247
|
|
|
228
|
-
```yaml config/locales/en.yml
|
|
248
|
+
```yaml server/config/locales/en.yml
|
|
229
249
|
en:
|
|
230
250
|
spree:
|
|
231
251
|
promotion_action_types:
|
|
@@ -240,7 +260,7 @@ Like rules, registered actions surface automatically in the dashboard's promotio
|
|
|
240
260
|
|
|
241
261
|
Not every charge or reduction is a promotion. A gift wrap fee, a payment surcharge, or loyalty pricing has no rules, no coupon codes, and no competition — it just needs to be on the order whenever it applies. That's an **adjuster**: a class invoked on every recalculation that owns a family of [Fee](../core-concepts/fees.md) or [Discount](../core-concepts/discounts.md) rows.
|
|
242
262
|
|
|
243
|
-
```ruby app/models/my_app/adjusters/gift_wrap.rb
|
|
263
|
+
```ruby server/app/models/my_app/adjusters/gift_wrap.rb
|
|
244
264
|
module MyApp
|
|
245
265
|
module Adjusters
|
|
246
266
|
class GiftWrap < Spree::Adjusters::Base
|
|
@@ -258,7 +278,7 @@ module MyApp
|
|
|
258
278
|
end
|
|
259
279
|
```
|
|
260
280
|
|
|
261
|
-
```ruby config/initializers/spree.rb
|
|
281
|
+
```ruby server/config/initializers/spree.rb
|
|
262
282
|
Rails.application.config.after_initialize do
|
|
263
283
|
Spree.adjusters << MyApp::Adjusters::GiftWrap
|
|
264
284
|
end
|
|
@@ -272,7 +292,7 @@ Custom discounts work the same way, writing `order.discounts` rows with your own
|
|
|
272
292
|
|
|
273
293
|
## Testing
|
|
274
294
|
|
|
275
|
-
```ruby spec/models/spree/promotion/rules/minimum_quantity_spec.rb
|
|
295
|
+
```ruby server/spec/models/spree/promotion/rules/minimum_quantity_spec.rb
|
|
276
296
|
require 'spec_helper'
|
|
277
297
|
|
|
278
298
|
RSpec.describe Spree::Promotion::Rules::MinimumQuantity do
|
|
@@ -300,7 +320,7 @@ RSpec.describe Spree::Promotion::Rules::MinimumQuantity do
|
|
|
300
320
|
end
|
|
301
321
|
```
|
|
302
322
|
|
|
303
|
-
```ruby spec/models/spree/promotion/actions/tiered_discount_spec.rb
|
|
323
|
+
```ruby server/spec/models/spree/promotion/actions/tiered_discount_spec.rb
|
|
304
324
|
require 'spec_helper'
|
|
305
325
|
|
|
306
326
|
RSpec.describe Spree::Promotion::Actions::TieredDiscount do
|
|
@@ -44,7 +44,7 @@ spree eject
|
|
|
44
44
|
|
|
45
45
|
### Adding gems
|
|
46
46
|
|
|
47
|
-
1. Add the following code to your `
|
|
47
|
+
1. Add the following code to your `server/Gemfile`:
|
|
48
48
|
|
|
49
49
|
```ruby
|
|
50
50
|
source "https://license:#{ENV['KEYGEN_LICENSE_KEY']}@rubygems.pkg.keygen.sh/#{ENV['KEYGEN_ACCOUNT_ID']}" do
|
|
@@ -66,10 +66,10 @@ spree eject
|
|
|
66
66
|
> In that case the Gemfile reads `KEYGEN_LICENSE_KEY` / `KEYGEN_ACCOUNT_ID` directly from
|
|
67
67
|
> your shell environment.
|
|
68
68
|
|
|
69
|
-
Wrap **every** `bundle install` in your `
|
|
69
|
+
Wrap **every** `bundle install` in your `server/Dockerfile` with the secret mounts. There
|
|
70
70
|
are usually two — one in the build stage and one in the dev stage:
|
|
71
71
|
|
|
72
|
-
```dockerfile
|
|
72
|
+
```dockerfile server/Dockerfile
|
|
73
73
|
COPY .ruby-version Gemfile Gemfile.lock ./
|
|
74
74
|
RUN bundle install # [!code --]
|
|
75
75
|
RUN --mount=type=secret,id=keygen_license_key,env=KEYGEN_LICENSE_KEY,required=false \ # [!code ++]
|
|
@@ -185,7 +185,7 @@ development by default, but `.lvh.me` (and your production domain) are not — r
|
|
|
185
185
|
`app.lvh.me` are rejected with a "Blocked hosts" error until you allow them. Add your root
|
|
186
186
|
domain to `config/environments/development.rb`:
|
|
187
187
|
|
|
188
|
-
```ruby
|
|
188
|
+
```ruby server/config/environments/development.rb
|
|
189
189
|
if (root_domain = ENV['SPREE_ROOT_DOMAIN']).present?
|
|
190
190
|
config.hosts << ".#{root_domain}"
|
|
191
191
|
end
|
|
@@ -200,7 +200,7 @@ to your customer user model automatically. You then need to **remove the `:valid
|
|
|
200
200
|
manually. `:validatable` validates the user's email uniqueness globally; the concern re-validates
|
|
201
201
|
it in the scope of the tenant instead, so the same email can exist across different tenants.
|
|
202
202
|
|
|
203
|
-
```ruby
|
|
203
|
+
```ruby server/app/models/spree/user.rb
|
|
204
204
|
class Spree::User < Spree.base_class
|
|
205
205
|
include Spree::UserAddress
|
|
206
206
|
include Spree::UserMethods
|
|
@@ -222,7 +222,7 @@ The generator also changes your admin user model's base class from `Spree.base_c
|
|
|
222
222
|
`Spree::Base`. If your `admin_user.rb` exists, this is applied automatically; otherwise make the
|
|
223
223
|
change yourself:
|
|
224
224
|
|
|
225
|
-
```ruby
|
|
225
|
+
```ruby server/app/models/spree/admin_user.rb
|
|
226
226
|
class Spree::AdminUser < Spree.base_class # [!code --]
|
|
227
227
|
class Spree::AdminUser < Spree::Base # [!code ++]
|
|
228
228
|
include Spree::AdminUserMethods
|
|
@@ -61,7 +61,7 @@ npm run test:e2e
|
|
|
61
61
|
|
|
62
62
|
### A `create-spree-app` project's backend
|
|
63
63
|
|
|
64
|
-
A project scaffolded with [`create-spree-app`](../../create-spree-app/quickstart.md) has its customizable Spree in `
|
|
64
|
+
A project scaffolded with [`create-spree-app`](../../create-spree-app/quickstart.md) has its customizable Spree in `server/` (built from `server/Dockerfile`) and this storefront in `apps/storefront/`. Build that backend into a local image and point the suite at it — this is what tests the storefront against the **exact Spree you deploy**, extensions and all:
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
67
|
# From the project root — build the customized backend image
|
|
@@ -74,7 +74,7 @@ npm run test:e2e
|
|
|
74
74
|
npm run e2e:down
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
> **NOTE:** New `create-spree-app` projects wire this into the generated storefront CI workflow automatically — the workflow builds `
|
|
77
|
+
> **NOTE:** New `create-spree-app` projects wire this into the generated storefront CI workflow automatically — the workflow builds `server/Dockerfile` and runs the storefront E2E against that image rather than stock Spree.
|
|
78
78
|
|
|
79
79
|
### Interactive / manual
|
|
80
80
|
|