@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
@@ -0,0 +1,205 @@
1
+ import { createPage } from '@sixtyninecommerce/core';
2
+ const REGISTER_FIELDS = 'id stockLocationId name status createdAt updatedAt';
3
+ const TOTALS = 'cash card other refunds net saleCount';
4
+ const SESSION_FIELDS = `id registerId deviceId openedByStaffId openingFloat status expectedCash countedCash cashOverShort totals openedAt closedAt`;
5
+ const CART_FIELDS = `id code state currencyCode total totalWithTax couponCodes
6
+ lines { id quantity productVariant { id } linePriceWithTax }
7
+ surcharges { description sku price priceWithTax taxRate }`;
8
+ const TENDER_FIELDS = 'orderId paymentId covered outstanding change';
9
+ const DEVICE_FIELDS = 'id stockLocationId registerId label status paired lastSeenAt';
10
+ export const POS_REGISTERS_QUERY = `query PosRegisters { posRegisters { ${REGISTER_FIELDS} } }`;
11
+ export const POS_REGISTER_QUERY = `query PosRegister($id: ID!) { posRegister(id: $id) { ${REGISTER_FIELDS} } }`;
12
+ export const CREATE_POS_REGISTER_MUTATION = `mutation CreatePosRegister($input: CreatePosRegisterInput!) { createPosRegister(input: $input) { ${REGISTER_FIELDS} } }`;
13
+ export const UPDATE_POS_REGISTER_MUTATION = `mutation UpdatePosRegister($id: ID!, $input: UpdatePosRegisterInput!) { updatePosRegister(id: $id, input: $input) { ${REGISTER_FIELDS} } }`;
14
+ export const OPEN_POS_SESSION_MUTATION = `mutation OpenPosRegisterSession($input: OpenPosRegisterSessionInput!, $staffToken: String) { openPosRegisterSession(input: $input, staffToken: $staffToken) { ${SESSION_FIELDS} } }`;
15
+ export const CLOSE_POS_SESSION_MUTATION = `mutation ClosePosRegisterSession($input: ClosePosRegisterSessionInput!, $staffToken: String) { closePosRegisterSession(input: $input, staffToken: $staffToken) { ${SESSION_FIELDS} } }`;
16
+ export const POS_X_REPORT_QUERY = `query PosXReport($sessionId: ID!) { posXReport(sessionId: $sessionId) { sessionId openingFloat expectedCash movementCount totals { ${TOTALS} } } }`;
17
+ export const POS_SESSION_QUERY = `query PosRegisterSession($id: ID!) { posRegisterSession(id: $id) { ${SESSION_FIELDS} } }`;
18
+ export const RECORD_POS_CASH_MOVEMENT_MUTATION = `mutation RecordPosCashMovement($input: RecordPosCashMovementInput!, $staffToken: String) { recordPosCashMovement(input: $input, staffToken: $staffToken) { id sessionId type amount reason orderId createdAt } }`;
19
+ export const POS_CREATE_CART_MUTATION = `mutation PosCreateCart($registerId: ID) { posCreateCart(registerId: $registerId) { ${CART_FIELDS} } }`;
20
+ export const POS_ADD_ITEM_MUTATION = `mutation PosAddItem($input: PosAddItemInput!) { posAddItem(input: $input) { ${CART_FIELDS} } }`;
21
+ export const POS_APPLY_DISCOUNT_MUTATION = `mutation PosApplyDiscount($input: PosApplyDiscountInput!, $staffToken: String) { posApplyDiscount(input: $input, staffToken: $staffToken) { ${CART_FIELDS} } }`;
22
+ export const POS_APPLY_COUPON_CODE_MUTATION = `mutation PosApplyCouponCode($input: PosCouponCodeInput!) { posApplyCouponCode(input: $input) { ${CART_FIELDS} } }`;
23
+ export const POS_REMOVE_COUPON_CODE_MUTATION = `mutation PosRemoveCouponCode($input: PosCouponCodeInput!) { posRemoveCouponCode(input: $input) { ${CART_FIELDS} } }`;
24
+ export const POS_COMPLETE_SALE_MUTATION = `mutation PosCompleteSale($input: PosCompleteSaleInput!, $staffToken: String) { posCompleteSale(input: $input, staffToken: $staffToken) { orderId orderCode receiptNumber state } }`;
25
+ export const POS_TENDER_CASH_MUTATION = `mutation PosTenderCash($input: PosTenderCashInput!, $staffToken: String) { posTenderCash(input: $input, staffToken: $staffToken) { ${TENDER_FIELDS} } }`;
26
+ export const POS_TENDER_CARD_MUTATION = `mutation PosTenderCard($input: PosTenderCardInput!, $staffToken: String) { posTenderCard(input: $input, staffToken: $staffToken) { ${TENDER_FIELDS} } }`;
27
+ export const POS_TENDER_STORED_VALUE_MUTATION = `mutation PosTenderStoredValue($input: PosTenderStoredValueInput!, $staffToken: String) { posTenderStoredValue(input: $input, staffToken: $staffToken) { ${TENDER_FIELDS} } }`;
28
+ export const POS_TENDER_MANUAL_MUTATION = `mutation PosTenderManual($input: PosTenderManualInput!, $staffToken: String) { posTenderManual(input: $input, staffToken: $staffToken) { ${TENDER_FIELDS} } }`;
29
+ export const POS_REFUND_MUTATION = `mutation PosRefund($input: PosRefundInput!, $staffToken: String) { posRefund(input: $input, staffToken: $staffToken) { orderId refundId state } }`;
30
+ export const POS_DEVICES_QUERY = `query PosDevices { posDevices { ${DEVICE_FIELDS} } }`;
31
+ export const POS_DEVICE_QUERY = `query PosDevice($id: ID!) { posDevice(id: $id) { lastSeenAt } }`;
32
+ export const POS_PAIRING_CODE_MUTATION = `mutation GeneratePosPairingCode($deviceId: ID!) { generatePosPairingCode(deviceId: $deviceId) { code expiresAt } }`;
33
+ export const REVOKE_POS_DEVICE_MUTATION = `mutation RevokePosDevice($deviceId: ID!) { revokePosDevice(deviceId: $deviceId) { ${DEVICE_FIELDS} } }`;
34
+ export const POS_RECEIPT_NUMBERING_QUERY = `query PosReceiptNumberingConfig { posReceiptNumberingConfig { prefix suffix digits } }`;
35
+ export const UPDATE_POS_RECEIPT_NUMBERING_MUTATION = `mutation UpdatePosReceiptNumberingConfig($input: UpdatePosReceiptNumberingConfigInput!) { updatePosReceiptNumberingConfig(input: $input) { prefix suffix digits } }`;
36
+ function toCart(raw) {
37
+ return {
38
+ ...raw,
39
+ lines: raw.lines.map((line) => ({
40
+ id: line.id,
41
+ quantity: line.quantity,
42
+ productVariantId: line.productVariant.id,
43
+ linePriceWithTax: line.linePriceWithTax,
44
+ })),
45
+ };
46
+ }
47
+ /**
48
+ * The wire answers `""` rather than null for a session a machine principal
49
+ * opened (the fields shipped `ID!`, and relaxing an output field breaks older
50
+ * consumers); this module's type says what that means.
51
+ */
52
+ function toSession(raw) {
53
+ return { ...raw, deviceId: raw.deviceId || null, openedByStaffId: raw.openedByStaffId || null };
54
+ }
55
+ function wholeList(items) {
56
+ return createPage(items, { nextCursor: null, hasNext: false, total: items.length }, () => {
57
+ throw new Error('this list is returned whole; there is no next page');
58
+ });
59
+ }
60
+ /**
61
+ * The key is a REQUIRED `String!` on the server; an empty one would be a
62
+ * GraphQL validation error that names no field a caller recognises, so it is
63
+ * refused here with the name of the option that was missing.
64
+ */
65
+ function requireKey(options) {
66
+ const key = options?.idempotencyKey;
67
+ if (typeof key !== 'string' || key.trim() === '') {
68
+ throw new TypeError('A POS money call needs options.idempotencyKey (a fresh UUIDv7 per operation).');
69
+ }
70
+ return key;
71
+ }
72
+ export function createPosModule(transport) {
73
+ const gql = async (query, variables, options) => transport.graphql({ api: 'admin', query, variables }, options);
74
+ return {
75
+ registers: {
76
+ async list(options) {
77
+ const data = await gql(POS_REGISTERS_QUERY, {}, options);
78
+ return wholeList(data.posRegisters);
79
+ },
80
+ async get(id, options) {
81
+ const data = await gql(POS_REGISTER_QUERY, { id }, options);
82
+ return data.posRegister;
83
+ },
84
+ async create(input, options) {
85
+ const data = await gql(CREATE_POS_REGISTER_MUTATION, { input }, options);
86
+ return data.createPosRegister;
87
+ },
88
+ async update(id, input, options) {
89
+ const data = await gql(UPDATE_POS_REGISTER_MUTATION, { id, input }, options);
90
+ return data.updatePosRegister;
91
+ },
92
+ },
93
+ sessions: {
94
+ async open(input, options) {
95
+ const data = await gql(OPEN_POS_SESSION_MUTATION, { input, staffToken: options?.staffToken }, options);
96
+ return toSession(data.openPosRegisterSession);
97
+ },
98
+ async close(input, options) {
99
+ const data = await gql(CLOSE_POS_SESSION_MUTATION, { input, staffToken: options?.staffToken }, options);
100
+ return toSession(data.closePosRegisterSession);
101
+ },
102
+ async xReport(sessionId, options) {
103
+ const data = await gql(POS_X_REPORT_QUERY, { sessionId }, options);
104
+ return data.posXReport;
105
+ },
106
+ async zReport(sessionId, options) {
107
+ const data = await gql(POS_SESSION_QUERY, { id: sessionId }, options);
108
+ return data.posRegisterSession && toSession(data.posRegisterSession);
109
+ },
110
+ },
111
+ cash: {
112
+ async record(input, options) {
113
+ const data = await gql(RECORD_POS_CASH_MOVEMENT_MUTATION, { input, staffToken: options?.staffToken }, options);
114
+ return data.recordPosCashMovement;
115
+ },
116
+ },
117
+ sale: {
118
+ async createCart(input, options) {
119
+ const data = await gql(POS_CREATE_CART_MUTATION, { registerId: input?.registerId }, options);
120
+ return toCart(data.posCreateCart);
121
+ },
122
+ async addItem(input, options) {
123
+ const data = await gql(POS_ADD_ITEM_MUTATION, { input }, options);
124
+ return toCart(data.posAddItem);
125
+ },
126
+ async applyDiscount(input, options) {
127
+ const data = await gql(POS_APPLY_DISCOUNT_MUTATION, {
128
+ input: { ...input, idempotencyKey: options?.idempotencyKey },
129
+ staffToken: options?.staffToken,
130
+ }, options);
131
+ return toCart(data.posApplyDiscount);
132
+ },
133
+ async applyCouponCode(input, options) {
134
+ const data = await gql(POS_APPLY_COUPON_CODE_MUTATION, { input: { ...input, idempotencyKey: options?.idempotencyKey } }, options);
135
+ return toCart(data.posApplyCouponCode);
136
+ },
137
+ async removeCouponCode(input, options) {
138
+ const data = await gql(POS_REMOVE_COUPON_CODE_MUTATION, { input: { ...input, idempotencyKey: options?.idempotencyKey } }, options);
139
+ return toCart(data.posRemoveCouponCode);
140
+ },
141
+ async complete(orderId, options) {
142
+ const idempotencyKey = requireKey(options);
143
+ const data = await gql(POS_COMPLETE_SALE_MUTATION, { input: { orderId, idempotencyKey }, staffToken: options.staffToken }, options);
144
+ return data.posCompleteSale;
145
+ },
146
+ },
147
+ tenders: {
148
+ async cash(input, options) {
149
+ const idempotencyKey = requireKey(options);
150
+ const data = await gql(POS_TENDER_CASH_MUTATION, { input: { ...input, idempotencyKey }, staffToken: options.staffToken }, options);
151
+ return data.posTenderCash;
152
+ },
153
+ async card(input, options) {
154
+ const idempotencyKey = requireKey(options);
155
+ const data = await gql(POS_TENDER_CARD_MUTATION, { input: { ...input, idempotencyKey }, staffToken: options.staffToken }, options);
156
+ return data.posTenderCard;
157
+ },
158
+ async manual(input, options) {
159
+ const idempotencyKey = requireKey(options);
160
+ const data = await gql(POS_TENDER_MANUAL_MUTATION, { input: { ...input, idempotencyKey }, staffToken: options.staffToken }, options);
161
+ return data.posTenderManual;
162
+ },
163
+ async storedValue(input, options) {
164
+ const idempotencyKey = requireKey(options);
165
+ const data = await gql(POS_TENDER_STORED_VALUE_MUTATION, { input: { ...input, idempotencyKey }, staffToken: options.staffToken }, options);
166
+ return data.posTenderStoredValue;
167
+ },
168
+ },
169
+ refunds: {
170
+ async create(input, options) {
171
+ const idempotencyKey = requireKey(options);
172
+ const data = await gql(POS_REFUND_MUTATION, { input: { ...input, idempotencyKey }, staffToken: options.staffToken }, options);
173
+ return data.posRefund;
174
+ },
175
+ },
176
+ devices: {
177
+ async list(options) {
178
+ const data = await gql(POS_DEVICES_QUERY, {}, options);
179
+ return wholeList(data.posDevices);
180
+ },
181
+ async pair(deviceId, options) {
182
+ const data = await gql(POS_PAIRING_CODE_MUTATION, { deviceId }, options);
183
+ return data.generatePosPairingCode;
184
+ },
185
+ async revoke(deviceId, options) {
186
+ const data = await gql(REVOKE_POS_DEVICE_MUTATION, { deviceId }, options);
187
+ return data.revokePosDevice;
188
+ },
189
+ async heartbeat(deviceId, options) {
190
+ const data = await gql(POS_DEVICE_QUERY, { id: deviceId }, options);
191
+ return data.posDevice;
192
+ },
193
+ },
194
+ receiptNumbering: {
195
+ async get(options) {
196
+ const data = await gql(POS_RECEIPT_NUMBERING_QUERY, {}, options);
197
+ return data.posReceiptNumberingConfig;
198
+ },
199
+ async set(input, options) {
200
+ const data = await gql(UPDATE_POS_RECEIPT_NUMBERING_MUTATION, { input }, options);
201
+ return data.updatePosReceiptNumberingConfig;
202
+ },
203
+ },
204
+ };
205
+ }
@@ -0,0 +1,405 @@
1
+ import { type Page, type Transport } from '@sixtyninecommerce/core';
2
+ import type { ConfigurableOperation, ConfigurableOperationInput, LanguageCode } from '../catalog/types.js';
3
+ import type { Call } from '../types.js';
4
+ /**
5
+ * Promotions at the register (headless spec §9.2 `pricing`; incentives spec §5,
6
+ * sprint 1): which promotions a register can offer, coupons on the order it is
7
+ * entering, and what each discount did to each line.
8
+ *
9
+ * Money is integer MINOR UNITS of the order's currency; times are ISO-8601 UTC.
10
+ *
11
+ * **Coded refusals** of the coupon methods, delivered as GraphQL errors with
12
+ * `extensions.code` (`BusinessRuleError`, 422, unless noted). Branch on the
13
+ * code, never on the class:
14
+ * - `COUPON_INVALID` (`ValidationError`, 400, by its `_INVALID` suffix) — no
15
+ * coupon of this store carries the code: unknown, mistyped, deactivated, its
16
+ * promotion disabled, or another store's code (the same answer, so no store
17
+ * learns of another's codes);
18
+ * - `COUPON_EXPIRED` — its promotion has ended;
19
+ * - `COUPON_NOT_YET_VALID` — its promotion has not started;
20
+ * - `COUPON_USAGE_EXHAUSTED` — used up: the promotion's limit, its per-customer
21
+ * limit for the order's customer, or a unique code's own limits
22
+ * (`extensions.details.limit`);
23
+ * - `COUPON_NOT_APPLICABLE` — valid, but its promotion does not apply to the
24
+ * order as it stands (a condition is not met, or the promotion is already on
25
+ * the order through another of its unique codes);
26
+ * - `EXTERNAL_LINE_PROMOTION_UNSUPPORTED` — it would discount a line whose price
27
+ * the caller stated (`orders.createOrRecover` external lines);
28
+ * - `ORDER_NOT_DRAFT` — the order is not a Draft; change a placed order through
29
+ * an order modification.
30
+ * A refused call leaves the order unchanged. Another store's order is
31
+ * `ENTITY_NOT_FOUND` (`NotFoundError`), as one that does not exist.
32
+ */
33
+ export interface PricingModule {
34
+ promotions: PricingPromotionsModule;
35
+ coupons: PricingCouponsModule;
36
+ /**
37
+ * The order's discounts as they stand: its coupon codes, the order-level
38
+ * discounts, and each line's discounts, every one naming the promotion it came
39
+ * from. Needs `ReadOrder`. `NotFoundError` (`ORDER_NOT_FOUND`) when this store
40
+ * has no such order.
41
+ */
42
+ discounts(orderId: string, options?: Call): Promise<OrderDiscounts>;
43
+ }
44
+ export interface PricingPromotionsModule {
45
+ /**
46
+ * The store's promotions that can apply right now: enabled, inside their date
47
+ * window, not used up, and — with `customerId` — open to that customer (a
48
+ * customer-group condition naming a group they are in). With no customer a
49
+ * customer-group promotion is left out: an anonymous sale is in no group.
50
+ * Conditions on the basket (amounts, products, the payment method) are not
51
+ * judged here, they are summarised. Ordered as the engine applies them.
52
+ *
53
+ * The targeting conditions are judged for a sale here and now:
54
+ * `selling_location` against `locationId`, else the request's `x-location`
55
+ * (with neither, such a promotion is left out); `time_window` on that
56
+ * location's clock, else the store's; `first_order` for `customerId` (left out
57
+ * without one, and for the till's walk-in). `locationId` must be a stock
58
+ * location of this store that the credential may act at
59
+ * (`LOCATION_NOT_IN_CHANNEL` / `LOCATION_NOT_ALLOWED`).
60
+ *
61
+ * Needs `ReadPromotion`, `CreateOrder` or `OperatePos`. A `Page` because every
62
+ * list in this SDK is one; the engine answers the whole list, so it is always
63
+ * the last page.
64
+ */
65
+ active(filter?: ActivePromotionsFilter, options?: Call): Promise<Page<ActivePromotion>>;
66
+ /**
67
+ * Create a promotion of this store. Build targeting conditions with
68
+ * {@link promotionConditions}; core's conditions and actions take their
69
+ * `ConfigurableOperationInput` as stored. The stacking guard the dashboard
70
+ * puts on every promotion it saves (`promotion_stacking_guard`) is added when
71
+ * the input does not carry it, so a promotion made here stacks like one made
72
+ * there. Needs `CreatePromotion`.
73
+ *
74
+ * **An empty `conditions` list creates a promotion that applies to every
75
+ * order** (with no coupon code: automatically), exactly as the dashboard's "No
76
+ * conditions means the promotion applies to all orders". The guard counts as
77
+ * a condition, so core's "no condition and no coupon code" refusal never
78
+ * fires for a promotion saved here: build at least one condition, or set
79
+ * `couponCode` or `enabled: false`, unless a store-wide promotion is meant.
80
+ *
81
+ * Refusals: `PROMOTION_CONDITION_INVALID` (`ValidationError`, 400: a
82
+ * targeting or set argument the engine cannot read, a second set condition or
83
+ * a set action without its condition (`argument: "conditions"`), or a set
84
+ * condition without its action or a second copy of a set action
85
+ * (`argument: "actions"`), judged on `update` for the pair the update leaves; `extensions.details` names the condition and
86
+ * argument), `LOCATION_NOT_IN_CHANNEL` (a location of another store, or not
87
+ * an id), `LOCATION_NOT_ALLOWED` (outside the credential's location
88
+ * restriction), `FACET_VALUE_NOT_FOUND` / `COLLECTION_NOT_FOUND`
89
+ * (`NotFoundError`, 404: a set component names a facet value or collection
90
+ * this store does not have; another store's answers the same).
91
+ */
92
+ create(input: CreatePromotionInput, options?: Call): Promise<PricingPromotion>;
93
+ /**
94
+ * Update a promotion of this store. `conditions` and `actions`, when sent,
95
+ * replace the whole list (the guard is kept as on create). Needs
96
+ * `UpdatePromotion`.
97
+ *
98
+ * Refusals: those of {@link PricingPromotionsModule.create}, and
99
+ * `MISSING_CONDITIONS_ERROR` (`BusinessRuleError`, 422) for one case: the input
100
+ * does not name `conditions`, the STORED promotion has none (an imported
101
+ * coupon, a seed: no guard was ever added), and the result would have no coupon
102
+ * code (`couponCode: ''` clears it, or none is stored). Core judges omitted
103
+ * conditions from the stored ones, and the guard is added only to conditions
104
+ * the input sends: send `conditions` (even `[]`) to keep such a promotion
105
+ * without a code.
106
+ */
107
+ update(input: UpdatePromotionInput, options?: Call): Promise<PricingPromotion>;
108
+ }
109
+ /** A day of the week as the `time_window` condition stores it (Monday first). */
110
+ export type Weekday = 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun';
111
+ /** `HH:mm`, 24-hour, local time. */
112
+ export type LocalTime = `${number}${number}:${number}${number}`;
113
+ /**
114
+ * The targeting conditions (incentives sprint 2), encoded as the engine stores
115
+ * them — every argument a string, lists JSON-encoded. Their argument names and
116
+ * shapes are a stored contract.
117
+ */
118
+ export declare const promotionConditions: {
119
+ /**
120
+ * `selling_location`: the order is sold from one of these stock locations of
121
+ * the store — a till there, an order `orders.createOrRecover` recorded for it
122
+ * (`location`), or a register sending it as `x-location` on the Admin API. A
123
+ * web order has no location and never matches.
124
+ */
125
+ readonly sellingLocation: (locationIds: readonly string[]) => ConfigurableOperationInput;
126
+ /**
127
+ * `time_window`: on one of `days`, from `from` (included) to `until`
128
+ * (excluded), local time — the selling location's profile zone, else the
129
+ * store's. An `until` not after `from` runs into the next day and belongs to
130
+ * the day it opened (`fri 22:00–02:00`); equal times are 24 hours
131
+ * (`00:00`–`00:00`: all day). Judged on the wall clock, so a window in the
132
+ * hour clocks repeat in autumn is open twice, one in the hour they skip in
133
+ * spring never opens. A placed order keeps a window it was placed with.
134
+ */
135
+ readonly timeWindow: (window: {
136
+ days: readonly Weekday[];
137
+ from: LocalTime | string;
138
+ until: LocalTime | string;
139
+ }) => ConfigurableOperationInput;
140
+ /**
141
+ * `first_order`: the customer has no earlier placed order in this store. An
142
+ * order with no customer, or the till's walk-in, never matches.
143
+ */
144
+ readonly firstOrder: () => ConfigurableOperationInput;
145
+ /**
146
+ * `bundle_fixed_price` (incentives sprint 4): each complete set of
147
+ * `components` costs `price` — minor units of the store's DEFAULT currency, in
148
+ * the store's tax basis (as its catalogue prices are entered), converted into
149
+ * an order's currency at the checkout's rate. The discount is spread over the
150
+ * set's lines by value; a set worth `price` or less stays at list price. Pair
151
+ * it with {@link promotionActions}`.bundleFixedPrice()`.
152
+ *
153
+ * `price` is required and must be a whole amount above 0: anything else throws
154
+ * `ValidationError` (`PROMOTION_CONDITION_INVALID`) before a request is sent,
155
+ * as the engine would refuse it. To give sets away use
156
+ * {@link promotionConditions}`.nthSetPercentage` with `discount: 100`.
157
+ */
158
+ readonly bundleFixedPrice: (set: {
159
+ components: readonly SetComponent[];
160
+ price: number;
161
+ }) => ConfigurableOperationInput;
162
+ /**
163
+ * `nth_set_percentage`: of every `nth` complete sets, the cheapest is
164
+ * `discount`% off ("second pair at 50%" is `nth: 2, discount: 50`; `nth: 1`
165
+ * discounts every set). Pair it with {@link promotionActions}`.nthSetPercentage()`.
166
+ */
167
+ readonly nthSetPercentage: (set: {
168
+ components: readonly SetComponent[];
169
+ nth: number;
170
+ discount: number;
171
+ }) => ConfigurableOperationInput;
172
+ /**
173
+ * `mix_and_match`: any `quantity` units matching the selector (all of
174
+ * `facetValueIds`, any of `collectionIds`) for `price`, per complete group;
175
+ * leftover units stay at list price. `price` as in `bundleFixedPrice`
176
+ * (required, above 0, refused before sending otherwise). Pair it with
177
+ * {@link promotionActions}`.mixAndMatch()`.
178
+ */
179
+ readonly mixAndMatch: (group: {
180
+ facetValueIds?: readonly string[];
181
+ collectionIds?: readonly string[];
182
+ quantity: number;
183
+ price: number;
184
+ }) => ConfigurableOperationInput;
185
+ };
186
+ /**
187
+ * One component of a set: `quantity` units, each carrying ALL of
188
+ * `facetValueIds` and sitting in ANY of `collectionIds` (at least one of the
189
+ * two lists). A unit that a caller priced (an external, imported, quoted or
190
+ * till-priced line) or that staff priced by hand never joins a set.
191
+ */
192
+ export interface SetComponent {
193
+ facetValueIds?: readonly string[];
194
+ collectionIds?: readonly string[];
195
+ quantity: number;
196
+ }
197
+ /**
198
+ * The set actions (incentives sprint 4). Each takes no arguments and applies
199
+ * what its same-code condition computed, so it goes on the promotion together
200
+ * with that condition: the engine refuses one without the other.
201
+ */
202
+ export declare const promotionActions: {
203
+ readonly bundleFixedPrice: () => ConfigurableOperationInput;
204
+ readonly nthSetPercentage: () => ConfigurableOperationInput;
205
+ readonly mixAndMatch: () => ConfigurableOperationInput;
206
+ };
207
+ export interface PromotionTranslationInput {
208
+ languageCode: LanguageCode;
209
+ name: string;
210
+ description?: string;
211
+ }
212
+ export interface CreatePromotionInput {
213
+ translations: PromotionTranslationInput[];
214
+ enabled: boolean;
215
+ /** ISO-8601; null or absent for an open end. */
216
+ startsAt?: string | null;
217
+ endsAt?: string | null;
218
+ couponCode?: string | null;
219
+ perCustomerUsageLimit?: number | null;
220
+ usageLimit?: number | null;
221
+ conditions: ConfigurableOperationInput[];
222
+ actions: ConfigurableOperationInput[];
223
+ /** Applies to customers on a price list too (the stacking guard's B2B rule). */
224
+ combineWithB2b?: boolean;
225
+ /** Stacks with other promotions instead of taking the exclusive slot. */
226
+ combineWithOtherPromotions?: boolean;
227
+ /** Higher is tested first and wins the exclusive slot. */
228
+ priority?: number;
229
+ }
230
+ export interface UpdatePromotionInput extends Partial<Omit<CreatePromotionInput, 'translations'>> {
231
+ id: string;
232
+ translations?: Array<PromotionTranslationInput & {
233
+ id?: string;
234
+ }>;
235
+ }
236
+ /** A promotion as `create` / `update` answer it. The coupon code is the caller's own input. */
237
+ export interface PricingPromotion {
238
+ id: string;
239
+ name: string;
240
+ description: string;
241
+ enabled: boolean;
242
+ couponCode: string | null;
243
+ startsAt: string | null;
244
+ endsAt: string | null;
245
+ usageLimit: number | null;
246
+ perCustomerUsageLimit: number | null;
247
+ conditions: ConfigurableOperation[];
248
+ actions: ConfigurableOperation[];
249
+ customFields: {
250
+ combineWithB2b: boolean | null;
251
+ combineWithOtherPromotions: boolean | null;
252
+ priority: number | null;
253
+ };
254
+ }
255
+ export interface PricingCouponsModule {
256
+ /**
257
+ * Apply a coupon code — a promotion's own code or a unique code generated for
258
+ * it — to a DRAFT order of this store: a back-office draft, or an order
259
+ * `orders.createOrRecover` composed and left as a Draft. Answers the re-priced
260
+ * order. Surcharges are left as they are. A code already on the order answers
261
+ * the order unchanged. Needs `CreateOrder`.
262
+ *
263
+ * Takes `options.idempotencyKey`: the same key with the same arguments replays
264
+ * the first answer, a refusal included; a different request under the same key
265
+ * is `IDEMPOTENCY_CONFLICT`. A till cart takes its coupons through
266
+ * `pos.sale.applyCouponCode`.
267
+ */
268
+ apply(orderId: string, couponCode: string, options?: Call): Promise<OrderDiscounts>;
269
+ /**
270
+ * Take a coupon code off a DRAFT order of this store — the code as applied (a
271
+ * unique code frees its use) or as `couponCodes` shows it. A code that is not
272
+ * on the order answers the order unchanged. Needs `CreateOrder`; takes
273
+ * `options.idempotencyKey` as {@link PricingCouponsModule.apply} does.
274
+ */
275
+ remove(orderId: string, couponCode: string, options?: Call): Promise<OrderDiscounts>;
276
+ }
277
+ export interface ActivePromotionsFilter {
278
+ locationId?: string;
279
+ customerId?: string;
280
+ }
281
+ /** A promotion's stored condition or action, and the sentence its definition makes of it. */
282
+ export interface PromotionOperationSummary {
283
+ code: string;
284
+ args: Array<{
285
+ name: string;
286
+ value: string;
287
+ }>;
288
+ /**
289
+ * The registered definition's description with the stored values filled in,
290
+ * in the request's language — `"If order total is greater than 50.00 EUR"`.
291
+ * Money reads in the store's default currency; a list argument as a count.
292
+ */
293
+ summary: string;
294
+ }
295
+ export interface ActivePromotion {
296
+ id: string;
297
+ name: string;
298
+ description: string;
299
+ startsAt: string | null;
300
+ endsAt: string | null;
301
+ /** Whether a coupon code must be applied for it to count. The code itself is never answered. */
302
+ requiresCouponCode: boolean;
303
+ usageLimit: number | null;
304
+ perCustomerUsageLimit: number | null;
305
+ conditions: PromotionOperationSummary[];
306
+ actions: PromotionOperationSummary[];
307
+ /** Conditions joined with "and", then what it gives. */
308
+ summary: string;
309
+ }
310
+ /** One discount, on the order or on a line. Amounts are negative minor units. */
311
+ export interface OrderDiscount {
312
+ /** The promotion it came from; null for a discount from anything else. */
313
+ promotionId: string | null;
314
+ /** `PROMOTION:<id>` for a promotion. */
315
+ adjustmentSource: string;
316
+ /** `PROMOTION` or `DISTRIBUTED_ORDER_PROMOTION` (an order-level discount's share of a line). */
317
+ type: string;
318
+ description: string;
319
+ amount: number;
320
+ amountWithTax: number;
321
+ }
322
+ export interface DiscountedOrderLine {
323
+ id: string;
324
+ quantity: number;
325
+ productVariant: {
326
+ id: string;
327
+ sku: string;
328
+ name: string;
329
+ };
330
+ unitPrice: number;
331
+ unitPriceWithTax: number;
332
+ /** Before any discount. */
333
+ linePrice: number;
334
+ linePriceWithTax: number;
335
+ /** After the line's own promotions. */
336
+ discountedLinePrice: number;
337
+ discountedLinePriceWithTax: number;
338
+ /** After the line's own promotions AND its share of the order-level ones: what it costs. */
339
+ proratedLinePrice: number;
340
+ proratedLinePriceWithTax: number;
341
+ discounts: OrderDiscount[];
342
+ }
343
+ /**
344
+ * Lines a set promotion priced together (`bundle_fixed_price`,
345
+ * `nth_set_percentage`, `mix_and_match`), read from the order's own lines and
346
+ * discounts: a placed order keeps the packages it was priced with.
347
+ */
348
+ export interface OrderPackage {
349
+ promotionId: string;
350
+ /** The promotion's name, as the order recorded it when it was priced. */
351
+ label: string;
352
+ /** What the package's units cost after its discount, excluding tax. */
353
+ price: number;
354
+ priceWithTax: number;
355
+ /** In the order's line order; a line belongs to one package at most. */
356
+ lineIds: string[];
357
+ /** Complete sets (groups) in the package. */
358
+ quantity: number;
359
+ }
360
+ export interface OrderDiscounts {
361
+ id: string;
362
+ code: string;
363
+ state: string;
364
+ currencyCode: string;
365
+ /**
366
+ * The codes on the order. A unique code is redeemed by standing in for its
367
+ * promotion's own code, so it shows here as THAT code.
368
+ */
369
+ couponCodes: string[];
370
+ subTotal: number;
371
+ subTotalWithTax: number;
372
+ shipping: number;
373
+ shippingWithTax: number;
374
+ total: number;
375
+ totalWithTax: number;
376
+ /** The order's discounts, one per promotion (a line's share is on the line). */
377
+ discounts: OrderDiscount[];
378
+ /** The promotions that apply to the order now. */
379
+ promotions: Array<{
380
+ id: string;
381
+ name: string;
382
+ }>;
383
+ lines: DiscountedOrderLine[];
384
+ /** The sets its set promotions priced together; empty when none applies. */
385
+ packages: OrderPackage[];
386
+ /** Untouched by coupons; listed so a register can show the whole bill. */
387
+ surcharges: Array<{
388
+ id: string;
389
+ description: string;
390
+ sku: string | null;
391
+ price: number;
392
+ priceWithTax: number;
393
+ }>;
394
+ }
395
+ /** An order's pricing readout; the manual pricing doors (`orders.setLinePrices`, …) answer it too. */
396
+ export declare const ORDER_DISCOUNTS_FIELDS = "\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";
397
+ export declare const ACTIVE_PROMOTIONS_QUERY = "\n query ActivePromotions($locationId: ID, $customerId: ID) {\n activePromotions(locationId: $locationId, customerId: $customerId) {\n id\n name\n description\n startsAt\n endsAt\n requiresCouponCode\n usageLimit\n perCustomerUsageLimit\n conditions { code args { name value } summary }\n actions { code args { name value } summary }\n summary\n }\n }\n";
398
+ export declare const CREATE_PROMOTION_MUTATION = "\n mutation CreatePromotion($input: CreatePromotionInput!) {\n createPromotion(input: $input) {\n ... on Promotion { \n id\n name\n description\n enabled\n couponCode\n startsAt\n endsAt\n usageLimit\n perCustomerUsageLimit\n conditions { code args { name value } }\n actions { code args { name value } }\n customFields { combineWithB2b combineWithOtherPromotions priority }\n }\n ... on ErrorResult { errorCode message }\n }\n }\n";
399
+ export declare const UPDATE_PROMOTION_MUTATION = "\n mutation UpdatePromotion($input: UpdatePromotionInput!) {\n updatePromotion(input: $input) {\n ... on Promotion { \n id\n name\n description\n enabled\n couponCode\n startsAt\n endsAt\n usageLimit\n perCustomerUsageLimit\n conditions { code args { name value } }\n actions { code args { name value } }\n customFields { combineWithB2b combineWithOtherPromotions priority }\n }\n ... on ErrorResult { errorCode message }\n }\n }\n";
400
+ /** The condition the dashboard and the admin app put on every promotion they save. */
401
+ export declare const STACKING_GUARD_CONDITION = "promotion_stacking_guard";
402
+ export declare const APPLY_COUPON_CODE_TO_ORDER_MUTATION = "\n mutation ApplyCouponCodeToOrder($orderId: ID!, $couponCode: String!, $idempotencyKey: String) {\n applyCouponCodeToOrder(\n orderId: $orderId\n couponCode: $couponCode\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";
403
+ export declare const REMOVE_COUPON_CODE_FROM_ORDER_MUTATION = "\n mutation RemoveCouponCodeFromOrder($orderId: ID!, $couponCode: String!, $idempotencyKey: String) {\n removeCouponCodeFromOrder(\n orderId: $orderId\n couponCode: $couponCode\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";
404
+ export declare const ORDER_DISCOUNTS_QUERY = "\n query OrderDiscounts($id: ID!) {\n order(id: $id) {\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";
405
+ export declare function createPricingModule(transport: Transport): PricingModule;