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,355 @@
|
|
|
1
|
+
// src/functions/utils/account-properties-handler.js
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const ApiResponse = require('./api-response');
|
|
6
|
+
const Logger = require('./logger');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Procesa recursivamente las propiedades del schema para extraer toda la información
|
|
10
|
+
* @param {Object} properties - Propiedades del schema
|
|
11
|
+
* @param {Array} requiredFields - Campos requeridos en este nivel
|
|
12
|
+
* @param {String} parentPath - Ruta padre para propiedades anidadas
|
|
13
|
+
* @returns {Object} Estructura procesada con metadatos
|
|
14
|
+
*/
|
|
15
|
+
const processSchemaProperties = (properties, requiredFields = [], parentPath = '') => {
|
|
16
|
+
const processedProperties = {};
|
|
17
|
+
|
|
18
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
19
|
+
const currentPath = parentPath ? `${parentPath}.${key}` : key;
|
|
20
|
+
const isRequired = requiredFields.includes(key);
|
|
21
|
+
|
|
22
|
+
processedProperties[key] = {
|
|
23
|
+
path: currentPath,
|
|
24
|
+
type: value.type,
|
|
25
|
+
required: isRequired,
|
|
26
|
+
description: value.description || null
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Agregar información adicional según el tipo
|
|
30
|
+
if (value.minLength !== undefined) {
|
|
31
|
+
processedProperties[key].minLength = value.minLength;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (value.maxLength !== undefined) {
|
|
35
|
+
processedProperties[key].maxLength = value.maxLength;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (value.pattern !== undefined) {
|
|
39
|
+
processedProperties[key].pattern = value.pattern;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (value.enum !== undefined) {
|
|
43
|
+
processedProperties[key].enum = value.enum;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (value.minimum !== undefined) {
|
|
47
|
+
processedProperties[key].minimum = value.minimum;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (value.maximum !== undefined) {
|
|
51
|
+
processedProperties[key].maximum = value.maximum;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (value.minProperties !== undefined) {
|
|
55
|
+
processedProperties[key].minProperties = value.minProperties;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (value.additionalProperties !== undefined) {
|
|
59
|
+
processedProperties[key].additionalProperties = value.additionalProperties;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Procesar propiedades anidadas para objetos
|
|
63
|
+
if (value.type === 'object' && value.properties) {
|
|
64
|
+
processedProperties[key].nested_properties = processSchemaProperties(
|
|
65
|
+
value.properties,
|
|
66
|
+
value.required || [],
|
|
67
|
+
currentPath
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Procesar items para arrays
|
|
72
|
+
if (value.type === 'array' && value.items) {
|
|
73
|
+
if (value.items.type === 'object' && value.items.properties) {
|
|
74
|
+
processedProperties[key].items = {
|
|
75
|
+
type: value.items.type,
|
|
76
|
+
properties: processSchemaProperties(
|
|
77
|
+
value.items.properties,
|
|
78
|
+
value.items.required || [],
|
|
79
|
+
`${currentPath}[]`
|
|
80
|
+
)
|
|
81
|
+
};
|
|
82
|
+
} else {
|
|
83
|
+
processedProperties[key].items = {
|
|
84
|
+
type: value.items.type
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Manejar patternProperties para objetos dinámicos
|
|
90
|
+
if (value.patternProperties) {
|
|
91
|
+
processedProperties[key].patternProperties = {};
|
|
92
|
+
for (const [pattern, patternValue] of Object.entries(value.patternProperties)) {
|
|
93
|
+
processedProperties[key].patternProperties[pattern] = {
|
|
94
|
+
type: patternValue.type,
|
|
95
|
+
properties: patternValue.properties ? processSchemaProperties(
|
|
96
|
+
patternValue.properties,
|
|
97
|
+
patternValue.required || [],
|
|
98
|
+
`${currentPath}.${pattern}`
|
|
99
|
+
) : undefined
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return processedProperties;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Obtiene un resumen de campos requeridos de manera plana
|
|
110
|
+
* @param {Object} processedSchema - Schema procesado
|
|
111
|
+
* @param {String} parentPath - Ruta padre
|
|
112
|
+
* @returns {Array} Lista de rutas de campos requeridos
|
|
113
|
+
*/
|
|
114
|
+
const getRequiredFieldsPaths = (processedSchema, parentPath = '') => {
|
|
115
|
+
const requiredPaths = [];
|
|
116
|
+
|
|
117
|
+
for (const [key, value] of Object.entries(processedSchema)) {
|
|
118
|
+
const currentPath = parentPath ? `${parentPath}.${key}` : key;
|
|
119
|
+
|
|
120
|
+
if (value.required) {
|
|
121
|
+
requiredPaths.push(currentPath);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (value.nested_properties) {
|
|
125
|
+
requiredPaths.push(...getRequiredFieldsPaths(value.nested_properties, currentPath));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (value.items && value.items.properties) {
|
|
129
|
+
requiredPaths.push(...getRequiredFieldsPaths(value.items.properties, `${currentPath}[]`));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (value.patternProperties) {
|
|
133
|
+
for (const [pattern, patternValue] of Object.entries(value.patternProperties)) {
|
|
134
|
+
if (patternValue.properties) {
|
|
135
|
+
requiredPaths.push(...getRequiredFieldsPaths(patternValue.properties, `${currentPath}.${pattern}`));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return requiredPaths;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Obtiene estadísticas del schema
|
|
146
|
+
* @param {Object} processedSchema - Schema procesado
|
|
147
|
+
* @returns {Object} Estadísticas del schema
|
|
148
|
+
*/
|
|
149
|
+
const getSchemaStatistics = (processedSchema) => {
|
|
150
|
+
let totalFields = 0;
|
|
151
|
+
let requiredFields = 0;
|
|
152
|
+
let optionalFields = 0;
|
|
153
|
+
let objectFields = 0;
|
|
154
|
+
let arrayFields = 0;
|
|
155
|
+
let primitiveFields = 0;
|
|
156
|
+
|
|
157
|
+
const countFields = (schema) => {
|
|
158
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
159
|
+
totalFields++;
|
|
160
|
+
|
|
161
|
+
if (value.required) {
|
|
162
|
+
requiredFields++;
|
|
163
|
+
} else {
|
|
164
|
+
optionalFields++;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
switch (value.type) {
|
|
168
|
+
case 'object':
|
|
169
|
+
objectFields++;
|
|
170
|
+
break;
|
|
171
|
+
case 'array':
|
|
172
|
+
arrayFields++;
|
|
173
|
+
break;
|
|
174
|
+
default:
|
|
175
|
+
primitiveFields++;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (value.nested_properties) {
|
|
179
|
+
countFields(value.nested_properties);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (value.items && value.items.properties) {
|
|
183
|
+
countFields(value.items.properties);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (value.patternProperties) {
|
|
187
|
+
for (const [pattern, patternValue] of Object.entries(value.patternProperties)) {
|
|
188
|
+
if (patternValue.properties) {
|
|
189
|
+
countFields(patternValue.properties);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
countFields(processedSchema);
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
total_fields: totalFields,
|
|
200
|
+
required_fields: requiredFields,
|
|
201
|
+
optional_fields: optionalFields,
|
|
202
|
+
object_fields: objectFields,
|
|
203
|
+
array_fields: arrayFields,
|
|
204
|
+
primitive_fields: primitiveFields
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Handler principal para obtener las propiedades del schema de Account
|
|
210
|
+
*/
|
|
211
|
+
const getAccountProperties = async () => {
|
|
212
|
+
try {
|
|
213
|
+
// Ruta al archivo del schema - ajustar según estructura del proyecto
|
|
214
|
+
const schemaPath = path.join(__dirname, '../../../json/schema-valid-json-account.json');
|
|
215
|
+
|
|
216
|
+
// Verificar que el archivo existe
|
|
217
|
+
if (!fs.existsSync(schemaPath)) {
|
|
218
|
+
Logger.error('Account schema file not found:', schemaPath);
|
|
219
|
+
return ApiResponse.response(404, {
|
|
220
|
+
error: 'Schema file not found',
|
|
221
|
+
details: 'The account schema definition file could not be located'
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Leer y parsear el schema
|
|
226
|
+
const schemaContent = fs.readFileSync(schemaPath, 'utf8');
|
|
227
|
+
const accountSchema = JSON.parse(schemaContent);
|
|
228
|
+
|
|
229
|
+
// Procesar el schema
|
|
230
|
+
const processedSchema = processSchemaProperties(
|
|
231
|
+
accountSchema.properties,
|
|
232
|
+
accountSchema.required || []
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
// Obtener rutas de campos requeridos
|
|
236
|
+
const requiredPaths = getRequiredFieldsPaths(processedSchema);
|
|
237
|
+
|
|
238
|
+
// Obtener estadísticas
|
|
239
|
+
const statistics = getSchemaStatistics(processedSchema);
|
|
240
|
+
|
|
241
|
+
// Construir respuesta
|
|
242
|
+
const response = {
|
|
243
|
+
schema_info: {
|
|
244
|
+
title: accountSchema.title || 'Account Schema',
|
|
245
|
+
description: accountSchema.description || 'Schema definition for Account entity',
|
|
246
|
+
schema_version: accountSchema.$schema || 'http://json-schema.org/draft-07/schema#',
|
|
247
|
+
total_root_properties: Object.keys(accountSchema.properties || {}).length,
|
|
248
|
+
total_required_root_properties: (accountSchema.required || []).length,
|
|
249
|
+
schema_type: accountSchema.type || 'object',
|
|
250
|
+
generated_at: new Date().toISOString()
|
|
251
|
+
},
|
|
252
|
+
properties: processedSchema,
|
|
253
|
+
required_fields_summary: requiredPaths,
|
|
254
|
+
statistics: statistics
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
Logger.info('Account properties processed successfully');
|
|
258
|
+
return ApiResponse.response(200, response);
|
|
259
|
+
|
|
260
|
+
} catch (error) {
|
|
261
|
+
Logger.error('Error processing account properties:', error);
|
|
262
|
+
|
|
263
|
+
if (error instanceof SyntaxError) {
|
|
264
|
+
return ApiResponse.response(400, {
|
|
265
|
+
error: 'Invalid schema format',
|
|
266
|
+
details: 'The schema file contains invalid JSON'
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return ApiResponse.response(500, {
|
|
271
|
+
error: 'Error processing account properties',
|
|
272
|
+
details: error.message
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Handler para obtener solo los campos requeridos
|
|
279
|
+
*/
|
|
280
|
+
const getRequiredFields = async () => {
|
|
281
|
+
try {
|
|
282
|
+
const schemaPath = path.join(__dirname, '../../json/schema-valid-json-account.json');
|
|
283
|
+
|
|
284
|
+
if (!fs.existsSync(schemaPath)) {
|
|
285
|
+
return ApiResponse.response(404, {
|
|
286
|
+
error: 'Schema file not found'
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const schemaContent = fs.readFileSync(schemaPath, 'utf8');
|
|
291
|
+
const accountSchema = JSON.parse(schemaContent);
|
|
292
|
+
|
|
293
|
+
const processedSchema = processSchemaProperties(
|
|
294
|
+
accountSchema.properties,
|
|
295
|
+
accountSchema.required || []
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
const requiredPaths = getRequiredFieldsPaths(processedSchema);
|
|
299
|
+
|
|
300
|
+
return ApiResponse.response(200, {
|
|
301
|
+
required_fields: requiredPaths,
|
|
302
|
+
count: requiredPaths.length,
|
|
303
|
+
root_required: accountSchema.required || [],
|
|
304
|
+
generated_at: new Date().toISOString()
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
} catch (error) {
|
|
308
|
+
Logger.error('Error getting required fields:', error);
|
|
309
|
+
return ApiResponse.response(500, {
|
|
310
|
+
error: 'Error processing required fields',
|
|
311
|
+
details: error.message
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Handler principal que maneja las rutas de propiedades de account
|
|
318
|
+
*/
|
|
319
|
+
const handler = async (event) => {
|
|
320
|
+
const { resource, httpMethod } = event;
|
|
321
|
+
|
|
322
|
+
try {
|
|
323
|
+
switch (resource) {
|
|
324
|
+
case "/accounts/properties":
|
|
325
|
+
if (httpMethod === "GET") {
|
|
326
|
+
return await getAccountProperties();
|
|
327
|
+
}
|
|
328
|
+
break;
|
|
329
|
+
|
|
330
|
+
case "/accounts/properties/required":
|
|
331
|
+
if (httpMethod === "GET") {
|
|
332
|
+
return await getRequiredFields();
|
|
333
|
+
}
|
|
334
|
+
break;
|
|
335
|
+
|
|
336
|
+
default:
|
|
337
|
+
return ApiResponse.response(404, { error: "Resource not found" });
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return ApiResponse.response(405, { error: "Method not allowed" });
|
|
341
|
+
|
|
342
|
+
} catch (error) {
|
|
343
|
+
Logger.error("Error in account properties handler:", error);
|
|
344
|
+
return ApiResponse.response(500, {
|
|
345
|
+
error: "Internal server error",
|
|
346
|
+
details: error.message
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
module.exports = {
|
|
352
|
+
handler,
|
|
353
|
+
getAccountProperties,
|
|
354
|
+
getRequiredFields
|
|
355
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const Logger = require("./logger");
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {number} statusCode
|
|
5
|
+
* @param {string} message
|
|
6
|
+
* @returns {import("aws-lambda").APIGatewayProxyResult}
|
|
7
|
+
* @example
|
|
8
|
+
* return response(404, "Account not found");
|
|
9
|
+
* @example
|
|
10
|
+
* return response(200, "Account found");
|
|
11
|
+
* */
|
|
12
|
+
const response = (statusCode, message, headers = {}) => {
|
|
13
|
+
if (message && typeof message === "string") {
|
|
14
|
+
message = JSON.stringify({ message }, null, 2);
|
|
15
|
+
} else if (message && typeof message === "object") {
|
|
16
|
+
message = JSON.stringify(message, null, 2);
|
|
17
|
+
} else {
|
|
18
|
+
message = JSON.stringify({ message: "Unknown error" }, null, 2);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
statusCode: statusCode || 500,
|
|
22
|
+
headers: {
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
...headers
|
|
25
|
+
},
|
|
26
|
+
body: message,
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
const responseNoCors = (statusCode, message) => {
|
|
32
|
+
if (message && typeof message === "string") {
|
|
33
|
+
message = JSON.stringify({ message }, null, 2);
|
|
34
|
+
} else if (message && typeof message === "object") {
|
|
35
|
+
message = JSON.stringify(message, null, 2);
|
|
36
|
+
} else {
|
|
37
|
+
message = JSON.stringify({ message: "Unknown error" }, null, 2);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
statusCode: statusCode || 500,
|
|
41
|
+
headers: {
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
"Access-Control-Allow-Origin": "*",
|
|
44
|
+
"Access-Control-Allow-Headers": "*",
|
|
45
|
+
"Access-Control-Allow-Methods": "*",
|
|
46
|
+
},
|
|
47
|
+
body: message,
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const validateRequiredParam = (name, evaluate) => {
|
|
52
|
+
if (!evaluate) {
|
|
53
|
+
Logger.error(`${name} is required`);
|
|
54
|
+
return response(400, `${name} is required`);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
module.exports = {
|
|
59
|
+
response,
|
|
60
|
+
responseNoCors,
|
|
61
|
+
validateRequiredParam,
|
|
62
|
+
};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
const { SQS, SSM, SecretsManager, DynamoDB } = require("aws-sdk");
|
|
2
|
+
const REGION_PROJECT = process.env.REGION_PROJECT;
|
|
3
|
+
const GeneralRequiredError = require("../../common/validation/GeneralErrorValidation.js");
|
|
4
|
+
const dynamoDb = new DynamoDB();
|
|
5
|
+
const Logger = require("./logger");
|
|
6
|
+
|
|
7
|
+
const sendSQSMessage = async (url, message) => {
|
|
8
|
+
const sqs = new SQS();
|
|
9
|
+
const params = {
|
|
10
|
+
MessageBody: JSON.stringify(message),
|
|
11
|
+
QueueUrl: url,
|
|
12
|
+
};
|
|
13
|
+
if (process.env.SQS_DELAY_SECONDS) {
|
|
14
|
+
params.DelaySeconds = process.env.SQS_DELAY_SECONDS;
|
|
15
|
+
}
|
|
16
|
+
await sqs.sendMessage(params).promise();
|
|
17
|
+
Logger.debug("Sending message to SQS", {
|
|
18
|
+
action: "SQS_SEND",
|
|
19
|
+
message: message,
|
|
20
|
+
url: URL
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Envia un mensaje a una cola SQS.
|
|
26
|
+
* @param {string} url URL de la cola SQS a la que se enviará el mensaje.
|
|
27
|
+
* @param {object} message Objeto JSON con los datos a enviar a la cola.
|
|
28
|
+
* @returns
|
|
29
|
+
*/
|
|
30
|
+
const sendMessageToSqs = async (url, message) => {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const sqs = new SQS()
|
|
33
|
+
|
|
34
|
+
// Si el "message" es un objeto, se hace una conversión a JSON String
|
|
35
|
+
if (typeof message === 'object') {
|
|
36
|
+
message = JSON.stringify(message);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const params = {
|
|
40
|
+
MessageBody: message,
|
|
41
|
+
QueueUrl: url
|
|
42
|
+
};
|
|
43
|
+
if (process?.env?.SQS_DELAY_SECONDS) {
|
|
44
|
+
params.DelaySeconds = process.env.SQS_DELAY_SECONDS;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Se ejecuta la tarea de enviar el mensaje a SQS
|
|
48
|
+
sqs.sendMessage(params, (err, data) => {
|
|
49
|
+
if (err) {
|
|
50
|
+
Logger.error('Error in SQS:', err);
|
|
51
|
+
reject(err);
|
|
52
|
+
} else {
|
|
53
|
+
const { MessageId } = data;
|
|
54
|
+
Logger.info("Message sent", {
|
|
55
|
+
action: "SQS_SEND",
|
|
56
|
+
message,
|
|
57
|
+
url,
|
|
58
|
+
messageId: MessageId
|
|
59
|
+
})
|
|
60
|
+
resolve(data);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const getSecretValue = async (paramPath) => {
|
|
67
|
+
const ssm = new SSM();
|
|
68
|
+
const params = {
|
|
69
|
+
Name: paramPath,
|
|
70
|
+
WithDecryption: true,
|
|
71
|
+
};
|
|
72
|
+
try {
|
|
73
|
+
const response = await ssm.getParameter(params).promise();
|
|
74
|
+
const secretValue = response.Parameter.Value;
|
|
75
|
+
return secretValue;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
Logger.error("Error getting secret value from SSM: ", error);
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const getSecretValueSecretsManager = async (secretName) => {
|
|
83
|
+
const client = new SecretsManager({ region: REGION_PROJECT });
|
|
84
|
+
const params = { SecretId: secretName };
|
|
85
|
+
try {
|
|
86
|
+
const response = await client.getSecretValue(params).promise();
|
|
87
|
+
if ('SecretString' in response) {
|
|
88
|
+
const secret = JSON.parse(response.SecretString);
|
|
89
|
+
return secret;
|
|
90
|
+
}
|
|
91
|
+
throw new GeneralRequiredError(`Secret information not found.`);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
Logger.error("Error getting secret: ", error);
|
|
94
|
+
throw new GeneralRequiredError(`Error getting secret value from SecretsManager: ${error.message}`);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Convierte un objeto JavaScript a formato DynamoDB
|
|
100
|
+
* @param {object} data - Objeto JavaScript a convertir
|
|
101
|
+
* @returns {object} - Objeto en formato DynamoDB
|
|
102
|
+
*/
|
|
103
|
+
const marshall = (data) => {
|
|
104
|
+
try {
|
|
105
|
+
return DynamoDB.Converter.marshall(data);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
Logger.error("Error marshalling data", { error: error.message });
|
|
108
|
+
throw new GeneralRequiredError(`Marshalling failed: ${error.message}`);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Convierte un objeto DynamoDB a JavaScript
|
|
114
|
+
* @param {object} data - Objeto DynamoDB a convertir
|
|
115
|
+
* @returns {object} - Objeto JavaScript
|
|
116
|
+
*/
|
|
117
|
+
const unmarshall = (data) => {
|
|
118
|
+
try {
|
|
119
|
+
return DynamoDB.Converter.unmarshall(data);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
Logger.error("Error unmarshalling data", { error: error.message });
|
|
122
|
+
throw new GeneralRequiredError(`Unmarshalling failed: ${error.message}`);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Ejecuta una operación Scan en DynamoDB
|
|
128
|
+
* @param {object} params - Parámetros para la operación Scan
|
|
129
|
+
* @returns {Promise<object>} - Resultado del escaneo
|
|
130
|
+
*/
|
|
131
|
+
const dynamoScan = async (params) => {
|
|
132
|
+
try {
|
|
133
|
+
const result = await dynamoDb.scan(params).promise();
|
|
134
|
+
return result;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
throw new Error(`DynamoDB Scan failed: ${error.message}`);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Ejecuta una operación Query en DynamoDB
|
|
142
|
+
* @param {object} params - Parámetros para la operación Query
|
|
143
|
+
* @returns {Promise<object>} - Resultado de la consulta
|
|
144
|
+
*/
|
|
145
|
+
const dynamoQuery = async (params) => {
|
|
146
|
+
try {
|
|
147
|
+
return await dynamoDb.query(params).promise();
|
|
148
|
+
} catch (error) {
|
|
149
|
+
Logger.error("DynamoDB query failed", {
|
|
150
|
+
action: "DYNAMO_QUERY_ERROR",
|
|
151
|
+
table: params.TableName,
|
|
152
|
+
error: error.message
|
|
153
|
+
});
|
|
154
|
+
throw new GeneralRequiredError(`DynamoDB query failed: ${error.message}`);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Ejecuta una operación BatchWrite en DynamoDB
|
|
160
|
+
* @param {object} params - Parámetros para la operación BatchWrite
|
|
161
|
+
* @returns {Promise<object>} - Resultado de la operación
|
|
162
|
+
*/
|
|
163
|
+
const dynamoBatchWrite = async (params) => {
|
|
164
|
+
try {
|
|
165
|
+
return await dynamoDb.batchWriteItem(params).promise();
|
|
166
|
+
} catch (error) {
|
|
167
|
+
Logger.error("DynamoDB batch write failed", {
|
|
168
|
+
action: "DYNAMO_BATCH_WRITE_ERROR",
|
|
169
|
+
table: Object.keys(params.RequestItems)[0],
|
|
170
|
+
error: error.message
|
|
171
|
+
});
|
|
172
|
+
throw new GeneralRequiredError(`DynamoDB batch write failed: ${error.message}`);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
module.exports = {
|
|
177
|
+
sendSQSMessage,
|
|
178
|
+
sendMessageToSqs,
|
|
179
|
+
getSecretValue,
|
|
180
|
+
getSecretValueSecretsManager,
|
|
181
|
+
marshall,
|
|
182
|
+
unmarshall,
|
|
183
|
+
dynamoQuery,
|
|
184
|
+
dynamoScan,
|
|
185
|
+
dynamoBatchWrite
|
|
186
|
+
};
|