@sixtyninecommerce/admin 0.8.0 → 0.10.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 (179) hide show
  1. package/README.md +2739 -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 +650 -0
  28. package/dist/catalog/products.js +458 -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 +324 -0
  34. package/dist/catalog/variants.js +288 -0
  35. package/dist/catalog/visibility.d.ts +57 -0
  36. package/dist/catalog/visibility.js +59 -0
  37. package/dist/client.d.ts +192 -3
  38. package/dist/client.js +87 -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 +437 -0
  66. package/dist/fulfillments/index.js +534 -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 +95 -9
  74. package/dist/index.js +21 -1
  75. package/dist/integrations/index.d.ts +14 -0
  76. package/dist/integrations/index.js +9 -0
  77. package/dist/integrations/pipelines.d.ts +113 -0
  78. package/dist/integrations/pipelines.js +62 -0
  79. package/dist/integrations/types.d.ts +176 -0
  80. package/dist/integrations/types.js +8 -0
  81. package/dist/jobs/bulk-action-run.d.ts +74 -0
  82. package/dist/jobs/bulk-action-run.js +69 -0
  83. package/dist/locations/index.d.ts +6 -2
  84. package/dist/meta/index.d.ts +32 -0
  85. package/dist/orders/bulk.d.ts +75 -0
  86. package/dist/orders/bulk.js +150 -0
  87. package/dist/orders/commit-edit.d.ts +123 -0
  88. package/dist/orders/commit-edit.js +142 -0
  89. package/dist/orders/deposit-policy.d.ts +103 -0
  90. package/dist/orders/deposit-policy.js +202 -0
  91. package/dist/orders/get.d.ts +722 -0
  92. package/dist/orders/get.js +530 -0
  93. package/dist/orders/index.d.ts +186 -21
  94. package/dist/orders/index.js +57 -0
  95. package/dist/orders/line-price-preview.d.ts +297 -0
  96. package/dist/orders/line-price-preview.js +50 -0
  97. package/dist/orders/manual-discounts.d.ts +141 -0
  98. package/dist/orders/manual-discounts.js +97 -0
  99. package/dist/orders/manual-pricing.d.ts +192 -0
  100. package/dist/orders/manual-pricing.js +72 -0
  101. package/dist/orders/order-entry.d.ts +566 -0
  102. package/dist/orders/order-entry.js +129 -0
  103. package/dist/orders/parcel-charge.d.ts +45 -0
  104. package/dist/orders/parcel-charge.js +55 -0
  105. package/dist/orders/plan-edit.d.ts +489 -0
  106. package/dist/orders/plan-edit.js +93 -0
  107. package/dist/orders/status.d.ts +235 -0
  108. package/dist/orders/status.js +96 -0
  109. package/dist/orders/surcharges.d.ts +75 -2
  110. package/dist/orders/surcharges.js +110 -4
  111. package/dist/payments/account-credit.d.ts +171 -0
  112. package/dist/payments/account-credit.js +107 -0
  113. package/dist/payments/index.d.ts +241 -9
  114. package/dist/payments/index.js +92 -0
  115. package/dist/payments/methods.d.ts +37 -0
  116. package/dist/payments/methods.js +33 -0
  117. package/dist/platform/catalog.d.ts +148 -0
  118. package/dist/platform/catalog.js +74 -0
  119. package/dist/platform/entitlements.d.ts +111 -0
  120. package/dist/platform/entitlements.js +86 -0
  121. package/dist/platform/legal-entities.d.ts +139 -0
  122. package/dist/platform/legal-entities.js +126 -0
  123. package/dist/platform/legal-entity-numbering.d.ts +103 -0
  124. package/dist/platform/legal-entity-numbering.js +101 -0
  125. package/dist/platform/organization-membership.d.ts +80 -0
  126. package/dist/platform/organization-membership.js +71 -0
  127. package/dist/platform/organization-settings.d.ts +33 -0
  128. package/dist/platform/organization-settings.js +42 -0
  129. package/dist/platform/organization-sharing.d.ts +172 -0
  130. package/dist/platform/organization-sharing.js +120 -0
  131. package/dist/platform/organizations.d.ts +205 -0
  132. package/dist/platform/organizations.js +180 -0
  133. package/dist/platform/provision-store.d.ts +88 -8
  134. package/dist/platform/provision-store.js +12 -0
  135. package/dist/platform/reports.d.ts +46 -0
  136. package/dist/platform/reports.js +31 -0
  137. package/dist/platform/server-metrics.d.ts +58 -0
  138. package/dist/platform/server-metrics.js +11 -0
  139. package/dist/pos/index.d.ts +567 -0
  140. package/dist/pos/index.js +205 -0
  141. package/dist/pricing/index.d.ts +408 -0
  142. package/dist/pricing/index.js +353 -0
  143. package/dist/pricing/vouchers.d.ts +103 -0
  144. package/dist/pricing/vouchers.js +69 -0
  145. package/dist/provenance/index.d.ts +93 -0
  146. package/dist/provenance/index.js +53 -0
  147. package/dist/reports/index.d.ts +199 -0
  148. package/dist/reports/index.js +154 -0
  149. package/dist/returns/index.d.ts +225 -0
  150. package/dist/returns/index.js +160 -0
  151. package/dist/search/index.d.ts +99 -0
  152. package/dist/search/index.js +62 -0
  153. package/dist/shipping/parcel-count-suggestion.d.ts +52 -0
  154. package/dist/shipping/parcel-count-suggestion.js +73 -0
  155. package/dist/shipping/parcel-rule.d.ts +48 -0
  156. package/dist/shipping/parcel-rule.js +91 -0
  157. package/dist/stock/index.d.ts +166 -0
  158. package/dist/stock/index.js +115 -0
  159. package/dist/stock/transfers.d.ts +520 -0
  160. package/dist/stock/transfers.js +437 -0
  161. package/dist/stored-value/index.d.ts +154 -0
  162. package/dist/stored-value/index.js +130 -0
  163. package/dist/tenant/capabilities.d.ts +10 -0
  164. package/dist/tenant/entitlements.d.ts +35 -0
  165. package/dist/tenant/entitlements.js +15 -0
  166. package/dist/tenant/field-groups.d.ts +64 -0
  167. package/dist/tenant/field-groups.js +34 -0
  168. package/dist/tenant/legal-entity.d.ts +32 -0
  169. package/dist/tenant/legal-entity.js +41 -0
  170. package/dist/tenant/notifications.d.ts +148 -0
  171. package/dist/tenant/notifications.js +79 -0
  172. package/dist/tenant/retention.d.ts +10 -4
  173. package/dist/tenant/settings-sources.d.ts +103 -0
  174. package/dist/tenant/settings-sources.js +92 -0
  175. package/dist/types.d.ts +86 -11
  176. package/dist/uploads/index.d.ts +11 -7
  177. package/dist/users/index.d.ts +104 -0
  178. package/dist/users/index.js +80 -0
  179. package/package.json +3 -2
@@ -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,141 @@
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
+ * The store's ceiling on manual discounts in basis points (1000 = 10 %), or `null` for none: how
42
+ * far below the price the customer would get anyway (its contract included) staff without the
43
+ * `OverrideDiscountLimit` permission may take a line (`DISCOUNT_OVER_LIMIT`). Reducing a
44
+ * discount is never refused. The POS till is not held to it.
45
+ */
46
+ maxDiscountBps: number | null;
47
+ }
48
+ export interface DiscountPolicyInput {
49
+ /** Omitted keeps the stored value. */
50
+ reasonRequired?: boolean;
51
+ /** 0..10000 basis points; omitted keeps the stored value, `null` removes the ceiling. */
52
+ maxDiscountBps?: number | null;
53
+ }
54
+ /**
55
+ * One price movement a manual-discount door made on an order. Append-only. Each row is a price
56
+ * movement that door made; the sum of an order's rows is the net manual price movement recorded
57
+ * since the layer was enabled, not a statement of what discount is in force.
58
+ */
59
+ export interface OrderManualDiscount {
60
+ id: string;
61
+ createdAt: string;
62
+ orderId: string;
63
+ /** The line the movement was on; `null` for a till discount on the whole cart. */
64
+ orderLineId: string | null;
65
+ /**
66
+ * `price_list`, `line_override` or `till` (`pos.sale.applyDiscount`, one row per call). Accept a
67
+ * value you do not know.
68
+ */
69
+ door: string;
70
+ /**
71
+ * The change of the line's total, net: (unit price after − before) × quantity, minor units of
72
+ * `currencyCode`, as the order holds it. Negative when the price fell (a manual discount). For
73
+ * `till`: the money the call's negative surcharges added.
74
+ */
75
+ amount: number;
76
+ /** The same movement gross. */
77
+ amountWithTax: number;
78
+ currencyCode: string;
79
+ /** The reason the price fell under; `null` when it rose, or fell with none asked. */
80
+ reason: {
81
+ id: string;
82
+ code: string;
83
+ label: string;
84
+ active: boolean;
85
+ } | null;
86
+ /** The Vendure user of the session that moved it. */
87
+ actorUserId: string | null;
88
+ /** The vouched-for `x-on-behalf-of` ref; for a till vouched for nothing, `pos-staff:<id>`. */
89
+ onBehalfOfRef: string | null;
90
+ /** The vouched-for `x-device-ref` ref; for a paired till vouched for nothing, `pos-device:<id>`. */
91
+ deviceRef: string | null;
92
+ /** Shared by the rows of one call. */
93
+ callId: string;
94
+ }
95
+ export interface DiscountReasonsModule {
96
+ /**
97
+ * The store's reasons, active first. Needs `ReadOrder`, `ReadSettings` or `OperatePos` (the
98
+ * `pos` token, whose till sends one with `pos.sale.applyDiscount`).
99
+ */
100
+ list(options?: Call & {
101
+ includeInactive?: boolean;
102
+ }): Promise<DiscountReason[]>;
103
+ /**
104
+ * Create the reason, or change the label and active flag of the one with this code. A reason
105
+ * is never deleted: retire it with `active: false`. Needs `UpdateSettings`. Refused
106
+ * `DISCOUNT_REASON_CODE_INVALID` / `DISCOUNT_REASON_LABEL_INVALID` (→ `ValidationError`), and
107
+ * `DISCOUNT_REASON_LABEL_CONFLICT` when an active reason would share a label or code with
108
+ * another, so each name means one reason (staff read labels, integrations send codes). Only a
109
+ * `reasonCode` satisfies the policy; a price note is free text and never read as a reason.
110
+ */
111
+ upsert(input: DiscountReasonInput, options?: Call): Promise<DiscountReason>;
112
+ }
113
+ export interface DiscountPolicyModule {
114
+ /**
115
+ * The store's policy; the default (no reason required) when it never set one. Needs
116
+ * `ReadOrder`, `ReadSettings` or `OperatePos`.
117
+ */
118
+ get(options?: Call): Promise<DiscountPolicy>;
119
+ /** Needs `UpdateSettings`. */
120
+ update(input: DiscountPolicyInput, options?: Call): Promise<DiscountPolicy>;
121
+ }
122
+ /**
123
+ * A store's discount reasons and policy, and what an order was given (`ReadOrder`).
124
+ *
125
+ * The policy is applied by the doors that give a manual discount (`orders.setLinePrices`,
126
+ * `orders.setOneTimeDiscounts`), which refuse with `DISCOUNT_REASON_REQUIRED` and
127
+ * `DISCOUNT_REASON_UNKNOWN`. The till's
128
+ * `pos.sale.applyDiscount` records the reason it is given and refuses only an unknown code.
129
+ */
130
+ export interface ManualDiscountsModule {
131
+ /** Every price movement recorded on the order, newest first. Another store's order answers `[]`. */
132
+ list(orderId: string, options?: Call): Promise<OrderManualDiscount[]>;
133
+ reasons: DiscountReasonsModule;
134
+ policy: DiscountPolicyModule;
135
+ }
136
+ 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";
137
+ 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";
138
+ export declare const DISCOUNT_POLICY_QUERY = "\n query DiscountPolicy {\n discountPolicy {\n reasonRequired\n maxDiscountBps\n }\n }\n";
139
+ export declare const UPDATE_DISCOUNT_POLICY_MUTATION = "\n mutation UpdateDiscountPolicy($input: UpdateDiscountPolicyInput!) {\n updateDiscountPolicy(input: $input) {\n reasonRequired\n maxDiscountBps\n }\n }\n";
140
+ 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";
141
+ export declare function createManualDiscountsModule(transport: Transport): ManualDiscountsModule;
@@ -0,0 +1,97 @@
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
+ maxDiscountBps
48
+ }
49
+ }
50
+ `;
51
+ export const UPDATE_DISCOUNT_POLICY_MUTATION = /* GraphQL */ `
52
+ mutation UpdateDiscountPolicy($input: UpdateDiscountPolicyInput!) {
53
+ updateDiscountPolicy(input: $input) {
54
+ reasonRequired
55
+ maxDiscountBps
56
+ }
57
+ }
58
+ `;
59
+ export const ORDER_MANUAL_DISCOUNTS_QUERY = /* GraphQL */ `
60
+ query OrderManualDiscounts($orderId: ID!) {
61
+ orderManualDiscounts(orderId: $orderId) {
62
+ ${RECORD_FIELDS}
63
+ }
64
+ }
65
+ `;
66
+ export function createManualDiscountsModule(transport) {
67
+ return {
68
+ async list(orderId, options) {
69
+ const data = await transport.graphql({ api: 'admin', query: ORDER_MANUAL_DISCOUNTS_QUERY, variables: { orderId } }, options);
70
+ return data.orderManualDiscounts;
71
+ },
72
+ reasons: {
73
+ async list(options) {
74
+ const data = await transport.graphql({
75
+ api: 'admin',
76
+ query: DISCOUNT_REASONS_QUERY,
77
+ variables: { includeInactive: options?.includeInactive },
78
+ }, options);
79
+ return data.discountReasons;
80
+ },
81
+ async upsert(input, options) {
82
+ const data = await transport.graphql({ api: 'admin', query: UPSERT_DISCOUNT_REASON_MUTATION, variables: { input } }, options);
83
+ return data.upsertDiscountReason;
84
+ },
85
+ },
86
+ policy: {
87
+ async get(options) {
88
+ const data = await transport.graphql({ api: 'admin', query: DISCOUNT_POLICY_QUERY }, options);
89
+ return data.discountPolicy;
90
+ },
91
+ async update(input, options) {
92
+ const data = await transport.graphql({ api: 'admin', query: UPDATE_DISCOUNT_POLICY_MUTATION, variables: { input } }, options);
93
+ return data.updateDiscountPolicy;
94
+ },
95
+ },
96
+ };
97
+ }
@@ -0,0 +1,192 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import { type OrderDiscounts } from '../pricing/index.js';
3
+ import type { Call } from '../types.js';
4
+ /**
5
+ * The two doors that move a manual price on an order (incentives spec §4 decision 6): a line's
6
+ * manual unit price (`applyOrderLinePriceOverrides`) and the order's one-time discounts
7
+ * (`setOrderPriceListDiscounts`). Their read twin is `orders.previewLinePrices`, which prices the
8
+ * same changes without saving them; what each call moved is read back with
9
+ * `orders.manualDiscounts.list`.
10
+ *
11
+ * Both run in one transaction, re-price the lines they change, and re-total the order. Both move
12
+ * money with NO refund, so both refuse an order whose payment was collected. Change such an
13
+ * order through an order modification: plan it with `orders.planEdit` (which saves and refunds
14
+ * nothing), then carry it out through the Admin API's `modifyOrder` directly, which issues the
15
+ * refund. This SDK has no method for that step until `orders.commitEdit` ships.
16
+ */
17
+ /** How a one-time discount is stated (the engine's `OrderPriceListDiscountType`). */
18
+ export type OneTimeDiscountType = 'PERCENTAGE' | 'FIXED_AMOUNT' | 'FIXED_PRICE';
19
+ /** One line's change for {@link OrderManualPricingModule.setLinePrices}. */
20
+ export interface LinePriceInput {
21
+ orderLineId: string;
22
+ /**
23
+ * The manual unit price, a whole number of minor units, 0 or more, in the LINE's tax basis:
24
+ * gross when the line's `listPriceIncludesTax` is true (`orders.get`), net otherwise. That is
25
+ * the `basis` `orders.previewLinePrices` answers for the line, and it is not always the store's:
26
+ * a line priced in a customer-country tax zone is net on a store that prices gross. The engine
27
+ * takes no basis with it and converts nothing.
28
+ *
29
+ * Three states: left out keeps the stored price (a note-only change), `null` clears it and
30
+ * re-prices the line from the catalogue, a number sets it.
31
+ */
32
+ unitPriceOverride?: number | null;
33
+ /** A free-text note on the price. Left out keeps the stored one; `null` or `''` clears it. */
34
+ priceOverrideReason?: string | null;
35
+ /**
36
+ * One of the store's active discount reasons (`manualDiscounts.reasons`), by code, for this
37
+ * line when the call lowers its price. Wins over the call's `reasonCode` for this line.
38
+ */
39
+ reasonCode?: string | null;
40
+ }
41
+ export interface SetLinePricesInput {
42
+ /** At least one line; a line once per call. Lines not named keep the price they have. */
43
+ lines: LinePriceInput[];
44
+ /** The reason for every line whose price the call lowers and that names none of its own. */
45
+ reasonCode?: string | null;
46
+ }
47
+ /** A one-time discount on one line's product variant. */
48
+ export interface OneTimeLineDiscountInput {
49
+ orderLineId: string;
50
+ discountType: OneTimeDiscountType;
51
+ /**
52
+ * A whole number. `PERCENTAGE`: basis points, 1 to 10000. `FIXED_AMOUNT`: minor units off each
53
+ * unit, 1 or more. `FIXED_PRICE`: the unit price itself, minor units, 0 or more. The two money
54
+ * kinds are in the STORE's tax basis (as its catalogue prices are entered), which is not always
55
+ * the line's, and in the order's currency.
56
+ */
57
+ discountValue: number;
58
+ /** One of the store's active discount reasons, by code, for this line when its price falls. */
59
+ reasonCode?: string | null;
60
+ }
61
+ /** The whole-order one-time discount: every live line without an entry of its own. */
62
+ export interface OneTimeOrderDiscountInput {
63
+ /** `FIXED_PRICE` is refused: one absolute price for every product is never what is meant. */
64
+ discountType: Exclude<OneTimeDiscountType, 'FIXED_PRICE'>;
65
+ /**
66
+ * `PERCENTAGE`: basis points, 1 to 10000. `FIXED_AMOUNT`: minor units in the store's tax basis
67
+ * taken off EVERY UNIT, 1 or more. An amount off the order total is a surcharge
68
+ * (`orders.surcharges.add` with a negative price), not this.
69
+ */
70
+ discountValue: number;
71
+ /**
72
+ * One of the store's active discount reasons, for every line this discount covers whose price
73
+ * falls. Wins over the call's `reasonCode` for those lines.
74
+ */
75
+ reasonCode?: string | null;
76
+ }
77
+ /**
78
+ * The COMPLETE one-time pricing the order should end with. Not a change: a live line that is not
79
+ * in `lines` has no line discount afterwards, and `orderDiscount: null` removes the whole-order
80
+ * one. To keep what the order has, send it again (`orders.get(id, { include: ['priceList'] })`
81
+ * reads it).
82
+ */
83
+ export interface SetOneTimeDiscountsInput {
84
+ /** Required, so that removing it is said out loud: `null` for no whole-order discount. */
85
+ orderDiscount: OneTimeOrderDiscountInput | null;
86
+ /** Every line discount the order should have. An empty list removes them all. */
87
+ lines: OneTimeLineDiscountInput[];
88
+ /** A free-text note kept once for the order. Left out or `null` keeps it; `''` clears it. */
89
+ reason?: string | null;
90
+ /** The reason for every line whose price the call lowers and that no other `reasonCode` covers. */
91
+ reasonCode?: string | null;
92
+ }
93
+ /**
94
+ * The two manual pricing doors. Each answers the order as the engine left it, read with the same
95
+ * fields as `pricing.discounts(orderId)`: every line's `unitPrice` / `unitPriceWithTax` is its
96
+ * price before promotions, which is where a manual price or a one-time discount shows (neither is
97
+ * a promotion, so neither appears in `discounts`). The record of what the call moved is
98
+ * `orders.manualDiscounts.list(orderId)`: one row per line whose price changed, with the reason
99
+ * when the price fell.
100
+ *
101
+ * **Reasons.** A line whose price before promotions the call LOWERS received a manual discount.
102
+ * When the store requires a reason (`orders.manualDiscounts.policy`), every such line needs one,
103
+ * from its own entry or from the call. A line whose price does not fall needs none: a raise, a
104
+ * price a contract's fixed price wins over, a note-only change. Only a `reasonCode` counts as a
105
+ * reason; a note is free text.
106
+ *
107
+ * **Idempotency.** Takes `options.idempotencyKey`, as the other money writes do. The first answer
108
+ * under a key is kept for 24 hours and given again to the same request without running it: a
109
+ * success (the order, re-read as it is now) and EVERY refusal with a 4xx status, the doors' own
110
+ * `USER_INPUT_ERROR` guards included (a collected payment, a completed order, a bad value). Only a
111
+ * failure with a 5xx, 408, 425 or 429 status frees the key for a retry. So once you have fixed
112
+ * the cause of a refusal (reopened the order, picked a reason), send the corrected request under a
113
+ * NEW key: the same key on a different request, the other door included, is
114
+ * `IDEMPOTENCY_CONFLICT`.
115
+ *
116
+ * **Coded refusals.** Nothing is written by a refused call.
117
+ * - `DISCOUNT_REASON_REQUIRED` (`BusinessRuleError`, 422): the store requires a reason, the call
118
+ * lowered a line's price, and no reason covers that line. Ask the merchant for one of
119
+ * `manualDiscounts.reasons.list()` and send it on the line or the call.
120
+ * - `DISCOUNT_REASON_UNKNOWN` (`BusinessRuleError`, 422): a code sent, at any level, is not one of
121
+ * the store's active reasons (unknown, retired, or another store's). Checked before anything is
122
+ * written, also on a call that lowers no price.
123
+ * - `IDEMPOTENCY_CONFLICT` (`ConflictError`, 409): the key was used for another request. Use a
124
+ * fresh key per intended write. `IDEMPOTENCY_IN_PROGRESS` (`ConflictError`, 409): the first call
125
+ * under the key is still running; ask again shortly. `IDEMPOTENCY_KEY_INVALID`
126
+ * (`ValidationError`, 400): a key is 1 to 255 characters.
127
+ *
128
+ * **Uncoded refusals.** The doors' own guards are core `UserInputError`s: `ValidationError` (400)
129
+ * with code `USER_INPUT_ERROR` and the engine's sentence, which says what to do. Branch on the
130
+ * class and show the message; the engine gives these no codes of their own. They are:
131
+ * - the payment was collected (a settled payment, or one authorized on a card or online gateway):
132
+ * plan the edit with `orders.planEdit`, then carry it out through the Admin API's `modifyOrder`
133
+ * (no SDK method until `orders.commitEdit`), which refunds the difference. A payment authorized
134
+ * on an offline method (bank transfer, invoice, net terms) collected nothing and does not
135
+ * block. A payment whose method is no longer on the store cannot be judged: restore the method;
136
+ * - the order is invoiced (locked), completed (reopen it first) or cancelled;
137
+ * - the call was made from the default channel instead of the order's own;
138
+ * - the order is not this store's (the same answer as a missing one), or a named line is not on
139
+ * it, has been cancelled, or is named twice.
140
+ *
141
+ * Each method lists the refusals of its own below. An id that is not a uuid is refused before all
142
+ * of this with core's `ENTITY_NOT_FOUND` (`NotFoundError`, 404).
143
+ *
144
+ * Both need `UpdateOrder`, and an engine with the discount-reason layer (one that serves
145
+ * `discountReasons`); on an older one only these two calls fail.
146
+ */
147
+ export interface OrderManualPricingModule {
148
+ /**
149
+ * Set or clear the manual unit price, or its note, on lines of an order, and re-total it. Only
150
+ * the named lines are re-priced; every other line keeps its price. Taxes and totals are
151
+ * recalculated across the whole order.
152
+ *
153
+ * The manual price is a layer, not the final price: the customer's price list and the order's
154
+ * one-time discounts still apply on top of it, and a contract's fixed price wins over it
155
+ * (`previewLinePrices` answers `overrideInert` then). Setting or clearing a price takes the line
156
+ * out of the "exact price" state an imported, quoted or till-priced line arrives in
157
+ * (`customFields.unitPriceImported`), so those layers apply to it from then on; this door never
158
+ * sets that flag.
159
+ *
160
+ * Refusals of its own (`ValidationError`, `USER_INPUT_ERROR`): an empty `lines`; a line with
161
+ * neither `unitPriceOverride` nor `priceOverrideReason` (it asks for nothing); a negative price;
162
+ * `unitPriceOverride: null` on a line an external system priced (`orders.createOrRecover`
163
+ * external lines), which has no catalogue price to fall back to: state the price instead.
164
+ */
165
+ setLinePrices(orderId: string, input: SetLinePricesInput, options?: Call): Promise<OrderDiscounts>;
166
+ /**
167
+ * Replace the order's one-time pricing with `input`, its complete desired state, and re-price
168
+ * the lines it affects. A one-time discount is a price list of the order's own, ranked above
169
+ * every other price list and applied on top of a manual unit price. It applies to a line's
170
+ * product VARIANT, so the engine refuses it on a variant that is on two live lines (merge them
171
+ * first). Under a whole-order discount, lines an external system or an import priced exactly
172
+ * and free lines are skipped. Fixed money is in the order's currency at the time of the call.
173
+ * A call that removes everything on an order that has nothing writes nothing.
174
+ *
175
+ * Refusals of its own (`ValidationError`, `USER_INPUT_ERROR`): a value out of range or not a
176
+ * whole number; a `FIXED_PRICE` whole-order discount; a line entry on a line priced exactly
177
+ * (an import, an accepted quote, a till price: give it a manual unit price instead), on a free
178
+ * line, or on a variant that is on another live line; a discount the pricing rules could not
179
+ * apply (a `FIXED_AMOUNT` larger than the unit price is skipped, never clamped, and the message
180
+ * names the SKU); fixed money stored in another currency than the order's now (remove the
181
+ * one-time pricing, then set it again); and two first writes on one order at once (reload the
182
+ * order, then try again).
183
+ */
184
+ setOneTimeDiscounts(orderId: string, input: SetOneTimeDiscountsInput, options?: Call): Promise<OrderDiscounts>;
185
+ }
186
+ /**
187
+ * Each door its own document: the reason and key arguments exist only on an engine with the
188
+ * discount-reason layer, so on an older one these calls alone fail validation.
189
+ */
190
+ export declare const APPLY_ORDER_LINE_PRICE_OVERRIDES_MUTATION = "\n mutation ApplyOrderLinePriceOverrides(\n $orderId: ID!\n $lines: [OrderLinePriceOverrideInput!]!\n $reasonCode: String\n $idempotencyKey: String\n ) {\n applyOrderLinePriceOverrides(\n orderId: $orderId\n lines: $lines\n reasonCode: $reasonCode\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n state\n currencyCode\n couponCodes\n subTotal\n subTotalWithTax\n shipping\n shippingWithTax\n total\n totalWithTax\n discounts { promotionId adjustmentSource type description amount amountWithTax }\n promotions { id name }\n lines {\n id\n quantity\n productVariant { id sku name }\n unitPrice\n unitPriceWithTax\n linePrice\n linePriceWithTax\n discountedLinePrice\n discountedLinePriceWithTax\n proratedLinePrice\n proratedLinePriceWithTax\n discounts { promotionId adjustmentSource type description amount amountWithTax }\n }\n surcharges { id description sku price priceWithTax }\n packages { promotionId label price priceWithTax lineIds quantity }\n\n }\n }\n";
191
+ export declare const SET_ORDER_PRICE_LIST_DISCOUNTS_MUTATION = "\n mutation SetOrderPriceListDiscounts(\n $input: SetOrderPriceListDiscountsInput!\n $idempotencyKey: String\n ) {\n setOrderPriceListDiscounts(input: $input, idempotencyKey: $idempotencyKey) {\n \n id\n code\n state\n currencyCode\n couponCodes\n subTotal\n subTotalWithTax\n shipping\n shippingWithTax\n total\n totalWithTax\n discounts { promotionId adjustmentSource type description amount amountWithTax }\n promotions { id name }\n lines {\n id\n quantity\n productVariant { id sku name }\n unitPrice\n unitPriceWithTax\n linePrice\n linePriceWithTax\n discountedLinePrice\n discountedLinePriceWithTax\n proratedLinePrice\n proratedLinePriceWithTax\n discounts { promotionId adjustmentSource type description amount amountWithTax }\n }\n surcharges { id description sku price priceWithTax }\n packages { promotionId label price priceWithTax lineIds quantity }\n\n }\n }\n";
192
+ export declare function createOrderManualPricingModule(transport: Transport): OrderManualPricingModule;
@@ -0,0 +1,72 @@
1
+ import { ORDER_DISCOUNTS_FIELDS } from '../pricing/index.js';
2
+ /**
3
+ * Each door its own document: the reason and key arguments exist only on an engine with the
4
+ * discount-reason layer, so on an older one these calls alone fail validation.
5
+ */
6
+ export const APPLY_ORDER_LINE_PRICE_OVERRIDES_MUTATION = /* GraphQL */ `
7
+ mutation ApplyOrderLinePriceOverrides(
8
+ $orderId: ID!
9
+ $lines: [OrderLinePriceOverrideInput!]!
10
+ $reasonCode: String
11
+ $idempotencyKey: String
12
+ ) {
13
+ applyOrderLinePriceOverrides(
14
+ orderId: $orderId
15
+ lines: $lines
16
+ reasonCode: $reasonCode
17
+ idempotencyKey: $idempotencyKey
18
+ ) {
19
+ ${ORDER_DISCOUNTS_FIELDS}
20
+ }
21
+ }
22
+ `;
23
+ export const SET_ORDER_PRICE_LIST_DISCOUNTS_MUTATION = /* GraphQL */ `
24
+ mutation SetOrderPriceListDiscounts(
25
+ $input: SetOrderPriceListDiscountsInput!
26
+ $idempotencyKey: String
27
+ ) {
28
+ setOrderPriceListDiscounts(input: $input, idempotencyKey: $idempotencyKey) {
29
+ ${ORDER_DISCOUNTS_FIELDS}
30
+ }
31
+ }
32
+ `;
33
+ export function createOrderManualPricingModule(transport) {
34
+ return {
35
+ async setLinePrices(orderId, input, options) {
36
+ const data = await transport.graphql({
37
+ api: 'admin',
38
+ query: APPLY_ORDER_LINE_PRICE_OVERRIDES_MUTATION,
39
+ // The lines go out as given, never normalised: a `unitPriceOverride` left out keeps the
40
+ // stored price and `null` clears it. `JSON.stringify` drops a key that is `undefined`
41
+ // and keeps a `null`, so a default here would turn "keep" into "clear". The same holds
42
+ // for the reason code and the key: absent, they never reach the wire as null.
43
+ variables: {
44
+ orderId,
45
+ lines: input.lines,
46
+ reasonCode: input.reasonCode,
47
+ idempotencyKey: options?.idempotencyKey,
48
+ },
49
+ }, options);
50
+ return data.applyOrderLinePriceOverrides;
51
+ },
52
+ async setOneTimeDiscounts(orderId, input, options) {
53
+ const data = await transport.graphql({
54
+ api: 'admin',
55
+ query: SET_ORDER_PRICE_LIST_DISCOUNTS_MUTATION,
56
+ variables: {
57
+ input: {
58
+ orderId,
59
+ // The engine reads a missing whole-order discount as none, so the request states it:
60
+ // the wire then carries the whole desired state, `null` included.
61
+ orderDiscount: input.orderDiscount ?? null,
62
+ lines: input.lines,
63
+ reason: input.reason,
64
+ reasonCode: input.reasonCode,
65
+ },
66
+ idempotencyKey: options?.idempotencyKey,
67
+ },
68
+ }, options);
69
+ return data.setOrderPriceListDiscounts;
70
+ },
71
+ };
72
+ }