up
This commit is contained in:
@@ -20,7 +20,7 @@ import { OrderRepository } from '../repositories/order.repository';
|
||||
import { FindOrdersDto } from '../dto/find-orders.dto';
|
||||
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class OrdersService {
|
||||
private readonly logger = new Logger(OrdersService.name);
|
||||
@@ -81,7 +81,7 @@ export class OrdersService {
|
||||
totalItems: cart.totalItems || 0,
|
||||
description: cart.description,
|
||||
tableNumber: cart.tableNumber,
|
||||
status: OrderStatus.Pending,
|
||||
status: OrderStatus.NEW,
|
||||
paymentStatus: PaymentStatusEnum.Pending,
|
||||
});
|
||||
|
||||
@@ -92,7 +92,7 @@ export class OrdersService {
|
||||
const { food, quantity, unitPrice, discount } = itemData;
|
||||
|
||||
// Stock check
|
||||
if (food.stock < quantity) {
|
||||
if (food.inventory.availableStock < quantity) {
|
||||
throw new BadRequestException(`${food.title} is out of stock`);
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ export class OrdersService {
|
||||
const orderItemsData: Array<{ food: Food; quantity: number; unitPrice: number; discount: number }> = [];
|
||||
|
||||
for (const cartItem of cart.items) {
|
||||
const food = await this.em.findOne(Food, { id: cartItem.foodId }, { populate: ['restaurant'] });
|
||||
const food = await this.em.findOne(Food, { id: cartItem.foodId }, { populate: ['restaurant', 'inventory'] });
|
||||
if (!food) {
|
||||
throw new NotFoundException(`Food with ID ${cartItem.foodId} not found`);
|
||||
}
|
||||
@@ -232,9 +232,10 @@ export class OrdersService {
|
||||
}
|
||||
|
||||
// Final stock validation
|
||||
if (food.stock < cartItem.quantity) {
|
||||
const availableStock = food.inventory?.availableStock ?? 0;
|
||||
if (availableStock < cartItem.quantity) {
|
||||
throw new BadRequestException(
|
||||
`Insufficient stock for food ${food.title || food.id}. Available: ${food.stock}, Requested: ${cartItem.quantity}`,
|
||||
`Insufficient stock for food ${food.title || food.id}. Available: ${availableStock}, Requested: ${cartItem.quantity}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -303,13 +304,13 @@ export class OrdersService {
|
||||
return order;
|
||||
}
|
||||
|
||||
async acceptOrder(orderId: string, restId: string) {
|
||||
async confirmOrder(orderId: string, restId: string) {
|
||||
const order = await this.em.findOne(Order, { id: orderId, restaurant: { id: restId } });
|
||||
if (!order) {
|
||||
throw new NotFoundException('Order not found');
|
||||
}
|
||||
if (order.status !== OrderStatus.Pending) {
|
||||
throw new BadRequestException('Order must be pending before accepting');
|
||||
if (order.status !== OrderStatus.CREATED) {
|
||||
throw new BadRequestException('Order must be created before confirming');
|
||||
}
|
||||
// Wallet payments should be paid before accepting (like Online)
|
||||
if (order.paymentMethod?.method === PaymentMethodEnum.Online && order.paymentStatus !== PaymentStatusEnum.Paid) {
|
||||
@@ -319,7 +320,7 @@ export class OrdersService {
|
||||
// Cash, CardOnDelivery, and Wallet can be accepted even if payment status is pending
|
||||
// (they're paid on delivery or already deducted)
|
||||
|
||||
order.status = OrderStatus.Confirmed;
|
||||
order.status = OrderStatus.CONFIRMED;
|
||||
await this.em.persistAndFlush(order);
|
||||
return order;
|
||||
}
|
||||
@@ -329,10 +330,13 @@ export class OrdersService {
|
||||
if (!order) {
|
||||
throw new NotFoundException('Order not found');
|
||||
}
|
||||
if (order.status !== OrderStatus.Confirmed) {
|
||||
if (!this.canTransition(order.status, OrderStatus.PREPARING, order.paymentMethod?.method)) {
|
||||
throw new BadRequestException('Invalid status transition');
|
||||
}
|
||||
if (order.status !== OrderStatus.CONFIRMED) {
|
||||
throw new BadRequestException('Order must be confirmed before preparing');
|
||||
}
|
||||
order.status = OrderStatus.Preparing;
|
||||
order.status = OrderStatus.PREPARING;
|
||||
await this.em.persistAndFlush(order);
|
||||
return order;
|
||||
}
|
||||
@@ -342,7 +346,7 @@ export class OrdersService {
|
||||
if (!order) {
|
||||
throw new NotFoundException('Order not found');
|
||||
}
|
||||
order.status = OrderStatus.RejectedByRestaurant;
|
||||
order.status = OrderStatus.CANCELED;
|
||||
await this.em.persistAndFlush(order);
|
||||
return order;
|
||||
}
|
||||
@@ -381,10 +385,10 @@ export class OrdersService {
|
||||
if (!order) {
|
||||
throw new NotFoundException('Order not found');
|
||||
}
|
||||
if (order.status !== OrderStatus.Pending) {
|
||||
if (order.status !== OrderStatus.) {
|
||||
throw new BadRequestException('Order is not pending');
|
||||
}
|
||||
order.status = OrderStatus.CancelledByUser;
|
||||
order.status = OrderStatus.CANCELED;
|
||||
await this.em.persistAndFlush(order);
|
||||
return order;
|
||||
}
|
||||
@@ -446,6 +450,30 @@ export class OrdersService {
|
||||
return order;
|
||||
}
|
||||
|
||||
transitions = {
|
||||
CREATED: [OrderStatus.PENDING_PAYMENT, OrderStatus.CONFIRMED, OrderStatus.CANCELED],
|
||||
PENDING_PAYMENT: [OrderStatus.PAID, OrderStatus.FAILED, OrderStatus.CANCELED],
|
||||
PAID: [OrderStatus.CONFIRMED, OrderStatus.REFUNDED],
|
||||
CONFIRMED: [OrderStatus.PREPARING, OrderStatus.CANCELED],
|
||||
PREPARING: [OrderStatus.READY, OrderStatus.SHIPPED, OrderStatus.CANCELED],
|
||||
READY: [OrderStatus.COMPLETED, OrderStatus.FAILED],
|
||||
SHIPPED: [OrderStatus.COMPLETED, OrderStatus.FAILED],
|
||||
}
|
||||
|
||||
canTransition(from: OrderStatus, to: OrderStatus, paymentMethod: PaymentMethodEnum) {
|
||||
if (!this.transitions[from]?.includes(to)) return false;
|
||||
|
||||
if (paymentMethod === PaymentMethodEnum.Cash) {
|
||||
if ([OrderStatus.PENDING_PAYMENT, OrderStatus.PAID].includes(to)) return false;
|
||||
}
|
||||
|
||||
if (paymentMethod === PaymentMethodEnum.Online) {
|
||||
if (to === OrderStatus.CONFIRMED && from !== OrderStatus.PAID) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup job to handle abandoned orders (pending payment for >30 minutes)
|
||||
* Runs every 10 minutes to check for abandoned orders
|
||||
|
||||
Reference in New Issue
Block a user