@controleonline/ui-common 1.2.80 → 1.2.81

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 (90) hide show
  1. package/AGENTS.md +8 -0
  2. package/package.json +9 -3
  3. package/src/api/fetch.js +7 -7
  4. package/src/react/components/AddImportModal.js +6 -2
  5. package/src/react/components/BackgroundRuntimeBridge.js +201 -215
  6. package/src/react/components/ConfirmModal.js +44 -9
  7. package/src/react/components/ConfirmModal.styles.js +55 -41
  8. package/src/react/components/CopyDeviceConfigModal.js +193 -0
  9. package/src/react/components/CopyDeviceConfigModal.styles.js +123 -0
  10. package/src/react/components/DefaultProvider.native.js +22 -0
  11. package/src/react/components/DefaultProvider.web.js +25 -1
  12. package/src/react/components/EntityLogBranch.js +482 -0
  13. package/src/react/components/EntityLogCards.js +369 -0
  14. package/src/react/components/EntityLogContent.js +113 -794
  15. package/src/react/components/LinkedOrderProductsTab.js +3 -3
  16. package/src/react/components/PrintService.js +130 -409
  17. package/src/react/components/RemoteCheckoutService.js +2 -2
  18. package/src/react/components/RuntimeBottomNavigationBar.js +141 -146
  19. package/src/react/components/RuntimeFooterMarqueeText.js +137 -0
  20. package/src/react/components/RuntimeInfoFooter.js +12 -15
  21. package/src/react/components/SystemErrorToast.js +49 -29
  22. package/src/react/components/SystemErrorToast.styles.js +43 -38
  23. package/src/react/components/UserAvatar.js +120 -28
  24. package/src/react/config/deviceConfigBootstrap.js +330 -304
  25. package/src/react/hooks/usePrintSpoolEffects.js +161 -0
  26. package/src/react/pages/DeviceDetailPage.js +6 -2882
  27. package/src/react/pages/Devices/detail/DeviceDetailAlertsCommandsSection.js +233 -0
  28. package/src/react/pages/Devices/detail/DeviceDetailHeader.js +138 -0
  29. package/src/react/pages/Devices/detail/DeviceDetailMovementSections.js +167 -0
  30. package/src/react/pages/Devices/detail/DeviceDetailOrdersPrintSection.js +216 -0
  31. package/src/react/pages/Devices/detail/DeviceDetailPaymentSection.js +40 -0
  32. package/src/react/pages/Devices/detail/DeviceDetailPdvConfigSection.js +390 -0
  33. package/src/react/pages/Devices/detail/DeviceDetailRenderers.js +135 -0
  34. package/src/react/pages/Devices/detail/DeviceDetailScreen.js +493 -0
  35. package/src/react/pages/Devices/detail/OptionButtonChip.js +65 -0
  36. package/src/react/pages/Devices/detail/deviceDetailConstants.js +36 -0
  37. package/src/react/pages/Devices/detail/deviceDetailHelpers.js +70 -0
  38. package/src/react/pages/Devices/detail/useDeviceDetailActions.js +483 -0
  39. package/src/react/pages/Devices/detail/useDeviceDetailCopyConfig.js +87 -0
  40. package/src/react/pages/Devices/detail/useDeviceDetailLoaders.js +327 -0
  41. package/src/react/pages/Devices/detail/useDeviceDetailSaves.js +429 -0
  42. package/src/react/pages/Devices/detail/useDeviceDetailStateA.js +484 -0
  43. package/src/react/pages/Devices/detail/useDeviceDetailStateB.js +71 -0
  44. package/src/react/pages/Devices/deviceTypes/index.js +2 -0
  45. package/src/react/pages/Devices/deviceTypes/pdv.js +11 -0
  46. package/src/react/pages/Imports.js +3 -2
  47. package/src/react/pages/IntegrationConfigFields.js +126 -0
  48. package/src/react/pages/IntegrationConfigPage.js +122 -591
  49. package/src/react/pages/IntegrationConfigPage.utils.js +95 -0
  50. package/src/react/print/usePrintButtonController.js +9 -1
  51. package/src/react/services/Getnet/Checkout.js +81 -0
  52. package/src/react/services/Getnet/Getnet.js +77 -0
  53. package/src/react/services/paymentGatewayExecution.js +20 -0
  54. package/src/react/utils/bottomNavigationToolbar.js +161 -0
  55. package/src/react/utils/commercialDocumentOrders.js +18 -6
  56. package/src/react/utils/copyDeviceConfigs.js +198 -0
  57. package/src/react/utils/fileUrl.js +43 -0
  58. package/src/react/utils/importStatus.js +19 -10
  59. package/src/react/utils/logSettings.js +7 -7
  60. package/src/react/utils/maintenanceSettings.js +16 -0
  61. package/src/react/utils/paymentDevices.js +6 -0
  62. package/src/react/utils/printManagedPrinter.js +45 -0
  63. package/src/react/utils/printRouting.js +63 -0
  64. package/src/react/utils/printSpoolUtils.js +119 -0
  65. package/src/react/utils/printerDevices.js +368 -368
  66. package/src/react/utils/runtimeFooter.js +10 -19
  67. package/src/react/utils/shopFranchises.js +186 -65
  68. package/src/react/utils/systemErrorMessage.js +71 -67
  69. package/src/store/device_config/customActions.js +119 -30
  70. package/src/tests/browser/manager/bottom-navigation-role-toolbar.spec.js +353 -0
  71. package/src/tests/browser/manager/device-detail-alias-save.spec.js +345 -0
  72. package/src/tests/browser/manager/device-detail-copy-config.spec.js +365 -0
  73. package/src/tests/browser/manager/runtime-footer-marquee.spec.js +262 -0
  74. package/src/tests/browser/manager/theme-confirm-toast.spec.js +236 -0
  75. package/src/tests/react/components/RuntimeFooterMarqueeText.test.js +171 -0
  76. package/src/tests/react/components/UserAvatar.test.js +6 -2
  77. package/src/tests/react/components/themeAwareModals.test.mjs +60 -0
  78. package/src/tests/react/config/deviceConfigBootstrap.test.js +104 -66
  79. package/src/tests/react/pages/deviceDetailDelete.test.js +78 -0
  80. package/src/tests/react/pages/receitaFederalIntegrationContract.test.mjs +48 -0
  81. package/src/tests/react/utils/bottomNavigationToolbar.test.js +222 -0
  82. package/src/tests/react/utils/copyDeviceConfigs.test.mjs +127 -0
  83. package/src/tests/react/utils/fileUrl.test.js +38 -0
  84. package/src/tests/react/utils/importStatus.test.js +26 -9
  85. package/src/tests/react/utils/passwordPolicy.test.js +27 -0
  86. package/src/tests/react/utils/printRouting.test.mjs +86 -0
  87. package/src/tests/react/utils/printSpoolUtils.test.mjs +52 -0
  88. package/src/tests/react/utils/runtimeFooter.test.js +7 -0
  89. package/src/tests/react/utils/shopFranchises.test.js +121 -115
  90. package/src/tests/react/utils/systemErrorMessage.test.js +32 -59
@@ -6,17 +6,17 @@ import {
6
6
  normalizeBooleanConfig,
7
7
  SHOP_LOYALTY_COUPONS_ENABLED_CONFIG_KEY,
8
8
  } from '@controleonline/ui-common/src/react/utils/shopConfig';
9
-
9
+
10
10
  export const CIELO_DEVICES = ['quantum', 'ingenico', 'positivo'];
11
11
  export const SUPPORTED_POS_GATEWAYS = ['cielo', 'infinite-pay'];
12
12
  export const DEVICE_ALERT_SOUND_ENABLED_KEY = 'notification-sound-enabled';
13
13
  export const DEVICE_ALERT_SOUND_URL_KEY = 'notification-sound-url';
14
- export const DEVICE_ORDER_VISIBILITY_KEY = 'pos-order-visibility';
15
- export const DEVICE_ORDER_VISIBILITY_DEVICE = 'device';
16
- export const DEVICE_ORDER_VISIBILITY_COMPANY = 'company';
17
- export const POS_DELIVERY_ENABLED_CONFIG_KEY = 'pos-delivery-enabled';
18
- export const DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY =
19
- 'device-runtime-debug-info-enabled';
14
+ export const DEVICE_ORDER_VISIBILITY_KEY = 'pos-order-visibility';
15
+ export const DEVICE_ORDER_VISIBILITY_DEVICE = 'device';
16
+ export const DEVICE_ORDER_VISIBILITY_COMPANY = 'company';
17
+ export const POS_DELIVERY_ENABLED_CONFIG_KEY = 'pos-delivery-enabled';
18
+ export const DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY =
19
+ 'device-runtime-debug-info-enabled';
20
20
  export const DISPLAY_AUTO_PRINT_PRODUCT_CONFIG_KEY =
21
21
  'display-auto-print-product';
22
22
  export const DISPLAY_ALLOW_PRINTER_CHANGE_CONFIG_KEY =
@@ -27,6 +27,8 @@ export const DISPLAY_SIZE_MIN = 1;
27
27
  export const DISPLAY_SIZE_MAX = 10;
28
28
  export const DISPLAY_SIZE_DEFAULT = 5;
29
29
  export const POS_OPERATION_MODE_CONFIG_KEY = 'pos-operation-mode';
30
+ /** Independent of operation mode: whether this device may run local charge/payment. */
31
+ export const POS_LOCAL_CHARGE_ENABLED_CONFIG_KEY = 'pos-local-charge-enabled';
30
32
  export const POS_PRODUCT_SHOWCASE_CONFIG_KEY = 'pos-product-showcase-id';
31
33
  export const DEVICE_ANDROID_KIOSK_ENABLED_CONFIG_KEY =
32
34
  'android-kiosk-enabled';
@@ -35,9 +37,9 @@ export const DEVICE_ANDROID_LAUNCHER_ENABLED_CONFIG_KEY =
35
37
  export const POS_AUTO_PRINT_ENABLED_CONFIG_KEY = 'pos-auto-print-enabled';
36
38
  export const POS_CASH_MANAGEMENT_MODE_CONFIG_KEY =
37
39
  'pos-cash-management-mode';
38
- export const POS_CHECK_ORDER_TYPE_CONFIG_KEY = 'check-order-type';
39
- export const POS_CHECK_ORDER_MANAGEMENT_MODE_CONFIG_KEY =
40
- 'check-order-management-mode';
40
+ export const POS_CHECK_ORDER_TYPE_CONFIG_KEY = 'check-order-type';
41
+ export const POS_CHECK_ORDER_MANAGEMENT_MODE_CONFIG_KEY =
42
+ 'check-order-management-mode';
41
43
  export const POS_OPERATION_MODE_COUNTER = 'counter';
42
44
  export const POS_OPERATION_MODE_WAITER = 'waiter';
43
45
  export const POS_OPERATION_MODE_TOTEM = 'totem';
@@ -47,27 +49,27 @@ export const POS_CHECK_ORDER_TYPE_NONE = 'none';
47
49
  export const POS_CHECK_ORDER_TYPE_TAB = 'tab';
48
50
  export const POS_CHECK_ORDER_TYPE_TABLE = 'table';
49
51
  export const POS_CHECK_ORDER_TYPE_STAMP = 'stamp';
50
- export const POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE = 'manage';
51
- export const POS_CHECK_ORDER_MANAGEMENT_MODE_EXISTING_ONLY = 'existing-only';
52
- export const POS_OPERATION_MODE_DEFAULT = POS_OPERATION_MODE_CASHIER;
53
- export const POS_PRINT_MODE_ORDER = 'order';
54
- export const POS_PRINT_MODE_FORM = 'form';
55
- export const POS_PRINT_MODE_DEFAULT = POS_PRINT_MODE_ORDER;
56
- export const POS_CASH_MANAGEMENT_MODE_CASH_REGISTER = 'cash-register';
57
- export const POS_CASH_MANAGEMENT_MODE_DAILY = 'daily';
58
- export const POS_CASH_MANAGEMENT_MODE_DEFAULT =
59
- POS_CASH_MANAGEMENT_MODE_CASH_REGISTER;
60
- export const POS_OPERATION_MODE_OPTIONS = [
61
- {
62
- value: POS_OPERATION_MODE_COUNTER,
63
- translationKey: 'counterService',
64
- descriptionKey: 'counterServiceDescription',
65
- },
66
- {
67
- value: POS_OPERATION_MODE_WAITER,
68
- translationKey: 'waiterService',
69
- descriptionKey: 'waiterServiceDescription',
70
- },
52
+ export const POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE = 'manage';
53
+ export const POS_CHECK_ORDER_MANAGEMENT_MODE_EXISTING_ONLY = 'existing-only';
54
+ export const POS_OPERATION_MODE_DEFAULT = POS_OPERATION_MODE_CASHIER;
55
+ export const POS_PRINT_MODE_ORDER = 'order';
56
+ export const POS_PRINT_MODE_FORM = 'form';
57
+ export const POS_PRINT_MODE_DEFAULT = POS_PRINT_MODE_ORDER;
58
+ export const POS_CASH_MANAGEMENT_MODE_CASH_REGISTER = 'cash-register';
59
+ export const POS_CASH_MANAGEMENT_MODE_DAILY = 'daily';
60
+ export const POS_CASH_MANAGEMENT_MODE_DEFAULT =
61
+ POS_CASH_MANAGEMENT_MODE_CASH_REGISTER;
62
+ export const POS_OPERATION_MODE_OPTIONS = [
63
+ {
64
+ value: POS_OPERATION_MODE_COUNTER,
65
+ translationKey: 'counterService',
66
+ descriptionKey: 'counterServiceDescription',
67
+ },
68
+ {
69
+ value: POS_OPERATION_MODE_WAITER,
70
+ translationKey: 'waiterService',
71
+ descriptionKey: 'waiterServiceDescription',
72
+ },
71
73
  {
72
74
  value: POS_OPERATION_MODE_TOTEM,
73
75
  translationKey: 'selfServiceKiosk',
@@ -82,19 +84,19 @@ export const POS_OPERATION_MODE_OPTIONS = [
82
84
  value: POS_OPERATION_MODE_CASHIER,
83
85
  translationKey: 'cashierPOS',
84
86
  descriptionKey: 'cashierPOSDescription',
85
- },
86
- ];
87
-
88
- export const DEFAULT_DEVICE_CONFIGS = {
89
- 'pos-type': 'full',
90
- 'print-mode': 'order',
91
- 'check-type': 'manual',
92
- 'product-input-type': 'manual',
93
- 'selection-type': 'single',
94
- sound: '0',
95
- vibration: '0',
96
- [DEVICE_ORDER_VISIBILITY_KEY]: DEVICE_ORDER_VISIBILITY_DEVICE,
97
- [POS_DELIVERY_ENABLED_CONFIG_KEY]: '1',
87
+ },
88
+ ];
89
+
90
+ export const DEFAULT_DEVICE_CONFIGS = {
91
+ 'pos-type': 'full',
92
+ 'print-mode': 'order',
93
+ 'check-type': 'manual',
94
+ 'product-input-type': 'manual',
95
+ 'selection-type': 'single',
96
+ sound: '0',
97
+ vibration: '0',
98
+ [DEVICE_ORDER_VISIBILITY_KEY]: DEVICE_ORDER_VISIBILITY_DEVICE,
99
+ [POS_DELIVERY_ENABLED_CONFIG_KEY]: '1',
98
100
  [DEVICE_ALERT_SOUND_ENABLED_KEY]: '0',
99
101
  [DEVICE_ALERT_SOUND_URL_KEY]: '',
100
102
  [DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY]: '0',
@@ -110,24 +112,24 @@ export const DEFAULT_DEVICE_CONFIGS = {
110
112
  [POS_AUTO_PRINT_ENABLED_CONFIG_KEY]: '0',
111
113
  [POS_CASH_MANAGEMENT_MODE_CONFIG_KEY]: POS_CASH_MANAGEMENT_MODE_DEFAULT,
112
114
  };
113
-
114
- export const isTruthyValue = value =>
115
- value === true || value === '1' || value === 1 || value === 'true';
116
-
117
- export const isMissingConfigValue = value =>
118
- value === undefined || value === null || value === '';
119
-
115
+
116
+ export const isTruthyValue = value =>
117
+ value === true || value === '1' || value === 1 || value === 'true';
118
+
119
+ export const isMissingConfigValue = value =>
120
+ value === undefined || value === null || value === '';
121
+
120
122
  export const parseConfigsObject = configs => {
121
123
  if (!configs) return {};
122
-
123
- if (typeof configs === 'string') {
124
- try {
125
- const parsed = JSON.parse(configs);
126
- return parsed && typeof parsed === 'object' ? parsed : {};
127
- } catch {
128
- return {};
129
- }
130
- }
124
+
125
+ if (typeof configs === 'string') {
126
+ try {
127
+ const parsed = JSON.parse(configs);
128
+ return parsed && typeof parsed === 'object' ? parsed : {};
129
+ } catch {
130
+ return {};
131
+ }
132
+ }
131
133
 
132
134
  return typeof configs === 'object' ? {...configs} : {};
133
135
  };
@@ -164,33 +166,33 @@ export const isDisplaySideBreakEnabled = configs =>
164
166
  export const normalizePosOperationMode = value => {
165
167
  const normalizedValue = String(value || '')
166
168
  .trim()
167
- .toLowerCase()
168
- .normalize('NFD')
169
- .replace(/[\u0300-\u036f]/g, '')
170
- .replace(/[\s_]/g, '-');
171
-
172
- if (
173
- [
174
- POS_OPERATION_MODE_COUNTER,
175
- 'balcao',
176
- 'counter-service',
177
- 'front-counter',
178
- ].includes(normalizedValue)
179
- ) {
180
- return POS_OPERATION_MODE_COUNTER;
181
- }
182
-
183
- if (
184
- [
185
- POS_OPERATION_MODE_WAITER,
186
- 'garcon',
187
- 'garcom',
188
- 'table-service',
189
- ].includes(normalizedValue)
190
- ) {
191
- return POS_OPERATION_MODE_WAITER;
192
- }
193
-
169
+ .toLowerCase()
170
+ .normalize('NFD')
171
+ .replace(/[\u0300-\u036f]/g, '')
172
+ .replace(/[\s_]/g, '-');
173
+
174
+ if (
175
+ [
176
+ POS_OPERATION_MODE_COUNTER,
177
+ 'balcao',
178
+ 'counter-service',
179
+ 'front-counter',
180
+ ].includes(normalizedValue)
181
+ ) {
182
+ return POS_OPERATION_MODE_COUNTER;
183
+ }
184
+
185
+ if (
186
+ [
187
+ POS_OPERATION_MODE_WAITER,
188
+ 'garcon',
189
+ 'garcom',
190
+ 'table-service',
191
+ ].includes(normalizedValue)
192
+ ) {
193
+ return POS_OPERATION_MODE_WAITER;
194
+ }
195
+
194
196
  if (
195
197
  [
196
198
  POS_OPERATION_MODE_TOTEM,
@@ -221,38 +223,38 @@ export const normalizePosOperationMode = value => {
221
223
  POS_OPERATION_MODE_CASHIER,
222
224
  'pdv',
223
225
  'pos',
224
- 'checkout',
225
- 'cashier-pos',
226
- ].includes(normalizedValue)
227
- ) {
228
- return POS_OPERATION_MODE_CASHIER;
229
- }
230
-
226
+ 'checkout',
227
+ 'cashier-pos',
228
+ ].includes(normalizedValue)
229
+ ) {
230
+ return POS_OPERATION_MODE_CASHIER;
231
+ }
232
+
231
233
  return '';
232
234
  };
233
-
234
- export const resolvePosOperationMode = configs =>
235
- normalizePosOperationMode(
236
- parseConfigsObject(configs)?.[POS_OPERATION_MODE_CONFIG_KEY],
237
- );
238
-
239
- export const normalizePosCheckOrderType = value => {
240
- const normalizedValue = String(value || '')
241
- .trim()
242
- .toLowerCase()
243
- .normalize('NFD')
244
- .replace(/[\u0300-\u036f]/g, '')
245
- .replace(/[\s_]/g, '-');
246
-
235
+
236
+ export const resolvePosOperationMode = configs =>
237
+ normalizePosOperationMode(
238
+ parseConfigsObject(configs)?.[POS_OPERATION_MODE_CONFIG_KEY],
239
+ );
240
+
241
+ export const normalizePosCheckOrderType = value => {
242
+ const normalizedValue = String(value || '')
243
+ .trim()
244
+ .toLowerCase()
245
+ .normalize('NFD')
246
+ .replace(/[\u0300-\u036f]/g, '')
247
+ .replace(/[\s_]/g, '-');
248
+
247
249
  if (
248
250
  [
249
251
  POS_CHECK_ORDER_TYPE_TAB,
250
252
  'tab',
251
253
  ].includes(normalizedValue)
252
- ) {
253
- return POS_CHECK_ORDER_TYPE_TAB;
254
- }
255
-
254
+ ) {
255
+ return POS_CHECK_ORDER_TYPE_TAB;
256
+ }
257
+
256
258
  if (
257
259
  [
258
260
  POS_CHECK_ORDER_TYPE_TABLE,
@@ -274,7 +276,7 @@ export const normalizePosCheckOrderType = value => {
274
276
 
275
277
  return POS_CHECK_ORDER_TYPE_NONE;
276
278
  };
277
-
279
+
278
280
  export const resolvePosCheckOrderType = configs =>
279
281
  normalizePosCheckOrderType(
280
282
  parseConfigsObject(configs)?.[POS_CHECK_ORDER_TYPE_CONFIG_KEY],
@@ -303,56 +305,56 @@ export const resolvePosCheckOrderTypeForShop = (
303
305
 
304
306
  return resolvedType;
305
307
  };
306
-
307
- export const normalizePosCheckOrderManagementMode = value => {
308
- const normalizedValue = String(value || '')
309
- .trim()
310
- .toLowerCase()
311
- .normalize('NFD')
312
- .replace(/[\u0300-\u036f]/g, '')
313
- .replace(/[\s_]/g, '-');
314
-
315
- if (
316
- [
317
- POS_CHECK_ORDER_MANAGEMENT_MODE_EXISTING_ONLY,
318
- 'existing',
319
- 'existing-open',
320
- 'opened-only',
321
- 'already-open',
322
- 'use-open-only',
323
- 'use-existing-only',
324
- ].includes(normalizedValue)
325
- ) {
326
- return POS_CHECK_ORDER_MANAGEMENT_MODE_EXISTING_ONLY;
327
- }
328
-
329
- if (
330
- [
331
- POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE,
332
- 'open-close',
333
- 'open-and-close',
334
- 'full',
335
- 'manage-open-close',
336
- ].includes(normalizedValue)
337
- ) {
338
- return POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE;
339
- }
340
-
341
- return POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE;
342
- };
343
-
344
- export const resolvePosCheckOrderManagementMode = configs =>
345
- normalizePosCheckOrderManagementMode(
346
- parseConfigsObject(configs)?.[POS_CHECK_ORDER_MANAGEMENT_MODE_CONFIG_KEY],
347
- );
348
-
349
- export const canManagePosCheckOrders = configs =>
350
- resolvePosCheckOrderManagementMode(configs) ===
351
- POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE;
352
-
353
- export const usesPosCheckLinkedOrder = configs =>
354
- resolvePosCheckOrderType(configs) !== POS_CHECK_ORDER_TYPE_NONE;
355
-
308
+
309
+ export const normalizePosCheckOrderManagementMode = value => {
310
+ const normalizedValue = String(value || '')
311
+ .trim()
312
+ .toLowerCase()
313
+ .normalize('NFD')
314
+ .replace(/[\u0300-\u036f]/g, '')
315
+ .replace(/[\s_]/g, '-');
316
+
317
+ if (
318
+ [
319
+ POS_CHECK_ORDER_MANAGEMENT_MODE_EXISTING_ONLY,
320
+ 'existing',
321
+ 'existing-open',
322
+ 'opened-only',
323
+ 'already-open',
324
+ 'use-open-only',
325
+ 'use-existing-only',
326
+ ].includes(normalizedValue)
327
+ ) {
328
+ return POS_CHECK_ORDER_MANAGEMENT_MODE_EXISTING_ONLY;
329
+ }
330
+
331
+ if (
332
+ [
333
+ POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE,
334
+ 'open-close',
335
+ 'open-and-close',
336
+ 'full',
337
+ 'manage-open-close',
338
+ ].includes(normalizedValue)
339
+ ) {
340
+ return POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE;
341
+ }
342
+
343
+ return POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE;
344
+ };
345
+
346
+ export const resolvePosCheckOrderManagementMode = configs =>
347
+ normalizePosCheckOrderManagementMode(
348
+ parseConfigsObject(configs)?.[POS_CHECK_ORDER_MANAGEMENT_MODE_CONFIG_KEY],
349
+ );
350
+
351
+ export const canManagePosCheckOrders = configs =>
352
+ resolvePosCheckOrderManagementMode(configs) ===
353
+ POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE;
354
+
355
+ export const usesPosCheckLinkedOrder = configs =>
356
+ resolvePosCheckOrderType(configs) !== POS_CHECK_ORDER_TYPE_NONE;
357
+
356
358
  export const isPosTotemMode = configs =>
357
359
  resolvePosOperationMode(configs) === POS_OPERATION_MODE_TOTEM;
358
360
 
@@ -393,48 +395,48 @@ export const shouldEnableAndroidLauncherMode = ({
393
395
  String(appType || '').trim().toUpperCase() === 'POS' &&
394
396
  platform === 'android' &&
395
397
  isAndroidLauncherEnabled(configs);
396
-
398
+
397
399
  export const isPosCounterMode = configs =>
398
400
  resolvePosOperationMode(configs) === POS_OPERATION_MODE_COUNTER;
399
401
 
400
402
  export const isPosSelfServiceMode = configs =>
401
403
  isPosTotemMode(configs) || isPosCounterMode(configs);
402
-
403
- export const resolvePosPrintMode = configs => {
404
- const value = String(parseConfigsObject(configs)?.['print-mode'] || '')
405
- .trim()
406
- .toLowerCase();
407
-
408
- return value === POS_PRINT_MODE_FORM
409
- ? POS_PRINT_MODE_FORM
410
- : POS_PRINT_MODE_DEFAULT;
411
- };
412
-
413
- export const isPosAutoPrintEnabled = configs => {
414
- const parsedConfigs = parseConfigsObject(configs);
415
- const storedValue = parsedConfigs?.[POS_AUTO_PRINT_ENABLED_CONFIG_KEY];
416
-
417
- if (
418
- storedValue === undefined ||
419
- storedValue === null ||
420
- String(storedValue).trim() === ''
421
- ) {
422
- return !isPosCounterMode(parsedConfigs);
423
- }
424
-
425
- return isTruthyValue(storedValue);
426
- };
427
-
428
- export const resolvePosCashManagementMode = configs => {
429
- const normalizedValue = String(
430
- parseConfigsObject(configs)?.[POS_CASH_MANAGEMENT_MODE_CONFIG_KEY] || '',
431
- )
432
- .trim()
433
- .toLowerCase()
434
- .normalize('NFD')
435
- .replace(/[\u0300-\u036f]/g, '')
436
- .replace(/[\s_]/g, '-');
437
-
404
+
405
+ export const resolvePosPrintMode = configs => {
406
+ const value = String(parseConfigsObject(configs)?.['print-mode'] || '')
407
+ .trim()
408
+ .toLowerCase();
409
+
410
+ return value === POS_PRINT_MODE_FORM
411
+ ? POS_PRINT_MODE_FORM
412
+ : POS_PRINT_MODE_DEFAULT;
413
+ };
414
+
415
+ export const isPosAutoPrintEnabled = configs => {
416
+ const parsedConfigs = parseConfigsObject(configs);
417
+ const storedValue = parsedConfigs?.[POS_AUTO_PRINT_ENABLED_CONFIG_KEY];
418
+
419
+ if (
420
+ storedValue === undefined ||
421
+ storedValue === null ||
422
+ String(storedValue).trim() === ''
423
+ ) {
424
+ return !isPosCounterMode(parsedConfigs);
425
+ }
426
+
427
+ return isTruthyValue(storedValue);
428
+ };
429
+
430
+ export const resolvePosCashManagementMode = configs => {
431
+ const normalizedValue = String(
432
+ parseConfigsObject(configs)?.[POS_CASH_MANAGEMENT_MODE_CONFIG_KEY] || '',
433
+ )
434
+ .trim()
435
+ .toLowerCase()
436
+ .normalize('NFD')
437
+ .replace(/[\u0300-\u036f]/g, '')
438
+ .replace(/[\s_]/g, '-');
439
+
438
440
  if (
439
441
  normalizedValue === POS_CASH_MANAGEMENT_MODE_DAILY
440
442
  ) {
@@ -446,25 +448,25 @@ export const resolvePosCashManagementMode = configs => {
446
448
  ) {
447
449
  return POS_CASH_MANAGEMENT_MODE_CASH_REGISTER;
448
450
  }
449
-
450
- return POS_CASH_MANAGEMENT_MODE_DEFAULT;
451
- };
452
-
451
+
452
+ return POS_CASH_MANAGEMENT_MODE_DEFAULT;
453
+ };
454
+
453
455
  export const shouldUsePosCashRegisterLifecycle = configs => {
454
456
  if (isPosTotemMode(configs)) {
455
457
  return false;
456
458
  }
457
-
458
- if (isPosCounterMode(configs)) {
459
- return (
460
- resolvePosCashManagementMode(configs) ===
461
- POS_CASH_MANAGEMENT_MODE_CASH_REGISTER
462
- );
463
- }
464
-
465
- return true;
466
- };
467
-
459
+
460
+ if (isPosCounterMode(configs)) {
461
+ return (
462
+ resolvePosCashManagementMode(configs) ===
463
+ POS_CASH_MANAGEMENT_MODE_CASH_REGISTER
464
+ );
465
+ }
466
+
467
+ return true;
468
+ };
469
+
468
470
  export const isPosCashRegisterOpen = configs => {
469
471
  if (!shouldUsePosCashRegisterLifecycle(configs)) {
470
472
  return true;
@@ -484,53 +486,77 @@ export const isPosCashRegisterOpen = configs => {
484
486
 
485
487
  return closedValue === 0 || closedValue === '0';
486
488
  };
487
-
488
- export const isPosCashRegisterClosed = configs =>
489
- !isPosCashRegisterOpen(configs);
490
-
489
+
490
+ export const isPosCashRegisterClosed = configs =>
491
+ !isPosCashRegisterOpen(configs);
492
+
493
+ export const normalizePosLocalChargeEnabled = (value, operationMode) => {
494
+ if (!isMissingConfigValue(value)) {
495
+ return isTruthyValue(value);
496
+ }
497
+
498
+ const mode = normalizePosOperationMode(operationMode);
499
+ // Waiter defaults to no local charge; all other modes keep legacy charge capability.
500
+ return mode !== POS_OPERATION_MODE_WAITER;
501
+ };
502
+
503
+ /**
504
+ * Whether the device is allowed to execute local payment/charge.
505
+ * Independent of pos-operation-mode and pay_before_production.
506
+ * Missing config preserves legacy: waiter=false, other modes=true.
507
+ */
508
+ export const isPosLocalChargeEnabled = configs => {
509
+ const parsed = parseConfigsObject(configs);
510
+ return normalizePosLocalChargeEnabled(
511
+ parsed?.[POS_LOCAL_CHARGE_ENABLED_CONFIG_KEY],
512
+ parsed?.[POS_OPERATION_MODE_CONFIG_KEY],
513
+ );
514
+ };
515
+
491
516
  export const getPosOperationModeOption = mode => {
517
+
492
518
  const normalizedMode = normalizePosOperationMode(mode);
493
519
 
494
520
  return POS_OPERATION_MODE_OPTIONS.find(
495
521
  option => option.value === normalizedMode,
496
522
  );
497
523
  };
498
-
499
- export const resolveDeviceOrderVisibility = configs => {
500
- const parsedConfigs = parseConfigsObject(configs);
501
- const value = String(parsedConfigs?.[DEVICE_ORDER_VISIBILITY_KEY] || '')
502
- .trim()
503
- .toLowerCase();
504
-
505
- return value === DEVICE_ORDER_VISIBILITY_COMPANY
506
- ? DEVICE_ORDER_VISIBILITY_COMPANY
507
- : DEVICE_ORDER_VISIBILITY_DEVICE;
508
- };
509
-
510
- export const canDeviceViewCompanyOrders = configs =>
511
- resolveDeviceOrderVisibility(configs) === DEVICE_ORDER_VISIBILITY_COMPANY;
512
-
513
- export const isPosDeliveryEnabled = configs => {
514
- const parsedConfigs = parseConfigsObject(configs);
515
- const storedValue = parsedConfigs?.[POS_DELIVERY_ENABLED_CONFIG_KEY];
516
-
517
- if (isMissingConfigValue(storedValue)) {
518
- return true;
519
- }
520
-
521
- return isTruthyValue(storedValue);
522
- };
523
-
524
- export const isDeviceRuntimeDebugInfoEnabled = configs =>
525
- isTruthyValue(
526
- parseConfigsObject(configs)?.[DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY],
527
- );
528
-
529
- export const canDisplayChangePrinter = configs =>
530
- isTruthyValue(
531
- parseConfigsObject(configs)?.[DISPLAY_ALLOW_PRINTER_CHANGE_CONFIG_KEY],
532
- );
533
-
524
+
525
+ export const resolveDeviceOrderVisibility = configs => {
526
+ const parsedConfigs = parseConfigsObject(configs);
527
+ const value = String(parsedConfigs?.[DEVICE_ORDER_VISIBILITY_KEY] || '')
528
+ .trim()
529
+ .toLowerCase();
530
+
531
+ return value === DEVICE_ORDER_VISIBILITY_COMPANY
532
+ ? DEVICE_ORDER_VISIBILITY_COMPANY
533
+ : DEVICE_ORDER_VISIBILITY_DEVICE;
534
+ };
535
+
536
+ export const canDeviceViewCompanyOrders = configs =>
537
+ resolveDeviceOrderVisibility(configs) === DEVICE_ORDER_VISIBILITY_COMPANY;
538
+
539
+ export const isPosDeliveryEnabled = configs => {
540
+ const parsedConfigs = parseConfigsObject(configs);
541
+ const storedValue = parsedConfigs?.[POS_DELIVERY_ENABLED_CONFIG_KEY];
542
+
543
+ if (isMissingConfigValue(storedValue)) {
544
+ return true;
545
+ }
546
+
547
+ return isTruthyValue(storedValue);
548
+ };
549
+
550
+ export const isDeviceRuntimeDebugInfoEnabled = configs =>
551
+ isTruthyValue(
552
+ parseConfigsObject(configs)?.[DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY],
553
+ );
554
+
555
+ export const canDisplayChangePrinter = configs =>
556
+ isTruthyValue(
557
+ parseConfigsObject(configs)?.[DISPLAY_ALLOW_PRINTER_CHANGE_CONFIG_KEY],
558
+ );
559
+
534
560
  export const resolveDefaultGateway = deviceInfo => {
535
561
  const manufacturer = String(deviceInfo?.manufacturer || '').toLowerCase();
536
562
  const isEmulator = isTruthyValue(deviceInfo?.isEmulator);
@@ -550,63 +576,63 @@ export const normalizePersistedGateway = value => {
550
576
  ? normalizedValue
551
577
  : '';
552
578
  };
553
-
554
- export const buildDefaultDeviceConfigs = ({configs, appVersion, deviceInfo}) => {
555
- let nextConfigs = parseConfigsObject(configs);
556
- let needsUpdate = false;
557
-
558
- const metricsConfigs = appendScreenMetrics(nextConfigs);
559
- if (hasScreenMetricsChanges(nextConfigs, metricsConfigs)) {
560
- nextConfigs = metricsConfigs;
561
- needsUpdate = true;
562
- }
563
-
564
- Object.entries(DEFAULT_DEVICE_CONFIGS).forEach(([key, defaultValue]) => {
565
- if (isMissingConfigValue(nextConfigs[key])) {
566
- nextConfigs[key] = defaultValue;
567
- needsUpdate = true;
568
- }
569
- });
570
-
571
- if (isMissingConfigValue(nextConfigs['config-version'])) {
572
- nextConfigs['config-version'] = appVersion || deviceInfo?.appVersion || '1.0.0';
573
- needsUpdate = true;
574
- }
575
-
576
- if (isMissingConfigValue(nextConfigs['pos-gateway'])) {
577
- nextConfigs['pos-gateway'] = resolveDefaultGateway(deviceInfo);
578
- needsUpdate = true;
579
- }
580
-
581
- return {nextConfigs, needsUpdate};
582
- };
583
-
579
+
580
+ export const buildDefaultDeviceConfigs = ({configs, appVersion, deviceInfo}) => {
581
+ let nextConfigs = parseConfigsObject(configs);
582
+ let needsUpdate = false;
583
+
584
+ const metricsConfigs = appendScreenMetrics(nextConfigs);
585
+ if (hasScreenMetricsChanges(nextConfigs, metricsConfigs)) {
586
+ nextConfigs = metricsConfigs;
587
+ needsUpdate = true;
588
+ }
589
+
590
+ Object.entries(DEFAULT_DEVICE_CONFIGS).forEach(([key, defaultValue]) => {
591
+ if (isMissingConfigValue(nextConfigs[key])) {
592
+ nextConfigs[key] = defaultValue;
593
+ needsUpdate = true;
594
+ }
595
+ });
596
+
597
+ if (isMissingConfigValue(nextConfigs['config-version'])) {
598
+ nextConfigs['config-version'] = appVersion || deviceInfo?.appVersion || '1.0.0';
599
+ needsUpdate = true;
600
+ }
601
+
602
+ if (isMissingConfigValue(nextConfigs['pos-gateway'])) {
603
+ nextConfigs['pos-gateway'] = resolveDefaultGateway(deviceInfo);
604
+ needsUpdate = true;
605
+ }
606
+
607
+ return {nextConfigs, needsUpdate};
608
+ };
609
+
584
610
  export const buildProviderManagedDeviceConfigs = ({
585
611
  configs,
586
612
  appVersion,
587
613
  deviceInfo,
588
614
  }) => {
589
- let nextConfigs = parseConfigsObject(configs);
590
- let needsUpdate = false;
591
-
592
- const metricsConfigs = appendScreenMetrics(nextConfigs);
593
- if (hasScreenMetricsChanges(nextConfigs, metricsConfigs)) {
594
- nextConfigs = metricsConfigs;
595
- needsUpdate = true;
596
- }
597
-
598
- const nextVersion = appVersion || deviceInfo?.appVersion || '1.0.0';
599
- if (nextVersion && nextConfigs['config-version'] !== nextVersion) {
600
- nextConfigs['config-version'] = nextVersion;
601
- needsUpdate = true;
602
- }
603
-
615
+ let nextConfigs = parseConfigsObject(configs);
616
+ let needsUpdate = false;
617
+
618
+ const metricsConfigs = appendScreenMetrics(nextConfigs);
619
+ if (hasScreenMetricsChanges(nextConfigs, metricsConfigs)) {
620
+ nextConfigs = metricsConfigs;
621
+ needsUpdate = true;
622
+ }
623
+
624
+ const nextVersion = appVersion || deviceInfo?.appVersion || '1.0.0';
625
+ if (nextVersion && nextConfigs['config-version'] !== nextVersion) {
626
+ nextConfigs['config-version'] = nextVersion;
627
+ needsUpdate = true;
628
+ }
629
+
604
630
  const persistedGateway = normalizePersistedGateway(nextConfigs['pos-gateway']);
605
631
  const nextGateway = persistedGateway || resolveDefaultGateway(deviceInfo);
606
632
  if (nextGateway && nextConfigs['pos-gateway'] !== nextGateway) {
607
633
  nextConfigs['pos-gateway'] = nextGateway;
608
634
  needsUpdate = true;
609
635
  }
610
-
611
- return {nextConfigs, needsUpdate};
612
- };
636
+
637
+ return {nextConfigs, needsUpdate};
638
+ };