@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,323 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Calculators
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
### Calculator Model Diagram
|
|
8
|
+
|
|
9
|
+
```mermaid
|
|
10
|
+
erDiagram
|
|
11
|
+
Calculator {
|
|
12
|
+
string type
|
|
13
|
+
string calculable_type
|
|
14
|
+
text preferences
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
TaxRate {
|
|
18
|
+
string name
|
|
19
|
+
decimal amount
|
|
20
|
+
boolean included_in_price
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
ShippingMethod {
|
|
24
|
+
string name
|
|
25
|
+
string display_on
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
PromotionAction {
|
|
29
|
+
string type
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
Adjustment {
|
|
33
|
+
decimal amount
|
|
34
|
+
string label
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
TaxRate ||--|| Calculator : "has one"
|
|
38
|
+
ShippingMethod ||--|| Calculator : "has one"
|
|
39
|
+
PromotionAction ||--|| Calculator : "has one"
|
|
40
|
+
TaxRate ||--o{ Adjustment : "creates"
|
|
41
|
+
ShippingMethod ||--o{ ShippingRate : "calculates"
|
|
42
|
+
PromotionAction ||--o{ Adjustment : "creates"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Key relationships:**
|
|
46
|
+
- **Calculator** computes amounts for various features
|
|
47
|
+
- Used by **[Tax Rates](/developer/core-concepts/taxes)** to calculate tax amounts
|
|
48
|
+
- Used by **[Shipping Methods](/developer/core-concepts/shipments)** to calculate shipping costs
|
|
49
|
+
- Used by **[Promotion Actions](/developer/core-concepts/promotions)** to calculate discounts
|
|
50
|
+
- Calculators store preferences (rates, percentages, etc.) for their calculations
|
|
51
|
+
|
|
52
|
+
Spree makes extensive use of the `Spree::Calculator` model and there are several subclasses provided to deal with various types of calculations flat rate, percentage discount, sales tax, VAT, etc. All calculators extend the `Spree::Calculator` class and must provide the following methods:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
def self.description
|
|
56
|
+
# Human readable description of the calculator
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def compute(object=nil)
|
|
60
|
+
# Returns the value after performing the required calculation
|
|
61
|
+
end
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Calculators link to a `calculable` object, which are typically one of `Spree::ShippingMethod`, `Spree::TaxRate`, or `Spree::Promotion::Actions::CreateAdjustment`. These three classes use the `Spree::Core::CalculatedAdjustment` module described below to provide an easy way to calculate adjustments for their objects.
|
|
65
|
+
|
|
66
|
+
## Available Calculators
|
|
67
|
+
|
|
68
|
+
The following are descriptions of the currently available calculators in Spree. If you would like to add your own, please see the [Creating a New Calculator](#creating-a-new-calculator) section.
|
|
69
|
+
|
|
70
|
+
### Default Tax
|
|
71
|
+
|
|
72
|
+
For information about this calculator, please read the [Taxes](/developer/core-concepts/taxes) guide.
|
|
73
|
+
|
|
74
|
+
### Flat Percent Per Item Total
|
|
75
|
+
|
|
76
|
+
This calculator has one preference: `flat_percent` and can be set like this:
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
calculator.preferred_flat_percent = 10
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This calculator takes an order and calculates an amount using this calculation:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
[item total] x [flat percentage]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
For example, if an order had an item total of `$31` and the calculator was configured to have a flat percent amount of `10`, the discount would be `$3.10`, because `$31 x 10% = $3.10`.
|
|
89
|
+
|
|
90
|
+
### Flat Rate
|
|
91
|
+
|
|
92
|
+
This calculator can be used to provide a flat rate discount.
|
|
93
|
+
|
|
94
|
+
This calculator has two preferences: `amount` and `currency`. These can be set like this:
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
calculator.preferred_amount = 10
|
|
98
|
+
calculator.currency = "USD"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The currency for this calculator is used to check to see if a shipping method is available for an order. If an order's currency does not match the shipping method's currency, then that shipping method will not be displayed on the frontend.
|
|
102
|
+
|
|
103
|
+
This calculator can take any object and will return simply the preferred amount.
|
|
104
|
+
|
|
105
|
+
### Flexi Rate
|
|
106
|
+
|
|
107
|
+
This calculator is typically used for promotional discounts when you want a specific discount for the first product, and then subsequent discounts for other products, up to a certain amount.
|
|
108
|
+
|
|
109
|
+
This calculator takes three preferences:
|
|
110
|
+
|
|
111
|
+
* `first_item`: The discounted price of the first items.
|
|
112
|
+
* `additional_item`: The discounted price of subsequent items.
|
|
113
|
+
* `max_items`: The maximum number of items this discount applies to.
|
|
114
|
+
|
|
115
|
+
The calculator computes based on this:
|
|
116
|
+
|
|
117
|
+
```text
|
|
118
|
+
[first item discount] + (([items_count*] - 1) x [additional item discount])
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
* up to the `max_items`
|
|
122
|
+
|
|
123
|
+
Thus, if you have ten items in your shopping cart, your `first_item` preference is set to `$10`, your `additional_items` preference is set to `$5`, and your `max_items` preference is set to `4`, the total discount would be `$25`:
|
|
124
|
+
|
|
125
|
+
* `$10` for the first item
|
|
126
|
+
* `$5` for each of the `3` subsequent items: `$5 \* 3 = $15`
|
|
127
|
+
* `$0` for the remaining `6` items
|
|
128
|
+
|
|
129
|
+
### Per Item
|
|
130
|
+
|
|
131
|
+
The Per Item calculator computes a value for every item within an order. This is useful for providing a discount for a specific product, without it affecting others.
|
|
132
|
+
|
|
133
|
+
This calculator takes two preferences:
|
|
134
|
+
|
|
135
|
+
* `amount`: The amount per item to calculate.
|
|
136
|
+
* `currency`: The currency for this calculator.
|
|
137
|
+
|
|
138
|
+
This calculator depends on its `calculable` responding to a `promotion` method, which should return a `Spree::Promotion` or similar object. This object should then return a list of rules, which should respond to a `products` method. This is used to return a result of matching products.
|
|
139
|
+
|
|
140
|
+
The list of matching products is compared against the line items for the order being calculated. If any of the matching products are included in the order, they are eligible for this calculator. The calculation is this:
|
|
141
|
+
|
|
142
|
+
\[matching product quantity\] x \[amount\]
|
|
143
|
+
|
|
144
|
+
Every matching product within an order will add to the calculator's total. For example, assuming the calculator has an `amount` of 5 and there's an order with the following line items:
|
|
145
|
+
|
|
146
|
+
* Product A: `$15.00` x `2` within matching products
|
|
147
|
+
* Product B: `$10.00` x `1` within matching products
|
|
148
|
+
* Product C: `$20.00` x `4` excluded from matching products
|
|
149
|
+
|
|
150
|
+
The calculation would be:
|
|
151
|
+
|
|
152
|
+
```text
|
|
153
|
+
= (2 x 5) + (1 x 5)
|
|
154
|
+
= 10 + 5
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
meaning the calculator will compute an amount of 15.
|
|
158
|
+
|
|
159
|
+
### Percent Per Item
|
|
160
|
+
|
|
161
|
+
The Percent Per Item calculator works in a near-identical fashion to the [Per Item Calculator](#per-item), with the exception that rather than providing a flat-rate per item, it is a percentage.
|
|
162
|
+
|
|
163
|
+
Assuming a calculator amount of 10% and an order such as this:
|
|
164
|
+
|
|
165
|
+
* Product A: $15.00 x 2 within matching products
|
|
166
|
+
* Product B: $10.00 x 1 within matching products
|
|
167
|
+
* Product C: $20.00 x 4 excluded from matching products
|
|
168
|
+
|
|
169
|
+
The calculation would be:
|
|
170
|
+
|
|
171
|
+
```text
|
|
172
|
+
= ($15 x 2 x 10%) + ($10 x 10%)
|
|
173
|
+
= ($30 x 10%) + ($10 x 10%)
|
|
174
|
+
= $3 + $1
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The calculator will calculate a discount of $4.
|
|
178
|
+
|
|
179
|
+
### Price Sack
|
|
180
|
+
|
|
181
|
+
The Price Sack calculator is useful for when you want to provide a discount for an order which is over a certain price. The calculator has four preferences:
|
|
182
|
+
|
|
183
|
+
* `minimal_amount`: The minimum amount for the line items total to trigger the calculator.
|
|
184
|
+
* `discount_amount`: The amount to discount from the order if the line items total is equal to or greater than the `minimal_amount`.
|
|
185
|
+
* `normal_amount`: The amount to discount from the order if the line items total is less than the `minimal_amount`.
|
|
186
|
+
* `currency`: The currency for this calculator. Defaults to the store currency
|
|
187
|
+
|
|
188
|
+
Suppose you have a Price Sack calculator with a `minimal_amount` preference of `$50`, a `normal_amount` preference of `$2`, and a `discount_amount` of `$5`. An order with a line items total of `$60` would result in a discount of `$5` for the whole order. An order of `$20` would result in a discount of `$2`.
|
|
189
|
+
|
|
190
|
+
## Creating a New Calculator
|
|
191
|
+
|
|
192
|
+
To create a new calculator for Spree, you need to do two things. The first is to inherit from the `Spree::Calculator` class and define `description` and `compute` methods on that class:
|
|
193
|
+
|
|
194
|
+
```ruby
|
|
195
|
+
class CustomCalculator < Spree::Calculator
|
|
196
|
+
def self.description
|
|
197
|
+
# Human readable description of the calculator
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def compute(object=nil)
|
|
201
|
+
# Returns the value after performing the required calculation
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
If you are creating a new calculator for shipping methods, please be aware that you need to inherit from `Spree::ShippingCalculator` instead, and define a `compute_package` method:
|
|
207
|
+
|
|
208
|
+
```ruby
|
|
209
|
+
class CustomCalculator < Spree::ShippingCalculator
|
|
210
|
+
def self.description
|
|
211
|
+
# Human readable description of the calculator
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def compute_package(package)
|
|
215
|
+
# Returns the value after performing the required calculation
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The second thing is to register this calculator as a tax, shipping, or promotion adjustment calculator by calling code like this at the end of `config/initializers/spree.rb` inside your application `config` variable defined for brevity:
|
|
221
|
+
|
|
222
|
+
**Spree 5.2+:**
|
|
223
|
+
|
|
224
|
+
```ruby config/initializers/spree.rb
|
|
225
|
+
Rails.application.config.after_initialize do
|
|
226
|
+
Spree.calculators.tax_rates << CustomCalculator
|
|
227
|
+
Spree.calculators.shipping_methods << CustomCalculator
|
|
228
|
+
Spree.calculators.promotion_actions_create_adjustments << CustomCalculator
|
|
229
|
+
end
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Spree 5.1 and below:**
|
|
233
|
+
|
|
234
|
+
```ruby config/initializers/spree.rb
|
|
235
|
+
Rails.application.config.spree.calculators.tax_rates << CustomCalculator
|
|
236
|
+
Rails.application.config.spree.calculators.shipping_methods << CustomCalculator
|
|
237
|
+
Rails.application.config.spree.calculators.promotion_actions_create_adjustments << CustomCalculator
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
For example if your calculator is placed in `app/models/spree/calculator/shipping/my_own_calculator.rb` you should call:
|
|
242
|
+
|
|
243
|
+
**Spree 5.2+:**
|
|
244
|
+
|
|
245
|
+
```ruby config/initializers/spree.rb
|
|
246
|
+
Rails.application.config.after_initialize do
|
|
247
|
+
Spree.calculators.shipping_methods << Spree::Calculator::Shipping::MyOwnCalculator
|
|
248
|
+
end
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Spree 5.1 and below:**
|
|
252
|
+
|
|
253
|
+
```ruby config/initializers/spree.rb
|
|
254
|
+
Rails.application.config.spree.calculators.shipping_methods << Spree::Calculator::Shipping::MyOwnCalculator
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
### Determining Availability
|
|
259
|
+
|
|
260
|
+
By default, all shipping method calculators are available at all times. If you wish to make this dependent on something from the order, you can re-define the `available?` method inside your calculator:
|
|
261
|
+
|
|
262
|
+
```ruby app/models/custom_calculator.rb
|
|
263
|
+
class CustomCalculator < Spree::Calculator
|
|
264
|
+
def available?(object)
|
|
265
|
+
object.currency == "USD"
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Calculated Adjustments
|
|
271
|
+
|
|
272
|
+
If you wish to use Spree's calculator functionality for your own application, you can include the `Spree::Core::CalculatedAdjustments` module into a model of your choosing.
|
|
273
|
+
|
|
274
|
+
```ruby app/models/plan.rb
|
|
275
|
+
class Plan < ActiveRecord::Base
|
|
276
|
+
include Spree::Core::CalculatedAdjustments
|
|
277
|
+
end
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
To have calculators available for this class, you will need to register them:
|
|
281
|
+
|
|
282
|
+
**Spree 5.2+:**
|
|
283
|
+
|
|
284
|
+
```ruby config/initializers/spree.rb
|
|
285
|
+
Rails.application.config.after_initialize do
|
|
286
|
+
Spree.calculators.plans << CustomCalculator
|
|
287
|
+
end
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Spree 5.1 and below:**
|
|
291
|
+
|
|
292
|
+
```ruby config/initializers/spree.rb
|
|
293
|
+
Rails.application.config.spree.calculators.plans << CustomCalculator
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
Then you can access these calculators by calling this method:
|
|
298
|
+
|
|
299
|
+
```ruby
|
|
300
|
+
Plan.calculators
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Using this method, you can then display the calculators as you please. Each object for this new class will need to have a calculator associated so that adjustments can be calculated on them.
|
|
304
|
+
|
|
305
|
+
This module provides a `has_one` association to a `calculator` object, as well as some convenience helpers for creating and updating adjustments for objects. Assuming that an object has a calculator associated with it first, creating an adjustment is simple:
|
|
306
|
+
|
|
307
|
+
```ruby
|
|
308
|
+
plan.create_adjustment("#{plan.name}", <target object>, <calculable object>)
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
To update this adjustment:
|
|
312
|
+
|
|
313
|
+
```ruby
|
|
314
|
+
plan.update_adjustment(<adjustment object>, <calculable object>)
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
To work out what the calculator would compute an amount to be:
|
|
318
|
+
|
|
319
|
+
```ruby
|
|
320
|
+
plan.compute_amount(<calculable object>)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
`create_adjustment`, `update_adjustment` and `compute_amount` will call `compute` on the `Calculator` object. This `calculable` amount is whatever object your `CustomCalculator` class supports.
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Customers
|
|
3
|
+
description: Customer accounts — registration, authentication, profiles, and guest checkout
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Customers interact with your store through the Store API. They can register, log in, manage their profile, and view order history.
|
|
9
|
+
|
|
10
|
+
```mermaid
|
|
11
|
+
erDiagram
|
|
12
|
+
Customer ||--o{ Order : "places"
|
|
13
|
+
Customer ||--o{ Address : "has many"
|
|
14
|
+
Customer ||--o{ Wishlist : "has many"
|
|
15
|
+
Customer ||--o{ StoreCredit : "has many"
|
|
16
|
+
Customer ||--o{ PaymentSource : "has many"
|
|
17
|
+
|
|
18
|
+
Customer {
|
|
19
|
+
string id
|
|
20
|
+
string email
|
|
21
|
+
string first_name
|
|
22
|
+
string last_name
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Order {
|
|
26
|
+
string number
|
|
27
|
+
string state
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
Address {
|
|
31
|
+
string firstname
|
|
32
|
+
string lastname
|
|
33
|
+
string address1
|
|
34
|
+
string city
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
Wishlist {
|
|
38
|
+
string name
|
|
39
|
+
boolean is_default
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Registration
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
```typescript SDK
|
|
47
|
+
const { token, user } = await client.customers.create({
|
|
48
|
+
email: 'john@example.com',
|
|
49
|
+
password: 'password123',
|
|
50
|
+
password_confirmation: 'password123',
|
|
51
|
+
first_name: 'John',
|
|
52
|
+
last_name: 'Doe',
|
|
53
|
+
})
|
|
54
|
+
// token => JWT token for subsequent authenticated requests
|
|
55
|
+
// user => { id: "usr_xxx", email: "john@example.com", first_name: "John", ... }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```bash cURL
|
|
59
|
+
curl -X POST 'https://api.mystore.com/api/v3/store/customers' \
|
|
60
|
+
-H 'X-Spree-Api-Key: spree_pk_xxx' \
|
|
61
|
+
-H 'Content-Type: application/json' \
|
|
62
|
+
-d '{
|
|
63
|
+
"email": "john@example.com",
|
|
64
|
+
"password": "password123",
|
|
65
|
+
"password_confirmation": "password123",
|
|
66
|
+
"first_name": "John",
|
|
67
|
+
"last_name": "Doe"
|
|
68
|
+
}'
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
## Login
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
```typescript SDK
|
|
76
|
+
const { token, user } = await client.auth.login({
|
|
77
|
+
email: 'john@example.com',
|
|
78
|
+
password: 'password123',
|
|
79
|
+
})
|
|
80
|
+
// Use the token for authenticated requests
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```bash cURL
|
|
84
|
+
curl -X POST 'https://api.mystore.com/api/v3/store/auth/login' \
|
|
85
|
+
-H 'Authorization: Bearer spree_pk_xxx' \
|
|
86
|
+
-H 'Content-Type: application/json' \
|
|
87
|
+
-d '{
|
|
88
|
+
"email": "john@example.com",
|
|
89
|
+
"password": "password123"
|
|
90
|
+
}'
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
The response includes a JWT `token` and a `user` object. Pass the token in subsequent requests via the `Authorization: Bearer <token>` header.
|
|
95
|
+
|
|
96
|
+
## Token Refresh
|
|
97
|
+
|
|
98
|
+
Refresh an expiring token to keep the session alive:
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
```typescript SDK
|
|
102
|
+
const { token } = await client.auth.refresh({
|
|
103
|
+
token: existingToken,
|
|
104
|
+
})
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```bash cURL
|
|
108
|
+
curl -X POST 'https://api.mystore.com/api/v3/store/auth/refresh' \
|
|
109
|
+
-H 'Authorization: Bearer <jwt_token>'
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
## Password Reset
|
|
114
|
+
|
|
115
|
+
Password reset is a two-step flow. First, request a reset email. Then, use the token from the email to set a new password.
|
|
116
|
+
|
|
117
|
+
### Step 1: Request Reset
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
```typescript SDK
|
|
121
|
+
await client.customer.passwordResets.create({
|
|
122
|
+
email: 'john@example.com',
|
|
123
|
+
redirect_url: 'https://myshop.com/reset-password',
|
|
124
|
+
})
|
|
125
|
+
// Always returns { message: "..." } — even if the email doesn't exist
|
|
126
|
+
// This prevents email enumeration
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```bash cURL
|
|
130
|
+
curl -X POST 'https://api.mystore.com/api/v3/store/customer/password_resets' \
|
|
131
|
+
-H 'X-Spree-Api-Key: spree_pk_xxx' \
|
|
132
|
+
-H 'Content-Type: application/json' \
|
|
133
|
+
-d '{
|
|
134
|
+
"email": "john@example.com",
|
|
135
|
+
"redirect_url": "https://myshop.com/reset-password"
|
|
136
|
+
}'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
The optional `redirect_url` parameter specifies where the password reset link in the email should point to. The token will be appended as a query parameter (e.g., `https://myshop.com/reset-password?token=...`). If the store has [Allowed Origins](/developer/core-concepts/allowed-origins) configured, the `redirect_url` must match one of them.
|
|
141
|
+
|
|
142
|
+
This fires a `customer.password_reset_requested` event with the reset token in the payload. If you're using the `spree_emails` package, the email is sent automatically. Otherwise, subscribe to this event to send the reset email yourself (see [Events](/developer/core-concepts/events)).
|
|
143
|
+
|
|
144
|
+
### Step 2: Reset Password
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
```typescript SDK
|
|
148
|
+
const { token, user } = await client.customer.passwordResets.update(
|
|
149
|
+
'reset-token-from-email',
|
|
150
|
+
{
|
|
151
|
+
password: 'newsecurepassword',
|
|
152
|
+
password_confirmation: 'newsecurepassword',
|
|
153
|
+
}
|
|
154
|
+
)
|
|
155
|
+
// Returns JWT token + user (auto-login)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
```bash cURL
|
|
159
|
+
curl -X PATCH 'https://api.mystore.com/api/v3/store/customer/password_resets/RESET_TOKEN' \
|
|
160
|
+
-H 'X-Spree-Api-Key: spree_pk_xxx' \
|
|
161
|
+
-H 'Content-Type: application/json' \
|
|
162
|
+
-d '{
|
|
163
|
+
"password": "newsecurepassword",
|
|
164
|
+
"password_confirmation": "newsecurepassword"
|
|
165
|
+
}'
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
On success, the user is automatically logged in and a JWT token is returned. The reset token expires after 15 minutes (configurable via `Spree::Config.customer_password_reset_expires_in`) and is single-use (changing the password invalidates it).
|
|
170
|
+
|
|
171
|
+
## Customer Profile
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
```typescript SDK
|
|
175
|
+
// Get current customer
|
|
176
|
+
const customer = await client.customer.get()
|
|
177
|
+
// {
|
|
178
|
+
// id: "usr_xxx",
|
|
179
|
+
// email: "john@example.com",
|
|
180
|
+
// first_name: "John",
|
|
181
|
+
// last_name: "Doe",
|
|
182
|
+
// default_shipping_address: { ... },
|
|
183
|
+
// default_billing_address: { ... },
|
|
184
|
+
// addresses: [{ ... }, { ... }],
|
|
185
|
+
// }
|
|
186
|
+
|
|
187
|
+
// Update profile
|
|
188
|
+
const updated = await client.customer.update({
|
|
189
|
+
first_name: 'Jonathan',
|
|
190
|
+
accepts_email_marketing: true,
|
|
191
|
+
})
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
```bash cURL
|
|
195
|
+
# Get current customer
|
|
196
|
+
curl 'https://api.mystore.com/api/v3/store/customer' \
|
|
197
|
+
-H 'Authorization: Bearer <jwt_token>'
|
|
198
|
+
|
|
199
|
+
# Update profile
|
|
200
|
+
curl -X PATCH 'https://api.mystore.com/api/v3/store/customer' \
|
|
201
|
+
-H 'Authorization: Bearer <jwt_token>' \
|
|
202
|
+
-H 'Content-Type: application/json' \
|
|
203
|
+
-d '{ "first_name": "Jonathan", "accepts_email_marketing": true }'
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
## Customer Resources
|
|
208
|
+
|
|
209
|
+
Authenticated customers have access to these resources:
|
|
210
|
+
|
|
211
|
+
| Resource | Description |
|
|
212
|
+
|----------|-------------|
|
|
213
|
+
| [**Addresses**](/developer/core-concepts/addresses#customer-address-book) | Billing and shipping addresses with default selection |
|
|
214
|
+
| [**Orders**](/developer/core-concepts/orders#order-history) | Past order history |
|
|
215
|
+
| **Credit Cards** | Saved credit cards for checkout |
|
|
216
|
+
| **Payment Sources** | Other saved payment methods (PayPal, Klarna, etc.) |
|
|
217
|
+
| **Store Credits** | Balance assigned by the store, usable at checkout |
|
|
218
|
+
| **Gift Cards** | Gift cards owned by or assigned to the customer |
|
|
219
|
+
| **Wishlists** | Saved product lists |
|
|
220
|
+
|
|
221
|
+
## Guest Checkout
|
|
222
|
+
|
|
223
|
+
Customers don't need to register to purchase. Guest checkout uses an order token (`X-Spree-Token`) to identify the cart. See [Orders — Cart](/developer/core-concepts/orders#cart) for details.
|
|
224
|
+
|
|
225
|
+
## Related Documentation
|
|
226
|
+
|
|
227
|
+
- [Addresses](/developer/core-concepts/addresses) — Customer address management
|
|
228
|
+
- [Orders](/developer/core-concepts/orders) — Order history and checkout
|
|
229
|
+
- [Authentication](/developer/customization/authentication) — Custom authentication setup
|
|
230
|
+
- [Staff & Roles](/developer/core-concepts/staff-roles) — Admin users and permissions
|