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.
- package/README.md +130 -0
- package/index.js +350 -0
- package/package.json +52 -0
- package/src/auth/handler.js +3 -0
- package/src/common/MondelezCastOrder.js +449 -0
- package/src/common/utils/AuthSecurity.js +46 -0
- package/src/common/utils/account-error-handler.js +279 -0
- package/src/common/utils/account-error-helper.js +231 -0
- package/src/common/utils/account-properties-handler.js +355 -0
- package/src/common/utils/api-response.js +62 -0
- package/src/common/utils/aws-services.js +186 -0
- package/src/common/utils/constants/account-error-codes.json +801 -0
- package/src/common/utils/constants.js +37 -0
- package/src/common/utils/convert/MondelezClientsItemsCast.js +52 -0
- package/src/common/utils/convert/MondelezInventoryItemsCast.js +15 -0
- package/src/common/utils/convert/MondelezOrderStatusCast.js +34 -0
- package/src/common/utils/convert/MondelezPricesItemsCast.js +37 -0
- package/src/common/utils/cron-ftp-get.js +143 -0
- package/src/common/utils/data-tables-helper.js +213 -0
- package/src/common/utils/date-range-calculator.js +113 -0
- package/src/common/utils/delay.js +17 -0
- package/src/common/utils/ftp-sftp.js +320 -0
- package/src/common/utils/logger.js +126 -0
- package/src/common/utils/nodemailerLib.js +61 -0
- package/src/common/utils/product-unit-converter.js +168 -0
- package/src/common/utils/schemas-utils.js +101 -0
- package/src/common/utils/seller-email-sharing-service.js +441 -0
- package/src/common/utils/sftp-utils.js +202 -0
- package/src/common/utils/status.js +15 -0
- package/src/common/utils/util.js +236 -0
- package/src/common/utils/validate-state-order.js +35 -0
- package/src/common/utils/validateProviders.js +67 -0
- package/src/common/utils/validation-data.js +45 -0
- package/src/common/utils/vtex/save-hooks.js +65 -0
- package/src/common/utils/vtex/save-schemas.js +65 -0
- package/src/common/utils/vtex-hook-handler.js +71 -0
- package/src/common/validation/AccountCoordinatesValidation.js +350 -0
- package/src/common/validation/GeneralErrorValidation.js +11 -0
- package/src/common/validation/MainErrorValidation.js +8 -0
- package/src/entities/account.js +639 -0
- package/src/entities/clients.js +104 -0
- package/src/entities/controlprice.js +196 -0
- package/src/entities/controlstock.js +206 -0
- package/src/entities/cron.js +77 -0
- package/src/entities/cronjob.js +71 -0
- package/src/entities/orders.js +195 -0
- package/src/entities/sftp-inbound.js +88 -0
- package/src/entities/sku.js +220 -0
- package/src/entities/taxpromotion.js +249 -0
- package/src/functions/account/account-get.js +262 -0
- package/src/functions/account/account-handler.js +299 -0
- package/src/functions/account/clients.js +10 -0
- package/src/functions/account/index.js +208 -0
- package/src/functions/actions/save-promotions-order-history.js +324 -0
- package/src/functions/affiliates/affiliates-hook-consumer.js +87 -0
- package/src/functions/affiliates/affiliates-hook-producer.js +45 -0
- package/src/functions/clients/clients-audience.js +62 -0
- package/src/functions/clients/clients-consumer.js +648 -0
- package/src/functions/clients/clients-producer.js +362 -0
- package/src/functions/clients/clients-suggested-product-consumer.js +166 -0
- package/src/functions/clients/helpers/suggested-product-mdlz.js +233 -0
- package/src/functions/clients_peru/email.html +129 -0
- package/src/functions/clients_peru/splitfile.js +357 -0
- package/src/functions/clients_peru/updateClients.js +1334 -0
- package/src/functions/clients_peru/utils.js +243 -0
- package/src/functions/cronjobs/cron-jobs-manager.js +40 -0
- package/src/functions/cronjobs/cron-jobs.js +171 -0
- package/src/functions/crons/cron.js +39 -0
- package/src/functions/distributors/distributor-handler.js +81 -0
- package/src/functions/distributors/distributor.js +535 -0
- package/src/functions/distributors/index.js +60 -0
- package/src/functions/financialpolicy/assign-financialpolicy.js +111 -0
- package/src/functions/financialpolicy/get-financialpolicy.js +91 -0
- package/src/functions/financialpolicy/index.js +28 -0
- package/src/functions/inventory/catalog-sync-consumer.js +17 -0
- package/src/functions/inventory/catalog-sync-handler.js +311 -0
- package/src/functions/inventory/inventory-consumer.js +119 -0
- package/src/functions/inventory/inventory-producer.js +197 -0
- package/src/functions/multiPresentation/multipre-queue.js +155 -0
- package/src/functions/multiPresentation/multipres.js +459 -0
- package/src/functions/nodeflow/index.js +83 -0
- package/src/functions/nodeflow/nodeflow-cron.js +200 -0
- package/src/functions/nodeflow/nodeflow-pub.js +203 -0
- package/src/functions/nodeflow/nodeflow-pvt.js +266 -0
- package/src/functions/notifications/download-leads-handler.js +67 -0
- package/src/functions/notifications/new-leads-notification-consumer.js +17 -0
- package/src/functions/notifications/new-leads-notification-handler.js +359 -0
- package/src/functions/notifications/order-status-notification-handler.js +482 -0
- package/src/functions/notifications/promotion-notification-handler.js +193 -0
- package/src/functions/orders/index.js +32 -0
- package/src/functions/orders/orders-cancel-handler.js +74 -0
- package/src/functions/orders/orders-handler.js +280 -0
- package/src/functions/orders/orders-hook-consumer.js +137 -0
- package/src/functions/orders/orders-hook-producer.js +170 -0
- package/src/functions/orders/orders-notifications-handler.js +137 -0
- package/src/functions/orders/orders-status-consumer.js +461 -0
- package/src/functions/orders/orders-status-producer.js +443 -0
- package/src/functions/prices/index.js +75 -0
- package/src/functions/prices/prices-consumer.js +236 -0
- package/src/functions/prices/prices-producer.js +323 -0
- package/src/functions/prices/promotion-and-tax.js +1284 -0
- package/src/functions/routesflow/assign-routeflow-queue.js +77 -0
- package/src/functions/schemas/vtex/handle-schemas.js +102 -0
- package/src/functions/security/process_gas.js +221 -0
- package/src/functions/security/security-handler.js +950 -0
- package/src/functions/sftp/sftp-consumer.js +453 -0
- package/src/functions/sftpIntegrations/processes/redirectServices.js +184 -0
- package/src/functions/sftpIntegrations/processes/validateFileSchema.js +226 -0
- package/src/functions/sftpIntegrations/schemas/credential-schema.js +123 -0
- package/src/functions/sftpIntegrations/schemas/record-schema.js +131 -0
- package/src/functions/sftpIntegrations/schemas/sftp_required_fields.json +3 -0
- package/src/functions/sftpIntegrations/sftp-config-producer.js +112 -0
- package/src/functions/sftpIntegrations/sftp-consumer.js +700 -0
- package/src/functions/sftpIntegrations/test/validateFile.test.js +122 -0
- package/src/functions/sftpIntegrations/utils/connect-dynamo.js +29 -0
- package/src/functions/sftpIntegrations/utils/split-data.js +25 -0
- package/src/functions/utils/index.js +130 -0
- package/src/functions/vtex/vtex-helpers.js +694 -0
- package/src/integrations/accountErrors/AccountErrorManager.js +437 -0
- package/src/integrations/audience/Audience.js +70 -0
- package/src/integrations/financialPolicy/FinancialPolicyApi.js +377 -0
- package/src/integrations/index.js +0 -0
- package/src/integrations/mobilvendor/MobilvendorApi.js +405 -0
- package/src/integrations/productmultipresentation/ProductMultiPresentation.js +200 -0
- package/src/mdlz/auth/SecretManagerApi.js +77 -0
- package/src/mdlz/client/MdlzApi.js +70 -0
- package/src/vtex/clients/ProvidersApi.js +51 -0
- package/src/vtex/clients/VtexApi.js +511 -0
- package/src/vtex/models/VtexOrder.js +87 -0
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
const DynamoAWS = require("aws-sdk/clients/dynamodb");
|
|
2
|
+
const Validation = require("../common/utils/validation-data");
|
|
3
|
+
const Logger = require("../common/utils/logger");
|
|
4
|
+
|
|
5
|
+
const ACCOUNT_DATA_CONFIG_TABLE = process.env.ACCOUNT_DATA_CONFIG_TABLE;
|
|
6
|
+
const MAX_LIMIT = process.env.MAX_LIMIT || 150;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Procesa respuesta de DynamoDB aplicando filtros adicionales y transformaciones
|
|
10
|
+
* @param {Array} items - Elementos obtenidos de DynamoDB
|
|
11
|
+
* @param {Object} queryParams - Parámetros de consulta
|
|
12
|
+
* @returns {Array} - Elementos filtrados y procesados
|
|
13
|
+
*/
|
|
14
|
+
const processItems = (items, queryParams) => {
|
|
15
|
+
if (!items || !items.length) return [];
|
|
16
|
+
|
|
17
|
+
let processedItems = [...items];
|
|
18
|
+
|
|
19
|
+
// Aplicar filtro _moduleActive
|
|
20
|
+
if (queryParams._moduleActive) {
|
|
21
|
+
const module = queryParams._moduleActive;
|
|
22
|
+
processedItems = processedItems.filter(item =>
|
|
23
|
+
item[module] &&
|
|
24
|
+
((typeof item[module] === 'object' && item[module].isActive === true) ||
|
|
25
|
+
(typeof item[module] === 'boolean' && item[module] === true))
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Aplicar filtro _accountPattern
|
|
30
|
+
if (queryParams._accountPattern) {
|
|
31
|
+
const pattern = queryParams._accountPattern.replace(/\*/g, '.*');
|
|
32
|
+
const regex = new RegExp(`^${pattern}$`, 'i');
|
|
33
|
+
processedItems = processedItems.filter(item => regex.test(item.AccountName));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Aplicar filtro _integration
|
|
37
|
+
if (queryParams._integration) {
|
|
38
|
+
const integrationType = queryParams._integration.toLowerCase();
|
|
39
|
+
|
|
40
|
+
processedItems = processedItems.filter(item => {
|
|
41
|
+
switch (integrationType) {
|
|
42
|
+
case 'sftp':
|
|
43
|
+
return item.SftpUsed === true ||
|
|
44
|
+
(item.SftpIntegration && item.SftpIntegration.isActive === true);
|
|
45
|
+
case 'api':
|
|
46
|
+
return item.Credentials && item.Credentials.key && item.Credentials.token;
|
|
47
|
+
case 'webhook':
|
|
48
|
+
return item.HookOrderVtexMDv2 && item.HookOrderVtexMDv2.trim() !== '';
|
|
49
|
+
default:
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Aplicar filtro _like
|
|
56
|
+
if (queryParams._like) {
|
|
57
|
+
const searchTerm = queryParams._like.toLowerCase();
|
|
58
|
+
|
|
59
|
+
processedItems = processedItems.filter(item => {
|
|
60
|
+
// Buscar en todas las propiedades de primer nivel
|
|
61
|
+
return Object.entries(item).some(([key, value]) => {
|
|
62
|
+
if (typeof value === 'string') {
|
|
63
|
+
return value.toLowerCase().includes(searchTerm);
|
|
64
|
+
} else if (typeof value === 'number') {
|
|
65
|
+
return value.toString().includes(searchTerm);
|
|
66
|
+
} else if (Array.isArray(value) && value.length > 0 && typeof value[0] === 'string') {
|
|
67
|
+
return value.some(val => val.toLowerCase().includes(searchTerm));
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Proyectar campos si se especifican en _fields
|
|
75
|
+
if (queryParams._fields) {
|
|
76
|
+
const fields = queryParams._fields.split(',').map(f => f.trim());
|
|
77
|
+
|
|
78
|
+
processedItems = processedItems.map(item => {
|
|
79
|
+
const projectedItem = {};
|
|
80
|
+
fields.forEach(field => {
|
|
81
|
+
// Soporte para campos anidados con notación de punto
|
|
82
|
+
if (field.includes('.')) {
|
|
83
|
+
const parts = field.split('.');
|
|
84
|
+
let current = item;
|
|
85
|
+
let valid = true;
|
|
86
|
+
|
|
87
|
+
// Navegar por el objeto hasta el campo anidado
|
|
88
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
89
|
+
if (current && current[parts[i]]) {
|
|
90
|
+
current = current[parts[i]];
|
|
91
|
+
} else {
|
|
92
|
+
valid = false;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Si el camino es válido, extraer el valor final
|
|
98
|
+
const lastPart = parts[parts.length - 1];
|
|
99
|
+
if (valid && current && current[lastPart] !== undefined) {
|
|
100
|
+
// Crear estructura anidada en el objeto proyectado
|
|
101
|
+
let target = projectedItem;
|
|
102
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
103
|
+
if (!target[parts[i]]) {
|
|
104
|
+
target[parts[i]] = {};
|
|
105
|
+
}
|
|
106
|
+
target = target[parts[i]];
|
|
107
|
+
}
|
|
108
|
+
target[lastPart] = current[lastPart];
|
|
109
|
+
}
|
|
110
|
+
} else if (item[field] !== undefined) {
|
|
111
|
+
projectedItem[field] = item[field];
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return projectedItem;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Excluir campos si se especifican en _excludeFields
|
|
120
|
+
if (queryParams._excludeFields) {
|
|
121
|
+
const excludeFields = queryParams._excludeFields.split(',').map(f => f.trim());
|
|
122
|
+
|
|
123
|
+
processedItems = processedItems.map(item => {
|
|
124
|
+
const filteredItem = { ...item };
|
|
125
|
+
|
|
126
|
+
excludeFields.forEach(field => {
|
|
127
|
+
// Soporte para campos anidados con notación de punto
|
|
128
|
+
if (field.includes('.')) {
|
|
129
|
+
const parts = field.split('.');
|
|
130
|
+
let current = filteredItem;
|
|
131
|
+
|
|
132
|
+
// Navegar hasta el penúltimo nivel
|
|
133
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
134
|
+
if (!current[parts[i]]) {
|
|
135
|
+
return; // Campo no existe, nada que eliminar
|
|
136
|
+
}
|
|
137
|
+
current = current[parts[i]];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Eliminar propiedad del último nivel
|
|
141
|
+
const lastPart = parts[parts.length - 1];
|
|
142
|
+
if (current[lastPart] !== undefined) {
|
|
143
|
+
delete current[lastPart];
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
delete filteredItem[field];
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
return filteredItem;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return processedItems;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Obtiene cuentas filtradas por ParentAccountName y parámetros avanzados de consulta
|
|
159
|
+
* @param {string} parentAccountName - Nombre de la cuenta padre (opcional)
|
|
160
|
+
* @param {Object} queryParams - Parámetros adicionales de consulta (opcional)
|
|
161
|
+
* @returns {Promise<{items: Array, lastEvaluatedKey: Object|null, count: number}>} - Resultados paginados
|
|
162
|
+
*/
|
|
163
|
+
const getAccountsByParentName = async (parentAccountName, queryParams = {}) => {
|
|
164
|
+
try {
|
|
165
|
+
const dynamodb = new DynamoAWS.DocumentClient();
|
|
166
|
+
|
|
167
|
+
// Configuración de parámetros básicos
|
|
168
|
+
const limit = Math.min(parseInt(queryParams._limit) || MAX_LIMIT, MAX_LIMIT);
|
|
169
|
+
const sortAscending = queryParams._sort?.toLowerCase() !== 'desc';
|
|
170
|
+
const exclusiveStartKey = queryParams._from ? JSON.parse(Buffer.from(queryParams._from, 'base64').toString()) : null;
|
|
171
|
+
|
|
172
|
+
// Parámetros base para DynamoDB
|
|
173
|
+
let params = {
|
|
174
|
+
TableName: ACCOUNT_DATA_CONFIG_TABLE,
|
|
175
|
+
Limit: limit,
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Si hay un ExclusiveStartKey (para paginación)
|
|
179
|
+
if (exclusiveStartKey) {
|
|
180
|
+
params.ExclusiveStartKey = exclusiveStartKey;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Si se proporciona una cuenta padre, usar query con el índice adecuado
|
|
184
|
+
if (parentAccountName) {
|
|
185
|
+
// Usar el índice ParentAccountNameIndex
|
|
186
|
+
params.IndexName = "ParentAccountNameIndex";
|
|
187
|
+
params.KeyConditionExpression = "ParentAccountName = :parentName";
|
|
188
|
+
params.ExpressionAttributeValues = {
|
|
189
|
+
":parentName": parentAccountName
|
|
190
|
+
};
|
|
191
|
+
params.ScanIndexForward = sortAscending; // Control del orden
|
|
192
|
+
|
|
193
|
+
// Ejecutar la consulta a DynamoDB
|
|
194
|
+
const response = await dynamodb.query(params).promise();
|
|
195
|
+
|
|
196
|
+
// Procesar los resultados con los filtros adicionales
|
|
197
|
+
const processedItems = processItems(response.Items || [], queryParams);
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
items: processedItems,
|
|
201
|
+
lastEvaluatedKey: response.LastEvaluatedKey ?
|
|
202
|
+
Buffer.from(JSON.stringify(response.LastEvaluatedKey)).toString('base64') :
|
|
203
|
+
null,
|
|
204
|
+
count: processedItems.length
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
// Si no se proporciona cuenta padre, usar scan
|
|
208
|
+
else {
|
|
209
|
+
// Ejecutar scan en DynamoDB
|
|
210
|
+
const response = await dynamodb.scan(params).promise();
|
|
211
|
+
|
|
212
|
+
// Procesar los resultados con los filtros adicionales
|
|
213
|
+
let processedItems = processItems(response.Items || [], queryParams);
|
|
214
|
+
|
|
215
|
+
// Ordenar resultados si se solicita
|
|
216
|
+
if (queryParams._sort) {
|
|
217
|
+
processedItems.sort((a, b) => {
|
|
218
|
+
if (sortAscending) {
|
|
219
|
+
return a.AccountName > b.AccountName ? 1 : -1;
|
|
220
|
+
} else {
|
|
221
|
+
return a.AccountName < b.AccountName ? 1 : -1;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
items: processedItems,
|
|
228
|
+
lastEvaluatedKey: response.LastEvaluatedKey ?
|
|
229
|
+
Buffer.from(JSON.stringify(response.LastEvaluatedKey)).toString('base64') :
|
|
230
|
+
null,
|
|
231
|
+
count: processedItems.length
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
} catch (err) {
|
|
235
|
+
Logger.error("Error getting accounts data: ", err);
|
|
236
|
+
return { items: [], lastEvaluatedKey: null, count: 0 };
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Obtiene todas las cuentas con soporte para paginación y filtros avanzados
|
|
242
|
+
* @param {Object} queryParams - Parámetros de consulta
|
|
243
|
+
* @returns {Promise<{items: Array, lastEvaluatedKey: Object|null, count: number}>} - Resultados paginados
|
|
244
|
+
*/
|
|
245
|
+
const getAccountDataAll = async (queryParams = {}) => {
|
|
246
|
+
return getAccountsByParentName(null, queryParams);
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Obtiene una cuenta específica por su AccountName con soporte para proyección de campos
|
|
251
|
+
* @param {string} accountName - Nombre de la cuenta a buscar
|
|
252
|
+
* @param {Object} queryParams - Parámetros de consulta para proyección
|
|
253
|
+
* @returns {Promise<Object|null>} - Cuenta encontrada o null
|
|
254
|
+
*/
|
|
255
|
+
const getAccountDataByAccountName = async (accountName, queryParams = {}) => {
|
|
256
|
+
try {
|
|
257
|
+
const dynamodb = new DynamoAWS.DocumentClient();
|
|
258
|
+
const params = {
|
|
259
|
+
TableName: ACCOUNT_DATA_CONFIG_TABLE,
|
|
260
|
+
IndexName: "AccountNameIndex",
|
|
261
|
+
KeyConditionExpression: "AccountName = :accountName",
|
|
262
|
+
ExpressionAttributeValues: {
|
|
263
|
+
":accountName": accountName,
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
const response = await dynamodb.query(params).promise();
|
|
267
|
+
|
|
268
|
+
if (!response?.Items || response.Items.length === 0) {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Aplicar proyección a un solo elemento
|
|
273
|
+
const items = processItems([response.Items[0]], queryParams);
|
|
274
|
+
return items[0] || null;
|
|
275
|
+
} catch (err) {
|
|
276
|
+
Logger.error("Error getting account data: ", err);
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
// El resto de funciones permanece igual
|
|
282
|
+
const deleteAccountByAccountName = async (accountName) => {
|
|
283
|
+
try {
|
|
284
|
+
const account = await getAccountDataByAccountName(accountName);
|
|
285
|
+
if (!account) {
|
|
286
|
+
Logger.error(`Account ${accountName} not found for deletion`);
|
|
287
|
+
return { success: false, message: `Account ${accountName} not found` };
|
|
288
|
+
}
|
|
289
|
+
const dynamodb = new DynamoAWS.DocumentClient();
|
|
290
|
+
const params = {
|
|
291
|
+
TableName: ACCOUNT_DATA_CONFIG_TABLE,
|
|
292
|
+
Key: {
|
|
293
|
+
AccountName: accountName,
|
|
294
|
+
ParentAccountName: account.ParentAccountName
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
await dynamodb.delete(params).promise();
|
|
298
|
+
return {
|
|
299
|
+
success: true,
|
|
300
|
+
message: `Account ${accountName} deleted successfully`
|
|
301
|
+
};
|
|
302
|
+
} catch (err) {
|
|
303
|
+
Logger.error(`Error deleting account ${accountName}:`, err);
|
|
304
|
+
return {
|
|
305
|
+
success: false,
|
|
306
|
+
message: `Error deleting account: ${err.message}`
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
const addAccountDataConfig = async (accountData) => {
|
|
312
|
+
const dynamodb = new DynamoAWS.DocumentClient();
|
|
313
|
+
let data = Validation.transformFirstKeysToUpperCaseValue(accountData);
|
|
314
|
+
try {
|
|
315
|
+
const params = {
|
|
316
|
+
TableName: ACCOUNT_DATA_CONFIG_TABLE,
|
|
317
|
+
Item: data,
|
|
318
|
+
ConditionExpression: "attribute_not_exists(AccountName)",
|
|
319
|
+
};
|
|
320
|
+
await dynamodb.put(params).promise();
|
|
321
|
+
return accountData;
|
|
322
|
+
} catch (err) {
|
|
323
|
+
Logger.error("Error saving account data config: ", err);
|
|
324
|
+
if (err.code === "ConditionalCheckFailedException") {
|
|
325
|
+
try {
|
|
326
|
+
let updateExpression = 'set';
|
|
327
|
+
let ExpressionAttributeNames = {};
|
|
328
|
+
let ExpressionAttributeValues = {};
|
|
329
|
+
for (const property in data) {
|
|
330
|
+
if (property != 'AccountName' && property != 'ParentAccountName') {
|
|
331
|
+
updateExpression += ` #${property} = :${property} ,`;
|
|
332
|
+
ExpressionAttributeNames['#' + property] = property;
|
|
333
|
+
ExpressionAttributeValues[':' + property] = data[property];
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
updateExpression = updateExpression.slice(0, -1);
|
|
337
|
+
const params2 = {
|
|
338
|
+
TableName: ACCOUNT_DATA_CONFIG_TABLE,
|
|
339
|
+
Key: {
|
|
340
|
+
AccountName: data.AccountName,
|
|
341
|
+
ParentAccountName: data.ParentAccountName
|
|
342
|
+
},
|
|
343
|
+
UpdateExpression: updateExpression,
|
|
344
|
+
ExpressionAttributeNames: ExpressionAttributeNames,
|
|
345
|
+
ExpressionAttributeValues: ExpressionAttributeValues
|
|
346
|
+
};
|
|
347
|
+
let res2 = await dynamodb.update(params2).promise();
|
|
348
|
+
return accountData;
|
|
349
|
+
} catch (err2) {
|
|
350
|
+
Logger.error("Error updating account data config: ", err2);
|
|
351
|
+
if (err2.code === "ConditionalCheckFailedException") {
|
|
352
|
+
return accountData;
|
|
353
|
+
}
|
|
354
|
+
return null
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Función de paginación completa para DataTables
|
|
363
|
+
*/
|
|
364
|
+
const getAccountsWithDataTablesPagination = async (dataTablesParams) => {
|
|
365
|
+
try {
|
|
366
|
+
const dynamodb = new DynamoAWS.DocumentClient();
|
|
367
|
+
|
|
368
|
+
const totalCountParams = {
|
|
369
|
+
TableName: ACCOUNT_DATA_CONFIG_TABLE,
|
|
370
|
+
Select: 'COUNT'
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
const totalCountResponse = await dynamodb.scan(totalCountParams).promise();
|
|
374
|
+
const recordsTotal = totalCountResponse.Count;
|
|
375
|
+
|
|
376
|
+
const allFilteredItems = await getAllFilteredAccounts(dataTablesParams);
|
|
377
|
+
const sortedItems = applySortingToAccounts(allFilteredItems, dataTablesParams.orderField, dataTablesParams.orderDir);
|
|
378
|
+
|
|
379
|
+
const start = dataTablesParams.start;
|
|
380
|
+
const length = dataTablesParams.length;
|
|
381
|
+
const paginatedItems = sortedItems.slice(start, start + length);
|
|
382
|
+
|
|
383
|
+
return {
|
|
384
|
+
data: paginatedItems,
|
|
385
|
+
recordsTotal: recordsTotal,
|
|
386
|
+
recordsFiltered: sortedItems.length,
|
|
387
|
+
draw: dataTablesParams.draw
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
} catch (err) {
|
|
391
|
+
Logger.error("Error in getAccountsWithDataTablesPagination: ", err);
|
|
392
|
+
return {
|
|
393
|
+
data: [],
|
|
394
|
+
recordsTotal: 0,
|
|
395
|
+
recordsFiltered: 0,
|
|
396
|
+
draw: dataTablesParams.draw
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Obtiene TODOS los registros filtrados usando paginación completa de DynamoDB
|
|
403
|
+
*/
|
|
404
|
+
const getAllFilteredAccounts = async (dataTablesParams) => {
|
|
405
|
+
const dynamodb = new DynamoAWS.DocumentClient();
|
|
406
|
+
let allItems = [];
|
|
407
|
+
let lastEvaluatedKey = null;
|
|
408
|
+
const BATCH_SIZE = 100;
|
|
409
|
+
|
|
410
|
+
do {
|
|
411
|
+
const params = {
|
|
412
|
+
TableName: ACCOUNT_DATA_CONFIG_TABLE,
|
|
413
|
+
Limit: BATCH_SIZE,
|
|
414
|
+
ExclusiveStartKey: lastEvaluatedKey
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const response = await dynamodb.scan(params).promise();
|
|
418
|
+
const filteredBatch = applyFiltersToAccounts(response.Items || [], dataTablesParams);
|
|
419
|
+
allItems = [...allItems, ...filteredBatch];
|
|
420
|
+
|
|
421
|
+
lastEvaluatedKey = response.LastEvaluatedKey;
|
|
422
|
+
|
|
423
|
+
} while (lastEvaluatedKey);
|
|
424
|
+
|
|
425
|
+
return allItems;
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Aplica filtros específicos a los accounts
|
|
430
|
+
*/
|
|
431
|
+
const applyFiltersToAccounts = (items, dataTablesParams) => {
|
|
432
|
+
if (!items || !items.length) return [];
|
|
433
|
+
|
|
434
|
+
let filteredItems = [...items];
|
|
435
|
+
|
|
436
|
+
if (dataTablesParams.globalSearch) {
|
|
437
|
+
const searchTerm = dataTablesParams.globalSearch.toLowerCase();
|
|
438
|
+
filteredItems = filteredItems.filter(item => {
|
|
439
|
+
return Object.entries(item).some(([key, value]) => {
|
|
440
|
+
if (typeof value === 'string') {
|
|
441
|
+
return value.toLowerCase().includes(searchTerm);
|
|
442
|
+
} else if (typeof value === 'number') {
|
|
443
|
+
return value.toString().includes(searchTerm);
|
|
444
|
+
} else if (Array.isArray(value) && value.length > 0 && typeof value[0] === 'string') {
|
|
445
|
+
return value.some(val => val.toLowerCase().includes(searchTerm));
|
|
446
|
+
}
|
|
447
|
+
return false;
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
Object.entries(dataTablesParams.columnFilters || {}).forEach(([fieldName, filterValue]) => {
|
|
453
|
+
if (filterValue) {
|
|
454
|
+
const searchTerm = filterValue.toLowerCase();
|
|
455
|
+
filteredItems = filteredItems.filter(item => {
|
|
456
|
+
const fieldValue = item[fieldName];
|
|
457
|
+
if (typeof fieldValue === 'string') {
|
|
458
|
+
return fieldValue.toLowerCase().includes(searchTerm);
|
|
459
|
+
} else if (typeof fieldValue === 'number') {
|
|
460
|
+
return fieldValue.toString().includes(searchTerm);
|
|
461
|
+
}
|
|
462
|
+
return false;
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
if (dataTablesParams._moduleActive) {
|
|
468
|
+
const module = dataTablesParams._moduleActive;
|
|
469
|
+
filteredItems = filteredItems.filter(item =>
|
|
470
|
+
item[module] &&
|
|
471
|
+
((typeof item[module] === 'object' && item[module].isActive === true) ||
|
|
472
|
+
(typeof item[module] === 'boolean' && item[module] === true))
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (dataTablesParams._accountPattern) {
|
|
477
|
+
const pattern = dataTablesParams._accountPattern.replace(/\*/g, '.*');
|
|
478
|
+
const regex = new RegExp(`^${pattern}$`, 'i');
|
|
479
|
+
filteredItems = filteredItems.filter(item => regex.test(item.AccountName));
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (dataTablesParams._integration) {
|
|
483
|
+
const integrationType = dataTablesParams._integration.toLowerCase();
|
|
484
|
+
filteredItems = filteredItems.filter(item => {
|
|
485
|
+
switch (integrationType) {
|
|
486
|
+
case 'sftp':
|
|
487
|
+
return item.SftpUsed === true ||
|
|
488
|
+
(item.SftpIntegration && item.SftpIntegration.isActive === true);
|
|
489
|
+
case 'api':
|
|
490
|
+
return item.Credentials && item.Credentials.key && item.Credentials.token;
|
|
491
|
+
case 'webhook':
|
|
492
|
+
return item.HookOrderVtexMDv2 && item.HookOrderVtexMDv2.trim() !== '';
|
|
493
|
+
default:
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return filteredItems;
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Aplica ordenamiento a los accounts
|
|
504
|
+
*/
|
|
505
|
+
const applySortingToAccounts = (items, orderField, orderDir) => {
|
|
506
|
+
if (!items || !items.length) return items;
|
|
507
|
+
|
|
508
|
+
return items.sort((a, b) => {
|
|
509
|
+
let valueA = a[orderField];
|
|
510
|
+
let valueB = b[orderField];
|
|
511
|
+
|
|
512
|
+
if (valueA == null) valueA = '';
|
|
513
|
+
if (valueB == null) valueB = '';
|
|
514
|
+
|
|
515
|
+
valueA = valueA.toString().toLowerCase();
|
|
516
|
+
valueB = valueB.toString().toLowerCase();
|
|
517
|
+
|
|
518
|
+
if (orderDir === 'desc') {
|
|
519
|
+
return valueB.localeCompare(valueA);
|
|
520
|
+
} else {
|
|
521
|
+
return valueA.localeCompare(valueB);
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Función para búsqueda por múltiples AccountNames
|
|
528
|
+
*/
|
|
529
|
+
const getAccountsByMultipleNames = async (accountNames, queryParams = {}) => {
|
|
530
|
+
try {
|
|
531
|
+
const dynamodb = new DynamoAWS.DocumentClient();
|
|
532
|
+
let allItems = [];
|
|
533
|
+
|
|
534
|
+
if (accountNames.length <= 100) {
|
|
535
|
+
const params = {
|
|
536
|
+
TableName: ACCOUNT_DATA_CONFIG_TABLE,
|
|
537
|
+
FilterExpression: "AccountName IN (" + accountNames.map((_, i) => `:an${i}`).join(', ') + ")",
|
|
538
|
+
ExpressionAttributeValues: {}
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
accountNames.forEach((accountName, i) => {
|
|
542
|
+
params.ExpressionAttributeValues[`:an${i}`] = accountName;
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
let lastEvaluatedKey = null;
|
|
546
|
+
do {
|
|
547
|
+
if (lastEvaluatedKey) {
|
|
548
|
+
params.ExclusiveStartKey = lastEvaluatedKey;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const response = await dynamodb.scan(params).promise();
|
|
552
|
+
allItems = [...allItems, ...(response.Items || [])];
|
|
553
|
+
lastEvaluatedKey = response.LastEvaluatedKey;
|
|
554
|
+
|
|
555
|
+
} while (lastEvaluatedKey);
|
|
556
|
+
} else {
|
|
557
|
+
const chunks = chunkArray(accountNames, 100);
|
|
558
|
+
|
|
559
|
+
for (const chunk of chunks) {
|
|
560
|
+
const chunkResult = await getAccountsByMultipleNames(chunk, queryParams);
|
|
561
|
+
allItems = [...allItems, ...(chunkResult.items || [])];
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const filteredItems = applyFiltersToAccounts(allItems, queryParams);
|
|
566
|
+
const sortedItems = applySortingToAccounts(filteredItems, queryParams.orderField || "AccountName", queryParams.orderDir || "asc");
|
|
567
|
+
|
|
568
|
+
return {
|
|
569
|
+
items: sortedItems,
|
|
570
|
+
count: sortedItems.length,
|
|
571
|
+
lastEvaluatedKey: null
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
} catch (err) {
|
|
575
|
+
Logger.error("Error getting accounts by multiple names: ", err);
|
|
576
|
+
return { items: [], lastEvaluatedKey: null, count: 0 };
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Función auxiliar para dividir array en chunks
|
|
582
|
+
*/
|
|
583
|
+
const chunkArray = (array, size) => {
|
|
584
|
+
const chunks = [];
|
|
585
|
+
for (let i = 0; i < array.length; i += size) {
|
|
586
|
+
chunks.push(array.slice(i, i + size));
|
|
587
|
+
}
|
|
588
|
+
return chunks;
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Función principal que maneja DataTables y Legacy - CON VALIDACIONES
|
|
593
|
+
*/
|
|
594
|
+
const getAccountsForDataTables = async (queryParams = {}) => {
|
|
595
|
+
try {
|
|
596
|
+
if (!queryParams || typeof queryParams !== 'object') {
|
|
597
|
+
Logger.error("Invalid queryParams:", queryParams);
|
|
598
|
+
throw new Error("Invalid query parameters");
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
if (queryParams.accountNamesFilter && queryParams.accountNamesFilter.length > 0) {
|
|
602
|
+
Logger.debug("Searching by multiple AccountNames:", queryParams.accountNamesFilter);
|
|
603
|
+
return getAccountsByMultipleNames(queryParams.accountNamesFilter, queryParams);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (queryParams.parentAccountName) {
|
|
607
|
+
return getAccountsByParentName(queryParams.parentAccountName, queryParams);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
if (queryParams.draw !== undefined) {
|
|
611
|
+
return getAccountsWithDataTablesPagination(queryParams);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
return getAccountsByParentName(null, queryParams);
|
|
615
|
+
} catch (error) {
|
|
616
|
+
Logger.error("Error in getAccountsForDataTables:", error);
|
|
617
|
+
return {
|
|
618
|
+
data: [],
|
|
619
|
+
items: [],
|
|
620
|
+
recordsTotal: 0,
|
|
621
|
+
recordsFiltered: 0,
|
|
622
|
+
count: 0,
|
|
623
|
+
draw: queryParams.draw || 1,
|
|
624
|
+
lastEvaluatedKey: null,
|
|
625
|
+
error: error.message
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
module.exports = {
|
|
631
|
+
getAccountDataAll,
|
|
632
|
+
getAccountsByParentName,
|
|
633
|
+
getAccountDataByAccountName,
|
|
634
|
+
getAccountsForDataTables,
|
|
635
|
+
getAccountsWithDataTablesPagination,
|
|
636
|
+
getAccountsByMultipleNames,
|
|
637
|
+
deleteAccountByAccountName,
|
|
638
|
+
addAccountDataConfig,
|
|
639
|
+
};
|