order-management 0.0.8 → 0.0.9
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.
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.config = void 0;
|
|
4
|
+
exports.default = sendOrderEmailHandler;
|
|
5
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
6
|
+
/**
|
|
7
|
+
* Format address object as HTML
|
|
8
|
+
*/
|
|
9
|
+
function formatAddress(address) {
|
|
10
|
+
const parts = [];
|
|
11
|
+
if (address.first_name || address.last_name) {
|
|
12
|
+
parts.push(`${address.first_name || ""} ${address.last_name || ""}`.trim());
|
|
13
|
+
}
|
|
14
|
+
if (address.address_1) {
|
|
15
|
+
parts.push(String(address.address_1));
|
|
16
|
+
}
|
|
17
|
+
if (address.address_2) {
|
|
18
|
+
parts.push(String(address.address_2));
|
|
19
|
+
}
|
|
20
|
+
if (address.city || address.province || address.postal_code) {
|
|
21
|
+
const cityParts = [
|
|
22
|
+
address.city,
|
|
23
|
+
address.province,
|
|
24
|
+
address.postal_code,
|
|
25
|
+
].filter(Boolean).map(String);
|
|
26
|
+
parts.push(cityParts.join(", "));
|
|
27
|
+
}
|
|
28
|
+
if (address.country_code) {
|
|
29
|
+
parts.push(String(address.country_code));
|
|
30
|
+
}
|
|
31
|
+
if (address.phone) {
|
|
32
|
+
parts.push(`Phone: ${address.phone}`);
|
|
33
|
+
}
|
|
34
|
+
return parts.length > 0 ? parts.join("<br>") : "No address provided";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Format order data as HTML content
|
|
38
|
+
*/
|
|
39
|
+
function formatOrderDataAsHTML(orderData) {
|
|
40
|
+
const orderId = orderData.id || "N/A";
|
|
41
|
+
const orderStatus = orderData.status || "N/A";
|
|
42
|
+
const orderTotal = orderData.total || orderData.grand_total || "N/A";
|
|
43
|
+
const orderEmail = orderData.email || "N/A";
|
|
44
|
+
const orderDate = orderData.created_at || orderData.updated_at || new Date().toISOString();
|
|
45
|
+
// Format items if available
|
|
46
|
+
let itemsHTML = "";
|
|
47
|
+
if (Array.isArray(orderData.items)) {
|
|
48
|
+
itemsHTML = `
|
|
49
|
+
<table style="width: 100%; border-collapse: collapse; margin: 20px 0;">
|
|
50
|
+
<thead>
|
|
51
|
+
<tr style="background-color: #f5f5f5;">
|
|
52
|
+
<th style="padding: 10px; text-align: left; border: 1px solid #ddd;">Item</th>
|
|
53
|
+
<th style="padding: 10px; text-align: left; border: 1px solid #ddd;">Quantity</th>
|
|
54
|
+
<th style="padding: 10px; text-align: right; border: 1px solid #ddd;">Price</th>
|
|
55
|
+
</tr>
|
|
56
|
+
</thead>
|
|
57
|
+
<tbody>
|
|
58
|
+
${orderData.items.map((item) => {
|
|
59
|
+
const itemData = item;
|
|
60
|
+
return `
|
|
61
|
+
<tr>
|
|
62
|
+
<td style="padding: 10px; border: 1px solid #ddd;">${itemData.title || itemData.variant_title || "Item"}</td>
|
|
63
|
+
<td style="padding: 10px; border: 1px solid #ddd;">${itemData.quantity || 0}</td>
|
|
64
|
+
<td style="padding: 10px; text-align: right; border: 1px solid #ddd;">${itemData.unit_price || itemData.total || 0}</td>
|
|
65
|
+
</tr>
|
|
66
|
+
`;
|
|
67
|
+
}).join("")}
|
|
68
|
+
</tbody>
|
|
69
|
+
</table>
|
|
70
|
+
`;
|
|
71
|
+
}
|
|
72
|
+
// Format addresses if available
|
|
73
|
+
let addressesHTML = "";
|
|
74
|
+
if (orderData.shipping_address || orderData.billing_address) {
|
|
75
|
+
addressesHTML = `
|
|
76
|
+
<div style="margin: 20px 0;">
|
|
77
|
+
${orderData.shipping_address ? `
|
|
78
|
+
<div style="margin-bottom: 15px;">
|
|
79
|
+
<h3 style="margin-bottom: 10px;">Shipping Address</h3>
|
|
80
|
+
<div style="padding: 10px; background-color: #f9f9f9; border: 1px solid #ddd;">
|
|
81
|
+
${formatAddress(orderData.shipping_address)}
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
` : ""}
|
|
85
|
+
${orderData.billing_address ? `
|
|
86
|
+
<div>
|
|
87
|
+
<h3 style="margin-bottom: 10px;">Billing Address</h3>
|
|
88
|
+
<div style="padding: 10px; background-color: #f9f9f9; border: 1px solid #ddd;">
|
|
89
|
+
${formatAddress(orderData.billing_address)}
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
` : ""}
|
|
93
|
+
</div>
|
|
94
|
+
`;
|
|
95
|
+
}
|
|
96
|
+
return `
|
|
97
|
+
<!DOCTYPE html>
|
|
98
|
+
<html>
|
|
99
|
+
<head>
|
|
100
|
+
<meta charset="UTF-8">
|
|
101
|
+
<style>
|
|
102
|
+
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
|
103
|
+
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
|
104
|
+
.header { background-color: #4CAF50; color: white; padding: 20px; text-align: center; }
|
|
105
|
+
.content { padding: 20px; background-color: #ffffff; }
|
|
106
|
+
.order-info { background-color: #f5f5f5; padding: 15px; margin: 15px 0; border-radius: 5px; }
|
|
107
|
+
.order-info p { margin: 5px 0; }
|
|
108
|
+
</style>
|
|
109
|
+
</head>
|
|
110
|
+
<body>
|
|
111
|
+
<div class="container">
|
|
112
|
+
<div class="header">
|
|
113
|
+
<h1>Order Information</h1>
|
|
114
|
+
</div>
|
|
115
|
+
<div class="content">
|
|
116
|
+
<div class="order-info">
|
|
117
|
+
<p><strong>Order ID:</strong> ${orderId}</p>
|
|
118
|
+
<p><strong>Status:</strong> ${orderStatus}</p>
|
|
119
|
+
<p><strong>Total:</strong> ${orderTotal}</p>
|
|
120
|
+
<p><strong>Email:</strong> ${orderEmail}</p>
|
|
121
|
+
<p><strong>Date:</strong> ${orderDate}</p>
|
|
122
|
+
</div>
|
|
123
|
+
${itemsHTML}
|
|
124
|
+
${addressesHTML}
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</body>
|
|
128
|
+
</html>
|
|
129
|
+
`;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Prepare email payload for notification service
|
|
133
|
+
*/
|
|
134
|
+
function prepareEmailPayload(to, subject, orderData) {
|
|
135
|
+
const htmlContent = formatOrderDataAsHTML(orderData);
|
|
136
|
+
// Create plain text version from HTML
|
|
137
|
+
const textContent = htmlContent
|
|
138
|
+
.replace(/<[^>]*>/g, '') // Remove HTML tags
|
|
139
|
+
.replace(/\s+/g, ' ') // Collapse whitespace
|
|
140
|
+
.trim();
|
|
141
|
+
const payload = {
|
|
142
|
+
to,
|
|
143
|
+
channel: "email",
|
|
144
|
+
subject,
|
|
145
|
+
// Root level fields for SMTP providers
|
|
146
|
+
html: htmlContent,
|
|
147
|
+
text: textContent,
|
|
148
|
+
body: htmlContent, // Some providers expect 'body' field
|
|
149
|
+
template: htmlContent, // Some providers expect 'template' field
|
|
150
|
+
data: {
|
|
151
|
+
subject,
|
|
152
|
+
orderData,
|
|
153
|
+
html: htmlContent,
|
|
154
|
+
text: textContent,
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
return payload;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Subscriber handler for order.placed event
|
|
161
|
+
* Automatically sends email with order data when an order is placed
|
|
162
|
+
*/
|
|
163
|
+
async function sendOrderEmailHandler({ event: { data }, container, }) {
|
|
164
|
+
try {
|
|
165
|
+
// Extract order ID from event data
|
|
166
|
+
const orderId = data.id;
|
|
167
|
+
if (!orderId) {
|
|
168
|
+
console.error("[Order Email Subscriber] No order ID found in event data");
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
// Query order details if event only provides ID
|
|
172
|
+
// Check if data already has full order object
|
|
173
|
+
let orderData;
|
|
174
|
+
if (data.email && data.items) {
|
|
175
|
+
// Event already contains full order data
|
|
176
|
+
orderData = data;
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
// Query order details using query service
|
|
180
|
+
const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
|
|
181
|
+
const { data: orders = [] } = await query.graph({
|
|
182
|
+
entity: "order",
|
|
183
|
+
fields: [
|
|
184
|
+
"id",
|
|
185
|
+
"status",
|
|
186
|
+
"total",
|
|
187
|
+
"grand_total",
|
|
188
|
+
"email",
|
|
189
|
+
"created_at",
|
|
190
|
+
"updated_at",
|
|
191
|
+
"items.*",
|
|
192
|
+
"shipping_address.*",
|
|
193
|
+
"billing_address.*",
|
|
194
|
+
],
|
|
195
|
+
filters: { id: orderId },
|
|
196
|
+
});
|
|
197
|
+
const order = Array.isArray(orders) ? orders[0] : orders;
|
|
198
|
+
if (!order) {
|
|
199
|
+
console.error(`[Order Email Subscriber] Order with id ${orderId} not found`);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
orderData = order;
|
|
203
|
+
}
|
|
204
|
+
// Extract email from order data
|
|
205
|
+
const email = orderData.email;
|
|
206
|
+
if (!email || typeof email !== "string" || !email.includes("@")) {
|
|
207
|
+
console.error(`[Order Email Subscriber] No valid email found for order ${orderId}`);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
// Resolve notification service
|
|
211
|
+
const notificationService = container.resolve(utils_1.Modules.NOTIFICATION);
|
|
212
|
+
if (!notificationService) {
|
|
213
|
+
console.error("[Order Email Subscriber] Notification service is not configured");
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
// Prepare email payload
|
|
217
|
+
const subject = "Order Confirmation";
|
|
218
|
+
const payload = prepareEmailPayload(email, subject, orderData);
|
|
219
|
+
// Send email
|
|
220
|
+
try {
|
|
221
|
+
if (typeof notificationService.createNotifications === "function") {
|
|
222
|
+
await notificationService.createNotifications([payload]);
|
|
223
|
+
console.log(`[Order Email Subscriber] Email sent successfully for order ${orderId}`);
|
|
224
|
+
}
|
|
225
|
+
else if (typeof notificationService.create === "function") {
|
|
226
|
+
await notificationService.create(payload);
|
|
227
|
+
console.log(`[Order Email Subscriber] Email sent successfully for order ${orderId}`);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
console.error("[Order Email Subscriber] Notification service does not support sending notifications");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
235
|
+
console.error(`[Order Email Subscriber] Failed to send email for order ${orderId}:`, errorMessage);
|
|
236
|
+
// Don't throw - subscriber errors shouldn't break the order flow
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
241
|
+
console.error("[Order Email Subscriber] Error processing order email:", errorMessage);
|
|
242
|
+
// Don't throw - subscriber errors shouldn't break the order flow
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Subscriber configuration
|
|
247
|
+
*/
|
|
248
|
+
exports.config = {
|
|
249
|
+
event: "order.placed",
|
|
250
|
+
};
|
|
251
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VuZC1vcmRlci1lbWFpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zdWJzY3JpYmVycy9zZW5kLW9yZGVyLWVtYWlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQXlNQSx3Q0FpR0M7QUF6U0QscURBQThFO0FBUTlFOztHQUVHO0FBQ0gsU0FBUyxhQUFhLENBQUMsT0FBZ0M7SUFDckQsTUFBTSxLQUFLLEdBQWEsRUFBRSxDQUFBO0lBRTFCLElBQUksT0FBTyxDQUFDLFVBQVUsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDNUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxVQUFVLElBQUksRUFBRSxJQUFJLE9BQU8sQ0FBQyxTQUFTLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUM3RSxDQUFDO0lBQ0QsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDdEIsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUE7SUFDdkMsQ0FBQztJQUNELElBQUksT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ3RCLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFBO0lBQ3ZDLENBQUM7SUFDRCxJQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLFFBQVEsSUFBSSxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDNUQsTUFBTSxTQUFTLEdBQUc7WUFDaEIsT0FBTyxDQUFDLElBQUk7WUFDWixPQUFPLENBQUMsUUFBUTtZQUNoQixPQUFPLENBQUMsV0FBVztTQUNwQixDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDN0IsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENB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
|