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,77 @@
|
|
|
1
|
+
const VtexApi = require('../../vtex/clients/VtexApi');
|
|
2
|
+
const Logger = require("../../common/utils/logger");
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Handles the event triggered by the Lambda function.
|
|
6
|
+
*
|
|
7
|
+
* @param {Object} event - The event object containing the request details.
|
|
8
|
+
* @returns {Promise<Object>} - A promise that resolves to the response object.
|
|
9
|
+
* @throws {Error} - If an error occurs during the execution.
|
|
10
|
+
*/
|
|
11
|
+
module.exports.handler= async (event)=>{
|
|
12
|
+
let statusCode = 200;
|
|
13
|
+
let response = {};
|
|
14
|
+
for (const record of event.Records) {
|
|
15
|
+
Logger.debug("Message Body: ", record.body);
|
|
16
|
+
try {
|
|
17
|
+
const order = JSON.parse(record.body);
|
|
18
|
+
const AccountConfig = order?.accountConfig;
|
|
19
|
+
const AccountConfigParent = order?.accountConfigParent;
|
|
20
|
+
const orderId = order?.orderInfo?.OrderId;
|
|
21
|
+
const vtexApiChild = new VtexApi(AccountConfig.AccountName, AccountConfig.Credentials.key, AccountConfig.Credentials.token);
|
|
22
|
+
const vtexApiParent = new VtexApi(AccountConfigParent.AccountName, AccountConfigParent.Credentials.key, AccountConfigParent.Credentials.token);
|
|
23
|
+
const responseOrderInfoChild = await vtexApiChild.fetch(`/oms/pvt/orders/${orderId}`, { method: "GET" });
|
|
24
|
+
const responseOrderInfoParent = await vtexApiParent.fetch(`/oms/pvt/orders/${responseOrderInfoChild?.data?.marketplaceOrderId}`, { method: "GET" });
|
|
25
|
+
if (!responseOrderInfoParent || responseOrderInfoParent.status !== 200) {
|
|
26
|
+
statusCode = 404;
|
|
27
|
+
response = { error: responseOrderInfoParent };
|
|
28
|
+
Logger.error({ statusCode, response});
|
|
29
|
+
}
|
|
30
|
+
const email = responseOrderInfoParent?.data?.clientProfileData?.email;
|
|
31
|
+
const responseMailParent = await vtexApiParent.fetchOrderMail(email);
|
|
32
|
+
const clientId = responseMailParent?.data?.email?.split("+")[1]?.split("@")[0];
|
|
33
|
+
Logger.setAccount(AccountConfig)
|
|
34
|
+
if(!clientId){
|
|
35
|
+
statusCode = 404;
|
|
36
|
+
response = { error: `Client not found, email: ${email}` };
|
|
37
|
+
Logger.error(statusCode, response);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const responseMasterDataCT = await vtexApiParent.fetch(
|
|
41
|
+
`/dataentities/${AccountConfig.AcronymClientVtex}/search?_fields=_all&id=${clientId}`, { method: "GET" }
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if (!responseMasterDataCT || responseMasterDataCT.status !== 200 || !responseMasterDataCT?.data?.length > 0) {
|
|
45
|
+
statusCode = 404;
|
|
46
|
+
response = { error: responseMasterDataCT };
|
|
47
|
+
Logger.error(statusCode, response);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let additionalFields = {
|
|
51
|
+
id : orderId,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const fields = AccountConfig?.AdditionalInfoOrderFromClient?.fields || [];
|
|
55
|
+
const data = responseMasterDataCT?.data[0] || {};
|
|
56
|
+
|
|
57
|
+
fields.forEach(field => {
|
|
58
|
+
additionalFields[field] = data[field] || ""; // Asigna el valor correspondiente o un string vacío si no existe
|
|
59
|
+
});
|
|
60
|
+
Logger.debug({ additionalFields });
|
|
61
|
+
const updateAdditionalFields = await vtexApiChild.fetch(
|
|
62
|
+
`/dataentities/${AccountConfig.AdditionalInfoOrderFromClient.nameEntity}/documents/`, { method: "PATCH", data: additionalFields });
|
|
63
|
+
|
|
64
|
+
if (!updateAdditionalFields && (updateAdditionalFields.status !== 200 || updateAdditionalFields.status !== 201 || updateAdditionalFields.status !== 204)) {
|
|
65
|
+
statusCode = 404;
|
|
66
|
+
response = { error: updateAdditionalFields };
|
|
67
|
+
Logger.error(statusCode, response);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
Logger.debug(statusCode, { additionalFields });
|
|
71
|
+
}catch (error) {
|
|
72
|
+
Logger.error(error);
|
|
73
|
+
statusCode = 500;
|
|
74
|
+
response = { error: error.message };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const Apiresponse = require('../../../common/utils/api-response.js');
|
|
2
|
+
const {
|
|
3
|
+
handlePutRecordSchema,
|
|
4
|
+
handleGetRecordSchema,
|
|
5
|
+
handleDeleteRecordSchema
|
|
6
|
+
} = require('../../../common/utils/schemas-utils.js');
|
|
7
|
+
const { handleSchemaVtexMD2 } = require('../../../common/utils/vtex/save-schemas.js');
|
|
8
|
+
const { handleHookVtexMD2 } = require('../../../common/utils/vtex/save-hooks.js');
|
|
9
|
+
|
|
10
|
+
const AccountData = require("../../../entities/account.js");
|
|
11
|
+
|
|
12
|
+
const { SCHEMAS_VTEX_TABLE, HOOKS_VTEX_TABLE } = process?.env ?? {};
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
module.exports.handler = async (event) => {
|
|
16
|
+
const schemaName = event?.pathParameters?.SchemaName ?? '';
|
|
17
|
+
const hookName = event?.pathParameters?.HookName ?? '';
|
|
18
|
+
const httpMethod = event?.httpMethod?.toUpperCase();
|
|
19
|
+
const account = event?.queryStringParameters;
|
|
20
|
+
const body = parseRequestBody(event?.body);
|
|
21
|
+
|
|
22
|
+
const arrPath = event.resource.split('/')
|
|
23
|
+
const [resource, identifier, provider] = arrPath.filter(part => part !== '')
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
if (identifier === 'schemas' && provider === 'vtex') {
|
|
27
|
+
return await handleRequest(schemaName, httpMethod, account, body, SCHEMAS_VTEX_TABLE, identifier)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (identifier === 'hooks' && provider === 'vtex') {
|
|
31
|
+
return await handleRequest(hookName, httpMethod, account, body, HOOKS_VTEX_TABLE, identifier)
|
|
32
|
+
}
|
|
33
|
+
return Apiresponse.response(404, `Resource: ${identifier} not found`)
|
|
34
|
+
} catch (error) {
|
|
35
|
+
return Apiresponse.response(500, `Internal Server Error: ${error.message}`);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const handleRequest = async (id, httpMethod, account, body, tableName, identifier) => {
|
|
40
|
+
switch (httpMethod) {
|
|
41
|
+
case 'PUT':
|
|
42
|
+
return await handlePutRecordSchema(id, body, tableName, identifier);
|
|
43
|
+
|
|
44
|
+
case 'GET':
|
|
45
|
+
return await handleGetRecordSchema({ id, tableName, identifier });
|
|
46
|
+
|
|
47
|
+
case 'DELETE':
|
|
48
|
+
if (identifier === 'schemas') {
|
|
49
|
+
if (account?.an && account?.entity) {
|
|
50
|
+
const accountConfig = await getAccountConfig(account.an);
|
|
51
|
+
return await handleSchemaVtexMD2({
|
|
52
|
+
id,
|
|
53
|
+
entityName: account.entity,
|
|
54
|
+
data: {},
|
|
55
|
+
origin: accountConfig,
|
|
56
|
+
httpMethod,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (identifier === 'hooks') {
|
|
62
|
+
if (account?.an) {
|
|
63
|
+
const accountConfig = await getAccountConfig(account.an);
|
|
64
|
+
return await handleHookVtexMD2({
|
|
65
|
+
id,
|
|
66
|
+
data: {},
|
|
67
|
+
origin: accountConfig,
|
|
68
|
+
httpMethod,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return await handleDeleteRecordSchema({ id, tableName, identifier });
|
|
74
|
+
|
|
75
|
+
default:
|
|
76
|
+
return Apiresponse.response(405, `Method ${httpMethod} not allowed`);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const getAccountConfig = async (accountName) => {
|
|
81
|
+
const accountConfig = await AccountData.getAccountDataByAccountName(accountName);
|
|
82
|
+
if (!accountConfig) {
|
|
83
|
+
throw new Error(`Account configuration not found for account: ${accountName}`);
|
|
84
|
+
}
|
|
85
|
+
const { AccountName, Credentials } = accountConfig;
|
|
86
|
+
if (!AccountName || !Credentials?.key || !Credentials?.token) {
|
|
87
|
+
throw new Error(`Incomplete account configuration for account: ${accountName}`);
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
AccountName,
|
|
91
|
+
AppKey: Credentials.key,
|
|
92
|
+
AppToken: Credentials.token,
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const parseRequestBody = (body) => {
|
|
97
|
+
try {
|
|
98
|
+
return body ? JSON.parse(body) : {};
|
|
99
|
+
} catch (error) {
|
|
100
|
+
throw new Error("Invalid JSON body format.");
|
|
101
|
+
}
|
|
102
|
+
};
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Funciones usadas en GAS (Google Apps Script) para ejecutar la actualización
|
|
3
|
+
* de roles con base a la información enviada por correo electrónico.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Se obtiene la referencia a las propiedades del script
|
|
7
|
+
const propsServices = PropertiesService.getScriptProperties();
|
|
8
|
+
const {
|
|
9
|
+
email_subject = 'Roles process',
|
|
10
|
+
auth_username,
|
|
11
|
+
auth_password,
|
|
12
|
+
auth_url,
|
|
13
|
+
service_url,
|
|
14
|
+
from_name = 'User roles manager',
|
|
15
|
+
limit_emails = 5
|
|
16
|
+
} = propsServices.getProperties();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Función callback del trigger configurado en Activadores(Triggers)
|
|
20
|
+
*/
|
|
21
|
+
function callbackTrigger() {
|
|
22
|
+
// Si se desea pausar la ejecución automática, se debe comentar el llamado a la función readEmails()
|
|
23
|
+
readEmails();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Función que se encarga de ejecutar el proceso de consultar los mensajes de correo para ejecutar la actualización de roles.
|
|
28
|
+
*/
|
|
29
|
+
function readEmails() {
|
|
30
|
+
// Se consulta los mensajes de correo sin leer y que tenga el asunto configurado en la propiedad 'email_subject'
|
|
31
|
+
const threads = GmailApp.search(`is:unread subject:(${email_subject})`);
|
|
32
|
+
if (!threads.length) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Se obtiene el token de autenticación para ejecutar el servicio
|
|
37
|
+
let authResponse = getAuthToken();
|
|
38
|
+
|
|
39
|
+
// Contador de correos electrónicos
|
|
40
|
+
let counter = 0;
|
|
41
|
+
|
|
42
|
+
// Se consulta la lista de mensajes en cada uno de los hilos de mensajes
|
|
43
|
+
for (let thread of threads) {
|
|
44
|
+
// Se obtiene los mensajes de cada uno de los hilos
|
|
45
|
+
const messages = thread.getMessages();
|
|
46
|
+
for (const message of messages) {
|
|
47
|
+
const messageId = message.getId();
|
|
48
|
+
// Si el mensaje está sin leer, se ejecuta el proceso
|
|
49
|
+
if (message.isUnread()) {
|
|
50
|
+
// Si el contador no ha llegado al límite de correos
|
|
51
|
+
if (counter < limit_emails) {
|
|
52
|
+
// Se obtiene el email de quien envía el mensaje y los archivos adjuntos
|
|
53
|
+
let { name, email } = getFromMail(message), attachments = message.getAttachments();
|
|
54
|
+
if (email) {
|
|
55
|
+
// Se obtiene el template HTML del mensaje de correo
|
|
56
|
+
let templateEmail = HtmlService.createTemplateFromFile('EmailTemplate');
|
|
57
|
+
templateEmail.username = name;
|
|
58
|
+
|
|
59
|
+
// Se valida el número de archivos adjuntos
|
|
60
|
+
if (attachments.length == 1) {
|
|
61
|
+
executeService(authResponse, message, templateEmail, email, attachments[0]);
|
|
62
|
+
} else {
|
|
63
|
+
templateEmail.message = attachments.length == 0 ?
|
|
64
|
+
'Su solicitud no pudo ser procesada, debido a que el correo no contiene un archivo adjunto.' :
|
|
65
|
+
`Su solicitud no pudo ser procesada, debido a que el correo contiene más de un archivo adjunto (${attachments.length}).`;
|
|
66
|
+
sendEmailNotification(message, templateEmail, email);
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
console.error(`Email message ${messageId} without from email address`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Se marca el correo como leido
|
|
73
|
+
message.markRead();
|
|
74
|
+
counter++;
|
|
75
|
+
} else {
|
|
76
|
+
// Si el contador de correos supera el límite, se finaliza el loop de threads
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Si el contador de correos supera el límite, se finaliza el loop de threads
|
|
84
|
+
if (counter >= limit_emails) {
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Obtiene el token de autenticación para ejecutar el servicio que se encarga de actualizar los roles de usuario.
|
|
92
|
+
* @return Objeto JSON con la respuesta de la API.
|
|
93
|
+
*/
|
|
94
|
+
function getAuthToken() {
|
|
95
|
+
// Token de autenticación Basic para ejecutar la autenticación al servicio
|
|
96
|
+
const basicToken = Utilities.base64Encode(auth_username + ':' + auth_password);
|
|
97
|
+
|
|
98
|
+
// Petición a la API de autenticación del servicio en Monaliza v2
|
|
99
|
+
let authRequest = UrlFetchApp.fetch(auth_url, {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
headers: { 'Authorization': `Basic ${basicToken}` },
|
|
102
|
+
payload: {
|
|
103
|
+
'grant_type': 'client_credentials',
|
|
104
|
+
'scope': 'vtex.rol/vtex.rol.read'
|
|
105
|
+
},
|
|
106
|
+
// Se agrega este parámetro para que no se dispare la excepción en caso que la petición falle
|
|
107
|
+
muteHttpExceptions: true
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
let responseCode = authRequest.getResponseCode(), responseText = authRequest.getContentText();
|
|
111
|
+
if (responseCode !== 200) {
|
|
112
|
+
throw new Error(`Error ${responseCode}: `, responseText);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Se obtiene el token de la respuesta de la petición
|
|
116
|
+
return JSON.parse(responseText);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Ejecuta el servicio encargado de actualizar los roles de usuario.
|
|
121
|
+
* @param {object} authResponse Objeto JSON con el token de autenticación.
|
|
122
|
+
* @param {GmailApp.GmailMessage} message Referencia al mensaje de correo enviado.
|
|
123
|
+
* @param {HtmlService.HtmlTemplate} templateEmail Referencia al template a usar en el cuerpo del correo electrónico.
|
|
124
|
+
* @param {string} email Dirección de correo del remitente.
|
|
125
|
+
* @param {GmailApp.GmailAttachment} attachment Archivo adjunto del correo electrónico.
|
|
126
|
+
*/
|
|
127
|
+
function executeService(authResponse, message, templateEmail, email, attachment) {
|
|
128
|
+
const boundary = 'googleAppsScriptBoundary';
|
|
129
|
+
// Se obtiene el nombre y tipo del archivo adjunto a enviar al servicio de actualización de roles
|
|
130
|
+
const fileName = attachment.getName(), fileType = attachment.getContentType();
|
|
131
|
+
// Content para el email del remitente
|
|
132
|
+
let emailData = '';
|
|
133
|
+
emailData += `--${boundary}\r\n`;
|
|
134
|
+
emailData += `Content-Disposition: form-data; name="email"\r\n\r\n`;
|
|
135
|
+
emailData += `${email}\r\n`;
|
|
136
|
+
|
|
137
|
+
// Se define el blob para el campo email
|
|
138
|
+
let emailFieldBlob = Utilities.newBlob(emailData).getBytes();
|
|
139
|
+
|
|
140
|
+
// Content para el archivo adjunto
|
|
141
|
+
let fileData = '';
|
|
142
|
+
fileData += `--${boundary}\r\n`;
|
|
143
|
+
fileData += `Content-Disposition: form-data; name="file"; filename="${fileName}"\r\n`;
|
|
144
|
+
fileData += `Content-Type: ${fileType}\r\n\r\n`;
|
|
145
|
+
|
|
146
|
+
// Se define el blob para el campo del archivo adjunto
|
|
147
|
+
let fileFieldBlob = Utilities.newBlob(fileData).getBytes().concat(attachment.copyBlob().getBytes());
|
|
148
|
+
|
|
149
|
+
// Se define el cuerpo de la petición con el email del remitente y la data del archivo adjunto, concatenando el cierre del bloque
|
|
150
|
+
let payload = emailFieldBlob.concat(fileFieldBlob)
|
|
151
|
+
.concat(Utilities.newBlob(`\r\n--${boundary}--`).getBytes());
|
|
152
|
+
const serviceRequest = UrlFetchApp.fetch(service_url, {
|
|
153
|
+
method: 'POST',
|
|
154
|
+
headers: { 'Authorization': `Bearer ${authResponse.access_token}` },
|
|
155
|
+
contentType: `multipart/form-data; boundary=${boundary}`,
|
|
156
|
+
payload: payload,
|
|
157
|
+
// Se agrega este parámetro para que no se dispare la excepción en caso que la petición falle
|
|
158
|
+
muteHttpExceptions: true,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Se obtiene el código y cuerpo de la respuesta de la petición.
|
|
162
|
+
const serviceResponseCode = serviceRequest.getResponseCode();
|
|
163
|
+
// Se obtiene la respuesta de la petición en formato JSON
|
|
164
|
+
let serviceResponse = JSON.parse(serviceRequest.getContentText());
|
|
165
|
+
|
|
166
|
+
// Se establece el texto del cuerpo del mensaje de respuesta
|
|
167
|
+
templateEmail.message = serviceResponseCode == 200 ?
|
|
168
|
+
'Su solicitud ha sido procesada satisfactoriamente. En el archivo adjunto podrá encontrar el resumen de ejecución.' :
|
|
169
|
+
'Su solicitud no pudo ser sido procesada satisfactoriamente. En el archivo adjunto podrá encontrar el detalle del error presentado.';
|
|
170
|
+
|
|
171
|
+
sendEmailNotification(message, templateEmail, email, [
|
|
172
|
+
Utilities.newBlob(JSON.stringify(serviceResponse, null, 2), 'application/json', 'ServiceResponse.json')
|
|
173
|
+
]);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Ejecuta el proceso de responder un mensaje de correo electrónico.
|
|
178
|
+
* @param {GmailApp.GmailMessage} message Referencia al mensaje de correo enviado.
|
|
179
|
+
* @param {HtmlService.HtmlTemplate} templateEmail Referencia al template a usar en el cuerpo del correo electrónico.
|
|
180
|
+
* @param {string} email Dirección de correo del remitente.
|
|
181
|
+
* @param {GmailApp.GmailAttachment[]} attachments Archivos adjuntos al correo de respuesta.
|
|
182
|
+
*/
|
|
183
|
+
function sendEmailNotification(message, templateEmail, email, attachments = null) {
|
|
184
|
+
let params = {
|
|
185
|
+
// Cuerpo del mensaje en formato HTML
|
|
186
|
+
htmlBody: templateEmail.evaluate().getContent(),
|
|
187
|
+
// Nombre de quien responde el correo
|
|
188
|
+
name: from_name,
|
|
189
|
+
// Parámetro para que en el correo se incluya el noreply@dominio.com
|
|
190
|
+
noReply: true
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Se valida si se incluye archivos adjuntos en la respuesta del correo
|
|
194
|
+
if (attachments?.length) {
|
|
195
|
+
params.attachments = attachments;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Se responde el mensaje
|
|
199
|
+
let replyEmail = message.reply('', params);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Extrae el nombre y dirección de correo electrónico del remitente del mensaje.
|
|
204
|
+
* @param {GmailApp.GmailMessage} message Mensaje de correo electrónico.
|
|
205
|
+
* @return Nombre y dirección de correo electrónico del remitente.
|
|
206
|
+
*/
|
|
207
|
+
function getFromMail(message) {
|
|
208
|
+
let sender = message.getFrom();
|
|
209
|
+
if (sender) {
|
|
210
|
+
let match = sender.match(/"*(.+)"* <(.+)>/);
|
|
211
|
+
if (match?.length == 3) {
|
|
212
|
+
const [, name, email] = match;
|
|
213
|
+
if (name && email) {
|
|
214
|
+
return { name, email };
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return { name: 'Usuario', email: sender };
|
|
219
|
+
}
|
|
220
|
+
return {};
|
|
221
|
+
}
|