|
|
|
@@ -9,6 +9,8 @@ import { Food } from '../foods/entities/food.entity';
|
|
|
|
|
import { Restaurant } from '../restaurants/entities/restaurant.entity';
|
|
|
|
|
import { Order } from '../orders/entities/order.entity';
|
|
|
|
|
import { ReservationStatus } from './inteface/reservation';
|
|
|
|
|
import { STOCK_RESERVE_MINUTES } from './const/reservation';
|
|
|
|
|
import { PaymentMethodEnum } from '../payments/interface/payment';
|
|
|
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
|
export class InventoryService {
|
|
|
|
@@ -59,8 +61,8 @@ export class InventoryService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async bulkSetStockForFoods(restaurantId: string, bulkSetStockDto: BulkSetStockDto): Promise<Inventory[]> {
|
|
|
|
|
|
|
|
|
|
const { items } = bulkSetStockDto;
|
|
|
|
|
|
|
|
|
|
// Validate all items first
|
|
|
|
|
for (const item of items) {
|
|
|
|
|
if (item.availableStock > item.totalStock) {
|
|
|
|
@@ -134,17 +136,19 @@ export class InventoryService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async tempBulkReserveFood(
|
|
|
|
|
em: EntityManager,
|
|
|
|
|
restaurantId: string,
|
|
|
|
|
orderId: string,
|
|
|
|
|
paymentMethod: PaymentMethodEnum,
|
|
|
|
|
bulkReserveFoodDto: BulkReserveFoodDto,
|
|
|
|
|
): Promise<Reservation[]> {
|
|
|
|
|
const { items } = bulkReserveFoodDto;
|
|
|
|
|
|
|
|
|
|
const expiresAt = this.getReservationExpiry(paymentMethod);
|
|
|
|
|
// Get all unique food IDs
|
|
|
|
|
const foodIds = [...new Set(items.map(item => item.foodId))];
|
|
|
|
|
|
|
|
|
|
// Load all foods in one query
|
|
|
|
|
const foods = await this.em.find(Food, { id: { $in: foodIds } }, { populate: ['restaurant'] });
|
|
|
|
|
const foods = await em.find(Food, { id: { $in: foodIds } }, { populate: ['restaurant'] });
|
|
|
|
|
|
|
|
|
|
// Verify all foods exist and belong to the restaurant
|
|
|
|
|
const foodMap = new Map<string, Food>();
|
|
|
|
@@ -162,13 +166,13 @@ export class InventoryService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load order
|
|
|
|
|
const order = await this.em.findOne(Order, { id: orderId });
|
|
|
|
|
const order = await em.findOne(Order, { id: orderId });
|
|
|
|
|
if (!order) {
|
|
|
|
|
throw new NotFoundException(`Order with ID ${orderId} not found`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load all existing inventories in one query
|
|
|
|
|
const existingInventories = await this.em.find(Inventory, {
|
|
|
|
|
const existingInventories = await em.find(Inventory, {
|
|
|
|
|
food: { id: { $in: foodIds }, restaurant: { id: restaurantId } },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@@ -196,11 +200,11 @@ export class InventoryService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create reservation record
|
|
|
|
|
const reservation = this.em.create(Reservation, {
|
|
|
|
|
const reservation = em.create(Reservation, {
|
|
|
|
|
food,
|
|
|
|
|
order,
|
|
|
|
|
quantity: item.quantity,
|
|
|
|
|
expiresAt: item.expiresAt,
|
|
|
|
|
expiresAt,
|
|
|
|
|
status: ReservationStatus.ACTIVE,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@@ -209,22 +213,36 @@ export class InventoryService {
|
|
|
|
|
// Update available stock (decrease by quantity)
|
|
|
|
|
inventory.availableStock -= item.quantity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Flush all changes at once
|
|
|
|
|
await this.em.flush();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return reservations;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async confirmReservationByOrderId(orderId: string): Promise<Reservation[]> {
|
|
|
|
|
const reservations = await this.em.find(Reservation, { order: { id: orderId } });
|
|
|
|
|
async confirmReservationByOrderId(em: EntityManager, orderId: string): Promise<Reservation[]> {
|
|
|
|
|
const reservations = await em.find(Reservation, { order: { id: orderId } });
|
|
|
|
|
if (!reservations) {
|
|
|
|
|
throw new NotFoundException(`Reservations with order ID ${orderId} not found`);
|
|
|
|
|
}
|
|
|
|
|
for (const reservation of reservations) {
|
|
|
|
|
reservation.status = ReservationStatus.CONFIRMED;
|
|
|
|
|
}
|
|
|
|
|
await this.em.flush();
|
|
|
|
|
return reservations;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async releaseReservationByOrderId(em: EntityManager, orderId: string): Promise<Reservation[]> {
|
|
|
|
|
const reservations = await em.find(Reservation, { order: { id: orderId } });
|
|
|
|
|
if (!reservations) {
|
|
|
|
|
throw new NotFoundException(`Reservations with order ID ${orderId} not found`);
|
|
|
|
|
}
|
|
|
|
|
for (const reservation of reservations) {
|
|
|
|
|
em.remove(reservation);
|
|
|
|
|
}
|
|
|
|
|
return reservations;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getReservationExpiry(method: PaymentMethodEnum): Date {
|
|
|
|
|
const minutes = STOCK_RESERVE_MINUTES[method] ?? 15;
|
|
|
|
|
return new Date(Date.now() + minutes * 60 * 1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|