@controleonline/ui-common 1.2.86 → 1.2.88

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 (73) hide show
  1. package/.github/workflows/integration-source-gate.yml +68 -0
  2. package/.github/workflows/manager-worker.yml +7 -156
  3. package/.github/workflows/publish-npm.yml +73 -27
  4. package/.github/workflows/pull-request-checks.yml +7 -5
  5. package/docs/technical/Device-Detail-Alias-UI-Sync.md +141 -0
  6. package/package.json +13 -8
  7. package/src/react/components/AddImportModal.js +61 -34
  8. package/src/react/components/BottomNavigationBar.js +178 -174
  9. package/src/react/components/BottomNavigationBar.styles.js +139 -118
  10. package/src/react/components/DefaultProvider.native.js +427 -421
  11. package/src/react/components/DefaultProvider.web.js +131 -125
  12. package/src/react/components/RemoteCheckoutService.js +3 -3
  13. package/src/react/components/RuntimeFooterMarqueeText.js +88 -36
  14. package/src/react/components/RuntimeInfoFooter.js +76 -43
  15. package/src/react/components/RuntimeInfoFooter.styles.js +22 -14
  16. package/src/react/config/deviceConfigBootstrap.js +3 -3
  17. package/src/react/pages/Devices/detail/DeviceDetailAlertsCommandsSection.js +4 -22
  18. package/src/react/pages/Devices/detail/DeviceDetailMovementSections.js +6 -2
  19. package/src/react/pages/Devices/detail/DeviceDetailOrdersPrintSection.js +4 -0
  20. package/src/react/pages/Devices/detail/DeviceDetailScreen.js +23 -338
  21. package/src/react/pages/Devices/detail/createDeviceDetailContext.js +20 -0
  22. package/src/react/pages/Devices/detail/useDeviceDetailActions.js +11 -36
  23. package/src/react/pages/Devices/detail/useDeviceDetailLoaders.js +129 -37
  24. package/src/react/pages/Devices/detail/useDeviceDetailSaves.js +11 -38
  25. package/src/react/pages/Devices/detail/useDeviceDetailStateA.js +9 -28
  26. package/src/react/pages/Imports.js +13 -11
  27. package/src/react/pages/IntegrationConfigFields.js +1 -0
  28. package/src/react/pages/IntegrationConfigPage.js +101 -45
  29. package/src/react/pages/IntegrationConfigPage.utils.js +21 -13
  30. package/src/react/pages/fetchPeopleConfigs.js +21 -0
  31. package/src/react/pages/integrationsCatalog.js +15 -110
  32. package/src/react/services/Cielo/Cielo.js +9 -9
  33. package/src/react/services/Getnet/Getnet.web.js +25 -0
  34. package/src/react/utils/companyAuthority.js +36 -0
  35. package/src/react/utils/fileUrl.js +14 -5
  36. package/src/react/utils/paymentDevices.js +375 -270
  37. package/src/react/utils/printerDevices.js +2 -2
  38. package/src/react/utils/runtimeFooter.js +178 -224
  39. package/src/react/utils/runtimeFooterText.js +160 -0
  40. package/src/react/utils/runtimeLanguage.js +5 -5
  41. package/src/react/utils/runtimeZoom.js +29 -5
  42. package/src/react/utils/shopFranchises.js +167 -12
  43. package/src/react/utils/storeColumns.js +235 -217
  44. package/src/react/utils/systemErrorMessage.js +2 -1
  45. package/src/store/imports/customActions.js +42 -2
  46. package/src/store/integration/index.js +43 -0
  47. package/src/tests/browser/manager/device-detail-apply-config-defined.spec.js +31 -0
  48. package/src/tests/browser/manager/device-detail-composition.spec.js +295 -0
  49. package/src/tests/browser/manager/device-detail-copy-config.spec.js +11 -1
  50. package/src/tests/browser/manager/device-detail-pdv-current-company.spec.js +273 -0
  51. package/src/tests/browser/manager/runtime-footer-rotation.spec.js +397 -0
  52. package/src/tests/react/components/DefaultProviderAuthority.test.js +28 -0
  53. package/src/tests/react/components/RuntimeFooterMarqueeText.build.test.js +29 -0
  54. package/src/tests/react/config/deviceConfigBootstrap.test.js +24 -1
  55. package/src/tests/react/pages/applyCurrentDeviceConfig.test.js +85 -0
  56. package/src/tests/react/pages/deviceDetailComposition.test.js +65 -0
  57. package/src/tests/react/pages/deviceDetailHookDependencies.test.mjs +31 -0
  58. package/src/tests/react/pages/deviceDetailLoaderDependencies.test.mjs +28 -0
  59. package/src/tests/react/pages/receitaFederalIntegrationContract.test.mjs +27 -6
  60. package/src/tests/react/services/Cielo.test.js +2 -2
  61. package/src/tests/react/utils/companyAuthority.test.js +53 -0
  62. package/src/tests/react/utils/formatter.test.mjs +6 -0
  63. package/src/tests/react/utils/paymentDevices.test.js +72 -0
  64. package/src/tests/react/utils/runtimeFooter.test.js +35 -0
  65. package/src/tests/react/utils/runtimeFooterText.test.js +88 -0
  66. package/src/tests/react/utils/runtimeLanguage.test.js +4 -4
  67. package/src/tests/react/utils/runtimeZoom.test.js +20 -0
  68. package/src/tests/react/utils/shopFranchises.test.js +32 -13
  69. package/src/tests/react/utils/translate.test.mjs +6 -6
  70. package/src/utils/formatter.js +7 -3
  71. package/src/utils/translate.js +16 -16
  72. package/src/utils/translatePending.js +6 -6
  73. package/src/utils/translateStorage.js +2 -2
@@ -144,7 +144,6 @@ export const INTEGRATION_CONFIGS = {
144
144
  description:
145
145
  'Configuracoes fiscais por tipo de documento (NF-e, cupom, NFS-e, CT-e, pre-notas).',
146
146
  saveLabel: 'Salvar configuracoes fiscais',
147
- // requiredKeys only enforce "Gerais" minima; tipos sao opcionais conforme operacao da empresa
148
147
  requiredKeys: [
149
148
  'receita-federal-tax-regime',
150
149
  'receita-federal-certificate-file',
@@ -166,11 +165,6 @@ export const INTEGRATION_CONFIGS = {
166
165
  { value: '3', label: 'Regime Normal' },
167
166
  ],
168
167
  },
169
- {
170
- key: 'receita-federal-ibge-code',
171
- label: 'Codigo IBGE (municipio)',
172
- placeholder: 'Ex.: 3550308',
173
- },
174
168
  {
175
169
  key: 'receita-federal-environment',
176
170
  label: 'Ambiente SEFAZ',
@@ -194,6 +188,11 @@ export const INTEGRATION_CONFIGS = {
194
188
  placeholder: 'Informe a senha do certificado',
195
189
  secureTextEntry: true,
196
190
  },
191
+ {
192
+ key: 'receita-federal-state-registration',
193
+ label: 'Inscricao estadual',
194
+ placeholder: 'IE do emitente',
195
+ },
197
196
  ],
198
197
  },
199
198
  {
@@ -201,25 +200,11 @@ export const INTEGRATION_CONFIGS = {
201
200
  label: 'NF-e (produtos)',
202
201
  description: 'Nota Fiscal Eletronica modelo 55 — saida de mercadorias.',
203
202
  fields: [
204
- {
205
- key: 'receita-federal-nfe-enabled',
206
- label: 'Habilitar NF-e',
207
- type: 'select',
208
- options: [
209
- { value: '0', label: 'Nao' },
210
- { value: '1', label: 'Sim' },
211
- ],
212
- },
213
203
  {
214
204
  key: 'receita-federal-nfe-serie',
215
205
  label: 'Serie NF-e',
216
206
  placeholder: 'Ex.: 1',
217
207
  },
218
- {
219
- key: 'receita-federal-nfe-last-number',
220
- label: 'Ultima NF-e / proximo numero',
221
- placeholder: 'Ex.: 100',
222
- },
223
208
  ],
224
209
  },
225
210
  {
@@ -227,36 +212,11 @@ export const INTEGRATION_CONFIGS = {
227
212
  label: 'NFC-e / Cupom',
228
213
  description: 'Cupom fiscal eletronico modelo 65 — consumidor final.',
229
214
  fields: [
230
- {
231
- key: 'receita-federal-nfce-enabled',
232
- label: 'Habilitar NFC-e / cupom',
233
- type: 'select',
234
- options: [
235
- { value: '0', label: 'Nao' },
236
- { value: '1', label: 'Sim' },
237
- ],
238
- },
239
215
  {
240
216
  key: 'receita-federal-nfce-serie',
241
217
  label: 'Serie NFC-e',
242
218
  placeholder: 'Ex.: 1',
243
219
  },
244
- {
245
- key: 'receita-federal-nfce-last-number',
246
- label: 'Ultima NFC-e / proximo numero',
247
- placeholder: 'Ex.: 100',
248
- },
249
- {
250
- key: 'receita-federal-nfce-csc-id',
251
- label: 'CSC ID (token)',
252
- placeholder: 'Identificador do CSC',
253
- },
254
- {
255
- key: 'receita-federal-nfce-csc',
256
- label: 'CSC (codigo de seguranca)',
257
- placeholder: 'Codigo CSC da SEFAZ',
258
- secureTextEntry: true,
259
- },
260
220
  ],
261
221
  },
262
222
  {
@@ -264,35 +224,7 @@ export const INTEGRATION_CONFIGS = {
264
224
  label: 'NFS-e (servicos)',
265
225
  description: 'Nota de servicos eletronica — prestacao de servicos.',
266
226
  fields: [
267
- {
268
- key: 'receita-federal-nfse-enabled',
269
- label: 'Habilitar NFS-e',
270
- type: 'select',
271
- options: [
272
- { value: '0', label: 'Nao' },
273
- { value: '1', label: 'Sim' },
274
- ],
275
- },
276
- {
277
- key: 'receita-federal-nfse-serie',
278
- label: 'Serie RPS / NFS-e',
279
- placeholder: 'Ex.: 1',
280
- },
281
- {
282
- key: 'receita-federal-nfse-last-number',
283
- label: 'Ultimo RPS / proximo numero',
284
- placeholder: 'Ex.: 50',
285
- },
286
- {
287
- key: 'receita-federal-nfse-im',
288
- label: 'Inscricao municipal',
289
- placeholder: 'IM do prestador',
290
- },
291
- {
292
- key: 'receita-federal-nfse-cnae',
293
- label: 'CNAE principal (servico)',
294
- placeholder: 'Ex.: 6201501',
295
- },
227
+ // NFS-e provider-specific fields are not supported by the current backend.
296
228
  ],
297
229
  },
298
230
  {
@@ -300,56 +232,29 @@ export const INTEGRATION_CONFIGS = {
300
232
  label: 'CT-e',
301
233
  description: 'Conhecimento de Transporte Eletronico.',
302
234
  fields: [
303
- {
304
- key: 'receita-federal-cte-enabled',
305
- label: 'Habilitar CT-e',
306
- type: 'select',
307
- options: [
308
- { value: '0', label: 'Nao' },
309
- { value: '1', label: 'Sim' },
310
- ],
311
- },
312
235
  {
313
236
  key: 'receita-federal-cte-serie',
314
237
  label: 'Serie CT-e',
315
238
  placeholder: 'Ex.: 1',
316
239
  },
317
240
  {
318
- key: 'receita-federal-cte-last-number',
319
- label: 'Ultimo CT-e / proximo numero',
320
- placeholder: 'Ex.: 10',
241
+ key: 'receita-federal-cte-rntrc',
242
+ label: 'RNTRC',
243
+ placeholder: 'Registro da transportadora na ANTT',
321
244
  },
322
- ],
323
- },
324
- {
325
- key: 'prenota',
326
- label: 'Pre-notas',
327
- description: 'Rascunhos / pre-notas antes da autorizacao SEFAZ.',
328
- fields: [
329
245
  {
330
- key: 'receita-federal-prenota-enabled',
331
- label: 'Habilitar pre-notas',
332
- type: 'select',
333
- options: [
334
- { value: '0', label: 'Nao' },
335
- { value: '1', label: 'Sim' },
336
- ],
246
+ key: 'receita-federal-mdfe-enabled',
247
+ label: 'Habilitar MDF-e',
248
+ type: 'switch',
337
249
  },
338
250
  {
339
- key: 'receita-federal-prenota-default-type',
340
- label: 'Tipo padrao ao gerar pre-nota',
341
- type: 'select',
342
- options: [
343
- { value: 'nfe', label: 'NF-e (produtos)' },
344
- { value: 'nfce', label: 'NFC-e / cupom' },
345
- { value: 'nfse', label: 'NFS-e (servicos)' },
346
- { value: 'cte', label: 'CT-e' },
347
- ],
251
+ key: 'receita-federal-mdfe-serie',
252
+ label: 'Serie MDF-e',
253
+ placeholder: 'Ex.: 1',
348
254
  },
349
255
  ],
350
256
  },
351
257
  ],
352
- // fields flat list derived at runtime from tabs when present
353
258
  fields: [],
354
259
  },
355
260
  };
@@ -59,31 +59,31 @@ const resolveRuntimeCompanyConfigs = () => {
59
59
  return peopleStore.currentCompany.configs;
60
60
  }
61
61
 
62
- if (isConfigMap(peopleStore.defaultCompany?.configs)) {
63
- return peopleStore.defaultCompany.configs;
62
+ if (isConfigMap(peopleStore.mainCompany?.configs)) {
63
+ return peopleStore.mainCompany.configs;
64
64
  }
65
65
 
66
66
  return {};
67
67
  };
68
68
 
69
- const resolveDefaultCompanyId = () => {
69
+ const resolveMainCompanyId = () => {
70
70
  const stores = getAllStores();
71
71
  const peopleStore = stores?.people?.getters || {};
72
72
 
73
73
  return normalizeEntityId(
74
- peopleStore.defaultCompany?.id || peopleStore.defaultCompany?.['@id'],
74
+ peopleStore.mainCompany?.id || peopleStore.mainCompany?.['@id'],
75
75
  );
76
76
  };
77
77
 
78
78
  const loadTechnicalCieloConfig = async () => {
79
- const defaultCompanyId = resolveDefaultCompanyId();
79
+ const mainCompanyId = resolveMainCompanyId();
80
80
 
81
- if (!defaultCompanyId) {
81
+ if (!mainCompanyId) {
82
82
  return DEFAULT_CIELO_CONFIG;
83
83
  }
84
84
 
85
85
  if (
86
- technicalCieloConfigCompanyId === defaultCompanyId &&
86
+ technicalCieloConfigCompanyId === mainCompanyId &&
87
87
  hasRequiredCieloConfig(technicalCieloConfigCache)
88
88
  ) {
89
89
  return technicalCieloConfigCache;
@@ -97,13 +97,13 @@ const loadTechnicalCieloConfig = async () => {
97
97
  .fetch('/configs', {
98
98
  params: {
99
99
  configKey: 'CIELO',
100
- people: '/people/' + defaultCompanyId,
100
+ people: '/people/' + mainCompanyId,
101
101
  visibility: 'private',
102
102
  },
103
103
  })
104
104
  .then(response => {
105
105
  const item = extractCollectionItems(response)[0];
106
- technicalCieloConfigCompanyId = defaultCompanyId;
106
+ technicalCieloConfigCompanyId = mainCompanyId;
107
107
  technicalCieloConfigCache = resolveCieloConfig(
108
108
  item?.configKey ? {[item.configKey]: item?.configValue} : {},
109
109
  );
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Web stub for Getnet POS. The native module
3
+ * `@controleonline/react-native-getnet-payment` is not part of the Expo web
4
+ * bundle (browser smokes / admin / manager / delivery). Native Android keeps
5
+ * using Getnet.js.
6
+ */
7
+ class GetnetService {
8
+ async payment() {
9
+ throw new Error('Getnet POS is available only on the native POS app.');
10
+ }
11
+
12
+ async refund() {
13
+ throw new Error('Getnet POS is available only on the native POS app.');
14
+ }
15
+
16
+ async reprint() {
17
+ throw new Error('Getnet POS is available only on the native POS app.');
18
+ }
19
+
20
+ async checkStatus() {
21
+ throw new Error('Getnet POS is available only on the native POS app.');
22
+ }
23
+ }
24
+
25
+ export default GetnetService;
@@ -0,0 +1,36 @@
1
+ const normalizeRole = value => String(value || '').trim().toLowerCase();
2
+
3
+ const normalizeRoles = values =>
4
+ (Array.isArray(values) ? values : []).map(normalizeRole);
5
+
6
+ const hasCompanyAdministrativeLink = company => {
7
+ const userFlags = company?.user || {};
8
+ const permissions = normalizeRoles(company?.permission || company?.permissions);
9
+
10
+ return Boolean(
11
+ userFlags.owner_enabled ||
12
+ userFlags.manager_enabled ||
13
+ company?.owner_enabled ||
14
+ company?.manager_enabled ||
15
+ permissions.includes('owner') ||
16
+ permissions.includes('manager'),
17
+ );
18
+ };
19
+
20
+ export const isSuperAdmin = ({mainCompany, user} = {}) => {
21
+ const roles = normalizeRoles(user?.roles);
22
+ const mainPermissions = normalizeRoles(
23
+ mainCompany?.permission || mainCompany?.permissions,
24
+ );
25
+
26
+ return Boolean(
27
+ roles.includes('role_super') ||
28
+ roles.includes('super') ||
29
+ mainPermissions.includes('super') ||
30
+ hasCompanyAdministrativeLink(mainCompany),
31
+ );
32
+ };
33
+
34
+ export const canAdministerCompany = ({company, mainCompany, user} = {}) =>
35
+ isSuperAdmin({mainCompany, user}) || hasCompanyAdministrativeLink(company);
36
+
@@ -138,8 +138,13 @@ const buildTenantDownloadUrl = (url, host) => {
138
138
  return absoluteUrl;
139
139
  }
140
140
 
141
- // Do not inject environment hosts into the path (app-community#432).
142
- if (isEnvironmentLikeHost(normalizedHost)) {
141
+ // File download ops are registered as /{appDomain}/files/{id}/download.
142
+ // Skipping path inject for environment hosts left SPA on /files/{id}/download
143
+ // which 404s until/unless a non-prefixed route is deployed (app-community#796).
144
+ const isFileDownloadPath = /\/files\/[^/?#]+\/download/i.test(absoluteUrl);
145
+
146
+ // Do not inject environment hosts into non-download paths (app-community#432).
147
+ if (isEnvironmentLikeHost(normalizedHost) && !isFileDownloadPath) {
143
148
  return absoluteUrl;
144
149
  }
145
150
 
@@ -304,15 +309,19 @@ export const resolveDefaultFileSource = (
304
309
  return null;
305
310
  }
306
311
 
312
+ // Prefer FileService domain (companies/my icon/logo payload) for path inject.
313
+ const fileDomain = normalizeText(normalizedFile?.domain);
314
+ const downloadHost = fileDomain || host;
315
+
307
316
  const uri = isBackendDownload
308
- ? buildTenantDownloadUrl(uriBase, host)
317
+ ? buildTenantDownloadUrl(uriBase, downloadHost)
309
318
  : uriBase;
310
319
 
311
320
  return {
312
321
  uri,
313
322
  headers:
314
- isBackendDownload && host
315
- ? {...sourceHeaders, ...headers, 'app-domain': host}
323
+ isBackendDownload && downloadHost
324
+ ? {...sourceHeaders, ...headers, 'app-domain': downloadHost}
316
325
  : {...sourceHeaders, ...headers},
317
326
  };
318
327
  }