@controleonline/ui-common 1.2.70

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 (203) hide show
  1. package/.github/agents/developer.agent.md +30 -0
  2. package/.github/agents/devops.agent.md +30 -0
  3. package/.github/agents/qa.agent.md +30 -0
  4. package/.github/agents/security.agent.md +30 -0
  5. package/.github/workflows/npmjs.yml +35 -0
  6. package/.github/workflows/pull-request-checks.yml +19 -0
  7. package/.scrutinizer.yml +24 -0
  8. package/FUNDING.yml +1 -0
  9. package/package.json +28 -0
  10. package/src/api/fetch.js +74 -0
  11. package/src/api/index.js +155 -0
  12. package/src/api/localDB.js +131 -0
  13. package/src/api/queue.js +66 -0
  14. package/src/react/assets/tap.mp3 +0 -0
  15. package/src/react/components/AddImportModal.js +157 -0
  16. package/src/react/components/AddImportModal.styles.js +81 -0
  17. package/src/react/components/BackgroundRuntimeBridge.js +219 -0
  18. package/src/react/components/BottomNavigationBar.config.js +238 -0
  19. package/src/react/components/BottomNavigationBar.js +120 -0
  20. package/src/react/components/BottomNavigationBar.styles.js +110 -0
  21. package/src/react/components/CategoryForm.js +572 -0
  22. package/src/react/components/CategoryForm.styles.js +334 -0
  23. package/src/react/components/ConfirmModal.js +24 -0
  24. package/src/react/components/ConfirmModal.styles.js +43 -0
  25. package/src/react/components/ContextHelpButton.js +69 -0
  26. package/src/react/components/ContextHelpButton.styles.js +62 -0
  27. package/src/react/components/DefaultProvider.native.js +848 -0
  28. package/src/react/components/DefaultProvider.styles.js +21 -0
  29. package/src/react/components/DefaultProvider.web.js +909 -0
  30. package/src/react/components/DeliveryPushBridge.native.js +314 -0
  31. package/src/react/components/DeliveryPushBridge.web.js +5 -0
  32. package/src/react/components/DeviceAlertSoundService.js +499 -0
  33. package/src/react/components/EntityLogContent.js +909 -0
  34. package/src/react/components/EntityLogContent.styles.js +400 -0
  35. package/src/react/components/EventBus.js +12 -0
  36. package/src/react/components/KioskModeBridge.js +65 -0
  37. package/src/react/components/LauncherModeBridge.js +47 -0
  38. package/src/react/components/LinkedOrderProductsTab.js +388 -0
  39. package/src/react/components/LinkedOrderProductsTab.styles.js +180 -0
  40. package/src/react/components/ManagerPushBridge.native.js +345 -0
  41. package/src/react/components/MessageService.js +314 -0
  42. package/src/react/components/Paywall/Google.js +89 -0
  43. package/src/react/components/PrintService.js +778 -0
  44. package/src/react/components/ProductCatalogCacheService.js +45 -0
  45. package/src/react/components/RemoteCheckoutService.js +292 -0
  46. package/src/react/components/RuntimeBottomNavigationBar.js +151 -0
  47. package/src/react/components/RuntimeInfoFooter.js +214 -0
  48. package/src/react/components/RuntimeInfoFooter.styles.js +56 -0
  49. package/src/react/components/SystemErrorToast.js +29 -0
  50. package/src/react/components/SystemErrorToast.styles.js +38 -0
  51. package/src/react/components/TouchFeedbackProvider.js +65 -0
  52. package/src/react/components/UnifiedPaymentBar.js +155 -0
  53. package/src/react/components/UnifiedPaymentBar.styles.js +174 -0
  54. package/src/react/components/WebsocketListener.native.js +487 -0
  55. package/src/react/components/WebsocketListener.web.js +102 -0
  56. package/src/react/components/inputs/IdInput.js +49 -0
  57. package/src/react/components/inputs/IdInput.styles.js +26 -0
  58. package/src/react/components/inputs/InvoiceDueDateFilterInput.js +74 -0
  59. package/src/react/components/inputs/InvoiceDueDateFilterInput.styles.js +34 -0
  60. package/src/react/components/inputs/InvoiceDueDateRangeFilterInput.js +115 -0
  61. package/src/react/components/inputs/InvoiceDueDateRangeFilterInput.styles.js +39 -0
  62. package/src/react/components/lists/CategoriesList.js +56 -0
  63. package/src/react/components/lists/PaymentTypeList.js +55 -0
  64. package/src/react/components/lists/ReceiverList.js +56 -0
  65. package/src/react/components/lists/SelectList.styles.js +18 -0
  66. package/src/react/components/lists/StatusList.js +55 -0
  67. package/src/react/components/lists/WalletList.js +54 -0
  68. package/src/react/components/radio/Spotify.js +144 -0
  69. package/src/react/components/radio/Spotify.styles.js +32 -0
  70. package/src/react/components/radio/YouTube.js +82 -0
  71. package/src/react/components/radio/YouTube.styles.js +16 -0
  72. package/src/react/components/toastConfig.js +16 -0
  73. package/src/react/config/deviceConfigBootstrap.js +571 -0
  74. package/src/react/index.js +4 -0
  75. package/src/react/localStorage.js +30 -0
  76. package/src/react/pages/EntityLogPage.js +124 -0
  77. package/src/react/pages/EntityLogPage.styles.js +17 -0
  78. package/src/react/pages/GenericLogPage.js +760 -0
  79. package/src/react/pages/GenericLogPage.styles.js +401 -0
  80. package/src/react/pages/Imports.js +361 -0
  81. package/src/react/pages/Imports.styles.js +223 -0
  82. package/src/react/pages/SettingsPage/PaymentTypesByWalletTab.js +462 -0
  83. package/src/react/pages/SettingsPage/index.js +1171 -0
  84. package/src/react/pages/SettingsPage/index.styles.js +122 -0
  85. package/src/react/print/jobs.js +147 -0
  86. package/src/react/print/providers/local.js +53 -0
  87. package/src/react/print/providers/remote.js +81 -0
  88. package/src/react/print/selection.js +296 -0
  89. package/src/react/print/usePrintButtonController.js +474 -0
  90. package/src/react/router/routes.js +42 -0
  91. package/src/react/services/NetworkPrinterService.native.js +391 -0
  92. package/src/react/services/NetworkPrinterService.web.js +15 -0
  93. package/src/react/stores/index.js +128 -0
  94. package/src/react/stores/storeErrorBridge.js +36 -0
  95. package/src/react/utils/backgroundRuntimeRegistration.js +69 -0
  96. package/src/react/utils/cashPayment.js +87 -0
  97. package/src/react/utils/commercialDocumentOrders.js +269 -0
  98. package/src/react/utils/dateRangeFilter.js +264 -0
  99. package/src/react/utils/deviceRuntime.js +193 -0
  100. package/src/react/utils/entityDisplay.js +231 -0
  101. package/src/react/utils/entityLog.js +649 -0
  102. package/src/react/utils/fileUrl.js +102 -0
  103. package/src/react/utils/frontendDebugLog.js +45 -0
  104. package/src/react/utils/googleMapsConfig.js +49 -0
  105. package/src/react/utils/importStatus.js +100 -0
  106. package/src/react/utils/invoiceDueDateMessages.js +14 -0
  107. package/src/react/utils/invoicePresentation.js +46 -0
  108. package/src/react/utils/logSettings.js +143 -0
  109. package/src/react/utils/maintenanceSettings.js +53 -0
  110. package/src/react/utils/managerOrderNotifications.js +523 -0
  111. package/src/react/utils/mapNavigation.js +76 -0
  112. package/src/react/utils/menuCatalogConfig.js +8 -0
  113. package/src/react/utils/menuCatalogDownload.js +157 -0
  114. package/src/react/utils/networkCameraDevices.js +175 -0
  115. package/src/react/utils/networkDeviceProfiles.js +135 -0
  116. package/src/react/utils/normalizedCatalogDownload.js +157 -0
  117. package/src/react/utils/notificationNavigation.js +94 -0
  118. package/src/react/utils/notificationSound.js +42 -0
  119. package/src/react/utils/paymentDevices.js +397 -0
  120. package/src/react/utils/paymentGatewayExecution.js +91 -0
  121. package/src/react/utils/paymentOptions.js +88 -0
  122. package/src/react/utils/peopleDisplay.js +39 -0
  123. package/src/react/utils/printerDevices.js +465 -0
  124. package/src/react/utils/remotePayment.js +61 -0
  125. package/src/react/utils/runtimeFooter.js +475 -0
  126. package/src/react/utils/runtimeLanguage.js +50 -0
  127. package/src/react/utils/runtimeMenu.js +224 -0
  128. package/src/react/utils/screenMetrics.js +30 -0
  129. package/src/react/utils/shopConfig.js +294 -0
  130. package/src/react/utils/shopFranchises.js +114 -0
  131. package/src/react/utils/socketRuntimePipeline.js +454 -0
  132. package/src/react/utils/spoolAckTracker.js +77 -0
  133. package/src/react/utils/storeColumns.js +427 -0
  134. package/src/react/utils/systemErrorChannel.js +109 -0
  135. package/src/react/utils/systemErrorMessage.js +67 -0
  136. package/src/react/utils/toastPresentation.js +53 -0
  137. package/src/react/utils/websocketSharedRuntime.js +826 -0
  138. package/src/store/acl/getters.js +4 -0
  139. package/src/store/acl/index.js +19 -0
  140. package/src/store/acl/mutation_types.js +4 -0
  141. package/src/store/acl/mutations.js +17 -0
  142. package/src/store/address/city.js +22 -0
  143. package/src/store/categories/category_file/index.js +25 -0
  144. package/src/store/categories/index.js +93 -0
  145. package/src/store/configs/customActions.js +131 -0
  146. package/src/store/configs/index.js +25 -0
  147. package/src/store/connections/customActions.js +26 -0
  148. package/src/store/connections/index.js +124 -0
  149. package/src/store/device/index.js +22 -0
  150. package/src/store/device_config/customActions.js +190 -0
  151. package/src/store/device_config/index.js +28 -0
  152. package/src/store/entity_log/customActions.js +63 -0
  153. package/src/store/entity_log/index.js +25 -0
  154. package/src/store/extra/data.js +85 -0
  155. package/src/store/extra/fields.js +88 -0
  156. package/src/store/file/actions.js +27 -0
  157. package/src/store/file/index.js +24 -0
  158. package/src/store/imports/index.js +88 -0
  159. package/src/store/print/customActions.js +251 -0
  160. package/src/store/print/index.js +28 -0
  161. package/src/store/printer/customActions.js +54 -0
  162. package/src/store/printer/index.js +26 -0
  163. package/src/store/runtime_debug/customActions.js +71 -0
  164. package/src/store/runtime_debug/index.js +30 -0
  165. package/src/store/status/index.js +65 -0
  166. package/src/store/timezones/index.js +43 -0
  167. package/src/store/websocket/customActions.js +24 -0
  168. package/src/store/websocket/index.js +28 -0
  169. package/src/tests/react/components/LauncherModeBridge.test.js +93 -0
  170. package/src/tests/react/config/deviceConfigBootstrap.test.js +337 -0
  171. package/src/tests/react/print/localPrintProvider.test.js +45 -0
  172. package/src/tests/react/utils/backgroundRuntimeRegistration.test.js +123 -0
  173. package/src/tests/react/utils/cashPayment.test.js +41 -0
  174. package/src/tests/react/utils/dateRangeFilter.test.mjs +29 -0
  175. package/src/tests/react/utils/entityDisplay.test.js +18 -0
  176. package/src/tests/react/utils/googleMapsConfig.test.js +32 -0
  177. package/src/tests/react/utils/importStatus.test.js +85 -0
  178. package/src/tests/react/utils/invoicePresentation.test.mjs +40 -0
  179. package/src/tests/react/utils/managerOrderNotifications.test.js +127 -0
  180. package/src/tests/react/utils/mapNavigation.test.js +58 -0
  181. package/src/tests/react/utils/notificationNavigation.test.js +39 -0
  182. package/src/tests/react/utils/notificationSound.test.js +27 -0
  183. package/src/tests/react/utils/paymentDevices.test.js +88 -0
  184. package/src/tests/react/utils/runtimeFooter.test.js +429 -0
  185. package/src/tests/react/utils/runtimeLanguage.test.js +80 -0
  186. package/src/tests/react/utils/runtimeMenu.test.js +174 -0
  187. package/src/tests/react/utils/shopFranchises.test.js +82 -0
  188. package/src/tests/react/utils/socketRuntimePipeline.test.js +124 -0
  189. package/src/tests/react/utils/spoolAckTracker.test.js +40 -0
  190. package/src/tests/react/utils/storeErrorBridge.test.js +66 -0
  191. package/src/tests/react/utils/systemErrorChannel.test.js +58 -0
  192. package/src/tests/react/utils/systemErrorMessage.test.js +59 -0
  193. package/src/tests/react/utils/toastPresentation.test.js +75 -0
  194. package/src/tests/react/utils/translate.test.mjs +396 -0
  195. package/src/tests/react/utils/websocketSharedRuntime.test.js +245 -0
  196. package/src/utils/apiEntryPoint.js +31 -0
  197. package/src/utils/appDomain.js +50 -0
  198. package/src/utils/config.js +14 -0
  199. package/src/utils/formatter.js +419 -0
  200. package/src/utils/integrationConfigs.js +79 -0
  201. package/src/utils/methods.js +23 -0
  202. package/src/utils/oauth.js +42 -0
  203. package/src/utils/translate.js +620 -0
@@ -0,0 +1,102 @@
1
+ import { env as APP_ENV } from '@env';
2
+ import { buildAssetUrl } from '@controleonline/../../src/styles/branding';
3
+ import {
4
+ resolveAppDomain,
5
+ resolveCompanyDomain,
6
+ } from '@controleonline/ui-common/src/utils/appDomain';
7
+
8
+ const IMAGE_PATH_PATTERN = /\.(?:avif|bmp|gif|ico|jpe?g|png|svg|webp)(?:\?|$)/i;
9
+
10
+ const normalizeText = value => String(value || '').trim();
11
+
12
+ const unwrapFile = file => {
13
+ if (!file || typeof file !== 'object' || Array.isArray(file)) {
14
+ return file;
15
+ }
16
+
17
+ if (file.file) {
18
+ return unwrapFile(file.file);
19
+ }
20
+
21
+ return file;
22
+ };
23
+
24
+ const resolveDirectFileUrl = file => {
25
+ if (!file) {
26
+ return '';
27
+ }
28
+
29
+ if (typeof file === 'string') {
30
+ const normalizedFile = normalizeText(file);
31
+ if (
32
+ /^https?:\/\//i.test(normalizedFile) ||
33
+ /^\/\//.test(normalizedFile) ||
34
+ /\/download(?:\?|$)/i.test(normalizedFile) ||
35
+ IMAGE_PATH_PATTERN.test(normalizedFile)
36
+ ) {
37
+ return buildAssetUrl(normalizedFile) || normalizedFile;
38
+ }
39
+
40
+ return '';
41
+ }
42
+
43
+ if (typeof file === 'object' && !Array.isArray(file)) {
44
+ return buildAssetUrl(file) || '';
45
+ }
46
+
47
+ return '';
48
+ };
49
+
50
+ export const extractFileId = file => {
51
+ const normalizedFile = unwrapFile(file);
52
+
53
+ if (!normalizedFile) {
54
+ return null;
55
+ }
56
+
57
+ if (typeof normalizedFile === 'number') {
58
+ return normalizedFile;
59
+ }
60
+
61
+ if (typeof normalizedFile === 'string') {
62
+ const matches = normalizedFile.match(/\d+/g);
63
+ return matches ? Number(matches[matches.length - 1]) : null;
64
+ }
65
+
66
+ if (typeof normalizedFile === 'object') {
67
+ const rawValue =
68
+ normalizedFile?.id ||
69
+ normalizedFile?.['@id'] ||
70
+ normalizedFile?.fileId ||
71
+ normalizedFile?.file_id ||
72
+ '';
73
+
74
+ return extractFileId(rawValue);
75
+ }
76
+
77
+ return null;
78
+ };
79
+
80
+ // Centraliza a resolucao de imagem/arquivo do backend em uma unica regra.
81
+ export const resolveFileImageUrl = (file, {company = null, appDomain = ''} = {}) => {
82
+ const normalizedFile = unwrapFile(file);
83
+ const directUrl = resolveDirectFileUrl(normalizedFile);
84
+ if (directUrl) {
85
+ return directUrl;
86
+ }
87
+
88
+ const fileId = extractFileId(normalizedFile);
89
+ if (!fileId) {
90
+ return '';
91
+ }
92
+
93
+ const fallbackDomain = normalizeText(appDomain) || resolveAppDomain(APP_ENV?.DOMAIN);
94
+ const host = resolveCompanyDomain(company, fallbackDomain);
95
+ const query = host ? `?app-domain=${encodeURIComponent(host)}` : '';
96
+ const relativeUrl = `/files/${fileId}/download${query}`;
97
+ const apiEntryPoint = normalizeText(APP_ENV?.API_ENTRYPOINT).replace(/\/$/, '');
98
+
99
+ return apiEntryPoint ? `${apiEntryPoint}${relativeUrl}` : relativeUrl;
100
+ };
101
+
102
+ export const resolveFileDownloadUrl = resolveFileImageUrl;
@@ -0,0 +1,45 @@
1
+ import {api} from '@controleonline/ui-common/src/api'
2
+
3
+ const normalizeContext = value =>
4
+ value && typeof value === 'object' && !Array.isArray(value) ? value : {}
5
+
6
+ export const sendFrontendDebugLog = async ({
7
+ channel = 'frontend-debug',
8
+ class: entityClass = '',
9
+ context = {},
10
+ entityRow = null,
11
+ level = 'info',
12
+ message = 'Frontend debug log',
13
+ row = null,
14
+ } = {}) => {
15
+ if (typeof __DEV__ !== 'undefined' && !__DEV__) {
16
+ return null
17
+ }
18
+
19
+ const normalizedContext = {
20
+ ...normalizeContext(context),
21
+ href:
22
+ typeof window !== 'undefined' && window?.location?.href
23
+ ? window.location.href
24
+ : '',
25
+ }
26
+
27
+ try {
28
+ const response = await api.fetch('/logs/frontend-debug', {
29
+ method: 'POST',
30
+ body: {
31
+ channel,
32
+ level,
33
+ message,
34
+ context: normalizedContext,
35
+ entityClass,
36
+ entityRow: entityRow ?? row,
37
+ },
38
+ })
39
+
40
+ return response
41
+ } catch {
42
+ return null
43
+ }
44
+ }
45
+ // TODO(store-first): quando este arquivo for mexido, mover a leitura para stores, remover api.fetch e evitar repassar dados em objetos quando o store ja resolver isso.
@@ -0,0 +1,49 @@
1
+ const parseJsonValue = (value, fallback) => {
2
+ if (value === null || value === undefined || value === '') {
3
+ return fallback;
4
+ }
5
+
6
+ if (typeof value === 'string') {
7
+ try {
8
+ return JSON.parse(value);
9
+ } catch {
10
+ return value;
11
+ }
12
+ }
13
+
14
+ return value;
15
+ };
16
+
17
+ const normalizeTextConfig = (value, fallback = '') => {
18
+ const parsed = parseJsonValue(value, fallback);
19
+
20
+ if (parsed === null || parsed === undefined) {
21
+ return fallback;
22
+ }
23
+
24
+ return String(parsed).trim();
25
+ };
26
+
27
+ export const GOOGLE_MAPS_WEB_API_KEY_CONFIG_KEY = 'web-google-maps-api-key';
28
+ export const GOOGLE_MAPS_ANDROID_API_KEY_CONFIG_KEY =
29
+ 'android-google-maps-api-key';
30
+
31
+ export const resolveGoogleMapsSettings = configs => {
32
+ const configMap =
33
+ configs && typeof configs === 'object' && !Array.isArray(configs)
34
+ ? configs
35
+ : {};
36
+
37
+ const webGoogleMapsApiKey = normalizeTextConfig(
38
+ configMap[GOOGLE_MAPS_WEB_API_KEY_CONFIG_KEY],
39
+ );
40
+
41
+ const androidGoogleMapsApiKey = normalizeTextConfig(
42
+ configMap[GOOGLE_MAPS_ANDROID_API_KEY_CONFIG_KEY],
43
+ );
44
+
45
+ return {
46
+ webGoogleMapsApiKey,
47
+ androidGoogleMapsApiKey,
48
+ };
49
+ };
@@ -0,0 +1,100 @@
1
+ const PROCESSING_IMPORT_STATUSES = ['pending', 'processing', 'queued', 'uploading', 'uploaded']
2
+ const ERROR_IMPORT_STATUSES = ['error', 'failed', 'failure', 'invalid']
3
+ const SUCCESS_IMPORT_STATUSES = ['done', 'success', 'completed', 'processed', 'finished']
4
+
5
+ function normalizeImportStatus(value) {
6
+ return String(value || '')
7
+ .trim()
8
+ .toLowerCase()
9
+ }
10
+
11
+ function getImportStatusMeta(item) {
12
+ const rawStatus =
13
+ item?.status?.realStatus ||
14
+ item?.status?.status ||
15
+ item?.status?.name ||
16
+ ''
17
+ const normalizedStatus = normalizeImportStatus(rawStatus)
18
+
19
+ if (PROCESSING_IMPORT_STATUSES.includes(normalizedStatus)) {
20
+ return {
21
+ isProcessing: true,
22
+ isError: false,
23
+ labelKey: 'processing',
24
+ rawStatus,
25
+ backgroundColor: '#FEF3C7',
26
+ textColor: '#B45309',
27
+ }
28
+ }
29
+
30
+ if (ERROR_IMPORT_STATUSES.includes(normalizedStatus)) {
31
+ return {
32
+ isProcessing: false,
33
+ isError: true,
34
+ labelKey: 'error',
35
+ rawStatus,
36
+ backgroundColor: '#FEE2E2',
37
+ textColor: '#B91C1C',
38
+ }
39
+ }
40
+
41
+ if (SUCCESS_IMPORT_STATUSES.includes(normalizedStatus)) {
42
+ return {
43
+ isProcessing: false,
44
+ isError: false,
45
+ labelKey: 'done',
46
+ rawStatus,
47
+ backgroundColor: '#DCFCE7',
48
+ textColor: '#15803D',
49
+ }
50
+ }
51
+
52
+ return {
53
+ isProcessing: false,
54
+ isError: false,
55
+ labelKey: 'fallback',
56
+ rawStatus,
57
+ backgroundColor: '#E2E8F0',
58
+ textColor: '#475569',
59
+ }
60
+ }
61
+
62
+ function getImportErrorDetail(item) {
63
+ const candidates = [
64
+ item?.error,
65
+ item?.errorMessage,
66
+ item?.status?.message,
67
+ item?.status?.description,
68
+ item?.status?.detail,
69
+ item?.detail,
70
+ item?.message,
71
+ ]
72
+
73
+ return candidates.find(candidate => String(candidate || '').trim()) || ''
74
+ }
75
+
76
+ function resolveImportLabels(translate) {
77
+ return {
78
+ refreshLabel: translate?.('imports', 'button', 'refresh'),
79
+ processingLabel: translate?.('imports', 'status', 'processing'),
80
+ errorLabel: translate?.('imports', 'status', 'error'),
81
+ doneLabel: translate?.('imports', 'status', 'done'),
82
+ noStatusLabel: translate?.('imports', 'status', 'no_status'),
83
+ processingHelpLabel: translate?.('imports', 'message', 'processing_after_upload'),
84
+ }
85
+ }
86
+
87
+ function resolveImportStatusLabel(statusMeta, labels = {}) {
88
+ if (statusMeta?.labelKey === 'processing') return labels.processingLabel
89
+ if (statusMeta?.labelKey === 'error') return labels.errorLabel
90
+ if (statusMeta?.labelKey === 'done') return labels.doneLabel
91
+ return statusMeta?.rawStatus || labels.noStatusLabel
92
+ }
93
+
94
+ module.exports = {
95
+ getImportErrorDetail,
96
+ getImportStatusMeta,
97
+ normalizeImportStatus,
98
+ resolveImportLabels,
99
+ resolveImportStatusLabel,
100
+ }
@@ -0,0 +1,14 @@
1
+ export const resolveInvoiceInvalidDateFormatMessage = () =>
2
+ global.t?.t('invoice', 'validation', 'Use o formato DD/MM/YYYY ou YYYY-MM-DD')
3
+
4
+ export const resolveInvoiceSingleDatePlaceholder = () =>
5
+ global.t?.t('invoice', 'placeholder', 'DD/MM/YYYY')
6
+
7
+ export const resolveInvoiceRangeLabel = () =>
8
+ global.t?.t('invoice', 'label', 'Vencimento (início/fim)')
9
+
10
+ export const resolveInvoiceRangeStartPlaceholder = () =>
11
+ global.t?.t('invoice', 'placeholder', 'Início: DD/MM/YYYY')
12
+
13
+ export const resolveInvoiceRangeEndPlaceholder = () =>
14
+ global.t?.t('invoice', 'placeholder', 'Fim: DD/MM/YYYY')
@@ -0,0 +1,46 @@
1
+ const normalizeText = value => String(value ?? '').trim()
2
+
3
+ const normalizeInvoiceType = value => {
4
+ const normalizedValue = normalizeText(value).toLowerCase()
5
+ return normalizedValue || 'invoice'
6
+ }
7
+
8
+ const formatInvoiceTypeLabel = value => {
9
+ const normalizedInvoiceType = normalizeInvoiceType(value)
10
+
11
+ const labels = {
12
+ invoice: 'Invoice',
13
+ payment: 'Payment',
14
+ discount: 'Discount',
15
+ tax: 'Tax',
16
+ }
17
+
18
+ if (labels[normalizedInvoiceType]) {
19
+ return labels[normalizedInvoiceType]
20
+ }
21
+
22
+ return normalizedInvoiceType
23
+ .split(/[_\s-]+/)
24
+ .filter(Boolean)
25
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
26
+ .join(' ')
27
+ }
28
+
29
+ const getInvoicePaymentTypeLabel = invoice =>
30
+ normalizeText(invoice?.paymentType?.paymentType || invoice?.paymentType?.name)
31
+
32
+ const getInvoicePartyLabel = entity =>
33
+ normalizeText(
34
+ entity?.alias ||
35
+ entity?.name ||
36
+ entity?.fantasy_name ||
37
+ entity?.company ||
38
+ entity?.document,
39
+ )
40
+
41
+ module.exports = {
42
+ normalizeInvoiceType,
43
+ formatInvoiceTypeLabel,
44
+ getInvoicePaymentTypeLabel,
45
+ getInvoicePartyLabel,
46
+ }
@@ -0,0 +1,143 @@
1
+ export const LOG_ERROR_EMAIL_ENABLED_KEY = 'log-error-email-enabled';
2
+ export const LOG_ERROR_EMAIL_RECIPIENTS_KEY = 'log-error-email-recipients';
3
+ export const LOG_POLICY_CONFIG_KEY = 'log-policy';
4
+
5
+ export const LOG_POLICY_ITEMS = [
6
+ {
7
+ key: 'backend_error',
8
+ title: 'Erros do backend',
9
+ description:
10
+ 'Registra excecoes e falhas HTTP do backend. E o grupo principal para erros 500.',
11
+ },
12
+ {
13
+ key: 'entity',
14
+ title: 'Historico de entidades',
15
+ description:
16
+ 'Mantem os diffs de criacao, alteracao e remocao das entidades do sistema.',
17
+ },
18
+ {
19
+ key: 'generic',
20
+ title: 'Logs genericos',
21
+ description:
22
+ 'Agrupa logs tecnicos de integracao, workers e eventos que nao sao timeline de entidade.',
23
+ },
24
+ {
25
+ key: 'operation_patterns',
26
+ title: 'Padroes operacionais',
27
+ description:
28
+ 'Mantem registros tecnicos ligados a padroes e diagnosticos operacionais do sistema.',
29
+ },
30
+ {
31
+ key: 'frontend_debug',
32
+ title: 'Debug do front-end',
33
+ description:
34
+ 'Recebe logs enviados pelo React para apoio de debug e investigacao remota.',
35
+ },
36
+ ];
37
+
38
+ export const DEFAULT_LOG_POLICY = LOG_POLICY_ITEMS.reduce((accumulator, item) => {
39
+ accumulator[item.key] = {
40
+ enabled: true,
41
+ retentionDays: null,
42
+ };
43
+
44
+ return accumulator;
45
+ }, {});
46
+
47
+ const parseJsonValue = (value, fallback) => {
48
+ if (value === null || value === undefined || value === '') {
49
+ return fallback;
50
+ }
51
+
52
+ if (typeof value === 'string') {
53
+ try {
54
+ return JSON.parse(value);
55
+ } catch {
56
+ return fallback;
57
+ }
58
+ }
59
+
60
+ return value;
61
+ };
62
+
63
+ const normalizeBoolean = value => {
64
+ if (typeof value === 'boolean') {
65
+ return value;
66
+ }
67
+
68
+ if (typeof value === 'number') {
69
+ return value === 1;
70
+ }
71
+
72
+ return ['1', 'true', 'yes', 'on'].includes(
73
+ String(value || '').trim().toLowerCase(),
74
+ );
75
+ };
76
+
77
+ const normalizeRetentionDays = value => {
78
+ const normalizedValue = String(value || '').replace(/\D+/g, '').trim();
79
+ if (!normalizedValue) {
80
+ return null;
81
+ }
82
+
83
+ const parsedValue = Number(normalizedValue);
84
+
85
+ return Number.isFinite(parsedValue) && parsedValue > 0 ? parsedValue : null;
86
+ };
87
+
88
+ export const normalizeLogAlertRecipients = value => {
89
+ const parsedValue = parseJsonValue(value, value);
90
+ const source = Array.isArray(parsedValue)
91
+ ? parsedValue
92
+ : String(parsedValue || '').split(/[\n,;]+/);
93
+
94
+ return Array.from(
95
+ new Set(
96
+ source
97
+ .map(item => String(item || '').trim().toLowerCase())
98
+ .filter(Boolean)
99
+ .filter(item => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(item)),
100
+ ),
101
+ );
102
+ };
103
+
104
+ export const findInvalidLogAlertRecipients = value => {
105
+ const parsedValue = parseJsonValue(value, value);
106
+ const source = Array.isArray(parsedValue)
107
+ ? parsedValue
108
+ : String(parsedValue || '').split(/[\n,;]+/);
109
+
110
+ return Array.from(
111
+ new Set(
112
+ source
113
+ .map(item => String(item || '').trim().toLowerCase())
114
+ .filter(Boolean)
115
+ .filter(item => !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(item)),
116
+ ),
117
+ );
118
+ };
119
+
120
+ export const normalizeLogPolicy = value => {
121
+ const parsedValue = parseJsonValue(value, {});
122
+ const safeValue =
123
+ parsedValue && typeof parsedValue === 'object' && !Array.isArray(parsedValue)
124
+ ? parsedValue
125
+ : {};
126
+
127
+ return LOG_POLICY_ITEMS.reduce((accumulator, item) => {
128
+ const config = safeValue[item.key] || {};
129
+
130
+ accumulator[item.key] = {
131
+ enabled:
132
+ config.enabled === undefined
133
+ ? DEFAULT_LOG_POLICY[item.key].enabled
134
+ : normalizeBoolean(config.enabled),
135
+ retentionDays: normalizeRetentionDays(config.retentionDays),
136
+ };
137
+
138
+ return accumulator;
139
+ }, {});
140
+ };
141
+
142
+ export const formatRecipientsForInput = value =>
143
+ normalizeLogAlertRecipients(value).join('\n');
@@ -0,0 +1,53 @@
1
+ export const MAINTENANCE_ROUTINES_CONFIG_KEY = 'maintenance-routines';
2
+
3
+ export const MAINTENANCE_ROUTINE_ITEMS = [
4
+ {
5
+ key: 'cleanup_logs',
6
+ title: 'Limpeza de logs',
7
+ description:
8
+ 'Executa a politica de retencao dos logs e remove registros expirados.',
9
+ defaultEnabled: true,
10
+ defaultCronExpression: '* * * * *',
11
+ },
12
+ ];
13
+
14
+ export const normalizeMaintenanceRoutines = value => {
15
+ let parsed = value;
16
+
17
+ if (typeof parsed === 'string') {
18
+ try {
19
+ parsed = JSON.parse(parsed);
20
+ } catch {
21
+ parsed = {};
22
+ }
23
+ }
24
+
25
+ const source = parsed && typeof parsed === 'object' ? parsed : {};
26
+
27
+ return MAINTENANCE_ROUTINE_ITEMS.reduce((accumulator, item) => {
28
+ const routine =
29
+ source[item.key] && typeof source[item.key] === 'object'
30
+ ? source[item.key]
31
+ : {};
32
+
33
+ const cronExpression = String(
34
+ routine.cronExpression || item.defaultCronExpression,
35
+ ).trim();
36
+
37
+ accumulator[item.key] = {
38
+ enabled:
39
+ routine.enabled === undefined
40
+ ? item.defaultEnabled
41
+ : Boolean(routine.enabled),
42
+ cronExpression: cronExpression || item.defaultCronExpression,
43
+ };
44
+
45
+ return accumulator;
46
+ }, {});
47
+ };
48
+
49
+ export const isLikelyCronExpression = value =>
50
+ String(value || '')
51
+ .trim()
52
+ .split(/\s+/)
53
+ .filter(Boolean).length === 5;