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,694 @@
|
|
|
1
|
+
const VtexApi = require("../../vtex/clients/VtexApi");
|
|
2
|
+
const ApiResponse = require("../../common/utils/api-response");
|
|
3
|
+
const AccountData = require("../../entities/account");
|
|
4
|
+
const ClientData = require("../../entities/clients");
|
|
5
|
+
const Logger = require("../../common/utils/logger");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {import("aws-lambda").APIGatewayProxyEvent} event
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
11
|
+
const list_products_vtex = async (event) => {
|
|
12
|
+
const clientId = event?.requestContext?.authorizer?.claims?.client_id;
|
|
13
|
+
let statusCode = 200;
|
|
14
|
+
let responseService = [];
|
|
15
|
+
|
|
16
|
+
const anRequest = event?.queryStringParameters?.an ?? null;
|
|
17
|
+
if(anRequest){
|
|
18
|
+
const validAccount = await ClientData.validateAccount(clientId, anRequest);
|
|
19
|
+
if (!validAccount) {
|
|
20
|
+
Logger.error("Data INVALID: ", validAccount);
|
|
21
|
+
return ApiResponse.response(404, "Account not found");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const listAccounts = anRequest ? null : await ClientData.getClient(clientId);
|
|
26
|
+
const an = listAccounts ? listAccounts?.AccountNames?.values[0] : anRequest;
|
|
27
|
+
if (!an) {
|
|
28
|
+
Logger.error("Error service: ", "AccountName not found");
|
|
29
|
+
return ApiResponse.response(statusCode, []);
|
|
30
|
+
}
|
|
31
|
+
const configAccount = await AccountData.getAccountDataByAccountName(an);
|
|
32
|
+
|
|
33
|
+
if (!configAccount) {
|
|
34
|
+
Logger.error("Error service: ", "Account not found");
|
|
35
|
+
return ApiResponse.response(statusCode, []);
|
|
36
|
+
}
|
|
37
|
+
const configAccountParent = configAccount?.AccountName === configAccount?.ParentAccountName ? configAccount : await AccountData.getAccountDataByAccountName(configAccount?.ParentAccountName);
|
|
38
|
+
|
|
39
|
+
if (!configAccountParent) {
|
|
40
|
+
Logger.error("Error service: ", "Parent Account not found");
|
|
41
|
+
return ApiResponse.response(statusCode, []);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
let productAll= event?.queryStringParameters?.ProductsAll ?? null;
|
|
46
|
+
|
|
47
|
+
if(typeof productAll === "string"){
|
|
48
|
+
productAll= productAll.toLowerCase();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const apiClient = new VtexApi(configAccountParent?.AccountName, configAccountParent?.Credentials?.key, configAccountParent?.Credentials?.token);
|
|
52
|
+
const isActive= event?.queryStringParameters?.isActive ?? null;
|
|
53
|
+
const isVisible= event?.queryStringParameters?.isVisible ?? null;
|
|
54
|
+
const sc= event?.queryStringParameters?.sc ?? "1";
|
|
55
|
+
const lengthData= event?.queryStringParameters?.rows ?? 2000;
|
|
56
|
+
|
|
57
|
+
if(productAll && (productAll===true || productAll==='true')){
|
|
58
|
+
responseService= await apiClient.getProductsAll(isActive, isVisible, sc, lengthData);
|
|
59
|
+
}else{
|
|
60
|
+
responseService= await apiClient.getProducts(event, isActive, isVisible, sc, lengthData);
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
Logger.error("Error service: ", error);
|
|
64
|
+
statusCode = 500;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return ApiResponse.response(statusCode, responseService);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {import("aws-lambda").APIGatewayProxyEvent} event
|
|
72
|
+
* @returns
|
|
73
|
+
*/
|
|
74
|
+
const list_categories_vtex = async (event) => {
|
|
75
|
+
const clientId = event?.requestContext?.authorizer?.claims?.client_id;
|
|
76
|
+
const anRequest = event?.queryStringParameters?.an ?? null;
|
|
77
|
+
if(anRequest){
|
|
78
|
+
const validAccount = await ClientData.validateAccount(clientId, anRequest);
|
|
79
|
+
if (!validAccount) {
|
|
80
|
+
Logger.error("Data INVALID: ", validAccount);
|
|
81
|
+
return ApiResponse.response(404, "Account not found");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const listAccounts = anRequest ? null : await ClientData.getClient(clientId);
|
|
86
|
+
const categoryLevels = event?.pathParameters?.categoryLevels;
|
|
87
|
+
let statusCode = 200;
|
|
88
|
+
let responseService = [];
|
|
89
|
+
const an = listAccounts ? listAccounts?.AccountNames?.values[0] : anRequest;
|
|
90
|
+
if (!an) {
|
|
91
|
+
Logger.error("Error service: ", "AccountName not found");
|
|
92
|
+
return ApiResponse.response(statusCode, []);
|
|
93
|
+
}
|
|
94
|
+
const configAccount = await AccountData.getAccountDataByAccountName(an);
|
|
95
|
+
|
|
96
|
+
if (!configAccount) {
|
|
97
|
+
Logger.error("Error service: ", "Account not found");
|
|
98
|
+
return ApiResponse.response(statusCode, []);
|
|
99
|
+
}
|
|
100
|
+
const configAccountParent = configAccount?.AccountName === configAccount?.ParentAccountName ? configAccount : await AccountData.getAccountDataByAccountName(configAccount?.ParentAccountName);
|
|
101
|
+
|
|
102
|
+
if (!configAccountParent) {
|
|
103
|
+
Logger.error("Error service: ", "Parent Account not found");
|
|
104
|
+
return ApiResponse.response(statusCode, []);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const apiClient = new VtexApi(configAccountParent?.AccountName, configAccountParent?.Credentials?.key, configAccountParent?.Credentials?.token);
|
|
109
|
+
const response = await apiClient.fetch(`/catalog_system/pub/category/tree/${categoryLevels}`, {
|
|
110
|
+
method: "GET",
|
|
111
|
+
params: event?.queryStringParameters
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
if (response?.data) {
|
|
115
|
+
responseService = response?.data ?? [];
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
Logger.error("Error service: ", error);
|
|
119
|
+
statusCode = 500;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return ApiResponse.response(statusCode, responseService);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @param {import("aws-lambda").APIGatewayProxyEvent} event
|
|
127
|
+
* @returns
|
|
128
|
+
*/
|
|
129
|
+
const list_brands_vtex = async (event) => {
|
|
130
|
+
const clientId = event?.requestContext?.authorizer?.claims?.client_id;
|
|
131
|
+
const anRequest = event?.queryStringParameters?.an ?? null;
|
|
132
|
+
if(anRequest){
|
|
133
|
+
const validAccount = await ClientData.validateAccount(clientId, anRequest);
|
|
134
|
+
if (!validAccount) {
|
|
135
|
+
Logger.error("Data INVALID: ", validAccount);
|
|
136
|
+
return ApiResponse.response(404, "Account not found");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const listAccounts = anRequest ? null : await ClientData.getClient(clientId);
|
|
141
|
+
let statusCode = 200;
|
|
142
|
+
let responseService = [];
|
|
143
|
+
const an = listAccounts ? listAccounts?.AccountNames?.values[0] : anRequest;
|
|
144
|
+
if (!an) {
|
|
145
|
+
Logger.error("Error service: ", "AccountName not found");
|
|
146
|
+
return ApiResponse.response(statusCode, []);
|
|
147
|
+
}
|
|
148
|
+
const configAccount = await AccountData.getAccountDataByAccountName(an);
|
|
149
|
+
|
|
150
|
+
if (!configAccount) {
|
|
151
|
+
Logger.error("Error service: ", "Account not found");
|
|
152
|
+
return ApiResponse.response(statusCode, []);
|
|
153
|
+
}
|
|
154
|
+
const configAccountParent = configAccount?.AccountName === configAccount?.ParentAccountName ? configAccount : await AccountData.getAccountDataByAccountName(configAccount?.ParentAccountName);
|
|
155
|
+
|
|
156
|
+
if (!configAccountParent) {
|
|
157
|
+
Logger.error("Error service: ", "Parent Account not found");
|
|
158
|
+
return ApiResponse.response(statusCode, []);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const apiClient = new VtexApi(configAccountParent?.AccountName, configAccountParent?.Credentials?.key, configAccountParent?.Credentials?.token);
|
|
163
|
+
const response = await apiClient.fetch(`/catalog_system/pub/brand/list`, {
|
|
164
|
+
method: "GET",
|
|
165
|
+
params: event?.queryStringParameters
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
if (response?.data) {
|
|
169
|
+
responseService = response?.data ?? [];
|
|
170
|
+
}
|
|
171
|
+
} catch (error) {
|
|
172
|
+
Logger.error("Error service: ", error);
|
|
173
|
+
statusCode = 500;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return ApiResponse.response(statusCode, responseService);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Retrieves an order form by its unique identifier
|
|
181
|
+
* @param {string} orderFormId - Unique identifier of the order form
|
|
182
|
+
* @param {string} accountName - VTEX account name
|
|
183
|
+
* @param {string} key - API authentication key
|
|
184
|
+
* @param {string} token - API authentication token
|
|
185
|
+
* @returns {Promise<Object|null>} Order form details or null if not found
|
|
186
|
+
* @throws {Error} Network or API connection errors
|
|
187
|
+
* @description Fetches complete order form details from VTEX using the provided order form ID
|
|
188
|
+
* @example
|
|
189
|
+
* const orderForm = await getOrderFormById('123456', 'myAccount', 'apiKey', 'apiToken');
|
|
190
|
+
* // Returns order form object or null
|
|
191
|
+
*/
|
|
192
|
+
async function getOrderFormById(orderFormId, accountName, key, token) {
|
|
193
|
+
try {
|
|
194
|
+
const vtexApi = new VtexApi(accountName, key, token);
|
|
195
|
+
const responseOrderForm = await vtexApi.fetch(`/checkout/pub/orderForm/${orderFormId}?refreshOutdatedData=true`, { method: "GET" });
|
|
196
|
+
|
|
197
|
+
if (responseOrderForm.status !== 200){
|
|
198
|
+
Logger.error("Error getOrderFormById: ", responseOrderForm);
|
|
199
|
+
ApiResponse.response(404, { approved: false, message: "orderForm is not found" });
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const { data } = responseOrderForm;
|
|
203
|
+
|
|
204
|
+
return data;
|
|
205
|
+
} catch (error) {
|
|
206
|
+
Logger.error("Error getOrderFormById: ", error);
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Retrieves client information by email
|
|
213
|
+
* @param {string} email - Client's email address
|
|
214
|
+
* @param {string} accountName - VTEX account name
|
|
215
|
+
* @param {string} key - API authentication key
|
|
216
|
+
* @param {string} token - API authentication token
|
|
217
|
+
* @param {string} acronymClientVtex - Client data entity acronym in VTEX
|
|
218
|
+
* @returns {Promise<Object|null>} Client details or null if not found
|
|
219
|
+
* @throws {Error} Network or API connection errors
|
|
220
|
+
* @description Extracts client ID from email and fetches client details from VTEX master data
|
|
221
|
+
* @example
|
|
222
|
+
* const clientDetails = await getClientById('user@example.com', 'myAccount', 'apiKey', 'apiToken', 'CL');
|
|
223
|
+
* // Returns client object or null
|
|
224
|
+
*/
|
|
225
|
+
async function getClientById(email, accountName, key, token, acronymClientVtex) {
|
|
226
|
+
try {
|
|
227
|
+
const vtexApi = new VtexApi(accountName, key, token);
|
|
228
|
+
const clientId = email?.split("+")[1]?.split("@")[0];
|
|
229
|
+
const responseMasterDataCT = await vtexApi.fetch(
|
|
230
|
+
`/dataentities/${acronymClientVtex}/search?_fields=_all&id=${clientId}`, { method: "GET" }
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
if (responseMasterDataCT.status >= 200 && responseMasterDataCT.status < 300) {
|
|
234
|
+
return responseMasterDataCT.data[0];
|
|
235
|
+
} else {
|
|
236
|
+
Logger.error("Error getClientById: ", responseMasterDataCT);
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
} catch (error) {
|
|
240
|
+
Logger.error(error);
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Deletes custom data from an order form
|
|
247
|
+
* @param {string} orderFormId - Unique identifier of the order form
|
|
248
|
+
* @param {string} accountName - VTEX account name
|
|
249
|
+
* @param {string} key - API authentication key
|
|
250
|
+
* @param {string} token - API authentication token
|
|
251
|
+
* @param {Object} configVtex - VTEX configuration object
|
|
252
|
+
* @param {Object} attachmentCredit - Credit attachment configuration
|
|
253
|
+
* @param {Object} customData - Custom data to be deleted
|
|
254
|
+
* @returns {Promise<boolean>} Indicates successful deletion
|
|
255
|
+
* @throws {Error} Deletion process errors
|
|
256
|
+
* @description Removes specific custom data and credit attachments from an order form
|
|
257
|
+
* @example
|
|
258
|
+
* const deleted = await deleteCustomData('123456', 'myAccount', 'apiKey', 'apiToken', configVtex, attachmentCredit, customData);
|
|
259
|
+
* // Returns true if deletion is successful
|
|
260
|
+
*/
|
|
261
|
+
async function deleteCustomData(orderFormId, accountName, key, token, configVtex, attachmentCredit, customData) {
|
|
262
|
+
try {
|
|
263
|
+
if (!customData) {
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
const vtexApi = new VtexApi(accountName, key, token);
|
|
267
|
+
const customApps = customData?.customApps ?? [];
|
|
268
|
+
const financialPolicy = customApps?.find(app => app.id === configVtex.id);
|
|
269
|
+
const fields = financialPolicy?.fields;
|
|
270
|
+
|
|
271
|
+
if (attachmentCredit && attachmentCredit?.name && attachmentCredit?.value) {
|
|
272
|
+
await vtexApi.fetchPub(`/checkout/pub/orderForm/${orderFormId}/attachments/${attachmentCredit?.name}`, { method: "POST" }, { value: null });
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
for (const field in fields) {
|
|
276
|
+
await vtexApi.fetchPub(`/checkout/pub/orderForm/${orderFormId}/customData/${configVtex.id}/${field}`, { method: "DELETE" });
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return true;
|
|
280
|
+
} catch (error) {
|
|
281
|
+
Logger.error(error);
|
|
282
|
+
return ApiResponse.response(401, { approved: false, message: "Error deleting customData orderForm" });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Updates custom data in an order form
|
|
288
|
+
* @param {string} orderFormId - Unique identifier of the order form
|
|
289
|
+
* @param {string} accountName - VTEX account name
|
|
290
|
+
* @param {string} key - API authentication key
|
|
291
|
+
* @param {string} token - API authentication token
|
|
292
|
+
* @param {string} idConfigVtex - VTEX configuration ID
|
|
293
|
+
* @param {Object} customData - Custom data to be updated
|
|
294
|
+
* @param {Object} attachmentCredit - Credit attachment configuration
|
|
295
|
+
* @returns {Promise<Object|Error>} Updated order form data or error response
|
|
296
|
+
* @throws {Error} Update process errors
|
|
297
|
+
* @description Updates custom data and credit attachments in an order form
|
|
298
|
+
* @example
|
|
299
|
+
* const updatedData = await updateOrderFormCustomData('123456', 'myAccount', 'apiKey', 'apiToken', 'configId', customData, attachmentCredit);
|
|
300
|
+
* // Returns updated data or error response
|
|
301
|
+
*/
|
|
302
|
+
async function updateOrderFormCustomData(orderFormId, accountName, key, token, idConfigVtex, customData, attachmentCredit) {
|
|
303
|
+
try {
|
|
304
|
+
const vtexApi = new VtexApi(accountName, key, token);
|
|
305
|
+
const response = await vtexApi.fetchPub(
|
|
306
|
+
`/checkout/pub/orderForm/${orderFormId}/customData/${idConfigVtex}`,
|
|
307
|
+
{ method: "PUT" },
|
|
308
|
+
customData
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
if (attachmentCredit && attachmentCredit?.name && attachmentCredit?.value) {
|
|
312
|
+
await vtexApi.fetchPub(`/checkout/pub/orderForm/${orderFormId}/attachments/${attachmentCredit?.name}`, { method: "POST" }, attachmentCredit?.value);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (response.status !== 200){
|
|
316
|
+
Logger.error("Error updateOrderFormCustomData: ", response);
|
|
317
|
+
return ApiResponse.response(401, { approved: false, message: "Error updating customData orderForm" });
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return response.data;
|
|
321
|
+
} catch (error) {
|
|
322
|
+
Logger.error(error);
|
|
323
|
+
return ApiResponse.response(401, { approved: false, message: "Error updating customData orderForm" });
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Cleans custom data in an order form by resetting to default values
|
|
329
|
+
* @param {string} orderFormId - Unique identifier of the order form
|
|
330
|
+
* @param {string} accountName - VTEX account name
|
|
331
|
+
* @param {string} key - API authentication key
|
|
332
|
+
* @param {string} token - API authentication token
|
|
333
|
+
* @param {string} idConfigVtex - VTEX configuration ID for custom data
|
|
334
|
+
* @returns {Promise<Object>} Updated order form data or error response
|
|
335
|
+
* @throws {Error} API connection or update errors
|
|
336
|
+
* @description Resets custom data fields to default "clean" state
|
|
337
|
+
* @example
|
|
338
|
+
* const cleanedData = await cleanOrderFormCustomData('123456', 'myAccount', 'apiKey', 'apiToken', 'configId');
|
|
339
|
+
* // Returns cleaned order form data
|
|
340
|
+
*/
|
|
341
|
+
async function cleanOrderFormCustomData(orderFormId, accountName, key, token, idConfigVtex) {
|
|
342
|
+
try {
|
|
343
|
+
const vtexApi = new VtexApi(accountName, key, token,);
|
|
344
|
+
const customData = {
|
|
345
|
+
"approved": "false",
|
|
346
|
+
"withCredit": "false",
|
|
347
|
+
"paymentTerm": "-",
|
|
348
|
+
"maximumCreditAmount": "-",
|
|
349
|
+
"paymentMethodCode": "-",
|
|
350
|
+
"creditDays": "-",
|
|
351
|
+
"paymentMethodName": "-"
|
|
352
|
+
};
|
|
353
|
+
const response = await vtexApi.fetchPub(
|
|
354
|
+
`/checkout/pub/orderForm/${orderFormId}/customData/${idConfigVtex}`,
|
|
355
|
+
{ method: "PUT" },
|
|
356
|
+
customData
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
if (response.status !== 200){
|
|
360
|
+
Logger.error("Error cleanOrderFormCustomData: ", response);
|
|
361
|
+
return ApiResponse.response(401, { approved: false, message: "Error deleting customData orderForm" });
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return response.data;
|
|
365
|
+
} catch (error) {
|
|
366
|
+
Logger.error(error);
|
|
367
|
+
return ApiResponse.response(401, { approved: false, message: "Error cleaning customData orderForm" });
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Formats and validates financial policy service response
|
|
373
|
+
* @param {Object} rawResponse - Original service response
|
|
374
|
+
* @param {boolean} rawResponse.approved - Approval status
|
|
375
|
+
* @param {boolean} rawResponse.withCredit - Credit eligibility
|
|
376
|
+
* @param {number|string} rawResponse.creditDays - Credit days
|
|
377
|
+
* @param {number|string} rawResponse.maximumCreditAmount - Maximum credit amount
|
|
378
|
+
* @param {string} [rawResponse.paymentMethodCode] - Payment method code
|
|
379
|
+
* @param {string} [rawResponse.paymentMethodName] - Payment method name
|
|
380
|
+
* @returns {Object} Formatted response with standardized types
|
|
381
|
+
* @description Transforms raw financial policy response to a consistent format
|
|
382
|
+
* @example
|
|
383
|
+
* const formatted = formatFinancialPolicyResponse({
|
|
384
|
+
* approved: true,
|
|
385
|
+
* withCredit: true,
|
|
386
|
+
* creditDays: 30,
|
|
387
|
+
* maximumCreditAmount: 10000
|
|
388
|
+
* });
|
|
389
|
+
* // Returns standardized response object
|
|
390
|
+
*/
|
|
391
|
+
function formatFinancialPolicyResponse(rawResponse) {
|
|
392
|
+
try {
|
|
393
|
+
const formattedResponse = {
|
|
394
|
+
approved: Boolean(rawResponse.approved),
|
|
395
|
+
withCredit: Boolean(rawResponse.withCredit),
|
|
396
|
+
paymentTerm: Number(rawResponse.creditDays) || 0,
|
|
397
|
+
maximumCreditAmount: parseFloat(rawResponse.maximumCreditAmount) || 0,
|
|
398
|
+
paymentMethodCode: rawResponse.withCredit ? String(rawResponse.paymentMethodCode || 'CONTADO') : 'CONTADO',
|
|
399
|
+
creditDays: Number(rawResponse.creditDays) || 0,
|
|
400
|
+
paymentMethodName: rawResponse.withCredit ? String(rawResponse.paymentMethodName || 'CONTADO') : 'CONTADO'
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
return formattedResponse;
|
|
404
|
+
} catch (error) {
|
|
405
|
+
return getDefaultResponse();
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Collection of base data transformation functions
|
|
411
|
+
* @type {Object}
|
|
412
|
+
* @description Utility functions for converting values between types
|
|
413
|
+
*/
|
|
414
|
+
const baseTransforms = {
|
|
415
|
+
toString: value => String(value || ''),
|
|
416
|
+
toNumber: value => Number(value || 0),
|
|
417
|
+
toBoolean: value => Boolean(value),
|
|
418
|
+
toFloat: value => parseFloat(value || 0),
|
|
419
|
+
toInt: value => parseInt(value || 0, 10),
|
|
420
|
+
toOrderValue: value => Number(value || 0) / 100
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Applies a specified transformation to a value
|
|
425
|
+
* @param {*} value - Input value to transform
|
|
426
|
+
* @param {string} transformType - Type of transformation to apply
|
|
427
|
+
* @returns {*} Transformed value
|
|
428
|
+
* @description Applies a predefined transformation if the type exists
|
|
429
|
+
* @example
|
|
430
|
+
* applyTransform('123', 'toNumber'); // Returns 123
|
|
431
|
+
* applyTransform('true', 'toBoolean'); // Returns true
|
|
432
|
+
*/
|
|
433
|
+
function applyTransform(value, transformType) {
|
|
434
|
+
if (!transformType || !baseTransforms[transformType]) return value;
|
|
435
|
+
return baseTransforms[transformType](value);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Updates the schema for a VTEX data entity
|
|
440
|
+
* @param {string} accountName - VTEX account name
|
|
441
|
+
* @param {string} entityName - Name of the data entity
|
|
442
|
+
* @param {Object} schemaData - Schema configuration object
|
|
443
|
+
* @returns {Promise<Object>} Updated schema details
|
|
444
|
+
*/
|
|
445
|
+
async function updateDataEntitySchema(accountName, key, token, entityName, schemaData) {
|
|
446
|
+
try {
|
|
447
|
+
const vtexApi = new VtexApi(accountName, key, token);
|
|
448
|
+
const response = await vtexApi.fetch(
|
|
449
|
+
`/dataentities/${entityName}/schemas/default`,
|
|
450
|
+
{
|
|
451
|
+
method: "PUT",
|
|
452
|
+
headers: {
|
|
453
|
+
'Content-Type': 'application/json',
|
|
454
|
+
'Accept': 'application/vnd.vtex.ds.v2+json'
|
|
455
|
+
},
|
|
456
|
+
body: schemaData
|
|
457
|
+
}
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
return response.data;
|
|
461
|
+
} catch (error) {
|
|
462
|
+
Logger.error(`Error updating schema for ${entityName}:`, error);
|
|
463
|
+
throw error;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Creates a document in a VTEX data entity
|
|
469
|
+
* @param {string} accountName - VTEX account name
|
|
470
|
+
* @param {string} entityName - Name of the data entity
|
|
471
|
+
* @param {Object} documentData - Document data to create
|
|
472
|
+
* @returns {Promise<Object>} Created document details
|
|
473
|
+
*/
|
|
474
|
+
async function createDataEntityDocument(vtexApi, config, fileData) {
|
|
475
|
+
const documentData = {
|
|
476
|
+
fileName: fileData.fileName,
|
|
477
|
+
fileContent: fileData.fileContent,
|
|
478
|
+
isPublic: true,
|
|
479
|
+
contentType: 'text/csv'
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
try {
|
|
483
|
+
const response = await vtexApi.fetch(
|
|
484
|
+
`/dataentities/${config.fileUploadEntity}/documents`,
|
|
485
|
+
{
|
|
486
|
+
method: 'POST',
|
|
487
|
+
data: documentData,
|
|
488
|
+
headers: {
|
|
489
|
+
'Cache-Control': 'no-cache',
|
|
490
|
+
'Accept': 'application/vnd.vtex.ds.v10+json',
|
|
491
|
+
'Content-Type': 'application/json'
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
if (response.status !== 201) {
|
|
497
|
+
Logger.error(`Failed to create document: ${response.statusText}`);
|
|
498
|
+
throw new Error(`Failed to create document: ${response.statusText}`);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Generar URL pública
|
|
502
|
+
const publicUrl = `https://${config.AccountName}.vtexcommercestable.com.br/api/dataentities/${config.fileUploadEntity}/documents/${response.data.DocumentId}/attachments/${fileData.fileName}`;
|
|
503
|
+
|
|
504
|
+
return {
|
|
505
|
+
...response.data,
|
|
506
|
+
publicUrl
|
|
507
|
+
};
|
|
508
|
+
} catch (error) {
|
|
509
|
+
Logger.error(`Error creating document in ${config.fileUploadEntity}:`, error);
|
|
510
|
+
throw error;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Updates a specific document in a VTEX data entity
|
|
516
|
+
* @param {string} accountName - VTEX account name
|
|
517
|
+
* @param {string} entityName - Name of the data entity
|
|
518
|
+
* @param {string} documentId - ID of the document to update
|
|
519
|
+
* @param {Object} updateData - Data to update
|
|
520
|
+
* @returns {Promise<Object>} Updated document details
|
|
521
|
+
*/
|
|
522
|
+
async function updateDataEntityDocument(accountName, key, token, entityName, documentId, updateData) {
|
|
523
|
+
try {
|
|
524
|
+
const vtexApi = new VtexApi(accountName, key, token);
|
|
525
|
+
const response = await vtexApi.fetch(
|
|
526
|
+
`/dataentities/${entityName}/documents/${documentId}`,
|
|
527
|
+
{
|
|
528
|
+
method: "PATCH",
|
|
529
|
+
headers: {
|
|
530
|
+
'Content-Type': 'application/json',
|
|
531
|
+
'Accept': 'application/vnd.vtex.ds.v2+json'
|
|
532
|
+
},
|
|
533
|
+
body: updateData
|
|
534
|
+
}
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
return response.data;
|
|
538
|
+
} catch (error) {
|
|
539
|
+
Logger.error(`Error updating document in ${entityName}:`, error);
|
|
540
|
+
throw error;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Formatea y valida campos para la entidad de leads
|
|
546
|
+
* @param {Object} lead - Los datos del lead a formatear
|
|
547
|
+
* @param {Object} fieldMapping - El mapeo de campos configurado
|
|
548
|
+
* @returns {Object} Lead formateado y validado
|
|
549
|
+
*/
|
|
550
|
+
const formatLeadFields = (lead, fieldMapping) => {
|
|
551
|
+
let formattedLead = {};
|
|
552
|
+
|
|
553
|
+
// Procesar cada campo según el mapeo
|
|
554
|
+
for (const [outputField, inputConfig] of Object.entries(fieldMapping)) {
|
|
555
|
+
try {
|
|
556
|
+
if (typeof inputConfig === 'string') {
|
|
557
|
+
formattedLead[outputField] = baseTransforms.toString(lead[inputConfig] || '');
|
|
558
|
+
} else if (typeof inputConfig === 'object') {
|
|
559
|
+
const value = lead[inputConfig.field];
|
|
560
|
+
const transformer = new Function('value', `return ${inputConfig.transform}`);
|
|
561
|
+
formattedLead[outputField] = transformer(value);
|
|
562
|
+
}
|
|
563
|
+
} catch (error) {
|
|
564
|
+
Logger.error(`Error formatting field ${outputField}:`, error);
|
|
565
|
+
formattedLead[outputField] = '';
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return formattedLead;
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Genera una URL de descarga para un documento en MasterData
|
|
574
|
+
* @param {string} accountName - Nombre de la cuenta VTEX
|
|
575
|
+
* @param {string} documentId - ID del documento
|
|
576
|
+
* @param {string} entity - Nombre de la entidad
|
|
577
|
+
* @param {string} [environment='vtexcommercestable'] - Ambiente VTEX
|
|
578
|
+
* @returns {string} URL de descarga del documento
|
|
579
|
+
*/
|
|
580
|
+
const generateMasterDataDownloadUrl = (accountName, documentId, entity, environment = 'vtexcommercestable') => {
|
|
581
|
+
return `https://${accountName}.${environment}.com.br/api/dataentities/${entity}/documents/${documentId}/file`;
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Función para transformar datos entre diferentes formatos
|
|
586
|
+
* @param {*} value - Valor a transformar
|
|
587
|
+
* @param {string} transformType - Tipo de transformación a aplicar
|
|
588
|
+
* @returns {*} Valor transformado
|
|
589
|
+
*/
|
|
590
|
+
const transformLeadData = (value, transformType) => {
|
|
591
|
+
if (!transformType || !baseTransforms[transformType]) {
|
|
592
|
+
return value;
|
|
593
|
+
}
|
|
594
|
+
return baseTransforms[transformType](value);
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Valida el formato y la estructura de un lead
|
|
599
|
+
* @param {Object} lead - Lead a validar
|
|
600
|
+
* @param {Object} requiredFields - Campos requeridos y sus validaciones
|
|
601
|
+
* @returns {Object} Resultado de la validación
|
|
602
|
+
*/
|
|
603
|
+
const validateLead = (lead, requiredFields) => {
|
|
604
|
+
const errors = [];
|
|
605
|
+
|
|
606
|
+
for (const [field, validation] of Object.entries(requiredFields)) {
|
|
607
|
+
const value = lead[field];
|
|
608
|
+
|
|
609
|
+
if (validation.required && !value) {
|
|
610
|
+
errors.push(`Campo ${field} es requerido`);
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
if (validation.regex && value) {
|
|
615
|
+
const regex = new RegExp(validation.regex);
|
|
616
|
+
if (!regex.test(value)) {
|
|
617
|
+
errors.push(`Campo ${field} tiene formato inválido`);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
if (validation.maxLength && value && value.length > validation.maxLength) {
|
|
622
|
+
errors.push(`Campo ${field} excede el máximo de ${validation.maxLength} caracteres`);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
return {
|
|
627
|
+
isValid: errors.length === 0,
|
|
628
|
+
errors
|
|
629
|
+
};
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Función para generar el nombre del archivo CSV de leads
|
|
634
|
+
* @param {string} accountName - Nombre de la cuenta
|
|
635
|
+
* @param {string} dateRange - Rango de fechas del reporte
|
|
636
|
+
* @returns {string} Nombre del archivo formateado
|
|
637
|
+
*/
|
|
638
|
+
const generateLeadReportFileName = (accountName, dateRange) => {
|
|
639
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
640
|
+
return `new-leads-${accountName}-${dateRange}-${timestamp}.csv`;
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Función para validar la configuración de leads de una cuenta
|
|
645
|
+
* @param {Object} config - Configuración a validar
|
|
646
|
+
* @returns {Object} Resultado de la validación
|
|
647
|
+
*/
|
|
648
|
+
const validateLeadsConfig = (config) => {
|
|
649
|
+
const requiredFields = [
|
|
650
|
+
'newLeadsEntity',
|
|
651
|
+
'fileUploadEntity',
|
|
652
|
+
'leadMap'
|
|
653
|
+
];
|
|
654
|
+
|
|
655
|
+
const errors = [];
|
|
656
|
+
|
|
657
|
+
for (const field of requiredFields) {
|
|
658
|
+
if (!config[field]) {
|
|
659
|
+
errors.push(`Missing required field: ${field}`);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
if (config.leadMap && typeof config.leadMap !== 'object') {
|
|
664
|
+
errors.push('leadMap must be an object');
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
return {
|
|
668
|
+
isValid: errors.length === 0,
|
|
669
|
+
errors
|
|
670
|
+
};
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
module.exports = {
|
|
674
|
+
list_products_vtex,
|
|
675
|
+
list_categories_vtex,
|
|
676
|
+
list_brands_vtex,
|
|
677
|
+
getOrderFormById,
|
|
678
|
+
getClientById,
|
|
679
|
+
deleteCustomData,
|
|
680
|
+
updateOrderFormCustomData,
|
|
681
|
+
cleanOrderFormCustomData,
|
|
682
|
+
formatFinancialPolicyResponse,
|
|
683
|
+
baseTransforms,
|
|
684
|
+
applyTransform,
|
|
685
|
+
updateDataEntitySchema,
|
|
686
|
+
createDataEntityDocument,
|
|
687
|
+
updateDataEntityDocument,
|
|
688
|
+
formatLeadFields,
|
|
689
|
+
generateMasterDataDownloadUrl,
|
|
690
|
+
transformLeadData,
|
|
691
|
+
validateLead,
|
|
692
|
+
generateLeadReportFileName,
|
|
693
|
+
validateLeadsConfig
|
|
694
|
+
};
|