128 lines
3.8 KiB
TypeScript
128 lines
3.8 KiB
TypeScript
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 = '🛒 <b>New Order Placed</b>\n\n';
|
|
|
|
ordersData.forEach((order, index) => {
|
|
message += `<b>Order ${order.id}</b>\n`;
|
|
|
|
message += '📦 <b>Items:</b>\n';
|
|
order.orderItems?.forEach((item: any) => {
|
|
message += ` • ${item.product?.name || 'Unknown'} x${item.quantity}\n`;
|
|
});
|
|
|
|
message += `\n💰 <b>Total:</b> ₹${order.totalAmount}\n`;
|
|
|
|
message += `🚚 <b>Delivery:</b> ${
|
|
order.isFlashDelivery ? 'Flash Delivery' : formatDateTime(order.slot?.deliveryTime)
|
|
}\n`;
|
|
|
|
message += `\n📍 <b>Address:</b>\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<void> => {
|
|
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<void> => {
|
|
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<boolean> => {
|
|
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<number | null, any[]>
|
|
): Promise<boolean> => {
|
|
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;
|
|
}
|
|
};
|