@spree/docs 0.1.0
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/README.md +54 -0
- package/dist/api-reference/platform/authentication.md +38 -0
- package/dist/api-reference/store-api/authentication.md +188 -0
- package/dist/api-reference/store-api/errors.md +277 -0
- package/dist/api-reference/store-api/idempotency.md +129 -0
- package/dist/api-reference/store-api/introduction.md +34 -0
- package/dist/api-reference/store-api/localization.md +279 -0
- package/dist/api-reference/store-api/metadata.md +160 -0
- package/dist/api-reference/store-api/monetary-amounts.md +65 -0
- package/dist/api-reference/store-api/querying.md +399 -0
- package/dist/api-reference/store-api/rate-limitting.md +103 -0
- package/dist/api-reference/store-api/relations.md +185 -0
- package/dist/api-reference/storefront/authentication.md +88 -0
- package/dist/api-reference/tutorials/adyen-integration-guide-for-android.md +165 -0
- package/dist/api-reference/tutorials/adyen-integration-guide-for-ios.md +194 -0
- package/dist/api-reference/tutorials/quick-checkout-with-stripe.md +248 -0
- package/dist/api-reference/v2/fetching-multiple-resources.md +26 -0
- package/dist/api-reference/v2/filtering-and-sorting.md +53 -0
- package/dist/api-reference/v2/introduction.md +22 -0
- package/dist/api-reference/v2/pagination.md +37 -0
- package/dist/api-reference/webhooks-events.md +883 -0
- package/dist/developer/admin/admin.md +205 -0
- package/dist/developer/admin/authentication.md +59 -0
- package/dist/developer/admin/components.md +711 -0
- package/dist/developer/admin/custom-css.md +243 -0
- package/dist/developer/admin/custom-javascript.md +116 -0
- package/dist/developer/admin/extending-ui.md +1964 -0
- package/dist/developer/admin/form-builder.md +444 -0
- package/dist/developer/admin/helper-methods.md +531 -0
- package/dist/developer/admin/navigation.md +805 -0
- package/dist/developer/admin/tables.md +491 -0
- package/dist/developer/advanced/adding_spree_to_rails_app.md +106 -0
- package/dist/developer/cli/quickstart.md +137 -0
- package/dist/developer/contributing/creating-an-extension.md +258 -0
- package/dist/developer/contributing/developing-spree.md +339 -0
- package/dist/developer/contributing/quickstart.md +32 -0
- package/dist/developer/contributing/updating-extensions.md +67 -0
- package/dist/developer/core-concepts/addresses.md +265 -0
- package/dist/developer/core-concepts/adjustments.md +107 -0
- package/dist/developer/core-concepts/architecture.md +177 -0
- package/dist/developer/core-concepts/calculators.md +323 -0
- package/dist/developer/core-concepts/customers.md +230 -0
- package/dist/developer/core-concepts/events.md +624 -0
- package/dist/developer/core-concepts/imports-exports.md +698 -0
- package/dist/developer/core-concepts/inventory.md +191 -0
- package/dist/developer/core-concepts/markets.md +250 -0
- package/dist/developer/core-concepts/media.md +167 -0
- package/dist/developer/core-concepts/metafields.md +187 -0
- package/dist/developer/core-concepts/orders.md +328 -0
- package/dist/developer/core-concepts/payments.md +710 -0
- package/dist/developer/core-concepts/pricing.md +163 -0
- package/dist/developer/core-concepts/products.md +360 -0
- package/dist/developer/core-concepts/promotions.md +322 -0
- package/dist/developer/core-concepts/reports.md +206 -0
- package/dist/developer/core-concepts/search-filtering.md +237 -0
- package/dist/developer/core-concepts/shipments.md +212 -0
- package/dist/developer/core-concepts/slugs.md +111 -0
- package/dist/developer/core-concepts/staff-roles.md +123 -0
- package/dist/developer/core-concepts/store-credits-gift-cards.md +317 -0
- package/dist/developer/core-concepts/stores.md +117 -0
- package/dist/developer/core-concepts/taxes.md +135 -0
- package/dist/developer/core-concepts/translations.md +120 -0
- package/dist/developer/core-concepts/users.md +299 -0
- package/dist/developer/core-concepts/webhooks.md +378 -0
- package/dist/developer/create-spree-app/quickstart.md +158 -0
- package/dist/developer/customization/api.md +93 -0
- package/dist/developer/customization/authentication.md +88 -0
- package/dist/developer/customization/checkout.md +204 -0
- package/dist/developer/customization/configuration.md +55 -0
- package/dist/developer/customization/decorators.md +523 -0
- package/dist/developer/customization/dependencies.md +232 -0
- package/dist/developer/customization/emails.md +21 -0
- package/dist/developer/customization/extensions.md +92 -0
- package/dist/developer/customization/metadata.md +236 -0
- package/dist/developer/customization/model-preferences.md +130 -0
- package/dist/developer/customization/permissions.md +265 -0
- package/dist/developer/customization/quickstart.md +229 -0
- package/dist/developer/customization/routes.md +24 -0
- package/dist/developer/customization/v4/admin-panel.md +78 -0
- package/dist/developer/customization/v4/authentication.md +210 -0
- package/dist/developer/customization/v4/checkout.md +212 -0
- package/dist/developer/customization/v4/deface.md +251 -0
- package/dist/developer/customization/v4/images.md +86 -0
- package/dist/developer/customization/v4/storefront.md +450 -0
- package/dist/developer/deployment/assets.md +87 -0
- package/dist/developer/deployment/aws.md +335 -0
- package/dist/developer/deployment/caching.md +27 -0
- package/dist/developer/deployment/cdn.md +39 -0
- package/dist/developer/deployment/database.md +155 -0
- package/dist/developer/deployment/docker.md +128 -0
- package/dist/developer/deployment/emails.md +77 -0
- package/dist/developer/deployment/environment_variables.md +111 -0
- package/dist/developer/deployment/heroku.md +51 -0
- package/dist/developer/deployment/render.md +95 -0
- package/dist/developer/getting-started/quickstart.md +82 -0
- package/dist/developer/how-to/custom-payment-method.md +374 -0
- package/dist/developer/how-to/custom-promotion.md +373 -0
- package/dist/developer/how-to/custom-report.md +387 -0
- package/dist/developer/how-to/custom-search-provider.md +230 -0
- package/dist/developer/multi-store/quickstart.md +71 -0
- package/dist/developer/multi-store/setup.md +38 -0
- package/dist/developer/multi-tenant/configuration.md +41 -0
- package/dist/developer/multi-tenant/core-concepts.md +75 -0
- package/dist/developer/multi-tenant/installation.md +96 -0
- package/dist/developer/multi-tenant/quickstart.md +20 -0
- package/dist/developer/multi-vendor/installation.md +45 -0
- package/dist/developer/multi-vendor/quickstart.md +17 -0
- package/dist/developer/sdk/admin/quickstart.md +22 -0
- package/dist/developer/sdk/authentication.md +89 -0
- package/dist/developer/sdk/configuration.md +225 -0
- package/dist/developer/sdk/quickstart.md +82 -0
- package/dist/developer/sdk/store/account.md +67 -0
- package/dist/developer/sdk/store/cart-checkout.md +140 -0
- package/dist/developer/sdk/store/markets.md +151 -0
- package/dist/developer/sdk/store/payments.md +96 -0
- package/dist/developer/sdk/store/products.md +149 -0
- package/dist/developer/sdk/store/wishlists.md +52 -0
- package/dist/developer/security/pci_compliance.md +15 -0
- package/dist/developer/security/security_policy.md +68 -0
- package/dist/developer/storefront/blocks.md +285 -0
- package/dist/developer/storefront/custom-css.md +260 -0
- package/dist/developer/storefront/custom-javascript.md +166 -0
- package/dist/developer/storefront/helper-methods.md +1288 -0
- package/dist/developer/storefront/links.md +298 -0
- package/dist/developer/storefront/nextjs/architecture.md +150 -0
- package/dist/developer/storefront/nextjs/customization.md +141 -0
- package/dist/developer/storefront/nextjs/deployment.md +180 -0
- package/dist/developer/storefront/nextjs/quickstart.md +92 -0
- package/dist/developer/storefront/nextjs/spree-next-package.md +314 -0
- package/dist/developer/storefront/pages.md +163 -0
- package/dist/developer/storefront/sections.md +569 -0
- package/dist/developer/storefront/storefront.md +56 -0
- package/dist/developer/storefront/themes.md +161 -0
- package/dist/developer/tutorial/admin.md +134 -0
- package/dist/developer/tutorial/extending-models.md +380 -0
- package/dist/developer/tutorial/file-uploads.md +121 -0
- package/dist/developer/tutorial/introduction.md +33 -0
- package/dist/developer/tutorial/model.md +41 -0
- package/dist/developer/tutorial/page-builder.md +487 -0
- package/dist/developer/tutorial/rich-text.md +73 -0
- package/dist/developer/tutorial/seo.md +332 -0
- package/dist/developer/tutorial/storefront.md +352 -0
- package/dist/developer/tutorial/testing.md +558 -0
- package/dist/developer/upgrades/2.0-to-2.1.md +46 -0
- package/dist/developer/upgrades/2.1-to-2.2.md +59 -0
- package/dist/developer/upgrades/2.2-to-2.3.md +44 -0
- package/dist/developer/upgrades/2.3-to-2.4.md +42 -0
- package/dist/developer/upgrades/3.0-to-3.1.md +47 -0
- package/dist/developer/upgrades/3.1-to-3.2.md +34 -0
- package/dist/developer/upgrades/3.2-to-3.3.md +70 -0
- package/dist/developer/upgrades/3.3-to-3.4.md +36 -0
- package/dist/developer/upgrades/3.4-to-3.5.md +44 -0
- package/dist/developer/upgrades/3.5-to-3.6.md +40 -0
- package/dist/developer/upgrades/3.6-to-3.7.md +62 -0
- package/dist/developer/upgrades/3.7-to-4.0.md +152 -0
- package/dist/developer/upgrades/4.0-to-4.1.md +92 -0
- package/dist/developer/upgrades/4.1-to-4.2.md +109 -0
- package/dist/developer/upgrades/4.10-to-5.0.md +129 -0
- package/dist/developer/upgrades/4.2-to-4.3.md +100 -0
- package/dist/developer/upgrades/4.3-to-4.4.md +125 -0
- package/dist/developer/upgrades/4.4-to-4.5.md +94 -0
- package/dist/developer/upgrades/4.5-to-4.6.md +119 -0
- package/dist/developer/upgrades/4.6-to-4.7.md +39 -0
- package/dist/developer/upgrades/4.8-to-4.9.md +24 -0
- package/dist/developer/upgrades/4.9-to-4.10.md +24 -0
- package/dist/developer/upgrades/4.x-to-4.8.md +52 -0
- package/dist/developer/upgrades/5.0-to-5.1.md +28 -0
- package/dist/developer/upgrades/5.1-to-5.2.md +127 -0
- package/dist/developer/upgrades/5.2-to-5.3.md +338 -0
- package/dist/developer/upgrades/5.3-to-5.4.md +248 -0
- package/dist/developer/upgrades/quickstart.md +36 -0
- package/dist/integrations/analytics/google-analytics.md +64 -0
- package/dist/integrations/analytics/google-tag-manager.md +78 -0
- package/dist/integrations/integrations.md +39 -0
- package/dist/integrations/marketing/klaviyo.md +99 -0
- package/dist/integrations/payments/adyen.md +90 -0
- package/dist/integrations/payments/paypal.md +41 -0
- package/dist/integrations/payments/razorpay.md +45 -0
- package/dist/integrations/payments/stripe.md +109 -0
- package/dist/integrations/search/meilisearch.md +236 -0
- package/dist/integrations/sso-mfa-social-login/admin-dashboard.md +57 -0
- package/dist/integrations/sso-mfa-social-login/storefront.md +56 -0
- package/package.json +27 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Promotions
|
|
3
|
+
description: Learn about Spree's flexible promotion system for discounts, free shipping, and gifts.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Promotions within Spree are used to provide discounts to orders, offer free shipping, or add items at no extra cost (e.g., free gifts). The promotion system is highly flexible, allowing you to create complex promotional campaigns based on various conditions.
|
|
9
|
+
|
|
10
|
+
### Promotion Model Diagram
|
|
11
|
+
|
|
12
|
+
```mermaid
|
|
13
|
+
erDiagram
|
|
14
|
+
Promotion {
|
|
15
|
+
string name
|
|
16
|
+
string description
|
|
17
|
+
string kind
|
|
18
|
+
string code
|
|
19
|
+
string path
|
|
20
|
+
datetime starts_at
|
|
21
|
+
datetime expires_at
|
|
22
|
+
integer usage_limit
|
|
23
|
+
string match_policy
|
|
24
|
+
boolean advertise
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
PromotionRule {
|
|
28
|
+
string type
|
|
29
|
+
text preferences
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
PromotionAction {
|
|
33
|
+
string type
|
|
34
|
+
integer position
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
CouponCode {
|
|
38
|
+
string code
|
|
39
|
+
string state
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
OrderPromotion {
|
|
43
|
+
integer order_id
|
|
44
|
+
integer promotion_id
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
Adjustment {
|
|
48
|
+
decimal amount
|
|
49
|
+
string label
|
|
50
|
+
boolean eligible
|
|
51
|
+
string state
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
Promotion ||--o{ PromotionRule : "has many"
|
|
55
|
+
Promotion ||--o{ PromotionAction : "has many"
|
|
56
|
+
Promotion ||--o{ CouponCode : "has many"
|
|
57
|
+
Promotion ||--o{ OrderPromotion : "has many"
|
|
58
|
+
Promotion }o--o{ Store : "available in"
|
|
59
|
+
PromotionRule }o--o{ Product : "applies to"
|
|
60
|
+
PromotionRule }o--o{ Taxon : "applies to"
|
|
61
|
+
PromotionRule }o--o{ User : "applies to"
|
|
62
|
+
PromotionAction ||--o{ Adjustment : "creates"
|
|
63
|
+
PromotionAction ||--|| Calculator : "has one"
|
|
64
|
+
Order ||--o{ OrderPromotion : "has many"
|
|
65
|
+
CouponCode }o--o| Order : "used by"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Key relationships:**
|
|
69
|
+
- **Promotion** defines the campaign with rules and actions
|
|
70
|
+
- **Promotion Rules** determine eligibility conditions (FirstOrder, ItemTotal, Taxon, etc.)
|
|
71
|
+
- **Promotion Actions** define what happens when applied (discount, free shipping, free items)
|
|
72
|
+
- **Coupon Codes** track usage for code-based promotions
|
|
73
|
+
- **[Adjustments](/developer/core-concepts/adjustments)** are created on orders/line items to apply discounts
|
|
74
|
+
|
|
75
|
+
Promotions can be activated in two ways:
|
|
76
|
+
|
|
77
|
+
- **Automatic promotions** - Applied automatically when eligibility rules are met (e.g., free shipping on orders over $50)
|
|
78
|
+
- **Coupon code promotions** - Applied when a customer enters a valid code during checkout
|
|
79
|
+
|
|
80
|
+
Promotions consist of two main components:
|
|
81
|
+
|
|
82
|
+
- **Rules** - Conditions that must be met for the promotion to apply
|
|
83
|
+
- **Actions** - What happens when the promotion is applied (discount, free shipping, etc.)
|
|
84
|
+
|
|
85
|
+
## Promotion Attributes
|
|
86
|
+
|
|
87
|
+
| Attribute | Description | Example |
|
|
88
|
+
|-----------|-------------|---------|
|
|
89
|
+
| `name` | The name of the promotion | Summer Sale |
|
|
90
|
+
| `description` | Brief description (max 255 chars) | 20% off all summer items |
|
|
91
|
+
| `kind` | Type: `coupon_code` or `automatic` | `automatic` |
|
|
92
|
+
| `starts_at` | When the promotion becomes active | 2025-06-01 00:00:00 |
|
|
93
|
+
| `expires_at` | When the promotion expires | 2025-09-01 23:59:59 |
|
|
94
|
+
| `usage_limit` | Max times the promotion can be used | 500 |
|
|
95
|
+
| `match_policy` | How rules are evaluated: `all` or `any` | `all` |
|
|
96
|
+
| `advertise` | Whether to display on storefront | `true` |
|
|
97
|
+
| `path` | SEO-friendly URL path | `summer-sale` |
|
|
98
|
+
|
|
99
|
+
### Multi-Code Promotions
|
|
100
|
+
|
|
101
|
+
For promotions that need unique codes per customer (e.g., influencer campaigns), Spree supports bulk code generation:
|
|
102
|
+
|
|
103
|
+
| Attribute | Description | Example |
|
|
104
|
+
|-----------|-------------|---------|
|
|
105
|
+
| `multi_codes` | Enable bulk code generation | `true` |
|
|
106
|
+
| `number_of_codes` | How many codes to generate | 1000 |
|
|
107
|
+
| `code_prefix` | Prefix for generated codes | `SUMMER` |
|
|
108
|
+
|
|
109
|
+
Generated codes follow the pattern `{prefix}{random}`, e.g., `SUMMER22A0F62A230BD919`.
|
|
110
|
+
|
|
111
|
+
## Rules
|
|
112
|
+
|
|
113
|
+
Rules determine when a promotion is eligible. You can combine multiple rules and configure whether **all** rules must match or **any** rule is sufficient (via `match_policy`).
|
|
114
|
+
|
|
115
|
+
### FirstOrder
|
|
116
|
+
|
|
117
|
+
Applies only to a customer's first order. Checks both user account and email address to prevent abuse.
|
|
118
|
+
|
|
119
|
+
**Use case:** Welcome discount for new customers.
|
|
120
|
+
|
|
121
|
+
### ItemTotal
|
|
122
|
+
|
|
123
|
+
Requires the order subtotal to meet minimum and/or maximum thresholds.
|
|
124
|
+
|
|
125
|
+
**Configuration:**
|
|
126
|
+
- `preferred_amount_min` - Minimum order amount (default: 100.00)
|
|
127
|
+
- `preferred_operator_min` - Comparison operator: `gt` (greater than) or `gte` (greater than or equal)
|
|
128
|
+
- `preferred_amount_max` - Maximum order amount (optional)
|
|
129
|
+
- `preferred_operator_max` - Comparison operator: `lt` (less than) or `lte` (less than or equal)
|
|
130
|
+
|
|
131
|
+
**Use case:** "Free shipping on orders over $50", "10% off orders between $100-$500".
|
|
132
|
+
|
|
133
|
+
### Product
|
|
134
|
+
|
|
135
|
+
Requires specific products to be in the order.
|
|
136
|
+
|
|
137
|
+
**Configuration:**
|
|
138
|
+
- `preferred_match_policy`:
|
|
139
|
+
- `any` - At least one of the specified products
|
|
140
|
+
- `all` - All specified products must be present
|
|
141
|
+
- `none` - None of the specified products (exclusion)
|
|
142
|
+
|
|
143
|
+
**Use case:** "Buy Product A and get 20% off", "Discount excludes sale items".
|
|
144
|
+
|
|
145
|
+
### Taxon
|
|
146
|
+
|
|
147
|
+
Requires products from specific categories (taxons) to be in the order.
|
|
148
|
+
|
|
149
|
+
**Configuration:**
|
|
150
|
+
- `preferred_match_policy`: `any` or `all`
|
|
151
|
+
|
|
152
|
+
The rule automatically includes products in child taxons when a parent taxon is selected.
|
|
153
|
+
|
|
154
|
+
**Use case:** "20% off Electronics", "Buy from Shoes category get 10% off".
|
|
155
|
+
|
|
156
|
+
### User
|
|
157
|
+
|
|
158
|
+
Limits the promotion to specific customer accounts.
|
|
159
|
+
|
|
160
|
+
**Use case:** Employee discounts, VIP customer promotions.
|
|
161
|
+
|
|
162
|
+
### UserLoggedIn
|
|
163
|
+
|
|
164
|
+
Requires the customer to be logged in with an account.
|
|
165
|
+
|
|
166
|
+
**Use case:** Member-only discounts.
|
|
167
|
+
|
|
168
|
+
### OneUsePerUser
|
|
169
|
+
|
|
170
|
+
Ensures each customer can only use the promotion once.
|
|
171
|
+
|
|
172
|
+
**Use case:** One-time welcome offers, limited redemption campaigns.
|
|
173
|
+
|
|
174
|
+
### Country
|
|
175
|
+
|
|
176
|
+
Limits the promotion to orders shipping to a specific country.
|
|
177
|
+
|
|
178
|
+
**Configuration:**
|
|
179
|
+
- `preferred_country_id` or `preferred_country_iso` (ISO 2-letter code)
|
|
180
|
+
|
|
181
|
+
**Use case:** Regional promotions, country-specific campaigns.
|
|
182
|
+
|
|
183
|
+
### Currency
|
|
184
|
+
|
|
185
|
+
Limits the promotion to orders in a specific currency.
|
|
186
|
+
|
|
187
|
+
**Configuration:**
|
|
188
|
+
- `preferred_currency` - Currency code (e.g., "USD", "EUR")
|
|
189
|
+
|
|
190
|
+
**Use case:** Currency-specific pricing strategies.
|
|
191
|
+
|
|
192
|
+
### OptionValue
|
|
193
|
+
|
|
194
|
+
Requires products with specific option values (e.g., size, color) to be in the order.
|
|
195
|
+
|
|
196
|
+
**Configuration:**
|
|
197
|
+
- `preferred_eligible_values` - Array of eligible variant IDs
|
|
198
|
+
|
|
199
|
+
**Use case:** "10% off all red items", "Discount on size XL".
|
|
200
|
+
|
|
201
|
+
### CustomerGroup
|
|
202
|
+
|
|
203
|
+
Limits the promotion to customers belonging to specific customer groups.
|
|
204
|
+
|
|
205
|
+
**Configuration:**
|
|
206
|
+
- `preferred_customer_group_ids` - Array of customer group IDs
|
|
207
|
+
|
|
208
|
+
Customer groups are managed in Admin > Customers > Customer Groups and allow you to segment customers for targeted promotions.
|
|
209
|
+
|
|
210
|
+
**Use case:** VIP programs, loyalty tiers, wholesale pricing, B2B customer segments.
|
|
211
|
+
|
|
212
|
+
## Actions
|
|
213
|
+
|
|
214
|
+
Actions define what happens when a promotion is applied.
|
|
215
|
+
|
|
216
|
+
### CreateAdjustment
|
|
217
|
+
|
|
218
|
+
Creates a discount on the entire order total.
|
|
219
|
+
|
|
220
|
+
**Default calculator:** `FlatPercentItemTotal` (percentage off order)
|
|
221
|
+
|
|
222
|
+
**Available calculators:**
|
|
223
|
+
- `FlatPercentItemTotal` - Percentage off the order total
|
|
224
|
+
- `FlatRate` - Fixed amount off
|
|
225
|
+
- `FlexiRate` - First item at one rate, additional items at another
|
|
226
|
+
- `TieredFlatRate` - Different rates based on order total tiers
|
|
227
|
+
- `TieredPercent` - Different percentages based on order total tiers
|
|
228
|
+
|
|
229
|
+
**Use case:** "10% off your order", "$20 off orders over $100".
|
|
230
|
+
|
|
231
|
+
### CreateItemAdjustments
|
|
232
|
+
|
|
233
|
+
Creates discounts on individual line items. Only applies to items that match the promotion rules (e.g., items in a specific category).
|
|
234
|
+
|
|
235
|
+
**Default calculator:** `PercentOnLineItem` (percentage off each item)
|
|
236
|
+
|
|
237
|
+
The action respects rule actionability - if a Taxon rule specifies "Electronics", only electronics items receive the discount.
|
|
238
|
+
|
|
239
|
+
**Use case:** "15% off shoes", "Buy 2+ shirts get 10% off each".
|
|
240
|
+
|
|
241
|
+
### FreeShipping
|
|
242
|
+
|
|
243
|
+
Makes all shipments free by creating negative adjustments equal to shipping costs.
|
|
244
|
+
|
|
245
|
+
**Use case:** "Free shipping on orders over $75", "Free shipping with code FREESHIP".
|
|
246
|
+
|
|
247
|
+
### CreateLineItems
|
|
248
|
+
|
|
249
|
+
Automatically adds specified products to the cart when the promotion is eligible.
|
|
250
|
+
|
|
251
|
+
**Configuration:**
|
|
252
|
+
- Map of variant IDs to quantities to add
|
|
253
|
+
|
|
254
|
+
The action checks stock availability before adding items. Items are not automatically removed if eligibility is lost - customers must remove them manually.
|
|
255
|
+
|
|
256
|
+
**Use case:** "Free gift with purchase", "Buy 2 get 1 free", "Spend $100 get free sample".
|
|
257
|
+
|
|
258
|
+
## Coupon Codes
|
|
259
|
+
|
|
260
|
+
Coupon codes track promotion usage and can be single-use or multi-use.
|
|
261
|
+
|
|
262
|
+
### Single Code Promotions
|
|
263
|
+
|
|
264
|
+
Set the `code` attribute directly on the promotion. The `usage_limit` controls how many times it can be redeemed.
|
|
265
|
+
|
|
266
|
+
### Multi-Code Promotions
|
|
267
|
+
|
|
268
|
+
For bulk-generated codes, each code tracks its usage state:
|
|
269
|
+
|
|
270
|
+
| Attribute | Description | Example |
|
|
271
|
+
|-----------|-------------|---------|
|
|
272
|
+
| `code` | The unique code | `SUMMER22A0F62A230BD919` |
|
|
273
|
+
| `state` | Usage state | `unused`, `used` |
|
|
274
|
+
|
|
275
|
+
## Applying Coupon Codes via Store API
|
|
276
|
+
|
|
277
|
+
Customers apply coupon codes during checkout via the Store API:
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
```typescript SDK
|
|
281
|
+
// Apply a coupon code to the cart
|
|
282
|
+
const cart = await client.carts.couponCodes.apply('cart_abc123', 'SUMMER20', {
|
|
283
|
+
spreeToken: '<token>',
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
// Remove a coupon code from the cart
|
|
287
|
+
await client.carts.couponCodes.remove('cart_abc123', 'SUMMER20', {
|
|
288
|
+
spreeToken: '<token>',
|
|
289
|
+
})
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
```bash cURL
|
|
293
|
+
# Apply a coupon code
|
|
294
|
+
curl -X POST 'https://api.mystore.com/api/v3/store/carts/cart_abc123/coupon_codes' \
|
|
295
|
+
-H 'Authorization: Bearer spree_pk_xxx' \
|
|
296
|
+
-H 'X-Spree-Token: <token>' \
|
|
297
|
+
-H 'Content-Type: application/json' \
|
|
298
|
+
-d '{ "code": "SUMMER20" }'
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
Automatic promotions are applied without any customer action — they are evaluated on every order update.
|
|
303
|
+
|
|
304
|
+
## Promotion Flow
|
|
305
|
+
|
|
306
|
+
How promotions are evaluated and applied:
|
|
307
|
+
|
|
308
|
+
1. **Order Update** — When an order is updated, the system checks all eligible promotions
|
|
309
|
+
2. **Eligibility Check** — For each promotion:
|
|
310
|
+
- Check if within `starts_at` and `expires_at` range
|
|
311
|
+
- Check if under `usage_limit`
|
|
312
|
+
- Evaluate all rules based on `match_policy` (all or any)
|
|
313
|
+
3. **Action Execution** — If eligible, each action is applied
|
|
314
|
+
4. **Tracking** — Applied promotions are recorded on the order
|
|
315
|
+
5. **Re-evaluation** — Eligibility is re-checked on every order update; adjustments from ineligible promotions are removed
|
|
316
|
+
|
|
317
|
+
## Related Documentation
|
|
318
|
+
|
|
319
|
+
- [Build Custom Promotion Rules & Actions](/developer/how-to/custom-promotion) - Step-by-step guide to creating custom rules and actions
|
|
320
|
+
- [Calculators](/developer/core-concepts/calculators) - Learn about promotion calculators
|
|
321
|
+
- [Orders](/developer/core-concepts/orders) - Understanding order processing
|
|
322
|
+
- [Customization Quickstart](/developer/customization/quickstart) - Overview of customization options
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Reports
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Spree provides a flexible reporting system that allows you to generate data exports for sales analytics, product performance, and custom business metrics. Reports are generated asynchronously and delivered as downloadable CSV files.
|
|
8
|
+
|
|
9
|
+
### Report System Diagram
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
erDiagram
|
|
13
|
+
Report {
|
|
14
|
+
string type
|
|
15
|
+
string currency
|
|
16
|
+
datetime date_from
|
|
17
|
+
datetime date_to
|
|
18
|
+
bigint store_id
|
|
19
|
+
bigint user_id
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
ReportLineItem {
|
|
23
|
+
string record
|
|
24
|
+
string report
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Store {
|
|
28
|
+
string name
|
|
29
|
+
string code
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
AdminUser {
|
|
33
|
+
string email
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
GenerateJob {
|
|
37
|
+
string report_id
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Report ||--|| Store : "belongs to"
|
|
41
|
+
Report ||--o| AdminUser : "belongs to"
|
|
42
|
+
Report ||--o{ ReportLineItem : "generates"
|
|
43
|
+
Report ||--|| GenerateJob : "triggers"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Key relationships:**
|
|
47
|
+
- **Report** is the base model for all report types using Single Table Inheritance (STI)
|
|
48
|
+
- **ReportLineItem** transforms raw database records into formatted report rows
|
|
49
|
+
- Reports are scoped to a **Store** and optionally track the **AdminUser** who created them
|
|
50
|
+
- **GenerateJob** handles asynchronous CSV generation via the events system
|
|
51
|
+
|
|
52
|
+
## Architecture
|
|
53
|
+
|
|
54
|
+
The reporting system uses several design patterns:
|
|
55
|
+
|
|
56
|
+
1. **Single Table Inheritance (STI)**: All report types inherit from `Spree::Report` and are stored in the same database table with a `type` column
|
|
57
|
+
2. **Presenter Pattern**: `Spree::ReportLineItem` subclasses transform raw records into formatted output
|
|
58
|
+
3. **Event-Driven Processing**: Report generation is triggered asynchronously via Spree's events system
|
|
59
|
+
4. **Registry Pattern**: Reports are registered in `Spree.reports` for discovery and validation
|
|
60
|
+
|
|
61
|
+
## Built-in Reports
|
|
62
|
+
|
|
63
|
+
Spree ships with two built-in reports:
|
|
64
|
+
|
|
65
|
+
### Sales Total Report
|
|
66
|
+
|
|
67
|
+
The Sales Total report provides line-item level detail for all completed orders within a date range.
|
|
68
|
+
|
|
69
|
+
**Columns:**
|
|
70
|
+
- `date` - Order completion date
|
|
71
|
+
- `order` - Order number
|
|
72
|
+
- `product` - Variant descriptive name
|
|
73
|
+
- `quantity` - Line item quantity
|
|
74
|
+
- `pre_tax_amount` - Amount before taxes
|
|
75
|
+
- `promo_total` - Promotion discounts applied
|
|
76
|
+
- `shipment_total` - Shipping costs
|
|
77
|
+
- `tax_total` - Tax amount
|
|
78
|
+
- `total` - Final amount including all adjustments
|
|
79
|
+
|
|
80
|
+
### Products Performance Report
|
|
81
|
+
|
|
82
|
+
The Products Performance report aggregates sales metrics by product for the specified period.
|
|
83
|
+
|
|
84
|
+
**Columns:**
|
|
85
|
+
- `sku` - Product SKU
|
|
86
|
+
- `name` - Product name
|
|
87
|
+
- `vendor` - Vendor name (if multi-vendor enabled)
|
|
88
|
+
- `brand` - Brand name
|
|
89
|
+
- `category_lvl0/1/2` - Category hierarchy from main taxon
|
|
90
|
+
- `price` - Current product price
|
|
91
|
+
- `weeks_online` - Weeks since product became available
|
|
92
|
+
- `pre_tax_amount` - Total pre-tax sales
|
|
93
|
+
- `tax_total` - Total taxes collected
|
|
94
|
+
- `quantity` - Total units sold
|
|
95
|
+
- `promo_total` - Total promotion discounts
|
|
96
|
+
- `total` - Total revenue
|
|
97
|
+
|
|
98
|
+
## How Reports Work Internally
|
|
99
|
+
|
|
100
|
+
### Generation Flow
|
|
101
|
+
|
|
102
|
+
1. **User creates report** via admin UI with date range, currency, and optional vendor
|
|
103
|
+
2. **Report is saved** to database with status tracking
|
|
104
|
+
3. **`report.created` event fires** via `publishes_lifecycle_events` concern
|
|
105
|
+
4. **`Spree::ReportSubscriber` catches event** and enqueues `GenerateJob`
|
|
106
|
+
5. **Background job runs `report.generate`**:
|
|
107
|
+
- Iterates through `line_items_scope` in batches
|
|
108
|
+
- Transforms each record via `ReportLineItem`
|
|
109
|
+
- Writes CSV to temp file
|
|
110
|
+
- Attaches CSV to report via ActiveStorage
|
|
111
|
+
- Sends notification email to user
|
|
112
|
+
|
|
113
|
+
### Key Files
|
|
114
|
+
|
|
115
|
+
| File | Purpose |
|
|
116
|
+
|------|---------|
|
|
117
|
+
| `core/app/models/spree/report.rb` | Base report model |
|
|
118
|
+
| `core/app/models/spree/report_line_item.rb` | Base line item presenter |
|
|
119
|
+
| `core/app/models/spree/reports/*.rb` | Built-in report implementations |
|
|
120
|
+
| `core/app/models/spree/report_line_items/*.rb` | Built-in line item formatters |
|
|
121
|
+
| `core/app/subscribers/spree/report_subscriber.rb` | Event subscriber for async generation |
|
|
122
|
+
| `core/app/jobs/spree/reports/generate_job.rb` | Background job for CSV creation |
|
|
123
|
+
| `core/app/mailers/spree/report_mailer.rb` | Notification emails |
|
|
124
|
+
| `admin/app/controllers/spree/admin/reports_controller.rb` | Admin UI controller |
|
|
125
|
+
|
|
126
|
+
### Report Base Class Methods
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
# Returns the scope of records for the report
|
|
130
|
+
def line_items_scope
|
|
131
|
+
raise NotImplementedError
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Returns formatted line items (with optional limit for preview)
|
|
135
|
+
def line_items(options = {})
|
|
136
|
+
scope = line_items_scope
|
|
137
|
+
scope = scope.limit(options[:limit]) if options[:limit].present?
|
|
138
|
+
scope.map { |record| line_item_class.new(record: record, report: self) }
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Generates the CSV file and handles attachment
|
|
142
|
+
def generate
|
|
143
|
+
generate_csv
|
|
144
|
+
handle_attachment
|
|
145
|
+
send_report_done_email
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Returns the corresponding line item class
|
|
149
|
+
def line_item_class
|
|
150
|
+
"Spree::ReportLineItems::#{type.demodulize}".safe_constantize
|
|
151
|
+
end
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### ReportLineItem Base Class Methods
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
# Returns column headers for display
|
|
158
|
+
def self.headers
|
|
159
|
+
attribute_types.keys.map do |attribute|
|
|
160
|
+
{ name: attribute.to_sym, label: Spree.t(attribute.to_sym) }
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Returns column names for CSV header row
|
|
165
|
+
def self.csv_headers
|
|
166
|
+
attribute_types.keys
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Converts line item to CSV row array
|
|
170
|
+
def to_csv
|
|
171
|
+
self.class.attribute_types.keys.map { |attr| send(attr) }
|
|
172
|
+
end
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Configuration
|
|
176
|
+
|
|
177
|
+
### Report Preview Limit
|
|
178
|
+
|
|
179
|
+
Configure the number of preview rows shown in the admin UI:
|
|
180
|
+
|
|
181
|
+
```ruby config/initializers/spree.rb
|
|
182
|
+
Spree::Admin::RuntimeConfig.reports_line_items_limit = 100
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Background Job Queue
|
|
186
|
+
|
|
187
|
+
Reports use a dedicated queue. Configure your job processor:
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
# Sidekiq example
|
|
191
|
+
Spree.queues.reports = :reports
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Permissions
|
|
195
|
+
|
|
196
|
+
Report access is controlled by CanCanCan. By default, only users with the `:manage` ability on `Spree::Report` can access reports. Configure permissions in your permission sets.
|
|
197
|
+
|
|
198
|
+
```ruby
|
|
199
|
+
# Example: Allow all admins to view reports
|
|
200
|
+
can :manage, Spree::Report
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Related Documentation
|
|
204
|
+
|
|
205
|
+
- [Build a Custom Report](/developer/how-to/custom-report) - Step-by-step guide to creating custom reports
|
|
206
|
+
- [Events](/developer/core-concepts/events) - How report generation uses the events system
|