@sixtyninecommerce/admin 0.10.0 → 0.12.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 (302) hide show
  1. package/README.md +5772 -118
  2. package/dist/auth/index.d.ts +7 -1
  3. package/dist/auth/index.js +8 -1
  4. package/dist/catalog/assets.d.ts +120 -8
  5. package/dist/catalog/assets.js +98 -12
  6. package/dist/catalog/collections.d.ts +279 -14
  7. package/dist/catalog/collections.js +246 -15
  8. package/dist/catalog/documents.d.ts +142 -0
  9. package/dist/catalog/documents.js +114 -0
  10. package/dist/catalog/index.d.ts +54 -6
  11. package/dist/catalog/index.js +10 -1
  12. package/dist/catalog/metadata.d.ts +244 -0
  13. package/dist/catalog/metadata.js +220 -0
  14. package/dist/catalog/products.d.ts +159 -19
  15. package/dist/catalog/products.js +88 -13
  16. package/dist/catalog/properties.d.ts +140 -14
  17. package/dist/catalog/properties.js +65 -1
  18. package/dist/catalog/recommendations.d.ts +288 -0
  19. package/dist/catalog/recommendations.js +237 -0
  20. package/dist/catalog/reviews.d.ts +381 -0
  21. package/dist/catalog/reviews.js +325 -0
  22. package/dist/catalog/types.d.ts +17 -1
  23. package/dist/catalog/types.js +10 -0
  24. package/dist/catalog/variant-find.d.ts +136 -0
  25. package/dist/catalog/variant-find.js +239 -0
  26. package/dist/catalog/variants.d.ts +293 -26
  27. package/dist/catalog/variants.js +164 -7
  28. package/dist/catalog/visibility.d.ts +38 -7
  29. package/dist/catalog/visibility.js +19 -1
  30. package/dist/client.d.ts +121 -9
  31. package/dist/client.js +53 -14
  32. package/dist/content/assets.d.ts +285 -0
  33. package/dist/content/assets.js +181 -0
  34. package/dist/content/forms.d.ts +332 -1
  35. package/dist/content/forms.js +140 -4
  36. package/dist/content/items.d.ts +292 -0
  37. package/dist/content/items.js +170 -0
  38. package/dist/content/menus.d.ts +254 -0
  39. package/dist/content/menus.js +70 -0
  40. package/dist/content/strings.d.ts +137 -0
  41. package/dist/content/strings.js +82 -0
  42. package/dist/content/types.d.ts +282 -0
  43. package/dist/content/types.js +100 -0
  44. package/dist/customers/age-verification.d.ts +66 -0
  45. package/dist/customers/age-verification.js +79 -0
  46. package/dist/customers/credit.d.ts +263 -0
  47. package/dist/customers/credit.js +244 -0
  48. package/dist/customers/delivery-preferences.d.ts +120 -0
  49. package/dist/customers/delivery-preferences.js +97 -0
  50. package/dist/customers/delivery-terms.d.ts +44 -0
  51. package/dist/customers/delivery-terms.js +32 -0
  52. package/dist/customers/groups.d.ts +207 -0
  53. package/dist/customers/groups.js +438 -0
  54. package/dist/customers/index.d.ts +462 -37
  55. package/dist/customers/index.js +317 -40
  56. package/dist/customers/invitation-status.d.ts +57 -0
  57. package/dist/customers/invitation-status.js +21 -0
  58. package/dist/customers/notes.d.ts +67 -0
  59. package/dist/customers/notes.js +51 -0
  60. package/dist/customers/notification-recipients.d.ts +97 -0
  61. package/dist/customers/notification-recipients.js +84 -0
  62. package/dist/customers/saved-lists.d.ts +42 -0
  63. package/dist/customers/saved-lists.js +61 -0
  64. package/dist/customers/vat.d.ts +83 -0
  65. package/dist/customers/vat.js +46 -0
  66. package/dist/customers/wire.d.ts +20 -0
  67. package/dist/customers/wire.js +35 -0
  68. package/dist/documents/ar.d.ts +307 -0
  69. package/dist/documents/ar.js +254 -0
  70. package/dist/documents/emails.d.ts +150 -0
  71. package/dist/documents/emails.js +220 -0
  72. package/dist/documents/index.d.ts +744 -21
  73. package/dist/documents/index.js +438 -24
  74. package/dist/documents/pdf.d.ts +2 -0
  75. package/dist/documents/pdf.js +11 -0
  76. package/dist/fulfillments/create.d.ts +167 -0
  77. package/dist/fulfillments/create.js +216 -0
  78. package/dist/fulfillments/index.d.ts +163 -11
  79. package/dist/fulfillments/index.js +135 -6
  80. package/dist/fulfillments/payment-policy.d.ts +64 -0
  81. package/dist/fulfillments/payment-policy.js +140 -0
  82. package/dist/fulfillments/warehouse.d.ts +724 -0
  83. package/dist/fulfillments/warehouse.js +914 -0
  84. package/dist/geo/index.d.ts +119 -0
  85. package/dist/geo/index.js +107 -0
  86. package/dist/index.d.ts +147 -39
  87. package/dist/index.js +51 -12
  88. package/dist/integrations/afas-actions.d.ts +234 -0
  89. package/dist/integrations/afas-actions.js +310 -0
  90. package/dist/integrations/afas-types.d.ts +483 -0
  91. package/dist/integrations/afas-types.js +5 -0
  92. package/dist/integrations/afas.d.ts +234 -0
  93. package/dist/integrations/afas.js +290 -0
  94. package/dist/integrations/connections.d.ts +103 -0
  95. package/dist/integrations/connections.js +55 -0
  96. package/dist/integrations/esp.d.ts +313 -0
  97. package/dist/integrations/esp.js +169 -0
  98. package/dist/integrations/exact-online-types.d.ts +965 -0
  99. package/dist/integrations/exact-online-types.js +6 -0
  100. package/dist/integrations/exact-online.d.ts +784 -0
  101. package/dist/integrations/exact-online.js +1089 -0
  102. package/dist/integrations/index.d.ts +44 -3
  103. package/dist/integrations/index.js +23 -3
  104. package/dist/integrations/pipeline-discoveries.d.ts +65 -0
  105. package/dist/integrations/pipeline-discoveries.js +65 -0
  106. package/dist/integrations/pipeline-keys.d.ts +13 -0
  107. package/dist/integrations/pipeline-keys.js +22 -0
  108. package/dist/integrations/pipeline-runs.d.ts +119 -0
  109. package/dist/integrations/pipeline-runs.js +87 -0
  110. package/dist/integrations/pipelines.d.ts +87 -15
  111. package/dist/integrations/pipelines.js +41 -22
  112. package/dist/integrations/price-import.d.ts +223 -0
  113. package/dist/integrations/price-import.js +124 -0
  114. package/dist/integrations/types.d.ts +367 -3
  115. package/dist/integrations/types.js +4 -3
  116. package/dist/locations/index.d.ts +66 -0
  117. package/dist/locations/index.js +31 -0
  118. package/dist/meta/index.d.ts +172 -0
  119. package/dist/metafields/index.d.ts +8 -1
  120. package/dist/metafields/index.js +10 -0
  121. package/dist/orders/cancel-with-money.d.ts +237 -0
  122. package/dist/orders/cancel-with-money.js +155 -0
  123. package/dist/orders/commit-edit.d.ts +23 -1
  124. package/dist/orders/commit-edit.js +19 -2
  125. package/dist/orders/deposit-policy.d.ts +3 -1
  126. package/dist/orders/drafts.d.ts +800 -0
  127. package/dist/orders/drafts.js +771 -0
  128. package/dist/orders/fields.d.ts +245 -0
  129. package/dist/orders/fields.js +188 -0
  130. package/dist/orders/get.d.ts +29 -19
  131. package/dist/orders/get.js +17 -8
  132. package/dist/orders/index.d.ts +66 -15
  133. package/dist/orders/index.js +25 -2
  134. package/dist/orders/lifecycle.d.ts +128 -0
  135. package/dist/orders/lifecycle.js +158 -0
  136. package/dist/orders/line-price-preview.d.ts +7 -2
  137. package/dist/orders/list.d.ts +243 -0
  138. package/dist/orders/list.js +487 -0
  139. package/dist/orders/manual-discounts.d.ts +13 -5
  140. package/dist/orders/manual-pricing.d.ts +5 -0
  141. package/dist/orders/money-view.d.ts +149 -0
  142. package/dist/orders/money-view.js +99 -0
  143. package/dist/orders/order-entry.d.ts +20 -7
  144. package/dist/orders/plan-edit.d.ts +34 -2
  145. package/dist/orders/plan-edit.js +112 -11
  146. package/dist/orders/settings.d.ts +201 -0
  147. package/dist/orders/settings.js +325 -0
  148. package/dist/orders/status.d.ts +159 -13
  149. package/dist/orders/status.js +21 -0
  150. package/dist/orders/surcharges.d.ts +20 -1
  151. package/dist/orders/surcharges.js +37 -11
  152. package/dist/payments/account-credit.d.ts +46 -0
  153. package/dist/payments/account-credit.js +42 -0
  154. package/dist/payments/ar.d.ts +292 -0
  155. package/dist/payments/ar.js +223 -0
  156. package/dist/payments/connected-account.d.ts +47 -0
  157. package/dist/payments/connected-account.js +61 -0
  158. package/dist/payments/credit-noted-fields.d.ts +19 -0
  159. package/dist/payments/credit-noted-fields.js +69 -0
  160. package/dist/payments/customer-consent.d.ts +30 -0
  161. package/dist/payments/customer-consent.js +49 -0
  162. package/dist/payments/index.d.ts +340 -19
  163. package/dist/payments/index.js +151 -1
  164. package/dist/payments/methods.d.ts +303 -8
  165. package/dist/payments/methods.js +337 -7
  166. package/dist/payments/mollie-methods.d.ts +159 -0
  167. package/dist/payments/mollie-methods.js +141 -0
  168. package/dist/payments/payment-links.d.ts +180 -0
  169. package/dist/payments/payment-links.js +97 -0
  170. package/dist/payments/provider-keys.d.ts +150 -0
  171. package/dist/payments/provider-keys.js +118 -0
  172. package/dist/payments/providers.d.ts +86 -11
  173. package/dist/payments/providers.js +29 -0
  174. package/dist/payments/requests.d.ts +147 -0
  175. package/dist/payments/requests.js +93 -0
  176. package/dist/payments/store-credit-fields.d.ts +15 -0
  177. package/dist/payments/store-credit-fields.js +51 -0
  178. package/dist/pickups/index.d.ts +106 -0
  179. package/dist/pickups/index.js +108 -0
  180. package/dist/platform/channels.d.ts +132 -0
  181. package/dist/platform/channels.js +128 -0
  182. package/dist/platform/email-gateways.d.ts +165 -0
  183. package/dist/platform/email-gateways.js +78 -0
  184. package/dist/platform/geo.d.ts +123 -0
  185. package/dist/platform/geo.js +144 -0
  186. package/dist/platform/tax.d.ts +162 -0
  187. package/dist/platform/tax.js +169 -0
  188. package/dist/pos/anomalies.d.ts +158 -0
  189. package/dist/pos/anomalies.js +64 -0
  190. package/dist/pos/assisted-selling.d.ts +79 -0
  191. package/dist/pos/assisted-selling.js +38 -0
  192. package/dist/pos/exchanges.d.ts +108 -0
  193. package/dist/pos/exchanges.js +22 -0
  194. package/dist/pos/gift-cards.d.ts +135 -0
  195. package/dist/pos/gift-cards.js +47 -0
  196. package/dist/pos/index.d.ts +2370 -58
  197. package/dist/pos/index.js +854 -7
  198. package/dist/pos/no-receipt.d.ts +94 -0
  199. package/dist/pos/no-receipt.js +25 -0
  200. package/dist/pos/offline-sales.d.ts +228 -0
  201. package/dist/pos/offline-sales.js +170 -0
  202. package/dist/pos/pay-by-link.d.ts +143 -0
  203. package/dist/pos/pay-by-link.js +57 -0
  204. package/dist/pos/quick-keys.d.ts +103 -0
  205. package/dist/pos/quick-keys.js +45 -0
  206. package/dist/pos/reports.d.ts +360 -0
  207. package/dist/pos/reports.js +62 -0
  208. package/dist/pos/returns.d.ts +244 -0
  209. package/dist/pos/returns.js +83 -0
  210. package/dist/pricing/bulk-coupons.d.ts +139 -0
  211. package/dist/pricing/bulk-coupons.js +112 -0
  212. package/dist/pricing/index.d.ts +174 -4
  213. package/dist/pricing/index.js +174 -1
  214. package/dist/pricing/price-lists.d.ts +606 -0
  215. package/dist/pricing/price-lists.js +600 -0
  216. package/dist/purchasing/alerts.d.ts +104 -0
  217. package/dist/purchasing/alerts.js +88 -0
  218. package/dist/purchasing/backorders.d.ts +61 -0
  219. package/dist/purchasing/backorders.js +92 -0
  220. package/dist/purchasing/cost.d.ts +110 -0
  221. package/dist/purchasing/cost.js +86 -0
  222. package/dist/purchasing/index.d.ts +54 -0
  223. package/dist/purchasing/index.js +24 -0
  224. package/dist/purchasing/links.d.ts +263 -0
  225. package/dist/purchasing/links.js +192 -0
  226. package/dist/purchasing/purchase-orders.d.ts +551 -0
  227. package/dist/purchasing/purchase-orders.js +491 -0
  228. package/dist/purchasing/receipts.d.ts +396 -0
  229. package/dist/purchasing/receipts.js +287 -0
  230. package/dist/purchasing/replenishment.d.ts +281 -0
  231. package/dist/purchasing/replenishment.js +240 -0
  232. package/dist/purchasing/returns.d.ts +273 -0
  233. package/dist/purchasing/returns.js +229 -0
  234. package/dist/purchasing/settings.d.ts +152 -0
  235. package/dist/purchasing/settings.js +181 -0
  236. package/dist/purchasing/suppliers.d.ts +476 -0
  237. package/dist/purchasing/suppliers.js +438 -0
  238. package/dist/quotes/index.d.ts +518 -0
  239. package/dist/quotes/index.js +439 -0
  240. package/dist/reports/index.d.ts +71 -8
  241. package/dist/reports/index.js +74 -11
  242. package/dist/returns/index.d.ts +675 -21
  243. package/dist/returns/index.js +756 -11
  244. package/dist/search/index.d.ts +76 -1
  245. package/dist/search/index.js +63 -0
  246. package/dist/seo/config.d.ts +128 -0
  247. package/dist/seo/config.js +95 -0
  248. package/dist/seo/redirects.d.ts +125 -0
  249. package/dist/seo/redirects.js +60 -1
  250. package/dist/seo/settings.d.ts +147 -0
  251. package/dist/seo/settings.js +209 -0
  252. package/dist/shipping/definitions.d.ts +29 -0
  253. package/dist/shipping/definitions.js +47 -0
  254. package/dist/shipping/fulfillment-profiles.d.ts +174 -0
  255. package/dist/shipping/fulfillment-profiles.js +104 -0
  256. package/dist/shipping/hendriks.d.ts +97 -0
  257. package/dist/shipping/hendriks.js +50 -0
  258. package/dist/shipping/index.d.ts +54 -0
  259. package/dist/shipping/index.js +27 -0
  260. package/dist/shipping/methods.d.ts +205 -0
  261. package/dist/shipping/methods.js +240 -0
  262. package/dist/shipping/myparcel.d.ts +668 -0
  263. package/dist/shipping/myparcel.js +466 -0
  264. package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
  265. package/dist/shipping/parcel-rule.d.ts +6 -5
  266. package/dist/shipping/parcel-rule.js +21 -23
  267. package/dist/shipping/rate-tables.d.ts +324 -0
  268. package/dist/shipping/rate-tables.js +390 -0
  269. package/dist/shipping/ship-to-countries.d.ts +75 -0
  270. package/dist/shipping/ship-to-countries.js +47 -0
  271. package/dist/stock/by-location.d.ts +86 -0
  272. package/dist/stock/by-location.js +94 -0
  273. package/dist/stock/index.d.ts +18 -4
  274. package/dist/stock/index.js +7 -0
  275. package/dist/stock/locations.d.ts +144 -0
  276. package/dist/stock/locations.js +168 -0
  277. package/dist/stock/settings.d.ts +106 -0
  278. package/dist/stock/settings.js +103 -0
  279. package/dist/stock/transfers.d.ts +386 -52
  280. package/dist/stock/transfers.js +222 -17
  281. package/dist/stored-value/index.d.ts +312 -11
  282. package/dist/stored-value/index.js +223 -4
  283. package/dist/subscriptions/index.d.ts +682 -0
  284. package/dist/subscriptions/index.js +815 -0
  285. package/dist/tax/display-policy.d.ts +105 -0
  286. package/dist/tax/display-policy.js +84 -0
  287. package/dist/tax/index.d.ts +79 -1
  288. package/dist/tax/index.js +52 -0
  289. package/dist/tenant/email-style.d.ts +102 -0
  290. package/dist/tenant/email-style.js +72 -0
  291. package/dist/tenant/email-templates.d.ts +287 -0
  292. package/dist/tenant/email-templates.js +271 -0
  293. package/dist/tenant/notifications.d.ts +23 -17
  294. package/dist/tenant/settings-sources.d.ts +1 -1
  295. package/dist/tenant/time-zone.d.ts +17 -0
  296. package/dist/tenant/time-zone.js +11 -0
  297. package/dist/types.d.ts +50 -3
  298. package/dist/users/index.d.ts +3 -0
  299. package/dist/users/index.js +2 -0
  300. package/dist/users/warehouses.d.ts +50 -0
  301. package/dist/users/warehouses.js +51 -0
  302. package/package.json +2 -2
@@ -0,0 +1,158 @@
1
+ import { type Page, type Transport } from '@sixtyninecommerce/core';
2
+ import type { Call, ListOptions } from '../types.js';
3
+ /**
4
+ * A store's anomaly flags (engine row 43): rules run over each location's ENDED business day flag
5
+ * unusual refunds, voids, returns without a receipt, outlying or unlogged discounts, cash
6
+ * variances, uncounted closes, money landed after a Z, a closed drawer whose cash changed, sales
7
+ * credited to another cashier and many no-sale opens. A flag never acts against anyone: a person
8
+ * reviews it and acknowledges it with a note.
9
+ *
10
+ * OFF until the store turns it on (`setRules({ enabled: true })`): flags name staff, and in the
11
+ * Netherlands and Germany a system that monitors staff needs the works council's consent first.
12
+ * Every read and write needs `UpdateSettings` or `ManagePosDevices` (`setRules`: `UpdateSettings`);
13
+ * a location-restricted caller sees its locations' flags only. Each method is its own document: an
14
+ * engine before 43 refuses it at validation, nothing else.
15
+ */
16
+ export interface PosAnomalyThresholds {
17
+ minCount: number | null;
18
+ minSales: number | null;
19
+ multiplier: number | null;
20
+ floorPercent: number | null;
21
+ fallbackPercent: number | null;
22
+ percentile: number | null;
23
+ /** Minor units of the drawer currency; null = that test off. */
24
+ amount: number | null;
25
+ }
26
+ export interface PosAnomalyRule {
27
+ code: string;
28
+ enabled: boolean;
29
+ /** False: the store lacks the rule's source (it is skipped). */
30
+ available: boolean;
31
+ /** `info`, `warning` or `high`; more may come. */
32
+ severity: string;
33
+ /** `staff`, `drawer` or `store_day`; more may come. */
34
+ subject: string;
35
+ /** The thresholds this rule takes. */
36
+ parameters: string[];
37
+ thresholds: PosAnomalyThresholds;
38
+ defaults: PosAnomalyThresholds;
39
+ }
40
+ export interface PosAnomalyRules {
41
+ enabled: boolean;
42
+ rulesVersion: number;
43
+ rules: PosAnomalyRule[];
44
+ }
45
+ export interface PosAnomalyRuleInput extends Partial<PosAnomalyThresholds> {
46
+ code: string;
47
+ enabled: boolean;
48
+ }
49
+ export interface PosAnomalyRulesInput {
50
+ enabled: boolean;
51
+ /** Rules not listed keep their stored settings; a listed one is replaced whole. */
52
+ rules?: PosAnomalyRuleInput[];
53
+ }
54
+ /** A figure: `count`, `percent`, `basis_points` or `minor` (more may come). */
55
+ export interface PosAnomalyFigure {
56
+ key: string;
57
+ value: number;
58
+ unit: string;
59
+ }
60
+ export interface PosAnomalyFlag {
61
+ id: string;
62
+ stockLocationId: string;
63
+ locationName: string | null;
64
+ businessDay: string;
65
+ rule: string;
66
+ severity: string;
67
+ subjectKind: string;
68
+ staffId: string | null;
69
+ staffName: string | null;
70
+ sessionId: string | null;
71
+ registerId: string | null;
72
+ registerName: string | null;
73
+ zNumber: number | null;
74
+ /** `open` or `acknowledged`; more may come. */
75
+ status: string;
76
+ measure: PosAnomalyFigure[];
77
+ thresholds: PosAnomalyFigure[];
78
+ evidence: {
79
+ orders: Array<{
80
+ orderId: string;
81
+ code: string;
82
+ receiptNumber: string | null;
83
+ amount: number | null;
84
+ }>;
85
+ sessionIds: string[];
86
+ truncated: boolean;
87
+ };
88
+ detectedAt: string;
89
+ lastEvaluatedAt: string;
90
+ acknowledgedAt: string | null;
91
+ acknowledgedByName: string | null;
92
+ note: string | null;
93
+ }
94
+ export interface PosAnomalyFlagListOptions extends ListOptions {
95
+ /** `open` (default), `acknowledged` or `all`. */
96
+ status?: string;
97
+ fromDay?: string;
98
+ toDay?: string;
99
+ stockLocationId?: string;
100
+ rule?: string;
101
+ severity?: string;
102
+ staffId?: string;
103
+ }
104
+ export interface PosAnomalyOverview {
105
+ enabled: boolean;
106
+ open: number;
107
+ openHigh: number;
108
+ openWarning: number;
109
+ openInfo: number;
110
+ oldestOpenDay: string | null;
111
+ }
112
+ export interface PosAnomalyScanResult {
113
+ stockLocationId: string;
114
+ businessDay: string;
115
+ newFlagCount: number;
116
+ openFlagCount: number;
117
+ skippedRules: string[];
118
+ }
119
+ export interface PosAnomaliesModule {
120
+ rules(options?: Call): Promise<PosAnomalyRules>;
121
+ /**
122
+ * Refused `POS_ANOMALY_RULES_INVALID`: `details[0].field` is a JSON Pointer into the input
123
+ * (`/rules/<index>/<threshold>`, `/enabled`), `details[0].code` the reason.
124
+ */
125
+ setRules(input: PosAnomalyRulesInput, options?: Call): Promise<PosAnomalyRules>;
126
+ /** Newest business day first, then severity; `limit` 1-100 (25), `after` an offset cursor. */
127
+ list(options?: PosAnomalyFlagListOptions): Promise<Page<PosAnomalyFlag>>;
128
+ /** One flag, or null (another store's, or another location's for a restricted caller). */
129
+ get(id: string, options?: Call): Promise<PosAnomalyFlag | null>;
130
+ overview(options?: Call): Promise<PosAnomalyOverview>;
131
+ /** Refused `POS_ANOMALY_FLAG_NOT_FOUND`, `POS_ANOMALY_FLAG_NOT_OPEN`, `POS_ANOMALY_NOTE_INVALID`. */
132
+ acknowledge(input: {
133
+ flagId: string;
134
+ note: string;
135
+ }, options?: Call): Promise<PosAnomalyFlag>;
136
+ /**
137
+ * Evaluate one ENDED business day of a location now (a rerun adds nothing). Refused
138
+ * `POS_ANOMALY_FLAGS_OFF`, `POS_ANOMALY_DAY_NOT_ENDED`, `POS_LIST_RANGE_INVALID`,
139
+ * `POS_ANOMALY_SCAN_BUSY`, `POS_LOCATION_NOT_FOUND`, `LOCATION_NOT_ALLOWED`.
140
+ */
141
+ scanDay(input: {
142
+ stockLocationId: string;
143
+ businessDay: string;
144
+ }, options?: Call): Promise<PosAnomalyScanResult>;
145
+ }
146
+ export declare const POS_ANOMALY_FLAG_FIELDS = "id stockLocationId locationName businessDay rule severity subjectKind staffId staffName sessionId registerId registerName zNumber status measure { key value unit } thresholds { key value unit } evidence { orders { orderId code receiptNumber amount } sessionIds truncated } detectedAt lastEvaluatedAt acknowledgedAt acknowledgedByName note";
147
+ export declare const POS_ANOMALY_RULES_QUERY = "query PosAnomalyRules { posAnomalyRules { enabled rulesVersion rules { code enabled available severity subject parameters thresholds { minCount minSales multiplier floorPercent fallbackPercent percentile amount } defaults { minCount minSales multiplier floorPercent fallbackPercent percentile amount } } } }";
148
+ export declare const SET_POS_ANOMALY_RULES_MUTATION = "mutation SetPosAnomalyRules($input: PosAnomalyRulesInput!) { setPosAnomalyRules(input: $input) { enabled rulesVersion rules { code enabled available severity subject parameters thresholds { minCount minSales multiplier floorPercent fallbackPercent percentile amount } defaults { minCount minSales multiplier floorPercent fallbackPercent percentile amount } } } }";
149
+ export declare const POS_ANOMALY_FLAGS_QUERY = "query PosAnomalyFlags($input: PosAnomalyFlagListInput) { posAnomalyFlags(input: $input) { items { id stockLocationId locationName businessDay rule severity subjectKind staffId staffName sessionId registerId registerName zNumber status measure { key value unit } thresholds { key value unit } evidence { orders { orderId code receiptNumber amount } sessionIds truncated } detectedAt lastEvaluatedAt acknowledgedAt acknowledgedByName note } totalItems } }";
150
+ export declare const POS_ANOMALY_FLAG_QUERY = "query PosAnomalyFlag($id: ID!) { posAnomalyFlag(id: $id) { id stockLocationId locationName businessDay rule severity subjectKind staffId staffName sessionId registerId registerName zNumber status measure { key value unit } thresholds { key value unit } evidence { orders { orderId code receiptNumber amount } sessionIds truncated } detectedAt lastEvaluatedAt acknowledgedAt acknowledgedByName note } }";
151
+ export declare const POS_ANOMALY_OVERVIEW_QUERY = "query PosAnomalyOverview { posAnomalyOverview { enabled open openHigh openWarning openInfo oldestOpenDay } }";
152
+ export declare const ACKNOWLEDGE_POS_ANOMALY_FLAG_MUTATION = "mutation AcknowledgePosAnomalyFlag($input: AcknowledgePosAnomalyFlagInput!) { acknowledgePosAnomalyFlag(input: $input) { id stockLocationId locationName businessDay rule severity subjectKind staffId staffName sessionId registerId registerName zNumber status measure { key value unit } thresholds { key value unit } evidence { orders { orderId code receiptNumber amount } sessionIds truncated } detectedAt lastEvaluatedAt acknowledgedAt acknowledgedByName note } }";
153
+ export declare const RUN_POS_ANOMALY_SCAN_MUTATION = "mutation RunPosAnomalyScan($input: RunPosAnomalyScanInput!) { runPosAnomalyScan(input: $input) { stockLocationId businessDay newFlagCount openFlagCount skippedRules } }";
154
+ /** A flag page: at most this many. */
155
+ export declare const POS_ANOMALY_FLAGS_MAX_PAGE = 100;
156
+ /** ... and this many when `limit` is omitted. */
157
+ export declare const POS_ANOMALY_FLAGS_DEFAULT_PAGE = 25;
158
+ export declare function createPosAnomaliesModule(transport: Transport): PosAnomaliesModule;
@@ -0,0 +1,64 @@
1
+ import { pageFromVendureList, readOffsetCursor, } from '@sixtyninecommerce/core';
2
+ const THRESHOLDS = 'minCount minSales multiplier floorPercent fallbackPercent percentile amount';
3
+ const RULES = `enabled rulesVersion rules { code enabled available severity subject parameters thresholds { ${THRESHOLDS} } defaults { ${THRESHOLDS} } }`;
4
+ const FIGURE = 'key value unit';
5
+ export const POS_ANOMALY_FLAG_FIELDS = `id stockLocationId locationName businessDay rule severity subjectKind staffId staffName sessionId registerId registerName zNumber status measure { ${FIGURE} } thresholds { ${FIGURE} } evidence { orders { orderId code receiptNumber amount } sessionIds truncated } detectedAt lastEvaluatedAt acknowledgedAt acknowledgedByName note`;
6
+ export const POS_ANOMALY_RULES_QUERY = `query PosAnomalyRules { posAnomalyRules { ${RULES} } }`;
7
+ export const SET_POS_ANOMALY_RULES_MUTATION = `mutation SetPosAnomalyRules($input: PosAnomalyRulesInput!) { setPosAnomalyRules(input: $input) { ${RULES} } }`;
8
+ export const POS_ANOMALY_FLAGS_QUERY = `query PosAnomalyFlags($input: PosAnomalyFlagListInput) { posAnomalyFlags(input: $input) { items { ${POS_ANOMALY_FLAG_FIELDS} } totalItems } }`;
9
+ export const POS_ANOMALY_FLAG_QUERY = `query PosAnomalyFlag($id: ID!) { posAnomalyFlag(id: $id) { ${POS_ANOMALY_FLAG_FIELDS} } }`;
10
+ export const POS_ANOMALY_OVERVIEW_QUERY = 'query PosAnomalyOverview { posAnomalyOverview { enabled open openHigh openWarning openInfo oldestOpenDay } }';
11
+ export const ACKNOWLEDGE_POS_ANOMALY_FLAG_MUTATION = `mutation AcknowledgePosAnomalyFlag($input: AcknowledgePosAnomalyFlagInput!) { acknowledgePosAnomalyFlag(input: $input) { ${POS_ANOMALY_FLAG_FIELDS} } }`;
12
+ export const RUN_POS_ANOMALY_SCAN_MUTATION = 'mutation RunPosAnomalyScan($input: RunPosAnomalyScanInput!) { runPosAnomalyScan(input: $input) { stockLocationId businessDay newFlagCount openFlagCount skippedRules } }';
13
+ /** A flag page: at most this many. */
14
+ export const POS_ANOMALY_FLAGS_MAX_PAGE = 100;
15
+ /** ... and this many when `limit` is omitted. */
16
+ export const POS_ANOMALY_FLAGS_DEFAULT_PAGE = 25;
17
+ const FILTERS = [
18
+ 'status',
19
+ 'fromDay',
20
+ 'toDay',
21
+ 'stockLocationId',
22
+ 'rule',
23
+ 'severity',
24
+ 'staffId',
25
+ ];
26
+ export function createPosAnomaliesModule(transport) {
27
+ const gql = (query, variables, options) => transport.graphql({ api: 'admin', query, variables }, options);
28
+ const page = async (skip, take, options) => {
29
+ const input = { skip, take };
30
+ for (const key of FILTERS) {
31
+ const value = options?.[key];
32
+ if (value !== undefined && value !== '')
33
+ input[key] = value;
34
+ }
35
+ const data = await gql(POS_ANOMALY_FLAGS_QUERY, { input }, options);
36
+ return pageFromVendureList(data.posAnomalyFlags, skip, take, (cursor) => page(readOffsetCursor(cursor), take, options));
37
+ };
38
+ return {
39
+ async rules(options) {
40
+ return (await gql(POS_ANOMALY_RULES_QUERY, {}, options))
41
+ .posAnomalyRules;
42
+ },
43
+ async setRules(input, options) {
44
+ return (await gql(SET_POS_ANOMALY_RULES_MUTATION, { input }, options)).setPosAnomalyRules;
45
+ },
46
+ async list(options) {
47
+ const take = Math.min(Math.max(Math.trunc(options?.limit ?? POS_ANOMALY_FLAGS_DEFAULT_PAGE), 1), POS_ANOMALY_FLAGS_MAX_PAGE);
48
+ const skip = options?.after === undefined ? 0 : readOffsetCursor(options.after);
49
+ return page(skip, take, options);
50
+ },
51
+ async get(id, options) {
52
+ return (await gql(POS_ANOMALY_FLAG_QUERY, { id }, options)).posAnomalyFlag;
53
+ },
54
+ async overview(options) {
55
+ return (await gql(POS_ANOMALY_OVERVIEW_QUERY, {}, options)).posAnomalyOverview;
56
+ },
57
+ async acknowledge(input, options) {
58
+ return (await gql(ACKNOWLEDGE_POS_ANOMALY_FLAG_MUTATION, { input }, options)).acknowledgePosAnomalyFlag;
59
+ },
60
+ async scanDay(input, options) {
61
+ return (await gql(RUN_POS_ANOMALY_SCAN_MUTATION, { input }, options)).runPosAnomalyScan;
62
+ },
63
+ };
64
+ }
@@ -0,0 +1,79 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /**
4
+ * A store's assisted selling at the till (engine sprint C4/44): upsell prompts under the till's
5
+ * cart, from the store's recommendation groups, and assisted search ("Ask": the cashier's words
6
+ * planned by the platform's AI, then searched in the catalogue). Upsell is on unless the store
7
+ * turns it off; assisted search is OFF unless the platform has enabled it AND the store turns it
8
+ * on.
9
+ */
10
+ /** The most upsell suggestions a store may choose, and the most groups it may name. */
11
+ export declare const POS_ASSISTED_SELLING_LIMITS: {
12
+ readonly upsellMaxItems: 8;
13
+ readonly upsellGroups: 10;
14
+ readonly assistedSearchDailyLimit: 5000;
15
+ readonly usageDays: 31;
16
+ };
17
+ export interface PosAssistedSelling {
18
+ /** Upsell prompts under the till's cart. */
19
+ upsellEnabled: boolean;
20
+ /** At most this many suggestions (1-8; 4 by default). */
21
+ upsellMaxItems: number;
22
+ /** Recommendation group slugs that feed the till, in order; empty = every enabled group. */
23
+ upsellGroupSlugs: string[];
24
+ /** AI-planned search at the till; always false while `assistedSearchAvailable` is false. */
25
+ assistedSearchEnabled: boolean;
26
+ /** The platform has enabled AI search; until then the store cannot turn it on. */
27
+ assistedSearchAvailable: boolean;
28
+ /** AI plans per day in the store's time zone (1-5,000; 300 by default). */
29
+ assistedSearchDailyLimit: number;
30
+ }
31
+ export interface PosAssistedSellingInput {
32
+ upsellEnabled: boolean;
33
+ /** Omitted keeps the stored value. */
34
+ upsellMaxItems?: number;
35
+ /** Replaces the list; omitted keeps it. */
36
+ upsellGroupSlugs?: string[];
37
+ assistedSearchEnabled: boolean;
38
+ /** Omitted keeps the stored value. */
39
+ assistedSearchDailyLimit?: number;
40
+ }
41
+ /** Why a search ran plain, counted per day. More reasons may come. */
42
+ export interface PosAssistedSearchFallbackCount {
43
+ reason: string;
44
+ count: number;
45
+ }
46
+ /** One day of a store's assisted search; the words are never kept. */
47
+ export interface PosAssistedSearchUsageDay {
48
+ /** YYYY-MM-DD in the store's time zone. */
49
+ day: string;
50
+ searches: number;
51
+ /** AI plans asked for (each counts against the daily limit). */
52
+ planned: number;
53
+ fallbacks: PosAssistedSearchFallbackCount[];
54
+ inputTokens: number;
55
+ outputTokens: number;
56
+ }
57
+ /** `get` needs any staff session of the store; `set` needs `UpdateSettings`; `usage` needs `UpdateSettings` or `ManagePosDevices`. */
58
+ export interface PosAssistedSellingModule {
59
+ /** The store's assisted selling, defaults applied. */
60
+ get(options?: Call): Promise<PosAssistedSelling>;
61
+ /**
62
+ * Set it. Refusals: `POS_ASSISTED_SELLING_INVALID` (`ValidationError`; `field` and `reason`:
63
+ * `upsellMaxItems` outside 1-8, `assistedSearchDailyLimit` outside 1-5,000, more than 10
64
+ * groups, a repeated or blank slug, or a newly picked slug that is not an enabled group of the
65
+ * store), `POS_ASSISTED_SEARCH_UNAVAILABLE` (turning assisted search on while the platform has
66
+ * it off), `ORGANIZATION_WORKSPACE_NOT_A_STORE`. An unchanged setting writes nothing.
67
+ */
68
+ set(input: PosAssistedSellingInput, options?: Call): Promise<PosAssistedSelling>;
69
+ /**
70
+ * The last `days` (1-31, 30 when omitted) of the store's assisted search, newest first; a day
71
+ * nobody searched has no entry. Refused `POS_ASSISTED_SELLING_INVALID` (`field: 'days'`) out of
72
+ * range; the SDK refuses a `days` that is not a whole number before sending.
73
+ */
74
+ usage(days?: number, options?: Call): Promise<PosAssistedSearchUsageDay[]>;
75
+ }
76
+ export declare const POS_ASSISTED_SELLING_QUERY = "query PosAssistedSelling { posAssistedSelling { upsellEnabled upsellMaxItems upsellGroupSlugs assistedSearchEnabled assistedSearchAvailable assistedSearchDailyLimit } }";
77
+ export declare const SET_POS_ASSISTED_SELLING_MUTATION = "mutation SetPosAssistedSelling($input: PosAssistedSellingInput!) { setPosAssistedSelling(input: $input) { upsellEnabled upsellMaxItems upsellGroupSlugs assistedSearchEnabled assistedSearchAvailable assistedSearchDailyLimit } }";
78
+ export declare const POS_ASSISTED_SEARCH_USAGE_QUERY = "query PosAssistedSearchUsage($days: Int) { posAssistedSearchUsage(days: $days) { day searches planned fallbacks { reason count } inputTokens outputTokens } }";
79
+ export declare function createPosAssistedSellingModule(transport: Transport): PosAssistedSellingModule;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * A store's assisted selling at the till (engine sprint C4/44): upsell prompts under the till's
3
+ * cart, from the store's recommendation groups, and assisted search ("Ask": the cashier's words
4
+ * planned by the platform's AI, then searched in the catalogue). Upsell is on unless the store
5
+ * turns it off; assisted search is OFF unless the platform has enabled it AND the store turns it
6
+ * on.
7
+ */
8
+ /** The most upsell suggestions a store may choose, and the most groups it may name. */
9
+ export const POS_ASSISTED_SELLING_LIMITS = {
10
+ upsellMaxItems: 8,
11
+ upsellGroups: 10,
12
+ assistedSearchDailyLimit: 5000,
13
+ usageDays: 31,
14
+ };
15
+ const SELLING_FIELDS = 'upsellEnabled upsellMaxItems upsellGroupSlugs assistedSearchEnabled assistedSearchAvailable assistedSearchDailyLimit';
16
+ export const POS_ASSISTED_SELLING_QUERY = `query PosAssistedSelling { posAssistedSelling { ${SELLING_FIELDS} } }`;
17
+ export const SET_POS_ASSISTED_SELLING_MUTATION = `mutation SetPosAssistedSelling($input: PosAssistedSellingInput!) { setPosAssistedSelling(input: $input) { ${SELLING_FIELDS} } }`;
18
+ export const POS_ASSISTED_SEARCH_USAGE_QUERY = 'query PosAssistedSearchUsage($days: Int) { posAssistedSearchUsage(days: $days) { day searches planned fallbacks { reason count } inputTokens outputTokens } }';
19
+ export function createPosAssistedSellingModule(transport) {
20
+ const gql = async (query, variables, options) => transport.graphql({ api: 'admin', query, variables }, options);
21
+ return {
22
+ async get(options) {
23
+ const data = await gql(POS_ASSISTED_SELLING_QUERY, {}, options);
24
+ return data.posAssistedSelling;
25
+ },
26
+ async set(input, options) {
27
+ const data = await gql(SET_POS_ASSISTED_SELLING_MUTATION, { input }, options);
28
+ return data.setPosAssistedSelling;
29
+ },
30
+ async usage(days, options) {
31
+ if (days !== undefined && !Number.isInteger(days)) {
32
+ throw new TypeError('assistedSelling.usage(days): days is a whole number from 1 to 31.');
33
+ }
34
+ const data = await gql(POS_ASSISTED_SEARCH_USAGE_QUERY, days === undefined ? {} : { days }, options);
35
+ return data.posAssistedSearchUsage;
36
+ },
37
+ };
38
+ }
@@ -0,0 +1,108 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ import type { PosReturnLeg, PosReturnLineInput, PosReturnQuoteLine, PosReturnRefund } from './returns.js';
4
+ /**
5
+ * Till exchanges (POS engine sprint 21): a completed till sale's items come back and their value
6
+ * pays an OPEN till cart as its LAST tender, carried as settled exchange-credit payments (no
7
+ * provider is asked for what is carried), any excess refunded to the sale's own payments. A
8
+ * headless till (a machine principal with `x-location`) is a supported caller: its CREDENTIAL is
9
+ * the manager gate, so no staff or approval token is sent. Money is integer minor units.
10
+ *
11
+ * `quote` is a read: the credit, what the cart owes, what would be carried, the excess and its
12
+ * refunds, and why it cannot be done now (`blockedBy`, never thrown:
13
+ * `POS_EXCHANGE_BALANCE_DUE` while the cart owes more than the credit — tender the difference
14
+ * first). `create` re-computes under the sale's money turn and refuses figures other than
15
+ * `expectedCredit` / `expectedApplied` (`POS_EXCHANGE_AMOUNT_CHANGED`). Then complete the cart
16
+ * with `sale.complete`. Refusals that mean NOTHING moved: `POS_EXCHANGE_INVALID`
17
+ * (`extensions.reason`: not_till_cart, same_order, currency, nothing_owed), the `POS_RETURN_*`
18
+ * refusals of `returns.create`, `POS_CART_HELD`. `IDEMPOTENCY_OUTCOME_UNKNOWN`: an excess card
19
+ * refund reached the provider and the outcome is unknown; never retry under a new key.
20
+ */
21
+ export interface PosExchangeQuoteInput {
22
+ /** The completed till sale the items come back from. */
23
+ returnOrderId: string;
24
+ /** The open till cart the credit goes to. */
25
+ orderId: string;
26
+ lines?: Array<{
27
+ orderLineId: string;
28
+ quantity: number;
29
+ }>;
30
+ cashFirst?: boolean;
31
+ }
32
+ export interface PosExchangeCarry {
33
+ /** The returned sale's payment the credit comes from. */
34
+ sourcePaymentId: string;
35
+ /** cash, card or other. More may come. */
36
+ kind: string;
37
+ method: string;
38
+ amount: number;
39
+ /** The exchange payment on the cart; null in a quote. */
40
+ paymentId: string | null;
41
+ }
42
+ export interface PosExchangeQuote {
43
+ returnOrderId: string;
44
+ orderId: string;
45
+ currencyCode: string;
46
+ receiptNumber: string | null;
47
+ lines: PosReturnQuoteLine[];
48
+ credit: number;
49
+ newSaleTotal: number;
50
+ newSalePaid: number;
51
+ /** Still to pay before the exchange: tender it first. */
52
+ due: number;
53
+ applied: number;
54
+ excess: number;
55
+ carries: PosExchangeCarry[];
56
+ legs: PosReturnLeg[];
57
+ cashPaidOut: number;
58
+ returnWindowEndsAt: string | null;
59
+ outsideWindow: boolean;
60
+ refundedOutsideReturns: number;
61
+ restockLocationName: string | null;
62
+ /** A POS_EXCHANGE_* / POS_RETURN_* code, or null. More may come. */
63
+ blockedBy: string | null;
64
+ blockedReason: string | null;
65
+ }
66
+ export interface PosExchangeCreateInput {
67
+ returnOrderId: string;
68
+ orderId: string;
69
+ lines: PosReturnLineInput[];
70
+ /** `quote(...).credit` as shown. */
71
+ expectedCredit: number;
72
+ /** `quote(...).applied` as shown. */
73
+ expectedApplied: number;
74
+ overrideWindow?: boolean;
75
+ cashFirst?: boolean;
76
+ }
77
+ export interface PosExchangeResult {
78
+ returnOrderId: string;
79
+ orderId: string;
80
+ returnId: string;
81
+ /** The return's RMA code. */
82
+ returnCode: string;
83
+ credit: number;
84
+ applied: number;
85
+ excess: number;
86
+ carries: PosExchangeCarry[];
87
+ refunds: PosReturnRefund[];
88
+ cashPaidOut: number;
89
+ /**
90
+ * What the cart still owes after the credit: 0, unless a card is being charged on it or a
91
+ * payment link is open, which the exchange holds back (it never carries credit over money in
92
+ * flight). Complete the sale with `sale.complete` once that money lands; a completion while
93
+ * money is still owed is refused `POS_SALE_NOT_COVERED`.
94
+ */
95
+ remaining: number;
96
+ complete: boolean;
97
+ }
98
+ export interface PosExchangesModule {
99
+ /** What an exchange would do now. Writes nothing. */
100
+ quote(input: PosExchangeQuoteInput, options?: Call): Promise<PosExchangeQuote>;
101
+ /** Exchange the items: the key is REQUIRED (`options.idempotencyKey`). */
102
+ create(input: PosExchangeCreateInput, options: Call & {
103
+ idempotencyKey: string;
104
+ }): Promise<PosExchangeResult>;
105
+ }
106
+ export declare const POS_EXCHANGE_QUOTE_QUERY = "query PosExchangeQuote($input: PosExchangeQuoteInput!) { posExchangeQuote(input: $input) { returnOrderId orderId currencyCode receiptNumber lines { orderLineId name sku customItem restockable soldQuantity returnedQuantity returnableQuantity quantity refundAmount } credit newSaleTotal newSalePaid due applied excess carries { sourcePaymentId kind method amount paymentId } legs { paymentId kind method amount } cashPaidOut returnWindowEndsAt outsideWindow refundedOutsideReturns restockLocationName blockedBy blockedReason } }";
107
+ export declare const POS_EXCHANGE_MUTATION = "mutation PosExchange($input: PosExchangeInput!) { posExchange(input: $input) { returnOrderId orderId returnId returnCode credit applied excess carries { sourcePaymentId kind method amount paymentId } refunds { paymentId kind method amount refundId outcome } cashPaidOut remaining complete } }";
108
+ export declare function createPosExchangesModule(transport: Transport): PosExchangesModule;
@@ -0,0 +1,22 @@
1
+ const CARRY_FIELDS = 'sourcePaymentId kind method amount paymentId';
2
+ const QUOTE_FIELDS = `returnOrderId orderId currencyCode receiptNumber lines { orderLineId name sku customItem restockable soldQuantity returnedQuantity returnableQuantity quantity refundAmount } credit newSaleTotal newSalePaid due applied excess carries { ${CARRY_FIELDS} } legs { paymentId kind method amount } cashPaidOut returnWindowEndsAt outsideWindow refundedOutsideReturns restockLocationName blockedBy blockedReason`;
3
+ const RESULT_FIELDS = `returnOrderId orderId returnId returnCode credit applied excess carries { ${CARRY_FIELDS} } refunds { paymentId kind method amount refundId outcome } cashPaidOut remaining complete`;
4
+ export const POS_EXCHANGE_QUOTE_QUERY = `query PosExchangeQuote($input: PosExchangeQuoteInput!) { posExchangeQuote(input: $input) { ${QUOTE_FIELDS} } }`;
5
+ export const POS_EXCHANGE_MUTATION = `mutation PosExchange($input: PosExchangeInput!) { posExchange(input: $input) { ${RESULT_FIELDS} } }`;
6
+ export function createPosExchangesModule(transport) {
7
+ const gql = async (query, variables, options) => transport.graphql({ api: 'admin', query, variables }, options);
8
+ return {
9
+ async quote(input, options) {
10
+ const data = await gql(POS_EXCHANGE_QUOTE_QUERY, { input }, options);
11
+ return data.posExchangeQuote;
12
+ },
13
+ async create(input, options) {
14
+ const key = options?.idempotencyKey;
15
+ if (typeof key !== 'string' || key.trim() === '') {
16
+ throw new TypeError('pos.exchanges.create needs options.idempotencyKey (a fresh UUIDv7 per exchange; reuse it only to retry the same one).');
17
+ }
18
+ const data = await gql(POS_EXCHANGE_MUTATION, { input: { ...input, idempotencyKey: key } }, options);
19
+ return data.posExchange;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,135 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /**
4
+ * Gift cards at the till (engine C6): a headless till sells a gift card like any item, takes one
5
+ * as payment by its CODE, checks a card's balance, and hands a sale's codes over itself.
6
+ *
7
+ * - **Selling to anyone.** A sale whose buyer has no email address may sell a gift card when the
8
+ * till hands the codes over itself: call `setHandover` before the sale's first tender (a
9
+ * printer, or any way your till shows the code once). The sale's cards are then issued when it
10
+ * completes, and `completeSale` answers their codes in its FIRST answer only.
11
+ * - **The code is shown once and kept nowhere.** The engine stores no code; a retry of the same
12
+ * completion key answers the cards with `code: null`. Hand the codes to your customer (print
13
+ * them) straight from that first answer, and never log, cache or persist them: this SDK keeps
14
+ * none. A lost first answer loses the codes; a back-office `giftCards.reissueCode` gives the card
15
+ * a new one.
16
+ * - **Paying by code.** `tender` resolves the code on the engine and pays from that card; the
17
+ * payment never names the card's account (an account id is not a way to spend a card).
18
+ *
19
+ * Every money call is keyed (`idempotencyKey`). Each lookup and each tender spends one of the
20
+ * caller's gift-card lookups (rate limited per credential and per address). An engine before C6
21
+ * answers every call `GRAPHQL_VALIDATION_FAILED`.
22
+ */
23
+ /** A gift card as a till sees it: masked, never its code. */
24
+ export interface PosGiftCardBalance {
25
+ /** `••••-••••-••••-K2Q7`. */
26
+ maskedCode: string;
27
+ /** What it can spend now, minor units of `currencyCode`. */
28
+ spendable: number;
29
+ currencyCode: string;
30
+ /** The last valid day (`YYYY-MM-DD`, store zone); null for no expiry. */
31
+ expiresOn: string | null;
32
+ /** `active`, `blocked` or `voided`; more may come (treat an unknown one as not usable). */
33
+ status: string;
34
+ /** Whether it can pay the sale named by `orderId` now; false without one. */
35
+ canPay: boolean;
36
+ /**
37
+ * Why not: `NO_SALE`, `EXPIRED`, `BLOCKED`, `CURRENCY`, `EMPTY`, `SALE_SELLS_GIFT_CARD`,
38
+ * `NOT_ACCEPTED`, `NOTHING_DUE`, `NOT_USABLE`; more may come. Null when it can pay.
39
+ */
40
+ cannotPayReason: string | null;
41
+ }
42
+ /** What a till needs to sell a sale's gift cards. */
43
+ export interface PosGiftCardSale {
44
+ /** Gift-card units on the sale. */
45
+ units: number;
46
+ /** The till hands this sale's codes over itself (`setHandover`). */
47
+ handover: boolean;
48
+ /** The sale's customer can receive the codes by email (not the walk-in, not a placeholder). */
49
+ buyerHasEmail: boolean;
50
+ /** The store can issue gift cards now. */
51
+ canIssue: boolean;
52
+ }
53
+ /** A gift card a completed sale issued. */
54
+ export interface PosIssuedGiftCard {
55
+ maskedCode: string;
56
+ /** `XXXX-XXXX-XXXX-XXXX` in the first answer of a handed-over sale only; null otherwise. */
57
+ code: string | null;
58
+ faceValue: number;
59
+ currencyCode: string;
60
+ expiresOn: string | null;
61
+ }
62
+ /** A completed sale with its gift cards. */
63
+ export interface PosCompletedSaleWithGiftCards {
64
+ orderId: string;
65
+ orderCode: string;
66
+ receiptNumber: string;
67
+ state: string;
68
+ giftCards: PosIssuedGiftCard[];
69
+ /**
70
+ * The till hands this sale's codes over itself: they come in the first answer only, so a repeat
71
+ * answering them null cannot show them again. False for cards that went by email.
72
+ */
73
+ giftCardsHandedOver: boolean;
74
+ }
75
+ /** A gift card's payment, as every tender answers. */
76
+ export interface PosGiftCardTenderResult {
77
+ orderId: string;
78
+ paymentId: string;
79
+ covered: boolean;
80
+ outstanding: number;
81
+ change: number;
82
+ }
83
+ /** A till call's cashier: a paired DEVICE's PIN session; a machine principal omits it. */
84
+ type TillCall = Call & {
85
+ staffToken?: string;
86
+ };
87
+ export interface PosGiftCardsModule {
88
+ /**
89
+ * This store's card for `code`, masked; null for an unknown, malformed or other store's code.
90
+ * With `orderId` (the tender screen's who-rule), `canPay` says whether it can pay what that sale
91
+ * still owes. Spends one gift-card lookup.
92
+ */
93
+ byCode(code: string, sale?: {
94
+ orderId?: string | null;
95
+ }, options?: Call): Promise<PosGiftCardBalance | null>;
96
+ /** What the tender screen needs to sell the sale's gift cards. */
97
+ sale(orderId: string, options?: Call): Promise<PosGiftCardSale>;
98
+ /**
99
+ * Pay `amount` (at most what the card can spend and the sale still owes) from the card `code`
100
+ * names. Keyed: a repeat answers the same payment; the same key with another card is
101
+ * `IDEMPOTENCY_CONFLICT`. Refusals: `POS_GIFT_CARD_NOT_FOUND` (unknown, malformed or another
102
+ * store's code), `POS_STORED_VALUE_UNAVAILABLE`, `POS_TENDER_EXCEEDS_OUTSTANDING`, and the
103
+ * ledger's (`STORED_VALUE_INSUFFICIENT_BALANCE`, `STORED_VALUE_ACCOUNT_EXPIRED`,
104
+ * `STORED_VALUE_ACCOUNT_BLOCKED`, `STORED_VALUE_GIFT_CARD_PURCHASE_NOT_ALLOWED`, ...). Spends one
105
+ * gift-card lookup.
106
+ */
107
+ tender(input: {
108
+ orderId: string;
109
+ code: string;
110
+ amount: number;
111
+ }, options: TillCall & {
112
+ idempotencyKey: string;
113
+ }): Promise<PosGiftCardTenderResult>;
114
+ /**
115
+ * The till hands this sale's codes over itself: before the first tender of an open till sale,
116
+ * one-way. Refusals: `POS_GIFT_CARD_HANDOVER_TOO_LATE` (money is in),
117
+ * `STORED_VALUE_GIFT_CARD_NOT_CONFIGURED` (the store cannot issue gift cards now).
118
+ */
119
+ setHandover(orderId: string, options?: TillCall): Promise<PosGiftCardSale>;
120
+ /**
121
+ * `sale.complete` with the sale's gift cards: a handed-over sale's codes are in this call's
122
+ * FIRST answer only (a retry of the same key answers `code: null`). Hand them over at once and
123
+ * keep them nowhere; this SDK stores none.
124
+ */
125
+ completeSale(orderId: string, options: TillCall & {
126
+ idempotencyKey: string;
127
+ }): Promise<PosCompletedSaleWithGiftCards>;
128
+ }
129
+ export declare const POS_GIFT_CARD_BY_CODE_QUERY = "query PosGiftCardByCode($code: String!, $orderId: ID) { posGiftCardByCode(code: $code, orderId: $orderId) { maskedCode spendable currencyCode expiresOn status canPay cannotPayReason } }";
130
+ export declare const POS_GIFT_CARD_SALE_QUERY = "query PosGiftCardSale($orderId: ID!) { posGiftCardSale(orderId: $orderId) { units handover buyerHasEmail canIssue } }";
131
+ export declare const POS_TENDER_GIFT_CARD_MUTATION = "mutation PosTenderGiftCard($input: PosTenderGiftCardInput!, $staffToken: String) { posTenderGiftCard(input: $input, staffToken: $staffToken) { orderId paymentId covered outstanding change } }";
132
+ export declare const POS_SET_GIFT_CARD_HANDOVER_MUTATION = "mutation PosSetGiftCardHandover($orderId: ID!, $staffToken: String) { posSetGiftCardHandover(orderId: $orderId, staffToken: $staffToken) { units handover buyerHasEmail canIssue } }";
133
+ export declare const POS_COMPLETE_SALE_WITH_GIFT_CARDS_MUTATION = "mutation PosCompleteSaleWithGiftCards($input: PosCompleteSaleInput!, $staffToken: String) { posCompleteSale(input: $input, staffToken: $staffToken) { orderId orderCode receiptNumber state giftCards { maskedCode code faceValue currencyCode expiresOn } giftCardsHandedOver } }";
134
+ export declare function createPosGiftCardsModule(transport: Transport): PosGiftCardsModule;
135
+ export {};
@@ -0,0 +1,47 @@
1
+ const BALANCE_FIELDS = 'maskedCode spendable currencyCode expiresOn status canPay cannotPayReason';
2
+ const SALE_FIELDS = 'units handover buyerHasEmail canIssue';
3
+ const TENDER_FIELDS = 'orderId paymentId covered outstanding change';
4
+ const ISSUED_FIELDS = 'maskedCode code faceValue currencyCode expiresOn';
5
+ export const POS_GIFT_CARD_BY_CODE_QUERY = `query PosGiftCardByCode($code: String!, $orderId: ID) { posGiftCardByCode(code: $code, orderId: $orderId) { ${BALANCE_FIELDS} } }`;
6
+ export const POS_GIFT_CARD_SALE_QUERY = `query PosGiftCardSale($orderId: ID!) { posGiftCardSale(orderId: $orderId) { ${SALE_FIELDS} } }`;
7
+ export const POS_TENDER_GIFT_CARD_MUTATION = `mutation PosTenderGiftCard($input: PosTenderGiftCardInput!, $staffToken: String) { posTenderGiftCard(input: $input, staffToken: $staffToken) { ${TENDER_FIELDS} } }`;
8
+ export const POS_SET_GIFT_CARD_HANDOVER_MUTATION = `mutation PosSetGiftCardHandover($orderId: ID!, $staffToken: String) { posSetGiftCardHandover(orderId: $orderId, staffToken: $staffToken) { ${SALE_FIELDS} } }`;
9
+ export const POS_COMPLETE_SALE_WITH_GIFT_CARDS_MUTATION = `mutation PosCompleteSaleWithGiftCards($input: PosCompleteSaleInput!, $staffToken: String) { posCompleteSale(input: $input, staffToken: $staffToken) { orderId orderCode receiptNumber state giftCards { ${ISSUED_FIELDS} } giftCardsHandedOver } }`;
10
+ function requireKey(method, options) {
11
+ const key = options?.idempotencyKey;
12
+ if (typeof key !== 'string' || key.trim() === '') {
13
+ throw new TypeError(`giftCards.${method} needs options.idempotencyKey (a fresh UUIDv7 per call; resend it only to retry the same one).`);
14
+ }
15
+ return key;
16
+ }
17
+ export function createPosGiftCardsModule(transport) {
18
+ const gql = async (query, variables, options) => transport.graphql({ api: 'admin', query, variables }, options);
19
+ return {
20
+ async byCode(code, sale, options) {
21
+ const data = await gql(POS_GIFT_CARD_BY_CODE_QUERY, { code, orderId: sale?.orderId ?? null }, options);
22
+ return data.posGiftCardByCode;
23
+ },
24
+ async sale(orderId, options) {
25
+ const data = await gql(POS_GIFT_CARD_SALE_QUERY, { orderId }, options);
26
+ return data.posGiftCardSale;
27
+ },
28
+ async tender(input, options) {
29
+ const idempotencyKey = requireKey('tender', options);
30
+ const data = await gql(POS_TENDER_GIFT_CARD_MUTATION, { input: { ...input, idempotencyKey }, staffToken: options.staffToken }, options);
31
+ return data.posTenderGiftCard;
32
+ },
33
+ async setHandover(orderId, options) {
34
+ const data = await gql(POS_SET_GIFT_CARD_HANDOVER_MUTATION, { orderId, staffToken: options?.staffToken }, options);
35
+ return data.posSetGiftCardHandover;
36
+ },
37
+ async completeSale(orderId, options) {
38
+ const idempotencyKey = requireKey('completeSale', options);
39
+ const data = await gql(POS_COMPLETE_SALE_WITH_GIFT_CARDS_MUTATION, { input: { orderId, idempotencyKey }, staffToken: options.staffToken }, options);
40
+ return {
41
+ ...data.posCompleteSale,
42
+ giftCards: data.posCompleteSale.giftCards ?? [],
43
+ giftCardsHandedOver: data.posCompleteSale.giftCardsHandedOver === true,
44
+ };
45
+ },
46
+ };
47
+ }