@sixtyninecommerce/admin 0.8.0 → 0.9.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 (161) hide show
  1. package/README.md +2445 -17
  2. package/dist/api-tokens/index.d.ts +15 -5
  3. package/dist/api-tokens/index.js +1 -0
  4. package/dist/apps/event-subscription.d.ts +59 -0
  5. package/dist/apps/event-subscription.js +32 -0
  6. package/dist/apps/hook-secret.d.ts +22 -0
  7. package/dist/apps/hook-secret.js +36 -0
  8. package/dist/apps/index.d.ts +54 -3
  9. package/dist/apps/index.js +17 -0
  10. package/dist/audit/index.d.ts +7 -0
  11. package/dist/auth/queries.d.ts +5 -1
  12. package/dist/auth/queries.js +6 -0
  13. package/dist/bulk/index.d.ts +323 -0
  14. package/dist/bulk/index.js +162 -0
  15. package/dist/catalog/assets.d.ts +147 -0
  16. package/dist/catalog/assets.js +164 -0
  17. package/dist/catalog/collections.d.ts +109 -0
  18. package/dist/catalog/collections.js +91 -0
  19. package/dist/catalog/facets.d.ts +103 -0
  20. package/dist/catalog/facets.js +100 -0
  21. package/dist/catalog/index.d.ts +115 -0
  22. package/dist/catalog/index.js +21 -0
  23. package/dist/catalog/options.d.ts +89 -0
  24. package/dist/catalog/options.js +88 -0
  25. package/dist/catalog/products-bulk.d.ts +21 -0
  26. package/dist/catalog/products-bulk.js +58 -0
  27. package/dist/catalog/products.d.ts +489 -0
  28. package/dist/catalog/products.js +365 -0
  29. package/dist/catalog/properties.d.ts +234 -0
  30. package/dist/catalog/properties.js +158 -0
  31. package/dist/catalog/types.d.ts +174 -0
  32. package/dist/catalog/types.js +141 -0
  33. package/dist/catalog/variants.d.ts +274 -0
  34. package/dist/catalog/variants.js +258 -0
  35. package/dist/catalog/visibility.d.ts +57 -0
  36. package/dist/catalog/visibility.js +59 -0
  37. package/dist/client.d.ts +171 -3
  38. package/dist/client.js +81 -12
  39. package/dist/compliance/index.d.ts +88 -0
  40. package/dist/compliance/index.js +88 -0
  41. package/dist/customer-data-redaction.d.ts +14 -0
  42. package/dist/customer-data-redaction.js +22 -0
  43. package/dist/customers/index.d.ts +428 -17
  44. package/dist/customers/index.js +322 -15
  45. package/dist/documents/index.d.ts +513 -16
  46. package/dist/documents/index.js +229 -3
  47. package/dist/events/index.d.ts +259 -0
  48. package/dist/events/index.js +147 -0
  49. package/dist/feeds/ai.d.ts +46 -0
  50. package/dist/feeds/ai.js +43 -0
  51. package/dist/feeds/categories.d.ts +50 -0
  52. package/dist/feeds/categories.js +56 -0
  53. package/dist/feeds/configs.d.ts +54 -0
  54. package/dist/feeds/configs.js +85 -0
  55. package/dist/feeds/identifier-fields.d.ts +25 -0
  56. package/dist/feeds/identifier-fields.js +29 -0
  57. package/dist/feeds/index.d.ts +54 -0
  58. package/dist/feeds/index.js +46 -0
  59. package/dist/feeds/preserve.d.ts +38 -0
  60. package/dist/feeds/preserve.js +74 -0
  61. package/dist/feeds/rules.d.ts +42 -0
  62. package/dist/feeds/rules.js +56 -0
  63. package/dist/feeds/types.d.ts +654 -0
  64. package/dist/feeds/types.js +135 -0
  65. package/dist/fulfillments/index.d.ts +360 -0
  66. package/dist/fulfillments/index.js +425 -0
  67. package/dist/heads/index.d.ts +60 -0
  68. package/dist/heads/index.js +45 -0
  69. package/dist/hooks/assignments.d.ts +90 -0
  70. package/dist/hooks/assignments.js +53 -0
  71. package/dist/hooks/index.d.ts +97 -0
  72. package/dist/hooks/index.js +76 -0
  73. package/dist/index.d.ts +84 -9
  74. package/dist/index.js +16 -1
  75. package/dist/jobs/bulk-action-run.d.ts +65 -0
  76. package/dist/jobs/bulk-action-run.js +70 -0
  77. package/dist/locations/index.d.ts +6 -2
  78. package/dist/meta/index.d.ts +32 -0
  79. package/dist/orders/commit-edit.d.ts +123 -0
  80. package/dist/orders/commit-edit.js +142 -0
  81. package/dist/orders/get.d.ts +722 -0
  82. package/dist/orders/get.js +530 -0
  83. package/dist/orders/index.d.ts +105 -20
  84. package/dist/orders/index.js +44 -0
  85. package/dist/orders/line-price-preview.d.ts +297 -0
  86. package/dist/orders/line-price-preview.js +50 -0
  87. package/dist/orders/manual-discounts.d.ts +132 -0
  88. package/dist/orders/manual-discounts.js +95 -0
  89. package/dist/orders/manual-pricing.d.ts +192 -0
  90. package/dist/orders/manual-pricing.js +72 -0
  91. package/dist/orders/order-entry.d.ts +566 -0
  92. package/dist/orders/order-entry.js +129 -0
  93. package/dist/orders/parcel-charge.d.ts +45 -0
  94. package/dist/orders/parcel-charge.js +55 -0
  95. package/dist/orders/plan-edit.d.ts +489 -0
  96. package/dist/orders/plan-edit.js +93 -0
  97. package/dist/orders/status.d.ts +235 -0
  98. package/dist/orders/status.js +96 -0
  99. package/dist/orders/surcharges.d.ts +75 -2
  100. package/dist/orders/surcharges.js +110 -4
  101. package/dist/payments/account-credit.d.ts +171 -0
  102. package/dist/payments/account-credit.js +107 -0
  103. package/dist/payments/index.d.ts +234 -9
  104. package/dist/payments/index.js +90 -0
  105. package/dist/platform/catalog.d.ts +148 -0
  106. package/dist/platform/catalog.js +74 -0
  107. package/dist/platform/entitlements.d.ts +111 -0
  108. package/dist/platform/entitlements.js +86 -0
  109. package/dist/platform/legal-entities.d.ts +139 -0
  110. package/dist/platform/legal-entities.js +126 -0
  111. package/dist/platform/legal-entity-numbering.d.ts +103 -0
  112. package/dist/platform/legal-entity-numbering.js +101 -0
  113. package/dist/platform/organization-membership.d.ts +80 -0
  114. package/dist/platform/organization-membership.js +71 -0
  115. package/dist/platform/organization-settings.d.ts +33 -0
  116. package/dist/platform/organization-settings.js +42 -0
  117. package/dist/platform/organization-sharing.d.ts +172 -0
  118. package/dist/platform/organization-sharing.js +120 -0
  119. package/dist/platform/organizations.d.ts +205 -0
  120. package/dist/platform/organizations.js +180 -0
  121. package/dist/platform/provision-store.d.ts +88 -8
  122. package/dist/platform/provision-store.js +12 -0
  123. package/dist/platform/reports.d.ts +46 -0
  124. package/dist/platform/reports.js +31 -0
  125. package/dist/platform/server-metrics.d.ts +58 -0
  126. package/dist/platform/server-metrics.js +11 -0
  127. package/dist/pos/index.d.ts +567 -0
  128. package/dist/pos/index.js +205 -0
  129. package/dist/pricing/index.d.ts +405 -0
  130. package/dist/pricing/index.js +351 -0
  131. package/dist/provenance/index.d.ts +93 -0
  132. package/dist/provenance/index.js +53 -0
  133. package/dist/reports/index.d.ts +199 -0
  134. package/dist/reports/index.js +154 -0
  135. package/dist/shipping/parcel-count-suggestion.d.ts +52 -0
  136. package/dist/shipping/parcel-count-suggestion.js +73 -0
  137. package/dist/shipping/parcel-rule.d.ts +48 -0
  138. package/dist/shipping/parcel-rule.js +91 -0
  139. package/dist/stock/index.d.ts +166 -0
  140. package/dist/stock/index.js +115 -0
  141. package/dist/stock/transfers.d.ts +520 -0
  142. package/dist/stock/transfers.js +437 -0
  143. package/dist/stored-value/index.d.ts +154 -0
  144. package/dist/stored-value/index.js +130 -0
  145. package/dist/tenant/capabilities.d.ts +10 -0
  146. package/dist/tenant/entitlements.d.ts +35 -0
  147. package/dist/tenant/entitlements.js +15 -0
  148. package/dist/tenant/field-groups.d.ts +64 -0
  149. package/dist/tenant/field-groups.js +34 -0
  150. package/dist/tenant/legal-entity.d.ts +32 -0
  151. package/dist/tenant/legal-entity.js +41 -0
  152. package/dist/tenant/notifications.d.ts +148 -0
  153. package/dist/tenant/notifications.js +79 -0
  154. package/dist/tenant/retention.d.ts +10 -4
  155. package/dist/tenant/settings-sources.d.ts +103 -0
  156. package/dist/tenant/settings-sources.js +92 -0
  157. package/dist/types.d.ts +86 -11
  158. package/dist/uploads/index.d.ts +11 -7
  159. package/dist/users/index.d.ts +104 -0
  160. package/dist/users/index.js +80 -0
  161. package/package.json +3 -2
@@ -1,4 +1,27 @@
1
+ import { NotFoundError } from '@sixtyninecommerce/core';
2
+ import { createOrderCommitEditModule } from './commit-edit.js';
3
+ import { createOrderGetModule } from './get.js';
4
+ import { createOrderLinePricePreviewModule, } from './line-price-preview.js';
5
+ import { createManualDiscountsModule } from './manual-discounts.js';
6
+ import { createOrderManualPricingModule } from './manual-pricing.js';
7
+ import { createOrderEntryModule } from './order-entry.js';
8
+ import { createOrderParcelChargeModule } from './parcel-charge.js';
9
+ import { createOrderPlanEditModule } from './plan-edit.js';
10
+ import { createOrderStatusModule } from './status.js';
1
11
  import { createSurchargesModule } from './surcharges.js';
12
+ const ORDER_PROVIDER_FALLBACKS_QUERY = /* GraphQL */ `
13
+ query OrderProviderFallbacks($id: ID!) {
14
+ order(id: $id) {
15
+ id
16
+ providerFallbacks {
17
+ kind
18
+ installationId
19
+ reason
20
+ since
21
+ }
22
+ }
23
+ }
24
+ `;
2
25
  const SETTLEMENT_FIELDS = /* GraphQL */ `
3
26
  order {
4
27
  id
@@ -67,7 +90,16 @@ export const ORDER_POSITION_QUERY = /* GraphQL */ `
67
90
  `;
68
91
  export function createOrdersModule(transport) {
69
92
  return {
93
+ ...createOrderEntryModule(transport),
94
+ ...createOrderGetModule(transport),
95
+ ...createOrderParcelChargeModule(transport),
96
+ ...createOrderLinePricePreviewModule(transport),
97
+ ...createOrderManualPricingModule(transport),
98
+ ...createOrderPlanEditModule(transport),
99
+ ...createOrderCommitEditModule(transport),
100
+ ...createOrderStatusModule(transport),
70
101
  surcharges: createSurchargesModule(transport),
102
+ manualDiscounts: createManualDiscountsModule(transport),
71
103
  async park(orderId, options) {
72
104
  const data = await transport.graphql({
73
105
  api: 'admin',
@@ -92,6 +124,18 @@ export function createOrdersModule(transport) {
92
124
  }, options);
93
125
  return data.unparkOrder;
94
126
  },
127
+ async providerFallbacks(orderId, options) {
128
+ const data = await transport.graphql({ api: 'admin', query: ORDER_PROVIDER_FALLBACKS_QUERY, variables: { id: orderId } }, options);
129
+ if (!data.order) {
130
+ throw new NotFoundError({
131
+ code: 'ORDER_NOT_FOUND',
132
+ message: `This store has no order ${orderId}.`,
133
+ status: 404,
134
+ service: 'vendure',
135
+ });
136
+ }
137
+ return data.order.providerFallbacks;
138
+ },
95
139
  async paymentPosition(orderId, options) {
96
140
  const data = await transport.graphql({ api: 'admin', query: ORDER_POSITION_QUERY, variables: { orderId } }, options);
97
141
  return data.orderPaymentPosition;
@@ -0,0 +1,297 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /** The tax basis a unit price is stated in. */
4
+ export type OrderLinePriceBasis = 'NET' | 'GROSS';
5
+ /**
6
+ * One layer a line's price goes through: the catalogue price, a manual unit
7
+ * price, the customer's price list, or the order's own one-time pricing.
8
+ */
9
+ export type OrderLinePriceSource = 'RETAIL' | 'OVERRIDE' | 'PRICE_LIST' | 'ONE_TIME';
10
+ /** How a one-time discount is stated. */
11
+ export type PreviewLineDiscountType = 'PERCENTAGE' | 'FIXED_AMOUNT' | 'FIXED_PRICE';
12
+ /** A manual unit price to stage on a line. */
13
+ export interface PreviewLinePriceOverride {
14
+ /**
15
+ * Minor units, a whole number of 0 or more, stated in `basis`. Stated in the
16
+ * line's own basis (the answer's `basis`) it is taken as it is, on every
17
+ * line. Stated in the other basis it is converted only at a tax rate the
18
+ * preview evaluated: the rate the platform taxes the line at on the order as
19
+ * it is now.
20
+ */
21
+ amount: number;
22
+ /**
23
+ * The basis `amount` is stated in. The line's own `basis` is always
24
+ * accepted. The other basis is refused with `INVALID_PREVIEW_INPUT`, in a
25
+ * message that names the basis to state it in, where the preview evaluates
26
+ * no tax rate for the line: on every line, stored or new, of a store with an
27
+ * active tax provider app, and on a line of the order whose variant was
28
+ * moved to another tax category since. To learn a line's basis first,
29
+ * preview it without an `override` and read `basis`.
30
+ */
31
+ basis: OrderLinePriceBasis;
32
+ }
33
+ /**
34
+ * A one-time discount to stage: on one line's product variant, or on the whole
35
+ * order (`options.orderDiscount`).
36
+ */
37
+ export interface PreviewOneTimeDiscount {
38
+ /** A whole-order discount is `PERCENTAGE` or `FIXED_AMOUNT`, never `FIXED_PRICE`. */
39
+ discountType: PreviewLineDiscountType;
40
+ /**
41
+ * A whole number. `PERCENTAGE`: basis points, 1 to 10000. `FIXED_AMOUNT`:
42
+ * minor units off each unit, 1 or more. `FIXED_PRICE`: the unit price in
43
+ * minor units, 0 or more. The two money kinds are in the CHANNEL's tax basis,
44
+ * which is not always the line's. These are the values the Admin API's
45
+ * `setOrderPriceListDiscounts` takes.
46
+ */
47
+ discountValue: number;
48
+ }
49
+ /**
50
+ * One line to preview.
51
+ *
52
+ * `override` and `oneTimeDiscount` each have three states: leave the key out
53
+ * to keep what the order has, pass `null` to clear it, pass a value to stage
54
+ * it. The SDK sends each as given. A key set to `undefined` counts as left out.
55
+ */
56
+ export interface PreviewLinePriceLine {
57
+ /**
58
+ * The order line to preview. Leave it out, or pass `null`, for a line that is
59
+ * not on the order yet. An order line may appear once per call.
60
+ */
61
+ lineId?: string | null;
62
+ /** Required on every line. With `lineId` it must be that line's variant. */
63
+ productVariantId: string;
64
+ /**
65
+ * The quantity the line would have, a whole number of 1 or more. It selects
66
+ * the quantity tier. A removed line cannot be staged.
67
+ */
68
+ quantity: number;
69
+ /** A staged manual unit price. */
70
+ override?: PreviewLinePriceOverride | null;
71
+ /**
72
+ * A staged one-time discount. It applies to the product variant, so to every
73
+ * line of it: two lines of one variant that stage different discounts are
74
+ * refused.
75
+ */
76
+ oneTimeDiscount?: PreviewOneTimeDiscount | null;
77
+ }
78
+ /** One layer of a previewed price. */
79
+ export interface LinePriceStackingStep {
80
+ source: OrderLinePriceSource;
81
+ /** The unit price after this layer, minor units in the line's `basis`. */
82
+ amount: number;
83
+ }
84
+ /**
85
+ * Why a line has no price to charge, as a platform code. A string on the wire.
86
+ * `VARIANT_NOT_FOR_SALE_IN_CURRENCY`: the store does not sell the variant in
87
+ * the order's currency, and no price was stated for the line.
88
+ */
89
+ export type LineNotPurchasableCode = 'VARIANT_NOT_FOR_SALE_IN_CURRENCY' | (string & {});
90
+ /** What a preview says of every line, whether it has a price or not. */
91
+ export interface LinePricePreviewBase {
92
+ /** The order line previewed. `null` for a line that is not on the order yet. */
93
+ lineId: string | null;
94
+ productVariantId: string;
95
+ /**
96
+ * The basis the engine prices the line in. Send a manual unit price to the
97
+ * Admin API's `applyOrderLinePriceOverrides` in this basis: the `OVERRIDE`
98
+ * step of `stacking` is that figure.
99
+ */
100
+ basis: OrderLinePriceBasis;
101
+ /** Always `true`: the engine prices the line in the order's tax zone itself. */
102
+ basisKnown: boolean;
103
+ /**
104
+ * The CATALOGUE retail moved since the stored line was priced: a re-price
105
+ * starts from another catalogue retail than `retailBase`. For a line a price
106
+ * list priced, the line recorded that retail gross and no tax rate of its
107
+ * day, so the two are compared gross. Besides a moved catalogue price, a
108
+ * change of the rate the catalogue taxes the variant at for this order can
109
+ * therefore set it too, while the net catalogue price did not move: the rate
110
+ * of the order's tax zone changed, the order now falls in another tax zone,
111
+ * or the variant moved to another tax category.
112
+ *
113
+ * A changed price list or quantity tier, and a tax driver that changes only
114
+ * the line's own tax (a reverse charge, tax removed), can move the previewed
115
+ * figures and leave it `false`. It is always `false` for a list-priced line
116
+ * of an order outside the store's default currency. To know
117
+ * whether a re-price would move a stored line, compare BOTH figures with the
118
+ * line's own: `chargedUnitPrice` with `unitPrice`, and
119
+ * `chargedUnitPriceWithTax` with `unitPriceWithTax` (a changed tax driver
120
+ * can move one of them and not the other). The comparison does not see a
121
+ * changed tax driver on a line that keeps the tax rate it carries: every
122
+ * line of the order on a store with an active tax provider app, and a line
123
+ * whose variant was moved to another tax category since.
124
+ */
125
+ catalogueChanged: boolean;
126
+ /**
127
+ * The layers a re-price goes through, in order. It starts with a `RETAIL`
128
+ * step at TODAY's catalogue price when the line has one, which is not always
129
+ * `retailBase`. The last step is the charged unit price in `basis`. Empty for
130
+ * a line that is not purchasable.
131
+ */
132
+ stacking: LinePriceStackingStep[];
133
+ /** A manual unit price is set, and a contract (fixed) price won over it. */
134
+ overrideInert: boolean;
135
+ /**
136
+ * The net/gross split is the PLATFORM's tax where the store's tax provider
137
+ * app decides. `true` for a line that is not on the order yet, on a store
138
+ * with an active tax provider app: a preview never asks the app, which
139
+ * answers when the line is added. The figure in the line's `basis` is firm.
140
+ * The OTHER one (the gross of a `NET` line, the net of a `GROSS` line) is
141
+ * derived at the platform's rate and may differ: show it as provisional.
142
+ *
143
+ * A manual price for such a line must be stated in the line's `basis`. One
144
+ * stated in the other basis is refused with `INVALID_PREVIEW_INPUT`, because
145
+ * converting it needs the app's rate. To learn the basis first, preview the
146
+ * line without an `override` and read `basis`. This is not the only line
147
+ * with that rule: see `PreviewLinePriceOverride.basis`.
148
+ *
149
+ * `false` everywhere else, and on a line that is not purchasable, which has
150
+ * no money to qualify.
151
+ */
152
+ taxProvisional: boolean;
153
+ }
154
+ /** A line with a price. Money is minor units in the order's currency, before promotions. */
155
+ export interface PurchasableLinePricePreview extends LinePricePreviewBase {
156
+ purchasable: true;
157
+ notPurchasableCode: null;
158
+ /**
159
+ * Net unit price the line would be charged. Provisional on a `GROSS` line
160
+ * while `taxProvisional` is `true`.
161
+ */
162
+ chargedUnitPrice: number;
163
+ /**
164
+ * Gross unit price the line would be charged. Provisional on a `NET` line
165
+ * while `taxProvisional` is `true`.
166
+ */
167
+ chargedUnitPriceWithTax: number;
168
+ /**
169
+ * The retail the line was PRICED AT, in `basis`: the base a percentage is
170
+ * measured against. For a line that is not on the order yet it is today's
171
+ * catalogue price. `null` when a stored line recorded none (a manual price
172
+ * with no price list), and when the line has no catalogue price (an
173
+ * externally priced line, or a variant not for sale in the order's currency
174
+ * that a stated price makes purchasable).
175
+ */
176
+ retailBase: number | null;
177
+ }
178
+ /**
179
+ * A line with no price to charge: the store does not sell the variant in the
180
+ * order's currency and no price was stated for the line. Every money field is
181
+ * `null`, never 0 and never a rate-derived figure.
182
+ */
183
+ export interface NotPurchasableLinePricePreview extends LinePricePreviewBase {
184
+ purchasable: false;
185
+ notPurchasableCode: LineNotPurchasableCode;
186
+ chargedUnitPrice: null;
187
+ chargedUnitPriceWithTax: null;
188
+ retailBase: null;
189
+ }
190
+ /**
191
+ * What one line would cost. Check `purchasable` before reading a price: the
192
+ * money fields are numbers only on a purchasable line.
193
+ */
194
+ export type LinePricePreview = PurchasableLinePricePreview | NotPurchasableLinePricePreview;
195
+ /**
196
+ * Its own document on purpose: `previewOrderLinePrices` exists only on an
197
+ * engine with the line price preview, so on an older one this call alone fails
198
+ * validation and no other order call does.
199
+ */
200
+ export declare const PREVIEW_ORDER_LINE_PRICES_QUERY = "\n query PreviewOrderLinePrices($input: PreviewOrderLinePricesInput!) {\n previewOrderLinePrices(input: $input) {\n lineId\n productVariantId\n purchasable\n notPurchasableCode\n chargedUnitPrice\n chargedUnitPriceWithTax\n basis\n basisKnown\n retailBase\n catalogueChanged\n stacking {\n source\n amount\n }\n overrideInert\n taxProvisional\n }\n }\n";
201
+ export interface OrderLinePricePreviewModule {
202
+ /**
203
+ * What lines of an order would cost, before anything is saved: the pricing
204
+ * engine's own answer for a staged manual unit price, one-time discount and
205
+ * quantity, on stored lines and on lines that are not on the order yet. One
206
+ * result per entry of `lines`, in the order of `lines`. Needs `ReadOrder`,
207
+ * and an engine that serves `previewOrderLinePrices`.
208
+ *
209
+ * A pure read: nothing is saved, no event is published, and no payment or
210
+ * tax provider is contacted.
211
+ *
212
+ * The answer is what a re-price of the line gives now: today's catalogue
213
+ * price, price lists, tiers and tax. A stored line that a save does not
214
+ * re-price keeps its stored price, so compare `chargedUnitPrice` and
215
+ * `chargedUnitPriceWithTax` with the line's own `unitPrice` and
216
+ * `unitPriceWithTax` to see whether they differ (a changed tax driver can
217
+ * move one of the two and not the other). `catalogueChanged` reports a
218
+ * moved catalogue retail only; its own description says what counts as one.
219
+ *
220
+ * Two kinds of stored line KEEP the tax rate they carry, and their tax is
221
+ * not re-evaluated: every line of the order on a store with an active tax
222
+ * provider app (the app is not asked), and a line whose variant was moved to
223
+ * another tax category since. A tax driver that changed since (a VAT number
224
+ * validated, tax removed) does not show in such a line's figures, so the
225
+ * comparison above does not see it.
226
+ *
227
+ * The preview does not
228
+ * predict what a save refuses: a staged one-time discount that the Admin
229
+ * API's `setOrderPriceListDiscounts` would refuse is still priced, and shows
230
+ * no `ONE_TIME` step when the pricing rules skipped it.
231
+ *
232
+ * Every figure is minor units in the order's currency, before promotions. A
233
+ * placed order converts at the rate it was placed at. Each line is taxed as
234
+ * a re-price would tax it now, apart from the two kinds of stored line named
235
+ * above.
236
+ *
237
+ * A store with an active tax provider app gets a platform-taxed preview for
238
+ * new lines. There a line of the order keeps the rate it carries, but a
239
+ * line that is not on the order yet is taxed at the platform's rate: the app
240
+ * is never asked by a preview and answers when the line is added.
241
+ * `taxProvisional` marks those lines. Their figure in `basis` is firm. The
242
+ * other one (the gross of a `NET` line, the net of a `GROSS` line) may then
243
+ * differ, so show it as provisional.
244
+ *
245
+ * On such a store, state every manual price in the line's `basis`, for a
246
+ * line of the order as well as a new one: preview the line without an
247
+ * `override` first and read `basis`. One stated in the other basis is
248
+ * refused there, and on a line of the order whose variant was moved to
249
+ * another tax category, because the preview never converts a price at a
250
+ * tax rate it did not evaluate (`PreviewLinePriceOverride.basis`).
251
+ *
252
+ * Check `purchasable` before reading a price. A variant the store does not
253
+ * sell in the order's currency is answered `purchasable: false` with
254
+ * `notPurchasableCode` set and every money field `null`, never 0, unless a
255
+ * price is stated for the line (for example a manual unit price, staged or
256
+ * stored). The own lines of an order placed at a recorded exchange rate are
257
+ * not judged; a line that is not on the order yet always is.
258
+ *
259
+ * `basis` on a result is the basis a manual unit price must be sent in to
260
+ * the Admin API's `applyOrderLinePriceOverrides`, and the `OVERRIDE` step of
261
+ * `stacking` is that figure.
262
+ *
263
+ * `override` and `oneTimeDiscount` on a line, and `options.orderDiscount`
264
+ * (a whole-order one-time discount, `PERCENTAGE` or `FIXED_AMOUNT`), each
265
+ * have three states: left out keeps what the order has, `null` clears it, a
266
+ * value stages it. The SDK sends them as given.
267
+ *
268
+ * At least 1 and at most 100 lines per call. Each call prices from the saved
269
+ * order plus what that call stages: stage a whole-order discount, and every
270
+ * quantity a collection or facet tier depends on, in the same call as the
271
+ * lines they affect. A removed line cannot be staged (a quantity is 1 or
272
+ * more): the collection and facet tiers of the other lines still count it at
273
+ * its stored quantity.
274
+ *
275
+ * Refusals:
276
+ * - `PREVIEW_ORDER_NOT_FOUND`, `PREVIEW_ORDER_LINE_NOT_FOUND` and
277
+ * `PREVIEW_VARIANT_NOT_FOUND` (`NotFoundError`, 404). An id of another
278
+ * store answers like a missing one, and a cancelled line is not found. An
279
+ * id that is not a uuid is refused before that with core's
280
+ * `ENTITY_NOT_FOUND`, also a `NotFoundError`: branch on the class for
281
+ * not-found, not on one code.
282
+ * - `INVALID_PREVIEW_INPUT` (`ValidationError`, 400): no lines or more than
283
+ * 100, a quantity below 1, an order line given twice, a `lineId` that is
284
+ * not a line of that `productVariantId`, an amount or discount value out
285
+ * of range, a `FIXED_PRICE` whole-order discount, two lines of one variant
286
+ * staging different one-time discounts, `override: null` on an externally
287
+ * priced line (it has no catalogue price to fall back to), or an `override`
288
+ * stated in the other basis than the line's on a line whose tax rate the
289
+ * preview does not evaluate (`PreviewLinePriceOverride.basis`).
290
+ * - `PREVIEW_CHANNEL_NOT_ALLOWED` (`PermissionDeniedError`, 403): the call
291
+ * was made from the default channel instead of the order's own.
292
+ */
293
+ previewLinePrices(orderId: string, lines: PreviewLinePriceLine[], options?: Call & {
294
+ orderDiscount?: PreviewOneTimeDiscount | null;
295
+ }): Promise<LinePricePreview[]>;
296
+ }
297
+ export declare function createOrderLinePricePreviewModule(transport: Transport): OrderLinePricePreviewModule;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Its own document on purpose: `previewOrderLinePrices` exists only on an
3
+ * engine with the line price preview, so on an older one this call alone fails
4
+ * validation and no other order call does.
5
+ */
6
+ export const PREVIEW_ORDER_LINE_PRICES_QUERY = /* GraphQL */ `
7
+ query PreviewOrderLinePrices($input: PreviewOrderLinePricesInput!) {
8
+ previewOrderLinePrices(input: $input) {
9
+ lineId
10
+ productVariantId
11
+ purchasable
12
+ notPurchasableCode
13
+ chargedUnitPrice
14
+ chargedUnitPriceWithTax
15
+ basis
16
+ basisKnown
17
+ retailBase
18
+ catalogueChanged
19
+ stacking {
20
+ source
21
+ amount
22
+ }
23
+ overrideInert
24
+ taxProvisional
25
+ }
26
+ }
27
+ `;
28
+ export function createOrderLinePricePreviewModule(transport) {
29
+ return {
30
+ async previewLinePrices(orderId, lines, options) {
31
+ const data = await transport.graphql({
32
+ api: 'admin',
33
+ query: PREVIEW_ORDER_LINE_PRICES_QUERY,
34
+ variables: {
35
+ input: {
36
+ orderId,
37
+ // The lines and `orderDiscount` go out as given, never
38
+ // normalised: left out, `null` and a value are three different
39
+ // requests to the engine (keep, clear, stage). `JSON.stringify`
40
+ // drops a key that is `undefined` and keeps a `null`, so adding
41
+ // a `?? null` or a default here would turn "keep" into "clear".
42
+ lines,
43
+ orderDiscount: options?.orderDiscount,
44
+ },
45
+ },
46
+ }, options);
47
+ return data.previewOrderLinePrices;
48
+ },
49
+ };
50
+ }
@@ -0,0 +1,132 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /**
4
+ * Manual discounts with a reason (incentives spec §4 decision 6): a store's list of discount
5
+ * reasons, its discount policy, and the log of the price movements the two pricing doors made on
6
+ * an order. The discounts themselves are given through those two doors: a manual unit price
7
+ * (`orders.setLinePrices`, the Admin API's `applyOrderLinePriceOverrides`) and one-time pricing
8
+ * (`orders.setOneTimeDiscounts`, `setOrderPriceListDiscounts`). Each takes a reason code, and a
9
+ * call that lowers a line's price follows the store's policy.
10
+ *
11
+ * WHO GAVE IT is never an argument: a token's own user is recorded, and the staff member and
12
+ * device it acts for are the `x-on-behalf-of` / `x-device-ref` refs the SDK already sends from
13
+ * `tenant.actor` (`TenantContext.actor`). The platform records them only when the credential is
14
+ * a machine token or an app installation, which it vouches for.
15
+ */
16
+ /** One of the store's reasons for a manual discount. */
17
+ export interface DiscountReason {
18
+ id: string;
19
+ /** Stable code the store chose: lower-case letters, digits, `-` and `_`. */
20
+ code: string;
21
+ label: string;
22
+ /** An inactive reason stays on the records that name it and is refused for new ones. */
23
+ active: boolean;
24
+ createdAt: string;
25
+ updatedAt: string;
26
+ }
27
+ export interface DiscountReasonInput {
28
+ code: string;
29
+ label: string;
30
+ /** Omitted keeps the stored state; a new reason starts active. */
31
+ active?: boolean;
32
+ }
33
+ /** The store's rule for the manual discount doors. */
34
+ export interface DiscountPolicy {
35
+ /**
36
+ * When true, a call that lowers a line's pre-promotion unit price needs one of the store's
37
+ * active reasons for that line. A till discount (`pos.sale.applyDiscount`) is not held to it.
38
+ */
39
+ reasonRequired: boolean;
40
+ }
41
+ export interface DiscountPolicyInput {
42
+ /** Omitted keeps the stored value. */
43
+ reasonRequired?: boolean;
44
+ }
45
+ /**
46
+ * One price movement a manual-discount door made on an order. Append-only. Each row is a price
47
+ * movement that door made; the sum of an order's rows is the net manual price movement recorded
48
+ * since the layer was enabled, not a statement of what discount is in force.
49
+ */
50
+ export interface OrderManualDiscount {
51
+ id: string;
52
+ createdAt: string;
53
+ orderId: string;
54
+ /** The line the movement was on; `null` for a till discount on the whole cart. */
55
+ orderLineId: string | null;
56
+ /**
57
+ * `price_list`, `line_override` or `till` (`pos.sale.applyDiscount`, one row per call). Accept a
58
+ * value you do not know.
59
+ */
60
+ door: string;
61
+ /**
62
+ * The change of the line's total, net: (unit price after − before) × quantity, minor units of
63
+ * `currencyCode`, as the order holds it. Negative when the price fell (a manual discount). For
64
+ * `till`: the money the call's negative surcharges added.
65
+ */
66
+ amount: number;
67
+ /** The same movement gross. */
68
+ amountWithTax: number;
69
+ currencyCode: string;
70
+ /** The reason the price fell under; `null` when it rose, or fell with none asked. */
71
+ reason: {
72
+ id: string;
73
+ code: string;
74
+ label: string;
75
+ active: boolean;
76
+ } | null;
77
+ /** The Vendure user of the session that moved it. */
78
+ actorUserId: string | null;
79
+ /** The vouched-for `x-on-behalf-of` ref; for a till vouched for nothing, `pos-staff:<id>`. */
80
+ onBehalfOfRef: string | null;
81
+ /** The vouched-for `x-device-ref` ref; for a paired till vouched for nothing, `pos-device:<id>`. */
82
+ deviceRef: string | null;
83
+ /** Shared by the rows of one call. */
84
+ callId: string;
85
+ }
86
+ export interface DiscountReasonsModule {
87
+ /**
88
+ * The store's reasons, active first. Needs `ReadOrder`, `ReadSettings` or `OperatePos` (the
89
+ * `pos` token, whose till sends one with `pos.sale.applyDiscount`).
90
+ */
91
+ list(options?: Call & {
92
+ includeInactive?: boolean;
93
+ }): Promise<DiscountReason[]>;
94
+ /**
95
+ * Create the reason, or change the label and active flag of the one with this code. A reason
96
+ * is never deleted: retire it with `active: false`. Needs `UpdateSettings`. Refused
97
+ * `DISCOUNT_REASON_CODE_INVALID` / `DISCOUNT_REASON_LABEL_INVALID` (→ `ValidationError`), and
98
+ * `DISCOUNT_REASON_LABEL_CONFLICT` when an active reason would share a label or code with
99
+ * another, so each name means one reason (staff read labels, integrations send codes). Only a
100
+ * `reasonCode` satisfies the policy; a price note is free text and never read as a reason.
101
+ */
102
+ upsert(input: DiscountReasonInput, options?: Call): Promise<DiscountReason>;
103
+ }
104
+ export interface DiscountPolicyModule {
105
+ /**
106
+ * The store's policy; the default (no reason required) when it never set one. Needs
107
+ * `ReadOrder`, `ReadSettings` or `OperatePos`.
108
+ */
109
+ get(options?: Call): Promise<DiscountPolicy>;
110
+ /** Needs `UpdateSettings`. */
111
+ update(input: DiscountPolicyInput, options?: Call): Promise<DiscountPolicy>;
112
+ }
113
+ /**
114
+ * A store's discount reasons and policy, and what an order was given (`ReadOrder`).
115
+ *
116
+ * The policy is applied by the doors that give a manual discount (`orders.setLinePrices`,
117
+ * `orders.setOneTimeDiscounts`), which refuse with `DISCOUNT_REASON_REQUIRED` and
118
+ * `DISCOUNT_REASON_UNKNOWN`. The till's
119
+ * `pos.sale.applyDiscount` records the reason it is given and refuses only an unknown code.
120
+ */
121
+ export interface ManualDiscountsModule {
122
+ /** Every price movement recorded on the order, newest first. Another store's order answers `[]`. */
123
+ list(orderId: string, options?: Call): Promise<OrderManualDiscount[]>;
124
+ reasons: DiscountReasonsModule;
125
+ policy: DiscountPolicyModule;
126
+ }
127
+ export declare const DISCOUNT_REASONS_QUERY = "\n query DiscountReasons($includeInactive: Boolean) {\n discountReasons(includeInactive: $includeInactive) {\n \n id\n code\n label\n active\n createdAt\n updatedAt\n\n }\n }\n";
128
+ export declare const UPSERT_DISCOUNT_REASON_MUTATION = "\n mutation UpsertDiscountReason($input: UpsertDiscountReasonInput!) {\n upsertDiscountReason(input: $input) {\n \n id\n code\n label\n active\n createdAt\n updatedAt\n\n }\n }\n";
129
+ export declare const DISCOUNT_POLICY_QUERY = "\n query DiscountPolicy {\n discountPolicy {\n reasonRequired\n }\n }\n";
130
+ export declare const UPDATE_DISCOUNT_POLICY_MUTATION = "\n mutation UpdateDiscountPolicy($input: UpdateDiscountPolicyInput!) {\n updateDiscountPolicy(input: $input) {\n reasonRequired\n }\n }\n";
131
+ export declare const ORDER_MANUAL_DISCOUNTS_QUERY = "\n query OrderManualDiscounts($orderId: ID!) {\n orderManualDiscounts(orderId: $orderId) {\n \n id\n createdAt\n orderId\n orderLineId\n door\n amount\n amountWithTax\n currencyCode\n reason {\n id\n code\n label\n active\n }\n actorUserId\n onBehalfOfRef\n deviceRef\n callId\n\n }\n }\n";
132
+ export declare function createManualDiscountsModule(transport: Transport): ManualDiscountsModule;
@@ -0,0 +1,95 @@
1
+ const REASON_FIELDS = /* GraphQL */ `
2
+ id
3
+ code
4
+ label
5
+ active
6
+ createdAt
7
+ updatedAt
8
+ `;
9
+ const RECORD_FIELDS = /* GraphQL */ `
10
+ id
11
+ createdAt
12
+ orderId
13
+ orderLineId
14
+ door
15
+ amount
16
+ amountWithTax
17
+ currencyCode
18
+ reason {
19
+ id
20
+ code
21
+ label
22
+ active
23
+ }
24
+ actorUserId
25
+ onBehalfOfRef
26
+ deviceRef
27
+ callId
28
+ `;
29
+ export const DISCOUNT_REASONS_QUERY = /* GraphQL */ `
30
+ query DiscountReasons($includeInactive: Boolean) {
31
+ discountReasons(includeInactive: $includeInactive) {
32
+ ${REASON_FIELDS}
33
+ }
34
+ }
35
+ `;
36
+ export const UPSERT_DISCOUNT_REASON_MUTATION = /* GraphQL */ `
37
+ mutation UpsertDiscountReason($input: UpsertDiscountReasonInput!) {
38
+ upsertDiscountReason(input: $input) {
39
+ ${REASON_FIELDS}
40
+ }
41
+ }
42
+ `;
43
+ export const DISCOUNT_POLICY_QUERY = /* GraphQL */ `
44
+ query DiscountPolicy {
45
+ discountPolicy {
46
+ reasonRequired
47
+ }
48
+ }
49
+ `;
50
+ export const UPDATE_DISCOUNT_POLICY_MUTATION = /* GraphQL */ `
51
+ mutation UpdateDiscountPolicy($input: UpdateDiscountPolicyInput!) {
52
+ updateDiscountPolicy(input: $input) {
53
+ reasonRequired
54
+ }
55
+ }
56
+ `;
57
+ export const ORDER_MANUAL_DISCOUNTS_QUERY = /* GraphQL */ `
58
+ query OrderManualDiscounts($orderId: ID!) {
59
+ orderManualDiscounts(orderId: $orderId) {
60
+ ${RECORD_FIELDS}
61
+ }
62
+ }
63
+ `;
64
+ export function createManualDiscountsModule(transport) {
65
+ return {
66
+ async list(orderId, options) {
67
+ const data = await transport.graphql({ api: 'admin', query: ORDER_MANUAL_DISCOUNTS_QUERY, variables: { orderId } }, options);
68
+ return data.orderManualDiscounts;
69
+ },
70
+ reasons: {
71
+ async list(options) {
72
+ const data = await transport.graphql({
73
+ api: 'admin',
74
+ query: DISCOUNT_REASONS_QUERY,
75
+ variables: { includeInactive: options?.includeInactive },
76
+ }, options);
77
+ return data.discountReasons;
78
+ },
79
+ async upsert(input, options) {
80
+ const data = await transport.graphql({ api: 'admin', query: UPSERT_DISCOUNT_REASON_MUTATION, variables: { input } }, options);
81
+ return data.upsertDiscountReason;
82
+ },
83
+ },
84
+ policy: {
85
+ async get(options) {
86
+ const data = await transport.graphql({ api: 'admin', query: DISCOUNT_POLICY_QUERY }, options);
87
+ return data.discountPolicy;
88
+ },
89
+ async update(input, options) {
90
+ const data = await transport.graphql({ api: 'admin', query: UPDATE_DISCOUNT_POLICY_MUTATION, variables: { input } }, options);
91
+ return data.updateDiscountPolicy;
92
+ },
93
+ },
94
+ };
95
+ }