array of statuses for fin orders

This commit is contained in:
2025-12-22 15:12:05 +03:30
parent 2a6d53b04d
commit 7aee650ac6
3 changed files with 54 additions and 85 deletions
+34 -77
View File
@@ -1,126 +1,83 @@
import { IsOptional, IsString, IsNumber, Min, IsIn, IsEnum, IsDateString } from 'class-validator'; import {
import { Type } from 'class-transformer'; IsOptional,
IsString,
IsNumber,
Min,
IsIn,
IsEnum,
IsDateString,
IsArray,
} from 'class-validator';
import { Type, Transform } from 'class-transformer';
import { ApiPropertyOptional } from '@nestjs/swagger'; import { ApiPropertyOptional } from '@nestjs/swagger';
import { OrderStatus } from '../interface/order.interface'; import { OrderStatus } from '../interface/order.interface';
import { PaymentStatusEnum } from '../../payments/interface/payment'; import { PaymentStatusEnum } from '../../payments/interface/payment';
// Define the valid sort directions
const sortOrderOptions = ['asc', 'desc'] as const; const sortOrderOptions = ['asc', 'desc'] as const;
type SortOrder = (typeof sortOrderOptions)[number]; type SortOrder = (typeof sortOrderOptions)[number];
export class FindOrdersDto { export class FindOrdersDto {
/** @ApiPropertyOptional({ default: 1, minimum: 1 })
* The page number to retrieve.
* @default 1
*/
@ApiPropertyOptional({
description: 'Page number',
type: Number,
default: 1,
minimum: 1,
})
@IsOptional() @IsOptional()
@Type(() => Number)
@IsNumber() @IsNumber()
@Min(1) @Min(1)
@Type(() => Number) page: number = 1;
page?: number = 1;
/** @ApiPropertyOptional({ default: 10, minimum: 1 })
* The number of items per page.
* @default 10
*/
@ApiPropertyOptional({
description: 'Number of items per page',
type: Number,
default: 10,
minimum: 1,
})
@IsOptional() @IsOptional()
@Type(() => Number)
@IsNumber() @IsNumber()
@Min(1) @Min(1)
@Type(() => Number) limit: number = 10;
limit?: number = 10;
/** /**
* Filter by order status * ?statuses=paid,confirmed
* ?statuses=paid&statuses=confirmed
*/ */
@ApiPropertyOptional({ @ApiPropertyOptional({
description: 'Filter by order status', description: 'Filter by order statuses',
enum: OrderStatus, enum: OrderStatus,
isArray: true,
}) })
@IsOptional() @IsOptional()
@IsEnum(OrderStatus) @Transform(({ value }) =>
status?: OrderStatus; Array.isArray(value) ? value : value?.split(',')
)
@IsArray()
@IsEnum(OrderStatus, { each: true })
statuses?: OrderStatus[];
/** @ApiPropertyOptional({ enum: PaymentStatusEnum })
* Filter by payment status
*/
@ApiPropertyOptional({
description: 'Filter by payment status',
enum: PaymentStatusEnum,
})
@IsOptional() @IsOptional()
@IsEnum(PaymentStatusEnum) @IsEnum(PaymentStatusEnum)
paymentStatus?: PaymentStatusEnum; paymentStatus?: PaymentStatusEnum;
/** @ApiPropertyOptional()
* Search by order number or user information
*/
@ApiPropertyOptional({
description: 'Search by order number or user information',
type: String,
})
@IsOptional() @IsOptional()
@IsString() @IsString()
search?: string; search?: string;
/** @ApiPropertyOptional({ format: 'date-time' })
* Filter orders from this date (ISO date string)
*/
@ApiPropertyOptional({
description: 'Filter orders from this date (ISO date string)',
type: String,
format: 'date-time',
})
@IsOptional() @IsOptional()
@IsDateString() @IsDateString()
startDate?: string; startDate?: string;
/** @ApiPropertyOptional({ format: 'date-time' })
* Filter orders until this date (ISO date string)
*/
@ApiPropertyOptional({
description: 'Filter orders until this date (ISO date string)',
type: String,
format: 'date-time',
})
@IsOptional() @IsOptional()
@IsDateString() @IsDateString()
endDate?: string; endDate?: string;
/** @ApiPropertyOptional({ default: 'createdAt' })
* The field to sort the results by.
* @default "createdAt"
*/
@ApiPropertyOptional({
description: 'Field to sort by (createdAt, total, orderNumber)',
type: String,
default: 'createdAt',
})
@IsOptional() @IsOptional()
@IsString() @IsString()
orderBy?: string = 'createdAt'; orderBy: string = 'createdAt';
/**
* The direction to sort the results.
* @default "desc"
*/
@ApiPropertyOptional({ @ApiPropertyOptional({
description: 'Sort direction (asc or desc)',
enum: sortOrderOptions, enum: sortOrderOptions,
default: 'desc', default: 'desc',
}) })
@IsOptional() @IsOptional()
@IsIn(sortOrderOptions) @IsIn(sortOrderOptions)
order?: SortOrder = 'desc'; order: SortOrder = 'desc';
} }
@@ -177,7 +177,7 @@ export class OrdersService {
const result = await this.orderRepository.findAllPaginated(restId, { const result = await this.orderRepository.findAllPaginated(restId, {
page: dto.page, page: dto.page,
limit: dto.limit, limit: dto.limit,
status: dto.status, statuses: dto.statuses,
paymentStatus: dto.paymentStatus, paymentStatus: dto.paymentStatus,
search: dto.search, search: dto.search,
startDate: dto.startDate, startDate: dto.startDate,
@@ -194,7 +194,7 @@ export class OrdersService {
const result = await this.orderRepository.findAllPaginated(restId, { const result = await this.orderRepository.findAllPaginated(restId, {
page: dto.page, page: dto.page,
limit: dto.limit, limit: dto.limit,
status: dto.status, statuses: dto.statuses,
paymentStatus: dto.paymentStatus, paymentStatus: dto.paymentStatus,
search: dto.search, search: dto.search,
startDate: dto.startDate, startDate: dto.startDate,
@@ -10,7 +10,7 @@ import { Review } from '../../review/entities/review.entity';
type FindOrdersOpts = { type FindOrdersOpts = {
page?: number; page?: number;
limit?: number; limit?: number;
status?: OrderStatus; statuses?: OrderStatus[];
paymentStatus?: PaymentStatusEnum; paymentStatus?: PaymentStatusEnum;
search?: string; search?: string;
startDate?: string; startDate?: string;
@@ -28,13 +28,13 @@ export class OrderRepository extends EntityRepository<Order> {
/** /**
* Find orders with pagination and optional filters. * Find orders with pagination and optional filters.
* Supports: status, paymentStatus, search (orderNumber), date range, ordering. * Supports: statuses, paymentStatus, search (orderNumber), date range, ordering.
*/ */
async findAllPaginated(restId: string, opts: FindOrdersOpts = {}): Promise<PaginatedResult<Order>> { async findAllPaginated(restId: string, opts: FindOrdersOpts = {}): Promise<PaginatedResult<Order>> {
const { const {
page = 1, page = 1,
limit = 10, limit = 10,
status, statuses,
search, search,
startDate, startDate,
endDate, endDate,
@@ -47,9 +47,21 @@ export class OrderRepository extends EntityRepository<Order> {
const where: FilterQuery<Order> = { restaurant: { id: restId } }; const where: FilterQuery<Order> = { restaurant: { id: restId } };
// Filter by status // Filter by statuses
if (status) { if (statuses) {
where.status = status; // 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);
if (validStatuses.length > 0) {
// Use direct equality for single value, $in for multiple values to avoid SQL generation issues
if (validStatuses.length === 1) {
where.status = validStatuses[0];
} else {
where.status = { $in: validStatuses };
}
}
} }
if (userId) { if (userId) {