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,226 @@
|
|
|
1
|
+
const csv = require('csv-parser')
|
|
2
|
+
const xml2js = require('xml2js')
|
|
3
|
+
const { Validator } = require('jsonschema')
|
|
4
|
+
const { Readable } = require('node:stream')
|
|
5
|
+
const Logger = require("../../../common/utils/logger");
|
|
6
|
+
|
|
7
|
+
class ValidFile {
|
|
8
|
+
constructor(schema) {
|
|
9
|
+
this.schema = schema // Esquema proporcionado durante la creación de la instancia
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
extractContentFile = async (file, contentType = null) => {
|
|
13
|
+
if (!file) {
|
|
14
|
+
return {
|
|
15
|
+
valid: false,
|
|
16
|
+
errors: ['No se proporcionó un archivo'],
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!this.schema) {
|
|
21
|
+
throw new Error('Esquema no inicializado.')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const firstExecution = !contentType;
|
|
25
|
+
|
|
26
|
+
if (!contentType) {
|
|
27
|
+
contentType = this.schema.ContentType;
|
|
28
|
+
}
|
|
29
|
+
contentType = contentType?.toLowerCase();
|
|
30
|
+
|
|
31
|
+
let parsedData
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
switch (contentType) {
|
|
35
|
+
case 'csv':
|
|
36
|
+
parsedData = await this.parseCSV(file.content, firstExecution)
|
|
37
|
+
break
|
|
38
|
+
case 'json':
|
|
39
|
+
parsedData = this.parseJson(file.content, firstExecution)
|
|
40
|
+
break
|
|
41
|
+
case 'xml':
|
|
42
|
+
parsedData = await this.parseXML(file.content, firstExecution)
|
|
43
|
+
break
|
|
44
|
+
default:
|
|
45
|
+
return { valid: false, errors: [`ContentType no soportado o no definido`] }
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return { valid: false, errors: [`Error al procesar el archivo: ${error.message}`] }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
valid: parsedData !== undefined,
|
|
53
|
+
data: parsedData,
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
// validador de esquema
|
|
59
|
+
validateRecordSchema = (data) => {
|
|
60
|
+
const { Schema } = this.schema
|
|
61
|
+
|
|
62
|
+
if (!Schema?.properties) {
|
|
63
|
+
throw new Error("El esquema no está definido correctamente.")
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const validator = new Validator()
|
|
67
|
+
const record = data
|
|
68
|
+
|
|
69
|
+
if (!record) {
|
|
70
|
+
return {
|
|
71
|
+
valid: false,
|
|
72
|
+
errors: ["No se encontró ningún registro en los datos parseados."],
|
|
73
|
+
record: null,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// validacion de datos contra el esquema
|
|
78
|
+
const validationResult = validator.validate(record, Schema)
|
|
79
|
+
|
|
80
|
+
if (validationResult.errors.length > 0) {
|
|
81
|
+
return {
|
|
82
|
+
valid: false,
|
|
83
|
+
errors: validationResult.errors.map(error => error.stack),
|
|
84
|
+
record: null,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
valid: true,
|
|
90
|
+
errors: [],
|
|
91
|
+
record,
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// -------------------------
|
|
96
|
+
standardizeData = (data) => {
|
|
97
|
+
const standardized = {}
|
|
98
|
+
const { Standardization: standardizationRules } = this.schema
|
|
99
|
+
this.callbackStandarize(standardized, standardizationRules, data);
|
|
100
|
+
return standardized
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
callbackStandarize = (standardized, standardizationRules, data) => {
|
|
104
|
+
for (const [key, rule] of Object.entries(standardizationRules)) {
|
|
105
|
+
try {
|
|
106
|
+
let ruleType = Object.prototype.toString.call(rule);
|
|
107
|
+
if (ruleType == '[object Object]') {
|
|
108
|
+
// Si los datos de conversión son de tipo Object se ejecuta la actualización de manera recursiva
|
|
109
|
+
standardized[key] = {};
|
|
110
|
+
this.callbackStandarize(standardized[key], standardizationRules[key], data);
|
|
111
|
+
} else {
|
|
112
|
+
standardized[key] = eval(rule)
|
|
113
|
+
}
|
|
114
|
+
} catch (ex) {
|
|
115
|
+
Logger.error(`Error procesando la regla: ${rule}`, ex)
|
|
116
|
+
standardized[key] = null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
parseCSV = async (content, firstExecution) => {
|
|
122
|
+
const { Separator, Headers = null, Conditional, GroupRecord } = this.schema;
|
|
123
|
+
|
|
124
|
+
const csvStream = new Readable()
|
|
125
|
+
csvStream.push(content)
|
|
126
|
+
csvStream.push(null)
|
|
127
|
+
|
|
128
|
+
let records = firstExecution ? {} : [], index = 0;
|
|
129
|
+
return new Promise((resolve, reject) => {
|
|
130
|
+
csvStream
|
|
131
|
+
.pipe(csv({ separator: Separator, headers: Headers }))
|
|
132
|
+
.on('data', item => {
|
|
133
|
+
if (firstExecution) {
|
|
134
|
+
let isValid = !Conditional;
|
|
135
|
+
if (Conditional) {
|
|
136
|
+
try {
|
|
137
|
+
eval(`isValid=${Conditional}`)
|
|
138
|
+
} catch (ex) { }
|
|
139
|
+
}
|
|
140
|
+
if (isValid) {
|
|
141
|
+
if (GroupRecord) {
|
|
142
|
+
try {
|
|
143
|
+
eval(GroupRecord);
|
|
144
|
+
} catch (ex) { }
|
|
145
|
+
} else {
|
|
146
|
+
records[index] = item;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
index++;
|
|
150
|
+
} else {
|
|
151
|
+
records.push(item);
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
.on('end', () => resolve(firstExecution ? Object.values(records) : records))
|
|
155
|
+
.on('error', (error) => reject(error))
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
parseXML = async (content, firstExecution) => {
|
|
160
|
+
const { RootElement, RecordElement, Conditional, GroupRecord } = this.schema;
|
|
161
|
+
|
|
162
|
+
const parser = new xml2js.Parser({
|
|
163
|
+
// Hace que el valor de cada key se retorne como un texto y no como array
|
|
164
|
+
explicitArray: false
|
|
165
|
+
});
|
|
166
|
+
const result = await parser.parseStringPromise(content);
|
|
167
|
+
if (!firstExecution) {
|
|
168
|
+
return result?.[RootElement]?.[RecordElement] ?? [];
|
|
169
|
+
}
|
|
170
|
+
if (result?.[RootElement]?.[RecordElement]?.length) {
|
|
171
|
+
let records = {};
|
|
172
|
+
result[RootElement][RecordElement].forEach((item, index) => {
|
|
173
|
+
let isValid = !Conditional;
|
|
174
|
+
if (Conditional) {
|
|
175
|
+
try {
|
|
176
|
+
eval(`isValid=${Conditional}`)
|
|
177
|
+
} catch (ex) { }
|
|
178
|
+
}
|
|
179
|
+
if (isValid) {
|
|
180
|
+
if (GroupRecord) {
|
|
181
|
+
try {
|
|
182
|
+
eval(GroupRecord);
|
|
183
|
+
} catch (ex) { }
|
|
184
|
+
} else {
|
|
185
|
+
records[index] = item;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
return Object.values(records);
|
|
190
|
+
}
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
parseJson = (content, firstExecution) => {
|
|
195
|
+
const { Conditional, GroupRecord } = this.schema;
|
|
196
|
+
|
|
197
|
+
const dataFile = JSON.parse(content);
|
|
198
|
+
if (!firstExecution) {
|
|
199
|
+
return dataFile;
|
|
200
|
+
}
|
|
201
|
+
if (dataFile.length) {
|
|
202
|
+
let records = {};
|
|
203
|
+
dataFile.forEach((item, index) => {
|
|
204
|
+
let isValid = !Conditional;
|
|
205
|
+
if (Conditional) {
|
|
206
|
+
try {
|
|
207
|
+
eval(`isValid=${Conditional}`)
|
|
208
|
+
} catch (ex) { }
|
|
209
|
+
}
|
|
210
|
+
if (isValid) {
|
|
211
|
+
if (GroupRecord) {
|
|
212
|
+
try {
|
|
213
|
+
eval(GroupRecord);
|
|
214
|
+
} catch (ex) { }
|
|
215
|
+
} else {
|
|
216
|
+
records[index] = item;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
return Object.values(records);
|
|
221
|
+
}
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
module.exports = ValidFile
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const AWS = require('aws-sdk')
|
|
2
|
+
const dynamoDb = new AWS.DynamoDB.DocumentClient()
|
|
3
|
+
// UTILS
|
|
4
|
+
const Apiresponse = require('../../../common/utils/api-response');
|
|
5
|
+
const { getErrorData } = require('../../../common/utils/util');
|
|
6
|
+
const Logger = require("../../../common/utils/logger");
|
|
7
|
+
// CONSTANTS
|
|
8
|
+
const { SFTP_CREDENTIALS_TABLE } = process?.env ?? {};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Función que se invoca desde la función 'sftp-credentiales' del archivo functions.xml
|
|
12
|
+
* @param {*} event Objeto que contiene información de una petición como: el body, path y método de una petición HTTP, o la lista de registros en una cola SQS.
|
|
13
|
+
* @param {*} context Objeto que contiene información sobre la invocación, la función y el entorno de ejecución.
|
|
14
|
+
*/
|
|
15
|
+
module.exports.handler = async (event, context) => {
|
|
16
|
+
const { httpMethod = '', pathParameters } = event;
|
|
17
|
+
const { FtpId = null } = pathParameters ?? {};
|
|
18
|
+
// ID de la petición en AWS
|
|
19
|
+
const { awsRequestId } = context;
|
|
20
|
+
try {
|
|
21
|
+
switch (httpMethod.toUpperCase()) {
|
|
22
|
+
case 'GET':
|
|
23
|
+
return await handleGetRecord(FtpId)
|
|
24
|
+
case 'PUT': {
|
|
25
|
+
const body = event?.body ? JSON.parse(event.body) : {}
|
|
26
|
+
return await handlePutRecord(FtpId, body)
|
|
27
|
+
}
|
|
28
|
+
case 'DELETE':
|
|
29
|
+
return await handleDeleteRecord(FtpId)
|
|
30
|
+
default:
|
|
31
|
+
return Apiresponse.response(405, `Method ${httpMethod} not allowed`)
|
|
32
|
+
}
|
|
33
|
+
} catch (ex) {
|
|
34
|
+
const { message, info } = getErrorData(ex);
|
|
35
|
+
Logger.error(info);
|
|
36
|
+
return Apiresponse.response(500, { 'error': message, awsRequestId });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Handler to GET (get a record)
|
|
41
|
+
const handleGetRecord = async (ftpId) => {
|
|
42
|
+
let params = {
|
|
43
|
+
TableName: SFTP_CREDENTIALS_TABLE
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
if (ftpId) {
|
|
48
|
+
params.Key = { FtpId: ftpId }
|
|
49
|
+
const result = await dynamoDb.get(params).promise()
|
|
50
|
+
if (!result.Item) {
|
|
51
|
+
return Apiresponse.response(404, `Schema not found, verify your FtpId or Get Schemas to see Schema Id`)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
statusCode: 200,
|
|
56
|
+
body: JSON.stringify(result.Item),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
} else {
|
|
60
|
+
let result = await dynamoDb.scan(params).promise();
|
|
61
|
+
let items = result.Items;
|
|
62
|
+
|
|
63
|
+
while (result.LastEvaluatedKey) {
|
|
64
|
+
params.ExclusiveStartKey = result.LastEvaluatedKey;
|
|
65
|
+
result = await dynamoDb.query(params).promise();
|
|
66
|
+
items = items.concat(result.Items);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
statusCode: 200,
|
|
71
|
+
body: JSON.stringify(items),
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} catch (error) {
|
|
75
|
+
return Apiresponse.response(500, `Error retrieving record: ${error}`)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Handler to PUT (create or update record)
|
|
80
|
+
const handlePutRecord = async (ftpId, data) => {
|
|
81
|
+
|
|
82
|
+
if (!data || Object.keys(data).length === 0) {
|
|
83
|
+
return Apiresponse.response(400, 'No data provided to create/update record schema')
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
await dynamoDb.put({
|
|
88
|
+
TableName: SFTP_CREDENTIALS_TABLE,
|
|
89
|
+
Item: {
|
|
90
|
+
FtpId: ftpId,
|
|
91
|
+
...data
|
|
92
|
+
}
|
|
93
|
+
}).promise()
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
statusCode: 200,
|
|
97
|
+
body: JSON.stringify({ message: 'Record created/updated successfully', data }),
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
} catch (error) {
|
|
101
|
+
return Apiresponse.response(500, `Error creating/updating record: ${error}`)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Handler to DELETE (delete a record)
|
|
106
|
+
const handleDeleteRecord = async (ftpId) => {
|
|
107
|
+
if (!ftpId) {
|
|
108
|
+
return Apiresponse.response(400, 'The "FtpId" parameter is required for this request.')
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
await dynamoDb.delete({
|
|
112
|
+
TableName: SFTP_CREDENTIALS_TABLE,
|
|
113
|
+
Key: { FtpId: ftpId }
|
|
114
|
+
}).promise();
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
statusCode: 200,
|
|
118
|
+
body: JSON.stringify({ message: 'Record deleted successfully' }),
|
|
119
|
+
}
|
|
120
|
+
} catch (error) {
|
|
121
|
+
return Apiresponse.response(500, `Error deleting record: ${error}`)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const AWS = require('aws-sdk')
|
|
2
|
+
const dynamoDb = new AWS.DynamoDB.DocumentClient()
|
|
3
|
+
// UTILS
|
|
4
|
+
const Apiresponse = require('../../../common/utils/api-response')
|
|
5
|
+
const Logger = require("../../../common/utils/logger");
|
|
6
|
+
|
|
7
|
+
// CONSTANTS
|
|
8
|
+
const SCHEMA_FILES_TABLE = process.env.SCHEMA_FILES_TABLE
|
|
9
|
+
const sftpConfigProducer= require("../sftp-config-producer");
|
|
10
|
+
|
|
11
|
+
module.exports.handler = async (event, res) => {
|
|
12
|
+
const id = event?.pathParameters?.SchemaId ?? ''
|
|
13
|
+
const method = event?.httpMethod?.toUpperCase()
|
|
14
|
+
const body = event?.body ? JSON.parse(event.body) : {}
|
|
15
|
+
Logger.debug('EVENT:', event);
|
|
16
|
+
try {
|
|
17
|
+
|
|
18
|
+
switch (method) {
|
|
19
|
+
case 'GET':
|
|
20
|
+
return await handleGetRecord({ id })
|
|
21
|
+
case 'PUT':{
|
|
22
|
+
return await handlePutRecord({ id, data:body })
|
|
23
|
+
}
|
|
24
|
+
case 'DELETE':
|
|
25
|
+
return await handleDeleteRecord({ id })
|
|
26
|
+
|
|
27
|
+
case 'POST':
|
|
28
|
+
return await sftpConfigProducer.producer(event, res)
|
|
29
|
+
|
|
30
|
+
default:
|
|
31
|
+
return Apiresponse.response(405, `Method ${method} not allowed`)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
} catch (error) {
|
|
35
|
+
return Apiresponse.response(500, `Internal Server Error Handler ${error}`)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Handler to GET (get a record)
|
|
40
|
+
const handleGetRecord = async ({ id }) => {
|
|
41
|
+
let params = {
|
|
42
|
+
TableName: SCHEMA_FILES_TABLE,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
|
|
47
|
+
if (id) {
|
|
48
|
+
params.Key = { SchemaId: id }
|
|
49
|
+
const result = await dynamoDb.get(params).promise()
|
|
50
|
+
if (!result.Item) {
|
|
51
|
+
return Apiresponse.response(404, `Schema not found, verify your schemaId or Get Schemas to see Schema Id`)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
statusCode: 200,
|
|
56
|
+
body: JSON.stringify(result.Item),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
} else {
|
|
60
|
+
result = await dynamoDb.scan(params).promise();
|
|
61
|
+
let items = result.Items;
|
|
62
|
+
|
|
63
|
+
while (result.LastEvaluatedKey) {
|
|
64
|
+
params.ExclusiveStartKey = result.LastEvaluatedKey;
|
|
65
|
+
result = await dynamoDb.query(params).promise();
|
|
66
|
+
items = items.concat(result.Items);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
statusCode: 200,
|
|
70
|
+
body: JSON.stringify(items),
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
} catch (error) {
|
|
76
|
+
return Apiresponse.response(500, `Error retrieving record: ${error}`)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Handler to PUT (create or update record)
|
|
81
|
+
const handlePutRecord = async ({ id, data }) => {
|
|
82
|
+
|
|
83
|
+
if (!data || Object.keys(data).length === 0) {
|
|
84
|
+
return Apiresponse.response(400, 'No data provided to create/update record schema')
|
|
85
|
+
}
|
|
86
|
+
if (id === '') {
|
|
87
|
+
return Apiresponse.response(400, 'The "SchemaId" parameter is required for create/update record schema')
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
await dynamoDb.put({
|
|
92
|
+
TableName: SCHEMA_FILES_TABLE,
|
|
93
|
+
Item: {
|
|
94
|
+
SchemaId: id,
|
|
95
|
+
...data
|
|
96
|
+
}
|
|
97
|
+
}).promise()
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
statusCode: 200,
|
|
101
|
+
body: JSON.stringify({ message: 'Record created/updated successfully', data }),
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
} catch (error) {
|
|
105
|
+
return Apiresponse.response(500, `Error creating/updating record: ${error}`)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Handler to DELETE (delete a record)
|
|
110
|
+
const handleDeleteRecord = async ({ id }) => {
|
|
111
|
+
if (!id) {
|
|
112
|
+
return Apiresponse.response(400, 'The "SchemaId" parameter is required for this request.')
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
await dynamoDb.delete({
|
|
116
|
+
TableName: SCHEMA_FILES_TABLE,
|
|
117
|
+
Key: {
|
|
118
|
+
SchemaId: id
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
.promise()
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
statusCode: 200,
|
|
125
|
+
body: JSON.stringify({ message: 'Record deleted successfully' }),
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return Apiresponse.response(500, `Error deleting record: ${error}`)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const ApiResponse = require('../../common/utils/api-response')
|
|
2
|
+
const AWSServices = require('../../common/utils/aws-services')
|
|
3
|
+
|
|
4
|
+
const { SftpFileSystem } = require('../../common/utils/ftp-sftp');
|
|
5
|
+
const requiredFieldsConfig = require('./schemas/sftp_required_fields.json');
|
|
6
|
+
const AccountData = require("../../entities/account");
|
|
7
|
+
const ClientData = require("../../entities/clients");
|
|
8
|
+
const Logger = require("../../common/utils/logger");
|
|
9
|
+
|
|
10
|
+
const SQS_CONNECTION_SFTP_QUEUE_URL = process.env.SQS_CONNECTION_SFTP_QUEUE_URL
|
|
11
|
+
|
|
12
|
+
module.exports.producer = async (event) => {
|
|
13
|
+
let statusCode = 200;
|
|
14
|
+
let message
|
|
15
|
+
let body = JSON.parse(event.body);
|
|
16
|
+
|
|
17
|
+
const { client_id: clientId } = event.requestContext.authorizer.claims || {};
|
|
18
|
+
Logger.log("EVENT:", event?.body, clientId);
|
|
19
|
+
// OBTENER LA CONFIGURACION DEL ACCOUNT ✅
|
|
20
|
+
try {
|
|
21
|
+
const listAccounts = await ClientData.getClient(clientId);
|
|
22
|
+
const accountName = listAccounts.AccountNames.values[0] || null;
|
|
23
|
+
|
|
24
|
+
if (!accountName) {
|
|
25
|
+
return ApiResponse.response(400, { approved: false, message: "AccountName is Required" });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const configAccount = await AccountData.getAccountDataByAccountName(accountName);
|
|
29
|
+
|
|
30
|
+
// VERIFICAR QUE EXISTE LA PROPIEDAD ESPECIFICADA SftpIntegration dentro de la configuracion del account
|
|
31
|
+
const sftpConfig = configAccount?.SftpIntegration ?? null
|
|
32
|
+
|
|
33
|
+
const isActive = isActiveServiceInConfiguration({ isActive: sftpConfig.isActive })
|
|
34
|
+
|
|
35
|
+
if (!isActive) {
|
|
36
|
+
return ApiResponse.response(400, { approved: false, message: "SftpIntegration service is not active" });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
const isConfigSFTP = isValidConnectionSFTP({ sftpConnectConfig: sftpConfig?.sftpConnectConfig})
|
|
41
|
+
|
|
42
|
+
if (!isConfigSFTP.success) {
|
|
43
|
+
return ApiResponse.response(400, { approved: false, message: isConfigSFTP.message });
|
|
44
|
+
}
|
|
45
|
+
// Send info to SQS
|
|
46
|
+
await sendSftpConnectionToSQS({ sftpConfig })
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
} catch (error) {
|
|
50
|
+
Logger.error(error)
|
|
51
|
+
return ApiResponse.response(500, { approved: false, message: "Error sending SFTP connection" })
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const isActiveServiceInConfiguration = ({ isActive }) => {
|
|
57
|
+
if (typeof isActive === 'boolean' && isActive !== '' && isActive) {
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const isValidConnectionSFTP = async ({ sftpConnectConfig }) => {
|
|
64
|
+
|
|
65
|
+
const response = validateRequiredFields(sftpConnectConfig, requiredFieldsConfig)
|
|
66
|
+
|
|
67
|
+
if(!response.success){
|
|
68
|
+
return { success: response?.success, message: response?.message}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const { host, port, user, password } = sftpConnectConfig;
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
const sftpFileSystem = SftpFileSystem.create(host, port, user, password);
|
|
75
|
+
|
|
76
|
+
await sftpFileSystem.connect();
|
|
77
|
+
await sftpFileSystem.disconnect();
|
|
78
|
+
|
|
79
|
+
return { success: true, message: 'Connection SFTP successfully.' };
|
|
80
|
+
|
|
81
|
+
} catch (error) {
|
|
82
|
+
Logger.error('Error connecting to SFTP:', error);
|
|
83
|
+
return { success: false, message: `Error connecting to SFTP: ${error.message}` };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function validateRequiredFields(obj, requiredFields) {
|
|
88
|
+
const missingFields = requiredFields.filter(field => !obj[field]);
|
|
89
|
+
|
|
90
|
+
if (missingFields.length > 0) {
|
|
91
|
+
return {
|
|
92
|
+
success: false,
|
|
93
|
+
message: `Missing fields required: ${missingFields.join(', ')}`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return { success: true };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
const sendSftpConnectionToSQS = async ({ sftpConfig }) => {
|
|
102
|
+
if(!sftpConfig){
|
|
103
|
+
return ApiResponse.response(400, "Data account not found")
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
await AWSServices.sendSQSMessage(SQS_CONNECTION_SFTP_QUEUE_URL, sftpConfig);
|
|
108
|
+
} catch (err) {
|
|
109
|
+
Logger.error('Failed to send message to SQS:', err);
|
|
110
|
+
return ApiResponse.response(500, 'Failed to process SFTP connection message.');
|
|
111
|
+
}
|
|
112
|
+
}
|