import { db } from '../db/db_index'; import { orders } from '../db/schema'; import redisClient from './redis-client'; import { sendTelegramMessage } from './telegram-service'; import { inArray } from 'drizzle-orm'; const ORDER_CHANNEL = 'orders:placed'; interface OrderIdMessage { orderIds: number[]; } const formatDateTime = (dateStr: string | null | undefined): string => { if (!dateStr) return 'N/A'; return new Date(dateStr).toLocaleString('en-IN', { dateStyle: 'medium', timeStyle: 'short', }); }; const formatOrderMessageWithFullData = (ordersData: any[]): string => { let message = 'šŸ›’ New Order Placed\n\n'; ordersData.forEach((order, index) => { message += `Order ${order.id}\n`; message += 'šŸ“¦ Items:\n'; order.orderItems?.forEach((item: any) => { message += ` • ${item.product?.name || 'Unknown'} x${item.quantity}\n`; }); message += `\nšŸ’° Total: ₹${order.totalAmount}\n`; message += `🚚 Delivery: ${ order.isFlashDelivery ? 'Flash Delivery' : formatDateTime(order.slot?.deliveryTime) }\n`; message += `\nšŸ“ Address:\n`; message += ` ${order.address?.name || 'N/A'}\n`; message += ` ${order.address?.addressLine1 || ''}\n`; if (order.address?.addressLine2) { message += ` ${order.address.addressLine2}\n`; } message += ` ${order.address?.city || ''}, ${order.address?.state || ''} - ${order.address?.pincode || ''}\n`; if (order.address?.phone) { message += ` šŸ“ž ${order.address.phone}\n`; } if (index < ordersData.length - 1) { message += '\n---\n\n'; } }); return message; }; /** * Start the post order handler * Subscribes to the orders:placed channel and sends to Telegram */ export const startOrderHandler = async (): Promise => { try { console.log('Starting post order handler...'); await redisClient.subscribe(ORDER_CHANNEL, async (message: string) => { try { const { orderIds }: OrderIdMessage = JSON.parse(message); console.log('New order received, sending to Telegram...'); const ordersData = await db.query.orders.findMany({ where: inArray(orders.id, orderIds), with: { address: true, orderItems: { with: { product: true } }, slot: true, }, }); const telegramMessage = formatOrderMessageWithFullData(ordersData); await sendTelegramMessage(telegramMessage); } catch (error) { console.error('Failed to process order message:', error); await sendTelegramMessage(`āš ļø Error parsing order: ${message}`); } }); console.log('Post order handler started successfully'); } catch (error) { console.error('Failed to start post order handler:', error); throw error; } }; /** * Stop the post order handler */ export const stopOrderHandler = async (): Promise => { try { await redisClient.unsubscribe(ORDER_CHANNEL); console.log('Post order handler stopped'); } catch (error) { console.error('Error stopping post order handler:', error); } }; export const publishOrder = async (orderDetails: OrderIdMessage): Promise => { try { const message = JSON.stringify(orderDetails); await redisClient.publish(ORDER_CHANNEL, message); return true; } catch (error) { console.error('Failed to publish order:', error); return false; } }; export const publishFormattedOrder = async ( createdOrders: any[], ordersBySlot: Map ): Promise => { try { const orderIds = createdOrders.map(order => order.id); return await publishOrder({ orderIds }); } catch (error) { console.error('Failed to format and publish order:', error); return false; } };