dcos-core-monalisav2-latam 1.1.3 → 1.1.5

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dcos-core-monalisav2-latam",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "scripts": {
5
5
  "test": "echo \"Error: no test specified\" && exit 1"
6
6
  },
@@ -3,107 +3,6 @@ const VtexApi = require("../../vtex/clients/VtexApi");
3
3
 
4
4
  const DATA_ENTITY_CLIENT_ACRONYM = process.env.DATA_ENTITY_CLIENT_ACRONYM || 'CT';
5
5
 
6
- const buildProductJson = (sku, status, quantity, type, priority) => ({
7
- refId: sku.sku,
8
- status,
9
- quantity: quantity || sku.quantity,
10
- type,
11
- priority: priority || sku.priority
12
- });
13
-
14
- const getClientUserId = async (vtexApi, pdv, an) => {
15
- try {
16
- const clientId = pdv;
17
- const searchResult = await vtexApi.fetch(`/dataentities/${DATA_ENTITY_CLIENT_ACRONYM}/search?_fields=_all&id=${clientId}`, {});
18
- if (searchResult?.status === 200 && searchResult.data?.length > 0) {
19
- return searchResult.data[0]?.id;
20
- }
21
- return null;
22
- } catch (error) {
23
- Logger.error("Error getting client userId", error);
24
- return null;
25
- }
26
- };
27
-
28
- const getCatalogProductStatus = async (vtexApi, skuId) => {
29
- try {
30
- const skuData = await vtexApi.fetch(`/catalog_system/pvt/sku/stockkeepingunitbyid/${skuId}`, {});
31
-
32
- if (skuData?.status === 200 && skuData.data) {
33
- const { IsActive, ProductId } = skuData.data;
34
-
35
- if (!IsActive) return 'inactive';
36
-
37
- const productData = await vtexApi.fetch(`/catalog_system/pvt/products/productget/${ProductId}`, {
38
- validateStatus: () => true
39
- });
40
-
41
- if (productData?.status === 200 && productData.data) {
42
- const { IsVisible, IsActive: productActive } = productData.data;
43
-
44
- if (!productActive) return 'inactive';
45
- if (!IsVisible) return 'not_visible';
46
- return 'active';
47
- }
48
- }
49
-
50
- return 'invalid';
51
- } catch (error) {
52
- Logger.error("Error getting catalog product status", error);
53
- return 'invalid';
54
- }
55
- };
56
-
57
- const saveSuggestedProducts = async (vtexApi, userId, productsData, an, entityProductSuggested) => {
58
- try {
59
- const orderDate = new Date().toISOString();
60
- const data = {
61
- id: `${userId}_${Date.now()}`,
62
- userId,
63
- orderDate,
64
- type: 'suggested',
65
- productsRegular: productsData?.regular,
66
- productsIncremental: productsData?.incremental,
67
- an
68
- };
69
-
70
- await vtexApi.fetch(`/dataentities/${entityProductSuggested}/documents`, {
71
- method: 'POST',
72
- data,
73
- headers: {
74
- 'authorization': 'Basic Og=='
75
- }
76
- });
77
-
78
- Logger.log("Suggested products saved successfully", { userId, orderDate });
79
- } catch (error) {
80
- Logger.error("Error saving suggested products", error);
81
- }
82
- };
83
-
84
- const saveOriginalDataToClient = async (vtexApi, pdv, originalData, an) => {
85
- try {
86
- const clientId = `${pdv}${an}dist1`;
87
- const updateData = {
88
- productsRegular: originalData.productsRegular || [],
89
- productsIncremental: originalData.productsIncremental || [],
90
- lastSuggestedProductsUpdate: new Date().toISOString()
91
- };
92
-
93
- await vtexApi.fetch(`/dataentities/${DATA_ENTITY_CLIENT_ACRONYM}/documents/${clientId}`, {
94
- method: 'PUT',
95
- data: updateData,
96
- headers: {
97
- 'authorization': 'Basic Og=='
98
- }
99
- });
100
-
101
- Logger.log("Original data saved to client", { pdv });
102
- } catch (error) {
103
- Logger.error("Error saving original data to client", error);
104
- }
105
- };
106
-
107
6
  const consumer = async (event) => {
108
7
  try {
109
8
  const records = event.Records || [];
@@ -115,45 +14,46 @@ const consumer = async (event) => {
115
14
  parentAccount,
116
15
  key,
117
16
  token,
118
- pdv,
119
- productsRegular,
120
- productsIncremental,
121
- originalData,
122
- nameEntityProductSuggested
17
+ suggestedProductEntityName,
18
+ Startemail,
19
+ Domainemail,
20
+ ...client
123
21
  } = messageBody;
124
22
 
125
- Logger.log("Processing suggested products for client", { pdv, an });
126
-
23
+ // Referencia a la API de VTEX sobre el marketplace asociado
127
24
  const vtexApi = new VtexApi(parentAccount, key, token);
128
25
 
129
- const userId = await getClientUserId(vtexApi, pdv, an);
130
- console.log("Fetched userId:", userId);
131
- if (!userId) {
132
- Logger.error("Client userId not found", { pdv, an });
133
- continue;
134
- }
135
-
136
- const regularProducts = [];
137
- const incrementalProducts = [];
138
-
139
- for (const sku of productsRegular) {
140
- const status = await getCatalogProductStatus(vtexApi, sku.sku);
141
- regularProducts.push(buildProductJson(sku, status, sku.quantity, 'regular', sku.priority));
142
- }
26
+ const { clientId, productsRegular, productsIncremental } = client;
143
27
 
144
- for (const sku of productsIncremental) {
145
- const status = await getCatalogProductStatus(vtexApi, sku.sku);
146
- incrementalProducts.push(buildProductJson(sku, status, sku.quantity, 'incremental', sku.priority));
147
- }
148
-
149
- await saveSuggestedProducts(vtexApi, userId, {
150
- regular: regularProducts,
151
- incremental: incrementalProducts
152
- }, an, nameEntityProductSuggested);
28
+ // Objeto de datos para el producto sugerido
29
+ const suggestedProductData = {
30
+ orderDate: new Date().toISOString(),
31
+ clientId,
32
+ type: 'SUGGESTED_ORDER',
33
+ productsRegular,
34
+ productsIncremental,
35
+ };
36
+ const email = `${Startemail}+${clientId}@${Domainemail}`;
37
+ // Consulta del userProfileId
38
+ await findUserProfileId(vtexApi, email, suggestedProductData);
39
+
40
+ // Insertar datos en entidad de Productos Sugeridos
41
+ await vtexApi.fetch(`/dataentities/${suggestedProductEntityName}/documents`, {
42
+ method: 'PATCH',
43
+ data: suggestedProductData
44
+ });
153
45
 
154
- await saveOriginalDataToClient(vtexApi, pdv, originalData, an);
46
+ // Insertar datos en Clientes Totales
47
+ await vtexApi.fetch(`/dataentities/${DATA_ENTITY_CLIENT_ACRONYM}/documents`, {
48
+ method: 'PATCH',
49
+ data: {
50
+ id: clientId,
51
+ productsRegular: JSON.stringify(productsRegular),
52
+ productsIncremental: JSON.stringify(productsIncremental),
53
+ }
54
+ });
155
55
 
156
- Logger.log("Suggested products processed successfully", { pdv, userId });
56
+ Logger.log("Suggested products processed successfully", { an, clientId });
157
57
  }
158
58
  } catch (error) {
159
59
  Logger.error("Error in suggested products consumer", error);
@@ -161,6 +61,22 @@ const consumer = async (event) => {
161
61
  }
162
62
  };
163
63
 
164
- module.exports = {
165
- consumer
166
- };
64
+ /**
65
+ * Consulta el userProfile del usuario con base al email.
66
+ * @param {*} vtexApi Instancia de conexión a la API de VTEX.
67
+ * @param {String} email Correo electrónico del usuario
68
+ * @param {Object} suggestedProductData Objeto donde se consolida la información de producto sugerido.
69
+ * @throws Si la consulta del profile genera un error, o el userProfile no está correcto.
70
+ */
71
+ async function findUserProfileId(vtexApi, email, suggestedProductData) {
72
+ const searchResult = await vtexApi.fetch(`/checkout/pub/profiles?email=${encodeURIComponent(email)}`, {});
73
+ if (searchResult?.status == 200) {
74
+ const { userProfileId, isComplete } = searchResult.data;
75
+ if (!(userProfileId && isComplete)) {
76
+ throw new Error(`User with id ${email} is not valid`);
77
+ }
78
+ suggestedProductData.id = userProfileId;
79
+ }
80
+ }
81
+
82
+ module.exports = { consumer };
@@ -2,232 +2,276 @@ const AWSServices = require("../../../common/utils/aws-services");
2
2
  const ApiResponse = require("../../../common/utils/api-response");
3
3
  const Logger = require("../../../common/utils/logger");
4
4
  const AccountData = require("../../../entities/account");
5
+ const SkuData = require("../../../entities/sku");
5
6
  const VtexApi = require("../../../vtex/clients/VtexApi");
6
7
 
7
- const SQS_CLIENT_PRODUCT_QUEUE_URL = process.env.SQS_CLIENT_PRODUCT_QUEUE_URL;
8
- const DEFAULT_MIN_PRODUCTS_COUNT = process.env.MIN_PRODUCTS_COUNT || 5;
8
+ const {
9
+ SQS_CLIENT_PRODUCT_QUEUE_URL,
10
+ MIN_PRODUCTS_COUNT = 5
11
+ } = process.env;
9
12
 
10
- const validateBody = (event, minProductsCount = DEFAULT_MIN_PRODUCTS_COUNT) => {
11
- if (!event.body) {
12
- return { valid: false, error: ApiResponse.response(400, "Body is required") };
13
- }
14
-
15
- const body = JSON.parse(event.body);
16
- const { an, clients } = body;
17
-
18
- if (!an || typeof an !== 'string') {
19
- return { valid: false, error: ApiResponse.response(400, "Field 'an' is required and must be a string") };
20
- }
21
-
22
- if (!clients || !Array.isArray(clients) || clients.length === 0) {
23
- return { valid: false, error: ApiResponse.response(400, "Field 'clients' is required and must be a non-empty array") };
24
- }
13
+ const suggestedProductMdlz = async (event) => {
14
+ try {
15
+ const { an, clients } = JSON.parse(event.body);
16
+ // return ApiResponse.response(200, { an, clients });
25
17
 
26
- for (const client of clients) {
27
- if (!Array.isArray(client.productsRegular)) {
28
- return { valid: false, error: ApiResponse.response(400, "Field 'productsRegular' must be an array") };
18
+ const account = await AccountData.getAccountDataByAccountName(an);
19
+ if (!account) {
20
+ return ApiResponse.response(404, "Account not found");
29
21
  }
30
- if (!Array.isArray(client.productsIncremental)) {
31
- return { valid: false, error: ApiResponse.response(400, "Field 'productsIncremental' must be an array") };
22
+
23
+ // Se extraen las propiedades del account requeridas
24
+ const {
25
+ Credentials, ProductSuggestedConfig = {},
26
+ IndexClientRegister,
27
+ Startemail,
28
+ Domainemail
29
+ } = account;
30
+ if (!Credentials?.key || !Credentials?.token) {
31
+ return ApiResponse.response(400, "VTEX credentials not configured for account");
32
32
  }
33
- if (client.productsRegular.length < minProductsCount) {
34
- return { valid: false, error: ApiResponse.response(400, `Field 'productsRegular' must have at least ${minProductsCount} elements`) };
33
+ if (!IndexClientRegister?.length) {
34
+ return ApiResponse.response(400, "IndexClientRegister not configured for account");
35
35
  }
36
- if (client.productsIncremental.length < minProductsCount) {
37
- return { valid: false, error: ApiResponse.response(400, `Field 'productsIncremental' must have at least ${minProductsCount} elements`) };
36
+ // Se valida que exista el índice 'an'
37
+ if (!IndexClientRegister.includes('an')) {
38
+ return ApiResponse.response(400, "IndexClientRegister must have a 'an' property");
38
39
  }
39
- }
40
-
41
- return { valid: true, data: body };
42
- };
43
-
44
- const validateSkusInVtex = async (skus, vtexApi) => {
45
- if (!skus || skus.length === 0) {
46
- Logger.info("No SKUs to validate");
47
- return { validSkus: [], invalidSkus: [] };
48
- }
49
-
50
- try {
51
- const skuIds = skus.map(s => s.sku);
52
- Logger.info(`Requesting VTEX validation for SKUs: [${skuIds.join(', ')}]`);
53
40
 
54
- const vtexSkus = await vtexApi.getDetailSkuById(skuIds);
55
- Logger.info(`VTEX API returned ${Array.isArray(vtexSkus) ? vtexSkus.length : 'invalid'} results`);
41
+ // Se obtiene las propiedades de la configuración de ProductSuggestedConfig
42
+ const {
43
+ minProductsCount = MIN_PRODUCTS_COUNT,
44
+ entityName: suggestedProductEntityName = 'suggestedProducts'
45
+ } = ProductSuggestedConfig;
56
46
 
57
- const validSkus = [];
58
- const invalidSkus = [];
59
-
60
- if (!vtexSkus || !Array.isArray(vtexSkus)) {
61
- Logger.warn("VTEX API returned invalid response");
62
- return { validSkus: [], invalidSkus: skus };
47
+ // Se agrupan los ítems de cada una de las listas por el "sku", de modo que no se tengan items con duplicados.
48
+ const skusList = {};
49
+ for (const client of clients) {
50
+ removeDuplicatesSku(client.productsRegular, skusList);
51
+ removeDuplicatesSku(client.productsIncremental, skusList);
63
52
  }
64
53
 
65
- skus.forEach(sku => {
66
- const found = vtexSkus.find(v => String(sku?.sku) === String(v?.Id));
67
- if (found && found.IsActive !== false) {
68
- validSkus.push(sku);
69
- } else {
70
- invalidSkus.push(sku);
71
- }
72
- });
54
+ // Se consulta la información de cada uno de los SKU's
55
+ await getSkuData(skusList, account);
73
56
 
74
- Logger.info(`Validation completed: ${validSkus.length} valid, ${invalidSkus.length} invalid`);
75
- return { validSkus, invalidSkus };
76
- } catch (error) {
77
- return { validSkus: [], invalidSkus: skus };
78
- }
79
- };
80
-
81
- const processClient = async (client, vtexApi, accountName, account) => {
82
- try {
83
- const { pdv, productsRegular = [], productsIncremental = [] } = client;
84
-
85
- const suggestedConfig = account?.ProductSuggestedConfig
86
- const entityName = suggestedConfig?.entityName || 'suggestedProducts';
87
- const minProductsCount = suggestedConfig?.minProductsCount || DEFAULT_MIN_PRODUCTS_COUNT;
88
-
89
- const regularValidation = await validateSkusInVtex(productsRegular, vtexApi);
90
- const incrementalValidation = await validateSkusInVtex(productsIncremental, vtexApi);
91
-
92
- const hasMinimumValid = regularValidation.validSkus.length >= minProductsCount &&
93
- incrementalValidation.validSkus.length >= minProductsCount;
94
-
95
- if (!hasMinimumValid) {
96
- return {
97
- pdv,
98
- success: false,
99
- error: `Minimum ${minProductsCount} valid SKUs required`,
100
- regularValid: regularValidation.validSkus.length,
101
- incrementalValid: incrementalValidation.validSkus.length,
102
- originalData: client
103
- };
57
+ // Se valida la información de cada uno de los registros de "clients"
58
+ const validBody = validateClientsData(clients, minProductsCount, IndexClientRegister, an, skusList);
59
+ if (!validBody.success) {
60
+ return ApiResponse.response(207, validBody.data);
104
61
  }
105
62
 
106
- const dataSend = {
107
- an: accountName,
108
- parentAccount: account?.ParentAccountName,
109
- key: account?.Credentials?.key,
110
- token: account?.Credentials?.token,
111
- pdv,
112
- productsRegular: regularValidation.validSkus,
113
- productsIncremental: incrementalValidation.validSkus,
114
- invalidSkusRegular: regularValidation.invalidSkus,
115
- invalidSkusIncremental: incrementalValidation.invalidSkus,
116
- originalData: client,
117
- nameEntityProductSuggested: entityName
118
- };
119
-
120
- if (SQS_CLIENT_PRODUCT_QUEUE_URL) {
121
- try {
122
- await AWSServices.sendSQSMessage(SQS_CLIENT_PRODUCT_QUEUE_URL, dataSend);
123
- Logger.info(`Message sent to SQS for client ${pdv}`);
124
- } catch (sqsError) {
125
- Logger.error(`Failed to send SQS message for client ${pdv}`, {
126
- error: sqsError.message
63
+ do {
64
+ // Se extrae las primeras filas de la lista para ejecutar las Promises
65
+ let dataToProcess = clients.splice(0, 10);
66
+ await Promise.allSettled(dataToProcess.map(client => {
67
+ return new Promise((resolve, reject) => {
68
+ const sqsData = {
69
+ ...client,
70
+ an,
71
+ parentAccount: account?.ParentAccountName,
72
+ key: account?.Credentials?.key,
73
+ token: account?.Credentials?.token,
74
+ suggestedProductEntityName,
75
+ Startemail,
76
+ Domainemail
77
+ }
78
+ AWSServices.sendMessageToSqs(SQS_CLIENT_PRODUCT_QUEUE_URL, sqsData).then(resolve).catch(reject);
127
79
  });
128
- }
129
- } else {
130
- Logger.warn(`SQS URL not configured`);
131
- }
132
-
133
- return {
134
- pdv,
135
- success: true,
136
- validRegular: regularValidation.validSkus.length,
137
- validIncremental: incrementalValidation.validSkus.length,
138
- invalidRegular: regularValidation.invalidSkus.length,
139
- invalidIncremental: incrementalValidation.invalidSkus.length,
140
- warnings: regularValidation.invalidSkus.length > 0 || incrementalValidation.invalidSkus.length > 0
141
- ? "Some SKUs were excluded as they don't exist in VTEX" : null
142
- };
80
+ })).catch(Logger.error);
81
+ } while (clients.length);
143
82
 
83
+ return ApiResponse.response(200, { message: 'Message accepted!' });
144
84
  } catch (error) {
145
- Logger.error(`Critical error in processClient for PDV: ${client?.pdv}`, {
85
+ Logger.error("Critical error in suggestedProductMdlz", {
146
86
  error: error.message,
147
- stack: error.stack,
148
- pdv: client?.pdv
87
+ stack: error.stack
149
88
  });
150
- throw error;
89
+ return ApiResponse.response(500, "Internal server error");
151
90
  }
152
91
  };
153
92
 
154
- const suggestedProductMdlz = async (event) => {
155
- try {
156
- const { an, clients } = JSON.parse(event.body);
93
+ /**
94
+ * Valida la información de la lista de clientes
95
+ * @param {Object[]} clients Lista de clientes
96
+ * @param {Number} minProductsCount Cantidad mínima requerida para el producto sugerido.
97
+ * @param {String[]} indexClientRegister Lista de índices para el Id del cliente.
98
+ * @param {Object} skusList Objeto donde se consolida la lista de SKU´s.
99
+ * @returns
100
+ */
101
+ function validateClientsData(clients, minProductsCount, indexClientRegister, an, skusList) {
102
+ const response = { success: true }, notProcessedItems = [];
157
103
 
158
- const account = await AccountData.getAccountDataByAccountName(an);
159
- if (!account) {
160
- return ApiResponse.response(404, "Account not found");
104
+ for (const client of clients) {
105
+ let remain = [], clientId = '';
106
+ for (let prop of indexClientRegister) {
107
+ if (prop == 'an') {
108
+ clientId += an;
109
+ } else {
110
+ if (client.hasOwnProperty(prop)) {
111
+ clientId += client[prop] ?? '';
112
+ } else {
113
+ remain.push(prop);
114
+ }
115
+ }
161
116
  }
162
-
163
- if (!account?.Credentials?.key || !account?.Credentials?.token) {
164
- return ApiResponse.response(400, "VTEX credentials not configured for account");
117
+ if (remain.length) {
118
+ client.error = `The properties ${remain.join(',')} are required`;
119
+ notProcessedItems.push(client);
120
+ continue;
165
121
  }
166
122
 
167
- const suggestedConfig = account?.ProductSuggestedConfig;
168
- const minProductsCount = suggestedConfig?.minProductsCount || DEFAULT_MIN_PRODUCTS_COUNT;
123
+ // Se valida si las propiedades existen en cada cliente
124
+ if (!client?.productsRegular || !client?.productsIncremental) {
125
+ client.error = `Validate the following properties productsRegular and productsIncremental are required`;
126
+ notProcessedItems.push(client);
127
+ continue;
128
+ }
169
129
 
170
- const validation = validateBody(event, minProductsCount);
171
- if (!validation.valid) {
172
- return validation.error;
130
+ // Se valida si la longitud de alguno de los ítems del cliente es menos al número mínimo de productos
131
+ if (client.productsRegular?.length < minProductsCount || client.productsIncremental?.length < minProductsCount) {
132
+ client.error = `Validate the following properties productsRegular and productsIncremental minimum ${minProductsCount} elements`;
133
+ notProcessedItems.push(client);
134
+ continue;
173
135
  }
174
136
 
175
- const vtexApi = new VtexApi(
176
- account.AccountName,
177
- account.Credentials.key,
178
- account.Credentials.token
179
- );
137
+ client.clientId = clientId;
138
+ setItemInformation(client.productsRegular, 'REGULAR', skusList);
139
+ setItemInformation(client.productsIncremental, 'INCREMENTAL', skusList);
140
+ }
180
141
 
181
- const results = [];
182
- const failedClients = [];
142
+ // Si hay ítems no procesados, se retorna el mensaje de error
143
+ if (notProcessedItems.length) {
144
+ response.success = false;
145
+ response.data = {
146
+ message: 'Not all items were processed.',
147
+ notProcessedItems
148
+ };
149
+ }
183
150
 
184
- for (const client of clients) {
185
- try {
186
- const result = await processClient(client, vtexApi, an, account);
187
- if (result.success) {
188
- results.push(result);
189
- } else {
190
- failedClients.push(result);
191
- }
192
- } catch (error) {
193
- Logger.error("Error processing client", {
194
- pdv: client.pdv,
195
- error: error.message,
196
- stack: error.stack
197
- });
198
- failedClients.push({
199
- pdv: client.pdv,
200
- success: false,
201
- error: "Internal processing error",
202
- originalData: client
203
- });
151
+ return response;
152
+ }
153
+
154
+ /**
155
+ * Consulta la información de los SKU definidos en la petición.
156
+ * @param {*} skusList Lista de SKU's.
157
+ * @param {*} account Información del account sobre el cual se realiza la consulta.
158
+ */
159
+ async function getSkuData(skusList, account) {
160
+ let skuRefUsed = account?.SkuRefUsed;
161
+ if (typeof skuRefUsed !== "boolean") {
162
+ skuRefUsed = true;
163
+ }
164
+
165
+ // Instancia para consumo de la API de VTEX
166
+ const vtexApi = new VtexApi(
167
+ account.AccountName,
168
+ account.Credentials.key,
169
+ account.Credentials.token
170
+ );
171
+
172
+ const items = Object.keys(skusList);
173
+ do {
174
+ // Se extrae las primeras filas de la lista para ejecutar las Promises
175
+ let rowsData = items.splice(0, 10);
176
+ await Promise.allSettled(rowsData.map(sku => {
177
+ return new Promise((resolve, reject) => {
178
+ // Se consulta el SKU en MonalisaV2
179
+ getSkuInformation(sku, account, skuRefUsed).then(skuId => {
180
+ // Se consulta en VTEX información del producto
181
+ skusList[sku].SkuId = skuId;
182
+ vtexApi.getDetailSkuById([skuId]).then(res => {
183
+ const { IsActive, ProductIsVisible } = res[0];
184
+ skusList[sku].IsActive = IsActive;
185
+ skusList[sku].ProductIsVisible = ProductIsVisible;
186
+ resolve(sku);
187
+ }).catch(reject);
188
+ }).catch(reject);
189
+ });
190
+ })).catch(Logger.error);
191
+ } while (items.length);
192
+ }
193
+
194
+ /**
195
+ * Consulta de información del sku en MonalisaV2.
196
+ * @param {String} sku SKU del producto.
197
+ * @param {Object} account Información del account en MonalisaV2.
198
+ * @param {Boolean} skuRefUsed
199
+ * @returns
200
+ */
201
+ async function getSkuInformation(sku, account, skuRefUsed) {
202
+ return new Promise((resolve, reject) => {
203
+ if (account?.ValidateSkuPriceInventoryInProcess === true) {
204
+ resolve(sku);
205
+ } else {
206
+ if (skuRefUsed) {
207
+ SkuData.getSkuByParentAccountNameAndSku(account?.ParentAccountName, sku).then(res => {
208
+ if (res?.SkuId) {
209
+ const { SkuId } = res;
210
+ resolve(SkuId);
211
+ } else {
212
+ reject(new Error(`SKU ${sku} not found`));
213
+ }
214
+ }).catch(reject);
215
+ } else {
216
+ SkuData.getSkuByParentAccountNameAndEan(account?.ParentAccountName, sku).then(res => {
217
+ if (res?.[0]) {
218
+ const { SkuId } = res[0];
219
+ resolve(SkuId);
220
+ } else {
221
+ reject(new Error(`SKU ${sku} not found`));
222
+ }
223
+ }).catch(reject);
204
224
  }
205
225
  }
206
-
207
- const response = failedClients.length > 0
208
- ? {
209
- message: "Not all clients were processed successfully",
210
- processedClients: results.length,
211
- failedClients
226
+ })
227
+ }
228
+
229
+ /**
230
+ * Recorre la lista de productos para eliminar registros con "sku" duplicado.
231
+ * @param {Object[]} items Lista de ítems
232
+ * @param {Object} skusList Objeto donde se consolida la lista de SKU´s.
233
+ */
234
+ function removeDuplicatesSku(items, skusList) {
235
+ const indexes = {};
236
+ // Se recorre la lista en orden invertido, para que en caso de encontrar registros con "sku" duplicado se eliminen y quede solamente el elemento de la última posición.
237
+ if (items?.length) {
238
+ for (let i = items.length - 1; i >= 0; i--) {
239
+ const { sku } = items[i];
240
+ !skusList.hasOwnProperty(sku) && (skusList[sku] = {});
241
+ if (indexes.hasOwnProperty(sku)) {
242
+ items.splice(i, 1);
243
+ } else {
244
+ indexes[sku] = true;
212
245
  }
213
- : {
214
- message: "All clients processed successfully",
215
- processedClients: results.length,
216
- results
217
- };
218
-
219
- const statusCode = failedClients.length > 0 ? 207 : 200;
220
- Logger.info(`Process completed with status ${statusCode}, processed: ${results.length}, failed: ${failedClients.length}`);
221
-
222
- return ApiResponse.response(statusCode, response);
223
-
224
- } catch (error) {
225
- Logger.error("Critical error in suggestedProductMdlz", {
226
- error: error.message,
227
- stack: error.stack
228
- });
229
- return ApiResponse.response(500, "Internal server error");
246
+ }
230
247
  }
231
- };
248
+ }
249
+
250
+ /**
251
+ * Organiza la información de los SKU en cada una de las listas de productos del cliente.
252
+ * @param {Object[]} list Lista de ítems de producto sugerido.
253
+ * @param {Object} skusList Objeto donde se consolida la información de los SKU.
254
+ * @param {Object} skusList Objeto donde se consolida la información de los SKU que no fueron encontrados.
255
+ */
256
+ function setItemInformation(list, productType, skusList) {
257
+ for (let item of list) {
258
+ item.type = productType;
259
+ const { sku } = item;
260
+ // Se elimina la propiedad "sku", para luego insertar este valor en la entidad de productos sugeridos
261
+ delete item.sku;
262
+ if (skusList?.[sku]) {
263
+ const { SkuId, IsActive, ProductIsVisible } = skusList[sku];
264
+ item.refId = sku;
265
+ item.skuId = SkuId;
266
+ if (IsActive) {
267
+ item.status = ProductIsVisible ? 'active' : 'not_visible';
268
+ } else {
269
+ item.status = 'inactive';
270
+ }
271
+ } else {
272
+ item.status = 'invalid';
273
+ }
274
+ }
275
+ }
232
276
 
233
277
  module.exports = suggestedProductMdlz;