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,74 @@
1
+ "use strict";
2
+ const ClientData = require("../../entities/clients");
3
+ const AccountData = require("../../entities/account");
4
+ const OrderData = require("../../entities/orders");
5
+ const VtexApi = require("../../vtex/clients/VtexApi");
6
+ const ApiResponse = require("../../common/utils/api-response");
7
+ const Logger = require("../../common/utils/logger");
8
+
9
+ const cancel = async (event) => {
10
+ const orderId = event.pathParameters?.orderId;
11
+ const clientId = event.requestContext?.authorizer?.claims?.client_id;
12
+ const scope = event?.requestContext?.authorizer?.claims?.scope;
13
+ ApiResponse.validateRequiredParam("ClientId", clientId);
14
+ ApiResponse.validateRequiredParam("OrderId", orderId);
15
+ const dataOrder = await OrderData.getOrderDataByOrderId(orderId);
16
+ if (!dataOrder || dataOrder.length === 0) {
17
+ return ApiResponse.response(404, "Order not found");
18
+ }
19
+ for (let i = 0; i < dataOrder.length; i++) {
20
+ const accountNameForOrder = dataOrder[i].AccountNameForOrder;
21
+ const acountValid = scope.includes("admin")
22
+ ? true
23
+ : await ClientData.validateAccount(clientId, accountNameForOrder);
24
+ if (acountValid) {
25
+ const accountData = await AccountData.getAccountDataByAccountName(accountNameForOrder);
26
+ const apiClient = new VtexApi(
27
+ accountData.AccountName,
28
+ accountData.Credentials?.key,
29
+ accountData.Credentials?.token
30
+ );
31
+ Logger.setAccount(accountData);
32
+ let reason = "Orden cancelada";
33
+ if(event?.body && event.body != ''){
34
+ try{
35
+ reason = JSON.parse(event.body)?.reason ?? "Orden cancelada";
36
+ }catch (e){
37
+ Logger.error(e);
38
+ reason = "Orden cancelada";
39
+ }
40
+ }
41
+ Logger.debug("VTEX API Client: ", apiClient);
42
+ const response = await apiClient.fetch(`/oms/pvt/orders/${orderId}/cancel`, {
43
+ method: "POST",
44
+ data: {
45
+ reason: reason,
46
+ },
47
+ });
48
+
49
+ if (response.status >= 200 || response.status < 300) {
50
+ const responseConfirm = await apiClient.fetch(`/oms/pvt/orders/${orderId}/cancel`, {
51
+ method: "POST",
52
+ data: {
53
+ reason: reason,
54
+ },
55
+ });
56
+ if (responseConfirm.status !== 200) {
57
+ return ApiResponse.response(200, "Order already cancelled");
58
+ }else{
59
+ return ApiResponse.response(response.status, "Order cancelled");
60
+ }
61
+ }else{
62
+ return ApiResponse.response(response.status, "Order cancelled");
63
+ }
64
+ } else {
65
+ Logger.error("Data INVALID: ", acountValid);
66
+ return ApiResponse.response(401, "Account not valid!");
67
+ }
68
+ }
69
+ return ApiResponse.response(500, "Internal Server Error");
70
+ };
71
+
72
+ module.exports = {
73
+ cancel,
74
+ };
@@ -0,0 +1,280 @@
1
+ "use strict";
2
+ const ClientData = require("../../entities/clients");
3
+ const OrderData = require("../../entities/orders");
4
+ const AccountData = require("../../entities/account");
5
+ const VtexApi = require("../../vtex/clients/VtexApi");
6
+ const ApiResponse = require("../../common/utils/api-response");
7
+ const Convert = require("../../common/MondelezCastOrder");
8
+ const TaxPromotionsData = require("../../entities/taxpromotion");
9
+ const Logger = require("../../common/utils/logger");
10
+ /**
11
+ *
12
+ * @param {import("aws-lambda").APIGatewayProxyEvent} event
13
+ * @returns
14
+ */
15
+ const getOrders = async (event) => {
16
+ try {
17
+ //Modify this search data
18
+
19
+ const clientId = event?.requestContext?.authorizer?.claims?.client_id;
20
+ const orderId = event?.pathParameters?.orderId;
21
+
22
+ const order = await OrderData.getOrderDataByOrderId(orderId);
23
+ if (!order) {
24
+ return ApiResponse.response(404, "Order not found");
25
+ }
26
+ Logger.log("Order: ", orderId);
27
+ for (let i = 0; i < order.length; i++) {
28
+ const accountNameForOrder = order[i].AccountNameForOrder;
29
+ const validateAccount = await ClientData.validateAccount(clientId, accountNameForOrder);
30
+ if (validateAccount) {
31
+ const data = await AccountData.getAccountDataByAccountName(accountNameForOrder);
32
+ const parentAccount = await AccountData.getAccountDataByAccountName(data.ParentAccountName);
33
+ Logger.setAccount(parentAccount);
34
+ if (data && parentAccount) {
35
+ const apiClient = new VtexApi(data?.AccountName, data?.Credentials?.key, data?.Credentials?.token);
36
+ const apiClientParent = new VtexApi(
37
+ parentAccount?.AccountName,
38
+ parentAccount?.Credentials?.key,
39
+ parentAccount?.Credentials?.token
40
+ );
41
+ Logger.debug("VTEX API Client: ", apiClient);
42
+ const response = await apiClient.fetch(`/oms/pvt/orders/${orderId}`, {
43
+ method: "GET",
44
+ });
45
+ Logger.debug("Response order: ", response);
46
+ if (response.status >= 200 && response.status < 300) {
47
+ Logger.debug("Response: ", response.data);
48
+ const parentOrderId = response?.data?.marketplaceOrderId;
49
+ if (!parentOrderId) {
50
+ return ApiResponse.response(404, "Order not found. Parent Order ID not found");
51
+ }
52
+ const responseParent = await apiClientParent.fetch(`/oms/pvt/orders/${parentOrderId}`, {
53
+ method: "GET",
54
+ });
55
+ if (responseParent.status >= 200 && responseParent.status < 300) {
56
+ Logger.debug("Response Parent: ", responseParent.data);
57
+ const orderDataAndPromotionERP = data?.BindIdExternalPromotion === true ? await TaxPromotionsData.bindIdExternalPromotionToOrderData(responseParent.data) : responseParent.data;
58
+ let orderMondelez = Convert.orderToJson(response.data, orderDataAndPromotionERP, data);
59
+ let email = orderMondelez?.clientProfileData?.email;
60
+ Logger.debug("Email: ", email, typeof email);
61
+ if (email) {
62
+ try {
63
+ const responseMailParent = await apiClientParent.fetchOrderMail(email);
64
+ Logger.debug("Mail Parent: ", responseMailParent);
65
+ Logger.debug("Mail Parent: ", responseMailParent?.data?.email);
66
+ orderMondelez.clientProfileData.email = responseMailParent?.data?.email;
67
+ } catch (error) {
68
+ Logger.error(error);
69
+ }
70
+ }
71
+ //obtener cliente Masterdat VTEX
72
+ const idCT = (orderMondelez?.clientProfileData?.email)?.split("+")[1]?.split("@")[0].toString();
73
+ const responseCT = await apiClientParent.fetch(`/dataentities/${data?.AcronymClientVtex}/search?_fields=_all&id=${idCT}`, {
74
+ method: "GET",
75
+ });
76
+
77
+ orderMondelez.clientProfileData.customerClassTwo = null;
78
+ orderMondelez.clientProfileData.customerID = null;
79
+ orderMondelez.clientProfileData.pdv = null;
80
+ if (responseCT.status >= 200 && responseCT.status < 300 && responseCT.data && responseCT.data.length > 0) {
81
+ orderMondelez.clientProfileData.customerClassTwo = responseCT.data[0].customerClassTwo;
82
+ orderMondelez.clientProfileData.customerID = responseCT?.data[0]?.pdv;
83
+ orderMondelez.clientProfileData.pdv = responseCT?.data[0]?.pdv;
84
+ orderMondelez.clientProfileData.priceTables = responseCT?.data[0]?.priceTables;
85
+ }
86
+
87
+ //obtener campos adicionales
88
+ try {
89
+ const fieldsAdditionalInfo = data?.AdditionalInfoOrderFromClient?.fields?.join(",");
90
+ const responseAdditionalInfo = fieldsAdditionalInfo && fieldsAdditionalInfo !== "" ? await apiClient.fetch(`/dataentities/${data?.AdditionalInfoOrderFromClient?.nameEntity}/documents/${orderId}?_fields=${fieldsAdditionalInfo}`, {
91
+ method: "GET",
92
+ }) : { status: 200, data: [] };
93
+
94
+ Logger.debug("responseAdditionalInfo: ", responseAdditionalInfo);
95
+ Logger.debug("responseCT: ", responseCT);
96
+
97
+ if (responseAdditionalInfo?.status >= 200 && responseAdditionalInfo?.status < 300 && responseAdditionalInfo?.data) {
98
+ const dataItems = responseAdditionalInfo?.data ?? {};
99
+ for (const dataItem in dataItems) {
100
+ Logger.debug("dataItem: ", dataItem);
101
+ orderMondelez.clientProfileData[dataItem] = dataItems[dataItem] ?? responseCT?.data[0]?.[dataItem] ?? null;
102
+ }
103
+ } else {
104
+ for (let j = 0; j < data?.AdditionalInfoOrderFromClient?.fields?.length; j++) {
105
+ let keyClient = data?.AdditionalInfoOrderFromClient?.fields[j];
106
+ if (keyClient && keyClient !== "") {
107
+ orderMondelez.clientProfileData[keyClient] = responseCT?.data[0]?.[keyClient] ?? null;
108
+ }
109
+ }
110
+ }
111
+ } catch (errorSetFields) {
112
+ Logger.error('Error set AdditionalInfoOrderFromClient', errorSetFields);
113
+ }
114
+
115
+ //obtener campos adicionales
116
+
117
+ if (data?.ObjectZeroTax === true) {
118
+ orderMondelez.items = setObjectZeroTax(orderMondelez.items);
119
+ }
120
+
121
+ if (data?.ChannelWarehouse) {
122
+ orderMondelez.shippingAddress.logisticsInfo.deliveryIds = orderMondelez?.shippingAddress?.logisticsInfo?.deliveryIds?.map(it => {
123
+ it.warehouse = "";
124
+ for (let wr in data?.ChannelWarehouse) {
125
+ if (data?.ChannelWarehouse[wr] == it?.warehouseId) {
126
+ it.warehouse = wr;
127
+ }
128
+ }
129
+
130
+ return it;
131
+ });
132
+ }
133
+
134
+ // adjuntar campos adicionales a las promociones de la orden
135
+ orderMondelez = await getAdditionalInfoPromotionsOrder(orderMondelez, data, apiClient);
136
+
137
+ try {
138
+ //Additional Info Fields Sku Distributors
139
+ Logger.debug("Sku Distributors Management: ", data?.SkuDistributorManagementAdditionalInfo);
140
+ orderMondelez = await setItemsSkuDistributors(orderMondelez, data);
141
+ Logger.debug("Order Mondelez: ", orderMondelez);
142
+ } catch (error) {
143
+ Logger.error("GetOrder: ", error);
144
+ }
145
+
146
+ return ApiResponse.response(200, orderMondelez);
147
+ } else {
148
+ return ApiResponse.response(responseParent.status, responseParent.data);
149
+ }
150
+ } else {
151
+ return ApiResponse.response(response.status, response.data);
152
+ }
153
+ }
154
+ }
155
+ }
156
+ return ApiResponse.response(404, "Order not found");
157
+ } catch (error) {
158
+ Logger.error(error);
159
+ return ApiResponse.response(error?.statusCode || 500, {
160
+ message: error.message,
161
+ });
162
+ }
163
+ };
164
+
165
+ const setObjectZeroTax = (items) => {
166
+ if (!items || typeof items != 'object') {
167
+ return null;
168
+ }
169
+
170
+ for (var i = 0; i < items.length; i++) {
171
+ let exitTax = items[i]?.priceTags?.find(it => (String(it.name).indexOf("tax@price") > -1));
172
+
173
+ if (items[i]?.priceTags?.length === 0 || exitTax?.length === 0) {
174
+ items[i].priceTags = [...items[i]?.priceTags, {
175
+ "name": "tax@price",
176
+ "value": 0,
177
+ "isPercentual": true,
178
+ "identifier": null,
179
+ "rawValue": 0,
180
+ "valueNominal": 0,
181
+ "rawValueNominal": 0,
182
+ "rate": null,
183
+ "jurisCode": null,
184
+ "jurisType": null,
185
+ "jurisName": null
186
+ }];
187
+ }
188
+ }
189
+
190
+ return items;
191
+ }
192
+
193
+ const getAdditionalInfoPromotionsOrder = async (data, account, apiClient) => {
194
+ if (!account
195
+ || !account?.AdditionalFieldsPromotionsInOrder
196
+ || !account.AdditionalFieldsPromotionsInOrder?.isActive
197
+ || !account.AdditionalFieldsPromotionsInOrder?.acronymEntity
198
+ || Object.keys(account.AdditionalFieldsPromotionsInOrder?.fields).length === 0) return data;
199
+
200
+ try {
201
+ const OrderId = data?.id;
202
+ const acronymEntity = account?.AdditionalFieldsPromotionsInOrder?.acronymEntity;
203
+ const responseAdditionalInfo = await apiClient.fetch(`/dataentities/${acronymEntity}/documents/${OrderId}?_fields=detailPromotions`, {
204
+ method: "GET",
205
+ });
206
+
207
+
208
+ if (responseAdditionalInfo?.status >= 200 && responseAdditionalInfo?.status < 300 && responseAdditionalInfo?.data) {
209
+ const promotions = responseAdditionalInfo?.data?.detailPromotions ?? [];
210
+
211
+ for (const promo of promotions) {
212
+ const identifiersBenefits = data?.ratesAndBenefitsData?.rateAndBenefitsIdentifiers || [];
213
+ for (let i = 0; i < identifiersBenefits.length; i++) {
214
+ const identifier = identifiersBenefits[i];
215
+ if (identifier?.id === promo?.id) {
216
+ data.ratesAndBenefitsData.rateAndBenefitsIdentifiers[i] = { ...identifier, ...promo?.fields };
217
+ }
218
+ }
219
+
220
+ for (let itemIndex = 0; itemIndex < data.items.length; itemIndex++) {
221
+ const item = data.items[itemIndex];
222
+ for (let priceTagIndex = 0; priceTagIndex < item.priceTags.length; priceTagIndex++) {
223
+ const priceTag = item.priceTags[priceTagIndex];
224
+ if (priceTag?.identifier === promo?.id) {
225
+ data.items[itemIndex].priceTags[priceTagIndex] = { ...priceTag, ...promo?.fields };
226
+ }
227
+ }
228
+ }
229
+ }
230
+ return data;
231
+ } else {
232
+ return data;
233
+ }
234
+ } catch (errorSetFields) {
235
+ return data;
236
+ }
237
+ }
238
+
239
+ //Additional Info Fields Sku Distributors
240
+ const setItemsSkuDistributors = async (orderMondelez, data) => {
241
+ if (!data || !data?.SkuDistributorManagementAdditionalInfo) {
242
+ return orderMondelez;
243
+ }
244
+ //TODO: Implement logic for Sku Distributors Management of Orders
245
+ const items = orderMondelez?.items;
246
+ const skuRefUsed = data?.SkuRefUsed;
247
+ if (typeof skuRefUsed !== "boolean") {
248
+ Logger.debug("Sku or ReferenceCode filter not defined, use default: ", skuRefUsed);
249
+ skuRefUsed = true;
250
+ }
251
+
252
+ if (!items) {
253
+ Logger.error("Orders without items.");
254
+ return orderMondelez;
255
+ }
256
+ const apiClient = new VtexApi(data?.AccountName, data?.Credentials?.key, data?.Credentials?.token);
257
+ Logger.debug("VTEX API Client: ", apiClient);
258
+ const responseAdditionalInfo = data?.SkuDistributorManagementAdditionalInfo && data?.SkuDistributorManagementAdditionalInfo !== "" ? await apiClient.fetch(`/dataentities/${data?.SkuDistributorManagementAdditionalInfo?.entityName}/documents/${orderMondelez.id}?_fields=_all`, {
259
+ method: "GET",
260
+ }) : { status: 200, data: [] };
261
+ Logger.debug("responseAdditionalInfo in setItemsSkuDistributors: ", responseAdditionalInfo?.data);
262
+ if (responseAdditionalInfo?.status >= 200 && responseAdditionalInfo?.status < 300 && responseAdditionalInfo?.data) {
263
+ const dataItems = responseAdditionalInfo?.data?.items ?? [];
264
+ let itemsOrder = orderMondelez?.items ?? [];
265
+ orderMondelez.items = itemsOrder.map(itemOrder => {
266
+ const distributorData = dataItems.find(it => skuRefUsed ? it.refId == itemOrder.sku : it.ean == itemOrder.ean);
267
+ if (distributorData && distributorData.ERPCode) {
268
+ itemOrder.sku = distributorData.ERPCode;
269
+ }
270
+ return itemOrder;
271
+ });
272
+ }
273
+
274
+ return orderMondelez;
275
+ };
276
+
277
+
278
+ module.exports = {
279
+ getOrders,
280
+ };
@@ -0,0 +1,137 @@
1
+ const OrderData = require("../../entities/orders");
2
+ const AccountData = require("../../entities/account");
3
+ const Convert = require("../../common/MondelezCastOrder");
4
+ const VtexApi = require("../../vtex/clients/VtexApi");
5
+ const TaxPromotionsData = require("../../entities/taxpromotion");
6
+ const Logger = require("../../common/utils/logger");
7
+
8
+ const fs = require("fs");
9
+ const csv = require("csv");
10
+ const AWS = require("aws-sdk");
11
+ const s3 = new AWS.S3();
12
+ const BUCKET_NAME = process.env.BUCKET_NAME;
13
+
14
+ const consumer = async (event) => {
15
+ for (const record of event.Records) {
16
+ Logger.debug("Message Body: ", record.body);
17
+ try {
18
+ let order = JSON.parse(record.body);
19
+ const dateValue = stringDateVtexToDate(order?.orderInfo?.CurrentChange);
20
+ const orderToUpdate = {
21
+ AccountNameForOrder: order?.orderInfo?.Origin?.Account,
22
+ OrderId: order?.orderInfo?.OrderId,
23
+ StatusDate: dateValue,
24
+ OrderState: order?.orderInfo?.State,
25
+ Domain: order?.orderInfo?.Domain,
26
+ Key: order?.orderInfo?.Origin?.Key
27
+ };
28
+ const orderSaved = await OrderData.addOrder(orderToUpdate);
29
+ const accountConfig = order?.accountConfig;
30
+ const configuredSftp = accountConfig?.SftpUsed || false;
31
+ const directory = accountConfig?.SftpDirectory?.orders;
32
+ if (accountConfig && configuredSftp && directory) {
33
+ const parentAccount = await AccountData.getAccountDataByAccountName(accountConfig.ParentAccountName);
34
+ if (parentAccount) {
35
+ const apiClient = new VtexApi(
36
+ accountConfig?.AccountName,
37
+ accountConfig?.Credentials?.key,
38
+ accountConfig?.Credentials?.token
39
+ );
40
+ const apiClientParent = new VtexApi(
41
+ parentAccount?.AccountName,
42
+ parentAccount?.Credentials?.key,
43
+ parentAccount?.Credentials?.token
44
+ );
45
+ const response = await apiClient.fetch(`/oms/pvt/orders/${order?.orderInfo?.OrderId}`, {
46
+ method: "GET",
47
+ });
48
+ if (response.status >= 200 && response.status < 300) {
49
+ const parentOrderId = response?.data?.marketplaceOrderId;
50
+ if (!parentOrderId) {
51
+ Logger.error("Order not found. Parent Order ID not found");
52
+ throw new Error("Order not found. Parent Order ID not found");
53
+ }
54
+ const responseParent = await apiClientParent.fetch(`/oms/pvt/orders/${parentOrderId}`, {
55
+ method: "GET",
56
+ });
57
+ if (responseParent.status >= 200 && responseParent.status < 300) {
58
+ const orderDataAndPromotionERP = accountConfig?.BindIdExternalPromotion === true ? await TaxPromotionsData.bindIdExternalPromotionToOrderData(responseParent.data) : responseParent.data;
59
+ let orderMondelez = Convert.orderToJson(response.data, orderDataAndPromotionERP);
60
+ let email = orderMondelez?.clientProfileData?.email;
61
+ if (email) {
62
+ try {
63
+ const responseMailParent = await apiClientParent.fetchOrderMail(email);
64
+ orderMondelez.clientProfileData.email = responseMailParent?.data?.email;
65
+ } catch (error) {
66
+ Logger.error(error);
67
+ }
68
+ }
69
+ const csvData = Convert.convertJsonOrderToCsv(orderMondelez);
70
+ let csvDataString = "";
71
+ await readStream(
72
+ csv.stringify(
73
+ csvData.csvData,
74
+ { header: true, columns: csvData.csvHeaders, delimiter: ";" },
75
+ (err, output) => {
76
+ if (err) {
77
+ Logger.error("Error CSV: ", err);
78
+ }
79
+ csvDataString = output;
80
+ }
81
+ )
82
+ );
83
+ const fileName = orderMondelez.id + "_" + orderMondelez.status + "_" + dateValue + ".csv";
84
+ const params = {
85
+ Bucket: BUCKET_NAME,
86
+ Key: `${directory}${fileName}`,
87
+ Body: csvDataString,
88
+ ContentType: "text/csv",
89
+ ACL: "public-read",
90
+ };
91
+ await s3.putObject(params).promise();
92
+ }
93
+ }
94
+ }
95
+ }
96
+ } catch (error) {
97
+ Logger.error(error);
98
+ }
99
+ }
100
+ };
101
+
102
+ function readStream(stream) {
103
+ return new Promise((resolve, reject) => {
104
+ let csvString = "";
105
+
106
+ stream.on("readable", () => {
107
+ let chunk;
108
+ while ((chunk = stream.read()) !== null) {
109
+ csvString += chunk;
110
+ }
111
+ });
112
+
113
+ stream.on("end", () => {
114
+ resolve(csvString);
115
+ });
116
+
117
+ stream.on("error", (error) => {
118
+ reject(error);
119
+ });
120
+ });
121
+ }
122
+
123
+ function stringDateVtexToDate(date) {
124
+ Logger.debug("Date: ", date);
125
+ let dateValue = date;
126
+ try {
127
+ dateValue = new Date(date).toISOString();
128
+ } catch (error) {
129
+ Logger.error(error);
130
+ }
131
+ Logger.debug("Date: ", dateValue);
132
+ return dateValue;
133
+ }
134
+
135
+ module.exports = {
136
+ consumer,
137
+ };
@@ -0,0 +1,170 @@
1
+ const AWSServices = require("../../common/utils/aws-services");
2
+ const ApiResponse = require("../../common/utils/api-response");
3
+ const { isStateInNotificationProviders } = require("../../common/utils/validate-state-order");
4
+ const Logger = require("../../common/utils/logger");
5
+ const ORDER_HOOK_QUEUE_URL = process.env.ORDER_HOOK_QUEUE_URL;
6
+ const SQS_ROUTEFLOW_QUEUE_URL = process.env.SQS_ROUTEFLOW_QUEUE_URL;
7
+ const SQS_SKU_DISTRIBUTOR_QUEUE_URL = process.env.SQS_SKU_DISTRIBUTOR_QUEUE_URL;
8
+ // NOTIFICATIONS
9
+ const SQS_NOTIFICATION_ORDER_STATUS_QUEUE_URL = process.env.SQS_NOTIFICATION_ORDER_STATUS_QUEUE_URL
10
+ // ADDITIONAL FIELDS PROMOTIONS ORDER
11
+ const SQS_PROMOTIONS_ORDER_QUEUE_URL = process.env.SQS_PROMOTIONS_ORDER_QUEUE_URL;
12
+
13
+ const AccountData = require("../../entities/account");
14
+
15
+ const producer = async (event) => {
16
+ let statusCode = 200;
17
+ let message;
18
+ if (!event.body) {
19
+ return ApiResponse.response(400, "No body was found");
20
+ }
21
+ try {
22
+ Logger.debug("all-event: ", event);
23
+ const appKey = event?.headers?.MDLZ_AppKey ?? event?.headers?.mdlz_appkey;
24
+ const appToken = event?.headers?.MDLZ_AppToken ?? event?.headers?.mdlz_apptoken;
25
+
26
+ if (!appKey || !appToken) {
27
+ Logger.error("Authorizer credentials is required.");
28
+ }
29
+
30
+ const {Domain, OrderId, CurrentChange, State, Origin} = JSON.parse(event.body);
31
+ if(!Domain){
32
+ Logger.error("Domain property is required.");
33
+ }
34
+ if(!OrderId){
35
+ Logger.error("OrderId property is required.");
36
+ }
37
+ if(!CurrentChange){
38
+ Logger.error("CurrentChange property is required.");
39
+ }
40
+ if(!State){
41
+ Logger.error("State property is required.");
42
+ }
43
+
44
+ const accountConfig = Origin?.Account ? await AccountData.getAccountDataByAccountName(Origin?.Account) : {};
45
+ Logger.setAccount(accountConfig);
46
+ Logger.debug("account-config: ", accountConfig);
47
+
48
+ if(!accountConfig){
49
+ Logger.error("Account config not found.");
50
+ }
51
+ if(!accountConfig?.MDLZAppKey || !accountConfig?.MDLZAppToken){
52
+ Logger.error("Credentials not found.");
53
+ }
54
+ if(accountConfig?.MDLZAppKey !== appKey || accountConfig?.MDLZAppToken !== appToken){
55
+ Logger.error("Credentials incorrect.");
56
+ }
57
+
58
+ if(Domain && OrderId && CurrentChange && State && accountConfig && accountConfig?.MDLZAppKey === appKey && accountConfig?.MDLZAppToken === appToken){
59
+ const orderInfo = JSON.parse(event.body);
60
+ const accountConfigParent = await AccountData.getAccountDataByAccountName(accountConfig?.ParentAccountName);
61
+ const orderData = {
62
+ orderInfo,
63
+ accountConfig,
64
+ accountConfigParent,
65
+ };
66
+ await AWSServices.sendSQSMessage(ORDER_HOOK_QUEUE_URL, orderData);
67
+ await sendAdditionalFields(orderData);
68
+ await sendAdditionalFieldsSkuDistributors(orderData);
69
+
70
+ // Send notification status order to user
71
+ await sendNotificationAtQueue(orderData)
72
+ // Save additional fields promotions in order
73
+ await sendAdditionalFieldsPromotionsByOrder(orderData)
74
+
75
+ message = "Message accepted!";
76
+ } else {
77
+ message = "Message no accepted!";
78
+ }
79
+
80
+ } catch (error) {
81
+ Logger.error(error);
82
+ message = error;
83
+ statusCode = 500;
84
+ }
85
+ return ApiResponse.response(statusCode, message);
86
+ };
87
+
88
+ async function sendAdditionalFieldsPromotionsByOrder(orderData) {
89
+
90
+ if (!SQS_PROMOTIONS_ORDER_QUEUE_URL || !orderData) {
91
+ Logger.error('ERROR send order to promotions queue: missing queueUrl or orderData');
92
+ return false;
93
+ }
94
+
95
+ const promotionsConfig = orderData?.accountConfig?.AdditionalFieldsPromotionsInOrder;
96
+ if (!promotionsConfig) {
97
+ return false;
98
+ }
99
+
100
+ const { isActive, initialState } = promotionsConfig;
101
+ if (isActive && initialState === orderData?.orderInfo?.State) {
102
+ await AWSServices.sendSQSMessage(SQS_PROMOTIONS_ORDER_QUEUE_URL, orderData);
103
+ return true;
104
+ }
105
+ return false
106
+ }
107
+
108
+ async function sendAdditionalFields(orderToUpdate) {
109
+ const additionalFields = orderToUpdate?.accountConfig?.AdditionalInfoOrderFromClient;
110
+
111
+ if(additionalFields &&
112
+ additionalFields?.initialState !== "" &&
113
+ additionalFields?.initialState !== "" &&
114
+ additionalFields?.initialState === orderToUpdate?.orderInfo?.State &&
115
+ additionalFields?.fields?.length > 0 &&
116
+ additionalFields?.nameEntity !== ""
117
+
118
+ ){
119
+ await AWSServices.sendSQSMessage(SQS_ROUTEFLOW_QUEUE_URL, orderToUpdate);
120
+ return true;
121
+ }
122
+
123
+ return false;
124
+ }
125
+
126
+ async function sendAdditionalFieldsSkuDistributors(orderToUpdate) {
127
+ const additionalFields = orderToUpdate?.accountConfig?.SkuDistributorManagementAdditionalInfo;
128
+
129
+ if(additionalFields &&
130
+ additionalFields?.initialState &&
131
+ additionalFields?.initialState !== "" &&
132
+ additionalFields?.initialState === orderToUpdate?.orderInfo?.State &&
133
+ additionalFields?.entityName !== "" &&
134
+ additionalFields?.isActive !== "" &&
135
+ additionalFields?.isActive === true
136
+ ) {
137
+ await AWSServices.sendSQSMessage(SQS_SKU_DISTRIBUTOR_QUEUE_URL, orderToUpdate);
138
+
139
+ return true;
140
+ }
141
+
142
+ return false;
143
+ }
144
+
145
+ // Builder to send notifications of the status of the generated order to the users.
146
+ async function sendNotificationAtQueue(orderData){
147
+
148
+ if(!SQS_NOTIFICATION_ORDER_STATUS_QUEUE_URL || !orderData){
149
+ Logger.error('ERROR in queue')
150
+ return false
151
+ }
152
+
153
+ const notificationOrderVTEX = orderData?.accountConfig?.NotificationsVTEX
154
+ const stateOrder = orderData?.orderInfo?.State
155
+
156
+ const isActiveNotifications = notificationOrderVTEX?.isActive
157
+ const notificationProviders = notificationOrderVTEX?.NotificationProviders ?? []
158
+
159
+ const isValidState = isStateInNotificationProviders({isActiveNotifications, notificationProviders, stateOrder})
160
+
161
+ if(isValidState){
162
+ await AWSServices.sendSQSMessage(SQS_NOTIFICATION_ORDER_STATUS_QUEUE_URL, orderData)
163
+ return true;
164
+ }
165
+ return false
166
+ }
167
+
168
+ module.exports = {
169
+ producer,
170
+ };