@spree/docs 0.1.182 → 0.1.183
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/developer/core-concepts/addresses.md +106 -198
- package/dist/developer/core-concepts/architecture.md +97 -126
- package/dist/developer/core-concepts/calculators.md +75 -252
- package/dist/developer/core-concepts/carts.md +1 -1
- package/dist/developer/core-concepts/channels.md +0 -4
- package/dist/developer/core-concepts/companies-and-catalogs.md +1 -1
- package/dist/developer/core-concepts/customers.md +0 -3
- package/dist/developer/core-concepts/discounts.md +133 -0
- package/dist/developer/core-concepts/events.md +83 -576
- package/dist/developer/core-concepts/fees.md +144 -0
- package/dist/developer/core-concepts/imports-exports.md +105 -679
- package/dist/developer/core-concepts/inventory.md +114 -248
- package/dist/developer/core-concepts/markets.md +9 -12
- package/dist/developer/core-concepts/media.md +9 -11
- package/dist/developer/core-concepts/metafields.md +123 -200
- package/dist/developer/core-concepts/order-totals.md +110 -0
- package/dist/developer/core-concepts/orders.md +1 -1
- package/dist/developer/core-concepts/payments.md +11 -14
- package/dist/developer/core-concepts/pricing.md +11 -13
- package/dist/developer/core-concepts/products.md +35 -19
- package/dist/developer/core-concepts/promotions.md +12 -11
- package/dist/developer/core-concepts/search-filtering.md +2 -4
- package/dist/developer/core-concepts/store-credits-gift-cards.md +0 -3
- package/dist/developer/core-concepts/taxes.md +125 -113
- package/dist/developer/core-concepts/translations.md +61 -68
- package/dist/developer/core-concepts/webhooks.md +25 -59
- package/dist/developer/how-to/custom-promotion.md +3 -3
- package/package.json +1 -1
- package/dist/developer/core-concepts/taxes-discounts-fees.md +0 -199
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Fees
|
|
3
|
+
description: Surcharges added to an order — handling, gift wrap, cash on delivery — and customs duties on cross-border sales.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
A fee is money added to an order that isn't the price of a product and isn't tax. Gift wrapping. A handling charge. The surcharge for paying cash on delivery. An import duty on a parcel crossing a border.
|
|
9
|
+
|
|
10
|
+
Fees are their own kind of row, separate from [tax](taxes.md) and [discounts](discounts.md), so a merchant can answer "what did we charge in handling this quarter" without untangling a mixed list.
|
|
11
|
+
|
|
12
|
+
```mermaid
|
|
13
|
+
erDiagram
|
|
14
|
+
Order ||--o{ Fee : "order-level"
|
|
15
|
+
LineItem ||--o{ Fee : "per item"
|
|
16
|
+
Fulfillment ||--o{ Fee : "per parcel"
|
|
17
|
+
Fee ||--o{ TaxLine : "may be taxed"
|
|
18
|
+
|
|
19
|
+
Fee {
|
|
20
|
+
string label
|
|
21
|
+
string kind
|
|
22
|
+
string amount
|
|
23
|
+
string metadata
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Fee attributes
|
|
28
|
+
|
|
29
|
+
| Attribute | Description |
|
|
30
|
+
|---|---|
|
|
31
|
+
| `label` | What the customer sees — `Gift wrapping` |
|
|
32
|
+
| `kind` | What sort of charge it is — see below |
|
|
33
|
+
| `amount` / `display_amount` | The charge |
|
|
34
|
+
| `line_item_id` | Set when the fee is for one item |
|
|
35
|
+
| `fulfillment_id` | Set when the fee is for one parcel |
|
|
36
|
+
|
|
37
|
+
When neither ID is set, the fee applies to the whole order.
|
|
38
|
+
|
|
39
|
+
| `kind` | Typical use |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `surcharge` | A general extra charge |
|
|
42
|
+
| `handling` | Packing and processing |
|
|
43
|
+
| `gift_wrap` | Gift wrapping |
|
|
44
|
+
| `cod` | Cash on delivery |
|
|
45
|
+
| `payment` | A payment method surcharge |
|
|
46
|
+
| `duty` | Customs duty — see [below](#customs-duties) |
|
|
47
|
+
|
|
48
|
+
The list is open — an extension can add its own kind.
|
|
49
|
+
|
|
50
|
+
> **NOTE:** **Fees are always positive.** To take money off, create a [discount](discounts.md) instead. This isn't pedantry: when a refund is worked out later, it has to know whether a row was a charge or a credit, and a negative fee makes that ambiguous.
|
|
51
|
+
|
|
52
|
+
## Adding a fee
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
```typescript Admin SDK
|
|
56
|
+
// Gift wrapping on one item
|
|
57
|
+
await adminClient.orders.fees.create('or_xxx', {
|
|
58
|
+
label: 'Gift wrapping',
|
|
59
|
+
kind: 'gift_wrap',
|
|
60
|
+
amount: '5.00',
|
|
61
|
+
line_item_id: 'li_xxx',
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
// A handling charge on the whole order
|
|
65
|
+
await adminClient.orders.fees.create('or_xxx', {
|
|
66
|
+
label: 'Handling',
|
|
67
|
+
kind: 'handling',
|
|
68
|
+
amount: '2.50',
|
|
69
|
+
})
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```bash cURL
|
|
73
|
+
curl -X POST 'https://api.mystore.com/api/v3/admin/orders/or_xxx/fees' \
|
|
74
|
+
-H 'X-Spree-API-Key: sk_xxx' \
|
|
75
|
+
-H 'Content-Type: application/json' \
|
|
76
|
+
-d '{ "label": "Gift wrapping", "kind": "gift_wrap", "amount": "5.00" }'
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
Fees are visible to the storefront on the cart and the order, so a customer sees what they're being charged before they pay:
|
|
81
|
+
|
|
82
|
+
```typescript Store SDK
|
|
83
|
+
const cart = await client.carts.get(cartId)
|
|
84
|
+
|
|
85
|
+
cart.fees.forEach((fee) => {
|
|
86
|
+
fee.label // "Gift wrapping"
|
|
87
|
+
fee.display_amount // "$5.00"
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
cart.display_fee_total // "$7.50"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Fees and tax
|
|
94
|
+
|
|
95
|
+
Fees are **taxable by default** — a handling charge in a VAT country is itself subject to VAT, and Spree writes tax lines against the fee accordingly.
|
|
96
|
+
|
|
97
|
+
Customs duties are the exception, described next.
|
|
98
|
+
|
|
99
|
+
## Customs duties
|
|
100
|
+
|
|
101
|
+
When a parcel crosses a border, the destination country may charge import duty. Whether the customer pays that at checkout or gets a bill from the courier later is a commercial decision — and quoting it up front is what avoids parcels being refused at the door.
|
|
102
|
+
|
|
103
|
+
A duty is recorded as a fee with `kind: 'duty'`. Two things make it different from every other fee.
|
|
104
|
+
|
|
105
|
+
### Duties aren't taxed
|
|
106
|
+
|
|
107
|
+
A duty is an import charge levied by the destination country, not a sale that domestic tax applies to. Charging tax on top of it would invent tax the merchant never owed, so Spree leaves duties out of the taxable set. Where import VAT genuinely applies, whoever calculated the duty records that tax itself.
|
|
108
|
+
|
|
109
|
+
### Duties remember what they were calculated from
|
|
110
|
+
|
|
111
|
+
A duty fee keeps a copy of its inputs — the commodity code, the country of origin, the rate — in its `metadata`.
|
|
112
|
+
|
|
113
|
+
This matters more than it sounds. A product's classification can be corrected next month; a supplier can change. What the customer was actually charged must not move when that happens. The snapshot is the authoritative record, and a duty is never re-derived from today's catalogue.
|
|
114
|
+
|
|
115
|
+
## Customs classification
|
|
116
|
+
|
|
117
|
+
For any of this to work, the goods have to be described in the language customs authorities use. Three fields on each variant do that:
|
|
118
|
+
|
|
119
|
+
| Field | What it is | Example |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| `hs_code` | The Harmonized System commodity code — the international classification for what the item *is* | `6109.10` |
|
|
122
|
+
| `country_of_origin` | Where it was made, as an ISO country code — not where it ships from | `PT` |
|
|
123
|
+
| `customs_description` | A plain description for the declaration, when the product name isn't clear enough | `Cotton t-shirt` |
|
|
124
|
+
|
|
125
|
+
```typescript Admin SDK
|
|
126
|
+
await adminClient.products.variants.update('prod_xxx', 'var_xxx', {
|
|
127
|
+
hs_code: '6109.10',
|
|
128
|
+
country_of_origin: 'PT',
|
|
129
|
+
customs_description: 'Cotton t-shirt',
|
|
130
|
+
})
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
> **WARNING:** `country_of_origin` is where the item was **manufactured**, not the warehouse it leaves from. Duty rates and trade agreements turn on origin, so getting this wrong produces the wrong charge — and can hold a parcel at the border.
|
|
134
|
+
|
|
135
|
+
These fields are editable per variant and in the bulk product editor. They're also what a carrier integration puts on the customs declaration for an international label — required for cross-border parcels, ignored for domestic ones.
|
|
136
|
+
|
|
137
|
+
> **INFO:** Spree records classification and charges duties; it does not itself estimate them. A landed-cost provider calculates the numbers and writes the duty fees. See [Providers](../providers/overview.md).
|
|
138
|
+
|
|
139
|
+
## Related
|
|
140
|
+
|
|
141
|
+
- [Taxes](taxes.md) — how tax is worked out
|
|
142
|
+
- [Discounts](discounts.md) — taking money off
|
|
143
|
+
- [Order totals](order-totals.md) — how fees roll into what a customer pays
|
|
144
|
+
- [Products](products.md) — variants and their attributes
|