orders pagination
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import { IsOptional, IsString, IsNumber, Min, IsIn, IsEnum, IsDateString } from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { OrderStatus } from '../interface/order-status';
|
||||
import { PaymentStatusEnum } from '../../payments/interface/payment';
|
||||
|
||||
// Define the valid sort directions
|
||||
const sortOrderOptions = ['asc', 'desc'] as const;
|
||||
type SortOrder = (typeof sortOrderOptions)[number];
|
||||
|
||||
export class FindOrdersDto {
|
||||
/**
|
||||
* The page number to retrieve.
|
||||
* @default 1
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Page number',
|
||||
type: Number,
|
||||
default: 1,
|
||||
minimum: 1,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@Min(1)
|
||||
@Type(() => Number)
|
||||
page?: number = 1;
|
||||
|
||||
/**
|
||||
* The number of items per page.
|
||||
* @default 10
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Number of items per page',
|
||||
type: Number,
|
||||
default: 10,
|
||||
minimum: 1,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@Min(1)
|
||||
@Type(() => Number)
|
||||
limit?: number = 10;
|
||||
|
||||
/**
|
||||
* Filter by order status
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Filter by order status',
|
||||
enum: OrderStatus,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsEnum(OrderStatus)
|
||||
status?: OrderStatus;
|
||||
|
||||
/**
|
||||
* Filter by payment status
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Filter by payment status',
|
||||
enum: PaymentStatusEnum,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsEnum(PaymentStatusEnum)
|
||||
paymentStatus?: PaymentStatusEnum;
|
||||
|
||||
/**
|
||||
* Search by order number or user information
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Search by order number or user information',
|
||||
type: String,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
search?: string;
|
||||
|
||||
/**
|
||||
* Filter orders from this date (ISO date string)
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Filter orders from this date (ISO date string)',
|
||||
type: String,
|
||||
format: 'date-time',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
startDate?: string;
|
||||
|
||||
/**
|
||||
* Filter orders until this date (ISO date string)
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Filter orders until this date (ISO date string)',
|
||||
type: String,
|
||||
format: 'date-time',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
endDate?: string;
|
||||
|
||||
/**
|
||||
* The field to sort the results by.
|
||||
* @default "createdAt"
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Field to sort by (createdAt, total, orderNumber)',
|
||||
type: String,
|
||||
default: 'createdAt',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
orderBy?: string = 'createdAt';
|
||||
|
||||
/**
|
||||
* The direction to sort the results.
|
||||
* @default "desc"
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Sort direction (asc or desc)',
|
||||
enum: sortOrderOptions,
|
||||
default: 'desc',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsIn(sortOrderOptions)
|
||||
order?: SortOrder = 'desc';
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
export enum OrderStatus {
|
||||
Pending = 'pending',
|
||||
|
||||
// PendingConfirmation = 'pendingConfirmation',
|
||||
|
||||
Confirmed = 'confirmed',
|
||||
RejectedByRestaurant = 'rejectedByRestaurant',
|
||||
CancelledByUser = 'cancelledByUser',
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Controller, Get, Post, Param, UseGuards, Patch } from '@nestjs/common';
|
||||
import { Controller, Get, Post, Param, UseGuards, Patch, Query } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam } from '@nestjs/swagger';
|
||||
import { OrdersService } from './orders.service';
|
||||
import { AuthGuard } from '../auth/guards/auth.guard';
|
||||
import { UserId } from '../../common/decorators/user-id.decorator';
|
||||
import { RestId } from 'src/common/decorators/rest-id.decorator';
|
||||
import { AdminAuthGuard } from '../auth/guards/adminAuth.guard';
|
||||
|
||||
import { FindOrdersDto } from './dto/find-orders.dto';
|
||||
|
||||
@ApiTags('orders')
|
||||
@Controller()
|
||||
export class OrdersController {
|
||||
@@ -22,9 +23,9 @@ export class OrdersController {
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@Get('public/orders')
|
||||
@ApiOperation({ summary: 'Get all orders' })
|
||||
findAll(@RestId() restId: string) {
|
||||
return this.ordersService.findAll(restId);
|
||||
@ApiOperation({ summary: 'Get all orders with pagination and filters' })
|
||||
findAll(@RestId() restId: string, @Query() dto: FindOrdersDto) {
|
||||
return this.ordersService.findAll(restId, dto);
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@@ -34,12 +35,19 @@ export class OrdersController {
|
||||
return this.ordersService.findOne(+id);
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@Patch('public/orders/:id/cancel')
|
||||
cancelOrder(@Param('id') id: string) {
|
||||
return this.ordersService.findOne(+id);
|
||||
}
|
||||
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@Get('admin/orders')
|
||||
@ApiOperation({ summary: 'Get all orders' })
|
||||
findAllAdmin(@RestId() restId: string) {
|
||||
return this.ordersService.findAll(restId);
|
||||
@ApiOperation({ summary: 'Get all orders with pagination and filters' })
|
||||
findAllAdmin(@RestId() restId: string, @Query() dto: FindOrdersDto) {
|
||||
return this.ordersService.findAll(restId, dto);
|
||||
}
|
||||
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@@ -68,9 +76,4 @@ export class OrdersController {
|
||||
readyForPickup(@Param('orderId') orderId: string) {
|
||||
return this.ordersService.readyForDelivery(orderId);
|
||||
}
|
||||
|
||||
// @Delete(':id')
|
||||
// remove(@Param('id') id: string) {
|
||||
// return this.ordersService.remove(+id);
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { UtilsModule } from '../utils/utils.module';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
import { PaymentsModule } from '../payments/payments.module';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { OrderRepository } from './repositories/order.repository';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -25,6 +26,7 @@ import { JwtModule } from '@nestjs/jwt';
|
||||
JwtModule,
|
||||
],
|
||||
controllers: [OrdersController],
|
||||
providers: [OrdersService],
|
||||
providers: [OrdersService, OrderRepository],
|
||||
exports: [OrderRepository],
|
||||
})
|
||||
export class OrdersModule {}
|
||||
|
||||
@@ -16,6 +16,9 @@ import { PaymentsService } from '../payments/services/payments.service';
|
||||
import { DeliveryMethodEnum } from '../delivery/interface/delivery';
|
||||
import { Delivery } from '../delivery/entities/delivery.entity';
|
||||
import { Cron, CronExpression } from '@nestjs/schedule';
|
||||
import { OrderRepository } from './repositories/order.repository';
|
||||
import { FindOrdersDto } from './dto/find-orders.dto';
|
||||
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
|
||||
|
||||
@Injectable()
|
||||
export class OrdersService {
|
||||
@@ -25,6 +28,7 @@ export class OrdersService {
|
||||
private readonly em: EntityManager,
|
||||
private readonly cartService: CartService,
|
||||
private readonly paymentsService: PaymentsService,
|
||||
private readonly orderRepository: OrderRepository,
|
||||
// private readonly paymentGatewayService: PaymentGatewayService,
|
||||
) {}
|
||||
|
||||
@@ -234,16 +238,18 @@ export class OrdersService {
|
||||
};
|
||||
}
|
||||
|
||||
async findAll(restId: string) {
|
||||
const orders = await this.em.find(
|
||||
Order,
|
||||
{ restaurant: { id: restId } },
|
||||
{ populate: ['user', 'restaurant', 'deliveryMethod', 'address', 'paymentMethod'] },
|
||||
);
|
||||
if (!orders) {
|
||||
throw new NotFoundException('No orders found');
|
||||
}
|
||||
return orders;
|
||||
async findAll(restId: string, dto: FindOrdersDto): Promise<PaginatedResult<Order>> {
|
||||
return this.orderRepository.findAllPaginated(restId, {
|
||||
page: dto.page,
|
||||
limit: dto.limit,
|
||||
status: dto.status,
|
||||
paymentStatus: dto.paymentStatus,
|
||||
search: dto.search,
|
||||
startDate: dto.startDate,
|
||||
endDate: dto.endDate,
|
||||
orderBy: dto.orderBy,
|
||||
order: dto.order,
|
||||
});
|
||||
}
|
||||
|
||||
findOne(id: number) {
|
||||
@@ -299,8 +305,17 @@ export class OrdersService {
|
||||
return order;
|
||||
}
|
||||
|
||||
remove(id: number) {
|
||||
return `This action removes a #${id} order`;
|
||||
async cancelOrder(orderId: string) {
|
||||
const order = await this.em.findOne(Order, { id: orderId });
|
||||
if (!order) {
|
||||
throw new NotFoundException('Order not found');
|
||||
}
|
||||
if (order.status !== OrderStatus.Pending) {
|
||||
throw new BadRequestException('Order is not pending');
|
||||
}
|
||||
order.status = OrderStatus.CancelledByUser;
|
||||
await this.em.persistAndFlush(order);
|
||||
return order;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user