dcos-core-monalisav2-latam 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +130 -0
  2. package/index.js +350 -0
  3. package/package.json +52 -0
  4. package/src/auth/handler.js +3 -0
  5. package/src/common/MondelezCastOrder.js +449 -0
  6. package/src/common/utils/AuthSecurity.js +46 -0
  7. package/src/common/utils/account-error-handler.js +279 -0
  8. package/src/common/utils/account-error-helper.js +231 -0
  9. package/src/common/utils/account-properties-handler.js +355 -0
  10. package/src/common/utils/api-response.js +62 -0
  11. package/src/common/utils/aws-services.js +186 -0
  12. package/src/common/utils/constants/account-error-codes.json +801 -0
  13. package/src/common/utils/constants.js +37 -0
  14. package/src/common/utils/convert/MondelezClientsItemsCast.js +52 -0
  15. package/src/common/utils/convert/MondelezInventoryItemsCast.js +15 -0
  16. package/src/common/utils/convert/MondelezOrderStatusCast.js +34 -0
  17. package/src/common/utils/convert/MondelezPricesItemsCast.js +37 -0
  18. package/src/common/utils/cron-ftp-get.js +143 -0
  19. package/src/common/utils/data-tables-helper.js +213 -0
  20. package/src/common/utils/date-range-calculator.js +113 -0
  21. package/src/common/utils/delay.js +17 -0
  22. package/src/common/utils/ftp-sftp.js +320 -0
  23. package/src/common/utils/logger.js +126 -0
  24. package/src/common/utils/nodemailerLib.js +61 -0
  25. package/src/common/utils/product-unit-converter.js +168 -0
  26. package/src/common/utils/schemas-utils.js +101 -0
  27. package/src/common/utils/seller-email-sharing-service.js +441 -0
  28. package/src/common/utils/sftp-utils.js +202 -0
  29. package/src/common/utils/status.js +15 -0
  30. package/src/common/utils/util.js +236 -0
  31. package/src/common/utils/validate-state-order.js +35 -0
  32. package/src/common/utils/validateProviders.js +67 -0
  33. package/src/common/utils/validation-data.js +45 -0
  34. package/src/common/utils/vtex/save-hooks.js +65 -0
  35. package/src/common/utils/vtex/save-schemas.js +65 -0
  36. package/src/common/utils/vtex-hook-handler.js +71 -0
  37. package/src/common/validation/AccountCoordinatesValidation.js +350 -0
  38. package/src/common/validation/GeneralErrorValidation.js +11 -0
  39. package/src/common/validation/MainErrorValidation.js +8 -0
  40. package/src/entities/account.js +639 -0
  41. package/src/entities/clients.js +104 -0
  42. package/src/entities/controlprice.js +196 -0
  43. package/src/entities/controlstock.js +206 -0
  44. package/src/entities/cron.js +77 -0
  45. package/src/entities/cronjob.js +71 -0
  46. package/src/entities/orders.js +195 -0
  47. package/src/entities/sftp-inbound.js +88 -0
  48. package/src/entities/sku.js +220 -0
  49. package/src/entities/taxpromotion.js +249 -0
  50. package/src/functions/account/account-get.js +262 -0
  51. package/src/functions/account/account-handler.js +299 -0
  52. package/src/functions/account/clients.js +10 -0
  53. package/src/functions/account/index.js +208 -0
  54. package/src/functions/actions/save-promotions-order-history.js +324 -0
  55. package/src/functions/affiliates/affiliates-hook-consumer.js +87 -0
  56. package/src/functions/affiliates/affiliates-hook-producer.js +45 -0
  57. package/src/functions/clients/clients-audience.js +62 -0
  58. package/src/functions/clients/clients-consumer.js +648 -0
  59. package/src/functions/clients/clients-producer.js +362 -0
  60. package/src/functions/clients/clients-suggested-product-consumer.js +166 -0
  61. package/src/functions/clients/helpers/suggested-product-mdlz.js +233 -0
  62. package/src/functions/clients_peru/email.html +129 -0
  63. package/src/functions/clients_peru/splitfile.js +357 -0
  64. package/src/functions/clients_peru/updateClients.js +1334 -0
  65. package/src/functions/clients_peru/utils.js +243 -0
  66. package/src/functions/cronjobs/cron-jobs-manager.js +40 -0
  67. package/src/functions/cronjobs/cron-jobs.js +171 -0
  68. package/src/functions/crons/cron.js +39 -0
  69. package/src/functions/distributors/distributor-handler.js +81 -0
  70. package/src/functions/distributors/distributor.js +535 -0
  71. package/src/functions/distributors/index.js +60 -0
  72. package/src/functions/financialpolicy/assign-financialpolicy.js +111 -0
  73. package/src/functions/financialpolicy/get-financialpolicy.js +91 -0
  74. package/src/functions/financialpolicy/index.js +28 -0
  75. package/src/functions/inventory/catalog-sync-consumer.js +17 -0
  76. package/src/functions/inventory/catalog-sync-handler.js +311 -0
  77. package/src/functions/inventory/inventory-consumer.js +119 -0
  78. package/src/functions/inventory/inventory-producer.js +197 -0
  79. package/src/functions/multiPresentation/multipre-queue.js +155 -0
  80. package/src/functions/multiPresentation/multipres.js +459 -0
  81. package/src/functions/nodeflow/index.js +83 -0
  82. package/src/functions/nodeflow/nodeflow-cron.js +200 -0
  83. package/src/functions/nodeflow/nodeflow-pub.js +203 -0
  84. package/src/functions/nodeflow/nodeflow-pvt.js +266 -0
  85. package/src/functions/notifications/download-leads-handler.js +67 -0
  86. package/src/functions/notifications/new-leads-notification-consumer.js +17 -0
  87. package/src/functions/notifications/new-leads-notification-handler.js +359 -0
  88. package/src/functions/notifications/order-status-notification-handler.js +482 -0
  89. package/src/functions/notifications/promotion-notification-handler.js +193 -0
  90. package/src/functions/orders/index.js +32 -0
  91. package/src/functions/orders/orders-cancel-handler.js +74 -0
  92. package/src/functions/orders/orders-handler.js +280 -0
  93. package/src/functions/orders/orders-hook-consumer.js +137 -0
  94. package/src/functions/orders/orders-hook-producer.js +170 -0
  95. package/src/functions/orders/orders-notifications-handler.js +137 -0
  96. package/src/functions/orders/orders-status-consumer.js +461 -0
  97. package/src/functions/orders/orders-status-producer.js +443 -0
  98. package/src/functions/prices/index.js +75 -0
  99. package/src/functions/prices/prices-consumer.js +236 -0
  100. package/src/functions/prices/prices-producer.js +323 -0
  101. package/src/functions/prices/promotion-and-tax.js +1284 -0
  102. package/src/functions/routesflow/assign-routeflow-queue.js +77 -0
  103. package/src/functions/schemas/vtex/handle-schemas.js +102 -0
  104. package/src/functions/security/process_gas.js +221 -0
  105. package/src/functions/security/security-handler.js +950 -0
  106. package/src/functions/sftp/sftp-consumer.js +453 -0
  107. package/src/functions/sftpIntegrations/processes/redirectServices.js +184 -0
  108. package/src/functions/sftpIntegrations/processes/validateFileSchema.js +226 -0
  109. package/src/functions/sftpIntegrations/schemas/credential-schema.js +123 -0
  110. package/src/functions/sftpIntegrations/schemas/record-schema.js +131 -0
  111. package/src/functions/sftpIntegrations/schemas/sftp_required_fields.json +3 -0
  112. package/src/functions/sftpIntegrations/sftp-config-producer.js +112 -0
  113. package/src/functions/sftpIntegrations/sftp-consumer.js +700 -0
  114. package/src/functions/sftpIntegrations/test/validateFile.test.js +122 -0
  115. package/src/functions/sftpIntegrations/utils/connect-dynamo.js +29 -0
  116. package/src/functions/sftpIntegrations/utils/split-data.js +25 -0
  117. package/src/functions/utils/index.js +130 -0
  118. package/src/functions/vtex/vtex-helpers.js +694 -0
  119. package/src/integrations/accountErrors/AccountErrorManager.js +437 -0
  120. package/src/integrations/audience/Audience.js +70 -0
  121. package/src/integrations/financialPolicy/FinancialPolicyApi.js +377 -0
  122. package/src/integrations/index.js +0 -0
  123. package/src/integrations/mobilvendor/MobilvendorApi.js +405 -0
  124. package/src/integrations/productmultipresentation/ProductMultiPresentation.js +200 -0
  125. package/src/mdlz/auth/SecretManagerApi.js +77 -0
  126. package/src/mdlz/client/MdlzApi.js +70 -0
  127. package/src/vtex/clients/ProvidersApi.js +51 -0
  128. package/src/vtex/clients/VtexApi.js +511 -0
  129. package/src/vtex/models/VtexOrder.js +87 -0
@@ -0,0 +1,65 @@
1
+ const VtexApi = require("../../../vtex/clients/VtexApi");
2
+ const Logger = require("../logger");
3
+
4
+ const handlePutOperation = async (vtexApi, url, data) => {
5
+ const options = {
6
+ method: 'PUT',
7
+ data,
8
+ };
9
+ const response = await vtexApi.fetch(url, options);
10
+ if ((response?.status >= 200 && response?.status < 400) || !response) {
11
+ return {
12
+ status: 200,
13
+ message: "Record created/updated successfully",
14
+ };
15
+ }
16
+ Logger.error("Failed PUT operation", response);
17
+ throw new Error("Failed PUT operation");
18
+ };
19
+
20
+ const handleDeleteOperation = async (vtexApi, url) => {
21
+ const options = {
22
+ method: 'DELETE',
23
+ };
24
+ const response = await vtexApi.fetch(url, options);
25
+
26
+ if ((response?.status >= 200 && response?.status < 400) || !response) {
27
+ return {
28
+ status: 200,
29
+ message: "Record deleted successfully",
30
+ };
31
+ }
32
+ Logger.error("Failed DELETE operation", response);
33
+ throw new Error("Failed DELETE operation");
34
+ };
35
+
36
+ const handleSchemaVtexMD2 = async ({ id, entityName, data, origin, httpMethod }) => {
37
+ if (!id || !origin) {
38
+ Logger.error("Missing required parameters (id or origin).");
39
+ throw new Error("Missing required parameters (id or origin).");
40
+ }
41
+ const { AccountName, AppKey, AppToken } = origin;
42
+ if (!AccountName || !AppKey || !AppToken) {
43
+ Logger.error("Incomplete 'origin' object.");
44
+ throw new Error("Incomplete 'origin' object.");
45
+ }
46
+ const vtexApi = new VtexApi(AccountName, AppKey, AppToken);
47
+ const url = `/dataentities/${entityName}/schemas/${id}`;
48
+ try {
49
+ switch (httpMethod) {
50
+ case 'PUT':
51
+ return await handlePutOperation(vtexApi, url, data);
52
+ case 'DELETE':
53
+ return await handleDeleteOperation(vtexApi, url);
54
+ default:
55
+ return { status: 405, message: `Method ${httpMethod} not allowed to VTEX` };
56
+ }
57
+ } catch (error) {
58
+ Logger.error(`Error during operation ${httpMethod}:`, error.message);
59
+ throw error;
60
+ }
61
+ };
62
+
63
+ module.exports = {
64
+ handleSchemaVtexMD2,
65
+ };
@@ -0,0 +1,71 @@
1
+ const ApiResponse = require("./api-response");
2
+ const AccountData = require("../../entities/account");
3
+ const VtexApi = require("../../vtex/clients/VtexApi");
4
+ const Logger = require("./logger");
5
+
6
+ async function handler(event) {
7
+ try {
8
+ const accountName = event.pathParameters?.accountName;
9
+
10
+ if (!accountName) {
11
+ return ApiResponse.response(400, {
12
+ success: false,
13
+ message: "accountName is required in URL path"
14
+ });
15
+ }
16
+
17
+ // Consultar la configuración de la cuenta en DynamoDB
18
+ const accountConfig = await AccountData.getAccountDataByAccountName(accountName);
19
+ if (!accountConfig) {
20
+ return ApiResponse.response(404, {
21
+ success: false,
22
+ message: `Account ${accountName} not found`
23
+ });
24
+ }
25
+
26
+ // Validar que tenga credenciales VTEX
27
+ if (!accountConfig.Credentials?.key || !accountConfig.Credentials?.token) {
28
+ return ApiResponse.response(400, {
29
+ success: false,
30
+ message: "VTEX credentials not configured for this account"
31
+ });
32
+ }
33
+
34
+ // Crear instancia de VtexApi
35
+ const vtexApi = new VtexApi(
36
+ accountConfig.AccountName,
37
+ accountConfig.Credentials.key,
38
+ accountConfig.Credentials.token
39
+ );
40
+
41
+ // Consultar configuración del hook en VTEX
42
+ const hookConfig = await vtexApi.fetch('/orders/hook/config', {
43
+ method: 'GET'
44
+ });
45
+
46
+ // Formatear respuesta
47
+ return ApiResponse.response(200, {
48
+ success: true,
49
+ data: {
50
+ accountName: accountConfig.AccountName,
51
+ parentAccountName: accountConfig.ParentAccountName,
52
+ hookConfiguration: hookConfig?.data || null
53
+ }
54
+ });
55
+
56
+ } catch (error) {
57
+ Logger.error("Error checking VTEX hook configuration", {
58
+ error: error.message,
59
+ stack: error.stack,
60
+ accountName: event.pathParameters?.accountName
61
+ });
62
+
63
+ return ApiResponse.response(500, {
64
+ success: false,
65
+ message: "Error checking VTEX hook configuration",
66
+ error: error.response?.data?.message || error.message
67
+ });
68
+ }
69
+ }
70
+
71
+ module.exports = { handler };
@@ -0,0 +1,350 @@
1
+ const VtexApi = require("../../vtex/clients/VtexApi");
2
+ const Logger = require("../utils/logger");
3
+ const GeneralRequiredError = require("./GeneralErrorValidation");
4
+
5
+ /**
6
+ * Clase para validar coordenadas geográficas de accounts en VTEX
7
+ */
8
+ class AccountCoordinatesValidation {
9
+ constructor(accountConfig) {
10
+ this.accountConfig = accountConfig;
11
+ this.vtexApi = null;
12
+
13
+ Logger.setAccount(accountConfig)
14
+
15
+ // Inicializar VtexApi si tenemos las credenciales
16
+ if (this.accountConfig?.Credentials?.key && this.accountConfig?.Credentials?.token) {
17
+ this.vtexApi = new VtexApi(
18
+ this.accountConfig.AccountName,
19
+ this.accountConfig.Credentials.key,
20
+ this.accountConfig.Credentials.token
21
+ );
22
+ }
23
+ }
24
+
25
+ /**
26
+ * Valida si las coordenadas geográficas están configuradas correctamente
27
+ * @returns {Promise<{isValid: boolean, errors: string[], warnings: string[]}>}
28
+ */
29
+ async validateCoordinates() {
30
+ const result = {
31
+ isValid: true,
32
+ errors: [],
33
+ warnings: []
34
+ };
35
+
36
+ try {
37
+ let shouldValidateDefault = false;
38
+ let shouldValidateListOptions = false;
39
+
40
+ // Determinar qué validaciones necesitamos hacer
41
+ if (this.accountConfig.SetGeoCoordinatesGlobal === true) {
42
+ shouldValidateDefault = true;
43
+ }
44
+
45
+ if (this.accountConfig.SetGeoCoordinatesApp === true) {
46
+ shouldValidateListOptions = true;
47
+ // Para SetGeoCoordinatesApp también validamos default porque son independientes
48
+ shouldValidateDefault = true;
49
+ }
50
+
51
+ // Si no hay nada que validar, retornar éxito
52
+ if (!shouldValidateDefault && !shouldValidateListOptions) {
53
+ Logger.debug("Both SetGeoCoordinatesGlobal and SetGeoCoordinatesApp are disabled, skipping coordinates validation");
54
+ return result;
55
+ }
56
+
57
+ // Validar que country esté configurado para cualquier tipo de validación
58
+ if (!this.accountConfig.CodeCountry || this.accountConfig.CodeCountry.trim() === "") {
59
+ result.isValid = false;
60
+ result.errors.push("CodeCountry property is required when SetGeoCoordinatesGlobal or SetGeoCoordinatesApp is enabled");
61
+ return result;
62
+ }
63
+
64
+ // Validar coordenadas por defecto (requerido para ambos casos)
65
+ if (shouldValidateDefault) {
66
+ Logger.debug("Validating default coordinates");
67
+ const defaultCoordinatesValidation = await this.validateDefaultCoordinates();
68
+ if (!defaultCoordinatesValidation.isValid) {
69
+ result.isValid = false;
70
+ result.errors.push(...defaultCoordinatesValidation.errors);
71
+ }
72
+ result.warnings.push(...defaultCoordinatesValidation.warnings);
73
+ }
74
+
75
+ // Validar coordenadas de listOptions si SetGeoCoordinatesApp está habilitado
76
+ if (shouldValidateListOptions) {
77
+ Logger.debug("Validating listOptions coordinates (SetGeoCoordinatesApp = true)");
78
+ const listOptionsValidation = await this.validateListOptionsCoordinates();
79
+ if (!listOptionsValidation.isValid) {
80
+ result.isValid = false;
81
+ result.errors.push(...listOptionsValidation.errors);
82
+ }
83
+ result.warnings.push(...listOptionsValidation.warnings);
84
+ }
85
+
86
+ } catch (error) {
87
+ Logger.error("Error during coordinates validation:", error);
88
+ result.isValid = false;
89
+ result.errors.push(`Validation error: ${error.message}`);
90
+ }
91
+
92
+ return result;
93
+ }
94
+
95
+ /**
96
+ * Valida las coordenadas por defecto
97
+ * @returns {Promise<{isValid: boolean, errors: string[], warnings: string[]}>}
98
+ */
99
+ async validateDefaultCoordinates() {
100
+ const result = {
101
+ isValid: true,
102
+ errors: [],
103
+ warnings: []
104
+ };
105
+
106
+ const defaultCoords = this.accountConfig.ConditionsGeoCoordinates?.default;
107
+
108
+ if (!defaultCoords) {
109
+ result.errors.push("Default coordinates are not configured in ConditionsGeoCoordinates.default");
110
+ result.isValid = false;
111
+ return result;
112
+ }
113
+
114
+ const { latitude, longitude } = defaultCoords;
115
+
116
+ // Caso 5: Ignorar validación si las coordenadas están en cero o vacías
117
+ if (this.isCoordinateZeroOrEmpty(latitude) && this.isCoordinateZeroOrEmpty(longitude)) {
118
+ result.warnings.push("Default coordinates are set to (0,0) or empty, skipping validation");
119
+ return result;
120
+ }
121
+
122
+ // Convertir a número si viene como string
123
+ const lat = typeof latitude === 'string' ? parseFloat(latitude) : latitude;
124
+ const lng = typeof longitude === 'string' ? parseFloat(longitude) : longitude;
125
+
126
+ // Validar que las coordenadas sean números válidos
127
+ if (!this.isValidCoordinate(lat) || !this.isValidCoordinate(lng)) {
128
+ result.errors.push("Invalid default coordinates format");
129
+ result.isValid = false;
130
+ return result;
131
+ }
132
+
133
+ // Validar coordenadas con VTEX API
134
+ const vtexValidation = await this.validateCoordinatesWithVtex(
135
+ lat,
136
+ lng,
137
+ "default coordinates"
138
+ );
139
+
140
+ if (!vtexValidation.isValid) {
141
+ result.isValid = false;
142
+ result.errors.push(...vtexValidation.errors);
143
+ }
144
+ result.warnings.push(...vtexValidation.warnings);
145
+
146
+ return result;
147
+ }
148
+
149
+ /**
150
+ * Valida las coordenadas de listOptions cuando SetGeoCoordinatesApp está habilitado
151
+ * @returns {Promise<{isValid: boolean, errors: string[], warnings: string[]}>}
152
+ */
153
+ async validateListOptionsCoordinates() {
154
+ const result = {
155
+ isValid: true,
156
+ errors: [],
157
+ warnings: []
158
+ };
159
+
160
+ const listOptions = this.accountConfig.ConditionsGeoCoordinates?.listOptions;
161
+
162
+ if (!listOptions || !Array.isArray(listOptions)) {
163
+ result.warnings.push("No listOptions found for SetGeoCoordinatesApp validation");
164
+ return result;
165
+ }
166
+
167
+ for (let i = 0; i < listOptions.length; i++) {
168
+ const option = listOptions[i];
169
+ const geoCoords = option?.geoCoordinates;
170
+
171
+ if (!geoCoords) {
172
+ result.warnings.push(`listOptions[${i}] missing geoCoordinates`);
173
+ continue;
174
+ }
175
+
176
+ const { latitude, longitude } = geoCoords;
177
+
178
+ // Caso 5: Ignorar si las coordenadas están en cero o vacías
179
+ if (this.isCoordinateZeroOrEmpty(latitude) && this.isCoordinateZeroOrEmpty(longitude)) {
180
+ result.warnings.push(`listOptions[${i}] coordinates are set to (0,0) or empty, skipping validation`);
181
+ continue;
182
+ }
183
+
184
+ // Convertir a número si viene como string
185
+ const lat = typeof latitude === 'string' ? parseFloat(latitude) : latitude;
186
+ const lng = typeof longitude === 'string' ? parseFloat(longitude) : longitude;
187
+
188
+ // Validar formato de coordenadas
189
+ if (!this.isValidCoordinate(lat) || !this.isValidCoordinate(lng)) {
190
+ result.errors.push(`Invalid coordinates format in listOptions[${i}]`);
191
+ result.isValid = false;
192
+ continue;
193
+ }
194
+
195
+ // Validar con VTEX API
196
+ const vtexValidation = await this.validateCoordinatesWithVtex(
197
+ lat,
198
+ lng,
199
+ `listOptions[${i}]`
200
+ );
201
+
202
+ if (!vtexValidation.isValid) {
203
+ result.isValid = false;
204
+ result.errors.push(...vtexValidation.errors.map(error =>
205
+ `listOptions[${i}]: ${error}`
206
+ ));
207
+ }
208
+ result.warnings.push(...vtexValidation.warnings.map(warning =>
209
+ `listOptions[${i}]: ${warning}`
210
+ ));
211
+ }
212
+
213
+ return result;
214
+ }
215
+
216
+ /**
217
+ * Valida coordenadas usando la API de regiones de VTEX
218
+ * @param {number} latitude - Latitud
219
+ * @param {number} longitude - Longitud
220
+ * @param {string} context - Contexto para logging
221
+ * @returns {Promise<{isValid: boolean, errors: string[], warnings: string[]}>}
222
+ */
223
+ async validateCoordinatesWithVtex(latitude, longitude, context = "") {
224
+ const result = {
225
+ isValid: true,
226
+ errors: [],
227
+ warnings: []
228
+ };
229
+
230
+ if (!this.vtexApi) {
231
+ result.errors.push("VTEX API credentials not available for coordinates validation");
232
+ result.isValid = false;
233
+ return result;
234
+ }
235
+
236
+ try {
237
+ const country = this.accountConfig.CodeCountry;
238
+ const geoCoordinates = `${longitude}%3B${latitude}`; // URL encoded format: lng%3Blat
239
+ const salesChannel = this.accountConfig.SalesChannel || "1";
240
+
241
+ Logger.debug(`Validating coordinates ${context}:`, {
242
+ country,
243
+ geoCoordinates,
244
+ salesChannel,
245
+ accountName: this.accountConfig.AccountName
246
+ });
247
+
248
+ // Llamada a la API de regiones de VTEX usando formato público
249
+ const response = await this.vtexApi.fetch(
250
+ `/checkout/pub/regions?country=${country}&geoCoordinates=${geoCoordinates}&sc=${salesChannel}`,
251
+ {
252
+ method: "GET"
253
+ },
254
+ false // printLog = false para evitar logs de error innecesarios
255
+ );
256
+
257
+ if (!response || response.status !== 200) {
258
+ result.errors.push(`VTEX regions API returned status ${response?.status || 'unknown'} for ${context}`);
259
+ result.isValid = false;
260
+ return result;
261
+ }
262
+
263
+ const regions = response.data;
264
+
265
+ // Verificar que la respuesta contenga información de sellers
266
+ if (!regions || !Array.isArray(regions) || regions.length === 0) {
267
+ result.errors.push(`No regions found for coordinates ${context} (${latitude}, ${longitude})`);
268
+ result.isValid = false;
269
+ return result;
270
+ }
271
+
272
+ // Buscar si alguna región contiene el AccountName como seller
273
+ let sellerFound = false;
274
+ let availableSellers = [];
275
+
276
+ for (const region of regions) {
277
+ if (region.sellers && Array.isArray(region.sellers)) {
278
+ const sellers = region.sellers || [];
279
+ availableSellers.push(...sellers.map(seller => seller.id));
280
+ const matchingSeller = sellers.find(seller => {
281
+ return seller.id && seller.id === this.accountConfig.AccountName;
282
+ });
283
+
284
+ if (matchingSeller) {
285
+ sellerFound = true;
286
+ break;
287
+ }
288
+ }
289
+ }
290
+
291
+ if (!sellerFound) {
292
+ const uniqueSellers = [...new Set(availableSellers)];
293
+ result.errors.push(
294
+ `Account '${this.accountConfig.AccountName}' not found as seller for ${context} (${latitude}, ${longitude}). ` +
295
+ `Available sellers: ${uniqueSellers.length > 0 ? uniqueSellers.join(', ') : 'none'}`
296
+ );
297
+ result.isValid = false;
298
+ } else {
299
+ Logger.debug(`✓ Coordinates ${context} validated successfully for account ${this.accountConfig.AccountName}`);
300
+ }
301
+
302
+ } catch (error) {
303
+ Logger.error(`Error validating coordinates ${context} with VTEX:`, error);
304
+ result.errors.push(`Error validating ${context}: ${error.message}`);
305
+ result.isValid = false;
306
+ }
307
+
308
+ return result;
309
+ }
310
+
311
+ /**
312
+ * Verifica si un valor es una coordenada válida
313
+ * @param {any} coordinate - Valor a validar
314
+ * @returns {boolean}
315
+ */
316
+ isValidCoordinate(coordinate) {
317
+ return (
318
+ typeof coordinate === 'number' &&
319
+ !isNaN(coordinate) &&
320
+ isFinite(coordinate)
321
+ );
322
+ }
323
+
324
+ /**
325
+ * Verifica si una coordenada es cero o está vacía (Caso 5)
326
+ * @param {any} coordinate - Valor a validar
327
+ * @returns {boolean}
328
+ */
329
+ isCoordinateZeroOrEmpty(coordinate) {
330
+ return (
331
+ coordinate === 0 || // número 0
332
+ coordinate === "0" || // string "0"
333
+ coordinate === "" || // string vacío
334
+ coordinate === null || // null
335
+ coordinate === undefined // undefined
336
+ );
337
+ }
338
+
339
+ /**
340
+ * Método estático para validar coordenadas de un account
341
+ * @param {Object} accountConfig - Configuración del account
342
+ * @returns {Promise<{isValid: boolean, errors: string[], warnings: string[]}>}
343
+ */
344
+ static async validate(accountConfig) {
345
+ const validator = new AccountCoordinatesValidation(accountConfig);
346
+ return await validator.validateCoordinates();
347
+ }
348
+ }
349
+
350
+ module.exports = AccountCoordinatesValidation;
@@ -0,0 +1,11 @@
1
+ const MainErrorValidation = require("./MainErrorValidation");
2
+
3
+ class GeneralErrorValidation extends MainErrorValidation {
4
+ constructor(property) {
5
+ super(`${property}`);
6
+ this.name = "GeneralErrorValidation";
7
+ this.property = property;
8
+ }
9
+ }
10
+
11
+ module.exports = GeneralErrorValidation;
@@ -0,0 +1,8 @@
1
+ class MainErrorValidation extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = "MainErrorValidation";
5
+ }
6
+ }
7
+
8
+ module.exports = MainErrorValidation;