@spree/docs 0.1.304 → 0.1.305

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.
@@ -8,18 +8,17 @@ All monetary values in the Admin API are **canonical decimal strings** (period d
8
8
 
9
9
  ## Reading
10
10
 
11
- Every monetary field is returned as a string, alongside a `display_` companion that includes currency formatting:
11
+ Every monetary field is returned as a decimal string, with its currency on the record or on the record it belongs to (an order's payments and fulfillments are in the order's currency):
12
12
 
13
13
  ```json
14
14
  {
15
15
  "amount": "29.99",
16
- "display_amount": "$29.99",
17
16
  "compare_at_amount": "39.99",
18
- "display_compare_at_amount": "$39.99"
17
+ "currency": "USD"
19
18
  }
20
19
  ```
21
20
 
22
- Use `display_*` for rendering and the raw string fields for calculations, with a decimal library rather than `parseFloat`. The SDK exports `sumMoney`, `subtractMoney`, `multiplyMoney`, `compareMoney` and `isZeroMoney`, which work on the strings exactly.
21
+ The Admin and Seller APIs return amounts only, with no `display_*` formatted copies: format them for the person reading them, in their own language. In JavaScript, pass the string to `Intl.NumberFormat` (`new Intl.NumberFormat('de', { style: 'currency', currency: 'EUR' }).format('1234.5')` gives `1.234,50 €`), which reads a numeric string exactly. Calculate with a decimal library rather than `parseFloat`: the SDK exports `sumMoney`, `subtractMoney`, `multiplyMoney`, `compareMoney` and `isZeroMoney`, which work on the strings exactly. The [Store API](../store-api/monetary-amounts.md) keeps `display_*` fields for storefronts, and webhook payloads and email templates carry them too.
23
22
 
24
23
  ## Writing
25
24
 
@@ -96,6 +96,23 @@ This hash will contain the value for every preference that has been defined for
96
96
 
97
97
  `preferences` never holds secrets — see [Secret preferences](#secret-preferences).
98
98
 
99
+ ## Money preferences
100
+
101
+ Declare an amount of money with the `:money` type, and a rate or a measure (a percentage, a weight) with `:decimal`:
102
+
103
+ ```ruby server/app/models/spree/calculator/handling_fee.rb
104
+ module Spree
105
+ class Calculator::HandlingFee < Spree::Calculator
106
+ preference :amount, :money, default: 0
107
+ preference :currency, :string, default: -> { Spree::Store.default.default_currency }
108
+ preference :surcharge_percent, :decimal, default: 0
109
+ end
110
+ end
111
+ ```
112
+
113
+ Both are read back as a `BigDecimal` and take a number or a decimal string (`"4.50"`); text such as `"4,50"` is refused rather than misread. The difference is on the [API](../../api-reference/admin-api/monetary-amounts.md): a `:money` preference is written with the decimals of the record's `currency` preference (`"4.50"`, or `"450"` in yen), and the dashboard shows it with that currency's symbol. A money preference on a record with no currency, such as a rule matching an order total in any currency, keeps its exact decimal.
114
+
115
+
99
116
  ## Secret preferences
100
117
 
101
118
  Declare API keys, signing secrets and other credentials with the `:password` type:
@@ -803,6 +803,8 @@ Other changes that come with it:
803
803
  - **Money on the API is written to each currency's decimals.** Every amount in the Store, Admin and Seller APIs, and so in webhook payloads and email variables, is a decimal string with exactly its currency's decimal places: `"10.00"` (was `"10.0"`), `"1000"` in yen (was `"1000.0"`), `"1.500"` in dinar. Unit prices keep up to four decimals. Fields that were JSON numbers are now strings: `cart.order_minimum` and `order_minimum_shortfall`, the product filter price range `min`/`max`, report money metrics and percentages, and the store's `preferred_default_minimum_payout_amount` and `preferred_default_commission_tax_rate`. Clients comparing these strings, or parsing them as numbers, should switch to exact decimal arithmetic; the SDKs export `sumMoney`, `subtractMoney`, `multiplyMoney`, `compareMoney` and `isZeroMoney`.
804
804
  - **Admin and Seller writes refuse JSON numbers for money.** Amounts and rates, including those inside `preferences`, must be canonical decimal strings (`"19.99"`). A number, a localized or grouped string, or more decimals than the field holds is answered with `422` and `invalid_money_format`, naming the field.
805
805
  - **Amounts may not carry more decimals than they can keep.** Now that the columns hold four decimals, the database no longer rounds away a fraction of a cent, so a payment, refund, store credit, gift card, fee or discount with more decimals than its currency has (`10.0049` dollars) fails validation with `too_many_decimals`. Unit prices and cost prices allow four, tax rates five decimals of the fraction (`rate_percent` `"7.125"`, not `"7.1255"`), and price list percentages three. Round in your own code before saving. A manual order discount's `value` and a commission rate's `value` are read as strictly as other money fields.
806
+ - **The Admin and Seller APIs no longer return `display_*` money fields.** Responses carry the amount (`"29.99"`) with its currency, and the client formats it in the reader's own language. Before 6.0 the server formatted a copy in the request's language, which could disagree with the editable amount beside it. Format with `Intl.NumberFormat` or your platform's equivalent. The Store API, webhook payloads and email templates keep their `display_*` fields, and labels such as `display_name` are unchanged.
807
+ - **Money preferences have their own type.** Calculator, rule and store preferences holding an amount (`amount`, `first_item`, `minimal_amount`, `amount_min`, `min_amount`, `default_minimum_payout_amount` and the like) are declared `:money` instead of `:decimal`, report `money` in `preference_schema`, and are written with the decimals of the calculator's currency (`"12.50"` rather than `"12.5"`). Declare your own extensions' amounts with `:money` so the dashboard shows their currency. A `:decimal` or `:money` preference now refuses text such as `"1,599.99"` instead of reading it as 1.
806
808
  - **Rates are decimal strings, and tax rates are renamed.** Rates and percentages read and write as strings without trailing zeros. A tax rate's `amount` (a fraction) is now `rate`, and `amount_percentage` is `rate_percent`; `Spree::TaxRate#amount_percentage` keeps working with a warning until 6.1.
807
809
  - **`amount_in_cents` and `compare_at_amount_in_cents` are removed** from prices and price history. Read `amount`, and each currency's `decimal_places` (new on `GET /api/v3/store/currencies`) if you need minor units.
808
810
  - **Money columns widen to `decimal(19,4)`.** They now hold a Kuwaiti dinar's third decimal, unit prices below a cent (`0.0125`), and very large amounts in currencies like the Vietnamese dong. No stored value changes. Totals, payments and refunds are still rounded to the currency's decimals; only unit prices (`price`, `compare_at_amount`, `cost_price`, `unit_cost`) keep up to four. The migration rewrites each money table while it runs, which locks `spree_orders`, `spree_line_items` and `spree_adjustments` for as long as that takes. If you cannot take that lock, widen those columns online first (add a `decimal(19,4)` shadow column, backfill it in batches, swap it in), and the migration skips any column already at `(19,4)`. Extensions with their own money tables, such as `spree_stripe_payment_intents` from the standalone Stripe gem, should widen theirs the same way.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spree/docs",
3
- "version": "0.1.304",
3
+ "version": "0.1.305",
4
4
  "description": "Spree Commerce developer documentation for AI agents and local reference",
5
5
  "type": "module",
6
6
  "license": "CC-BY-4.0",