This commit is contained in:
2025-12-06 10:47:13 +03:30
parent 8336e7f81a
commit 803e56f0d3
3 changed files with 118 additions and 3 deletions
+3 -1
View File
@@ -4,8 +4,11 @@ export enum OrderStatus {
// PendingConfirmation = 'pendingConfirmation',
Confirmed = 'confirmed',
Preparing = 'preparing',
RejectedByRestaurant = 'rejectedByRestaurant',
CancelledByUser = 'cancelledByUser',
CancelledBySystem = 'cancelledBySystem',
ReadyForCustomerPickup = 'readyForCustomerPickup',
ReadyForDineIn = 'readyForDineIn',
@@ -13,5 +16,4 @@ export enum OrderStatus {
ReadyForDeliveryCourier = 'readyForDeliveryCourier',
Delivered = 'delivered',
CancelledBySystem = 'cancelledBySystem',
}
+9 -2
View File
@@ -252,8 +252,15 @@ export class OrdersService {
});
}
findOne(id: number) {
return `This action returns a #${id} order`;
async findOne(id: string): Promise<Order> {
const order = await this.orderRepository.findOne(
{ id },
{ populate: ['user', 'restaurant', 'deliveryMethod', 'address', 'paymentMethod', 'items', 'items.food'] },
);
if (!order) {
throw new NotFoundException('Order not found');
}
return order;
}
async acceptOrder(orderId: string) {
@@ -0,0 +1,106 @@
import { Injectable } from '@nestjs/common';
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
import { FilterQuery } from '@mikro-orm/core';
import { Order } from '../entities/order.entity';
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
import { OrderStatus } from '../interface/order-status';
import { PaymentStatusEnum } from '../../payments/interface/payment';
type FindOrdersOpts = {
page?: number;
limit?: number;
status?: OrderStatus;
paymentStatus?: PaymentStatusEnum;
search?: string;
startDate?: string;
endDate?: string;
orderBy?: string;
order?: 'asc' | 'desc';
};
@Injectable()
export class OrderRepository extends EntityRepository<Order> {
constructor(readonly em: EntityManager) {
super(em, Order);
}
/**
* Find orders with pagination and optional filters.
* Supports: status, paymentStatus, search (orderNumber), date range, ordering.
*/
async findAllPaginated(restId: string, opts: FindOrdersOpts = {}): Promise<PaginatedResult<Order>> {
const {
page = 1,
limit = 10,
status,
paymentStatus,
search,
startDate,
endDate,
orderBy = 'createdAt',
order = 'desc',
} = opts;
const offset = (page - 1) * limit;
const where: FilterQuery<Order> = { restaurant: { id: restId } };
// Filter by status
if (status) {
where.status = status;
}
// Filter by payment status
if (paymentStatus) {
where.paymentStatus = paymentStatus;
}
// Filter by date range
if (startDate || endDate) {
where.createdAt = {};
if (startDate) {
where.createdAt.$gte = new Date(startDate);
}
if (endDate) {
where.createdAt.$lte = new Date(endDate);
}
}
// Search by order number or user information
if (search) {
const searchPattern = `%${search}%`;
const searchConditions: any[] = [
{ user: { firstName: { $ilike: searchPattern } } },
{ user: { lastName: { $ilike: searchPattern } } },
{ user: { phone: { $ilike: searchPattern } } },
];
// If search is numeric, also search by orderNumber
const numericSearch = Number(search);
if (!isNaN(numericSearch) && isFinite(numericSearch)) {
searchConditions.push({ orderNumber: numericSearch });
}
where.$or = searchConditions;
}
const [data, total] = await this.findAndCount(where, {
limit,
offset,
orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' },
populate: ['user', 'restaurant', 'deliveryMethod', 'address', 'paymentMethod', 'items', 'items.food'],
});
const totalPages = Math.ceil(total / limit);
return {
data,
meta: {
total,
page,
limit,
totalPages,
},
};
}
}