dcos-core-monalisav2-latam 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +130 -0
  2. package/index.js +350 -0
  3. package/package.json +52 -0
  4. package/src/auth/handler.js +3 -0
  5. package/src/common/MondelezCastOrder.js +449 -0
  6. package/src/common/utils/AuthSecurity.js +46 -0
  7. package/src/common/utils/account-error-handler.js +279 -0
  8. package/src/common/utils/account-error-helper.js +231 -0
  9. package/src/common/utils/account-properties-handler.js +355 -0
  10. package/src/common/utils/api-response.js +62 -0
  11. package/src/common/utils/aws-services.js +186 -0
  12. package/src/common/utils/constants/account-error-codes.json +801 -0
  13. package/src/common/utils/constants.js +37 -0
  14. package/src/common/utils/convert/MondelezClientsItemsCast.js +52 -0
  15. package/src/common/utils/convert/MondelezInventoryItemsCast.js +15 -0
  16. package/src/common/utils/convert/MondelezOrderStatusCast.js +34 -0
  17. package/src/common/utils/convert/MondelezPricesItemsCast.js +37 -0
  18. package/src/common/utils/cron-ftp-get.js +143 -0
  19. package/src/common/utils/data-tables-helper.js +213 -0
  20. package/src/common/utils/date-range-calculator.js +113 -0
  21. package/src/common/utils/delay.js +17 -0
  22. package/src/common/utils/ftp-sftp.js +320 -0
  23. package/src/common/utils/logger.js +126 -0
  24. package/src/common/utils/nodemailerLib.js +61 -0
  25. package/src/common/utils/product-unit-converter.js +168 -0
  26. package/src/common/utils/schemas-utils.js +101 -0
  27. package/src/common/utils/seller-email-sharing-service.js +441 -0
  28. package/src/common/utils/sftp-utils.js +202 -0
  29. package/src/common/utils/status.js +15 -0
  30. package/src/common/utils/util.js +236 -0
  31. package/src/common/utils/validate-state-order.js +35 -0
  32. package/src/common/utils/validateProviders.js +67 -0
  33. package/src/common/utils/validation-data.js +45 -0
  34. package/src/common/utils/vtex/save-hooks.js +65 -0
  35. package/src/common/utils/vtex/save-schemas.js +65 -0
  36. package/src/common/utils/vtex-hook-handler.js +71 -0
  37. package/src/common/validation/AccountCoordinatesValidation.js +350 -0
  38. package/src/common/validation/GeneralErrorValidation.js +11 -0
  39. package/src/common/validation/MainErrorValidation.js +8 -0
  40. package/src/entities/account.js +639 -0
  41. package/src/entities/clients.js +104 -0
  42. package/src/entities/controlprice.js +196 -0
  43. package/src/entities/controlstock.js +206 -0
  44. package/src/entities/cron.js +77 -0
  45. package/src/entities/cronjob.js +71 -0
  46. package/src/entities/orders.js +195 -0
  47. package/src/entities/sftp-inbound.js +88 -0
  48. package/src/entities/sku.js +220 -0
  49. package/src/entities/taxpromotion.js +249 -0
  50. package/src/functions/account/account-get.js +262 -0
  51. package/src/functions/account/account-handler.js +299 -0
  52. package/src/functions/account/clients.js +10 -0
  53. package/src/functions/account/index.js +208 -0
  54. package/src/functions/actions/save-promotions-order-history.js +324 -0
  55. package/src/functions/affiliates/affiliates-hook-consumer.js +87 -0
  56. package/src/functions/affiliates/affiliates-hook-producer.js +45 -0
  57. package/src/functions/clients/clients-audience.js +62 -0
  58. package/src/functions/clients/clients-consumer.js +648 -0
  59. package/src/functions/clients/clients-producer.js +362 -0
  60. package/src/functions/clients/clients-suggested-product-consumer.js +166 -0
  61. package/src/functions/clients/helpers/suggested-product-mdlz.js +233 -0
  62. package/src/functions/clients_peru/email.html +129 -0
  63. package/src/functions/clients_peru/splitfile.js +357 -0
  64. package/src/functions/clients_peru/updateClients.js +1334 -0
  65. package/src/functions/clients_peru/utils.js +243 -0
  66. package/src/functions/cronjobs/cron-jobs-manager.js +40 -0
  67. package/src/functions/cronjobs/cron-jobs.js +171 -0
  68. package/src/functions/crons/cron.js +39 -0
  69. package/src/functions/distributors/distributor-handler.js +81 -0
  70. package/src/functions/distributors/distributor.js +535 -0
  71. package/src/functions/distributors/index.js +60 -0
  72. package/src/functions/financialpolicy/assign-financialpolicy.js +111 -0
  73. package/src/functions/financialpolicy/get-financialpolicy.js +91 -0
  74. package/src/functions/financialpolicy/index.js +28 -0
  75. package/src/functions/inventory/catalog-sync-consumer.js +17 -0
  76. package/src/functions/inventory/catalog-sync-handler.js +311 -0
  77. package/src/functions/inventory/inventory-consumer.js +119 -0
  78. package/src/functions/inventory/inventory-producer.js +197 -0
  79. package/src/functions/multiPresentation/multipre-queue.js +155 -0
  80. package/src/functions/multiPresentation/multipres.js +459 -0
  81. package/src/functions/nodeflow/index.js +83 -0
  82. package/src/functions/nodeflow/nodeflow-cron.js +200 -0
  83. package/src/functions/nodeflow/nodeflow-pub.js +203 -0
  84. package/src/functions/nodeflow/nodeflow-pvt.js +266 -0
  85. package/src/functions/notifications/download-leads-handler.js +67 -0
  86. package/src/functions/notifications/new-leads-notification-consumer.js +17 -0
  87. package/src/functions/notifications/new-leads-notification-handler.js +359 -0
  88. package/src/functions/notifications/order-status-notification-handler.js +482 -0
  89. package/src/functions/notifications/promotion-notification-handler.js +193 -0
  90. package/src/functions/orders/index.js +32 -0
  91. package/src/functions/orders/orders-cancel-handler.js +74 -0
  92. package/src/functions/orders/orders-handler.js +280 -0
  93. package/src/functions/orders/orders-hook-consumer.js +137 -0
  94. package/src/functions/orders/orders-hook-producer.js +170 -0
  95. package/src/functions/orders/orders-notifications-handler.js +137 -0
  96. package/src/functions/orders/orders-status-consumer.js +461 -0
  97. package/src/functions/orders/orders-status-producer.js +443 -0
  98. package/src/functions/prices/index.js +75 -0
  99. package/src/functions/prices/prices-consumer.js +236 -0
  100. package/src/functions/prices/prices-producer.js +323 -0
  101. package/src/functions/prices/promotion-and-tax.js +1284 -0
  102. package/src/functions/routesflow/assign-routeflow-queue.js +77 -0
  103. package/src/functions/schemas/vtex/handle-schemas.js +102 -0
  104. package/src/functions/security/process_gas.js +221 -0
  105. package/src/functions/security/security-handler.js +950 -0
  106. package/src/functions/sftp/sftp-consumer.js +453 -0
  107. package/src/functions/sftpIntegrations/processes/redirectServices.js +184 -0
  108. package/src/functions/sftpIntegrations/processes/validateFileSchema.js +226 -0
  109. package/src/functions/sftpIntegrations/schemas/credential-schema.js +123 -0
  110. package/src/functions/sftpIntegrations/schemas/record-schema.js +131 -0
  111. package/src/functions/sftpIntegrations/schemas/sftp_required_fields.json +3 -0
  112. package/src/functions/sftpIntegrations/sftp-config-producer.js +112 -0
  113. package/src/functions/sftpIntegrations/sftp-consumer.js +700 -0
  114. package/src/functions/sftpIntegrations/test/validateFile.test.js +122 -0
  115. package/src/functions/sftpIntegrations/utils/connect-dynamo.js +29 -0
  116. package/src/functions/sftpIntegrations/utils/split-data.js +25 -0
  117. package/src/functions/utils/index.js +130 -0
  118. package/src/functions/vtex/vtex-helpers.js +694 -0
  119. package/src/integrations/accountErrors/AccountErrorManager.js +437 -0
  120. package/src/integrations/audience/Audience.js +70 -0
  121. package/src/integrations/financialPolicy/FinancialPolicyApi.js +377 -0
  122. package/src/integrations/index.js +0 -0
  123. package/src/integrations/mobilvendor/MobilvendorApi.js +405 -0
  124. package/src/integrations/productmultipresentation/ProductMultiPresentation.js +200 -0
  125. package/src/mdlz/auth/SecretManagerApi.js +77 -0
  126. package/src/mdlz/client/MdlzApi.js +70 -0
  127. package/src/vtex/clients/ProvidersApi.js +51 -0
  128. package/src/vtex/clients/VtexApi.js +511 -0
  129. package/src/vtex/models/VtexOrder.js +87 -0
@@ -0,0 +1,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,3 @@
1
+ {
2
+ "sftpConnectConfig": ["host", "port", "user", "password", "routeDirectory"]
3
+ }
@@ -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
+ }