order list for user

This commit is contained in:
2026-01-17 18:37:04 +03:30
parent e07075a7c5
commit 02ab8fbc6a
9 changed files with 84 additions and 91 deletions
@@ -1,11 +1,11 @@
import { Controller, Get, Post, Param, UseGuards, Patch, Query, Body } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiHeader, ApiBody } from '@nestjs/swagger';
import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiHeader, ApiBody, ApiQuery } from '@nestjs/swagger';
import { OrdersService } from '../providers/orders.service';
import { AuthGuard } from '../../auth/guards/auth.guard';
import { UserId } from '../../../common/decorators/user-id.decorator';
import { AdminAuthGuard } from '../../auth/guards/adminAuth.guard';
import { FindOrdersDto } from '../dto/find-orders.dto';
import { OrderStatus } from '../interface/order.interface';
import { OrderStatusEnum } from '../interface/order.interface';
import { UpdateOrderStatusDto } from '../dto/update-order-status.dto';
import { Permissions } from 'src/common/decorators/permissions.decorator';
import { Permission } from 'src/common/enums/permission.enum';
@@ -25,13 +25,21 @@ export class OrdersController {
return this.ordersService.createOrder(userId, body);
}
// @UseGuards(AuthGuard)
// @Get('public/orders')
// @ApiOperation({ summary: 'Get all orders with pagination and filters' })
// findAll(@Query() dto: FindOrdersDto, @UserId() userId: string) {
// return this.ordersService.findAllForUser(dto, userId);
// }
@Get('public/orders')
@UseGuards(AuthGuard)
@ApiQuery({ name: 'page', required: false, type: Number })
@ApiQuery({ name: 'limit', required: false, type: Number })
@ApiQuery({ name: 'search', required: false, type: String })
@ApiQuery({ name: 'orderBy', required: false, type: String })
@ApiQuery({ name: 'order', required: false, enum: ['asc', 'desc'] })
@ApiQuery({ name: 'statuses', required: false, enum: OrderStatusEnum })
@ApiQuery({ name: 'from', required: false, type: Date })
@ApiQuery({ name: 'to', required: false, type: Date })
@ApiOperation({ summary: 'Get all orders with pagination and filters' })
async findAll(@Query() dto: FindOrdersDto, @UserId() userId: string) {
const orders=await this.ordersService.findAllForUser(userId, dto);
return orders
}
// @UseGuards(AuthGuard)
// @ApiOperation({ summary: 'Get an order By id for User' })
+11 -14
View File
@@ -10,7 +10,7 @@ import {
} from 'class-validator';
import { Type, Transform } from 'class-transformer';
import { ApiPropertyOptional } from '@nestjs/swagger';
import { OrderStatus } from '../interface/order.interface';
import { OrderStatusEnum } from '../interface/order.interface';
import { PaymentStatusEnum } from '../../payment/interface/payment';
const sortOrderOptions = ['asc', 'desc'] as const;
@@ -31,13 +31,10 @@ export class FindOrdersDto {
@Min(1)
limit: number = 10;
/**
* ?statuses=paid,confirmed
* ?statuses=paid&statuses=confirmed
*/
@ApiPropertyOptional({
description: 'Filter by order statuses',
enum: OrderStatus,
enum: OrderStatusEnum,
isArray: true,
})
@IsOptional()
@@ -45,13 +42,13 @@ export class FindOrdersDto {
Array.isArray(value) ? value : value?.split(',')
)
@IsArray()
@IsEnum(OrderStatus, { each: true })
statuses?: OrderStatus[];
@IsEnum(OrderStatusEnum, { each: true })
statuses?: OrderStatusEnum[];
@ApiPropertyOptional({ enum: PaymentStatusEnum })
@IsOptional()
@IsEnum(PaymentStatusEnum)
paymentStatus?: PaymentStatusEnum;
// @ApiPropertyOptional({ enum: PaymentStatusEnum })
// @IsOptional()
// @IsEnum(PaymentStatusEnum)
// paymentStatus?: PaymentStatusEnum;
@ApiPropertyOptional()
@IsOptional()
@@ -61,12 +58,12 @@ export class FindOrdersDto {
@ApiPropertyOptional({ format: 'date-time' })
@IsOptional()
@IsDateString()
startDate?: string;
from?: string;
@ApiPropertyOptional({ format: 'date-time' })
@IsOptional()
@IsDateString()
endDate?: string;
to?: string;
@ApiPropertyOptional({ default: 'createdAt' })
@IsOptional()
+3 -3
View File
@@ -10,7 +10,7 @@ import {
PrimaryKey,
} from '@mikro-orm/core';
import { BaseEntity } from '../../../common/entities/base.entity';
import { OrderStatus } from '../interface/order.interface';
import { OrderStatusEnum } from '../interface/order.interface';
import { User } from '../../user/entities/user.entity';
import { OrderItem } from './order-item.entity';
import { Payment } from 'src/modules/payment/entities/payment.entity';
@@ -68,7 +68,7 @@ export class Order extends BaseEntity {
// description?: string;
@Enum(() => OrderStatus)
status!: OrderStatus;
@Enum(() => OrderStatusEnum)
status!: OrderStatusEnum;
}
+3 -3
View File
@@ -1,4 +1,4 @@
import type { OrderStatus } from '../interface/order.interface';
import type { OrderStatusEnum } from '../interface/order.interface';
export class OrderCreatedEvent {
constructor(
@@ -15,7 +15,7 @@ export class OrderStatusChangedEvent {
public readonly userId: string,
public readonly orderNumber: string,
public readonly: string,
public readonly previousStatus: OrderStatus,
public readonly newStatus: OrderStatus,
public readonly previousStatus: OrderStatusEnum,
public readonly newStatus: OrderStatusEnum,
) { }
}
@@ -1,5 +1,6 @@
export enum OrderStatus {
export enum OrderStatusEnum {
NEW = 'new',
INVOICE = 'invoice',
PREPARING = 'preparing',
COMPLETED = 'completed',
CANCELED = 'canceled',
@@ -7,7 +7,7 @@ import { NotifTitleEnum } from 'src/modules/notification/interfaces/notification
import { NotificationService } from 'src/modules/notification/services/notification.service';
import { ConfigService } from '@nestjs/config';
import { OrderRepository } from '../repositories/order.repository';
import { OrderStatus } from '../interface/order.interface';
import { OrderStatusEnum } from '../interface/order.interface';
import { PaymentMethodEnum } from 'src/modules/payment/interface/payment';
import { UserService } from 'src/modules/user/providers/user.service';
@@ -3,23 +3,18 @@ import { EntityManager } from '@mikro-orm/postgresql';
import { Order } from '../entities/order.entity';
import { OrderItem } from '../entities/order-item.entity';
import { User } from '../../user/entities/user.entity';
import { PaymentMethodEnum, PaymentStatusEnum } from '../../payment/interface/payment';
import { PaymentsService } from '../../payment/services/payments.service';
import { OrderRepository } from '../repositories/order.repository';
import { FindOrdersDto } from '../dto/find-orders.dto';
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
import { Payment } from 'src/modules/payment/entities/payment.entity';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { OrderCreatedEvent, OrderStatusChangedEvent } from '../events/order.events';
import { OrderMessage } from 'src/common/enums/message.enum';
import { CreateOrderDto } from '../dto/create-order.dto';
import { UserService } from 'src/modules/user/providers/user.service';
import { OrderItemStatus, OrderStatus } from '../interface/order.interface';
import { OrderItemStatus, OrderStatusEnum } from '../interface/order.interface';
import { OrderItemRepository } from '../repositories/order-item.repository';
import { ProductService } from 'src/modules/product/providers/product.service';
import { ProductRepository } from 'src/modules/product/repositories/product.repository';
@@ -62,7 +57,7 @@ export class OrdersService {
total: 0,
paidAmount: 0,
balance: 0,
status: OrderStatus.NEW
status: OrderStatusEnum.NEW
})
em.persist(order)
@@ -109,4 +104,8 @@ export class OrdersService {
return order
}
async findAllForUser(userId: string, dto: FindOrdersDto) {
const orders = await this.orderRepository.findAllPaginated({ userId, ...dto })
return orders
}
}
@@ -3,22 +3,13 @@ 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.interface';
import { OrderStatusEnum } from '../interface/order.interface';
import { PaymentMethodEnum, PaymentStatusEnum } from '../../payment/interface/payment';
import { FindOrdersDto } from '../dto/find-orders.dto';
type FindOrdersOpts = {
page?: number;
limit?: number;
statuses?: OrderStatus[];
paymentStatus?: PaymentStatusEnum;
search?: string;
startDate?: string;
endDate?: string;
orderBy?: string;
order?: 'asc' | 'desc';
class FindOrdersOpts extends FindOrdersDto {
userId?: string;
excludeOnlinePendingPayment?: boolean;
};
@Injectable()
@@ -31,18 +22,17 @@ export class OrderRepository extends EntityRepository<Order> {
* Find orders with pagination and optional filters.
* Supports: statuses, paymentStatus, search (orderNumber), date range, ordering.
*/
async findAllPaginated( opts: FindOrdersOpts = {}): Promise<PaginatedResult<Order>> {
async findAllPaginated(opts: FindOrdersOpts): Promise<PaginatedResult<Order>> {
const {
page = 1,
limit = 10,
statuses,
search,
startDate,
endDate,
orderBy = 'createdAt',
order = 'desc',
userId,
excludeOnlinePendingPayment = false,
from,
to
} = opts;
const offset = (page - 1) * limit;
@@ -54,7 +44,7 @@ export class OrderRepository extends EntityRepository<Order> {
// Ensure statuses is always an array and normalize it
const normalizedStatuses = Array.isArray(statuses) ? statuses : [statuses];
// Filter out any empty values
const validStatuses = normalizedStatuses.filter((s): s is OrderStatus => !!s);
const validStatuses = normalizedStatuses.filter((s): s is OrderStatusEnum => !!s);
if (validStatuses.length > 0) {
// Use direct equality for single value, $in for multiple values to avoid SQL generation issues
@@ -71,13 +61,13 @@ export class OrderRepository extends EntityRepository<Order> {
}
// Filter by date range
if (startDate || endDate) {
if (from || to) {
where.createdAt = {};
if (startDate) {
where.createdAt.$gte = new Date(startDate);
if (from) {
where.createdAt.$gte = new Date(from);
}
if (endDate) {
where.createdAt.$lte = new Date(endDate);
if (to) {
where.createdAt.$lte = new Date(to);
}
}
@@ -99,40 +89,38 @@ export class OrderRepository extends EntityRepository<Order> {
where.$or = searchConditions;
}
// First, fetch orders without reviews
const [data, total] = await this.findAndCount(where, {
limit,
offset,
orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' },
populate: ['user', 'restaurant', 'deliveryMethod', 'paymentMethod', 'items', 'items.product'] as never,
populate: ['items','items.product'],
});
// Collect all (orderId, productId) pairs for efficient review lookup
const orderproductPairs: Array<{ orderId: string; productId: bigint }> = [];
for (const order of data) {
for (const item of order.items.getItems()) {
if (item.product?.id) {
orderproductPairs.push({ orderId: order.id, productId: item.product.id });
}
}
}
// const orderproductPairs: Array<{ orderId: string; productId: bigint }> = [];
// for (const order of data) {
// for (const item of order.items.getItems()) {
// if (item.product?.id) {
// orderproductPairs.push({ orderId: order.id, productId: item.product.id });
// }
// }
// }
// Map reviewIds to products
for (const order of data) {
for (const item of order.items.getItems()) {
if (item.product) {
const key = `${order.id}-${item.product.id}`;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const product = item.product as any;
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
// for (const order of data) {
// for (const item of order.items.getItems()) {
// if (item.product) {
// const key = `${order.id}-${item.product.id}`;
// // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
// const product = item.product as any;
// // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
}
}
}
// }
// }
// }
const totalPages = Math.ceil(total / limit);
@@ -6,7 +6,7 @@ import { Order } from '../../order/entities/order.entity';
import { Logger } from '@nestjs/common';
import { GatewayManager } from '../gateways/gateway.manager';
import { OrderPaymentContext } from '../interface/payment';
import { OrderStatus } from 'src/modules/order/interface/order.interface';
import { OrderStatusEnum } from 'src/modules/order/interface/order.interface';
import { ChartPeriodEnum, PaymentChartDto } from '../dto/payment-chart.dto';
import { PaymentMessage, OrderMessage } from 'src/common/enums/message.enum';
import { EventEmitter2 } from '@nestjs/event-emitter';