@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.
- package/README.md +5772 -118
- package/dist/auth/index.d.ts +7 -1
- package/dist/auth/index.js +8 -1
- package/dist/catalog/assets.d.ts +120 -8
- package/dist/catalog/assets.js +98 -12
- package/dist/catalog/collections.d.ts +279 -14
- package/dist/catalog/collections.js +246 -15
- package/dist/catalog/documents.d.ts +142 -0
- package/dist/catalog/documents.js +114 -0
- package/dist/catalog/index.d.ts +54 -6
- package/dist/catalog/index.js +10 -1
- package/dist/catalog/metadata.d.ts +244 -0
- package/dist/catalog/metadata.js +220 -0
- package/dist/catalog/products.d.ts +159 -19
- package/dist/catalog/products.js +88 -13
- package/dist/catalog/properties.d.ts +140 -14
- package/dist/catalog/properties.js +65 -1
- package/dist/catalog/recommendations.d.ts +288 -0
- package/dist/catalog/recommendations.js +237 -0
- package/dist/catalog/reviews.d.ts +381 -0
- package/dist/catalog/reviews.js +325 -0
- package/dist/catalog/types.d.ts +17 -1
- package/dist/catalog/types.js +10 -0
- package/dist/catalog/variant-find.d.ts +136 -0
- package/dist/catalog/variant-find.js +239 -0
- package/dist/catalog/variants.d.ts +293 -26
- package/dist/catalog/variants.js +164 -7
- package/dist/catalog/visibility.d.ts +38 -7
- package/dist/catalog/visibility.js +19 -1
- package/dist/client.d.ts +121 -9
- package/dist/client.js +53 -14
- package/dist/content/assets.d.ts +285 -0
- package/dist/content/assets.js +181 -0
- package/dist/content/forms.d.ts +332 -1
- package/dist/content/forms.js +140 -4
- package/dist/content/items.d.ts +292 -0
- package/dist/content/items.js +170 -0
- package/dist/content/menus.d.ts +254 -0
- package/dist/content/menus.js +70 -0
- package/dist/content/strings.d.ts +137 -0
- package/dist/content/strings.js +82 -0
- package/dist/content/types.d.ts +282 -0
- package/dist/content/types.js +100 -0
- package/dist/customers/age-verification.d.ts +66 -0
- package/dist/customers/age-verification.js +79 -0
- package/dist/customers/credit.d.ts +263 -0
- package/dist/customers/credit.js +244 -0
- package/dist/customers/delivery-preferences.d.ts +120 -0
- package/dist/customers/delivery-preferences.js +97 -0
- package/dist/customers/delivery-terms.d.ts +44 -0
- package/dist/customers/delivery-terms.js +32 -0
- package/dist/customers/groups.d.ts +207 -0
- package/dist/customers/groups.js +438 -0
- package/dist/customers/index.d.ts +462 -37
- package/dist/customers/index.js +317 -40
- package/dist/customers/invitation-status.d.ts +57 -0
- package/dist/customers/invitation-status.js +21 -0
- package/dist/customers/notes.d.ts +67 -0
- package/dist/customers/notes.js +51 -0
- package/dist/customers/notification-recipients.d.ts +97 -0
- package/dist/customers/notification-recipients.js +84 -0
- package/dist/customers/saved-lists.d.ts +42 -0
- package/dist/customers/saved-lists.js +61 -0
- package/dist/customers/vat.d.ts +83 -0
- package/dist/customers/vat.js +46 -0
- package/dist/customers/wire.d.ts +20 -0
- package/dist/customers/wire.js +35 -0
- package/dist/documents/ar.d.ts +307 -0
- package/dist/documents/ar.js +254 -0
- package/dist/documents/emails.d.ts +150 -0
- package/dist/documents/emails.js +220 -0
- package/dist/documents/index.d.ts +744 -21
- package/dist/documents/index.js +438 -24
- package/dist/documents/pdf.d.ts +2 -0
- package/dist/documents/pdf.js +11 -0
- package/dist/fulfillments/create.d.ts +167 -0
- package/dist/fulfillments/create.js +216 -0
- package/dist/fulfillments/index.d.ts +163 -11
- package/dist/fulfillments/index.js +135 -6
- package/dist/fulfillments/payment-policy.d.ts +64 -0
- package/dist/fulfillments/payment-policy.js +140 -0
- package/dist/fulfillments/warehouse.d.ts +724 -0
- package/dist/fulfillments/warehouse.js +914 -0
- package/dist/geo/index.d.ts +119 -0
- package/dist/geo/index.js +107 -0
- package/dist/index.d.ts +147 -39
- package/dist/index.js +51 -12
- package/dist/integrations/afas-actions.d.ts +234 -0
- package/dist/integrations/afas-actions.js +310 -0
- package/dist/integrations/afas-types.d.ts +483 -0
- package/dist/integrations/afas-types.js +5 -0
- package/dist/integrations/afas.d.ts +234 -0
- package/dist/integrations/afas.js +290 -0
- package/dist/integrations/connections.d.ts +103 -0
- package/dist/integrations/connections.js +55 -0
- package/dist/integrations/esp.d.ts +313 -0
- package/dist/integrations/esp.js +169 -0
- package/dist/integrations/exact-online-types.d.ts +965 -0
- package/dist/integrations/exact-online-types.js +6 -0
- package/dist/integrations/exact-online.d.ts +784 -0
- package/dist/integrations/exact-online.js +1089 -0
- package/dist/integrations/index.d.ts +44 -3
- package/dist/integrations/index.js +23 -3
- package/dist/integrations/pipeline-discoveries.d.ts +65 -0
- package/dist/integrations/pipeline-discoveries.js +65 -0
- package/dist/integrations/pipeline-keys.d.ts +13 -0
- package/dist/integrations/pipeline-keys.js +22 -0
- package/dist/integrations/pipeline-runs.d.ts +119 -0
- package/dist/integrations/pipeline-runs.js +87 -0
- package/dist/integrations/pipelines.d.ts +87 -15
- package/dist/integrations/pipelines.js +41 -22
- package/dist/integrations/price-import.d.ts +223 -0
- package/dist/integrations/price-import.js +124 -0
- package/dist/integrations/types.d.ts +367 -3
- package/dist/integrations/types.js +4 -3
- package/dist/locations/index.d.ts +66 -0
- package/dist/locations/index.js +31 -0
- package/dist/meta/index.d.ts +172 -0
- package/dist/metafields/index.d.ts +8 -1
- package/dist/metafields/index.js +10 -0
- package/dist/orders/cancel-with-money.d.ts +237 -0
- package/dist/orders/cancel-with-money.js +155 -0
- package/dist/orders/commit-edit.d.ts +23 -1
- package/dist/orders/commit-edit.js +19 -2
- package/dist/orders/deposit-policy.d.ts +3 -1
- package/dist/orders/drafts.d.ts +800 -0
- package/dist/orders/drafts.js +771 -0
- package/dist/orders/fields.d.ts +245 -0
- package/dist/orders/fields.js +188 -0
- package/dist/orders/get.d.ts +29 -19
- package/dist/orders/get.js +17 -8
- package/dist/orders/index.d.ts +66 -15
- package/dist/orders/index.js +25 -2
- package/dist/orders/lifecycle.d.ts +128 -0
- package/dist/orders/lifecycle.js +158 -0
- package/dist/orders/line-price-preview.d.ts +7 -2
- package/dist/orders/list.d.ts +243 -0
- package/dist/orders/list.js +487 -0
- package/dist/orders/manual-discounts.d.ts +13 -5
- package/dist/orders/manual-pricing.d.ts +5 -0
- package/dist/orders/money-view.d.ts +149 -0
- package/dist/orders/money-view.js +99 -0
- package/dist/orders/order-entry.d.ts +20 -7
- package/dist/orders/plan-edit.d.ts +34 -2
- package/dist/orders/plan-edit.js +112 -11
- package/dist/orders/settings.d.ts +201 -0
- package/dist/orders/settings.js +325 -0
- package/dist/orders/status.d.ts +159 -13
- package/dist/orders/status.js +21 -0
- package/dist/orders/surcharges.d.ts +20 -1
- package/dist/orders/surcharges.js +37 -11
- package/dist/payments/account-credit.d.ts +46 -0
- package/dist/payments/account-credit.js +42 -0
- package/dist/payments/ar.d.ts +292 -0
- package/dist/payments/ar.js +223 -0
- package/dist/payments/connected-account.d.ts +47 -0
- package/dist/payments/connected-account.js +61 -0
- package/dist/payments/credit-noted-fields.d.ts +19 -0
- package/dist/payments/credit-noted-fields.js +69 -0
- package/dist/payments/customer-consent.d.ts +30 -0
- package/dist/payments/customer-consent.js +49 -0
- package/dist/payments/index.d.ts +340 -19
- package/dist/payments/index.js +151 -1
- package/dist/payments/methods.d.ts +303 -8
- package/dist/payments/methods.js +337 -7
- package/dist/payments/mollie-methods.d.ts +159 -0
- package/dist/payments/mollie-methods.js +141 -0
- package/dist/payments/payment-links.d.ts +180 -0
- package/dist/payments/payment-links.js +97 -0
- package/dist/payments/provider-keys.d.ts +150 -0
- package/dist/payments/provider-keys.js +118 -0
- package/dist/payments/providers.d.ts +86 -11
- package/dist/payments/providers.js +29 -0
- package/dist/payments/requests.d.ts +147 -0
- package/dist/payments/requests.js +93 -0
- package/dist/payments/store-credit-fields.d.ts +15 -0
- package/dist/payments/store-credit-fields.js +51 -0
- package/dist/pickups/index.d.ts +106 -0
- package/dist/pickups/index.js +108 -0
- package/dist/platform/channels.d.ts +132 -0
- package/dist/platform/channels.js +128 -0
- package/dist/platform/email-gateways.d.ts +165 -0
- package/dist/platform/email-gateways.js +78 -0
- package/dist/platform/geo.d.ts +123 -0
- package/dist/platform/geo.js +144 -0
- package/dist/platform/tax.d.ts +162 -0
- package/dist/platform/tax.js +169 -0
- package/dist/pos/anomalies.d.ts +158 -0
- package/dist/pos/anomalies.js +64 -0
- package/dist/pos/assisted-selling.d.ts +79 -0
- package/dist/pos/assisted-selling.js +38 -0
- package/dist/pos/exchanges.d.ts +108 -0
- package/dist/pos/exchanges.js +22 -0
- package/dist/pos/gift-cards.d.ts +135 -0
- package/dist/pos/gift-cards.js +47 -0
- package/dist/pos/index.d.ts +2370 -58
- package/dist/pos/index.js +854 -7
- package/dist/pos/no-receipt.d.ts +94 -0
- package/dist/pos/no-receipt.js +25 -0
- package/dist/pos/offline-sales.d.ts +228 -0
- package/dist/pos/offline-sales.js +170 -0
- package/dist/pos/pay-by-link.d.ts +143 -0
- package/dist/pos/pay-by-link.js +57 -0
- package/dist/pos/quick-keys.d.ts +103 -0
- package/dist/pos/quick-keys.js +45 -0
- package/dist/pos/reports.d.ts +360 -0
- package/dist/pos/reports.js +62 -0
- package/dist/pos/returns.d.ts +244 -0
- package/dist/pos/returns.js +83 -0
- package/dist/pricing/bulk-coupons.d.ts +139 -0
- package/dist/pricing/bulk-coupons.js +112 -0
- package/dist/pricing/index.d.ts +174 -4
- package/dist/pricing/index.js +174 -1
- package/dist/pricing/price-lists.d.ts +606 -0
- package/dist/pricing/price-lists.js +600 -0
- package/dist/purchasing/alerts.d.ts +104 -0
- package/dist/purchasing/alerts.js +88 -0
- package/dist/purchasing/backorders.d.ts +61 -0
- package/dist/purchasing/backorders.js +92 -0
- package/dist/purchasing/cost.d.ts +110 -0
- package/dist/purchasing/cost.js +86 -0
- package/dist/purchasing/index.d.ts +54 -0
- package/dist/purchasing/index.js +24 -0
- package/dist/purchasing/links.d.ts +263 -0
- package/dist/purchasing/links.js +192 -0
- package/dist/purchasing/purchase-orders.d.ts +551 -0
- package/dist/purchasing/purchase-orders.js +491 -0
- package/dist/purchasing/receipts.d.ts +396 -0
- package/dist/purchasing/receipts.js +287 -0
- package/dist/purchasing/replenishment.d.ts +281 -0
- package/dist/purchasing/replenishment.js +240 -0
- package/dist/purchasing/returns.d.ts +273 -0
- package/dist/purchasing/returns.js +229 -0
- package/dist/purchasing/settings.d.ts +152 -0
- package/dist/purchasing/settings.js +181 -0
- package/dist/purchasing/suppliers.d.ts +476 -0
- package/dist/purchasing/suppliers.js +438 -0
- package/dist/quotes/index.d.ts +518 -0
- package/dist/quotes/index.js +439 -0
- package/dist/reports/index.d.ts +71 -8
- package/dist/reports/index.js +74 -11
- package/dist/returns/index.d.ts +675 -21
- package/dist/returns/index.js +756 -11
- package/dist/search/index.d.ts +76 -1
- package/dist/search/index.js +63 -0
- package/dist/seo/config.d.ts +128 -0
- package/dist/seo/config.js +95 -0
- package/dist/seo/redirects.d.ts +125 -0
- package/dist/seo/redirects.js +60 -1
- package/dist/seo/settings.d.ts +147 -0
- package/dist/seo/settings.js +209 -0
- package/dist/shipping/definitions.d.ts +29 -0
- package/dist/shipping/definitions.js +47 -0
- package/dist/shipping/fulfillment-profiles.d.ts +174 -0
- package/dist/shipping/fulfillment-profiles.js +104 -0
- package/dist/shipping/hendriks.d.ts +97 -0
- package/dist/shipping/hendriks.js +50 -0
- package/dist/shipping/index.d.ts +54 -0
- package/dist/shipping/index.js +27 -0
- package/dist/shipping/methods.d.ts +205 -0
- package/dist/shipping/methods.js +240 -0
- package/dist/shipping/myparcel.d.ts +668 -0
- package/dist/shipping/myparcel.js +466 -0
- package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
- package/dist/shipping/parcel-rule.d.ts +6 -5
- package/dist/shipping/parcel-rule.js +21 -23
- package/dist/shipping/rate-tables.d.ts +324 -0
- package/dist/shipping/rate-tables.js +390 -0
- package/dist/shipping/ship-to-countries.d.ts +75 -0
- package/dist/shipping/ship-to-countries.js +47 -0
- package/dist/stock/by-location.d.ts +86 -0
- package/dist/stock/by-location.js +94 -0
- package/dist/stock/index.d.ts +18 -4
- package/dist/stock/index.js +7 -0
- package/dist/stock/locations.d.ts +144 -0
- package/dist/stock/locations.js +168 -0
- package/dist/stock/settings.d.ts +106 -0
- package/dist/stock/settings.js +103 -0
- package/dist/stock/transfers.d.ts +386 -52
- package/dist/stock/transfers.js +222 -17
- package/dist/stored-value/index.d.ts +312 -11
- package/dist/stored-value/index.js +223 -4
- package/dist/subscriptions/index.d.ts +682 -0
- package/dist/subscriptions/index.js +815 -0
- package/dist/tax/display-policy.d.ts +105 -0
- package/dist/tax/display-policy.js +84 -0
- package/dist/tax/index.d.ts +79 -1
- package/dist/tax/index.js +52 -0
- package/dist/tenant/email-style.d.ts +102 -0
- package/dist/tenant/email-style.js +72 -0
- package/dist/tenant/email-templates.d.ts +287 -0
- package/dist/tenant/email-templates.js +271 -0
- package/dist/tenant/notifications.d.ts +23 -17
- package/dist/tenant/settings-sources.d.ts +1 -1
- package/dist/tenant/time-zone.d.ts +17 -0
- package/dist/tenant/time-zone.js +11 -0
- package/dist/types.d.ts +50 -3
- package/dist/users/index.d.ts +3 -0
- package/dist/users/index.js +2 -0
- package/dist/users/warehouses.d.ts +50 -0
- package/dist/users/warehouses.js +51 -0
- package/package.json +2 -2
package/dist/pos/index.js
CHANGED
|
@@ -1,26 +1,170 @@
|
|
|
1
|
-
import { createPage } from '@sixtyninecommerce/core';
|
|
1
|
+
import { createPage, pageFromVendureList, readOffsetCursor, ValidationError, } from '@sixtyninecommerce/core';
|
|
2
|
+
import { redactionWatcher } from '../customer-data-redaction.js';
|
|
3
|
+
import { createPosAnomaliesModule } from './anomalies.js';
|
|
4
|
+
import { createPosAssistedSellingModule, } from './assisted-selling.js';
|
|
5
|
+
import { createPosExchangesModule } from './exchanges.js';
|
|
6
|
+
import { createPosGiftCardsModule } from './gift-cards.js';
|
|
7
|
+
import { createPosNoReceiptModule } from './no-receipt.js';
|
|
8
|
+
import { createPosOfflineSalesModule, readOfflineCashSales, readOfflineSalesToReview, writeOfflineCashSales, } from './offline-sales.js';
|
|
9
|
+
import { createPosPayByLinkModule } from './pay-by-link.js';
|
|
10
|
+
import { createPosQuickKeysModule } from './quick-keys.js';
|
|
11
|
+
import { createPosReportsModule } from './reports.js';
|
|
12
|
+
import { createPosReturnsModule } from './returns.js';
|
|
13
|
+
/** The kinds a device is created as (engine sprint 39), in the engine's order. */
|
|
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 };
|
|
31
|
+
/**
|
|
32
|
+
* The languages a staff member's own till language may be (`en`, `nl`, `de`, `fr`); the engine's
|
|
33
|
+
* list, which a value outside it is refused against. The till speaks a language only once its
|
|
34
|
+
* catalogue is released; until then it falls back to the store's language.
|
|
35
|
+
*/
|
|
36
|
+
export const POS_STAFF_LOCALES = ['en', 'nl', 'de', 'fr'];
|
|
37
|
+
/**
|
|
38
|
+
* The till actions a store may let a cashier do without a manager's approval (engine sprint 18). A
|
|
39
|
+
* manager may do all of them, whatever is stored. Closing a drawer above the store's variance
|
|
40
|
+
* threshold is not one: it stays a manager's.
|
|
41
|
+
*/
|
|
42
|
+
export const POS_STAFF_GRANTS = [
|
|
43
|
+
'manual_price',
|
|
44
|
+
'discount',
|
|
45
|
+
'custom_item_over_limit',
|
|
46
|
+
'refund',
|
|
47
|
+
'discard_held_sale',
|
|
48
|
+
'paid_out',
|
|
49
|
+
'no_sale',
|
|
50
|
+
'safe_drop',
|
|
51
|
+
'float_adjust',
|
|
52
|
+
// Engine sprint 20: returning a sale items, and voiding a sale.
|
|
53
|
+
'return_items',
|
|
54
|
+
'void_sale',
|
|
55
|
+
// Engine sprint 21: a return without a receipt paid to store credit (cash needs a manager).
|
|
56
|
+
'no_receipt_return',
|
|
57
|
+
// Engine C3/34: a webshop order returned at the till, refunded to its online payment.
|
|
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',
|
|
76
|
+
];
|
|
2
77
|
const REGISTER_FIELDS = 'id stockLocationId name status createdAt updatedAt';
|
|
78
|
+
// The X report selects only fields every engine answers; per-tender refunds come with the stored Z.
|
|
79
|
+
// So does the cash rounding: the X report does not select it; it arrives with the stored Z.
|
|
3
80
|
const TOTALS = 'cash card other refunds net saleCount';
|
|
4
81
|
const SESSION_FIELDS = `id registerId deviceId openedByStaffId openingFloat status expectedCash countedCash cashOverShort totals openedAt closedAt`;
|
|
82
|
+
// Engine sprint 25b: the close's details.
|
|
83
|
+
const SESSION_CLOSE_FIELDS = 'closedByStaffId blindCount varianceThreshold varianceApproval varianceApprovedByStaffId varianceApprovedAt';
|
|
84
|
+
const DEFAULT_SESSION_PAGE = 50;
|
|
85
|
+
const MAX_SESSION_PAGE = 100;
|
|
5
86
|
const CART_FIELDS = `id code state currencyCode total totalWithTax couponCodes
|
|
6
87
|
lines { id quantity productVariant { id } linePriceWithTax }
|
|
7
88
|
surcharges { description sku price priceWithTax taxRate }`;
|
|
8
89
|
const TENDER_FIELDS = 'orderId paymentId covered outstanding change';
|
|
9
|
-
const DEVICE_FIELDS = 'id stockLocationId registerId label status paired lastSeenAt';
|
|
90
|
+
const DEVICE_FIELDS = 'id stockLocationId registerId label status paired lastSeenAt mollieTerminalId createdAt updatedAt';
|
|
10
91
|
export const POS_REGISTERS_QUERY = `query PosRegisters { posRegisters { ${REGISTER_FIELDS} } }`;
|
|
11
92
|
export const POS_REGISTER_QUERY = `query PosRegister($id: ID!) { posRegister(id: $id) { ${REGISTER_FIELDS} } }`;
|
|
12
93
|
export const CREATE_POS_REGISTER_MUTATION = `mutation CreatePosRegister($input: CreatePosRegisterInput!) { createPosRegister(input: $input) { ${REGISTER_FIELDS} } }`;
|
|
13
94
|
export const UPDATE_POS_REGISTER_MUTATION = `mutation UpdatePosRegister($id: ID!, $input: UpdatePosRegisterInput!) { updatePosRegister(id: $id, input: $input) { ${REGISTER_FIELDS} } }`;
|
|
14
95
|
export const OPEN_POS_SESSION_MUTATION = `mutation OpenPosRegisterSession($input: OpenPosRegisterSessionInput!, $staffToken: String) { openPosRegisterSession(input: $input, staffToken: $staffToken) { ${SESSION_FIELDS} } }`;
|
|
15
96
|
export const CLOSE_POS_SESSION_MUTATION = `mutation ClosePosRegisterSession($input: ClosePosRegisterSessionInput!, $staffToken: String) { closePosRegisterSession(input: $input, staffToken: $staffToken) { ${SESSION_FIELDS} } }`;
|
|
16
|
-
export const POS_X_REPORT_QUERY = `query PosXReport($sessionId: ID!) { posXReport(sessionId: $sessionId) { sessionId openingFloat expectedCash movementCount totals { ${TOTALS} } } }`;
|
|
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} } } }`;
|
|
17
100
|
export const POS_SESSION_QUERY = `query PosRegisterSession($id: ID!) { posRegisterSession(id: $id) { ${SESSION_FIELDS} } }`;
|
|
101
|
+
// Engine sprint 25b; an older engine refuses the document at validation.
|
|
102
|
+
export const POS_SESSION_DETAIL_QUERY = `query PosRegisterSessionDetail($id: ID!) { posRegisterSession(id: $id) { ${SESSION_FIELDS} ${SESSION_CLOSE_FIELDS} } }`;
|
|
103
|
+
// Engine sprint 27: who approved a pending close afterwards. Only these two documents select the
|
|
104
|
+
// approval fields, so an older engine refuses them alone (the rest of `sessions` keeps working).
|
|
105
|
+
const SESSION_APPROVAL_FIELDS = 'varianceApprovedByUserId varianceApprovedByUserName varianceApprovedByCredential varianceApprovalNote';
|
|
106
|
+
export const POS_SESSION_APPROVAL_QUERY = `query PosRegisterSessionApproval($id: ID!) { posRegisterSession(id: $id) { id varianceApproval varianceThreshold varianceApprovedByStaffId varianceApprovedAt ${SESSION_APPROVAL_FIELDS} } }`;
|
|
107
|
+
export const APPROVE_POS_SESSION_CLOSE_MUTATION = `mutation ApprovePosRegisterSessionClose($input: ApprovePosRegisterSessionCloseInput!) { approvePosRegisterSessionClose(input: $input) { ${SESSION_FIELDS} ${SESSION_CLOSE_FIELDS} ${SESSION_APPROVAL_FIELDS} } }`;
|
|
108
|
+
// Engine sprint 26: a session's Z record. Only `sessions.record` / `sessions.records` select these,
|
|
109
|
+
// each its own document, so an older engine refuses them alone (`get` and `list` are unchanged).
|
|
110
|
+
// Sprint 26b adds the close without a count and its count afterwards; 26e reads none of them.
|
|
111
|
+
export const SESSION_RECORD_FIELDS = 'businessDay stockLocationId timeZone zNumber closeSource closedByUserId autoCloseReason closeNote countedAt countedByUserId countNote';
|
|
112
|
+
// The names are read per session (an administrator read each): the single record only.
|
|
113
|
+
export const SESSION_RECORD_NAME_FIELDS = 'varianceApprovedByUserName closedByUserName countedByUserName';
|
|
114
|
+
const SESSION_RECORD_APPROVAL_FIELDS = 'varianceApprovedByUserId varianceApprovedByCredential varianceApprovalNote';
|
|
115
|
+
export const POS_SESSION_RECORD_QUERY = `query PosRegisterSessionRecord($id: ID!) { posRegisterSession(id: $id) { ${SESSION_FIELDS} ${SESSION_CLOSE_FIELDS} ${SESSION_RECORD_APPROVAL_FIELDS} ${SESSION_RECORD_FIELDS} ${SESSION_RECORD_NAME_FIELDS} } }`;
|
|
116
|
+
export const POS_SESSION_RECORDS_QUERY = `query PosRegisterSessionRecords($options: PosRegisterSessionListOptions) { posRegisterSessions(options: $options) { totalItems items { ${SESSION_FIELDS} ${SESSION_CLOSE_FIELDS} ${SESSION_RECORD_APPROVAL_FIELDS} ${SESSION_RECORD_FIELDS} } } }`;
|
|
117
|
+
// Engine sprint 26b: the back office closes a drawer without a count, and counts it later. Each
|
|
118
|
+
// answers the session as `record` reads it; each its own document.
|
|
119
|
+
const SESSION_RECORD_SELECTION = `${SESSION_FIELDS} ${SESSION_CLOSE_FIELDS} ${SESSION_RECORD_APPROVAL_FIELDS} ${SESSION_RECORD_FIELDS} ${SESSION_RECORD_NAME_FIELDS}`;
|
|
120
|
+
export const CLOSE_POS_SESSION_UNCOUNTED_MUTATION = `mutation ClosePosRegisterSessionUncounted($input: ClosePosRegisterSessionUncountedInput!) { closePosRegisterSessionUncounted(input: $input) { ${SESSION_RECORD_SELECTION} } }`;
|
|
121
|
+
export const COUNT_POS_SESSION_MUTATION = `mutation CountPosRegisterSession($input: CountPosRegisterSessionInput!) { countPosRegisterSession(input: $input) { ${SESSION_RECORD_SELECTION} } }`;
|
|
122
|
+
// Engine sprint 27: the back office's sales, its till sale card and the store-wide movements.
|
|
123
|
+
// Each its own document, so an older engine refuses only it.
|
|
124
|
+
const POS_ORDER_SUMMARY_FIELDS = 'orderId orderCode receiptNumber placedAt state currencyCode totalWithTax totalQuantity refundedTotal tenderKinds customerKind customerName registerId registerName sessionId deviceId deviceLabel staffId staffName';
|
|
125
|
+
export const POS_ORDERS_QUERY = `query PosOrders($input: PosOrderListInput) { posOrders(input: $input) { totalItems items { ${POS_ORDER_SUMMARY_FIELDS} } } }`;
|
|
126
|
+
const POS_TILL_SALE_FIELDS = 'order { id code state } receiptNumber placedAt customerKind deviceId deviceLabel registerId registerName sessionId staffId staffName payments { paymentId kind method state amount refunded refundUnknown refundable }';
|
|
127
|
+
export const POS_TILL_SALE_QUERY = `query PosTillSale($orderId: ID!) { posTillOrder(orderId: $orderId) { ${POS_TILL_SALE_FIELDS} idCheck { id checkedAt staffId staffName deviceId deviceLabel stockLocationId minimumAge } } }`;
|
|
128
|
+
/**
|
|
129
|
+
* {@link POS_TILL_SALE_QUERY} for an engine older than the till's ID check (user decision L1),
|
|
130
|
+
* which refuses the whole document at validation: the sale is still read, with no ID check.
|
|
131
|
+
*/
|
|
132
|
+
export const POS_TILL_SALE_QUERY_LEGACY = `query PosTillSale($orderId: ID!) { posTillOrder(orderId: $orderId) { ${POS_TILL_SALE_FIELDS} } }`;
|
|
133
|
+
export const POS_CASH_MOVEMENTS_QUERY = `query PosCashMovements($input: PosCashMovementListInput) { posCashMovements(input: $input) { totalItems items { id sessionId registerId registerName deviceId deviceLabel type amount reason staffId staffName approvedByStaffId approvedByStaffName orderId orderCode receiptNumber idempotencyKey createdAt } } }`;
|
|
134
|
+
const DEFAULT_BACK_OFFICE_PAGE = 50;
|
|
135
|
+
const MAX_BACK_OFFICE_PAGE = 100;
|
|
136
|
+
// Engine sprint 25b (the close's details); an older engine refuses the document at validation.
|
|
137
|
+
// Engine sprint 26e: a location's business days.
|
|
138
|
+
export const STORE_DAY_TOTALS_FIELDS = 'currencyCode sessionCount uncountedCount openingFloat expectedCash countedCash cashOverShort cash card other refunds net saleCount cashRefunds cardRefunds otherRefunds cashRounding';
|
|
139
|
+
export const STORE_DAY_SESSION_FIELDS = 'sessionId registerId registerName zNumber status closeSource openedAt closedAt openingFloat expectedCash countedCash cashOverShort varianceApproval totals { cash card other refunds net saleCount cashRefunds cardRefunds otherRefunds cashRounding }';
|
|
140
|
+
export const STORE_DAY_FIELDS = `id stockLocationId businessDay timeZone startsAt endsAt status totalsFinal totals { ${STORE_DAY_TOTALS_FIELDS} } openSessionCount pendingCount uncountedCount closedAt closedByUserId closedByCredential closeNote closeCount reopenedAt reopenedByUserId reopenNote`;
|
|
141
|
+
/** What a single day's read adds to a list item: its drawers and the two names. */
|
|
142
|
+
export const STORE_DAY_DETAIL_FIELDS = `sessions { ${STORE_DAY_SESSION_FIELDS} } closedByUserName reopenedByUserName`;
|
|
143
|
+
export const POS_STORE_DAY_QUERY = `query PosStoreDay($stockLocationId: ID!, $businessDay: String!) { posStoreDay(stockLocationId: $stockLocationId, businessDay: $businessDay) { ${STORE_DAY_FIELDS} ${STORE_DAY_DETAIL_FIELDS} } }`;
|
|
144
|
+
export const POS_STORE_DAYS_QUERY = `query PosStoreDays($input: PosStoreDayListInput!) { posStoreDays(input: $input) { totalItems items { ${STORE_DAY_FIELDS} } } }`;
|
|
145
|
+
export const CLOSE_POS_STORE_DAY_MUTATION = `mutation ClosePosStoreDay($input: ClosePosStoreDayInput!) { closePosStoreDay(input: $input) { ${STORE_DAY_FIELDS} ${STORE_DAY_DETAIL_FIELDS} } }`;
|
|
146
|
+
export const REOPEN_POS_STORE_DAY_MUTATION = `mutation ReopenPosStoreDay($input: ReopenPosStoreDayInput!) { reopenPosStoreDay(input: $input) { ${STORE_DAY_FIELDS} ${STORE_DAY_DETAIL_FIELDS} } }`;
|
|
147
|
+
export const POS_SESSION_LIST_QUERY = `query PosRegisterSessionList($options: PosRegisterSessionListOptions) { posRegisterSessions(options: $options) { totalItems items { ${SESSION_FIELDS} ${SESSION_CLOSE_FIELDS} } } }`;
|
|
18
148
|
export const RECORD_POS_CASH_MOVEMENT_MUTATION = `mutation RecordPosCashMovement($input: RecordPosCashMovementInput!, $staffToken: String) { recordPosCashMovement(input: $input, staffToken: $staffToken) { id sessionId type amount reason orderId createdAt } }`;
|
|
149
|
+
// Engine sprint 25a; an older engine refuses the document at validation.
|
|
150
|
+
export const POS_DRAWER_MOVEMENTS_QUERY = `query PosDrawerMovements($sessionId: ID!, $skip: Int, $take: Int) { posDrawerMovements(sessionId: $sessionId, skip: $skip, take: $take) { totalItems items { id type amount balanceAfter reason staffId staffName approvedByStaffId approvedByStaffName orderId orderCode receiptNumber createdAt } summary { openingFloat cashSales cashRefunds cashRounding paidIn paidOut safeDrops floatAdjustments noSaleCount expectedCash movementCount } } }`;
|
|
19
151
|
export const POS_CREATE_CART_MUTATION = `mutation PosCreateCart($registerId: ID) { posCreateCart(registerId: $registerId) { ${CART_FIELDS} } }`;
|
|
20
152
|
export const POS_ADD_ITEM_MUTATION = `mutation PosAddItem($input: PosAddItemInput!) { posAddItem(input: $input) { ${CART_FIELDS} } }`;
|
|
21
153
|
export const POS_APPLY_DISCOUNT_MUTATION = `mutation PosApplyDiscount($input: PosApplyDiscountInput!, $staffToken: String) { posApplyDiscount(input: $input, staffToken: $staffToken) { ${CART_FIELDS} } }`;
|
|
22
154
|
export const POS_APPLY_COUPON_CODE_MUTATION = `mutation PosApplyCouponCode($input: PosCouponCodeInput!) { posApplyCouponCode(input: $input) { ${CART_FIELDS} } }`;
|
|
23
155
|
export const POS_REMOVE_COUPON_CODE_MUTATION = `mutation PosRemoveCouponCode($input: PosCouponCodeInput!) { posRemoveCouponCode(input: $input) { ${CART_FIELDS} } }`;
|
|
156
|
+
// A custom item's cart also selects each line's name (merged into CART_FIELDS' `lines`), which
|
|
157
|
+
// an engine before sprint 16b cannot answer: only this document asks for it.
|
|
158
|
+
export const POS_ADD_CUSTOM_ITEM_MUTATION = `mutation PosAddCustomItem($input: PosAddCustomItemInput!, $staffToken: String, $approvalToken: String) { posAddCustomItem(input: $input, staffToken: $staffToken, approvalToken: $approvalToken) { ${CART_FIELDS} lines { id customFields { posCustomItemName } } } }`;
|
|
159
|
+
// The note documents (16c) also select the sale's note and each line's note and name (merged into
|
|
160
|
+
// CART_FIELDS), which an engine before sprint 16c cannot answer: only these documents ask for them.
|
|
161
|
+
const NOTE_CART_FIELDS = `${CART_FIELDS} customFields { posOrderNote } lines { id customFields { posCustomItemName posLineNote } }`;
|
|
162
|
+
export const POS_SET_ORDER_NOTE_MUTATION = `mutation PosSetOrderNote($input: PosSetOrderNoteInput!, $staffToken: String) { posSetOrderNote(input: $input, staffToken: $staffToken) { ${NOTE_CART_FIELDS} } }`;
|
|
163
|
+
export const POS_SET_LINE_NOTE_MUTATION = `mutation PosSetLineNote($input: PosSetLineNoteInput!, $staffToken: String) { posSetLineNote(input: $input, staffToken: $staffToken) { ${NOTE_CART_FIELDS} } }`;
|
|
164
|
+
// A back office's read of what a till wrote on an order (16d): only this document names the POS
|
|
165
|
+
// note and custom item fields on `order`, so `orders.get` keeps working against an older engine.
|
|
166
|
+
export const POS_TILL_SALE_DETAILS_QUERY = `query PosTillSaleDetails($id: ID!) { order(id: $id) { id customFields { isPosOrder posOrderNote } lines { id customFields { posCustomItemName posLineNote } } } }`;
|
|
167
|
+
export const POS_CLEAR_CART_MUTATION = `mutation PosClearCart($input: PosClearCartInput!, $staffToken: String) { posClearCart(input: $input, staffToken: $staffToken) { orderId orderCode } }`;
|
|
24
168
|
export const POS_COMPLETE_SALE_MUTATION = `mutation PosCompleteSale($input: PosCompleteSaleInput!, $staffToken: String) { posCompleteSale(input: $input, staffToken: $staffToken) { orderId orderCode receiptNumber state } }`;
|
|
25
169
|
export const POS_TENDER_CASH_MUTATION = `mutation PosTenderCash($input: PosTenderCashInput!, $staffToken: String) { posTenderCash(input: $input, staffToken: $staffToken) { ${TENDER_FIELDS} } }`;
|
|
26
170
|
export const POS_TENDER_CARD_MUTATION = `mutation PosTenderCard($input: PosTenderCardInput!, $staffToken: String) { posTenderCard(input: $input, staffToken: $staffToken) { ${TENDER_FIELDS} } }`;
|
|
@@ -30,17 +174,200 @@ export const POS_REFUND_MUTATION = `mutation PosRefund($input: PosRefundInput!,
|
|
|
30
174
|
export const POS_DEVICES_QUERY = `query PosDevices { posDevices { ${DEVICE_FIELDS} } }`;
|
|
31
175
|
export const POS_DEVICE_QUERY = `query PosDevice($id: ID!) { posDevice(id: $id) { lastSeenAt } }`;
|
|
32
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 } }`;
|
|
33
180
|
export const REVOKE_POS_DEVICE_MUTATION = `mutation RevokePosDevice($deviceId: ID!) { revokePosDevice(deviceId: $deviceId) { ${DEVICE_FIELDS} } }`;
|
|
181
|
+
// The device's own read and its three assignments: Admin API doors every deployed engine serves.
|
|
182
|
+
// Like `list` and `revoke`, they select no kind or health column (`fleet` reads those).
|
|
183
|
+
export const POS_DEVICE_DETAIL_QUERY = `query PosDeviceDetail($id: ID!) { posDevice(id: $id) { ${DEVICE_FIELDS} } }`;
|
|
184
|
+
export const ASSIGN_POS_DEVICE_LOCATION_MUTATION = `mutation AssignPosDeviceLocation($deviceId: ID!, $stockLocationId: ID!) { assignPosDeviceLocation(deviceId: $deviceId, stockLocationId: $stockLocationId) { ${DEVICE_FIELDS} } }`;
|
|
185
|
+
export const ASSIGN_POS_DEVICE_REGISTER_MUTATION = `mutation AssignPosDeviceRegister($deviceId: ID!, $registerId: ID!) { assignPosDeviceRegister(deviceId: $deviceId, registerId: $registerId) { ${DEVICE_FIELDS} } }`;
|
|
186
|
+
export const ASSIGN_POS_DEVICE_TERMINAL_MUTATION = `mutation AssignPosDeviceMollieTerminal($deviceId: ID!, $terminalId: String!) { assignPosDeviceMollieTerminal(deviceId: $deviceId, terminalId: $terminalId) { ${DEVICE_FIELDS} } }`;
|
|
187
|
+
// Engine `pos-device-writes-validate`: a move that names the register at the new location, and
|
|
188
|
+
// taking a terminal off. Only these documents name the new argument and field, so an older engine
|
|
189
|
+
// refuses them alone.
|
|
190
|
+
export const ASSIGN_POS_DEVICE_LOCATION_WITH_REGISTER_MUTATION = `mutation AssignPosDeviceLocationWithRegister($deviceId: ID!, $stockLocationId: ID!, $registerId: ID!) { assignPosDeviceLocation(deviceId: $deviceId, stockLocationId: $stockLocationId, registerId: $registerId) { ${DEVICE_FIELDS} } }`;
|
|
191
|
+
export const CLEAR_POS_DEVICE_TERMINAL_MUTATION = `mutation ClearPosDeviceMollieTerminal($deviceId: ID!) { clearPosDeviceMollieTerminal(deviceId: $deviceId) { ${DEVICE_FIELDS} } }`;
|
|
192
|
+
export const POS_OPEN_SESSION_FOR_DEVICE_QUERY = `query PosOpenSessionForDevice($deviceId: ID!) { posOpenSessionForDevice(deviceId: $deviceId) { ${SESSION_FIELDS} } }`;
|
|
193
|
+
// Engine sprint 35: the fleet read and the lock. Only these documents select the health columns,
|
|
194
|
+
// so an older engine refuses them alone (`list`, `revoke` and the rest are unchanged). They select
|
|
195
|
+
// the device's kind (39) too: the engine ships both in one release.
|
|
196
|
+
const DEVICE_HEALTH_FIELDS = 'heartbeatAt lockedAt silentSince kind';
|
|
197
|
+
// A device created without a kind is a till on every engine; only a create that names one sends
|
|
198
|
+
// (and selects) the kind, so a till is still created on an engine before 39.
|
|
199
|
+
export const CREATE_POS_DEVICE_MUTATION = `mutation CreatePosDevice($input: CreatePosDeviceInput!) { createPosDevice(input: $input) { ${DEVICE_FIELDS} } }`;
|
|
200
|
+
export const CREATE_POS_DEVICE_KIND_MUTATION = `mutation CreatePosDeviceOfKind($input: CreatePosDeviceInput!) { createPosDevice(input: $input) { ${DEVICE_FIELDS} kind } }`;
|
|
201
|
+
const HEARTBEAT_REPORT_FIELDS = 'appVersion buildNumber runtimeVersion updateId updateChannel platform connection outboxPending offlineSalesPending offlineSalesRefused printer reportedAt';
|
|
202
|
+
export const POS_DEVICE_FLEET_QUERY = `query PosDeviceFleet($stockLocationId: ID) { posDeviceFleet(stockLocationId: $stockLocationId) { device { ${DEVICE_FIELDS} ${DEVICE_HEALTH_FIELDS} } health { status lastHeardAt silentSince } report { ${HEARTBEAT_REPORT_FIELDS} } openDrawer { sessionId registerId openedAt openedByStaffName } lockedByUserName } }`;
|
|
203
|
+
export const LOCK_POS_DEVICE_MUTATION = `mutation LockPosDevice($deviceId: ID!) { lockPosDevice(deviceId: $deviceId) { ${DEVICE_FIELDS} ${DEVICE_HEALTH_FIELDS} } }`;
|
|
204
|
+
export const UNLOCK_POS_DEVICE_MUTATION = `mutation UnlockPosDevice($deviceId: ID!) { unlockPosDevice(deviceId: $deviceId) { ${DEVICE_FIELDS} ${DEVICE_HEALTH_FIELDS} } }`;
|
|
34
205
|
export const POS_RECEIPT_NUMBERING_QUERY = `query PosReceiptNumberingConfig { posReceiptNumberingConfig { prefix suffix digits } }`;
|
|
35
206
|
export const UPDATE_POS_RECEIPT_NUMBERING_MUTATION = `mutation UpdatePosReceiptNumberingConfig($input: UpdatePosReceiptNumberingConfigInput!) { updatePosReceiptNumberingConfig(input: $input) { prefix suffix digits } }`;
|
|
207
|
+
const SETTINGS_FIELDS = 'enabled cashPaymentMethodCode cardPaymentMethodCode inStoreShippingMethodId fulfillmentProfileId defaultStockLocationId cashRoundingMode hasMollieKey maskedMollieApiKey';
|
|
208
|
+
export const POS_SETTINGS_QUERY = `query PosSettings { getPosConfig { ${SETTINGS_FIELDS} } }`;
|
|
209
|
+
export const UPDATE_POS_SETTINGS_MUTATION = `mutation UpdatePosSettings($input: UpdatePosConfigInput!) { updatePosConfig(input: $input) { ${SETTINGS_FIELDS} } }`;
|
|
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) }`;
|
|
214
|
+
// Engine sprint 25b; an older engine refuses both documents at validation.
|
|
215
|
+
export const POS_CASH_CONTROLS_QUERY = `query PosCashControls { getPosConfig { cashControls { blindCount varianceThreshold } } }`;
|
|
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 } }`;
|
|
220
|
+
// Engine sprint 22 (the receipt's tender and refund `exchange`, its lines' `ships` and its `delivery`:
|
|
221
|
+
// engine C3); an older engine refuses each document at validation.
|
|
222
|
+
const RECEIPT_SETTINGS_FIELDS = 'configured showStoreName showAddress showPhone showVatNumber headerLines footerLines taxDisplay identity { storeName addressLines phone vatNumber registrationNumber }';
|
|
223
|
+
const RECEIPT_FIELDS = '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';
|
|
224
|
+
export const POS_RECEIPT_SETTINGS_QUERY = `query PosReceiptSettings { getPosConfig { receipt { ${RECEIPT_SETTINGS_FIELDS} } } }`;
|
|
225
|
+
export const SET_POS_RECEIPT_SETTINGS_MUTATION = `mutation SetPosReceiptSettings($input: PosReceiptSettingsInput!) { setPosReceiptSettings(input: $input) { ${RECEIPT_SETTINGS_FIELDS} } }`;
|
|
226
|
+
export const POS_RECEIPT_PREVIEW_QUERY = `query PosReceiptPreview($input: PosReceiptSettingsInput) { posReceiptPreview(input: $input) { ${RECEIPT_FIELDS} } }`;
|
|
227
|
+
export const POS_RECEIPT_QUERY = `query PosReceipt($orderId: ID!) { posReceipt(orderId: $orderId) { ${RECEIPT_FIELDS} } }`;
|
|
228
|
+
// Engine sprint 23: each its own document, so a call to an engine before 23 fails alone.
|
|
229
|
+
const RECEIPT_LINK_FIELDS = 'variant url issuedAt expiresAt';
|
|
230
|
+
const RECEIPT_LINK_STATUS_FIELDS = 'variant state url issuedAt expiresAt revokedAt revokeReason';
|
|
231
|
+
const GIFT_RECEIPT_FIELDS = `orderId orderCode receiptNumber issuedAt language locale timeZone header { storeName addressLines phone vatNumber registrationNumber extraLines } registerName lines { orderLineId name sku quantity } footerLines thankYou scanCode link { ${RECEIPT_LINK_FIELDS} } copy { number printedAt }`;
|
|
232
|
+
export const POS_RECEIPT_SHARING_QUERY = `query PosReceiptSharing($orderId: ID!) { posReceiptSharing(orderId: $orderId) { available enabled ttlDays links { ${RECEIPT_LINK_STATUS_FIELDS} } receiptCopies giftPrints } }`;
|
|
233
|
+
export const POS_ISSUE_RECEIPT_LINK_MUTATION = `mutation PosIssueReceiptLink($orderId: ID!, $variant: PosReceiptVariant!) { posIssueReceiptLink(orderId: $orderId, variant: $variant) { ${RECEIPT_LINK_STATUS_FIELDS} } }`;
|
|
234
|
+
export const REVOKE_POS_RECEIPT_LINK_MUTATION = `mutation RevokePosReceiptLink($orderId: ID!, $variant: PosReceiptVariant!) { revokePosReceiptLink(orderId: $orderId, variant: $variant) { ${RECEIPT_LINK_STATUS_FIELDS} } }`;
|
|
235
|
+
export const POS_PRINT_RECEIPT_MUTATION = `mutation PosPrintReceipt($input: PosPrintReceiptInput!, $staffToken: String) { posPrintReceipt(input: $input, staffToken: $staffToken) { orderId variant printNumber copy receipt { ${RECEIPT_FIELDS} link { ${RECEIPT_LINK_FIELDS} } copy { number printedAt } } giftReceipt { ${GIFT_RECEIPT_FIELDS} } } }`;
|
|
236
|
+
export const POS_GIFT_RECEIPT_QUERY = `query PosGiftReceipt($orderId: ID!) { posReceipt(orderId: $orderId) { gift { ${GIFT_RECEIPT_FIELDS} } } }`;
|
|
237
|
+
export const POS_DIGITAL_RECEIPTS_QUERY = `query PosDigitalReceipts { getPosConfig { receipt { publicLink publicLinkAvailable } } }`;
|
|
238
|
+
// Engine C3/32: its own document, so `digitalReceipts()` keeps working on an engine before C3.
|
|
239
|
+
export const POS_RECEIPT_ACCOUNT_CLAIM_QUERY = `query PosReceiptAccountClaim { getPosConfig { receipt { accountClaim accountClaimAvailable } } }`;
|
|
240
|
+
// Engine sprint 22c.
|
|
241
|
+
export const POS_EMAIL_RECEIPT_MUTATION = `mutation PosEmailReceipt($input: PosEmailReceiptInput!, $staffToken: String) { posEmailReceipt(input: $input, staffToken: $staffToken) { orderId source sentForSale } }`;
|
|
242
|
+
// Engine sprint 26: the store's day controls, each its own document.
|
|
243
|
+
const DAY_CONTROLS_FIELDS = 'businessDayStartsAt closingTime autoCloseAfterClosingMinutes autoCloseIdleMinutes';
|
|
244
|
+
export const POS_DAY_CONTROLS_QUERY = `query PosDayControls { getPosConfig { id dayControls { ${DAY_CONTROLS_FIELDS} } } }`;
|
|
245
|
+
export const SET_POS_DAY_CONTROLS_MUTATION = `mutation SetPosDayControls($input: PosDayControlsInput!) { setPosDayControls(input: $input) { ${DAY_CONTROLS_FIELDS} } }`;
|
|
246
|
+
export const POS_SETUP_READINESS_QUERY = `query PosSetupReadiness { posSetupReadiness { ready checks { check ok required reason } } }`;
|
|
247
|
+
const CUSTOM_ITEM_POLICY_FIELDS = 'enabled available maxUnitPrice cashierLimit amountsIncludeTax currencyCode taxCategories { id name taxRate } taxCategoryChoices { id name taxRate }';
|
|
248
|
+
export const POS_CUSTOM_ITEM_POLICY_QUERY = `query PosCustomItemPolicy { posCustomItemPolicy { ${CUSTOM_ITEM_POLICY_FIELDS} } }`;
|
|
249
|
+
export const SET_POS_CUSTOM_ITEM_POLICY_MUTATION = `mutation SetPosCustomItemPolicy($input: PosCustomItemPolicyInput!) { setPosCustomItemPolicy(input: $input) { ${CUSTOM_ITEM_POLICY_FIELDS} } }`;
|
|
250
|
+
const STAFF_FIELDS = 'id name role active administratorId locale createdAt updatedAt';
|
|
251
|
+
export const POS_STAFF_LIST_QUERY = `query PosStaffList { posStaffList { ${STAFF_FIELDS} } }`;
|
|
252
|
+
export const POS_STAFF_QUERY = `query PosStaff($id: ID!) { posStaff(id: $id) { ${STAFF_FIELDS} } }`;
|
|
253
|
+
export const CREATE_POS_STAFF_MUTATION = `mutation CreatePosStaff($input: CreatePosStaffInput!) { createPosStaff(input: $input) { ${STAFF_FIELDS} } }`;
|
|
254
|
+
export const UPDATE_POS_STAFF_MUTATION = `mutation UpdatePosStaff($id: ID!, $input: UpdatePosStaffInput!) { updatePosStaff(id: $id, input: $input) { ${STAFF_FIELDS} } }`;
|
|
255
|
+
// Names no `locale`, unlike the four above: a PIN can be set on an engine older than the staff
|
|
256
|
+
// language too.
|
|
257
|
+
export const SET_POS_STAFF_PIN_MUTATION = `mutation SetPosStaffPin($id: ID!, $pin: String!) { setPosStaffPin(id: $id, pin: $pin) }`;
|
|
258
|
+
// Engine sprint 18: only these three documents name `grants`, so the four above keep working on an
|
|
259
|
+
// older engine.
|
|
260
|
+
const STAFF_GRANTS_FIELDS = 'id role grants';
|
|
261
|
+
export const POS_STAFF_GRANTS_QUERY = `query PosStaffGrants($id: ID!) { posStaff(id: $id) { ${STAFF_GRANTS_FIELDS} } }`;
|
|
262
|
+
export const POS_STAFF_GRANTS_LIST_QUERY = `query PosStaffGrantsList { posStaffList { ${STAFF_GRANTS_FIELDS} } }`;
|
|
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 } } }`;
|
|
266
|
+
const DEVICE_KIND_INVALID = 'POS_DEVICE_KIND_INVALID';
|
|
267
|
+
/** A kind outside {@link POS_DEVICE_KINDS}, refused before sending, as the engine refuses it. */
|
|
268
|
+
function deviceKindRefusal(kind) {
|
|
269
|
+
const message = `A POS device is a ${POS_DEVICE_KINDS.join(' or a ')}, not "${String(kind).slice(0, 40)}".`;
|
|
270
|
+
return new ValidationError({
|
|
271
|
+
code: DEVICE_KIND_INVALID,
|
|
272
|
+
message,
|
|
273
|
+
status: 400,
|
|
274
|
+
service: 'vendure',
|
|
275
|
+
details: [{ field: 'kind', code: DEVICE_KIND_INVALID, message }],
|
|
276
|
+
});
|
|
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
|
+
}
|
|
290
|
+
const LOCALE_UNSUPPORTED = 'POS_LOCALE_UNSUPPORTED';
|
|
291
|
+
const LOCALE_UNSUPPORTED_MESSAGE = `A staff language must be one of ${POS_STAFF_LOCALES.join(', ')}, or null to follow the store.`;
|
|
292
|
+
function localeRefusal(message) {
|
|
293
|
+
return new ValidationError({
|
|
294
|
+
code: LOCALE_UNSUPPORTED,
|
|
295
|
+
message,
|
|
296
|
+
status: 400,
|
|
297
|
+
service: 'vendure',
|
|
298
|
+
details: [{ field: 'locale', code: LOCALE_UNSUPPORTED, message }],
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* A staff language as the engine stores it, refused here before anything is sent when it is not
|
|
303
|
+
* one: `undefined` stays absent (leave it), null and a blank string follow the store, a listed
|
|
304
|
+
* language in any case with spaces around it is that language. Never quotes the value.
|
|
305
|
+
*/
|
|
306
|
+
function staffLocale(value) {
|
|
307
|
+
if (value === undefined)
|
|
308
|
+
return undefined;
|
|
309
|
+
if (value === null)
|
|
310
|
+
return null;
|
|
311
|
+
if (typeof value !== 'string')
|
|
312
|
+
throw localeRefusal(LOCALE_UNSUPPORTED_MESSAGE);
|
|
313
|
+
const locale = value.trim().toLowerCase();
|
|
314
|
+
if (locale === '')
|
|
315
|
+
return null;
|
|
316
|
+
const listed = POS_STAFF_LOCALES.find((known) => known === locale);
|
|
317
|
+
if (!listed)
|
|
318
|
+
throw localeRefusal(LOCALE_UNSUPPORTED_MESSAGE);
|
|
319
|
+
return listed;
|
|
320
|
+
}
|
|
321
|
+
/** The input with its `locale` checked; an absent one stays absent, so the engine leaves it. */
|
|
322
|
+
function withStaffLocale(input) {
|
|
323
|
+
const { locale, ...rest } = input;
|
|
324
|
+
const checked = staffLocale(locale);
|
|
325
|
+
return (checked === undefined ? rest : { ...rest, locale: checked });
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Whether a failure is "this engine does not know that field yet": the document refused before it
|
|
329
|
+
* ran, never an execution-time refusal or a transient failure (the rule `customers.credit` and the
|
|
330
|
+
* purchasing settings read with).
|
|
331
|
+
*/
|
|
332
|
+
function isUnknownFieldRejection(error) {
|
|
333
|
+
if (!(error instanceof ValidationError) || error.service !== 'vendure')
|
|
334
|
+
return false;
|
|
335
|
+
return (error.code === 'BAD_REQUEST' ||
|
|
336
|
+
error.code === 'GRAPHQL_VALIDATION_FAILED' ||
|
|
337
|
+
/Cannot query field/i.test(error.message));
|
|
338
|
+
}
|
|
339
|
+
function toTillSale(raw) {
|
|
340
|
+
const { order, ...rest } = raw;
|
|
341
|
+
return { orderId: order.id, orderCode: order.code, orderState: order.state, ...rest };
|
|
342
|
+
}
|
|
343
|
+
function toTillSaleDetails(raw) {
|
|
344
|
+
return {
|
|
345
|
+
orderId: raw.id,
|
|
346
|
+
isPosOrder: raw.customFields?.isPosOrder === true,
|
|
347
|
+
note: raw.customFields?.posOrderNote ?? null,
|
|
348
|
+
lines: raw.lines.map((line) => ({
|
|
349
|
+
id: line.id,
|
|
350
|
+
customItemName: line.customFields?.posCustomItemName ?? null,
|
|
351
|
+
note: line.customFields?.posLineNote ?? null,
|
|
352
|
+
})),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
36
355
|
function toCart(raw) {
|
|
356
|
+
const { customFields, ...cart } = raw;
|
|
37
357
|
return {
|
|
38
|
-
...
|
|
358
|
+
...cart,
|
|
359
|
+
...(customFields === undefined ? {} : { note: customFields?.posOrderNote ?? null }),
|
|
39
360
|
lines: raw.lines.map((line) => ({
|
|
40
361
|
id: line.id,
|
|
41
362
|
quantity: line.quantity,
|
|
42
363
|
productVariantId: line.productVariant.id,
|
|
43
364
|
linePriceWithTax: line.linePriceWithTax,
|
|
365
|
+
...(line.customFields === undefined
|
|
366
|
+
? {}
|
|
367
|
+
: { customItemName: line.customFields?.posCustomItemName ?? null }),
|
|
368
|
+
...(line.customFields === undefined || !('posLineNote' in (line.customFields ?? {}))
|
|
369
|
+
? {}
|
|
370
|
+
: { note: line.customFields?.posLineNote ?? null }),
|
|
44
371
|
})),
|
|
45
372
|
};
|
|
46
373
|
}
|
|
@@ -71,6 +398,61 @@ function requireKey(options) {
|
|
|
71
398
|
}
|
|
72
399
|
export function createPosModule(transport) {
|
|
73
400
|
const gql = async (query, variables, options) => transport.graphql({ api: 'admin', query, variables }, options);
|
|
401
|
+
async function sessionPage(skip, take, options, query = POS_SESSION_LIST_QUERY) {
|
|
402
|
+
const filters = {};
|
|
403
|
+
for (const key of [
|
|
404
|
+
'status',
|
|
405
|
+
'registerId',
|
|
406
|
+
'deviceId',
|
|
407
|
+
'staffId',
|
|
408
|
+
'openedAfter',
|
|
409
|
+
'openedBefore',
|
|
410
|
+
]) {
|
|
411
|
+
const value = options?.[key];
|
|
412
|
+
if (value !== undefined)
|
|
413
|
+
filters[key] = value;
|
|
414
|
+
}
|
|
415
|
+
const data = await gql(query, { options: { ...filters, skip, take } }, options);
|
|
416
|
+
const list = data.posRegisterSessions;
|
|
417
|
+
return pageFromVendureList({ items: list.items.map(toSession), totalItems: list.totalItems }, skip, take, (cursor) => sessionPage(readOffsetCursor(cursor), take, options, query));
|
|
418
|
+
}
|
|
419
|
+
/** The take of a back-office list (1 to 100, 50 when omitted) and its offset from `after`. */
|
|
420
|
+
function backOfficePaging(options) {
|
|
421
|
+
const take = Math.min(Math.max(Math.trunc(options?.limit ?? DEFAULT_BACK_OFFICE_PAGE), 1), MAX_BACK_OFFICE_PAGE);
|
|
422
|
+
const skip = options?.after === undefined ? 0 : readOffsetCursor(options.after);
|
|
423
|
+
return { skip, take };
|
|
424
|
+
}
|
|
425
|
+
async function orderPage(skip, take, options) {
|
|
426
|
+
const input = { skip, take };
|
|
427
|
+
for (const key of [
|
|
428
|
+
'fromDay',
|
|
429
|
+
'toDay',
|
|
430
|
+
'registerId',
|
|
431
|
+
'sessionId',
|
|
432
|
+
'deviceId',
|
|
433
|
+
'staffId',
|
|
434
|
+
'tender',
|
|
435
|
+
'term',
|
|
436
|
+
]) {
|
|
437
|
+
const value = options?.[key];
|
|
438
|
+
if (value !== undefined)
|
|
439
|
+
input[key] = value;
|
|
440
|
+
}
|
|
441
|
+
const data = await gql(POS_ORDERS_QUERY, { input }, options);
|
|
442
|
+
return pageFromVendureList(data.posOrders, skip, take, (cursor) => orderPage(readOffsetCursor(cursor), take, options));
|
|
443
|
+
}
|
|
444
|
+
async function movementPage(skip, take, options) {
|
|
445
|
+
const input = { skip, take };
|
|
446
|
+
for (const key of ['fromDay', 'toDay', 'registerId', 'sessionId', 'staffId']) {
|
|
447
|
+
const value = options?.[key];
|
|
448
|
+
if (value !== undefined)
|
|
449
|
+
input[key] = value;
|
|
450
|
+
}
|
|
451
|
+
if (options?.types !== undefined)
|
|
452
|
+
input.types = [...options.types];
|
|
453
|
+
const data = await gql(POS_CASH_MOVEMENTS_QUERY, { input }, options);
|
|
454
|
+
return pageFromVendureList(data.posCashMovements, skip, take, (cursor) => movementPage(readOffsetCursor(cursor), take, options));
|
|
455
|
+
}
|
|
74
456
|
return {
|
|
75
457
|
registers: {
|
|
76
458
|
async list(options) {
|
|
@@ -100,19 +482,149 @@ export function createPosModule(transport) {
|
|
|
100
482
|
return toSession(data.closePosRegisterSession);
|
|
101
483
|
},
|
|
102
484
|
async xReport(sessionId, options) {
|
|
103
|
-
|
|
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);
|
|
104
496
|
return data.posXReport;
|
|
105
497
|
},
|
|
498
|
+
async get(sessionId, options) {
|
|
499
|
+
const data = await gql(POS_SESSION_DETAIL_QUERY, { id: sessionId }, options);
|
|
500
|
+
return data.posRegisterSession && toSession(data.posRegisterSession);
|
|
501
|
+
},
|
|
502
|
+
async openForDevice(deviceId, options) {
|
|
503
|
+
const data = await gql(POS_OPEN_SESSION_FOR_DEVICE_QUERY, { deviceId }, options);
|
|
504
|
+
return data.posOpenSessionForDevice && toSession(data.posOpenSessionForDevice);
|
|
505
|
+
},
|
|
506
|
+
async list(options) {
|
|
507
|
+
const take = Math.min(Math.max(Math.trunc(options?.limit ?? DEFAULT_SESSION_PAGE), 1), MAX_SESSION_PAGE);
|
|
508
|
+
const skip = options?.after === undefined ? 0 : readOffsetCursor(options.after);
|
|
509
|
+
return sessionPage(skip, take, options);
|
|
510
|
+
},
|
|
106
511
|
async zReport(sessionId, options) {
|
|
107
512
|
const data = await gql(POS_SESSION_QUERY, { id: sessionId }, options);
|
|
108
513
|
return data.posRegisterSession && toSession(data.posRegisterSession);
|
|
109
514
|
},
|
|
515
|
+
async movements(sessionId, options) {
|
|
516
|
+
const data = await gql(POS_DRAWER_MOVEMENTS_QUERY, { sessionId, skip: options?.skip, take: options?.take }, options);
|
|
517
|
+
return data.posDrawerMovements;
|
|
518
|
+
},
|
|
519
|
+
async approval(sessionId, options) {
|
|
520
|
+
const data = await gql(POS_SESSION_APPROVAL_QUERY, { id: sessionId }, options);
|
|
521
|
+
const raw = data.posRegisterSession;
|
|
522
|
+
if (!raw)
|
|
523
|
+
return null;
|
|
524
|
+
const { id, ...rest } = raw;
|
|
525
|
+
return { sessionId: id, ...rest };
|
|
526
|
+
},
|
|
527
|
+
async approveClose(sessionId, input, options) {
|
|
528
|
+
const data = await gql(APPROVE_POS_SESSION_CLOSE_MUTATION, { input: { sessionId, note: input.note } }, options);
|
|
529
|
+
return toSession(data.approvePosRegisterSessionClose);
|
|
530
|
+
},
|
|
531
|
+
async record(sessionId, options) {
|
|
532
|
+
const data = await gql(POS_SESSION_RECORD_QUERY, { id: sessionId }, options);
|
|
533
|
+
return data.posRegisterSession && toSession(data.posRegisterSession);
|
|
534
|
+
},
|
|
535
|
+
async records(options) {
|
|
536
|
+
const take = Math.min(Math.max(Math.trunc(options?.limit ?? DEFAULT_SESSION_PAGE), 1), MAX_SESSION_PAGE);
|
|
537
|
+
const skip = options?.after === undefined ? 0 : readOffsetCursor(options.after);
|
|
538
|
+
return sessionPage(skip, take, options, POS_SESSION_RECORDS_QUERY);
|
|
539
|
+
},
|
|
540
|
+
async closeUncounted(sessionId, input, options) {
|
|
541
|
+
const data = await gql(CLOSE_POS_SESSION_UNCOUNTED_MUTATION, { input: { sessionId, note: input.note } }, options);
|
|
542
|
+
return toSession(data.closePosRegisterSessionUncounted);
|
|
543
|
+
},
|
|
544
|
+
async count(sessionId, input, options) {
|
|
545
|
+
const data = await gql(COUNT_POS_SESSION_MUTATION, {
|
|
546
|
+
input: {
|
|
547
|
+
sessionId,
|
|
548
|
+
countedCash: input.countedCash,
|
|
549
|
+
// Only what was given: an absent count or note is none.
|
|
550
|
+
...(input.closingCounts === undefined ? {} : { closingCounts: input.closingCounts }),
|
|
551
|
+
...(input.note === undefined ? {} : { note: input.note }),
|
|
552
|
+
},
|
|
553
|
+
}, options);
|
|
554
|
+
return toSession(data.countPosRegisterSession);
|
|
555
|
+
},
|
|
110
556
|
},
|
|
111
557
|
cash: {
|
|
112
558
|
async record(input, options) {
|
|
113
|
-
const data = await gql(RECORD_POS_CASH_MOVEMENT_MUTATION, {
|
|
559
|
+
const data = await gql(RECORD_POS_CASH_MOVEMENT_MUTATION, {
|
|
560
|
+
// The key only when given: an engine before 25a refuses the input field.
|
|
561
|
+
input: options?.idempotencyKey === undefined
|
|
562
|
+
? input
|
|
563
|
+
: { ...input, idempotencyKey: options.idempotencyKey },
|
|
564
|
+
staffToken: options?.staffToken,
|
|
565
|
+
}, options);
|
|
114
566
|
return data.recordPosCashMovement;
|
|
115
567
|
},
|
|
568
|
+
async list(options) {
|
|
569
|
+
const { skip, take } = backOfficePaging(options);
|
|
570
|
+
return movementPage(skip, take, options);
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
orders: {
|
|
574
|
+
async list(options) {
|
|
575
|
+
const { skip, take } = backOfficePaging(options);
|
|
576
|
+
return orderPage(skip, take, options);
|
|
577
|
+
},
|
|
578
|
+
async get(orderId, options) {
|
|
579
|
+
try {
|
|
580
|
+
const data = await gql(POS_TILL_SALE_QUERY, { orderId }, options);
|
|
581
|
+
return toTillSale(data.posTillOrder);
|
|
582
|
+
}
|
|
583
|
+
catch (error) {
|
|
584
|
+
// An engine older than the ID check refuses the whole document; the sale is still
|
|
585
|
+
// readable, with no ID check. Any other failure is the read's own.
|
|
586
|
+
if (!isUnknownFieldRejection(error))
|
|
587
|
+
throw error;
|
|
588
|
+
const data = await gql(POS_TILL_SALE_QUERY_LEGACY, { orderId }, options);
|
|
589
|
+
return toTillSale({ ...data.posTillOrder, idCheck: null });
|
|
590
|
+
}
|
|
591
|
+
},
|
|
592
|
+
},
|
|
593
|
+
days: {
|
|
594
|
+
async get(input, options) {
|
|
595
|
+
const data = await gql(POS_STORE_DAY_QUERY, { stockLocationId: input.stockLocationId, businessDay: input.businessDay }, options);
|
|
596
|
+
return data.posStoreDay;
|
|
597
|
+
},
|
|
598
|
+
async list(input, options) {
|
|
599
|
+
const data = await gql(POS_STORE_DAYS_QUERY, {
|
|
600
|
+
input: {
|
|
601
|
+
stockLocationId: input.stockLocationId,
|
|
602
|
+
...(input.fromDay === undefined ? {} : { fromDay: input.fromDay }),
|
|
603
|
+
...(input.toDay === undefined ? {} : { toDay: input.toDay }),
|
|
604
|
+
},
|
|
605
|
+
}, options);
|
|
606
|
+
return wholeList(data.posStoreDays.items);
|
|
607
|
+
},
|
|
608
|
+
async close(input, options) {
|
|
609
|
+
const data = await gql(CLOSE_POS_STORE_DAY_MUTATION, {
|
|
610
|
+
input: {
|
|
611
|
+
stockLocationId: input.stockLocationId,
|
|
612
|
+
businessDay: input.businessDay,
|
|
613
|
+
...(input.note === undefined ? {} : { note: input.note }),
|
|
614
|
+
},
|
|
615
|
+
}, options);
|
|
616
|
+
return data.closePosStoreDay;
|
|
617
|
+
},
|
|
618
|
+
async reopen(input, options) {
|
|
619
|
+
const data = await gql(REOPEN_POS_STORE_DAY_MUTATION, {
|
|
620
|
+
input: {
|
|
621
|
+
stockLocationId: input.stockLocationId,
|
|
622
|
+
businessDay: input.businessDay,
|
|
623
|
+
note: input.note,
|
|
624
|
+
},
|
|
625
|
+
}, options);
|
|
626
|
+
return data.reopenPosStoreDay;
|
|
627
|
+
},
|
|
116
628
|
},
|
|
117
629
|
sale: {
|
|
118
630
|
async createCart(input, options) {
|
|
@@ -138,11 +650,96 @@ export function createPosModule(transport) {
|
|
|
138
650
|
const data = await gql(POS_REMOVE_COUPON_CODE_MUTATION, { input: { ...input, idempotencyKey: options?.idempotencyKey } }, options);
|
|
139
651
|
return toCart(data.posRemoveCouponCode);
|
|
140
652
|
},
|
|
653
|
+
async addCustomItem(input, options) {
|
|
654
|
+
const idempotencyKey = requireKey(options);
|
|
655
|
+
const data = await gql(POS_ADD_CUSTOM_ITEM_MUTATION, {
|
|
656
|
+
input: { ...input, idempotencyKey },
|
|
657
|
+
staffToken: options.staffToken,
|
|
658
|
+
...(options.approvalToken === undefined
|
|
659
|
+
? {}
|
|
660
|
+
: { approvalToken: options.approvalToken }),
|
|
661
|
+
}, options);
|
|
662
|
+
return toCart(data.posAddCustomItem);
|
|
663
|
+
},
|
|
664
|
+
async setOrderNote(input, options) {
|
|
665
|
+
const idempotencyKey = requireKey(options);
|
|
666
|
+
const data = await gql(POS_SET_ORDER_NOTE_MUTATION, { input: { ...input, idempotencyKey }, staffToken: options.staffToken }, options);
|
|
667
|
+
return toCart(data.posSetOrderNote);
|
|
668
|
+
},
|
|
669
|
+
async setLineNote(input, options) {
|
|
670
|
+
const idempotencyKey = requireKey(options);
|
|
671
|
+
const data = await gql(POS_SET_LINE_NOTE_MUTATION, { input: { ...input, idempotencyKey }, staffToken: options.staffToken }, options);
|
|
672
|
+
return toCart(data.posSetLineNote);
|
|
673
|
+
},
|
|
674
|
+
async clearCart(orderId, options) {
|
|
675
|
+
const idempotencyKey = requireKey(options);
|
|
676
|
+
const data = await gql(POS_CLEAR_CART_MUTATION, { input: { orderId, idempotencyKey }, staffToken: options.staffToken }, options);
|
|
677
|
+
return data.posClearCart;
|
|
678
|
+
},
|
|
141
679
|
async complete(orderId, options) {
|
|
142
680
|
const idempotencyKey = requireKey(options);
|
|
143
681
|
const data = await gql(POS_COMPLETE_SALE_MUTATION, { input: { orderId, idempotencyKey }, staffToken: options.staffToken }, options);
|
|
144
682
|
return data.posCompleteSale;
|
|
145
683
|
},
|
|
684
|
+
async tillDetails(orderId, options) {
|
|
685
|
+
const redaction = redactionWatcher();
|
|
686
|
+
const data = await transport.graphql({
|
|
687
|
+
api: 'admin',
|
|
688
|
+
query: POS_TILL_SALE_DETAILS_QUERY,
|
|
689
|
+
variables: { id: orderId },
|
|
690
|
+
onExtensions: redaction.onExtensions,
|
|
691
|
+
}, options);
|
|
692
|
+
return redaction.mark(data.order === null ? null : toTillSaleDetails(data.order));
|
|
693
|
+
},
|
|
694
|
+
async receipt(orderId, options) {
|
|
695
|
+
const redaction = redactionWatcher();
|
|
696
|
+
const data = await transport.graphql({
|
|
697
|
+
api: 'admin',
|
|
698
|
+
query: POS_RECEIPT_QUERY,
|
|
699
|
+
variables: { orderId },
|
|
700
|
+
onExtensions: redaction.onExtensions,
|
|
701
|
+
}, options);
|
|
702
|
+
return redaction.mark(data.posReceipt);
|
|
703
|
+
},
|
|
704
|
+
async emailReceipt(input, options) {
|
|
705
|
+
const idempotencyKey = requireKey(options);
|
|
706
|
+
const data = await gql(POS_EMAIL_RECEIPT_MUTATION, {
|
|
707
|
+
input: {
|
|
708
|
+
orderId: input.orderId,
|
|
709
|
+
...(input.emailAddress === undefined ? {} : { emailAddress: input.emailAddress }),
|
|
710
|
+
idempotencyKey,
|
|
711
|
+
},
|
|
712
|
+
staffToken: options.staffToken,
|
|
713
|
+
}, options);
|
|
714
|
+
return data.posEmailReceipt;
|
|
715
|
+
},
|
|
716
|
+
async receiptSharing(orderId, options) {
|
|
717
|
+
const data = await gql(POS_RECEIPT_SHARING_QUERY, { orderId }, options);
|
|
718
|
+
return data.posReceiptSharing;
|
|
719
|
+
},
|
|
720
|
+
async issueReceiptLink(orderId, variant, options) {
|
|
721
|
+
const data = await gql(POS_ISSUE_RECEIPT_LINK_MUTATION, { orderId, variant }, options);
|
|
722
|
+
return data.posIssueReceiptLink;
|
|
723
|
+
},
|
|
724
|
+
async revokeReceiptLink(orderId, variant, options) {
|
|
725
|
+
const data = await gql(REVOKE_POS_RECEIPT_LINK_MUTATION, { orderId, variant }, options);
|
|
726
|
+
return data.revokePosReceiptLink;
|
|
727
|
+
},
|
|
728
|
+
async printReceipt(input, options) {
|
|
729
|
+
const supplied = options?.idempotencyKey;
|
|
730
|
+
const idempotencyKey = typeof supplied === 'string' && supplied.trim() !== ''
|
|
731
|
+
? supplied
|
|
732
|
+
: globalThis.crypto.randomUUID();
|
|
733
|
+
const data = await gql(POS_PRINT_RECEIPT_MUTATION, {
|
|
734
|
+
input: { orderId: input.orderId, variant: input.variant, idempotencyKey },
|
|
735
|
+
staffToken: options?.staffToken,
|
|
736
|
+
}, options);
|
|
737
|
+
return data.posPrintReceipt;
|
|
738
|
+
},
|
|
739
|
+
async giftReceipt(orderId, options) {
|
|
740
|
+
const data = await gql(POS_GIFT_RECEIPT_QUERY, { orderId }, options);
|
|
741
|
+
return data.posReceipt.gift;
|
|
742
|
+
},
|
|
146
743
|
},
|
|
147
744
|
tenders: {
|
|
148
745
|
async cash(input, options) {
|
|
@@ -178,14 +775,77 @@ export function createPosModule(transport) {
|
|
|
178
775
|
const data = await gql(POS_DEVICES_QUERY, {}, options);
|
|
179
776
|
return wholeList(data.posDevices);
|
|
180
777
|
},
|
|
778
|
+
async get(deviceId, options) {
|
|
779
|
+
const data = await gql(POS_DEVICE_DETAIL_QUERY, { id: deviceId }, options);
|
|
780
|
+
return data.posDevice;
|
|
781
|
+
},
|
|
782
|
+
async assignLocation(deviceId, stockLocationId, options) {
|
|
783
|
+
const registerId = options?.registerId;
|
|
784
|
+
const data = await gql(registerId === undefined
|
|
785
|
+
? ASSIGN_POS_DEVICE_LOCATION_MUTATION
|
|
786
|
+
: ASSIGN_POS_DEVICE_LOCATION_WITH_REGISTER_MUTATION, registerId === undefined
|
|
787
|
+
? { deviceId, stockLocationId }
|
|
788
|
+
: { deviceId, stockLocationId, registerId }, options);
|
|
789
|
+
return data.assignPosDeviceLocation;
|
|
790
|
+
},
|
|
791
|
+
async assignRegister(deviceId, registerId, options) {
|
|
792
|
+
const data = await gql(ASSIGN_POS_DEVICE_REGISTER_MUTATION, { deviceId, registerId }, options);
|
|
793
|
+
return data.assignPosDeviceRegister;
|
|
794
|
+
},
|
|
795
|
+
async assignTerminal(deviceId, terminalId, options) {
|
|
796
|
+
const data = await gql(ASSIGN_POS_DEVICE_TERMINAL_MUTATION, { deviceId, terminalId }, options);
|
|
797
|
+
return data.assignPosDeviceMollieTerminal;
|
|
798
|
+
},
|
|
799
|
+
async clearTerminal(deviceId, options) {
|
|
800
|
+
const data = await gql(CLEAR_POS_DEVICE_TERMINAL_MUTATION, { deviceId }, options);
|
|
801
|
+
return data.clearPosDeviceMollieTerminal;
|
|
802
|
+
},
|
|
803
|
+
async create(input, options) {
|
|
804
|
+
const base = {
|
|
805
|
+
label: input.label,
|
|
806
|
+
stockLocationId: input.stockLocationId,
|
|
807
|
+
registerId: input.registerId ?? null,
|
|
808
|
+
};
|
|
809
|
+
if (input.kind === undefined) {
|
|
810
|
+
const data = await gql(CREATE_POS_DEVICE_MUTATION, { input: base }, options);
|
|
811
|
+
return data.createPosDevice;
|
|
812
|
+
}
|
|
813
|
+
if (!POS_DEVICE_KINDS.includes(input.kind))
|
|
814
|
+
throw deviceKindRefusal(input.kind);
|
|
815
|
+
const data = await gql(CREATE_POS_DEVICE_KIND_MUTATION, { input: { ...base, kind: input.kind } }, options);
|
|
816
|
+
return data.createPosDevice;
|
|
817
|
+
},
|
|
181
818
|
async pair(deviceId, options) {
|
|
182
|
-
const
|
|
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);
|
|
183
828
|
return data.generatePosPairingCode;
|
|
184
829
|
},
|
|
185
830
|
async revoke(deviceId, options) {
|
|
186
831
|
const data = await gql(REVOKE_POS_DEVICE_MUTATION, { deviceId }, options);
|
|
187
832
|
return data.revokePosDevice;
|
|
188
833
|
},
|
|
834
|
+
async fleet(options) {
|
|
835
|
+
const data = await gql(POS_DEVICE_FLEET_QUERY, { stockLocationId: options?.stockLocationId ?? null }, options);
|
|
836
|
+
return wholeList(data.posDeviceFleet);
|
|
837
|
+
},
|
|
838
|
+
async offlineSalesToReview(options) {
|
|
839
|
+
return wholeList(await readOfflineSalesToReview(transport, options));
|
|
840
|
+
},
|
|
841
|
+
async lock(deviceId, options) {
|
|
842
|
+
const data = await gql(LOCK_POS_DEVICE_MUTATION, { deviceId }, options);
|
|
843
|
+
return data.lockPosDevice;
|
|
844
|
+
},
|
|
845
|
+
async unlock(deviceId, options) {
|
|
846
|
+
const data = await gql(UNLOCK_POS_DEVICE_MUTATION, { deviceId }, options);
|
|
847
|
+
return data.unlockPosDevice;
|
|
848
|
+
},
|
|
189
849
|
async heartbeat(deviceId, options) {
|
|
190
850
|
const data = await gql(POS_DEVICE_QUERY, { id: deviceId }, options);
|
|
191
851
|
return data.posDevice;
|
|
@@ -201,5 +861,192 @@ export function createPosModule(transport) {
|
|
|
201
861
|
return data.updatePosReceiptNumberingConfig;
|
|
202
862
|
},
|
|
203
863
|
},
|
|
864
|
+
settings: {
|
|
865
|
+
async get(options) {
|
|
866
|
+
const data = await gql(POS_SETTINGS_QUERY, {}, options);
|
|
867
|
+
return data.getPosConfig;
|
|
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
|
+
},
|
|
879
|
+
async setMollieApiKey(apiKey, options) {
|
|
880
|
+
const key = apiKey.trim();
|
|
881
|
+
if (key === '') {
|
|
882
|
+
// Never quotes the argument: a key mistyped as whitespace around it must not reach a log.
|
|
883
|
+
throw new TypeError('setMollieApiKey needs a key; remove the stored one with removeMollieApiKey().');
|
|
884
|
+
}
|
|
885
|
+
const data = await gql(UPDATE_POS_SETTINGS_MUTATION, { input: { mollieApiKey: key } }, options);
|
|
886
|
+
return data.updatePosConfig;
|
|
887
|
+
},
|
|
888
|
+
async removeMollieApiKey(options) {
|
|
889
|
+
// `''` clears (the input documents "Pass empty string to clear").
|
|
890
|
+
const data = await gql(UPDATE_POS_SETTINGS_MUTATION, { input: { mollieApiKey: '' } }, options);
|
|
891
|
+
return data.updatePosConfig;
|
|
892
|
+
},
|
|
893
|
+
async setCashRoundingMode(mode, options) {
|
|
894
|
+
const data = await gql(UPDATE_POS_SETTINGS_MUTATION, { input: { cashRoundingMode: mode } }, options);
|
|
895
|
+
return data.updatePosConfig;
|
|
896
|
+
},
|
|
897
|
+
async readiness(options) {
|
|
898
|
+
const data = await gql(POS_SETUP_READINESS_QUERY, {}, options);
|
|
899
|
+
return data.posSetupReadiness;
|
|
900
|
+
},
|
|
901
|
+
async cashControls(options) {
|
|
902
|
+
const data = await gql(POS_CASH_CONTROLS_QUERY, {}, options);
|
|
903
|
+
return data.getPosConfig?.cashControls ?? null;
|
|
904
|
+
},
|
|
905
|
+
async setCashControls(input, options) {
|
|
906
|
+
// Only the fields given: an omitted threshold keeps the stored one.
|
|
907
|
+
const data = await gql(SET_POS_CASH_CONTROLS_MUTATION, {
|
|
908
|
+
input: input.varianceThreshold === undefined
|
|
909
|
+
? { blindCount: input.blindCount }
|
|
910
|
+
: { blindCount: input.blindCount, varianceThreshold: input.varianceThreshold },
|
|
911
|
+
}, options);
|
|
912
|
+
return data.setPosCashControls;
|
|
913
|
+
},
|
|
914
|
+
async dayControls(options) {
|
|
915
|
+
const data = await gql(POS_DAY_CONTROLS_QUERY, {}, options);
|
|
916
|
+
return data.getPosConfig?.dayControls ?? null;
|
|
917
|
+
},
|
|
918
|
+
async setDayControls(input, options) {
|
|
919
|
+
// The fields given, as given: an omitted idle time keeps the stored one on the engine.
|
|
920
|
+
const sent = {
|
|
921
|
+
businessDayStartsAt: input.businessDayStartsAt,
|
|
922
|
+
autoCloseAfterClosingMinutes: input.autoCloseAfterClosingMinutes,
|
|
923
|
+
};
|
|
924
|
+
if (input.closingTime !== undefined)
|
|
925
|
+
sent.closingTime = input.closingTime;
|
|
926
|
+
if (input.autoCloseIdleMinutes !== undefined) {
|
|
927
|
+
sent.autoCloseIdleMinutes = input.autoCloseIdleMinutes;
|
|
928
|
+
}
|
|
929
|
+
const data = await gql(SET_POS_DAY_CONTROLS_MUTATION, { input: sent }, options);
|
|
930
|
+
return data.setPosDayControls;
|
|
931
|
+
},
|
|
932
|
+
async customItemPolicy(options) {
|
|
933
|
+
const data = await gql(POS_CUSTOM_ITEM_POLICY_QUERY, {}, options);
|
|
934
|
+
return data.posCustomItemPolicy;
|
|
935
|
+
},
|
|
936
|
+
async setCustomItemPolicy(input, options) {
|
|
937
|
+
const data = await gql(SET_POS_CUSTOM_ITEM_POLICY_MUTATION, { input }, options);
|
|
938
|
+
return data.setPosCustomItemPolicy;
|
|
939
|
+
},
|
|
940
|
+
async receipt(options) {
|
|
941
|
+
const data = await gql(POS_RECEIPT_SETTINGS_QUERY, {}, options);
|
|
942
|
+
return data.getPosConfig?.receipt ?? null;
|
|
943
|
+
},
|
|
944
|
+
async setReceipt(input, options) {
|
|
945
|
+
const data = await gql(SET_POS_RECEIPT_SETTINGS_MUTATION, { input }, options);
|
|
946
|
+
return data.setPosReceiptSettings;
|
|
947
|
+
},
|
|
948
|
+
async previewReceipt(input, options) {
|
|
949
|
+
const data = await gql(POS_RECEIPT_PREVIEW_QUERY, { input: input ?? null }, options);
|
|
950
|
+
return data.posReceiptPreview;
|
|
951
|
+
},
|
|
952
|
+
async digitalReceipts(options) {
|
|
953
|
+
const data = await gql(POS_DIGITAL_RECEIPTS_QUERY, {}, options);
|
|
954
|
+
return data.getPosConfig?.receipt ?? null;
|
|
955
|
+
},
|
|
956
|
+
async receiptAccountClaim(options) {
|
|
957
|
+
const data = await gql(POS_RECEIPT_ACCOUNT_CLAIM_QUERY, {}, options);
|
|
958
|
+
return data.getPosConfig?.receipt ?? null;
|
|
959
|
+
},
|
|
960
|
+
async offlineCashSales(options) {
|
|
961
|
+
return readOfflineCashSales(transport, options);
|
|
962
|
+
},
|
|
963
|
+
async setOfflineCashSales(input, options) {
|
|
964
|
+
return writeOfflineCashSales(transport, input, options);
|
|
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
|
+
},
|
|
977
|
+
},
|
|
978
|
+
terminals: {
|
|
979
|
+
async list(options) {
|
|
980
|
+
const data = await gql(POS_MOLLIE_TERMINALS_QUERY, {}, options);
|
|
981
|
+
return wholeList(data.posMollieTerminals);
|
|
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
|
+
},
|
|
991
|
+
},
|
|
992
|
+
staff: {
|
|
993
|
+
async list(options) {
|
|
994
|
+
const data = await gql(POS_STAFF_LIST_QUERY, {}, options);
|
|
995
|
+
return wholeList(data.posStaffList);
|
|
996
|
+
},
|
|
997
|
+
async get(id, options) {
|
|
998
|
+
const data = await gql(POS_STAFF_QUERY, { id }, options);
|
|
999
|
+
return data.posStaff;
|
|
1000
|
+
},
|
|
1001
|
+
async create(input, options) {
|
|
1002
|
+
// Only the fields this module publishes are sent: the engine stores an `administratorId`
|
|
1003
|
+
// link without checking it belongs to the store, so it is not offered here.
|
|
1004
|
+
const { name, pin, role, locale } = input;
|
|
1005
|
+
const checked = withStaffLocale({
|
|
1006
|
+
name,
|
|
1007
|
+
pin,
|
|
1008
|
+
...(role === undefined ? {} : { role }),
|
|
1009
|
+
...(locale === undefined ? {} : { locale }),
|
|
1010
|
+
});
|
|
1011
|
+
const data = await gql(CREATE_POS_STAFF_MUTATION, { input: checked }, options);
|
|
1012
|
+
return data.createPosStaff;
|
|
1013
|
+
},
|
|
1014
|
+
async update(id, input, options) {
|
|
1015
|
+
const checked = withStaffLocale(input);
|
|
1016
|
+
const data = await gql(UPDATE_POS_STAFF_MUTATION, { id, input: checked }, options);
|
|
1017
|
+
return data.updatePosStaff;
|
|
1018
|
+
},
|
|
1019
|
+
async setPin(id, pin, options) {
|
|
1020
|
+
// The engine answers true or throws: there is no "not set" answer to read.
|
|
1021
|
+
await gql(SET_POS_STAFF_PIN_MUTATION, { id, pin }, options);
|
|
1022
|
+
},
|
|
1023
|
+
async grants(id, options) {
|
|
1024
|
+
const data = await gql(POS_STAFF_GRANTS_QUERY, { id }, options);
|
|
1025
|
+
return data.posStaff;
|
|
1026
|
+
},
|
|
1027
|
+
async listGrants(options) {
|
|
1028
|
+
const data = await gql(POS_STAFF_GRANTS_LIST_QUERY, {}, options);
|
|
1029
|
+
return wholeList(data.posStaffList);
|
|
1030
|
+
},
|
|
1031
|
+
async setGrants(id, grants, options) {
|
|
1032
|
+
// Sent as given: the engine's enum refuses a value it does not know, and it dedupes.
|
|
1033
|
+
const data = await gql(SET_POS_STAFF_GRANTS_MUTATION, { id, grants: [...grants] }, options);
|
|
1034
|
+
return data.setPosStaffGrants;
|
|
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
|
+
},
|
|
1040
|
+
},
|
|
1041
|
+
quickKeys: createPosQuickKeysModule(transport),
|
|
1042
|
+
returns: createPosReturnsModule(transport),
|
|
1043
|
+
exchanges: createPosExchangesModule(transport),
|
|
1044
|
+
reports: createPosReportsModule(transport),
|
|
1045
|
+
anomalies: createPosAnomaliesModule(transport),
|
|
1046
|
+
noReceipt: createPosNoReceiptModule(transport),
|
|
1047
|
+
assistedSelling: createPosAssistedSellingModule(transport),
|
|
1048
|
+
payByLink: createPosPayByLinkModule(transport),
|
|
1049
|
+
offlineSales: createPosOfflineSalesModule(transport),
|
|
1050
|
+
giftCards: createPosGiftCardsModule(transport),
|
|
204
1051
|
};
|
|
205
1052
|
}
|