feat: implement Phase 1 LINE Message Integration (Order Created, Payment Confirmed, Shipped, Cancelled)

This commit is contained in:
Your Name committed 2026-06-13 00:23:21 -04:00
1 parent 852d9c1925
commit 59363616c4
4 files changed
+630 -34

No files matched your search

+52 -24
View File
@@ -1,5 +1,12 @@
import { Elysia, t } from "elysia";
import prisma from "../lib/prisma";
import {
sendOrderCreatedNotification,
sendPaymentConfirmedNotification,
sendOrderShippedNotification,
sendOrderCancelledNotification,
markOrderAsPaid
} from "../lib/notifications";
export const ordersRoute = new Elysia({ prefix: "/orders" })
.get("/", async () => {
@@ -87,6 +94,11 @@ export const ordersRoute = new Elysia({ prefix: "/orders" })
}
}
// Trigger LINE notification asynchronously
sendOrderCreatedNotification(order.id).catch(e => {
console.error("Failed to trigger sendOrderCreatedNotification:", e);
});
return order;
} catch (err) {
console.error("[Orders] Error:", err);
@@ -127,29 +139,40 @@ export const ordersRoute = new Elysia({ prefix: "/orders" })
const { status } = body as any;
const order = await prisma.order.findUnique({ where: { id: Number(id) } });
const updatedOrder = await prisma.order.update({
where: { id: Number(id) },
data: { status },
include: { items: true }
if (!order) {
set.status = 404;
return { error: "Order not found" };
}
if (status === 'PAID') {
await markOrderAsPaid(order.id);
} else {
await prisma.order.update({
where: { id: order.id },
data: { status }
});
// If status becomes CANCELLED, refund the points used and notify
if (status === 'CANCELLED' && order.status !== 'CANCELLED') {
if (order.customerId && order.pointsUsed > 0) {
await prisma.customer.update({
where: { id: order.customerId },
data: { points: { increment: order.pointsUsed } }
});
}
sendOrderCancelledNotification(order.id).catch(e => console.error(e));
}
// If status becomes SHIPPED, notify
if (status === 'SHIPPED' && order.status !== 'SHIPPED') {
sendOrderShippedNotification(order.id).catch(e => console.error(e));
}
}
return await prisma.order.findUnique({
where: { id: order.id },
include: { items: true, customer: true }
});
// Grant points if status becomes PAID and it wasn't PAID before
if (status === 'PAID' && order?.status !== 'PAID' && order?.customerId && order?.pointsEarned > 0) {
await prisma.customer.update({
where: { id: order.customerId },
data: { points: { increment: order.pointsEarned } }
});
}
// If status becomes CANCELLED, refund the points used
if (status === 'CANCELLED' && order?.status !== 'CANCELLED' && order?.customerId && order?.pointsUsed > 0) {
await prisma.customer.update({
where: { id: order.customerId },
data: { points: { increment: order.pointsUsed } }
});
}
return updatedOrder;
} catch (err) {
set.status = 500;
return { error: "Failed to update order status" };
@@ -179,11 +202,16 @@ export const ordersRoute = new Elysia({ prefix: "/orders" })
.patch("/:id/tracking", async ({ params: { id }, body, set }) => {
try {
const { trackingNo } = body as any;
return await prisma.order.update({
const order = await prisma.order.update({
where: { id: Number(id) },
data: { trackingNo },
data: { trackingNo, status: "SHIPPED" },
include: { items: true }
});
// Trigger notification asynchronously
sendOrderShippedNotification(order.id).catch(e => {
console.error("Failed to trigger sendOrderShippedNotification:", e);
});
return order;
} catch (err) {
set.status = 500;
return { error: "Failed to update tracking number" };