import prisma from "./prisma"; import { lineClient } from "./lineClient"; export async function sendOrderCreatedNotification(orderId: number) { try { const order = await prisma.order.findUnique({ where: { id: orderId }, include: { items: true, customer: true } }); if (!order || !order.customer?.lineUserId) { console.log(`[Notification] Order #${orderId} has no associated lineUserId or does not exist.`); return; } const settings = await prisma.storeSettings.findFirst(); const bankName = settings?.bankName || "KASIKORNBANK (KBANK)"; const bankAccountNumber = settings?.bankAccountNumber || "012-3-45678-9"; const bankAccountName = settings?.bankAccountName || "HomAroma Co., Ltd."; const itemContents = order.items.map(item => ({ type: "box", layout: "horizontal", contents: [ { type: "text", text: `${item.productName}${item.variantName ? ` (${item.variantName})` : ""} x ${item.quantity}`, size: "sm", color: "#333333", flex: 3, wrap: true }, { type: "text", text: `฿${item.priceAtPurchase * item.quantity}`, size: "sm", color: "#1C3F3A", weight: "bold", align: "end", flex: 1 } ] })); const flexMessage: any = { type: "flex", altText: `HomAroma: คำสั่งซื้อ #${order.id} ได้รับแล้ว กรุณาชำระเงิน`, contents: { type: "bubble", header: { type: "box", layout: "vertical", backgroundColor: "#1C3F3A", contents: [ { type: "text", text: "HomAroma Official", color: "#D4B16A", weight: "bold", size: "xs" }, { type: "text", text: "ได้รับคำสั่งซื้อของคุณแล้ว", color: "#FFFFFF", weight: "bold", size: "md", margin: "sm" } ] }, body: { type: "box", layout: "vertical", contents: [ { type: "text", text: `หมายเลขออเดอร์: #HM-${order.id}`, weight: "bold", size: "sm", color: "#333333" }, { type: "separator", margin: "md" }, { type: "box", layout: "vertical", margin: "md", spacing: "sm", contents: [ { type: "box", layout: "horizontal", contents: [ { type: "text", text: "รายการสินค้า", size: "xs", color: "#888888", flex: 3 }, { type: "text", text: "ยอดรวม", size: "xs", color: "#888888", align: "end", flex: 1 } ] }, ...itemContents ] }, { type: "separator", margin: "md" }, { type: "box", layout: "horizontal", margin: "md", contents: [ { type: "text", text: "ยอดชำระสุทธิ (รวมค่าส่ง)", size: "sm", color: "#555555", weight: "bold", flex: 3 }, { type: "text", text: `฿${order.totalAmount}`, size: "sm", color: "#1C3F3A", weight: "bold", align: "end", flex: 1 } ] }, { type: "separator", margin: "md" }, { type: "box", layout: "vertical", margin: "md", contents: [ { type: "text", text: "🏦 ช่องทางการชำระเงินโอนเงิน:", size: "xs", color: "#555555", weight: "bold" }, { type: "text", text: `${bankName} (${bankAccountNumber})`, size: "xs", color: "#1C3F3A", margin: "xs", weight: "bold" }, { type: "text", text: `ชื่อบัญชี: ${bankAccountName}`, size: "xs", color: "#555555" } ] } ] }, footer: { type: "box", layout: "vertical", spacing: "sm", contents: [ { type: "button", style: "primary", color: "#1C3F3A", action: { "type": "uri", "label": "แนบสลิปชำระเงิน", "uri": `https://spa.homaroma.shop/order-success?id=${order.id}` } }, { type: "button", style: "link", height: "sm", action: { "type": "uri", "label": "ติดตามสถานะออเดอร์", "uri": "https://spa.homaroma.shop/track-order" } } ] } } }; await lineClient.pushMessage({ to: order.customer.lineUserId, messages: [flexMessage] }); console.log(`[Notification] OrderCreated notification sent for Order #${orderId}`); } catch (err) { console.error(`[Notification] Failed to send OrderCreated notification for Order #${orderId}:`, err); } } export async function sendPaymentConfirmedNotification(orderId: number) { try { const order = await prisma.order.findUnique({ where: { id: orderId }, include: { customer: true } }); if (!order || !order.customer?.lineUserId) { console.log(`[Notification] Order #${orderId} has no associated lineUserId or does not exist.`); return; } const flexMessage: any = { type: "flex", altText: "HomAroma: ได้รับการชำระเงินเรียบร้อยแล้ว", contents: { type: "bubble", body: { type: "box", layout: "vertical", contents: [ { type: "box", layout: "vertical", alignItems: "center", contents: [ { type: "text", text: "✨ ชำระเงินสำเร็จ ✨", weight: "bold", size: "xl", color: "#1C3F3A" }, { type: "text", text: `ขอขอบคุณสำหรับคำสั่งซื้อออเดอร์ #HM-${order.id}`, size: "xs", color: "#888888", margin: "xs" } ] }, { type: "box", layout: "vertical", backgroundColor: "#F4F6F5", margin: "lg", paddingAll: "md", cornerRadius: "md", contents: [ { type: "box", layout: "horizontal", contents: [ { type: "text", text: "ได้รับแต้มครั้งนี้", size: "sm", color: "#555555" }, { type: "text", text: `+${order.pointsEarned} แต้ม`, weight: "bold", size: "sm", color: "#1C3F3A", align: "end" } ] }, { type: "box", layout: "horizontal", margin: "xs", contents: [ { type: "text", text: "แต้มสะสมรวมล่าสุด", size: "sm", color: "#555555" }, { type: "text", text: `${order.customer.points} แต้ม`, weight: "bold", size: "sm", color: "#D4B16A", align: "end" } ] } ] } ] }, footer: { type: "box", layout: "vertical", contents: [ { type: "button", style: "primary", color: "#1C3F3A", action: { "type": "uri", "label": "แลกของรางวัล & คูปองสะสม", "uri": "https://spa.homaroma.shop/profile" } } ] } } }; await lineClient.pushMessage({ to: order.customer.lineUserId, messages: [flexMessage] }); console.log(`[Notification] PaymentConfirmed notification sent for Order #${orderId}`); } catch (err) { console.error(`[Notification] Failed to send PaymentConfirmed notification for Order #${orderId}:`, err); } } export async function sendOrderShippedNotification(orderId: number) { try { const order = await prisma.order.findUnique({ where: { id: orderId }, include: { customer: true } }); if (!order || !order.customer?.lineUserId) { console.log(`[Notification] Order #${orderId} has no associated lineUserId or does not exist.`); return; } const flexMessage: any = { type: "flex", altText: "HomAroma: สินค้าของคุณอยู่ระหว่างจัดส่ง", contents: { type: "bubble", header: { type: "box", layout: "vertical", backgroundColor: "#1C3F3A", contents: [ { type: "text", text: "ออเดอร์ของคุณกำลังเดินทาง 🚚", color: "#FFFFFF", weight: "bold", size: "md" } ] }, body: { type: "box", layout: "vertical", spacing: "md", contents: [ { type: "box", layout: "horizontal", contents: [ { type: "text", text: "หมายเลขออเดอร์:", size: "sm", color: "#888888", flex: 2 }, { type: "text", text: `#HM-${order.id}`, size: "sm", color: "#333333", weight: "bold", flex: 3 } ] }, { type: "box", layout: "horizontal", contents: [ { type: "text", text: "หมายเลขพัสดุ:", size: "sm", color: "#888888", flex: 2 }, { type: "text", text: order.trackingNo || "อยู่ระหว่างเข้ารับพัสดุ", size: "sm", color: "#1C3F3A", weight: "bold", flex: 3 } ] } ] }, footer: { type: "box", layout: "vertical", contents: [ { type: "button", style: "primary", color: "#1C3F3A", action: { "type": "uri", "label": "เช็คสถานะการจัดส่ง", "uri": "https://spa.homaroma.shop/track-order" } } ] } } }; await lineClient.pushMessage({ to: order.customer.lineUserId, messages: [flexMessage] }); console.log(`[Notification] OrderShipped notification sent for Order #${orderId}`); } catch (err) { console.error(`[Notification] Failed to send OrderShipped notification for Order #${orderId}:`, err); } } export async function sendOrderCancelledNotification(orderId: number) { try { const order = await prisma.order.findUnique({ where: { id: orderId }, include: { customer: true } }); if (!order || !order.customer?.lineUserId) { console.log(`[Notification] Order #${orderId} has no associated lineUserId or does not exist.`); return; } const flexMessage: any = { type: "flex", altText: "HomAroma: คำสั่งซื้อของคุณถูกยกเลิกแล้ว", contents: { type: "bubble", header: { type: "box", layout: "vertical", backgroundColor: "#8C2A2A", contents: [ { type: "text", text: "คำสั่งซื้อถูกยกเลิก 🚫", color: "#FFFFFF", weight: "bold", size: "md" } ] }, body: { type: "box", layout: "vertical", spacing: "md", contents: [ { type: "text", text: `คำสั่งซื้อหมายเลข #HM-${order.id} ได้ถูกยกเลิกแล้ว เนื่องจากเกินกำหนดเวลาชำระเงิน หรือสิทธิประโยชน์บางประการ หรือตามความประสงค์ของคุณ`, size: "sm", color: "#333333", wrap: true }, ...(order.pointsUsed > 0 ? [ { type: "text", text: `* ระบบได้ทำการคืนคะแนนสะสมจำนวน ${order.pointsUsed} แต้มเข้าบัญชีของคุณเรียบร้อยแล้ว`, size: "xs", color: "#8C2A2A", weight: "bold", margin: "md" } ] : []) ] }, footer: { type: "box", layout: "vertical", contents: [ { type: "button", style: "primary", color: "#1C3F3A", action: { "type": "uri", "label": "ช้อปต่ออีกครั้ง", "uri": "https://spa.homaroma.shop/" } } ] } } }; await lineClient.pushMessage({ to: order.customer.lineUserId, messages: [flexMessage] }); console.log(`[Notification] OrderCancelled notification sent for Order #${orderId}`); } catch (err) { console.error(`[Notification] Failed to send OrderCancelled notification for Order #${orderId}:`, err); } } export async function markOrderAsPaid(orderId: number) { try { const order = await prisma.order.findUnique({ where: { id: orderId } }); if (!order) { console.log(`[Payment] Order #${orderId} not found in markOrderAsPaid.`); return; } if (order.status === "PAID") { console.log(`[Payment] Order #${orderId} is already PAID.`); return; } // 1. Update status to PAID await prisma.order.update({ where: { id: orderId }, data: { status: "PAID" } }); // 2. Grant points if (order.customerId && order.pointsEarned > 0) { await prisma.customer.update({ where: { id: order.customerId }, data: { points: { increment: order.pointsEarned } } }); console.log(`[Payment] Granted ${order.pointsEarned} points to Customer #${order.customerId} for Order #${orderId}`); } // 3. Send payment notification await sendPaymentConfirmedNotification(orderId); } catch (err) { console.error(`[Payment] Error in markOrderAsPaid for Order #${orderId}:`, err); } }