cron for complete order
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import { Cron } from '@nestjs/schedule';
|
import { Cron } from '@nestjs/schedule';
|
||||||
import { EntityManager } from '@mikro-orm/postgresql';
|
import { EntityManager } from '@mikro-orm/postgresql';
|
||||||
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
import { Payment } from '../../payments/entities/payment.entity';
|
import { Payment } from '../../payments/entities/payment.entity';
|
||||||
import { PaymentMethodEnum, PaymentStatusEnum } from '../../payments/interface/payment';
|
import { PaymentMethodEnum, PaymentStatusEnum } from '../../payments/interface/payment';
|
||||||
import { InventoryService } from '../../inventory/inventory.service';
|
import { InventoryService } from '../../inventory/inventory.service';
|
||||||
import { OrderStatus } from '../interface/order.interface';
|
import { OrderStatus } from '../interface/order.interface';
|
||||||
|
import { Order } from '../entities/order.entity';
|
||||||
|
// import { OrderStatusChangedEvent } from '../events/order.events';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OrdersCrone {
|
export class OrdersCrone {
|
||||||
@@ -13,6 +16,7 @@ export class OrdersCrone {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly em: EntityManager,
|
private readonly em: EntityManager,
|
||||||
private readonly inventoryService: InventoryService,
|
private readonly inventoryService: InventoryService,
|
||||||
|
// private readonly eventEmitter: EventEmitter2,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
// run every minute and fail pending online payments older than 15 minutes
|
// run every minute and fail pending online payments older than 15 minutes
|
||||||
@@ -86,4 +90,98 @@ export class OrdersCrone {
|
|||||||
this.logger.error(`OrdersCrone failed: ${err.message}`, err.stack);
|
this.logger.error(`OrdersCrone failed: ${err.message}`, err.stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// run every 15 minutes to complete orders that have been in shipped/delivered statuses for more than 3 hours
|
||||||
|
@Cron('*/15 * * * *', {
|
||||||
|
name: 'completeOldDeliveredOrders',
|
||||||
|
timeZone: 'UTC',
|
||||||
|
})
|
||||||
|
async completeOldDeliveredOrders() {
|
||||||
|
try {
|
||||||
|
const cutoff = new Date(Date.now() - 3 * 60 * 60 * 1000); // 3 hours ago
|
||||||
|
|
||||||
|
this.logger.debug('Searching for orders in shipped/delivered statuses older than 3 hours');
|
||||||
|
|
||||||
|
const orders = await this.em.find(
|
||||||
|
Order,
|
||||||
|
{
|
||||||
|
status: {
|
||||||
|
$in: [
|
||||||
|
OrderStatus.SHIPPED,
|
||||||
|
OrderStatus.DELIVERED_TO_WAITER,
|
||||||
|
OrderStatus.DELIVERED_TO_RECEPTIONIST,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
updatedAt: { $lte: cutoff },
|
||||||
|
},
|
||||||
|
{ populate: ['restaurant'] },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!orders || orders.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.log(`Found ${orders.length} orders to mark as completed`);
|
||||||
|
|
||||||
|
for (const order of orders) {
|
||||||
|
try {
|
||||||
|
await this.em.transactional(async em => {
|
||||||
|
// reload inside transaction to avoid concurrency issues
|
||||||
|
const reloadedOrder = await em.findOne(
|
||||||
|
Order,
|
||||||
|
{ id: order.id },
|
||||||
|
{ populate: ['restaurant', 'user'] },
|
||||||
|
);
|
||||||
|
if (!reloadedOrder) return;
|
||||||
|
if (
|
||||||
|
![
|
||||||
|
OrderStatus.SHIPPED,
|
||||||
|
OrderStatus.DELIVERED_TO_WAITER,
|
||||||
|
OrderStatus.DELIVERED_TO_RECEPTIONIST,
|
||||||
|
].includes(reloadedOrder.status)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const previousStatus = reloadedOrder.status;
|
||||||
|
const restaurantId =
|
||||||
|
typeof reloadedOrder.restaurant === 'string'
|
||||||
|
? reloadedOrder.restaurant
|
||||||
|
: reloadedOrder.restaurant.id;
|
||||||
|
|
||||||
|
// Update order status and history
|
||||||
|
reloadedOrder.status = OrderStatus.COMPLETED;
|
||||||
|
reloadedOrder.history.push({
|
||||||
|
status: OrderStatus.COMPLETED,
|
||||||
|
changedAt: new Date(),
|
||||||
|
desc: 'تکمیل سفارش توسط سیستم',
|
||||||
|
});
|
||||||
|
|
||||||
|
em.persist(reloadedOrder);
|
||||||
|
await em.flush();
|
||||||
|
|
||||||
|
// // Emit event after transaction completes
|
||||||
|
// this.eventEmitter.emit(
|
||||||
|
// OrderStatusChangedEvent.name,
|
||||||
|
// new OrderStatusChangedEvent(
|
||||||
|
// reloadedOrder.id,
|
||||||
|
// reloadedOrder.user?.id || '',
|
||||||
|
// String(reloadedOrder.orderNumber) || '',
|
||||||
|
// restaurantId,
|
||||||
|
// previousStatus,
|
||||||
|
// OrderStatus.COMPLETED,
|
||||||
|
// 'admin',
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
|
||||||
|
this.logger.log(`Marked order ${reloadedOrder.id} as completed`);
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.logger.error(`Error processing order ${order.id}: ${err.message}`, err.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.logger.error(`completeOldDeliveredOrders cron failed: ${err.message}`, err.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user