@sixtyninecommerce/admin 0.11.0 → 0.13.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 (153) hide show
  1. package/README.md +1509 -28
  2. package/dist/auth/index.d.ts +7 -1
  3. package/dist/auth/index.js +8 -1
  4. package/dist/catalog/documents.d.ts +142 -0
  5. package/dist/catalog/documents.js +114 -0
  6. package/dist/catalog/index.d.ts +48 -7
  7. package/dist/catalog/index.js +6 -1
  8. package/dist/catalog/metadata.d.ts +244 -0
  9. package/dist/catalog/metadata.js +220 -0
  10. package/dist/catalog/properties.d.ts +38 -0
  11. package/dist/catalog/properties.js +52 -1
  12. package/dist/catalog/recommendations.d.ts +33 -6
  13. package/dist/catalog/recommendations.js +94 -2
  14. package/dist/catalog/reviews.d.ts +17 -4
  15. package/dist/catalog/reviews.js +7 -0
  16. package/dist/catalog/variants.d.ts +60 -0
  17. package/dist/catalog/variants.js +39 -0
  18. package/dist/catalog/visibility.d.ts +18 -2
  19. package/dist/client.d.ts +29 -3
  20. package/dist/client.js +19 -8
  21. package/dist/content/assets.d.ts +3 -4
  22. package/dist/content/forms.d.ts +332 -1
  23. package/dist/content/forms.js +140 -4
  24. package/dist/content/items.d.ts +31 -8
  25. package/dist/content/items.js +1 -1
  26. package/dist/content/menus.d.ts +254 -0
  27. package/dist/content/menus.js +70 -0
  28. package/dist/content/strings.d.ts +137 -0
  29. package/dist/content/strings.js +82 -0
  30. package/dist/customers/delivery-terms.d.ts +44 -0
  31. package/dist/customers/delivery-terms.js +32 -0
  32. package/dist/customers/groups.d.ts +16 -5
  33. package/dist/customers/groups.js +6 -2
  34. package/dist/customers/index.d.ts +15 -0
  35. package/dist/customers/index.js +4 -0
  36. package/dist/documents/emails.d.ts +154 -0
  37. package/dist/documents/emails.js +220 -0
  38. package/dist/documents/index.d.ts +13 -0
  39. package/dist/documents/index.js +2 -0
  40. package/dist/fulfillments/create.d.ts +1 -1
  41. package/dist/fulfillments/create.js +5 -2
  42. package/dist/fulfillments/index.d.ts +119 -1
  43. package/dist/fulfillments/index.js +124 -4
  44. package/dist/fulfillments/warehouse.d.ts +29 -17
  45. package/dist/fulfillments/warehouse.js +32 -1
  46. package/dist/index.d.ts +43 -23
  47. package/dist/index.js +11 -5
  48. package/dist/integrations/exact-online-types.d.ts +542 -0
  49. package/dist/integrations/exact-online.d.ts +541 -5
  50. package/dist/integrations/exact-online.js +714 -1
  51. package/dist/integrations/index.d.ts +23 -8
  52. package/dist/integrations/index.js +9 -4
  53. package/dist/integrations/pipeline-discoveries.d.ts +65 -0
  54. package/dist/integrations/pipeline-discoveries.js +65 -0
  55. package/dist/integrations/pipeline-runs.d.ts +119 -0
  56. package/dist/integrations/pipeline-runs.js +87 -0
  57. package/dist/integrations/pipelines.d.ts +73 -2
  58. package/dist/integrations/pipelines.js +36 -1
  59. package/dist/integrations/price-import.d.ts +223 -0
  60. package/dist/integrations/price-import.js +124 -0
  61. package/dist/integrations/types.d.ts +221 -3
  62. package/dist/integrations/types.js +4 -3
  63. package/dist/meta/index.d.ts +10 -0
  64. package/dist/metafields/index.d.ts +8 -1
  65. package/dist/metafields/index.js +10 -0
  66. package/dist/orders/cancel-with-money.d.ts +10 -0
  67. package/dist/orders/cancel-with-money.js +2 -0
  68. package/dist/orders/commit-edit.d.ts +16 -0
  69. package/dist/orders/commit-edit.js +14 -1
  70. package/dist/orders/deposit-policy.d.ts +3 -1
  71. package/dist/orders/index.d.ts +22 -11
  72. package/dist/orders/index.js +5 -2
  73. package/dist/orders/list.d.ts +26 -5
  74. package/dist/orders/list.js +123 -13
  75. package/dist/orders/manual-discounts.d.ts +13 -5
  76. package/dist/orders/money-view.d.ts +149 -0
  77. package/dist/orders/money-view.js +99 -0
  78. package/dist/orders/plan-edit.d.ts +34 -2
  79. package/dist/orders/plan-edit.js +110 -12
  80. package/dist/orders/surcharges.d.ts +12 -0
  81. package/dist/orders/surcharges.js +34 -9
  82. package/dist/payments/account-credit.d.ts +17 -1
  83. package/dist/payments/account-credit.js +25 -2
  84. package/dist/payments/credit-noted-fields.d.ts +8 -1
  85. package/dist/payments/credit-noted-fields.js +34 -2
  86. package/dist/payments/customer-consent.d.ts +30 -0
  87. package/dist/payments/customer-consent.js +49 -0
  88. package/dist/payments/index.d.ts +89 -14
  89. package/dist/payments/index.js +22 -2
  90. package/dist/payments/requests.d.ts +6 -3
  91. package/dist/payments/requests.js +1 -0
  92. package/dist/pickups/index.d.ts +5 -3
  93. package/dist/pickups/index.js +5 -2
  94. package/dist/platform/email-gateways.d.ts +165 -0
  95. package/dist/platform/email-gateways.js +78 -0
  96. package/dist/platform/tax.d.ts +11 -3
  97. package/dist/platform/tax.js +30 -0
  98. package/dist/pos/exchanges.d.ts +6 -1
  99. package/dist/pos/index.d.ts +229 -10
  100. package/dist/pos/index.js +113 -4
  101. package/dist/pos/offline-sales.d.ts +44 -3
  102. package/dist/pos/offline-sales.js +57 -3
  103. package/dist/pos/returns.d.ts +28 -1
  104. package/dist/pos/returns.js +36 -6
  105. package/dist/pricing/price-lists.d.ts +3 -1
  106. package/dist/purchasing/alerts.d.ts +19 -4
  107. package/dist/purchasing/alerts.js +29 -3
  108. package/dist/purchasing/backorders.d.ts +61 -0
  109. package/dist/purchasing/backorders.js +92 -0
  110. package/dist/purchasing/index.d.ts +21 -3
  111. package/dist/purchasing/index.js +8 -0
  112. package/dist/purchasing/links.d.ts +263 -0
  113. package/dist/purchasing/links.js +192 -0
  114. package/dist/purchasing/purchase-orders.d.ts +4 -1
  115. package/dist/purchasing/receipts.d.ts +396 -0
  116. package/dist/purchasing/receipts.js +287 -0
  117. package/dist/purchasing/returns.d.ts +273 -0
  118. package/dist/purchasing/returns.js +229 -0
  119. package/dist/quotes/index.d.ts +20 -3
  120. package/dist/returns/index.d.ts +62 -1
  121. package/dist/returns/index.js +61 -0
  122. package/dist/seo/config.d.ts +128 -0
  123. package/dist/seo/config.js +95 -0
  124. package/dist/seo/redirects.d.ts +125 -0
  125. package/dist/seo/redirects.js +60 -1
  126. package/dist/seo/settings.d.ts +147 -0
  127. package/dist/seo/settings.js +209 -0
  128. package/dist/shipping/index.d.ts +6 -0
  129. package/dist/shipping/index.js +2 -0
  130. package/dist/shipping/methods.d.ts +8 -1
  131. package/dist/shipping/myparcel.d.ts +415 -1
  132. package/dist/shipping/myparcel.js +291 -3
  133. package/dist/shipping/rate-tables.d.ts +149 -4
  134. package/dist/shipping/rate-tables.js +229 -23
  135. package/dist/shipping/ship-to-countries.d.ts +75 -0
  136. package/dist/shipping/ship-to-countries.js +47 -0
  137. package/dist/stock/by-location.d.ts +86 -0
  138. package/dist/stock/by-location.js +94 -0
  139. package/dist/stock/index.d.ts +8 -1
  140. package/dist/stock/index.js +4 -0
  141. package/dist/stock/settings.d.ts +106 -0
  142. package/dist/stock/settings.js +103 -0
  143. package/dist/stock/transfers.d.ts +171 -10
  144. package/dist/stock/transfers.js +82 -4
  145. package/dist/stored-value/index.d.ts +98 -7
  146. package/dist/stored-value/index.js +71 -4
  147. package/dist/tax/display-policy.d.ts +105 -0
  148. package/dist/tax/display-policy.js +84 -0
  149. package/dist/tax/index.d.ts +3 -0
  150. package/dist/tax/index.js +2 -0
  151. package/dist/tenant/email-templates.d.ts +222 -1
  152. package/dist/tenant/email-templates.js +227 -10
  153. package/package.json +2 -2
@@ -113,6 +113,12 @@ import { type PosReturnsModule } from './returns.js';
113
113
  * till makes while offline (off by default) and its limits; `offlineSales` is the manager's queue
114
114
  * of the ones the engine could not record as rung (engine sprint 45). The till's replay is its
115
115
  * own door: no method here sends one.
116
+ *
117
+ * ## Idle lock
118
+ *
119
+ * `settings.idleLock` / `setIdleLock` are after how many minutes without a cashier's touch,
120
+ * keystroke or scan the store's tills sign their cashier out (1 to 60; the tills' default of 5
121
+ * until the store chooses).
116
122
  */
117
123
  export interface PosModule {
118
124
  registers: PosRegistersModule;
@@ -388,12 +394,23 @@ export interface PosSessionApproval {
388
394
  * is no variance yet: count it with `sessions.count` (never approved as it is).
389
395
  */
390
396
  export type PosVarianceApproval = 'not_required' | 'approved' | 'pending' | 'uncounted';
397
+ /** The X report's totals: the drawer so far, with the gift cards its sales issued (engine C6). */
398
+ export interface PosXReportTotals extends PosSessionTotals {
399
+ /**
400
+ * Of which gift cards sold (engine C6): the face value of the cards the session's completed sales
401
+ * issued, a memo already inside the tenders (a liability, not sales; never subtract it from
402
+ * `net`). Absent when an engine before C6 answered: leave it out, never show it as 0.
403
+ */
404
+ giftCardsSold?: number;
405
+ /** How many gift cards those sales issued; absent like {@link giftCardsSold}. */
406
+ giftCardsSoldCount?: number;
407
+ }
391
408
  /** A mid-shift snapshot. Reading it changes nothing. */
392
409
  export interface PosXReport {
393
410
  sessionId: string;
394
411
  openingFloat: number;
395
412
  expectedCash: number;
396
- totals: PosSessionTotals;
413
+ totals: PosXReportTotals;
397
414
  movementCount: number;
398
415
  }
399
416
  export interface OpenPosSessionInput {
@@ -428,7 +445,14 @@ export interface PosSessionsModule {
428
445
  countedCash: number;
429
446
  closingCounts?: Record<string, number>;
430
447
  }, options?: PosCall): Promise<PosRegisterSession>;
431
- /** The X report: the drawer so far, read-only. */
448
+ /**
449
+ * The X report: the drawer so far, read-only, with the gift cards its sales issued
450
+ * (`totals.giftCardsSold`, engine C6). On a closed session the figures are its stored Z's. An
451
+ * engine before C6 refuses the memo at validation; the report is then read without it (the two
452
+ * memo fields absent). An id that is no session of the store is `POS_SESSION_NOT_FOUND`.
453
+ *
454
+ * @effect read
455
+ */
432
456
  xReport(sessionId: string, options?: Call): Promise<PosXReport>;
433
457
  /**
434
458
  * One session with its close's details (engine sprint 25b): who closed it, whether the store
@@ -1726,6 +1750,14 @@ export interface PosPairingCode {
1726
1750
  code: string;
1727
1751
  expiresAt: string;
1728
1752
  }
1753
+ /**
1754
+ * How long a pairing code works before a tablet claims it (`devices.pair`, engine
1755
+ * `emre/pos-reviewer-pairing`): `STANDARD` 10 minutes, `APP_REVIEW` 30 days for a store reviewer's
1756
+ * device. Either way the code is claimed once.
1757
+ */
1758
+ export type PosPairingCodeValidity = 'STANDARD' | 'APP_REVIEW';
1759
+ /** The validities a pairing code is issued with, in the engine's order. */
1760
+ export declare const POS_PAIRING_CODE_VALIDITIES: readonly PosPairingCodeValidity[];
1729
1761
  /** A new device (`devices.create`). */
1730
1762
  export interface PosDeviceCreateInput {
1731
1763
  label: string;
@@ -1852,6 +1884,14 @@ export interface PosDevicesModule {
1852
1884
  * 400 the transport reports as `BAD_REQUEST`); without it the document is the one every engine
1853
1885
  * serves.
1854
1886
  *
1887
+ * From engine `pos-device-move-refuses-open-drawer`, a move that changes the device's location
1888
+ * or register is refused `POS_DEVICE_SESSION_OPEN` (`BusinessRuleError`, the engine's sentence
1889
+ * naming the drawer's register) while the device has an open drawer: the drawer stays on the
1890
+ * register it opened on, so close it first (at the till, or `sessions.close` /
1891
+ * `sessions.closeUncounted` in the back office; {@link PosSessionsModule.openForDevice} reads
1892
+ * it). A move to where the device already stands, with its own register, still answers the
1893
+ * device. An older engine moves the device and leaves the drawer behind.
1894
+ *
1855
1895
  * @effect write
1856
1896
  */
1857
1897
  assignLocation(deviceId: string, stockLocationId: string, options?: {
@@ -1868,7 +1908,10 @@ export interface PosDevicesModule {
1868
1908
  * `pos-device-writes-validate` the device is judged first, as
1869
1909
  * {@link PosDevicesModule.assignLocation} judges it (`POS_DEVICE_NOT_FOUND`,
1870
1910
  * `LOCATION_NOT_ALLOWED` for a device at a location outside a restricted credential's,
1871
- * `POS_DEVICE_REVOKED`).
1911
+ * `POS_DEVICE_REVOKED`). From engine `pos-device-move-refuses-open-drawer`, another register
1912
+ * is refused `POS_DEVICE_SESSION_OPEN` (`BusinessRuleError`) while the device has an open
1913
+ * drawer, as {@link PosDevicesModule.assignLocation} says; the register it holds still answers
1914
+ * the device.
1872
1915
  *
1873
1916
  * @effect write
1874
1917
  */
@@ -1952,9 +1995,23 @@ export interface PosDevicesModule {
1952
1995
  * a restricted credential's, and `POS_DEVICE_CEILING_NOT_ALLOWED` to a caller that does not
1953
1996
  * hold every permission the till will carry.
1954
1997
  *
1998
+ * `validity` sets how long the code works unclaimed: `STANDARD` (10 minutes, what a call without
1999
+ * it gets) or `APP_REVIEW` (30 days), for a store reviewer who installs the app days after it
2000
+ * was submitted. Either way the code is claimed once, by one tablet, and a new code of either
2001
+ * validity replaces the device's unclaimed one. Only a platform SuperAdmin may ask for
2002
+ * `APP_REVIEW` (the demo store's tool): anyone else is refused
2003
+ * `POS_PAIRING_REVIEW_CODE_NOT_ALLOWED` (`PermissionDeniedError`) before the device is read. Without `validity` the call works against any
2004
+ * engine; with one it needs an engine with `emre/pos-reviewer-pairing`. An older engine refuses
2005
+ * the document (it does not know the argument), and the SDK raises a 400 `ValidationError`
2006
+ * (`BAD_REQUEST`). A value outside
2007
+ * `POS_PAIRING_CODE_VALIDITIES` is refused before anything is sent (`ValidationError`, code
2008
+ * `POS_PAIRING_CODE_VALIDITY_INVALID`). Show `expiresAt` in the store's time zone.
2009
+ *
1955
2010
  * @effect write
1956
2011
  */
1957
- pair(deviceId: string, options?: Call): Promise<PosPairingCode>;
2012
+ pair(deviceId: string, options?: {
2013
+ validity?: PosPairingCodeValidity;
2014
+ } & Call): Promise<PosPairingCode>;
1958
2015
  /**
1959
2016
  * Retire the device for good: its token stops working at once, its tablet's sessions end, and
1960
2017
  * it can never be paired again (add a new device to use that tablet). There is no undo.
@@ -1985,7 +2042,21 @@ export interface PosReceiptNumbering {
1985
2042
  }
1986
2043
  /** Needs `ManagePosDevices` (or `UpdateSettings`). */
1987
2044
  export interface PosReceiptNumberingModule {
2045
+ /**
2046
+ * The format the store's receipts are numbered in: its organization's while it inherits
2047
+ * `settings.numbering_formats`, else its own.
2048
+ *
2049
+ * @effect read
2050
+ */
1988
2051
  get(options?: Call): Promise<PosReceiptNumbering>;
2052
+ /**
2053
+ * Change the store's own receipt number format; an omitted field keeps its value, `digits` is
2054
+ * held to 3..8. Answers the store's own row, not the inherited format `get` reads: read again
2055
+ * after saving. A store that inherits the format is refused `ORGANIZATION_SETTINGS_INHERITED`
2056
+ * until it overrides the group, and one whose organization locks it `MANAGED_BY_ORGANIZATION`.
2057
+ *
2058
+ * @effect write
2059
+ */
1989
2060
  set(input: Partial<PosReceiptNumbering>, options?: Call): Promise<PosReceiptNumbering>;
1990
2061
  }
1991
2062
  /** A store's POS settings as the setup surfaces read them. The Mollie key itself is never returned. */
@@ -1997,6 +2068,11 @@ export interface PosSettings {
1997
2068
  /** The till's card (terminal) payment method; null = the engine's default `pos-mollie-terminal`. */
1998
2069
  cardPaymentMethodCode: string | null;
1999
2070
  inStoreShippingMethodId: string | null;
2071
+ /**
2072
+ * The fulfillment profile a till sale prefers when it sits at the till's location; null = the
2073
+ * location's own POS profile (`pos-<locationId>`), else its first enabled one.
2074
+ */
2075
+ fulfillmentProfileId: string | null;
2000
2076
  /** Pre-fills a new device's location; the engine never reads it otherwise. */
2001
2077
  defaultStockLocationId: string | null;
2002
2078
  /** `none`, `nearest_05` or `nearest_10`; a till treats any other stored value as `none`. */
@@ -2011,6 +2087,29 @@ export interface PosSettings {
2011
2087
  */
2012
2088
  maskedMollieApiKey: string | null;
2013
2089
  }
2090
+ /**
2091
+ * What `settings.update` changes: an omitted field keeps its value, `null` clears a reference
2092
+ * (the till then charges through the engine's default method, `pos-cash` / `pos-mollie-terminal`).
2093
+ * Every reference names one of the store's own records. The Mollie key and the cash rounding have
2094
+ * methods of their own (`setMollieApiKey`, `setCashRoundingMode`), and so do the receipt
2095
+ * (`setReceipt`) and the idle lock (`setIdleLock`).
2096
+ */
2097
+ export interface PosSettingsInput {
2098
+ /** Whether the store's tills may open sessions and take payments. */
2099
+ enabled?: boolean;
2100
+ /** A payment method CODE of the store, the one cash sales are recorded on. */
2101
+ cashPaymentMethodCode?: string | null;
2102
+ /** A payment method CODE of the store, the one card (terminal) sales are recorded on. */
2103
+ cardPaymentMethodCode?: string | null;
2104
+ /** A live shipping method of the store: the zero-cost "collect in store" method till sales carry. */
2105
+ inStoreShippingMethodId?: string | null;
2106
+ /** A fulfillment profile of the store a till sale prefers. */
2107
+ fulfillmentProfileId?: string | null;
2108
+ /** A stock location of the store that a new device is pre-filled with. */
2109
+ defaultStockLocationId?: string | null;
2110
+ }
2111
+ /** The fields `settings.update` sends; anything else is refused before a request is made. */
2112
+ export declare const POS_SETTINGS_INPUT_FIELDS: readonly ["enabled", "cashPaymentMethodCode", "cardPaymentMethodCode", "inStoreShippingMethodId", "fulfillmentProfileId", "defaultStockLocationId"];
2014
2113
  /** A Mollie terminal the store's till key reaches, as Mollie reports it now. */
2015
2114
  export interface PosMollieTerminal {
2016
2115
  /** `term_…`: what a device is assigned. */
@@ -2024,6 +2123,22 @@ export interface PosMollieTerminal {
2024
2123
  serialNumber: string | null;
2025
2124
  currency: string | null;
2026
2125
  }
2126
+ /**
2127
+ * A Mollie terminal pairing code for the store's till key (engine `pos-mollie-terminal-pairing`):
2128
+ * a Mollie Tap terminal (the Tap app on a phone, or a Mollie Tap device) scans `qrCodeSvg` or has
2129
+ * `code` typed in to join the key's Mollie profile. Usable more than once until it expires or is
2130
+ * revoked: `code` is a secret, never store or log it.
2131
+ */
2132
+ export interface PosMollieTerminalPairingCode {
2133
+ /** Mollie's id for the code (`termpc_…`): what {@link PosTerminalsModule.revokePairingCode} takes. */
2134
+ pairingCodeId: string;
2135
+ /** The code a person types on the terminal. */
2136
+ code: string;
2137
+ /** Mollie's QR for the code, a `data:image/svg+xml;base64,` URI to show as an image; null when Mollie sent none. */
2138
+ qrCodeSvg: string | null;
2139
+ /** ISO 8601: when Mollie stops accepting it; null when Mollie did not say. */
2140
+ expiresAt: string | null;
2141
+ }
2027
2142
  /** One thing the store's tills need before they take cash and card payments. */
2028
2143
  export interface PosSetupCheck {
2029
2144
  /** `pos_enabled`, `cash_method`, `card_method`, `mollie_key`, `card_device`, `in_store_shipping`, `default_location`, `staff`, `fulfillment_profile`; more may come. */
@@ -2079,8 +2194,35 @@ export interface PosCustomItemPolicyInput {
2079
2194
  }
2080
2195
  /** Needs `UpdateSettings` to write; `get` needs any session of the store. */
2081
2196
  export interface PosSettingsModule {
2082
- /** The store's POS settings, or null when POS was never set up. */
2197
+ /**
2198
+ * The store's POS settings, or null when POS was never set up.
2199
+ *
2200
+ * @effect read
2201
+ */
2083
2202
  get(options?: Call): Promise<PosSettings | null>;
2203
+ /**
2204
+ * Change what the store's tills sell through: POS on or off, the cash and card payment methods,
2205
+ * the in-store shipping method, the fulfillment profile and the default stock location
2206
+ * ({@link PosSettingsInput}); an omitted field keeps its value. Needs `UpdateSettings` alone: it
2207
+ * names the methods the till charges through, so `ManagePosDevices` (the till estate) is not
2208
+ * enough. A store with no POS settings yet gets them, POS off unless `enabled` says otherwise.
2209
+ *
2210
+ * Refusals: `POS_CONFIG_REFERENCE_INVALID` (400) when a reference the call CHANGES is not one of
2211
+ * the store's own records: a payment method code the store does not have, a shipping method,
2212
+ * fulfillment profile or stock location of another store or of none; `details[]` names each
2213
+ * such field as `/<field>`, and nothing is written. Another store's record and a missing one are
2214
+ * refused alike. A value sent back unchanged always passes, even one stored before the check
2215
+ * that no longer resolves. `LOCATION_NOT_ALLOWED` when a location-restricted credential names a
2216
+ * default location outside its own. `ORGANIZATION_WORKSPACE_NOT_A_STORE` when switching POS on in
2217
+ * an organization's workspace (switching it off is never refused). A field this method does not
2218
+ * know (the Mollie key, the cash rounding) is refused with a `TypeError` before anything is sent.
2219
+ *
2220
+ * Whether a method is enabled, or works with the till's cash or terminal handler, is not judged
2221
+ * here: `readiness()` reports it.
2222
+ *
2223
+ * @effect write
2224
+ */
2225
+ update(input: PosSettingsInput, options?: Call): Promise<PosSettings>;
2084
2226
  /**
2085
2227
  * Store the till's Mollie API key (encrypted at rest; never readable again). The key is trimmed;
2086
2228
  * an empty one is refused here (`TypeError`) — remove it with `removeMollieApiKey`. Sending the
@@ -2218,7 +2360,35 @@ export interface PosSettingsModule {
2218
2360
  * `UpdateSettings`. An engine before 45 refuses the document at validation.
2219
2361
  */
2220
2362
  setOfflineCashSales(input: PosOfflineCashSalesInput, options?: Call): Promise<PosOfflineCashSales>;
2221
- }
2363
+ /**
2364
+ * The store's idle lock at its tills: after how many minutes without a cashier's touch,
2365
+ * keystroke or scan a till signs its cashier out. `minutes` is the store's choice, 1 to 60, or
2366
+ * null until it chooses (its tills then lock after `POS_IDLE_LOCK_LIMITS.defaultMinutes`, 5).
2367
+ * Null when POS was never set up. Any staff session of the store reads it. Its own document: an
2368
+ * engine without the setting refuses it at validation, and every other settings read keeps
2369
+ * working.
2370
+ */
2371
+ idleLock(options?: Call): Promise<PosIdleLock | null>;
2372
+ /**
2373
+ * Set the store's idle lock: a whole number of minutes, which the engine holds to
2374
+ * `POS_IDLE_LOCK_LIMITS` (never refused: 0 is stored as 1, 90 as 60), or `null` back to the
2375
+ * tills' default. A value that is not a whole number is refused here (`TypeError`), before
2376
+ * anything is sent. It applies at each till's next sign-in. Needs `UpdateSettings`. An engine
2377
+ * without the setting refuses the document at validation.
2378
+ */
2379
+ setIdleLock(minutes: number | null, options?: Call): Promise<PosIdleLock>;
2380
+ }
2381
+ /** A store's idle lock at its tills. */
2382
+ export interface PosIdleLock {
2383
+ /** The store's choice, 1 to 60 minutes; null for the tills' default. */
2384
+ minutes: number | null;
2385
+ }
2386
+ /** The bounds the engine holds a store's idle lock to, and the tills' default. */
2387
+ export declare const POS_IDLE_LOCK_LIMITS: {
2388
+ readonly minMinutes: 1;
2389
+ readonly maxMinutes: 60;
2390
+ readonly defaultMinutes: 5;
2391
+ };
2222
2392
  /** How tax shows on a receipt (engine sprint 22). */
2223
2393
  export type PosReceiptTaxDisplay = 'INCLUSIVE' | 'EXCLUSIVE';
2224
2394
  /** The store's details as the platform holds them (what a receipt's header may print). */
@@ -2415,6 +2585,33 @@ export interface PosTerminalsModule {
2415
2585
  * operator must configure it; a non-retryable 500, Mollie not asked). Branch on the code.
2416
2586
  */
2417
2587
  list(options?: Call): Promise<Page<PosMollieTerminal>>;
2588
+ /**
2589
+ * A new Mollie pairing code, with Mollie's QR, for the profile of the store's till key (engine
2590
+ * `pos-mollie-terminal-pairing`): show it, and a Mollie Tap terminal that scans it (or has the
2591
+ * code typed in) joins the profile and appears in {@link list}, pending at first. PAX terminals
2592
+ * take no code: Mollie ships them set up. Every call makes a new code; revoke it with
2593
+ * {@link revokePairingCode} once the terminal shows up. Refusals, each carrying `.code`:
2594
+ * POS_MOLLIE_PAIRING_TEST_MODE (a `test_` key: Mollie pairs nothing in test mode, its test
2595
+ * terminal is in {@link list} already), POS_MOLLIE_PAIRING_NOT_ELIGIBLE (Mollie does not let the
2596
+ * account pair terminals yet: finish onboarding at Mollie), and the key refusals of
2597
+ * {@link list}. A person's session only: an API token is refused `TOKEN_CREDENTIAL_NOT_ALLOWED`
2598
+ * and an app installation `APP_CREDENTIAL_NOT_ALLOWED` (each a `PermissionDeniedError`), since the
2599
+ * code joins a card reader to the store's Mollie account. An engine before it fails the
2600
+ * document's validation (`GRAPHQL_VALIDATION_FAILED`, or a 400 the transport reports as
2601
+ * `BAD_REQUEST`).
2602
+ *
2603
+ * @effect write
2604
+ */
2605
+ createPairingCode(options?: Call): Promise<PosMollieTerminalPairingCode>;
2606
+ /**
2607
+ * Revoke a pairing code of the store's till key: no terminal pairs with it again, and terminals it
2608
+ * already paired keep working. A code Mollie no longer knows answers `true`. Refused
2609
+ * POS_MOLLIE_PAIRING_CODE_ID_INVALID (`ValidationError`: not a `termpc_` id) and the key
2610
+ * refusals of {@link list}.
2611
+ *
2612
+ * @effect write
2613
+ */
2614
+ revokePairingCode(pairingCodeId: string, options?: Call): Promise<boolean>;
2418
2615
  }
2419
2616
  /**
2420
2617
  * The languages a staff member's own till language may be (`en`, `nl`, `de`, `fr`); the engine's
@@ -2463,8 +2660,14 @@ export interface PosStaffUpdateInput {
2463
2660
  * manager may do all of them, whatever is stored. Closing a drawer above the store's variance
2464
2661
  * threshold is not one: it stays a manager's.
2465
2662
  */
2466
- export declare const POS_STAFF_GRANTS: readonly ["manual_price", "discount", "custom_item_over_limit", "refund", "discard_held_sale", "paid_out", "no_sale", "safe_drop", "float_adjust", "return_items", "void_sale", "no_receipt_return", "online_return"];
2663
+ export declare const POS_STAFF_GRANTS: readonly ["manual_price", "discount", "custom_item_over_limit", "refund", "discard_held_sale", "paid_out", "no_sale", "safe_drop", "float_adjust", "return_items", "void_sale", "no_receipt_return", "online_return", "manage_card_terminal", "discount_over_limit", "view_reports"];
2467
2664
  export type PosStaffGrant = (typeof POS_STAFF_GRANTS)[number];
2665
+ /**
2666
+ * The grants a staff member holds only when stored on their record, whatever their role: a manager
2667
+ * does not hold these by being one. `discount_over_limit` lets a till discount they authorise
2668
+ * (their own, or one they approve as a manager) go past the store's discount limit.
2669
+ */
2670
+ export declare const POS_EXPLICIT_STAFF_GRANTS: readonly ["discount_over_limit"];
2468
2671
  /** What one staff member may do at a till without a manager, as the store stored it. */
2469
2672
  export interface PosStaffGrants {
2470
2673
  id: string;
@@ -2555,6 +2758,14 @@ export interface PosStaffModule {
2555
2758
  * @effect write
2556
2759
  */
2557
2760
  setGrants(id: string, grants: readonly PosStaffGrant[], options?: Call): Promise<PosStaffGrants>;
2761
+ /**
2762
+ * The grants the engine this client talks to knows (its `PosStaffGrant` enum), so a caller
2763
+ * deployed ahead of the engine offers only those: `setGrants` naming one the engine lacks fails
2764
+ * GraphQL validation for the whole document. Empty for an engine with no grants at all.
2765
+ *
2766
+ * @effect read
2767
+ */
2768
+ knownGrants(options?: Call): Promise<string[]>;
2558
2769
  }
2559
2770
  export declare const POS_REGISTERS_QUERY = "query PosRegisters { posRegisters { id stockLocationId name status createdAt updatedAt } }";
2560
2771
  export declare const POS_REGISTER_QUERY = "query PosRegister($id: ID!) { posRegister(id: $id) { id stockLocationId name status createdAt updatedAt } }";
@@ -2562,7 +2773,9 @@ export declare const CREATE_POS_REGISTER_MUTATION = "mutation CreatePosRegister(
2562
2773
  export declare const UPDATE_POS_REGISTER_MUTATION = "mutation UpdatePosRegister($id: ID!, $input: UpdatePosRegisterInput!) { updatePosRegister(id: $id, input: $input) { id stockLocationId name status createdAt updatedAt } }";
2563
2774
  export declare const OPEN_POS_SESSION_MUTATION = "mutation OpenPosRegisterSession($input: OpenPosRegisterSessionInput!, $staffToken: String) { openPosRegisterSession(input: $input, staffToken: $staffToken) { id registerId deviceId openedByStaffId openingFloat status expectedCash countedCash cashOverShort totals openedAt closedAt } }";
2564
2775
  export declare const CLOSE_POS_SESSION_MUTATION = "mutation ClosePosRegisterSession($input: ClosePosRegisterSessionInput!, $staffToken: String) { closePosRegisterSession(input: $input, staffToken: $staffToken) { id registerId deviceId openedByStaffId openingFloat status expectedCash countedCash cashOverShort totals openedAt closedAt } }";
2565
- export declare const POS_X_REPORT_QUERY = "query PosXReport($sessionId: ID!) { posXReport(sessionId: $sessionId) { sessionId openingFloat expectedCash movementCount totals { cash card other refunds net saleCount } } }";
2776
+ export declare const POS_X_REPORT_QUERY = "query PosXReport($sessionId: ID!) { posXReport(sessionId: $sessionId) { sessionId openingFloat expectedCash movementCount totals { cash card other refunds net saleCount giftCardsSold giftCardsSoldCount } } }";
2777
+ /** {@link POS_X_REPORT_QUERY} for an engine before C6 (no gift-card memo), which refuses it. */
2778
+ export declare const POS_X_REPORT_QUERY_BEFORE_GIFT_CARDS = "query PosXReport($sessionId: ID!) { posXReport(sessionId: $sessionId) { sessionId openingFloat expectedCash movementCount totals { cash card other refunds net saleCount } } }";
2566
2779
  export declare const POS_SESSION_QUERY = "query PosRegisterSession($id: ID!) { posRegisterSession(id: $id) { id registerId deviceId openedByStaffId openingFloat status expectedCash countedCash cashOverShort totals openedAt closedAt } }";
2567
2780
  export declare const POS_SESSION_DETAIL_QUERY = "query PosRegisterSessionDetail($id: ID!) { posRegisterSession(id: $id) { id registerId deviceId openedByStaffId openingFloat status expectedCash countedCash cashOverShort totals openedAt closedAt closedByStaffId blindCount varianceThreshold varianceApproval varianceApprovedByStaffId varianceApprovedAt } }";
2568
2781
  export declare const POS_SESSION_APPROVAL_QUERY = "query PosRegisterSessionApproval($id: ID!) { posRegisterSession(id: $id) { id varianceApproval varianceThreshold varianceApprovedByStaffId varianceApprovedAt varianceApprovedByUserId varianceApprovedByUserName varianceApprovedByCredential varianceApprovalNote } }";
@@ -2612,6 +2825,7 @@ export declare const POS_REFUND_MUTATION = "mutation PosRefund($input: PosRefund
2612
2825
  export declare const POS_DEVICES_QUERY = "query PosDevices { posDevices { id stockLocationId registerId label status paired lastSeenAt mollieTerminalId createdAt updatedAt } }";
2613
2826
  export declare const POS_DEVICE_QUERY = "query PosDevice($id: ID!) { posDevice(id: $id) { lastSeenAt } }";
2614
2827
  export declare const POS_PAIRING_CODE_MUTATION = "mutation GeneratePosPairingCode($deviceId: ID!) { generatePosPairingCode(deviceId: $deviceId) { code expiresAt } }";
2828
+ export declare const POS_PAIRING_CODE_WITH_VALIDITY_MUTATION = "mutation GeneratePosPairingCodeWithValidity($deviceId: ID!, $validity: PosPairingCodeValidity!) { generatePosPairingCode(deviceId: $deviceId, validity: $validity) { code expiresAt } }";
2615
2829
  export declare const REVOKE_POS_DEVICE_MUTATION = "mutation RevokePosDevice($deviceId: ID!) { revokePosDevice(deviceId: $deviceId) { id stockLocationId registerId label status paired lastSeenAt mollieTerminalId createdAt updatedAt } }";
2616
2830
  export declare const POS_DEVICE_DETAIL_QUERY = "query PosDeviceDetail($id: ID!) { posDevice(id: $id) { id stockLocationId registerId label status paired lastSeenAt mollieTerminalId createdAt updatedAt } }";
2617
2831
  export declare const ASSIGN_POS_DEVICE_LOCATION_MUTATION = "mutation AssignPosDeviceLocation($deviceId: ID!, $stockLocationId: ID!) { assignPosDeviceLocation(deviceId: $deviceId, stockLocationId: $stockLocationId) { id stockLocationId registerId label status paired lastSeenAt mollieTerminalId createdAt updatedAt } }";
@@ -2627,11 +2841,15 @@ export declare const LOCK_POS_DEVICE_MUTATION = "mutation LockPosDevice($deviceI
2627
2841
  export declare const UNLOCK_POS_DEVICE_MUTATION = "mutation UnlockPosDevice($deviceId: ID!) { unlockPosDevice(deviceId: $deviceId) { id stockLocationId registerId label status paired lastSeenAt mollieTerminalId createdAt updatedAt heartbeatAt lockedAt silentSince kind } }";
2628
2842
  export declare const POS_RECEIPT_NUMBERING_QUERY = "query PosReceiptNumberingConfig { posReceiptNumberingConfig { prefix suffix digits } }";
2629
2843
  export declare const UPDATE_POS_RECEIPT_NUMBERING_MUTATION = "mutation UpdatePosReceiptNumberingConfig($input: UpdatePosReceiptNumberingConfigInput!) { updatePosReceiptNumberingConfig(input: $input) { prefix suffix digits } }";
2630
- export declare const POS_SETTINGS_QUERY = "query PosSettings { getPosConfig { enabled cashPaymentMethodCode cardPaymentMethodCode inStoreShippingMethodId defaultStockLocationId cashRoundingMode hasMollieKey maskedMollieApiKey } }";
2631
- export declare const UPDATE_POS_SETTINGS_MUTATION = "mutation UpdatePosSettings($input: UpdatePosConfigInput!) { updatePosConfig(input: $input) { enabled cashPaymentMethodCode cardPaymentMethodCode inStoreShippingMethodId defaultStockLocationId cashRoundingMode hasMollieKey maskedMollieApiKey } }";
2844
+ export declare const POS_SETTINGS_QUERY = "query PosSettings { getPosConfig { enabled cashPaymentMethodCode cardPaymentMethodCode inStoreShippingMethodId fulfillmentProfileId defaultStockLocationId cashRoundingMode hasMollieKey maskedMollieApiKey } }";
2845
+ export declare const UPDATE_POS_SETTINGS_MUTATION = "mutation UpdatePosSettings($input: UpdatePosConfigInput!) { updatePosConfig(input: $input) { enabled cashPaymentMethodCode cardPaymentMethodCode inStoreShippingMethodId fulfillmentProfileId defaultStockLocationId cashRoundingMode hasMollieKey maskedMollieApiKey } }";
2632
2846
  export declare const POS_MOLLIE_TERMINALS_QUERY = "query PosMollieTerminals { posMollieTerminals { terminalId description status brand model serialNumber currency } }";
2847
+ export declare const CREATE_POS_MOLLIE_PAIRING_CODE_MUTATION = "mutation CreatePosMollieTerminalPairingCode { createPosMollieTerminalPairingCode { pairingCodeId code qrCodeSvg expiresAt } }";
2848
+ export declare const REVOKE_POS_MOLLIE_PAIRING_CODE_MUTATION = "mutation RevokePosMollieTerminalPairingCode($pairingCodeId: String!) { revokePosMollieTerminalPairingCode(pairingCodeId: $pairingCodeId) }";
2633
2849
  export declare const POS_CASH_CONTROLS_QUERY = "query PosCashControls { getPosConfig { cashControls { blindCount varianceThreshold } } }";
2634
2850
  export declare const SET_POS_CASH_CONTROLS_MUTATION = "mutation SetPosCashControls($input: PosCashControlsInput!) { setPosCashControls(input: $input) { blindCount varianceThreshold } }";
2851
+ export declare const POS_IDLE_LOCK_QUERY = "query PosIdleLock { getPosConfig { idleLockMinutes } }";
2852
+ export declare const SET_POS_IDLE_LOCK_MUTATION = "mutation SetPosIdleLock($input: UpdatePosConfigInput!) { updatePosConfig(input: $input) { idleLockMinutes } }";
2635
2853
  export declare const POS_RECEIPT_SETTINGS_QUERY = "query PosReceiptSettings { getPosConfig { receipt { configured showStoreName showAddress showPhone showVatNumber headerLines footerLines taxDisplay identity { storeName addressLines phone vatNumber registrationNumber } } } }";
2636
2854
  export declare const SET_POS_RECEIPT_SETTINGS_MUTATION = "mutation SetPosReceiptSettings($input: PosReceiptSettingsInput!) { setPosReceiptSettings(input: $input) { configured showStoreName showAddress showPhone showVatNumber headerLines footerLines taxDisplay identity { storeName addressLines phone vatNumber registrationNumber } } }";
2637
2855
  export declare const POS_RECEIPT_PREVIEW_QUERY = "query PosReceiptPreview($input: PosReceiptSettingsInput) { posReceiptPreview(input: $input) { kind orderId orderCode receiptNumber issuedAt language locale timeZone currencyCode taxDisplay header { storeName addressLines phone vatNumber registrationNumber extraLines } cashierName registerName lines { orderLineId name sku quantity unitPrice amount taxRate discounts { kind description amount } note ships } subtotal adjustments { kind description amount } taxes { description rate base amount } total tenders { kind exchange methodName amount tendered cashRounding change } changeDue refunds { kind exchange methodName amount refundedAt } orderNote delivery { name addressLines methodName } footerLines thankYou scanCode } }";
@@ -2657,4 +2875,5 @@ export declare const SET_POS_STAFF_PIN_MUTATION = "mutation SetPosStaffPin($id:
2657
2875
  export declare const POS_STAFF_GRANTS_QUERY = "query PosStaffGrants($id: ID!) { posStaff(id: $id) { id role grants } }";
2658
2876
  export declare const POS_STAFF_GRANTS_LIST_QUERY = "query PosStaffGrantsList { posStaffList { id role grants } }";
2659
2877
  export declare const SET_POS_STAFF_GRANTS_MUTATION = "mutation SetPosStaffGrants($id: ID!, $grants: [PosStaffGrant!]!) { setPosStaffGrants(id: $id, grants: $grants) { id role grants } }";
2878
+ export declare const POS_STAFF_GRANT_VALUES_QUERY = "query PosStaffGrantValues { __type(name: \"PosStaffGrant\") { enumValues { name } } }";
2660
2879
  export declare function createPosModule(transport: Transport): PosModule;
package/dist/pos/index.js CHANGED
@@ -12,6 +12,22 @@ import { createPosReportsModule } from './reports.js';
12
12
  import { createPosReturnsModule } from './returns.js';
13
13
  /** The kinds a device is created as (engine sprint 39), in the engine's order. */
14
14
  export const POS_DEVICE_KINDS = ['till', 'display'];
15
+ /** The validities a pairing code is issued with, in the engine's order. */
16
+ export const POS_PAIRING_CODE_VALIDITIES = [
17
+ 'STANDARD',
18
+ 'APP_REVIEW',
19
+ ];
20
+ /** The fields `settings.update` sends; anything else is refused before a request is made. */
21
+ export const POS_SETTINGS_INPUT_FIELDS = [
22
+ 'enabled',
23
+ 'cashPaymentMethodCode',
24
+ 'cardPaymentMethodCode',
25
+ 'inStoreShippingMethodId',
26
+ 'fulfillmentProfileId',
27
+ 'defaultStockLocationId',
28
+ ];
29
+ /** The bounds the engine holds a store's idle lock to, and the tills' default. */
30
+ export const POS_IDLE_LOCK_LIMITS = { minMinutes: 1, maxMinutes: 60, defaultMinutes: 5 };
15
31
  /**
16
32
  * The languages a staff member's own till language may be (`en`, `nl`, `de`, `fr`); the engine's
17
33
  * list, which a value outside it is refused against. The till speaks a language only once its
@@ -40,6 +56,23 @@ export const POS_STAFF_GRANTS = [
40
56
  'no_receipt_return',
41
57
  // Engine C3/34: a webshop order returned at the till, refunded to its online payment.
42
58
  'online_return',
59
+ // Engine pos-mollie-terminal-pairing: the till's own card terminal (assign, clear, pair a new
60
+ // Mollie Tap terminal from the till).
61
+ 'manage_card_terminal',
62
+ // Engine pos-cart-integrity: a till discount past the store limit. EXPLICIT: a manager holds it
63
+ // only when stored, like a cashier (see POS_EXPLICIT_STAFF_GRANTS).
64
+ 'discount_over_limit',
65
+ // Engine POS programme PR 15: the money figures of the till day report (its Reports tab);
66
+ // without it a cashier sees the counts of the day only. A manager holds it by role.
67
+ 'view_reports',
68
+ ];
69
+ /**
70
+ * The grants a staff member holds only when stored on their record, whatever their role: a manager
71
+ * does not hold these by being one. `discount_over_limit` lets a till discount they authorise
72
+ * (their own, or one they approve as a manager) go past the store's discount limit.
73
+ */
74
+ export const POS_EXPLICIT_STAFF_GRANTS = [
75
+ 'discount_over_limit',
43
76
  ];
44
77
  const REGISTER_FIELDS = 'id stockLocationId name status createdAt updatedAt';
45
78
  // The X report selects only fields every engine answers; per-tender refunds come with the stored Z.
@@ -61,7 +94,9 @@ export const CREATE_POS_REGISTER_MUTATION = `mutation CreatePosRegister($input:
61
94
  export const UPDATE_POS_REGISTER_MUTATION = `mutation UpdatePosRegister($id: ID!, $input: UpdatePosRegisterInput!) { updatePosRegister(id: $id, input: $input) { ${REGISTER_FIELDS} } }`;
62
95
  export const OPEN_POS_SESSION_MUTATION = `mutation OpenPosRegisterSession($input: OpenPosRegisterSessionInput!, $staffToken: String) { openPosRegisterSession(input: $input, staffToken: $staffToken) { ${SESSION_FIELDS} } }`;
63
96
  export const CLOSE_POS_SESSION_MUTATION = `mutation ClosePosRegisterSession($input: ClosePosRegisterSessionInput!, $staffToken: String) { closePosRegisterSession(input: $input, staffToken: $staffToken) { ${SESSION_FIELDS} } }`;
64
- export const POS_X_REPORT_QUERY = `query PosXReport($sessionId: ID!) { posXReport(sessionId: $sessionId) { sessionId openingFloat expectedCash movementCount totals { ${TOTALS} } } }`;
97
+ export const POS_X_REPORT_QUERY = `query PosXReport($sessionId: ID!) { posXReport(sessionId: $sessionId) { sessionId openingFloat expectedCash movementCount totals { ${TOTALS} giftCardsSold giftCardsSoldCount } } }`;
98
+ /** {@link POS_X_REPORT_QUERY} for an engine before C6 (no gift-card memo), which refuses it. */
99
+ export const POS_X_REPORT_QUERY_BEFORE_GIFT_CARDS = `query PosXReport($sessionId: ID!) { posXReport(sessionId: $sessionId) { sessionId openingFloat expectedCash movementCount totals { ${TOTALS} } } }`;
65
100
  export const POS_SESSION_QUERY = `query PosRegisterSession($id: ID!) { posRegisterSession(id: $id) { ${SESSION_FIELDS} } }`;
66
101
  // Engine sprint 25b; an older engine refuses the document at validation.
67
102
  export const POS_SESSION_DETAIL_QUERY = `query PosRegisterSessionDetail($id: ID!) { posRegisterSession(id: $id) { ${SESSION_FIELDS} ${SESSION_CLOSE_FIELDS} } }`;
@@ -139,6 +174,9 @@ export const POS_REFUND_MUTATION = `mutation PosRefund($input: PosRefundInput!,
139
174
  export const POS_DEVICES_QUERY = `query PosDevices { posDevices { ${DEVICE_FIELDS} } }`;
140
175
  export const POS_DEVICE_QUERY = `query PosDevice($id: ID!) { posDevice(id: $id) { lastSeenAt } }`;
141
176
  export const POS_PAIRING_CODE_MUTATION = `mutation GeneratePosPairingCode($deviceId: ID!) { generatePosPairingCode(deviceId: $deviceId) { code expiresAt } }`;
177
+ // Engine `emre/pos-reviewer-pairing`: a code that names its validity. Only this document names the
178
+ // argument, so an older engine refuses it alone and `pair` without a validity keeps working there.
179
+ export const POS_PAIRING_CODE_WITH_VALIDITY_MUTATION = `mutation GeneratePosPairingCodeWithValidity($deviceId: ID!, $validity: PosPairingCodeValidity!) { generatePosPairingCode(deviceId: $deviceId, validity: $validity) { code expiresAt } }`;
142
180
  export const REVOKE_POS_DEVICE_MUTATION = `mutation RevokePosDevice($deviceId: ID!) { revokePosDevice(deviceId: $deviceId) { ${DEVICE_FIELDS} } }`;
143
181
  // The device's own read and its three assignments: Admin API doors every deployed engine serves.
144
182
  // Like `list` and `revoke`, they select no kind or health column (`fleet` reads those).
@@ -166,13 +204,19 @@ export const LOCK_POS_DEVICE_MUTATION = `mutation LockPosDevice($deviceId: ID!)
166
204
  export const UNLOCK_POS_DEVICE_MUTATION = `mutation UnlockPosDevice($deviceId: ID!) { unlockPosDevice(deviceId: $deviceId) { ${DEVICE_FIELDS} ${DEVICE_HEALTH_FIELDS} } }`;
167
205
  export const POS_RECEIPT_NUMBERING_QUERY = `query PosReceiptNumberingConfig { posReceiptNumberingConfig { prefix suffix digits } }`;
168
206
  export const UPDATE_POS_RECEIPT_NUMBERING_MUTATION = `mutation UpdatePosReceiptNumberingConfig($input: UpdatePosReceiptNumberingConfigInput!) { updatePosReceiptNumberingConfig(input: $input) { prefix suffix digits } }`;
169
- const SETTINGS_FIELDS = 'enabled cashPaymentMethodCode cardPaymentMethodCode inStoreShippingMethodId defaultStockLocationId cashRoundingMode hasMollieKey maskedMollieApiKey';
207
+ const SETTINGS_FIELDS = 'enabled cashPaymentMethodCode cardPaymentMethodCode inStoreShippingMethodId fulfillmentProfileId defaultStockLocationId cashRoundingMode hasMollieKey maskedMollieApiKey';
170
208
  export const POS_SETTINGS_QUERY = `query PosSettings { getPosConfig { ${SETTINGS_FIELDS} } }`;
171
209
  export const UPDATE_POS_SETTINGS_MUTATION = `mutation UpdatePosSettings($input: UpdatePosConfigInput!) { updatePosConfig(input: $input) { ${SETTINGS_FIELDS} } }`;
172
210
  export const POS_MOLLIE_TERMINALS_QUERY = `query PosMollieTerminals { posMollieTerminals { terminalId description status brand model serialNumber currency } }`;
211
+ // Engine `pos-mollie-terminal-pairing`; an older engine refuses both documents at validation.
212
+ export const CREATE_POS_MOLLIE_PAIRING_CODE_MUTATION = `mutation CreatePosMollieTerminalPairingCode { createPosMollieTerminalPairingCode { pairingCodeId code qrCodeSvg expiresAt } }`;
213
+ export const REVOKE_POS_MOLLIE_PAIRING_CODE_MUTATION = `mutation RevokePosMollieTerminalPairingCode($pairingCodeId: String!) { revokePosMollieTerminalPairingCode(pairingCodeId: $pairingCodeId) }`;
173
214
  // Engine sprint 25b; an older engine refuses both documents at validation.
174
215
  export const POS_CASH_CONTROLS_QUERY = `query PosCashControls { getPosConfig { cashControls { blindCount varianceThreshold } } }`;
175
216
  export const SET_POS_CASH_CONTROLS_MUTATION = `mutation SetPosCashControls($input: PosCashControlsInput!) { setPosCashControls(input: $input) { blindCount varianceThreshold } }`;
217
+ // The store's idle lock (POS polish programme PR 2); an older engine refuses both at validation.
218
+ export const POS_IDLE_LOCK_QUERY = `query PosIdleLock { getPosConfig { idleLockMinutes } }`;
219
+ export const SET_POS_IDLE_LOCK_MUTATION = `mutation SetPosIdleLock($input: UpdatePosConfigInput!) { updatePosConfig(input: $input) { idleLockMinutes } }`;
176
220
  // Engine sprint 22 (the receipt's tender and refund `exchange`, its lines' `ships` and its `delivery`:
177
221
  // engine C3); an older engine refuses each document at validation.
178
222
  const RECEIPT_SETTINGS_FIELDS = 'configured showStoreName showAddress showPhone showVatNumber headerLines footerLines taxDisplay identity { storeName addressLines phone vatNumber registrationNumber }';
@@ -217,6 +261,8 @@ const STAFF_GRANTS_FIELDS = 'id role grants';
217
261
  export const POS_STAFF_GRANTS_QUERY = `query PosStaffGrants($id: ID!) { posStaff(id: $id) { ${STAFF_GRANTS_FIELDS} } }`;
218
262
  export const POS_STAFF_GRANTS_LIST_QUERY = `query PosStaffGrantsList { posStaffList { ${STAFF_GRANTS_FIELDS} } }`;
219
263
  export const SET_POS_STAFF_GRANTS_MUTATION = `mutation SetPosStaffGrants($id: ID!, $grants: [PosStaffGrant!]!) { setPosStaffGrants(id: $id, grants: $grants) { ${STAFF_GRANTS_FIELDS} } }`;
264
+ // The engine's own list of grants, read by introspection: any engine answers it (null type, none).
265
+ export const POS_STAFF_GRANT_VALUES_QUERY = `query PosStaffGrantValues { __type(name: "PosStaffGrant") { enumValues { name } } }`;
220
266
  const DEVICE_KIND_INVALID = 'POS_DEVICE_KIND_INVALID';
221
267
  /** A kind outside {@link POS_DEVICE_KINDS}, refused before sending, as the engine refuses it. */
222
268
  function deviceKindRefusal(kind) {
@@ -229,6 +275,18 @@ function deviceKindRefusal(kind) {
229
275
  details: [{ field: 'kind', code: DEVICE_KIND_INVALID, message }],
230
276
  });
231
277
  }
278
+ const PAIRING_CODE_VALIDITY_INVALID = 'POS_PAIRING_CODE_VALIDITY_INVALID';
279
+ /** A validity outside {@link POS_PAIRING_CODE_VALIDITIES}, refused before sending. */
280
+ function pairingValidityRefusal(validity) {
281
+ const message = `A pairing code is ${POS_PAIRING_CODE_VALIDITIES.join(' or ')}, not "${String(validity).slice(0, 40)}".`;
282
+ return new ValidationError({
283
+ code: PAIRING_CODE_VALIDITY_INVALID,
284
+ message,
285
+ status: 400,
286
+ service: 'vendure',
287
+ details: [{ field: 'validity', code: PAIRING_CODE_VALIDITY_INVALID, message }],
288
+ });
289
+ }
232
290
  const LOCALE_UNSUPPORTED = 'POS_LOCALE_UNSUPPORTED';
233
291
  const LOCALE_UNSUPPORTED_MESSAGE = `A staff language must be one of ${POS_STAFF_LOCALES.join(', ')}, or null to follow the store.`;
234
292
  function localeRefusal(message) {
@@ -424,7 +482,17 @@ export function createPosModule(transport) {
424
482
  return toSession(data.closePosRegisterSession);
425
483
  },
426
484
  async xReport(sessionId, options) {
427
- const data = await gql(POS_X_REPORT_QUERY, { sessionId }, options);
485
+ try {
486
+ const data = await gql(POS_X_REPORT_QUERY, { sessionId }, options);
487
+ return data.posXReport;
488
+ }
489
+ catch (error) {
490
+ // An engine before C6 knows no gift-card memo: the report without it. Anything else
491
+ // (a missing session, a refusal, a transient failure) is the read's own.
492
+ if (!isUnknownFieldRejection(error))
493
+ throw error;
494
+ }
495
+ const data = await gql(POS_X_REPORT_QUERY_BEFORE_GIFT_CARDS, { sessionId }, options);
428
496
  return data.posXReport;
429
497
  },
430
498
  async get(sessionId, options) {
@@ -748,7 +816,15 @@ export function createPosModule(transport) {
748
816
  return data.createPosDevice;
749
817
  },
750
818
  async pair(deviceId, options) {
751
- const data = await gql(POS_PAIRING_CODE_MUTATION, { deviceId }, options);
819
+ const validity = options?.validity;
820
+ if (validity === undefined || validity === null) {
821
+ const data = await gql(POS_PAIRING_CODE_MUTATION, { deviceId }, options);
822
+ return data.generatePosPairingCode;
823
+ }
824
+ if (!POS_PAIRING_CODE_VALIDITIES.includes(validity)) {
825
+ throw pairingValidityRefusal(validity);
826
+ }
827
+ const data = await gql(POS_PAIRING_CODE_WITH_VALIDITY_MUTATION, { deviceId, validity }, options);
752
828
  return data.generatePosPairingCode;
753
829
  },
754
830
  async revoke(deviceId, options) {
@@ -790,6 +866,16 @@ export function createPosModule(transport) {
790
866
  const data = await gql(POS_SETTINGS_QUERY, {}, options);
791
867
  return data.getPosConfig;
792
868
  },
869
+ async update(input, options) {
870
+ const known = POS_SETTINGS_INPUT_FIELDS;
871
+ // Names the field, never its value: a Mollie key sent here must not reach a log.
872
+ const unknown = Object.keys(input).filter((field) => !known.includes(field));
873
+ if (unknown.length > 0) {
874
+ throw new TypeError(`settings.update does not change ${unknown.join(', ')}: use setMollieApiKey, setCashRoundingMode, setReceipt or setIdleLock.`);
875
+ }
876
+ const data = await gql(UPDATE_POS_SETTINGS_MUTATION, { input: { ...input } }, options);
877
+ return data.updatePosConfig;
878
+ },
793
879
  async setMollieApiKey(apiKey, options) {
794
880
  const key = apiKey.trim();
795
881
  if (key === '') {
@@ -877,12 +963,31 @@ export function createPosModule(transport) {
877
963
  async setOfflineCashSales(input, options) {
878
964
  return writeOfflineCashSales(transport, input, options);
879
965
  },
966
+ async idleLock(options) {
967
+ const data = await gql(POS_IDLE_LOCK_QUERY, {}, options);
968
+ return data.getPosConfig ? { minutes: data.getPosConfig.idleLockMinutes ?? null } : null;
969
+ },
970
+ async setIdleLock(minutes, options) {
971
+ if (minutes !== null && !Number.isInteger(minutes)) {
972
+ throw new TypeError('setIdleLock needs a whole number of minutes, or null.');
973
+ }
974
+ const data = await gql(SET_POS_IDLE_LOCK_MUTATION, { input: { idleLockMinutes: minutes } }, options);
975
+ return { minutes: data.updatePosConfig.idleLockMinutes ?? null };
976
+ },
880
977
  },
881
978
  terminals: {
882
979
  async list(options) {
883
980
  const data = await gql(POS_MOLLIE_TERMINALS_QUERY, {}, options);
884
981
  return wholeList(data.posMollieTerminals);
885
982
  },
983
+ async createPairingCode(options) {
984
+ const data = await gql(CREATE_POS_MOLLIE_PAIRING_CODE_MUTATION, {}, options);
985
+ return data.createPosMollieTerminalPairingCode;
986
+ },
987
+ async revokePairingCode(pairingCodeId, options) {
988
+ const data = await gql(REVOKE_POS_MOLLIE_PAIRING_CODE_MUTATION, { pairingCodeId }, options);
989
+ return data.revokePosMollieTerminalPairingCode;
990
+ },
886
991
  },
887
992
  staff: {
888
993
  async list(options) {
@@ -928,6 +1033,10 @@ export function createPosModule(transport) {
928
1033
  const data = await gql(SET_POS_STAFF_GRANTS_MUTATION, { id, grants: [...grants] }, options);
929
1034
  return data.setPosStaffGrants;
930
1035
  },
1036
+ async knownGrants(options) {
1037
+ const data = await gql(POS_STAFF_GRANT_VALUES_QUERY, {}, options);
1038
+ return (data.__type?.enumValues ?? []).map((value) => value.name);
1039
+ },
931
1040
  },
932
1041
  quickKeys: createPosQuickKeysModule(transport),
933
1042
  returns: createPosReturnsModule(transport),