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,67 @@
|
|
|
1
|
+
const VtexApi = require("../../vtex/clients/VtexApi");
|
|
2
|
+
const AccountData = require("../../entities/account");
|
|
3
|
+
const ApiResponse = require("../../common/utils/api-response");
|
|
4
|
+
const jwt = require('jsonwebtoken');
|
|
5
|
+
const Logger = require("../../common/utils/logger");
|
|
6
|
+
|
|
7
|
+
const SECRET_KEY = process.env.JWT_SECRET || 'your-secret-key';
|
|
8
|
+
const handler = async (event) => {
|
|
9
|
+
try {
|
|
10
|
+
const { token } = event.queryStringParameters;
|
|
11
|
+
const { accountName, fileId, entity } = decryptUrlParams(token);
|
|
12
|
+
|
|
13
|
+
if (!accountName || !fileId) {
|
|
14
|
+
return ApiResponse.response(400, {
|
|
15
|
+
success: false,
|
|
16
|
+
message: "Missing required parameters"
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//Obtener configuración de cuenta
|
|
20
|
+
const configAccount = await AccountData.getAccountDataByAccountName(accountName);
|
|
21
|
+
if (!configAccount?.NewLeadsNotification) {
|
|
22
|
+
return ApiResponse.response(404, {
|
|
23
|
+
success: false,
|
|
24
|
+
message: "Account configuration not found"
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const vtexApi = new VtexApi(
|
|
28
|
+
configAccount.AccountName,
|
|
29
|
+
configAccount.Credentials.key,
|
|
30
|
+
configAccount.Credentials.token
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const fileData = await vtexApi.fetch(
|
|
34
|
+
`/dataentities/${configAccount.NewLeadsNotification.fileUploadEntity}/search?_fields=_all&id=${fileId}`,
|
|
35
|
+
{
|
|
36
|
+
method: 'GET',
|
|
37
|
+
headers: {
|
|
38
|
+
'Cache-Control': 'no-cache',
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
'REST-Range': 'resources=0-1'
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
return {
|
|
45
|
+
statusCode: 200,
|
|
46
|
+
headers: {
|
|
47
|
+
'Content-Type': 'text/csv',
|
|
48
|
+
'Content-Disposition': `attachment; filename="${fileData.data[0].fileName}"`,
|
|
49
|
+
},
|
|
50
|
+
body: fileData.data[0].fileContent
|
|
51
|
+
};
|
|
52
|
+
} catch (error) {
|
|
53
|
+
Logger.error('Download error:', error);
|
|
54
|
+
return ApiResponse.response(500, {
|
|
55
|
+
success: false,
|
|
56
|
+
message: "Error downloading file",
|
|
57
|
+
error: error.message,
|
|
58
|
+
id: fileId
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
function decryptUrlParams(token) {
|
|
64
|
+
return jwt.verify(token, SECRET_KEY);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = { handler };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const AccountData = require("../../entities/account");
|
|
2
|
+
const { handler: newLeadsHandler } = require("./new-leads-notification-handler");
|
|
3
|
+
|
|
4
|
+
exports.processNewLeadsNotification = async (accountName, actionProcess, values) => {
|
|
5
|
+
const accountConfig = await AccountData.getAccountDataByAccountName(accountName);
|
|
6
|
+
if (!accountConfig) {
|
|
7
|
+
throw new Error("Account configuration not found");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (actionProcess === 'new-leads') {
|
|
11
|
+
await newLeadsHandler({
|
|
12
|
+
source: 'cron',
|
|
13
|
+
accountName,
|
|
14
|
+
...values
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
//new-leads-notification-handler.js
|
|
2
|
+
const VtexHelper = require("../vtex/vtex-helpers");
|
|
3
|
+
const VtexApi = require("../../vtex/clients/VtexApi");
|
|
4
|
+
const ApiResponse = require("../../common/utils/api-response");
|
|
5
|
+
const AccountData = require("../../entities/account");
|
|
6
|
+
const ClientData = require("../../entities/clients");
|
|
7
|
+
const { calculateDateRange } = require("../../common/utils/date-range-calculator");
|
|
8
|
+
const jwt = require('jsonwebtoken');
|
|
9
|
+
const Logger = require("../../common/utils/logger");
|
|
10
|
+
|
|
11
|
+
const SECRET_KEY = process.env.JWT_SECRET || 'your-secret-key';
|
|
12
|
+
const BASE_URL_API = `https://${process.env.BASE_URL_API}${(process.env.ENV_URL_API == 'prod' ? '' : `/${process.env.ENV_URL_API}`)}` || 'https://localhost:3000';
|
|
13
|
+
|
|
14
|
+
const handler = async (event) => {
|
|
15
|
+
try {
|
|
16
|
+
let accountName, configAccount;
|
|
17
|
+
const accountHttp = event?.pathParameters?.an ?? null;
|
|
18
|
+
|
|
19
|
+
if (event.source === 'cron') {
|
|
20
|
+
accountName = event.accountName;
|
|
21
|
+
} else if(accountHttp){
|
|
22
|
+
accountName = accountHttp;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!accountName) {
|
|
26
|
+
return ApiResponse.response(400, {
|
|
27
|
+
success: false,
|
|
28
|
+
message: "AccountName is Required"
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
configAccount = await AccountData.getAccountDataByAccountName(accountName);
|
|
33
|
+
if (!configAccount) {
|
|
34
|
+
return ApiResponse.response(400, { success: false, message: "Account not found" });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const newLeadsConfig = configAccount.NewLeadsNotification;
|
|
38
|
+
const configValidation = VtexHelper.validateLeadsConfig(newLeadsConfig);
|
|
39
|
+
|
|
40
|
+
if (!configValidation.isValid) {
|
|
41
|
+
return ApiResponse.response(400, {
|
|
42
|
+
success: false,
|
|
43
|
+
message: "Invalid leads configuration",
|
|
44
|
+
errors: configValidation.errors
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const vtexApi = new VtexApi(
|
|
49
|
+
configAccount.AccountName,
|
|
50
|
+
configAccount.Credentials.key,
|
|
51
|
+
configAccount.Credentials.token
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const dateRange = calculateDateRange(
|
|
55
|
+
newLeadsConfig.rangeQuery,
|
|
56
|
+
newLeadsConfig.rangeValue
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const currentDate = new Date().toISOString();
|
|
60
|
+
const fileName = `new-leads-${newLeadsConfig.fileUploadEntity}-${currentDate}.csv`;
|
|
61
|
+
|
|
62
|
+
const leads = await getLeadsFromMasterData(
|
|
63
|
+
vtexApi,
|
|
64
|
+
newLeadsConfig.newLeadsEntity,
|
|
65
|
+
dateRange,
|
|
66
|
+
configAccount
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
if (!leads || leads.length === 0) {
|
|
70
|
+
return ApiResponse.response(200, {
|
|
71
|
+
success: true,
|
|
72
|
+
message: "No new leads found in the specified date range"
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Crear documento con CSV
|
|
77
|
+
const document = await createLeadsDocument(vtexApi, newLeadsConfig, leads, dateRange, fileName);
|
|
78
|
+
|
|
79
|
+
// Generar URL
|
|
80
|
+
const downloadUrl = generatePublicDownloadUrl(
|
|
81
|
+
configAccount.AccountName,
|
|
82
|
+
document.documentId,
|
|
83
|
+
newLeadsConfig.fileUploadEntity
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
// Actualizar documento con URL y enviar notificación
|
|
87
|
+
await sendNotification(vtexApi, configAccount, downloadUrl, dateRange, fileName, document.fileContent, document.documentId);
|
|
88
|
+
|
|
89
|
+
return ApiResponse.response(200, {
|
|
90
|
+
success: true,
|
|
91
|
+
message: "New leads notification processed successfully",
|
|
92
|
+
data: {
|
|
93
|
+
leadsCount: leads.length,
|
|
94
|
+
downloadUrl,
|
|
95
|
+
dateRange,
|
|
96
|
+
documentId: document.documentId,
|
|
97
|
+
metadata: {
|
|
98
|
+
accountName: configAccount.AccountName,
|
|
99
|
+
entity: newLeadsConfig.newLeadsEntity,
|
|
100
|
+
expirationTime: newLeadsConfig.ExpirationTimeFile
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
} catch (error) {
|
|
106
|
+
return ApiResponse.response(500, {
|
|
107
|
+
success: false,
|
|
108
|
+
message: "Error processing new leads notification",
|
|
109
|
+
error: error.message
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
async function getLeadsFromMasterData(vtexApi, entity, dateRange, configAccount) {
|
|
115
|
+
const config = configAccount.NewLeadsNotification;
|
|
116
|
+
const leads = [];
|
|
117
|
+
let stopApi = false;
|
|
118
|
+
let scrollToken = null;
|
|
119
|
+
let page = 1;
|
|
120
|
+
|
|
121
|
+
while (!stopApi) {
|
|
122
|
+
try {
|
|
123
|
+
const listLeads = await getLeadsSearchAllVTEX({
|
|
124
|
+
vtexApi: vtexApi,
|
|
125
|
+
entity: entity,
|
|
126
|
+
_fields: config.fields,
|
|
127
|
+
size: config.ScrollSize,
|
|
128
|
+
page: page,
|
|
129
|
+
scroll: true,
|
|
130
|
+
scrollToken: scrollToken,
|
|
131
|
+
dateField: config.dateField,
|
|
132
|
+
startDate: dateRange.startDate,
|
|
133
|
+
endDate: dateRange.endDate,
|
|
134
|
+
config: config
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (listLeads && listLeads?.data && listLeads?.data?.length > 0) {
|
|
138
|
+
leads.push(...listLeads.data);
|
|
139
|
+
|
|
140
|
+
if (!listLeads.scrollToken) {
|
|
141
|
+
scrollToken = null;
|
|
142
|
+
stopApi = true;
|
|
143
|
+
} else {
|
|
144
|
+
scrollToken = listLeads.scrollToken;
|
|
145
|
+
page++;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Opcional: Detener si se alcanza el máximo de solicitudes de scroll
|
|
149
|
+
if (page > config.MaxScrollRequests) {
|
|
150
|
+
stopApi = true;
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
stopApi = true;
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
Logger.error(`Error al recuperar lote de leads: ${error.message}`);
|
|
157
|
+
stopApi = true;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return leads;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function getLeadsSearchAllVTEX({
|
|
165
|
+
vtexApi,
|
|
166
|
+
entity = 'CT',
|
|
167
|
+
_fields = "_all",
|
|
168
|
+
size = 1000,
|
|
169
|
+
page = 1,
|
|
170
|
+
scroll = false,
|
|
171
|
+
scrollToken = null,
|
|
172
|
+
dateField = null,
|
|
173
|
+
startDate = null,
|
|
174
|
+
endDate = null,
|
|
175
|
+
config = {}
|
|
176
|
+
}) {
|
|
177
|
+
if (!vtexApi) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const endpoint = scroll ? '/scroll' : '/search';
|
|
182
|
+
const url = `/dataentities/${entity}${endpoint}?_fields=${_fields}`;
|
|
183
|
+
|
|
184
|
+
const requestOptions = {
|
|
185
|
+
method: 'GET',
|
|
186
|
+
headers: {
|
|
187
|
+
'Cache-Control': 'no-cache'
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// Agregar filtro de rango de fechas
|
|
192
|
+
if (dateField && startDate && endDate) {
|
|
193
|
+
let whereClause = `${dateField} between ${startDate} AND ${endDate}`;
|
|
194
|
+
|
|
195
|
+
// Agregar validación de campo duplicado si existe
|
|
196
|
+
if (config?.duplicateField) {
|
|
197
|
+
whereClause += ` AND ${config.duplicateField} is null`;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
requestOptions.params = {
|
|
201
|
+
...(requestOptions.params || {}),
|
|
202
|
+
_where: whereClause
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (scroll === false) {
|
|
207
|
+
requestOptions.headers['REST-Range'] = `resources=${(page > 1 ? ((parseFloat(page)*parseFloat(size))+1) : 0)}-${(page > 1 ? (parseFloat((page+1))*parseFloat(size)) : size)}`;
|
|
208
|
+
} else if (scroll === true && typeof scrollToken === 'string') {
|
|
209
|
+
requestOptions.params = {
|
|
210
|
+
...(requestOptions.params || {}),
|
|
211
|
+
_token: scrollToken
|
|
212
|
+
};
|
|
213
|
+
} else {
|
|
214
|
+
requestOptions.params = {
|
|
215
|
+
...(requestOptions.params || {}),
|
|
216
|
+
_size: size
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
const response = await vtexApi.fetch(url, requestOptions);
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
data: response.data,
|
|
225
|
+
page: response.data?.length === 0 ? null : (parseInt(page) + 1),
|
|
226
|
+
scrollToken: response.headers['x-vtex-md-token'] || null
|
|
227
|
+
};
|
|
228
|
+
} catch (error) {
|
|
229
|
+
Logger.error('Error en getLeadsSearchAllVTEX:', error);
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function transformLeadFields(lead, leadMap) {
|
|
235
|
+
if (!lead || typeof lead !== 'object') return {};
|
|
236
|
+
if (!leadMap || typeof leadMap !== 'object') return {};
|
|
237
|
+
|
|
238
|
+
const transformedLead = {};
|
|
239
|
+
|
|
240
|
+
for (const [csvHeader, mapConfig] of Object.entries(leadMap)) {
|
|
241
|
+
let value = '';
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
if (typeof mapConfig === 'string') {
|
|
245
|
+
value = lead[mapConfig] ?? '';
|
|
246
|
+
} else if (typeof mapConfig === 'object' && mapConfig !== null) {
|
|
247
|
+
if (!mapConfig.field) continue;
|
|
248
|
+
|
|
249
|
+
if (Array.isArray(mapConfig.field)) {
|
|
250
|
+
const fieldValues = mapConfig.field
|
|
251
|
+
.map(field => {
|
|
252
|
+
const fieldValue = lead[field];
|
|
253
|
+
return fieldValue != null ? String(fieldValue).trim() : '';
|
|
254
|
+
})
|
|
255
|
+
.filter(Boolean);
|
|
256
|
+
value = fieldValues.length > 0 ? fieldValues.join(' ') : '';
|
|
257
|
+
} else {
|
|
258
|
+
value = lead[mapConfig.field] ?? '';
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (mapConfig.transform) {
|
|
262
|
+
try {
|
|
263
|
+
const transformResult = new Function('value', `return ${mapConfig.transform}`)(value);
|
|
264
|
+
value = transformResult ?? value;
|
|
265
|
+
} catch (transformError) {
|
|
266
|
+
Logger.error(`Transform error for ${csvHeader}: ${transformError.message}`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
value = value !== null && value !== undefined ? String(value).trim() : '';
|
|
272
|
+
|
|
273
|
+
if (typeof value === 'string' && value.includes(',')) {
|
|
274
|
+
value = `"${value.replace(/"/g, '""')}"`;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
transformedLead[csvHeader] = value;
|
|
278
|
+
|
|
279
|
+
} catch (error) {
|
|
280
|
+
Logger.error(`Error processing ${csvHeader}: ${error.message}`);
|
|
281
|
+
transformedLead[csvHeader] = '';
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return transformedLead;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
async function createLeadsDocument(vtexApi, config, leads, dateRange, fileName) {
|
|
289
|
+
const formattedLeads = leads.map(lead => transformLeadFields(lead, config.leadMap));
|
|
290
|
+
const uniqueDocumentId = `${config.fileUploadEntity}-${Math.random().toString(36).slice(2, 11)}`;;
|
|
291
|
+
const currentDate = new Date().toISOString();
|
|
292
|
+
|
|
293
|
+
const headers = Object.keys(config.leadMap);
|
|
294
|
+
const csvRows = [headers.join(',')]; // Header row
|
|
295
|
+
|
|
296
|
+
formattedLeads.forEach(lead => {
|
|
297
|
+
const row = headers.map(header => {
|
|
298
|
+
const value = lead[header] || '';
|
|
299
|
+
// Escapar comas y comillas en valores
|
|
300
|
+
return `"${String(value).replace(/"/g, '""')}"`;
|
|
301
|
+
});
|
|
302
|
+
csvRows.push(row.join(','));
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
const csvContent = csvRows.join('\n');
|
|
306
|
+
|
|
307
|
+
const documentSave = {
|
|
308
|
+
documentId: uniqueDocumentId,
|
|
309
|
+
fileName,
|
|
310
|
+
fileContent: csvContent,
|
|
311
|
+
downloadUrl: null,
|
|
312
|
+
generationDate: currentDate
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
return documentSave;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function encryptUrlParams(params) {
|
|
319
|
+
return jwt.sign(params, SECRET_KEY);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function generatePublicDownloadUrl(accountName, fileId, entity) {
|
|
323
|
+
const params = { accountName, fileId, entity };
|
|
324
|
+
const token = encryptUrlParams(params);
|
|
325
|
+
return `${BASE_URL_API}/new-leads/download?token=${token}`;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async function sendNotification(vtexApi, config, downloadUrl, dateRange, fileName, fileContent, documentId) {
|
|
329
|
+
const currentDate = new Date().toISOString();
|
|
330
|
+
const { fileUploadEntity, schema = '' } = config.NewLeadsNotification;
|
|
331
|
+
|
|
332
|
+
const document = {
|
|
333
|
+
id: documentId,
|
|
334
|
+
downloadUrl,
|
|
335
|
+
generationDate: currentDate,
|
|
336
|
+
fileName,
|
|
337
|
+
fileContent
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
// Construir URL asegurando que termine con /
|
|
341
|
+
const baseUrl = `/dataentities/${fileUploadEntity}/documents/`;
|
|
342
|
+
const url = schema ? `${baseUrl}?_schema=${schema}` : baseUrl;
|
|
343
|
+
const response = await vtexApi.fetch(url,
|
|
344
|
+
{
|
|
345
|
+
method: 'PATCH',
|
|
346
|
+
data: document,
|
|
347
|
+
headers: {
|
|
348
|
+
'Cache-Control': 'no-cache',
|
|
349
|
+
'Content-Type': 'application/json'
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
if (response.status >= 400) {
|
|
355
|
+
throw new Error(`Failed to update notification document. Status: ${response.status}, Message: ${response.statusText || 'Unknown error'}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
module.exports = { handler };
|