@nimee/inforu 1.0.16 → 1.0.18
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/dist/automations.js +89 -1
- package/dist/automations.js.map +1 -1
- package/dist/ecommerce-example.d.ts +10 -0
- package/dist/ecommerce-example.js +246 -0
- package/dist/ecommerce-example.js.map +1 -0
- package/dist/ecommerce.d.ts +119 -0
- package/dist/ecommerce.js +232 -0
- package/dist/ecommerce.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/automations.ts +108 -1
- package/src/ecommerce-curl-examples.md +361 -0
- package/src/ecommerce.ts +346 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.parseBookPurchaseEventType = exports.isBookPurchaseEvent = exports.BookPurchaseEventType = exports.parseEcommerceEventType = exports.isEcommerceEvent = exports.sendEcommerceOrder = exports.EcommerceEventType = void 0;
|
|
16
|
+
const error_handler_1 = require("@nimee/error-handler");
|
|
17
|
+
const logger_1 = __importDefault(require("@nimee/logger"));
|
|
18
|
+
const axios_1 = __importDefault(require("axios"));
|
|
19
|
+
// Type for ecommerce events
|
|
20
|
+
var EcommerceEventType;
|
|
21
|
+
(function (EcommerceEventType) {
|
|
22
|
+
// Purchase events
|
|
23
|
+
EcommerceEventType["PURCHASED_PHYSICAL_BOOK"] = "PURCHASED_PHYSICAL_BOOK";
|
|
24
|
+
EcommerceEventType["PURCHASED_DIGITAL_BOOK"] = "PURCHASED_DIGITAL_BOOK";
|
|
25
|
+
EcommerceEventType["PURCHASED_VOD_PRODUCT"] = "PURCHASED_VOD_PRODUCT";
|
|
26
|
+
EcommerceEventType["PURCHASED_EVENT_TICKET"] = "PURCHASED_EVENT_TICKET";
|
|
27
|
+
// Abandoned cart events
|
|
28
|
+
EcommerceEventType["ABANDONED_CART_BOOK"] = "ABANDONED_CART_BOOK";
|
|
29
|
+
EcommerceEventType["ABANDONED_CART"] = "ABANDONED_CART";
|
|
30
|
+
})(EcommerceEventType || (exports.EcommerceEventType = EcommerceEventType = {}));
|
|
31
|
+
// Map internal event types to InfoRu API event names
|
|
32
|
+
const EVENT_TYPE_TO_API_EVENT = {
|
|
33
|
+
[EcommerceEventType.PURCHASED_PHYSICAL_BOOK]: "sales_order_place_after",
|
|
34
|
+
[EcommerceEventType.PURCHASED_DIGITAL_BOOK]: "sales_order_place_after",
|
|
35
|
+
[EcommerceEventType.PURCHASED_VOD_PRODUCT]: "sales_order_place_after",
|
|
36
|
+
[EcommerceEventType.PURCHASED_EVENT_TICKET]: "sales_order_place_after",
|
|
37
|
+
[EcommerceEventType.ABANDONED_CART_BOOK]: "cart_abandoned",
|
|
38
|
+
[EcommerceEventType.ABANDONED_CART]: "cart_abandoned",
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Helper function to determine product type from event type
|
|
42
|
+
*/
|
|
43
|
+
function getProductType(eventType) {
|
|
44
|
+
switch (eventType) {
|
|
45
|
+
case EcommerceEventType.PURCHASED_PHYSICAL_BOOK:
|
|
46
|
+
return "physical_book";
|
|
47
|
+
case EcommerceEventType.PURCHASED_DIGITAL_BOOK:
|
|
48
|
+
return "digital_book";
|
|
49
|
+
case EcommerceEventType.PURCHASED_VOD_PRODUCT:
|
|
50
|
+
return "vod";
|
|
51
|
+
case EcommerceEventType.PURCHASED_EVENT_TICKET:
|
|
52
|
+
return "event_ticket";
|
|
53
|
+
case EcommerceEventType.ABANDONED_CART_BOOK:
|
|
54
|
+
return "abandoned_book";
|
|
55
|
+
case EcommerceEventType.ABANDONED_CART:
|
|
56
|
+
return "abandoned_cart";
|
|
57
|
+
default:
|
|
58
|
+
return "product";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Transforms purchase data into ecommerce API format
|
|
63
|
+
*/
|
|
64
|
+
function prepareEcommercePayload(eventType, data) {
|
|
65
|
+
const isAbandonedCart = eventType === EcommerceEventType.ABANDONED_CART_BOOK || eventType === EcommerceEventType.ABANDONED_CART;
|
|
66
|
+
// Map products to order items
|
|
67
|
+
const orderItems = data.products.map((product) => {
|
|
68
|
+
var _a, _b;
|
|
69
|
+
return ({
|
|
70
|
+
ProductCode: product.code || product.isbn || "",
|
|
71
|
+
ProductName: product.name,
|
|
72
|
+
ProductPrice: product.price,
|
|
73
|
+
ProductQty: product.quantity,
|
|
74
|
+
ProductDescription: product.description || null,
|
|
75
|
+
ProductLink: product.link,
|
|
76
|
+
ProductImage: product.image,
|
|
77
|
+
// Custom fields based on product type
|
|
78
|
+
Custom1: product.isbn || ((_a = product.eventDate) === null || _a === void 0 ? void 0 : _a.toString()) || product.vodDuration,
|
|
79
|
+
Custom2: product.author || product.eventLocation || ((_b = product.vodExpiry) === null || _b === void 0 ? void 0 : _b.toString()),
|
|
80
|
+
Custom3: product.publisher || product.seatNumber || product.vodStreamUrl,
|
|
81
|
+
Custom4: product.format || getProductType(eventType),
|
|
82
|
+
Custom5: eventType, // Add the original event type (e.g., PURCHASED_PHYSICAL_BOOK)
|
|
83
|
+
ProductAttributes: [
|
|
84
|
+
// Always include the event category
|
|
85
|
+
{ label: "event_category", value: eventType },
|
|
86
|
+
...(product.format ? [{ label: "format", value: product.format }] : []),
|
|
87
|
+
...(product.author ? [{ label: "author", value: product.author }] : []),
|
|
88
|
+
...(product.publisher ? [{ label: "publisher", value: product.publisher }] : []),
|
|
89
|
+
...(product.eventDate ? [{ label: "event_date", value: product.eventDate.toString() }] : []),
|
|
90
|
+
...(product.eventLocation ? [{ label: "location", value: product.eventLocation }] : []),
|
|
91
|
+
...(product.seatNumber ? [{ label: "seat", value: product.seatNumber }] : []),
|
|
92
|
+
...(product.downloadLink ? [{ label: "download_link", value: product.downloadLink }] : []),
|
|
93
|
+
].filter(attr => attr.value) // Remove empty attributes
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
// Format order time
|
|
97
|
+
const orderTime = data.orderTime
|
|
98
|
+
? (data.orderTime instanceof Date
|
|
99
|
+
? data.orderTime.toISOString().replace('T', ' ').substring(0, 19)
|
|
100
|
+
: data.orderTime)
|
|
101
|
+
: new Date().toISOString().replace('T', ' ').substring(0, 19);
|
|
102
|
+
// Get the appropriate InfoRu API event name
|
|
103
|
+
const apiEventName = EVENT_TYPE_TO_API_EVENT[eventType];
|
|
104
|
+
// Determine group names based on event type
|
|
105
|
+
const groupNames = [];
|
|
106
|
+
switch (eventType) {
|
|
107
|
+
case EcommerceEventType.PURCHASED_PHYSICAL_BOOK:
|
|
108
|
+
groupNames.push("physical_book_buyers");
|
|
109
|
+
break;
|
|
110
|
+
case EcommerceEventType.PURCHASED_DIGITAL_BOOK:
|
|
111
|
+
groupNames.push("digital_book_buyers");
|
|
112
|
+
break;
|
|
113
|
+
case EcommerceEventType.PURCHASED_VOD_PRODUCT:
|
|
114
|
+
groupNames.push("vod_purchasers");
|
|
115
|
+
break;
|
|
116
|
+
case EcommerceEventType.PURCHASED_EVENT_TICKET:
|
|
117
|
+
groupNames.push("event_attendees");
|
|
118
|
+
break;
|
|
119
|
+
case EcommerceEventType.ABANDONED_CART_BOOK:
|
|
120
|
+
groupNames.push("abandoned_cart_books");
|
|
121
|
+
break;
|
|
122
|
+
case EcommerceEventType.ABANDONED_CART:
|
|
123
|
+
groupNames.push("abandoned_cart_general");
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
// Determine if physical shipping is needed
|
|
127
|
+
const needsShipping = eventType === EcommerceEventType.PURCHASED_PHYSICAL_BOOK ||
|
|
128
|
+
eventType === EcommerceEventType.PURCHASED_EVENT_TICKET;
|
|
129
|
+
return {
|
|
130
|
+
Data: {
|
|
131
|
+
Event: apiEventName,
|
|
132
|
+
Category: eventType, // Add the original event type (e.g., PURCHASED_PHYSICAL_BOOK)
|
|
133
|
+
StoreName: data.storeName || "Nimi Store",
|
|
134
|
+
StoreBaseUrl: data.storeUrl || "https://www.nimi.co.il/",
|
|
135
|
+
LinkToCart: isAbandonedCart && data.cartUrl
|
|
136
|
+
? data.cartUrl
|
|
137
|
+
: `${data.storeUrl || "https://www.nimi.co.il"}/checkout/cart/`,
|
|
138
|
+
IP: data.ip,
|
|
139
|
+
CustomerEmail: data.customerEmail,
|
|
140
|
+
CustomerFirstName: data.customerFirstName,
|
|
141
|
+
CustomerLastName: data.customerLastName,
|
|
142
|
+
ContactRefId: data.contactRefId || "",
|
|
143
|
+
SubscriberStatus: "Subscribed",
|
|
144
|
+
AddToGroupName: groupNames,
|
|
145
|
+
OrderNumber: data.orderNumber,
|
|
146
|
+
OrderAmount: String(data.orderAmount),
|
|
147
|
+
OrderStatus: isAbandonedCart ? "abandoned" : (data.orderStatus || "processing"),
|
|
148
|
+
BillingAddress: data.billingAddress,
|
|
149
|
+
ShippingAddress: needsShipping ? data.shippingAddress : undefined,
|
|
150
|
+
PaymentDescription: data.paymentMethod || "credit card",
|
|
151
|
+
ShippingDescription: needsShipping
|
|
152
|
+
? (data.shippingMethod || "Standard shipping")
|
|
153
|
+
: "Digital delivery - Instant",
|
|
154
|
+
OrderTime: orderTime,
|
|
155
|
+
OrderItems: orderItems
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Sends ecommerce order data to InfoRu API based on event type
|
|
161
|
+
*/
|
|
162
|
+
function sendEcommerceOrder(params) {
|
|
163
|
+
var _a, _b, _c, _d;
|
|
164
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
165
|
+
try {
|
|
166
|
+
const { apiKey, eventType, data } = params;
|
|
167
|
+
if (!apiKey) {
|
|
168
|
+
throw new error_handler_1.CustomError("MISSING_API_KEY", 400, "API key is required");
|
|
169
|
+
}
|
|
170
|
+
if (!eventType || !Object.values(EcommerceEventType).includes(eventType)) {
|
|
171
|
+
throw new error_handler_1.CustomError("INVALID_EVENT_TYPE", 400, `Invalid event type. Must be one of: ${Object.values(EcommerceEventType).join(', ')}`);
|
|
172
|
+
}
|
|
173
|
+
if (!data || !data.customerEmail || !data.orderNumber) {
|
|
174
|
+
throw new error_handler_1.CustomError("MISSING_REQUIRED_DATA", 400, "Customer email and order number are required");
|
|
175
|
+
}
|
|
176
|
+
if (!data.products || data.products.length === 0) {
|
|
177
|
+
throw new error_handler_1.CustomError("NO_ORDER_ITEMS", 400, "Order must contain at least one product");
|
|
178
|
+
}
|
|
179
|
+
// Prepare the payload based on event type
|
|
180
|
+
const payload = prepareEcommercePayload(eventType, data);
|
|
181
|
+
// API endpoint for ecommerce
|
|
182
|
+
const apiUrl = "https://capi.inforu.co.il/api/v2/EcommerceApi";
|
|
183
|
+
// Send the request
|
|
184
|
+
const response = yield axios_1.default.post(apiUrl, payload, {
|
|
185
|
+
headers: {
|
|
186
|
+
"Authorization": apiKey,
|
|
187
|
+
"Content-Type": "application/json"
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
return {
|
|
191
|
+
success: true,
|
|
192
|
+
data: response.data,
|
|
193
|
+
orderNumber: data.orderNumber,
|
|
194
|
+
eventType
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
logger_1.default.error("Failed to send ecommerce order", {
|
|
199
|
+
error: error instanceof Error ? error.message : error,
|
|
200
|
+
eventType: params.eventType,
|
|
201
|
+
orderNumber: (_a = params.data) === null || _a === void 0 ? void 0 : _a.orderNumber
|
|
202
|
+
});
|
|
203
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
204
|
+
throw new error_handler_1.CustomError("ECOMMERCE_API_ERROR", ((_b = error.response) === null || _b === void 0 ? void 0 : _b.status) || 500, `Failed to send ecommerce order: ${((_d = (_c = error.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.message) || error.message}`);
|
|
205
|
+
}
|
|
206
|
+
throw new error_handler_1.CustomError("ECOMMERCE_ORDER_ERROR", 500, `Failed to process ecommerce order: ${error instanceof Error ? error.message : JSON.stringify(error)}`);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
exports.sendEcommerceOrder = sendEcommerceOrder;
|
|
211
|
+
/**
|
|
212
|
+
* Helper function to determine if an event is an ecommerce event
|
|
213
|
+
*/
|
|
214
|
+
function isEcommerceEvent(eventName) {
|
|
215
|
+
return Object.values(EcommerceEventType).includes(eventName);
|
|
216
|
+
}
|
|
217
|
+
exports.isEcommerceEvent = isEcommerceEvent;
|
|
218
|
+
/**
|
|
219
|
+
* Helper function to validate and parse ecommerce event type
|
|
220
|
+
*/
|
|
221
|
+
function parseEcommerceEventType(eventName) {
|
|
222
|
+
if (Object.values(EcommerceEventType).includes(eventName)) {
|
|
223
|
+
return eventName;
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
exports.parseEcommerceEventType = parseEcommerceEventType;
|
|
228
|
+
// Backward compatibility aliases for book events
|
|
229
|
+
exports.BookPurchaseEventType = EcommerceEventType; // Type alias
|
|
230
|
+
exports.isBookPurchaseEvent = isEcommerceEvent;
|
|
231
|
+
exports.parseBookPurchaseEventType = parseEcommerceEventType;
|
|
232
|
+
//# sourceMappingURL=ecommerce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecommerce.js","sourceRoot":"","sources":["../src/ecommerce.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -20,4 +20,5 @@ __exportStar(require("./createGroup"), exports);
|
|
|
20
20
|
__exportStar(require("./automations"), exports);
|
|
21
21
|
__exportStar(require("./sendWA"), exports);
|
|
22
22
|
__exportStar(require("./sendEmail"), exports);
|
|
23
|
+
__exportStar(require("./ecommerce"), exports);
|
|
23
24
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2BAA2B;AAC3B,4CAA0B;AAC1B,gDAA8B;AAC9B,gDAA8B;AAC9B,2CAAyB;AACzB,8CAA4B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2BAA2B;AAC3B,4CAA0B;AAC1B,gDAA8B;AAC9B,gDAA8B;AAC9B,2CAAyB;AACzB,8CAA4B;AAC5B,8CAA4B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nimee/inforu",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
4
4
|
"description": "inforu SDK for Node.js",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "dan goldberg",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"types": "dist/index.d.ts",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@nimee/error-handler": "
|
|
30
|
+
"@nimee/error-handler": "0.0.14",
|
|
31
31
|
"@nimee/logger": "^1.0.27",
|
|
32
32
|
"axios": "1.2.1"
|
|
33
33
|
}
|
package/src/automations.ts
CHANGED
|
@@ -2,13 +2,120 @@ import { CustomError, errorHandler } from "@nimee/error-handler";
|
|
|
2
2
|
import { prepareContactsPayload } from "./normalize";
|
|
3
3
|
import logger from "@nimee/logger";
|
|
4
4
|
import axios from "axios";
|
|
5
|
+
import {
|
|
6
|
+
sendEcommerceOrder,
|
|
7
|
+
isEcommerceEvent,
|
|
8
|
+
parseEcommerceEventType,
|
|
9
|
+
IEcommercePurchaseData,
|
|
10
|
+
IOrderProduct
|
|
11
|
+
} from "./ecommerce";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Normalizes CRM event data to InfoRu ecommerce format
|
|
15
|
+
* Handles the transformation from the internal data structure to InfoRu's expected format
|
|
16
|
+
*/
|
|
17
|
+
function normalizeEcommerceData(data: any, endUser?: any): IEcommercePurchaseData {
|
|
18
|
+
// The data structure from CRM service has endUser fields merged with the data object
|
|
19
|
+
// Extract customer info from data (which contains endUser fields + data fields)
|
|
20
|
+
const customerEmail = data.email || data.customerEmail || endUser?.email || "";
|
|
21
|
+
const customerFirstName = data.fname || data.customerFirstName || endUser?.fname || "";
|
|
22
|
+
const customerLastName = data.lname || data.customerLastName || endUser?.lname || "";
|
|
23
|
+
|
|
24
|
+
// Normalize order fields
|
|
25
|
+
const orderNumber = data.orderNumber || data.Order_id?.toString() || data.orderId?.toString() || "";
|
|
26
|
+
const orderAmount = data.orderAmount || data.Total || data.total || 0;
|
|
27
|
+
const orderStatus = data.orderStatus || data.Status || data.status || "processing";
|
|
28
|
+
const paymentMethod = data.paymentMethod || data.Payment_method || data.payment_method || "";
|
|
29
|
+
|
|
30
|
+
// Normalize products array
|
|
31
|
+
let products: IOrderProduct[] = [];
|
|
32
|
+
|
|
33
|
+
if (data.products && Array.isArray(data.products)) {
|
|
34
|
+
products = data.products;
|
|
35
|
+
} else if (data.Products && Array.isArray(data.Products)) {
|
|
36
|
+
// Transform from internal format to InfoRu format
|
|
37
|
+
products = data.Products.map((product: any) => ({
|
|
38
|
+
code: product.code || product.Code || product.SKU || product.Name || "",
|
|
39
|
+
name: product.name || product.Name || "",
|
|
40
|
+
price: parseFloat(product.price || product.Price || "0"),
|
|
41
|
+
quantity: parseInt(product.quantity || product.Quantity || "1", 10),
|
|
42
|
+
description: product.description || product.Description || "",
|
|
43
|
+
link: product.link || product.Link || "",
|
|
44
|
+
image: product.image || product.Image || "",
|
|
45
|
+
isbn: product.isbn || product.ISBN || "",
|
|
46
|
+
author: product.author || product.Author || "",
|
|
47
|
+
publisher: product.publisher || product.Publisher || "",
|
|
48
|
+
format: product.format || product.Format || "physical",
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
customerEmail,
|
|
54
|
+
customerFirstName,
|
|
55
|
+
customerLastName,
|
|
56
|
+
orderNumber,
|
|
57
|
+
orderAmount,
|
|
58
|
+
orderStatus,
|
|
59
|
+
billingAddress: data.billingAddress || data.Billing_address || "",
|
|
60
|
+
shippingAddress: data.shippingAddress || data.Shipping_address || "",
|
|
61
|
+
paymentMethod,
|
|
62
|
+
shippingMethod: data.shippingMethod || data.Shipping_method || "",
|
|
63
|
+
orderTime: data.orderTime || data.Order_time || new Date().toISOString(),
|
|
64
|
+
products,
|
|
65
|
+
storeName: data.storeName || data.Store_name || "",
|
|
66
|
+
storeUrl: data.storeUrl || data.Store_url || "",
|
|
67
|
+
ip: data.ip || data.IP || "",
|
|
68
|
+
contactRefId: data.contactRefId || data._id?.toString() || endUser?._id?.toString() || "",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
5
72
|
export async function triggerEventToStartAutomation(params: { apiKey: string; eventName: string; data: any }) {
|
|
6
73
|
try {
|
|
7
74
|
const { apiKey, eventName, data } = params;
|
|
8
75
|
if (!apiKey || !eventName || !data) {
|
|
9
76
|
throw new CustomError("Missing_API_KEY_TRIGGER_EVENT", 400, "Missing API key or event name or data");
|
|
10
77
|
}
|
|
11
|
-
|
|
78
|
+
|
|
79
|
+
// Check if this is an ecommerce event (book purchases, VOD, tickets, abandoned carts)
|
|
80
|
+
if (isEcommerceEvent(eventName)) {
|
|
81
|
+
const ecommerceEventType = parseEcommerceEventType(eventName);
|
|
82
|
+
if (ecommerceEventType) {
|
|
83
|
+
// Handle ecommerce events differently
|
|
84
|
+
logger.info(`Processing ecommerce event: ${eventName}`);
|
|
85
|
+
|
|
86
|
+
// Normalize the data from CRM format to InfoRu format
|
|
87
|
+
const normalizedData = normalizeEcommerceData(data, data.endUser);
|
|
88
|
+
|
|
89
|
+
// Validate that normalized data has required fields
|
|
90
|
+
if (!normalizedData.customerEmail || !normalizedData.orderNumber || !normalizedData.products || normalizedData.products.length === 0) {
|
|
91
|
+
throw new CustomError(
|
|
92
|
+
"INVALID_ECOMMERCE_DATA",
|
|
93
|
+
400,
|
|
94
|
+
`Ecommerce data must include customerEmail, orderNumber, and products array. Received: ${JSON.stringify({
|
|
95
|
+
customerEmail: normalizedData.customerEmail,
|
|
96
|
+
orderNumber: normalizedData.orderNumber,
|
|
97
|
+
productsCount: normalizedData.products?.length
|
|
98
|
+
})}`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
logger.debug(`Normalized ecommerce data for event ${eventName}`, {
|
|
103
|
+
orderNumber: normalizedData.orderNumber,
|
|
104
|
+
customerEmail: normalizedData.customerEmail,
|
|
105
|
+
productsCount: normalizedData.products.length
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Send to ecommerce API
|
|
109
|
+
return await sendEcommerceOrder({
|
|
110
|
+
apiKey,
|
|
111
|
+
eventType: ecommerceEventType,
|
|
112
|
+
data: normalizedData
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Handle regular automation triggers
|
|
118
|
+
const normalizeContact = prepareContactsPayload({ endUser: data });
|
|
12
119
|
const json = {
|
|
13
120
|
Data: {
|
|
14
121
|
ApiEventName: eventName,
|