@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.
Files changed (183) hide show
  1. package/README.md +54 -0
  2. package/dist/api-reference/platform/authentication.md +38 -0
  3. package/dist/api-reference/store-api/authentication.md +188 -0
  4. package/dist/api-reference/store-api/errors.md +277 -0
  5. package/dist/api-reference/store-api/idempotency.md +129 -0
  6. package/dist/api-reference/store-api/introduction.md +34 -0
  7. package/dist/api-reference/store-api/localization.md +279 -0
  8. package/dist/api-reference/store-api/metadata.md +160 -0
  9. package/dist/api-reference/store-api/monetary-amounts.md +65 -0
  10. package/dist/api-reference/store-api/querying.md +399 -0
  11. package/dist/api-reference/store-api/rate-limitting.md +103 -0
  12. package/dist/api-reference/store-api/relations.md +185 -0
  13. package/dist/api-reference/storefront/authentication.md +88 -0
  14. package/dist/api-reference/tutorials/adyen-integration-guide-for-android.md +165 -0
  15. package/dist/api-reference/tutorials/adyen-integration-guide-for-ios.md +194 -0
  16. package/dist/api-reference/tutorials/quick-checkout-with-stripe.md +248 -0
  17. package/dist/api-reference/v2/fetching-multiple-resources.md +26 -0
  18. package/dist/api-reference/v2/filtering-and-sorting.md +53 -0
  19. package/dist/api-reference/v2/introduction.md +22 -0
  20. package/dist/api-reference/v2/pagination.md +37 -0
  21. package/dist/api-reference/webhooks-events.md +883 -0
  22. package/dist/developer/admin/admin.md +205 -0
  23. package/dist/developer/admin/authentication.md +59 -0
  24. package/dist/developer/admin/components.md +711 -0
  25. package/dist/developer/admin/custom-css.md +243 -0
  26. package/dist/developer/admin/custom-javascript.md +116 -0
  27. package/dist/developer/admin/extending-ui.md +1964 -0
  28. package/dist/developer/admin/form-builder.md +444 -0
  29. package/dist/developer/admin/helper-methods.md +531 -0
  30. package/dist/developer/admin/navigation.md +805 -0
  31. package/dist/developer/admin/tables.md +491 -0
  32. package/dist/developer/advanced/adding_spree_to_rails_app.md +106 -0
  33. package/dist/developer/cli/quickstart.md +137 -0
  34. package/dist/developer/contributing/creating-an-extension.md +258 -0
  35. package/dist/developer/contributing/developing-spree.md +339 -0
  36. package/dist/developer/contributing/quickstart.md +32 -0
  37. package/dist/developer/contributing/updating-extensions.md +67 -0
  38. package/dist/developer/core-concepts/addresses.md +265 -0
  39. package/dist/developer/core-concepts/adjustments.md +107 -0
  40. package/dist/developer/core-concepts/architecture.md +177 -0
  41. package/dist/developer/core-concepts/calculators.md +323 -0
  42. package/dist/developer/core-concepts/customers.md +230 -0
  43. package/dist/developer/core-concepts/events.md +624 -0
  44. package/dist/developer/core-concepts/imports-exports.md +698 -0
  45. package/dist/developer/core-concepts/inventory.md +191 -0
  46. package/dist/developer/core-concepts/markets.md +250 -0
  47. package/dist/developer/core-concepts/media.md +167 -0
  48. package/dist/developer/core-concepts/metafields.md +187 -0
  49. package/dist/developer/core-concepts/orders.md +328 -0
  50. package/dist/developer/core-concepts/payments.md +710 -0
  51. package/dist/developer/core-concepts/pricing.md +163 -0
  52. package/dist/developer/core-concepts/products.md +360 -0
  53. package/dist/developer/core-concepts/promotions.md +322 -0
  54. package/dist/developer/core-concepts/reports.md +206 -0
  55. package/dist/developer/core-concepts/search-filtering.md +237 -0
  56. package/dist/developer/core-concepts/shipments.md +212 -0
  57. package/dist/developer/core-concepts/slugs.md +111 -0
  58. package/dist/developer/core-concepts/staff-roles.md +123 -0
  59. package/dist/developer/core-concepts/store-credits-gift-cards.md +317 -0
  60. package/dist/developer/core-concepts/stores.md +117 -0
  61. package/dist/developer/core-concepts/taxes.md +135 -0
  62. package/dist/developer/core-concepts/translations.md +120 -0
  63. package/dist/developer/core-concepts/users.md +299 -0
  64. package/dist/developer/core-concepts/webhooks.md +378 -0
  65. package/dist/developer/create-spree-app/quickstart.md +158 -0
  66. package/dist/developer/customization/api.md +93 -0
  67. package/dist/developer/customization/authentication.md +88 -0
  68. package/dist/developer/customization/checkout.md +204 -0
  69. package/dist/developer/customization/configuration.md +55 -0
  70. package/dist/developer/customization/decorators.md +523 -0
  71. package/dist/developer/customization/dependencies.md +232 -0
  72. package/dist/developer/customization/emails.md +21 -0
  73. package/dist/developer/customization/extensions.md +92 -0
  74. package/dist/developer/customization/metadata.md +236 -0
  75. package/dist/developer/customization/model-preferences.md +130 -0
  76. package/dist/developer/customization/permissions.md +265 -0
  77. package/dist/developer/customization/quickstart.md +229 -0
  78. package/dist/developer/customization/routes.md +24 -0
  79. package/dist/developer/customization/v4/admin-panel.md +78 -0
  80. package/dist/developer/customization/v4/authentication.md +210 -0
  81. package/dist/developer/customization/v4/checkout.md +212 -0
  82. package/dist/developer/customization/v4/deface.md +251 -0
  83. package/dist/developer/customization/v4/images.md +86 -0
  84. package/dist/developer/customization/v4/storefront.md +450 -0
  85. package/dist/developer/deployment/assets.md +87 -0
  86. package/dist/developer/deployment/aws.md +335 -0
  87. package/dist/developer/deployment/caching.md +27 -0
  88. package/dist/developer/deployment/cdn.md +39 -0
  89. package/dist/developer/deployment/database.md +155 -0
  90. package/dist/developer/deployment/docker.md +128 -0
  91. package/dist/developer/deployment/emails.md +77 -0
  92. package/dist/developer/deployment/environment_variables.md +111 -0
  93. package/dist/developer/deployment/heroku.md +51 -0
  94. package/dist/developer/deployment/render.md +95 -0
  95. package/dist/developer/getting-started/quickstart.md +82 -0
  96. package/dist/developer/how-to/custom-payment-method.md +374 -0
  97. package/dist/developer/how-to/custom-promotion.md +373 -0
  98. package/dist/developer/how-to/custom-report.md +387 -0
  99. package/dist/developer/how-to/custom-search-provider.md +230 -0
  100. package/dist/developer/multi-store/quickstart.md +71 -0
  101. package/dist/developer/multi-store/setup.md +38 -0
  102. package/dist/developer/multi-tenant/configuration.md +41 -0
  103. package/dist/developer/multi-tenant/core-concepts.md +75 -0
  104. package/dist/developer/multi-tenant/installation.md +96 -0
  105. package/dist/developer/multi-tenant/quickstart.md +20 -0
  106. package/dist/developer/multi-vendor/installation.md +45 -0
  107. package/dist/developer/multi-vendor/quickstart.md +17 -0
  108. package/dist/developer/sdk/admin/quickstart.md +22 -0
  109. package/dist/developer/sdk/authentication.md +89 -0
  110. package/dist/developer/sdk/configuration.md +225 -0
  111. package/dist/developer/sdk/quickstart.md +82 -0
  112. package/dist/developer/sdk/store/account.md +67 -0
  113. package/dist/developer/sdk/store/cart-checkout.md +140 -0
  114. package/dist/developer/sdk/store/markets.md +151 -0
  115. package/dist/developer/sdk/store/payments.md +96 -0
  116. package/dist/developer/sdk/store/products.md +149 -0
  117. package/dist/developer/sdk/store/wishlists.md +52 -0
  118. package/dist/developer/security/pci_compliance.md +15 -0
  119. package/dist/developer/security/security_policy.md +68 -0
  120. package/dist/developer/storefront/blocks.md +285 -0
  121. package/dist/developer/storefront/custom-css.md +260 -0
  122. package/dist/developer/storefront/custom-javascript.md +166 -0
  123. package/dist/developer/storefront/helper-methods.md +1288 -0
  124. package/dist/developer/storefront/links.md +298 -0
  125. package/dist/developer/storefront/nextjs/architecture.md +150 -0
  126. package/dist/developer/storefront/nextjs/customization.md +141 -0
  127. package/dist/developer/storefront/nextjs/deployment.md +180 -0
  128. package/dist/developer/storefront/nextjs/quickstart.md +92 -0
  129. package/dist/developer/storefront/nextjs/spree-next-package.md +314 -0
  130. package/dist/developer/storefront/pages.md +163 -0
  131. package/dist/developer/storefront/sections.md +569 -0
  132. package/dist/developer/storefront/storefront.md +56 -0
  133. package/dist/developer/storefront/themes.md +161 -0
  134. package/dist/developer/tutorial/admin.md +134 -0
  135. package/dist/developer/tutorial/extending-models.md +380 -0
  136. package/dist/developer/tutorial/file-uploads.md +121 -0
  137. package/dist/developer/tutorial/introduction.md +33 -0
  138. package/dist/developer/tutorial/model.md +41 -0
  139. package/dist/developer/tutorial/page-builder.md +487 -0
  140. package/dist/developer/tutorial/rich-text.md +73 -0
  141. package/dist/developer/tutorial/seo.md +332 -0
  142. package/dist/developer/tutorial/storefront.md +352 -0
  143. package/dist/developer/tutorial/testing.md +558 -0
  144. package/dist/developer/upgrades/2.0-to-2.1.md +46 -0
  145. package/dist/developer/upgrades/2.1-to-2.2.md +59 -0
  146. package/dist/developer/upgrades/2.2-to-2.3.md +44 -0
  147. package/dist/developer/upgrades/2.3-to-2.4.md +42 -0
  148. package/dist/developer/upgrades/3.0-to-3.1.md +47 -0
  149. package/dist/developer/upgrades/3.1-to-3.2.md +34 -0
  150. package/dist/developer/upgrades/3.2-to-3.3.md +70 -0
  151. package/dist/developer/upgrades/3.3-to-3.4.md +36 -0
  152. package/dist/developer/upgrades/3.4-to-3.5.md +44 -0
  153. package/dist/developer/upgrades/3.5-to-3.6.md +40 -0
  154. package/dist/developer/upgrades/3.6-to-3.7.md +62 -0
  155. package/dist/developer/upgrades/3.7-to-4.0.md +152 -0
  156. package/dist/developer/upgrades/4.0-to-4.1.md +92 -0
  157. package/dist/developer/upgrades/4.1-to-4.2.md +109 -0
  158. package/dist/developer/upgrades/4.10-to-5.0.md +129 -0
  159. package/dist/developer/upgrades/4.2-to-4.3.md +100 -0
  160. package/dist/developer/upgrades/4.3-to-4.4.md +125 -0
  161. package/dist/developer/upgrades/4.4-to-4.5.md +94 -0
  162. package/dist/developer/upgrades/4.5-to-4.6.md +119 -0
  163. package/dist/developer/upgrades/4.6-to-4.7.md +39 -0
  164. package/dist/developer/upgrades/4.8-to-4.9.md +24 -0
  165. package/dist/developer/upgrades/4.9-to-4.10.md +24 -0
  166. package/dist/developer/upgrades/4.x-to-4.8.md +52 -0
  167. package/dist/developer/upgrades/5.0-to-5.1.md +28 -0
  168. package/dist/developer/upgrades/5.1-to-5.2.md +127 -0
  169. package/dist/developer/upgrades/5.2-to-5.3.md +338 -0
  170. package/dist/developer/upgrades/5.3-to-5.4.md +248 -0
  171. package/dist/developer/upgrades/quickstart.md +36 -0
  172. package/dist/integrations/analytics/google-analytics.md +64 -0
  173. package/dist/integrations/analytics/google-tag-manager.md +78 -0
  174. package/dist/integrations/integrations.md +39 -0
  175. package/dist/integrations/marketing/klaviyo.md +99 -0
  176. package/dist/integrations/payments/adyen.md +90 -0
  177. package/dist/integrations/payments/paypal.md +41 -0
  178. package/dist/integrations/payments/razorpay.md +45 -0
  179. package/dist/integrations/payments/stripe.md +109 -0
  180. package/dist/integrations/search/meilisearch.md +236 -0
  181. package/dist/integrations/sso-mfa-social-login/admin-dashboard.md +57 -0
  182. package/dist/integrations/sso-mfa-social-login/storefront.md +56 -0
  183. 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