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,405 @@
1
+ const axios = require("axios");
2
+ const ApiResponse = require("../../common/utils/api-response");
3
+ const VtexApi = require("../../vtex/clients/VtexApi");
4
+ const Logger = require("../../common/utils/logger");
5
+
6
+ /**
7
+ * Class representing the MobilvendorApi.
8
+ *
9
+ * @class
10
+ * @classdesc This class provides methods for interacting with the Mobilvendor API.
11
+ */
12
+ class MobilvendorApi {
13
+ constructor(AccountName, Key, Token, AcronymClientVtex, FinancialPolicyEcu) {
14
+ this.AccountName = AccountName;
15
+ this.Key = Key;
16
+ this.Token = Token;
17
+ this.AcronymClientVtex = AcronymClientVtex;
18
+ this.FinancialPolicyEcu = FinancialPolicyEcu;
19
+ }
20
+
21
+ /**
22
+ * set FinancialPolicyEcu
23
+ * */
24
+ setConfig(FinancialPolicyEcu) {
25
+ this.FinancialPolicyEcu= FinancialPolicyEcu;
26
+ }
27
+
28
+ /**
29
+ * Logs in to the Mobilvendor API.
30
+ *
31
+ * @returns {Object} An object containing the context ID and session ID.
32
+ * - contextId: The ID of the context.
33
+ * - sessionId: The ID of the session.
34
+ * @throws {Error} If there is an error during the login process.
35
+ */
36
+ async login() {
37
+ try {
38
+ const responseLogin = await axios.post(this.FinancialPolicyEcu.configService.url,
39
+ this.FinancialPolicyEcu.configService.body
40
+ );
41
+
42
+ if (!responseLogin || !responseLogin?.data?.session_id){
43
+ Logger.error("Login mobilvendor have problems");
44
+ return ApiResponse.response(404, { approved: false, message: "Login mobilvendor have problems" });
45
+ }
46
+
47
+ const sessionId = responseLogin.data.session_id;
48
+ const responseContexts = await axios.post(this.FinancialPolicyEcu.configService.url, {
49
+ session_id: sessionId,
50
+ action: "getContexts",
51
+ });
52
+ const response = responseContexts?.data?.records;
53
+ let contextId = response?.find(record => record?.id === this.FinancialPolicyEcu.configService.context)?.id;
54
+
55
+ if (!contextId) {
56
+ contextId = this.FinancialPolicyEcu.configService.context;
57
+ }
58
+
59
+ return { contextId, sessionId };
60
+ } catch (error) {
61
+ Logger.error(error);
62
+ return ApiResponse.response(404, { approved: false, message: "Login mobilvendor have problems" });
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Retrieves the client data by email.
68
+ *
69
+ * This method retrieves the client data by performing the following steps:
70
+ * 1. Creates an instance of the VtexApi class using the provided account name, key, and token.
71
+ * 2. Extracts the client ID from the email.
72
+ * 3. Sends a GET request to the Vtex API to retrieve the client data for the specified ID.
73
+ * 4. Checks the response status. If the status is between 200 and 299 (inclusive), returns the client data.
74
+ * 5. Returns null if the response status is outside the range of 200 to 299.
75
+ *
76
+ * @param {string} email - The email of the client.
77
+ * @returns {Promise<Object|null>} A promise that resolves to the client data if successful, or null in case of an error.
78
+ * @throws {Error} If there is an error during the retrieval process.
79
+ */
80
+ async getClientById(email) {
81
+ try {
82
+ const vtexApi = new VtexApi(this.AccountName, this.Key, this.Token);
83
+ const clientId = email?.split("+")[1]?.split("@")[0];
84
+ const responseMasterDataCT = await vtexApi.fetch(
85
+ `/dataentities/${this.AcronymClientVtex}/search?_fields=_all&id=${clientId}`, { method: "GET" }
86
+ );
87
+
88
+ if (responseMasterDataCT.status >= 200 && responseMasterDataCT.status < 300) {
89
+ return responseMasterDataCT.data[0];
90
+ } else {
91
+ Logger.error(responseMasterDataCT);
92
+ return null;
93
+ }
94
+ } catch (error) {
95
+ Logger.error(error);
96
+ return null;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Retrieves the order form data by ID.
102
+ *
103
+ * This method retrieves the order form data by performing the following steps:
104
+ * 1. Creates an instance of the VtexApi class using the provided account name, key, and token.
105
+ * 2. Sends a GET request to the Vtex API to retrieve the order form data for the specified ID.
106
+ * 3. Checks the response status. If the status is not 200, returns an error response.
107
+ * 4. Returns the order form data.
108
+ *
109
+ * @param {string} orderFormId - The ID of the order form to retrieve.
110
+ * @returns {Promise<Object|null>} A promise that resolves to the order form data if successful, or null in case of an error.
111
+ * @throws {Error} If there is an error during the retrieval process.
112
+ */
113
+ async getOrderFormById(orderFormId) {
114
+ try {
115
+ const vtexApi = new VtexApi(this.AccountName, this.Key, this.Token);
116
+ const responseOrderForm = await vtexApi.fetch(`/checkout/pub/orderForm/${orderFormId}?refreshOutdatedData=true`, { method: "GET" });
117
+
118
+ if (responseOrderForm.status !== 200){
119
+ Logger.error(responseOrderForm);
120
+ ApiResponse.response(404, { approved: false, message: "orderForm is not found" });
121
+ }
122
+
123
+ const { data } = responseOrderForm;
124
+
125
+ return data;
126
+ } catch (error) {
127
+ Logger.error(error);
128
+ return null;
129
+ }
130
+ }
131
+
132
+ async deleteCustomData(orderFormId, customData) {
133
+ try {
134
+ if (!customData) {
135
+ return true;
136
+ }
137
+ const vtexApi = new VtexApi(this.AccountName, this.Key, this.Token);
138
+ const customApps = customData?.customApps ?? [];
139
+ const financialPolicy = customApps?.find(app => app.id === this.FinancialPolicyEcu.configVtex.id);
140
+ const fields = financialPolicy?.fields;
141
+
142
+ if(this.FinancialPolicyEcu?.attachmentCredit && this.FinancialPolicyEcu?.attachmentCredit?.name && this.FinancialPolicyEcu?.attachmentCredit?.value){
143
+ await vtexApi.fetchPub(`/checkout/pub/orderForm/${orderFormId}/attachments/${this.FinancialPolicyEcu?.attachmentCredit?.name}`, { method: "POST" }, {value: null});
144
+ }
145
+
146
+ for (const field in fields) {
147
+ await vtexApi.fetchPub(`/checkout/pub/orderForm/${orderFormId}/customData/${this.FinancialPolicyEcu.configVtex.id}/${field}`, { method: "DELETE" });
148
+ }
149
+
150
+ return true;
151
+ } catch (error) {
152
+ Logger.error(error);
153
+ return ApiResponse.response(401, { approved: false, message: "Error deleting customData orderForm" });
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Updates the custom data of an order form.
159
+ *
160
+ * This method updates the custom data of an order form by performing the following steps:
161
+ * 1. Creates an instance of the VtexApi class using the provided account name, key, and token.
162
+ * 2. Sends a PUT request to the Vtex API to update the custom data of the specified order form.
163
+ * 3. Checks the response status. If the status is not 200, returns an error response.
164
+ * 4. Returns the updated custom data.
165
+ *
166
+ * @param {string} orderFormId - The ID of the order form to update.
167
+ * @param {string} idConfigVtex - The ID of the custom data configuration in Vtex.
168
+ * @param {Object} customData - The custom data to update.
169
+ * @returns {Promise<Object|null>} A promise that resolves to the updated custom data if successful, or null in case of an error.
170
+ * @throws {Error} If there is an error during the update process.
171
+ */
172
+ async updateOrderFormCustomData(orderFormId, idConfigVtex, customData) {
173
+ try {
174
+ const vtexApi = new VtexApi(this.AccountName, this.Key, this.Token);
175
+ const response = await vtexApi.fetchPub(
176
+ `/checkout/pub/orderForm/${orderFormId}/customData/${idConfigVtex}`,
177
+ { method: "PUT" },
178
+ customData
179
+ );
180
+
181
+ if(this.FinancialPolicyEcu?.attachmentCredit && this.FinancialPolicyEcu?.attachmentCredit?.name && this.FinancialPolicyEcu?.attachmentCredit?.value){
182
+ await vtexApi.fetchPub(`/checkout/pub/orderForm/${orderFormId}/attachments/${this.FinancialPolicyEcu?.attachmentCredit?.name}`, { method: "POST" }, this.FinancialPolicyEcu?.attachmentCredit?.value);
183
+ }
184
+
185
+ if (response.status !== 200) {
186
+ Logger.error(response);
187
+ return ApiResponse.response(401, { approved: false, message: "Error updating customData orderForm" });
188
+ }
189
+
190
+ return response.data;
191
+ } catch (error) {
192
+ Logger.error(error);
193
+ return ApiResponse.response(401, { approved: false, message: "Error updating customData orderForm" });
194
+ }
195
+ }
196
+
197
+ async cleanOrderFormCustomData(orderFormId, idConfigVtex) {
198
+ try {
199
+ const vtexApi = new VtexApi(this.AccountName, this.Key, this.Token);
200
+ const customData = {
201
+ "approved": "false",
202
+ "withCredit": "false",
203
+ "paymentTerm": "-",
204
+ "maximumCreditAmount": "-",
205
+ "paymentMethodCode": "-",
206
+ "creditDays": "-",
207
+ "paymentMethodName": "-"
208
+ };
209
+ const response = await vtexApi.fetchPub(
210
+ `/checkout/pub/orderForm/${orderFormId}/customData/${idConfigVtex}`,
211
+ { method: "PUT" },
212
+ customData
213
+ );
214
+
215
+ if (response.status !== 200){
216
+ Logger.error(response);
217
+ return ApiResponse.response(401, { approved: false, message: "Error deleting customData orderForm" });
218
+ }
219
+
220
+ return response.data;
221
+ } catch (error) {
222
+ Logger.error(error);
223
+ return ApiResponse.response(401, { approved: false, message: "Error cleaning customData orderForm" });
224
+ }
225
+ }
226
+
227
+ /**
228
+ * Retrieves the customer balance from the Mobilvendor API.
229
+ *
230
+ * This method retrieves the customer balance by performing the following steps:
231
+ * 1. Checks if the Financial Policy is active. If not, returns an error response.
232
+ * 2. Checks if the orderFormId is provided. If not, returns an error response.
233
+ * 3. Retrieves the order form data using the provided orderFormId.
234
+ * 4. Retrieves the client data using the email from the order form data.
235
+ * 5. Retrieves the customer balance from the Mobilvendor API using the customer code.
236
+ * 6. Checks if the customer is found in the Mobilvendor API. If not, throws an error response.
237
+ * 7. Calculates the approved status based on various conditions.
238
+ * 8. Constructs the response object with the customer balance information.
239
+ * 9. Checks if the credit is not approved. If not, returns an error response.
240
+ * 10. Returns the response object with the customer balance information.
241
+ *
242
+ * @param {string} orderFormId - The ID of the order form associated with the customer.
243
+ * @param {number} creditDays - The number of credit days to consider for the customer.
244
+ * @returns {Promise<Object|null>} A promise that resolves to the response object with the customer balance information if successful, or null in case of an error.
245
+ * @throws {Error} If there is an error during the retrieval process.
246
+ */
247
+ async getCustomerBalance(orderForm, creditDays = null, responseMasterDataCT=null) {
248
+ // Verificar si la política financiera está activa
249
+ if (!this.FinancialPolicyEcu.isActive) {
250
+ Logger.error("Financial Policy is not active");
251
+ return ApiResponse.response(401, { approved: false, message: "Financial Policy is not active" });
252
+ }
253
+
254
+ // Verificar si se proporcionó el orderFormId
255
+ if (!orderForm) {
256
+ Logger.error("orderForm is Required");
257
+ return ApiResponse.response(400, { approved: false, message: "orderForm is Required" });
258
+ }
259
+
260
+ // Obtener la información del cliente
261
+ const email = orderForm.clientProfileData?.email;
262
+ if (!responseMasterDataCT) {
263
+ Logger.error("Client not found");
264
+ return ApiResponse.response(404, { approved: false, message: "Client not found" });
265
+ }
266
+
267
+ // Calcular el valor del pedido
268
+ const value = (orderForm.value || 0) / 100;
269
+ const customerCode = responseMasterDataCT.pdv;
270
+ const customerWithCredit = responseMasterDataCT.withCredit ?? false;
271
+ // Obtener el balance del cliente
272
+ const responseMobilvendor = await this.getBalanceByCode(customerCode, value, creditDays, customerWithCredit);
273
+ return responseMobilvendor;
274
+ }
275
+
276
+ /**
277
+ * Retrieves the customer balance from the Mobilvendor API based on the customer code, value, and credit days.
278
+ *
279
+ * @param {string} customerCode - The customer code.
280
+ * @param {number} value - The value.
281
+ * @param {number} creditDays - The credit days.
282
+ * @returns {Object} - The response from the Mobilvendor API containing the customer balance information.
283
+ * @throws {Error} - If there is an error retrieving the customer balance.
284
+ */
285
+ async getBalanceByCode(customerCode, value, creditDays = null, customerWithCredit=false) {
286
+ const { contextId, sessionId } = await this.login();
287
+ const dataGetCustomerBalance = {
288
+ session_id: sessionId,
289
+ action: "getCustomerBalance",
290
+ context_id: contextId,
291
+ customer_codes: [customerCode],
292
+ };
293
+ const { data } = await axios.post(this.FinancialPolicyEcu.configService.url, dataGetCustomerBalance);
294
+
295
+ if (!data?.records || data?.records.length == 0) {
296
+ Logger.error("customer not found in mobilvendor", dataGetCustomerBalance);
297
+ return ApiResponse.response(404, { approved: false, message: "customer not found in mobilvendor" });
298
+ }
299
+
300
+ const controlData = data.records[0];
301
+ const balanceRecord = data.records.find(
302
+ (record) =>
303
+ (record.concepts === "2" || parseFloat(record.credit_limit) > 0) &&
304
+ record.status === "A" &&
305
+ record.expired_invoices === "0" &&
306
+ (creditDays ? parseInt(record.payment_term_days) === parseInt(creditDays) : true)
307
+ );
308
+
309
+ if (!balanceRecord) {
310
+ Logger.error("customer not found credit", controlData);
311
+ return ApiResponse.response(404, { approved: false, message: "customer not found credit" });
312
+ }
313
+
314
+ const {
315
+ balance,
316
+ status,
317
+ credit_limit,
318
+ payment_term_code,
319
+ payment_term_days,
320
+ payment_term_description,
321
+ concepts,
322
+ expired_invoices,
323
+ } = balanceRecord;
324
+
325
+ const approved =
326
+ status === "A" &&
327
+ (concepts === "0" || concepts === "2") &&
328
+ value <= parseFloat(credit_limit) &&
329
+ expired_invoices === "0" &&
330
+ parseFloat(balance) === 0;
331
+
332
+ const responseMobilvendor = {
333
+ approved,
334
+ withCredit: approved,
335
+ paymentTerm: payment_term_days || "",
336
+ maximumCreditAmount: parseFloat(credit_limit) || 0,
337
+ creditDays: parseInt(payment_term_days) || 0,
338
+ paymentMethodCode: payment_term_code || "",
339
+ paymentMethodName: payment_term_description || "",
340
+ customerWithCredit: approved ?? false
341
+ };
342
+
343
+ Logger.debug({ responseMobilvendor });
344
+ return responseMobilvendor;
345
+ }
346
+
347
+ /**
348
+ * Retrieves information about a specific route from the Mobilvendor API.
349
+ *
350
+ * This method first logs in to obtain the necessary session and context IDs. It then sends a POST request to the Mobilvendor API with the route code to retrieve information about the specified route.
351
+ *
352
+ * @param {string} routeCode - The code of the route for which to retrieve information.
353
+ * @returns {Promise<Object|null>} A promise that resolves to the route information from the Mobilvendor API if successful, or null in case of an error.
354
+ */
355
+ async getRoute(routeCode) {
356
+ try {
357
+ const { contextId, sessionId } = await this.login();
358
+ const dataGetRoute = {
359
+ session_id: sessionId,
360
+ action: "getRoute",
361
+ context_id: contextId,
362
+ route_code: routeCode,
363
+ };
364
+ const responseGetRoute = await axios.post(
365
+ this.FinancialPolicyEcu.configService.url,
366
+ dataGetRoute
367
+ );
368
+
369
+ return responseGetRoute.data;
370
+ } catch (error) {
371
+ Logger.error(error);
372
+ return null;
373
+ }
374
+ }
375
+
376
+ /**
377
+ * Retrieves information about a specific route from the Mobilvendor API.
378
+ *
379
+ * This method first logs in to obtain the necessary session and context IDs. It then sends a POST request to the Mobilvendor API with the route code to retrieve information about the specified route.
380
+ *
381
+ * @param {string} routeCode - The code of the route for which to retrieve information.
382
+ * @returns {Promise<Object|null>} A promise that resolves to the route information from the Mobilvendor API if successful, or null in case of an error.
383
+ */
384
+ async getRoutes() {
385
+ try {
386
+ const { contextId, sessionId } = await this.login();
387
+ const dataGetRoutes = {
388
+ session_id: sessionId,
389
+ action: "getRoutes",
390
+ context_id: contextId,
391
+ };
392
+ const responseGetRoutes = await axios.post(
393
+ this.FinancialPolicyEcu.configService.url,
394
+ dataGetRoutes
395
+ );
396
+
397
+ return responseGetRoutes.data.records;
398
+ } catch (error) {
399
+ Logger.error(error);
400
+ return null;
401
+ }
402
+ }
403
+ }
404
+
405
+ module.exports = MobilvendorApi;
@@ -0,0 +1,200 @@
1
+ const axios = require("axios");
2
+ const VtexApi = require("../../vtex/clients/VtexApi");
3
+ const Logger = require("../../common/utils/logger");
4
+
5
+ class ProductMultiPresentation {
6
+ constructor(AccountName, Key, Token, AcronymDistributorVtex, ProductMultiPresentation) {
7
+ this.AccountName = AccountName;
8
+ this.Key = Key;
9
+ this.Token = Token;
10
+ this.AcronymDistributorVtex = AcronymDistributorVtex;
11
+ this.ProductMultiPresentation = ProductMultiPresentation;
12
+ }
13
+
14
+ /**
15
+ * Function per uatentication service external
16
+ **/
17
+ async getTokenAuth() {
18
+ return new Promise(async (response) => {
19
+ if (this.ProductMultiPresentation?.ServiceAuth && this.ProductMultiPresentation?.ServiceAuth?.Url && this.ProductMultiPresentation?.ServiceAuth?.Url != "") {
20
+ const url = this.ProductMultiPresentation?.ServiceAuth?.Url;
21
+ const options = {
22
+ method: this.ProductMultiPresentation?.ServiceAuth?.Method ?? 'GET',
23
+ headers: this.ProductMultiPresentation?.ServiceAuth?.Headers ?? {},
24
+ data: (this.ProductMultiPresentation?.ServiceAuth?.Body ? this.ProductMultiPresentation?.ServiceAuth?.Body : {}),
25
+ url
26
+ };
27
+
28
+ try {
29
+ const resp = await axios(options);
30
+ if (resp?.data) {
31
+ response(resp?.data);
32
+ } else {
33
+ response(null);
34
+ }
35
+ } catch (e) {
36
+ Logger.error("error auth ProductMultiPresentation", e);
37
+ response(null);
38
+ }
39
+ } else {
40
+ Logger.error("error auth ProductMultiPresentation", "ServiceAuth not found");
41
+ response(null);
42
+ }
43
+
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Normalize service extenal headers and body
49
+ **/
50
+ async normalizeBodyAndHeaders(AppExternalPresentation, token=null) {
51
+ let { Body: body, Headers: headers } = AppExternalPresentation;
52
+
53
+ if (typeof body === 'object') {
54
+ for (let property in body) {
55
+ if (typeof body[property] === 'string') {
56
+ try {
57
+ body[property] = eval(body[property]);
58
+ } catch (errEval) {
59
+ Logger.debug("error normalizeBodyAndHeaders", errEval, token);
60
+ }
61
+ }
62
+ }
63
+ }
64
+ if (typeof headers === 'object') {
65
+ for (let property in headers) {
66
+ if (typeof headers[property] === 'string') {
67
+ try {
68
+ headers[property] = eval(headers[property]);
69
+ } catch (errEval) {
70
+ Logger.debug("error normalizeBodyAndHeaders", errEval, token);
71
+ }
72
+ }
73
+ }
74
+ }
75
+
76
+ return { body, headers };
77
+ }
78
+
79
+ async getProductList() {
80
+ let productList = [];
81
+ try {
82
+ const { AppExternalPresentation } = this.ProductMultiPresentation;
83
+ const { Url, Method, DtoProducts, AssignListProduct } = AppExternalPresentation;
84
+ const token= await this.getTokenAuth();
85
+ const { body, headers } = await this.normalizeBodyAndHeaders(AppExternalPresentation, token);
86
+ const response = await axios({
87
+ url: Url,
88
+ method: Method ?? 'post',
89
+ headers: headers,
90
+ data: JSON.stringify(body)
91
+ });
92
+
93
+ // Se extrae la lista de productos de Geosales obtenida de la petición
94
+ let products = [];
95
+ if (AssignListProduct && AssignListProduct !== "") {
96
+ eval(`products=${AssignListProduct};`);
97
+ } else {
98
+ products = response?.data;
99
+ }
100
+
101
+ // Se recorre la lista de productos (si existen elementos)
102
+ if (products?.length > 0) {
103
+ // Como la petición puede retornar 2 o más ítems con un mismo SKU, se deben agrupar los mismos priorizando aquellos que cumplan con la condicion "activo=1"
104
+ let skus = {}, index = 0;
105
+ for (let product of products) {
106
+ const { sku, activo } = product;
107
+ if (!skus.hasOwnProperty(sku)) {
108
+ // Si el SKU no está en el listado se agrega la información en la lista y se define los datos del índice de array y estado
109
+ productList.push(product);
110
+ skus[sku] = { index, activo };
111
+ index++;
112
+ } else {
113
+ // Se verifica si el producto de la lista tiene activo=0; pero se encontró un registro con el mismo SKU pero con activo=1, para actualizar los datos del producto
114
+ const { index } = skus[sku];
115
+ if (skus[sku].activo == '0' && activo == '1') {
116
+ productList[index] = product;
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+ // Si la lista unificada de productos tiene elementos, y se contempla aplicar un transformado de los datos, se actualiza el contenido de la lista
123
+ if (productList.length && Object.keys(DtoProducts).length > 0) {
124
+ productList = productList.map(product => {
125
+ const formattedProduct = {};
126
+ for (const [key, value] of Object.entries(DtoProducts)) {
127
+ if (product.hasOwnProperty(value)) {
128
+ formattedProduct[key] = product[value];
129
+ }
130
+ }
131
+ return formattedProduct;
132
+ });
133
+ }
134
+ } catch (error) {
135
+ Logger.error(error);
136
+ }
137
+ return productList;
138
+ }
139
+
140
+ async getDistributorList() {
141
+ try {
142
+ const vtexApi = new VtexApi(this.AccountName, this.Key, this.Token);
143
+ const distributors = await vtexApi.fetch(`/dataentities/${this.AcronymDistributorVtex}/search?_fields=_all`, {
144
+ method: "GET",
145
+ });
146
+
147
+ return distributors?.data?.length > 0 ? distributors.data : [];
148
+ } catch (error) {
149
+ Logger.error(error);
150
+ return [];
151
+ }
152
+ }
153
+
154
+ async getAllProductsVTEX() {
155
+ return new Promise(async (res, err) => {
156
+ let listProductSkus = [];
157
+ try {
158
+ const listTradePolicy = this.ProductMultiPresentation?.TradePolicyId?.length > 0 ? this.ProductMultiPresentation?.TradePolicyId : [1];
159
+ const vtexApi = new VtexApi(this.AccountName, this.Key, this.Token);
160
+
161
+ for (let i = 0; i < listTradePolicy.length; i++) {
162
+ let stop = false, _from = 0, _to = 49;
163
+ while (stop === false) {
164
+ try {
165
+ const products = await vtexApi.fetch(`/catalog_system/pub/products/search/?sc=${listTradePolicy[i]}&_to=${_to}&_from=${_from}&O=OrderByNameASC`, {
166
+ method: "GET",
167
+ });
168
+
169
+ if (products?.data?.length > 0) {
170
+ for (let j = 0; j < products.data.length; j++) {
171
+ for (let t = 0; t < products.data[j].items.length; t++) {
172
+ let prod = products.data[j].items[t];
173
+ prod.productId = products.data[j].productId;
174
+ prod.TradePolicyId = listTradePolicy[i];
175
+ listProductSkus.push(prod);
176
+ }
177
+ }
178
+ } else {
179
+ stop = true;
180
+ }
181
+ } catch (error) {
182
+ Logger.error("error getAllProductsVTEX while", error);
183
+ stop = true;
184
+ }
185
+
186
+ _from += 50;
187
+ _to += 50;
188
+ }
189
+ }
190
+
191
+ } catch (error) {
192
+ Logger.error("error getAllProductsVTEX", error);
193
+ }
194
+
195
+ res(listProductSkus);
196
+ });
197
+ }
198
+ }
199
+
200
+ module.exports = ProductMultiPresentation;
@@ -0,0 +1,77 @@
1
+ const axios = require("axios");
2
+ const Logger = require("../../common/utils/logger");
3
+
4
+ class SecretManagerApi {
5
+ constructor(authorization, baseUrl) {
6
+ if (!authorization || !baseUrl) {
7
+ throw new Error("Invalid Secret Manager API Credentials");
8
+ }
9
+ this.authorization = authorization;
10
+ this.baseUrl = baseUrl;
11
+ }
12
+
13
+ get baseURL() {
14
+ return this.baseUrl;
15
+ }
16
+
17
+ /**
18
+ * Excute a request to Secret Manager API
19
+ * @param {string} path
20
+ * @param {import("axios").AxiosRequestConfig} options
21
+ * @returns {Promise<import("axios").AxiosResponse>}
22
+ */
23
+ fetch(path, options, includeFullResponse = true) {
24
+ const params = {
25
+ url: `${this.baseURL}/${path}`.replace(/([^:]\/)\/+/g, "$1"),
26
+ method: options.method || "GET",
27
+ headers: {
28
+ "Content-Type": "application/json",
29
+ Authorization: this.authorization,
30
+ ...options.headers,
31
+ },
32
+ data : options.data,
33
+ ValidateStatus: function (status) {
34
+ return status >= 200 && status < 300;
35
+ },
36
+ };
37
+
38
+ return axios.request(params).then((response) => {
39
+ if (includeFullResponse) {
40
+ return response;
41
+ }
42
+ return response.data;
43
+ })
44
+ .catch((error) => {
45
+ // error is handled in catch block
46
+ Logger.error("Error Secret Manager API response: ", params);
47
+ if (error.response) {
48
+ // status code out of the range of 2xx
49
+ Logger.error("Data Secret Manager API response: ", error.response.data);
50
+ Logger.error("Status Secret Manager API response : ", error.response.status);
51
+ const errorResponse = {
52
+ status: error.response.status,
53
+ data: error.response.data,
54
+ };
55
+ return errorResponse;
56
+ } else if (error.request) {
57
+ // The request was made but no response was received
58
+ Logger.error("Error Secret Manager API no response: ", error.request);
59
+ const errorResponse = {
60
+ status: 500,
61
+ data: error.request,
62
+ };
63
+ return errorResponse;
64
+ } else {
65
+ // Error on setting up the request
66
+ Logger.error("Error Secret Manager API response: ", error.message);
67
+ const errorResponse = {
68
+ status: 500,
69
+ data: error.message,
70
+ };
71
+ return errorResponse;
72
+ }
73
+ });
74
+ }
75
+ }
76
+
77
+ module.exports = SecretManagerApi;