@kb0912/notification-brevo 0.0.1 → 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/.medusa/server/src/config.js +13 -0
- package/.medusa/server/src/jobs/abandoned-cart.js +2 -7
- package/.medusa/server/src/loaders/brevo.js +13 -0
- package/.medusa/server/src/providers/notifications-brevo/index.js +18 -4
- package/.medusa/server/src/providers/notifications-brevo/services.js +35 -24
- package/.medusa/server/src/providers/notifications-brevo/types/index.js +3 -0
- package/.medusa/server/src/subscribers/customer-created.js +4 -17
- package/.medusa/server/src/subscribers/shipment-created.js +17 -0
- package/.medusa/server/src/workflows/send-abandoned-cart.js +3 -3
- package/.medusa/server/src/workflows/send-order-confirmation.js +13 -69
- package/.medusa/server/src/workflows/steps/check-abandoned-carts.js +38 -33
- package/.medusa/server/src/workflows/steps/send-notification.js +1 -1
- package/README.md +1 -0
- package/package.json +3 -3
- package/.medusa/server/src/loaders/abandoned-cart.js +0 -8
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.abandonedCartConfig = void 0;
|
|
4
|
+
exports.abandonedCartConfig = {
|
|
5
|
+
abandoned_carts: process.env.ENABLE_ABANDONED_CARTS === "true" || false,
|
|
6
|
+
checks: [
|
|
7
|
+
{ delay: process.env.BREVO_CART_FIRST_DELAY || 24 },
|
|
8
|
+
{ delay: process.env.BREVO_CART_SECOND_DELAY },
|
|
9
|
+
{ delay: process.env.BREVO_CART_THIRD_DELAY },
|
|
10
|
+
].filter((check) => // Type guard để ép kiểu
|
|
11
|
+
check.delay !== undefined && check.delay !== null && check.delay !== ""),
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFLZSxRQUFBLG1CQUFtQixHQUFHO0lBQ2pDLGVBQWUsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLHNCQUFzQixLQUFLLE1BQU0sSUFBSSxLQUFLO0lBQ3ZFLE1BQU0sRUFBRTtRQUNOLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLElBQUksRUFBRSxFQUFDO1FBQ2xELEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLEVBQUU7UUFDOUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsRUFBRTtLQUM5QyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBa0IsRUFBRSxDQUFDLHdCQUF3QjtLQUMxRCxLQUFLLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLENBQUMsS0FBSyxLQUFLLEVBQUUsQ0FDeEU7Q0FDRixDQUFDIn0=
|
|
@@ -5,15 +5,10 @@ exports.default = checkAbandonedCartsJob;
|
|
|
5
5
|
const check_abandoned_carts_1 = require("../workflows/steps/check-abandoned-carts");
|
|
6
6
|
async function checkAbandonedCartsJob(container) {
|
|
7
7
|
const logger = container.resolve("logger");
|
|
8
|
-
console.log("Registered services:", container.registrations); // Debug container
|
|
9
|
-
const myNotificationProvider = container.resolve("brevo");
|
|
10
|
-
const providerOptions = myNotificationProvider.options; // Lấy options từ BrevoProviderService
|
|
11
8
|
try {
|
|
12
|
-
logger.info("Running check-abandoned-carts scheduled job...");
|
|
13
9
|
await (0, check_abandoned_carts_1.checkAbandonedCartsWorkflow)(container).run({
|
|
14
10
|
input: {
|
|
15
|
-
container,
|
|
16
|
-
options: providerOptions.abandoned_cart, // Truyền abandoned_cart options
|
|
11
|
+
container,
|
|
17
12
|
},
|
|
18
13
|
});
|
|
19
14
|
}
|
|
@@ -25,4 +20,4 @@ exports.config = {
|
|
|
25
20
|
name: "check-abandoned-carts",
|
|
26
21
|
schedule: "* * * * *", // Chạy mỗi giờ
|
|
27
22
|
};
|
|
28
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJhbmRvbmVkLWNhcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvam9icy9hYmFuZG9uZWQtY2FydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFHQSx5Q0FhQztBQWZELG9GQUF1RjtBQUV4RSxLQUFLLFVBQVUsc0JBQXNCLENBQUMsU0FBMEI7SUFDN0UsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUUzQyxJQUFJLENBQUM7UUFFSCxNQUFNLElBQUEsbURBQTJCLEVBQUMsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDO1lBQy9DLEtBQUssRUFBRTtnQkFDTCxTQUFTO2FBQ1Y7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE1BQU0sQ0FBQyxLQUFLLENBQUMsK0NBQStDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDdkUsQ0FBQztBQUNILENBQUM7QUFFWSxRQUFBLE1BQU0sR0FBRztJQUNwQixJQUFJLEVBQUUsdUJBQXVCO0lBQzdCLFFBQVEsRUFBRSxXQUFXLEVBQUUsZUFBZTtDQUN2QyxDQUFDIn0=
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = abandonedCartLoader;
|
|
7
|
+
const abandoned_cart_1 = __importDefault(require("../jobs/abandoned-cart"));
|
|
8
|
+
async function abandonedCartLoader({ container, options, }) {
|
|
9
|
+
const logger = container.resolve("logger");
|
|
10
|
+
abandoned_cart_1.default;
|
|
11
|
+
logger.info("Initializing abandoned cart loader...");
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJldm8uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbG9hZGVycy9icmV2by50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVlBLHNDQVVDO0FBakJELDRFQUE0RDtBQU83QyxLQUFLLFVBQVUsbUJBQW1CLENBQUMsRUFDOUMsU0FBUyxFQUNULE9BQU8sR0FDTztJQUNoQixNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRTNDLHdCQUFzQixDQUFBO0lBQ3RCLE1BQU0sQ0FBQyxJQUFJLENBQUMsdUNBQXVDLENBQUMsQ0FBQztBQUd2RCxDQUFDIn0=
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
18
|
};
|
|
5
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.BREVO_MODULE = void 0;
|
|
7
20
|
const services_1 = __importDefault(require("./services"));
|
|
8
21
|
const utils_1 = require("@medusajs/framework/utils");
|
|
9
|
-
|
|
10
|
-
|
|
22
|
+
__exportStar(require("./types"), exports);
|
|
23
|
+
__exportStar(require("../../jobs/abandoned-cart"), exports);
|
|
24
|
+
exports.default = (0, utils_1.ModuleProvider)(utils_1.Modules.NOTIFICATION, {
|
|
11
25
|
services: [services_1.default],
|
|
12
26
|
});
|
|
13
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL25vdGlmaWNhdGlvbnMtYnJldm8vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUNBLDBEQUE2QztBQUM3QyxxREFHa0M7QUFFbEMsMENBQXVCO0FBQ3ZCLDREQUF5QztBQUV6QyxrQkFBZSxJQUFBLHNCQUFjLEVBQUMsZUFBTyxDQUFDLFlBQVksRUFBRTtJQUNsRCxRQUFRLEVBQUUsQ0FBQyxrQkFBb0IsQ0FBQztDQUVqQyxDQUFDLENBQUEifQ==
|
|
@@ -40,12 +40,11 @@ class BrevoProviderService extends utils_1.AbstractNotificationProviderService {
|
|
|
40
40
|
super();
|
|
41
41
|
this.options = options;
|
|
42
42
|
this.logger = logger;
|
|
43
|
-
console.log("BrevoProviderService initialized with options:", options);
|
|
44
43
|
if (!this.options.apiKey) {
|
|
45
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "BREVO_API_KEY
|
|
44
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "BREVO_API_KEY need to be set");
|
|
46
45
|
}
|
|
47
46
|
if (!this.options.from) {
|
|
48
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "BREVO_FROM_EMAIL
|
|
47
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "BREVO_FROM_EMAIL need to be set");
|
|
49
48
|
}
|
|
50
49
|
this.apiInstance = new Brevo.TransactionalEmailsApi();
|
|
51
50
|
this.apiInstance.setApiKey(Brevo.TransactionalEmailsApiApiKeys.apiKey, this.options.apiKey);
|
|
@@ -57,18 +56,29 @@ class BrevoProviderService extends utils_1.AbstractNotificationProviderService {
|
|
|
57
56
|
switch (template) {
|
|
58
57
|
case "order.placed":
|
|
59
58
|
templateId = parseInt(this.options.orderPlacedTemplateId);
|
|
59
|
+
const order = data.order;
|
|
60
|
+
// Tạo formatter dựa trên currency_code
|
|
61
|
+
const formatter = new Intl.NumberFormat([], {
|
|
62
|
+
style: "currency",
|
|
63
|
+
currencyDisplay: "narrowSymbol",
|
|
64
|
+
currency: order.currency_code.toUpperCase(), // "VND"
|
|
65
|
+
});
|
|
60
66
|
params = {
|
|
61
|
-
order_id:
|
|
62
|
-
email:
|
|
63
|
-
currency_code:
|
|
64
|
-
display_id:
|
|
65
|
-
total:
|
|
66
|
-
customer_name:
|
|
67
|
-
items:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
order_id: order?.id,
|
|
68
|
+
email: order?.email,
|
|
69
|
+
currency_code: order?.currency_code,
|
|
70
|
+
display_id: order?.display_id,
|
|
71
|
+
total: formatter.format(order?.total),
|
|
72
|
+
customer_name: order?.shipping_address?.first_name,
|
|
73
|
+
items: order?.items.map((item) => ({
|
|
74
|
+
...item,
|
|
75
|
+
unit_price: formatter.format(item.total),
|
|
76
|
+
})),
|
|
77
|
+
shipping_address: order?.shipping_address,
|
|
78
|
+
shipping_subtotal: formatter.format(order?.shipping_subtotal),
|
|
79
|
+
shipping_methods: order?.shipping_methods,
|
|
80
|
+
payment_collections: order?.payment_collections?.payments,
|
|
81
|
+
fulfillments: order?.fulfillments,
|
|
72
82
|
};
|
|
73
83
|
this.logger.info(JSON.stringify(params, null, 2));
|
|
74
84
|
break;
|
|
@@ -76,14 +86,14 @@ class BrevoProviderService extends utils_1.AbstractNotificationProviderService {
|
|
|
76
86
|
templateId = parseInt(this.options.orderCanceledTemplateId);
|
|
77
87
|
params = {
|
|
78
88
|
order_id: data.order?.id,
|
|
79
|
-
customer_name: data.order?.billing_address?.first_name
|
|
89
|
+
customer_name: data.order?.billing_address?.first_name,
|
|
80
90
|
};
|
|
81
91
|
break;
|
|
82
92
|
case "customer.created":
|
|
83
93
|
templateId = parseInt(this.options.customerCreatedTemplateId);
|
|
84
94
|
params = {
|
|
85
95
|
name: data.customer?.first_name + " " + (data.customer?.last_name || ""),
|
|
86
|
-
phone: data.customer?.phone
|
|
96
|
+
phone: data.customer?.phone,
|
|
87
97
|
customer_id: data.customer?.id,
|
|
88
98
|
};
|
|
89
99
|
break;
|
|
@@ -92,18 +102,19 @@ class BrevoProviderService extends utils_1.AbstractNotificationProviderService {
|
|
|
92
102
|
params = {
|
|
93
103
|
cart_id: data.cart?.id,
|
|
94
104
|
created_at: data.cart?.created_at,
|
|
95
|
-
name: data.cart?.name
|
|
96
|
-
phone: data.cart?.phone
|
|
105
|
+
name: data.cart?.name,
|
|
106
|
+
phone: data.cart?.phone,
|
|
107
|
+
items: data.cart?.items,
|
|
97
108
|
};
|
|
98
109
|
break;
|
|
99
110
|
default:
|
|
100
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Template ${template}
|
|
111
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Template ${template} is not supported`);
|
|
101
112
|
}
|
|
102
113
|
if (isNaN(templateId) || templateId === 0) {
|
|
103
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Template ID
|
|
114
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Template ID for ${template} is not set in options`);
|
|
104
115
|
}
|
|
105
116
|
if (!to) {
|
|
106
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `
|
|
117
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Email is not found for ${template}`);
|
|
107
118
|
}
|
|
108
119
|
const sendSmtpEmail = new Brevo.SendSmtpEmail();
|
|
109
120
|
sendSmtpEmail.sender = { email: this.options.from };
|
|
@@ -118,8 +129,8 @@ class BrevoProviderService extends utils_1.AbstractNotificationProviderService {
|
|
|
118
129
|
};
|
|
119
130
|
}
|
|
120
131
|
catch (error) {
|
|
121
|
-
this.logger.error(`
|
|
122
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "
|
|
132
|
+
this.logger.error(`Error while sending email ${to}:`, error);
|
|
133
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Email is not send");
|
|
123
134
|
}
|
|
124
135
|
}
|
|
125
136
|
async resend(notification) {
|
|
@@ -128,4 +139,4 @@ class BrevoProviderService extends utils_1.AbstractNotificationProviderService {
|
|
|
128
139
|
}
|
|
129
140
|
BrevoProviderService.identifier = "brevo";
|
|
130
141
|
exports.default = BrevoProviderService;
|
|
131
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
142
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL25vdGlmaWNhdGlvbnMtYnJldm8vc2VydmljZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxxREFHbUM7QUFNbkMsdURBQXlDO0FBS3pDLE1BQU0sb0JBQXFCLFNBQVEsMkNBQW1DO0lBT3BFLFlBQVksRUFBRSxNQUFNLEVBQXNCLEVBQUUsT0FBNEI7UUFDdEUsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUVyQixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN6QixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5Qiw4QkFBOEIsQ0FDL0IsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN2QixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5QixpQ0FBaUMsQ0FDbEMsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksS0FBSyxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFDdEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQ3hCLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxNQUFNLEVBQzFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUNwQixDQUFDO0lBQ0osQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJLENBQ1IsWUFBeUM7UUFFekMsTUFBTSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEdBQUcs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
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL25vdGlmaWNhdGlvbnMtYnJldm8vdHlwZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
|
|
@@ -4,24 +4,11 @@ exports.config = void 0;
|
|
|
4
4
|
exports.default = customerCreatedHandler;
|
|
5
5
|
const send_customer_created_1 = require("../workflows/send-customer-created");
|
|
6
6
|
async function customerCreatedHandler({ event, container, }) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
try {
|
|
11
|
-
// Gọi workflow và in thông tin trước khi chạy
|
|
12
|
-
console.log("Running sendCustomerCreatedWorkflow with input:", { id: event.data.id });
|
|
13
|
-
const result = await (0, send_customer_created_1.sendCustomerCreatedWorkflow)(container).run({
|
|
14
|
-
input: { id: event.data.id },
|
|
15
|
-
});
|
|
16
|
-
console.log("Workflow result:", result);
|
|
17
|
-
}
|
|
18
|
-
catch (error) {
|
|
19
|
-
// In lỗi chi tiết nếu có
|
|
20
|
-
console.error("Error in customer.created subscriber:", error);
|
|
21
|
-
throw error; // Ném lại lỗi để Medusa ghi log
|
|
22
|
-
}
|
|
7
|
+
const result = await (0, send_customer_created_1.sendCustomerCreatedWorkflow)(container).run({
|
|
8
|
+
input: { id: event.data.id },
|
|
9
|
+
});
|
|
23
10
|
}
|
|
24
11
|
exports.config = {
|
|
25
12
|
event: "customer.created",
|
|
26
13
|
};
|
|
27
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tZXItY3JlYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zdWJzY3JpYmVycy9jdXN0b21lci1jcmVhdGVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUdBLHlDQVVDO0FBWkQsOEVBQWlGO0FBRWxFLEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxFQUNuRCxLQUFLLEVBQ0wsU0FBUyxHQUNzQjtJQUc3QixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEsbURBQTJCLEVBQUMsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQzlELEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTtLQUM3QixDQUFDLENBQUM7QUFFUCxDQUFDO0FBRVksUUFBQSxNQUFNLEdBQXFCO0lBQ3RDLEtBQUssRUFBRSxrQkFBa0I7Q0FDMUIsQ0FBQyJ9
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.config = void 0;
|
|
4
|
+
exports.default = orderPlacedHandler;
|
|
5
|
+
const send_order_confirmation_1 = require("../workflows/send-order-confirmation");
|
|
6
|
+
async function orderPlacedHandler({ event: { data }, container, }) {
|
|
7
|
+
await (0, send_order_confirmation_1.sendOrderConfirmationWorkflow)(container)
|
|
8
|
+
.run({
|
|
9
|
+
input: {
|
|
10
|
+
id: data.id
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
exports.config = {
|
|
15
|
+
event: "shipment.created",
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hpcG1lbnQtY3JlYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zdWJzY3JpYmVycy9zaGlwbWVudC1jcmVhdGVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQVFFLHFDQVVDO0FBWkQsa0ZBQW9GO0FBRXJFLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxFQUMvQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFDZixTQUFTLEdBQ3NCO0lBQy9CLE1BQU0sSUFBQSx1REFBNkIsRUFBQyxTQUFTLENBQUM7U0FDM0MsR0FBRyxDQUFDO1FBQ0gsS0FBSyxFQUFFO1lBQ0wsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFO1NBQ1o7S0FDRixDQUFDLENBQUE7QUFDTixDQUFDO0FBRVksUUFBQSxNQUFNLEdBQXFCO0lBQ3RDLEtBQUssRUFBRSxrQkFBa0I7Q0FDMUIsQ0FBQSJ9
|
|
@@ -20,7 +20,7 @@ exports.sendAbandonedCartWorkflow = (0, workflows_sdk_1.createWorkflow)("send-ab
|
|
|
20
20
|
});
|
|
21
21
|
const prepareNotificationStep = (0, workflows_sdk_1.createStep)("prepare-abandoned-cart-notification", async (input) => {
|
|
22
22
|
const carts = input.data;
|
|
23
|
-
console.log("Cart data retrieved:", carts);
|
|
23
|
+
//console.log("Cart data retrieved:", carts);
|
|
24
24
|
const notificationData = [
|
|
25
25
|
{
|
|
26
26
|
to: carts[0].email,
|
|
@@ -37,11 +37,11 @@ exports.sendAbandonedCartWorkflow = (0, workflows_sdk_1.createWorkflow)("send-ab
|
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
39
|
];
|
|
40
|
-
console.log("Prepared abandoned cart notification data:", notificationData);
|
|
40
|
+
//console.log("Prepared abandoned cart notification data:", notificationData);
|
|
41
41
|
return new workflows_sdk_1.StepResponse(notificationData);
|
|
42
42
|
});
|
|
43
43
|
const notificationData = prepareNotificationStep(cartStep);
|
|
44
44
|
const notificationStep = (0, send_notification_1.sendNotificationStep)(notificationData);
|
|
45
45
|
return new workflows_sdk_1.WorkflowResponse(notificationStep);
|
|
46
46
|
});
|
|
47
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
47
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VuZC1hYmFuZG9uZWQtY2FydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy93b3JrZmxvd3Mvc2VuZC1hYmFuZG9uZWQtY2FydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxRUFBK0c7QUFDL0csNERBQWdFO0FBQ2hFLGlFQUFpRTtBQU9wRCxRQUFBLHlCQUF5QixHQUFHLElBQUEsOEJBQWMsRUFDckQscUJBQXFCLEVBQ3JCLENBQUMsRUFBRSxNQUFNLEVBQWlCLEVBQUUsRUFBRTtJQUM1QixNQUFNLFFBQVEsR0FBRyxJQUFBLDhCQUFpQixFQUFDO1FBQ2pDLE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFO1lBQ04sSUFBSTtZQUNKLE9BQU87WUFDUCxZQUFZO1lBQ1oscUJBQXFCO1lBQ3JCLG9CQUFvQjtZQUNwQixnQkFBZ0I7WUFDaEIsU0FBUztTQUNWO1FBQ0QsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRTtLQUN4QixDQUFDLENBQUM7SUFFSCxNQUFNLHVCQUF1QixHQUFHLElBQUEsMEJBQVUsRUFDeEMscUNBQXFDLEVBQ3JDLEtBQUssRUFBRSxLQUFzQixFQUFFLEVBQUU7UUFDL0IsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQztRQUN6Qiw2Q0FBNkM7UUFFN0MsTUFBTSxnQkFBZ0IsR0FBNEI7WUFDaEQ7Z0JBQ0UsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLO2dCQUNsQixPQUFPLEVBQUUsT0FBTztnQkFDaEIsUUFBUSxFQUFFLGdCQUFnQjtnQkFDMUIsSUFBSSxFQUFFO29CQUNKLElBQUksRUFBRTt3QkFDSixFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7d0JBQ2YsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVO3dCQUMvQixJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLFVBQVUsSUFBSSxFQUFFLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLFNBQVMsSUFBSSxFQUFFLENBQUM7d0JBQ3hGLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLEtBQUssSUFBSSx3QkFBd0I7d0JBQzNELEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLHFDQUFxQztxQkFDNUQ7aUJBQ0Y7YUFDRjtTQUNGLENBQUM7UUFFRiw4RUFBOEU7UUFDOUUsT0FBTyxJQUFJLDRCQUFZLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUM1QyxDQUFDLENBQ0YsQ0FBQztJQUVGLE1BQU0sZ0JBQWdCLEdBQUcsdUJBQXVCLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDM0QsTUFBTSxnQkFBZ0IsR0FBRyxJQUFBLHdDQUFvQixFQUFDLGdCQUFnQixDQUFDLENBQUM7SUFFaEUsT0FBTyxJQUFJLGdDQUFnQixDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFDaEQsQ0FBQyxDQUNGLENBQUMifQ==
|
|
@@ -5,78 +5,22 @@ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
|
5
5
|
const core_flows_1 = require("@medusajs/medusa/core-flows");
|
|
6
6
|
const send_notification_1 = require("./steps/send-notification");
|
|
7
7
|
exports.sendOrderConfirmationWorkflow = (0, workflows_sdk_1.createWorkflow)("send-order-confirmation", ({ id }) => {
|
|
8
|
-
|
|
9
|
-
const orderStep = (0, core_flows_1.useQueryGraphStep)({
|
|
8
|
+
const { data: orders } = (0, core_flows_1.useQueryGraphStep)({
|
|
10
9
|
entity: "order",
|
|
11
|
-
fields: [
|
|
12
|
-
"id",
|
|
13
|
-
"email",
|
|
14
|
-
"currency_code",
|
|
15
|
-
"display_id",
|
|
16
|
-
"total",
|
|
17
|
-
"items.*",
|
|
18
|
-
"billing_address.*",
|
|
19
|
-
"shipping_address.*",
|
|
20
|
-
"payment_collections.*",
|
|
21
|
-
"fulfillments.*",
|
|
22
|
-
"shipping_subtotal"
|
|
23
|
-
],
|
|
10
|
+
fields: ["id", "email", "currency_code", "display_id", "shipping_subtotal", "total", "items.*", "shipping_address.*", "payment_collections.*", "payment_collections.payments.*", "fulfillments.*", "shipping_methods.*"],
|
|
24
11
|
filters: { id },
|
|
25
12
|
});
|
|
26
|
-
//
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const order = orders[0];
|
|
37
|
-
// Tạo formatter dựa trên currency_code của đơn hàng
|
|
38
|
-
const formatter = new Intl.NumberFormat([], {
|
|
39
|
-
style: "currency",
|
|
40
|
-
currencyDisplay: "narrowSymbol",
|
|
41
|
-
currency: order.currency_code.toUpperCase(), // "VND"
|
|
42
|
-
});
|
|
43
|
-
// Dùng payment_collections.amount thay vì total
|
|
44
|
-
const formattedShippingTotal = formatter.format(order.shipping_subtotal);
|
|
45
|
-
const formattedTotal = formatter.format(order.total);
|
|
46
|
-
// Định dạng unit_price cho từng item (giả sử dữ liệu gốc cần điều chỉnh)
|
|
47
|
-
const formattedItems = order.items.map((item) => ({
|
|
48
|
-
...item, // Giữ nguyên các trường khác
|
|
49
|
-
unit_price: formatter.format(item.unit_price), // Dùng giá trị từ log
|
|
50
|
-
}));
|
|
51
|
-
const notificationData = [
|
|
52
|
-
{
|
|
53
|
-
to: order.email,
|
|
54
|
-
channel: "email",
|
|
55
|
-
template: "order.placed",
|
|
56
|
-
data: {
|
|
57
|
-
order: {
|
|
58
|
-
id: order.id,
|
|
59
|
-
email: order.email,
|
|
60
|
-
currency_code: order.currency_code,
|
|
61
|
-
display_id: order.display_id,
|
|
62
|
-
total: formattedTotal,
|
|
63
|
-
shipping_total: formattedShippingTotal,
|
|
64
|
-
items: formattedItems,
|
|
65
|
-
billing_address: order.billing_address,
|
|
66
|
-
shipping_address: order.shipping_address,
|
|
67
|
-
payment_collections: order.payment_collections,
|
|
68
|
-
fulfillments: order.fulfillments,
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
];
|
|
73
|
-
console.log("Prepared order confirmed notification data:", JSON.stringify(notificationData, null, 2));
|
|
74
|
-
return new workflows_sdk_1.StepResponse(notificationData);
|
|
75
|
-
});
|
|
76
|
-
// Liên kết các bước
|
|
77
|
-
const resolvedOrders = logOrderDataStep(orderStep);
|
|
78
|
-
const notificationData = prepareNotificationStep(resolvedOrders);
|
|
13
|
+
//console.log("Order data retrieved (resolved):", JSON.stringify(orders, null, 2));
|
|
14
|
+
const notificationData = [
|
|
15
|
+
{
|
|
16
|
+
to: orders[0].email,
|
|
17
|
+
channel: "email",
|
|
18
|
+
template: "order.placed",
|
|
19
|
+
data: { order: orders[0] },
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
//console.log("Prepared order confirmed notification data:", JSON.stringify(notificationData, null, 2));
|
|
79
23
|
const notification = (0, send_notification_1.sendNotificationStep)(notificationData);
|
|
80
24
|
return new workflows_sdk_1.WorkflowResponse(notification);
|
|
81
25
|
});
|
|
82
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VuZC1vcmRlci1jb25maXJtYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3NlbmQtb3JkZXItY29uZmlybWF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUFxRjtBQUNyRiw0REFBZ0U7QUFDaEUsaUVBQWlFO0FBT3BELFFBQUEsNkJBQTZCLEdBQUcsSUFBQSw4QkFBYyxFQUN6RCx5QkFBeUIsRUFDekIsQ0FBQyxFQUFFLEVBQUUsRUFBaUIsRUFBRSxFQUFFO0lBQ3hCLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBQSw4QkFBaUIsRUFBQztRQUN6QyxNQUFNLEVBQUUsT0FBTztRQUNmLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxtQkFBbUIsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLG9CQUFvQixFQUFFLHVCQUF1QixFQUFDLGdDQUFnQyxFQUFFLGdCQUFnQixFQUFFLG9CQUFvQixDQUFDO1FBQ3ZOLE9BQU8sRUFBRSxFQUFFLEVBQUUsRUFBRTtLQUNoQixDQUFDLENBQUM7SUFDSCxtRkFBbUY7SUFFbkYsTUFBTSxnQkFBZ0IsR0FBNEI7UUFDaEQ7WUFDRSxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUs7WUFDbkIsT0FBTyxFQUFFLE9BQU87WUFDaEIsUUFBUSxFQUFFLGNBQWM7WUFDeEIsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRTtTQUMzQjtLQUNGLENBQUM7SUFDRix3R0FBd0c7SUFDeEcsTUFBTSxZQUFZLEdBQUcsSUFBQSx3Q0FBb0IsRUFBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBRTVELE9BQU8sSUFBSSxnQ0FBZ0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUM1QyxDQUFDLENBQ0YsQ0FBQyJ9
|
|
@@ -4,56 +4,61 @@ exports.checkAbandonedCartsWorkflow = void 0;
|
|
|
4
4
|
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
5
5
|
const utils_1 = require("@medusajs/framework/utils");
|
|
6
6
|
const send_abandoned_cart_1 = require("../send-abandoned-cart");
|
|
7
|
-
|
|
7
|
+
const config_1 = require("../../config");
|
|
8
|
+
exports.checkAbandonedCartsWorkflow = (0, workflows_sdk_1.createWorkflow)("check-abandoned-carts", ({ container }) => {
|
|
8
9
|
const checkCartsStep = (0, workflows_sdk_1.createStep)("check-abandoned-carts-step", async (_, { container: stepContainer }) => {
|
|
9
10
|
const cartModuleService = stepContainer.resolve(utils_1.Modules.CART);
|
|
10
11
|
const logger = stepContainer.resolve("logger");
|
|
11
12
|
const query = stepContainer.resolve("query");
|
|
13
|
+
if (!config_1.abandonedCartConfig.abandoned_carts) {
|
|
14
|
+
logger.info("Abandoned carts feature is disabled in config.");
|
|
15
|
+
return new workflows_sdk_1.StepResponse(null);
|
|
16
|
+
}
|
|
17
|
+
if (!config_1.abandonedCartConfig.checks.length) {
|
|
18
|
+
logger.info("No abandoned cart checks configured.");
|
|
19
|
+
return new workflows_sdk_1.StepResponse(null);
|
|
20
|
+
}
|
|
21
|
+
logger.info("Running check-abandoned-carts scheduled job...");
|
|
12
22
|
const now = new Date();
|
|
13
23
|
const seventyTwoHoursAgo = new Date(now.getTime() - 72 * 60 * 60 * 1000);
|
|
14
|
-
//
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const thirdCheck = new Date(now.getTime() - parseInt(options.third.delay) * 60 * 60 * 1000);
|
|
18
|
-
logger.info("Starting to check abandoned carts...");
|
|
19
|
-
logger.info(`Checking intervals: first=${options.first.delay}, second=${options.second.delay}, third=${options.third.delay}`);
|
|
24
|
+
// Tính các ngưỡng kiểm tra dựa trên số phần tử thực tế trong checks
|
|
25
|
+
const checkTimes = config_1.abandonedCartConfig.checks.map(check => new Date(now.getTime() - parseInt(check.delay) * 60 * 60 * 1000));
|
|
26
|
+
//logger.info(`Checking intervals: ${abandonedCartConfig.checks.map(c => `${c.delay} hours`).join(", ")}`);
|
|
20
27
|
const { data: carts } = await query.graph({
|
|
21
28
|
entity: "cart",
|
|
22
|
-
fields: [
|
|
29
|
+
fields: [
|
|
30
|
+
"id", "email", "created_at", "updated_at", "completed_at", "metadata",
|
|
31
|
+
"items.id", "items.updated_at"
|
|
32
|
+
],
|
|
23
33
|
filters: {
|
|
24
34
|
completed_at: null,
|
|
25
35
|
email: { $ne: null },
|
|
26
36
|
updated_at: { $gte: seventyTwoHoursAgo.toISOString() },
|
|
27
37
|
},
|
|
28
38
|
});
|
|
29
|
-
logger.info(`Found ${carts.length} carts to check`);
|
|
39
|
+
//logger.info(`Found ${carts.length} carts to check`);
|
|
30
40
|
for (const cart of carts) {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
else if (updatedAt <= secondCheck && !notifiedFlags.second_abandonedcart_mail) {
|
|
46
|
-
logger.info(`Sending second abandoned cart email to ${cart.email} after ${options.second.delay} hours`);
|
|
47
|
-
await (0, send_abandoned_cart_1.sendAbandonedCartWorkflow)(stepContainer).run({ input: { cartId: cart.id } });
|
|
48
|
-
await cartModuleService.updateCarts(cart.id, {
|
|
49
|
-
metadata: { ...cart.metadata, second_abandonedcart_mail: true },
|
|
50
|
-
});
|
|
41
|
+
const latestItemUpdate = cart.items?.length > 0
|
|
42
|
+
? cart.items.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime())[0].updated_at
|
|
43
|
+
: cart.updated_at;
|
|
44
|
+
const check = new Date(latestItemUpdate);
|
|
45
|
+
const hoursSinceUpdate = Math.floor((now.getTime() - check.getTime()) / (1000 * 60 * 60));
|
|
46
|
+
const notifiedFlags = cart.metadata || {};
|
|
47
|
+
let actionIndex = -1;
|
|
48
|
+
for (let i = checkTimes.length - 1; i >= 0; i--) {
|
|
49
|
+
if (check < checkTimes[i] && !notifiedFlags[`abandonedcart_mail_${i + 1}`]) {
|
|
50
|
+
actionIndex = i;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
51
53
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
if (actionIndex >= 0) {
|
|
55
|
+
const delay = config_1.abandonedCartConfig.checks[actionIndex].delay;
|
|
56
|
+
const flagKey = `abandonedcart_mail_${actionIndex + 1}`;
|
|
57
|
+
//logger.info(`Cart ${cart.id}: check = ${check}, hoursSinceUpdate = ${hoursSinceUpdate}`);
|
|
58
|
+
//logger.info(`Sending abandoned cart email #${actionIndex + 1} to ${cart.email} after ${delay} hours`);
|
|
54
59
|
await (0, send_abandoned_cart_1.sendAbandonedCartWorkflow)(stepContainer).run({ input: { cartId: cart.id } });
|
|
55
60
|
await cartModuleService.updateCarts(cart.id, {
|
|
56
|
-
metadata: { ...
|
|
61
|
+
metadata: { ...notifiedFlags, [flagKey]: true },
|
|
57
62
|
});
|
|
58
63
|
}
|
|
59
64
|
}
|
|
@@ -63,4 +68,4 @@ exports.checkAbandonedCartsWorkflow = (0, workflows_sdk_1.createWorkflow)("check
|
|
|
63
68
|
const result = checkCartsStep();
|
|
64
69
|
return new workflows_sdk_1.WorkflowResponse(result);
|
|
65
70
|
});
|
|
66
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
71
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2stYWJhbmRvbmVkLWNhcnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zdGVwcy9jaGVjay1hYmFuZG9uZWQtY2FydHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBQStHO0FBQy9HLHFEQUFvRDtBQUNwRCxnRUFBbUU7QUFDbkUseUNBQW1EO0FBTXRDLFFBQUEsMkJBQTJCLEdBQUcsSUFBQSw4QkFBYyxFQUN2RCx1QkFBdUIsRUFDdkIsQ0FBQyxFQUFFLFNBQVMsRUFBaUIsRUFBRSxFQUFFO0lBQy9CLE1BQU0sY0FBYyxHQUFHLElBQUEsMEJBQVUsRUFDL0IsNEJBQTRCLEVBQzVCLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLEVBQUUsRUFBRTtRQUN4QyxNQUFNLGlCQUFpQixHQUFHLGFBQWEsQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzlELE1BQU0sTUFBTSxHQUFHLGFBQWEsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDL0MsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUU3QyxJQUFJLENBQUMsNEJBQW1CLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDekMsTUFBTSxDQUFDLElBQUksQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO1lBQzlELE9BQU8sSUFBSSw0QkFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hDLENBQUM7UUFFRCxJQUFJLENBQUMsNEJBQW1CLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sQ0FBQyxJQUFJLENBQUMsc0NBQXNDLENBQUMsQ0FBQztZQUNwRCxPQUFPLElBQUksNEJBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoQyxDQUFDO1FBRUQsTUFBTSxDQUFDLElBQUksQ0FBQyxnREFB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
|
|
@@ -8,4 +8,4 @@ exports.sendNotificationStep = (0, workflows_sdk_1.createStep)("send-notificatio
|
|
|
8
8
|
const notification = await notificationModuleService.createNotifications(data);
|
|
9
9
|
return new workflows_sdk_1.StepResponse(notification);
|
|
10
10
|
});
|
|
11
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VuZC1ub3RpZmljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3N0ZXBzL3NlbmQtbm90aWZpY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFEQUFtRDtBQUNuRCxxRUFBNEU7QUFJL0QsUUFBQSxvQkFBb0IsR0FBRyxJQUFBLDBCQUFVLEVBQzVDLG1CQUFtQixFQUNuQixLQUFLLEVBQUUsSUFBNkIsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDckQsTUFBTSx5QkFBeUIsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUNqRCxlQUFPLENBQUMsWUFBWSxDQUNyQixDQUFBO0lBSUQsTUFBTSxZQUFZLEdBQUcsTUFBTSx5QkFBeUIsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUM5RSxPQUFPLElBQUksNEJBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQTtBQUN2QyxDQUFDLENBQ0YsQ0FBQSJ9
|
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kb0912/notification-brevo",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
5
|
-
"author": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Sending email notification using Brevo.",
|
|
5
|
+
"author": "KBa (https://medusajs.com)",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"files": [
|
|
8
8
|
".medusa/server"
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = abandonedCartLoader;
|
|
4
|
-
async function abandonedCartLoader({ container, options, }) {
|
|
5
|
-
const logger = container.resolve("logger");
|
|
6
|
-
logger.info("Initializing abandoned cart loader...");
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJhbmRvbmVkLWNhcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbG9hZGVycy9hYmFuZG9uZWQtY2FydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVdBLHNDQVNDO0FBVGMsS0FBSyxVQUFVLG1CQUFtQixDQUFDLEVBQzlDLFNBQVMsRUFDVCxPQUFPLEdBQ087SUFDaEIsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUUzQyxNQUFNLENBQUMsSUFBSSxDQUFDLHVDQUF1QyxDQUFDLENBQUM7QUFHdkQsQ0FBQyJ9
|