From 82f53a1642bf54f13615a0fa4d2937152e91a99b Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Sat, 4 Jul 2026 12:49:00 +0330 Subject: [PATCH] wallet creadit request list --- .../controllers/restaurants.controller.ts | 14 ++++ .../find-restaurant-credit-requests.dto.ts | 65 +++++++++++++++ .../providers/restaurant-wallet.service.ts | 7 ++ .../providers/restaurants.service.ts | 5 ++ .../restaurant-credit-request.repository.ts | 81 +++++++++++++++++++ src/modules/restaurants/restaurants.module.ts | 2 + 6 files changed, 174 insertions(+) create mode 100644 src/modules/restaurants/dto/find-restaurant-credit-requests.dto.ts create mode 100644 src/modules/restaurants/repositories/restaurant-credit-request.repository.ts diff --git a/src/modules/restaurants/controllers/restaurants.controller.ts b/src/modules/restaurants/controllers/restaurants.controller.ts index 86b17c5..75e3136 100644 --- a/src/modules/restaurants/controllers/restaurants.controller.ts +++ b/src/modules/restaurants/controllers/restaurants.controller.ts @@ -27,6 +27,7 @@ import { UpdateRestaurantBgDto } from '../dto/update-restaurant-bg.dto'; import { ChargeRequestDto } from '../dto/charge-request.dto'; import { FinishChargeRequestDto } from '../dto/finish-charge-request.dto'; import { FindRestaurantWalletTransactionsDto } from '../dto/find-restaurant-wallet-transactions.dto'; +import { FindRestaurantCreditRequestsDto } from '../dto/find-restaurant-credit-requests.dto'; @ApiTags('restaurants') @Controller() @@ -122,6 +123,19 @@ export class RestaurantsController { return this.restaurantsService.getWalletTransactions(restId, query); } + @UseGuards(AdminAuthGuard) + @ApiBearerAuth() + @Permissions(Permission.UPDATE_RESTAURANT) + @ApiOperation({ summary: 'Get restaurant credit requests with pagination' }) + @Get('admin/restaurants/charge-requests') + getCreditRequests( + @RestId() restId: string, + @Query(new ValidationPipe({ transform: true, whitelist: true })) + query: FindRestaurantCreditRequestsDto, + ) { + return this.restaurantsService.getCreditRequests(restId, query); + } + @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Permissions(Permission.UPDATE_RESTAURANT) diff --git a/src/modules/restaurants/dto/find-restaurant-credit-requests.dto.ts b/src/modules/restaurants/dto/find-restaurant-credit-requests.dto.ts new file mode 100644 index 0000000..2222826 --- /dev/null +++ b/src/modules/restaurants/dto/find-restaurant-credit-requests.dto.ts @@ -0,0 +1,65 @@ +import { IsOptional, IsString, IsNumber, Min, IsIn, IsDateString } from 'class-validator'; +import { Type } from 'class-transformer'; +import { ApiPropertyOptional } from '@nestjs/swagger'; +import { RestaurantCreditRequestStatus } from '../interface/restaurant-credit-request.interface'; + +const sortOrderOptions = ['asc', 'desc'] as const; +type SortOrder = (typeof sortOrderOptions)[number]; + +export class FindRestaurantCreditRequestsDto { + @ApiPropertyOptional({ description: 'Page number', type: Number, default: 1, minimum: 1 }) + @IsOptional() + @IsNumber() + @Min(1) + @Type(() => Number) + page?: number = 1; + + @ApiPropertyOptional({ description: 'Items per page', type: Number, default: 10, minimum: 1 }) + @IsOptional() + @IsNumber() + @Min(1) + @Type(() => Number) + limit?: number = 10; + + @ApiPropertyOptional({ description: 'Status filter', enum: RestaurantCreditRequestStatus }) + @IsOptional() + @IsIn(Object.values(RestaurantCreditRequestStatus)) + status?: RestaurantCreditRequestStatus; + + @ApiPropertyOptional({ description: 'Invoice ID filter', type: String }) + @IsOptional() + @IsString() + invoiceId?: string; + + @ApiPropertyOptional({ description: 'Start date filter (ISO 8601 format)', type: String }) + @IsOptional() + @IsDateString() + startDate?: string; + + @ApiPropertyOptional({ description: 'End date filter (ISO 8601 format)', type: String }) + @IsOptional() + @IsDateString() + endDate?: string; + + @ApiPropertyOptional({ description: 'Minimum amount filter', type: Number }) + @IsOptional() + @IsNumber() + @Type(() => Number) + minAmount?: number; + + @ApiPropertyOptional({ description: 'Maximum amount filter', type: Number }) + @IsOptional() + @IsNumber() + @Type(() => Number) + maxAmount?: number; + + @ApiPropertyOptional({ description: 'Sort field', type: String, default: 'createdAt' }) + @IsOptional() + @IsString() + orderBy?: string = 'createdAt'; + + @ApiPropertyOptional({ description: 'Sort direction', enum: sortOrderOptions, default: 'desc' }) + @IsOptional() + @IsIn(sortOrderOptions) + order?: SortOrder = 'desc'; +} diff --git a/src/modules/restaurants/providers/restaurant-wallet.service.ts b/src/modules/restaurants/providers/restaurant-wallet.service.ts index 59b1fbb..d748137 100644 --- a/src/modules/restaurants/providers/restaurant-wallet.service.ts +++ b/src/modules/restaurants/providers/restaurant-wallet.service.ts @@ -16,7 +16,9 @@ import { CreateExternalInvoice } from '../interface/external-invoice.interface'; import { ChargeRequestDto } from '../dto/charge-request.dto'; import { FinishChargeRequestDto } from '../dto/finish-charge-request.dto'; import { FindRestaurantWalletTransactionsDto } from '../dto/find-restaurant-wallet-transactions.dto'; +import { FindRestaurantCreditRequestsDto } from '../dto/find-restaurant-credit-requests.dto'; import { RestaurantCreditTransactionRepository } from '../repositories/restaurant-credit-transaction.repository'; +import { RestaurantCreditRequestRepository } from '../repositories/restaurant-credit-request.repository'; import { RestMessage } from 'src/common/enums/message.enum'; @Injectable() @@ -28,6 +30,7 @@ export class RestaurantWalletService { private readonly httpService: HttpService, private readonly configService: ConfigService, private readonly restaurantCreditTransactionRepository: RestaurantCreditTransactionRepository, + private readonly restaurantCreditRequestRepository: RestaurantCreditRequestRepository, ) {} async getCurrentBalance(restaurantId: string, em: EntityManager = this.defaultEm): Promise { @@ -44,6 +47,10 @@ export class RestaurantWalletService { return this.restaurantCreditTransactionRepository.findAllPaginated(restaurantId, dto); } + getCreditRequests(restaurantId: string, dto: FindRestaurantCreditRequestsDto) { + return this.restaurantCreditRequestRepository.findAllPaginated(restaurantId, dto); + } + async createTransaction(params: { restaurant: Restaurant; amount: number; diff --git a/src/modules/restaurants/providers/restaurants.service.ts b/src/modules/restaurants/providers/restaurants.service.ts index 6059d2b..f0b06a7 100644 --- a/src/modules/restaurants/providers/restaurants.service.ts +++ b/src/modules/restaurants/providers/restaurants.service.ts @@ -36,6 +36,7 @@ import { RestaurantWalletService } from './restaurant-wallet.service'; import { ChargeRequestDto } from '../dto/charge-request.dto'; import { FinishChargeRequestDto } from '../dto/finish-charge-request.dto'; import { FindRestaurantWalletTransactionsDto } from '../dto/find-restaurant-wallet-transactions.dto'; +import { FindRestaurantCreditRequestsDto } from '../dto/find-restaurant-credit-requests.dto'; @Injectable() @@ -340,6 +341,10 @@ export class RestaurantsService { return this.restaurantWalletService.getTransactions(restId, dto); } + getCreditRequests(restId: string, dto: FindRestaurantCreditRequestsDto) { + return this.restaurantWalletService.getCreditRequests(restId, dto); + } + chargeRequest(restId: string, dto: ChargeRequestDto) { return this.restaurantWalletService.chargeRequest(restId, dto); } diff --git a/src/modules/restaurants/repositories/restaurant-credit-request.repository.ts b/src/modules/restaurants/repositories/restaurant-credit-request.repository.ts new file mode 100644 index 0000000..41bb2e1 --- /dev/null +++ b/src/modules/restaurants/repositories/restaurant-credit-request.repository.ts @@ -0,0 +1,81 @@ +import { Injectable } from '@nestjs/common'; +import { FilterQuery } from '@mikro-orm/core'; +import { EntityManager, EntityRepository } from '@mikro-orm/postgresql'; +import { RestaurantCreditRequest } from '../entities/restaurant-credit-request.entity'; +import { FindRestaurantCreditRequestsDto } from '../dto/find-restaurant-credit-requests.dto'; +import { PaginatedResult } from 'src/common/interfaces/pagination.interface'; + +@Injectable() +export class RestaurantCreditRequestRepository extends EntityRepository { + constructor(readonly em: EntityManager) { + super(em, RestaurantCreditRequest); + } + + async findAllPaginated( + restaurantId: string, + dto: FindRestaurantCreditRequestsDto, + ): Promise> { + const { + page = 1, + limit = 10, + status, + invoiceId, + startDate, + endDate, + minAmount, + maxAmount, + orderBy = 'createdAt', + order = 'desc', + } = dto; + + const offset = (page - 1) * limit; + + const where: FilterQuery = { + restaurant: { id: restaurantId }, + }; + + if (status) { + where.status = status; + } + + if (invoiceId) { + where.invoiceId = invoiceId; + } + + if (startDate || endDate) { + where.createdAt = {}; + if (startDate) { + where.createdAt.$gte = new Date(startDate); + } + if (endDate) { + where.createdAt.$lte = new Date(endDate); + } + } + + if (minAmount !== undefined || maxAmount !== undefined) { + where.amount = {}; + if (minAmount !== undefined) { + where.amount.$gte = minAmount; + } + if (maxAmount !== undefined) { + where.amount.$lte = maxAmount; + } + } + + const [data, total] = await this.findAndCount(where, { + limit, + offset, + orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' }, + }); + + return { + data, + meta: { + total, + page, + limit, + totalPages: Math.ceil(total / limit), + }, + }; + } +} diff --git a/src/modules/restaurants/restaurants.module.ts b/src/modules/restaurants/restaurants.module.ts index 8ac67f8..b1ad6fb 100644 --- a/src/modules/restaurants/restaurants.module.ts +++ b/src/modules/restaurants/restaurants.module.ts @@ -16,6 +16,7 @@ import { UtilsModule } from '../utils/utils.module'; import { Background } from './entities/background.entity'; import { BackgroundRepository } from './repositories/background.repository'; import { RestaurantCreditTransactionRepository } from './repositories/restaurant-credit-transaction.repository'; +import { RestaurantCreditRequestRepository } from './repositories/restaurant-credit-request.repository'; import { RestaurantCreditTransaction } from './entities/restaurant-credit-transaction.entity'; import { RestaurantCreditRequest } from './entities/restaurant-credit-request.entity'; import { RestaurantWalletService } from './providers/restaurant-wallet.service'; @@ -31,6 +32,7 @@ import { httpConfig } from 'src/config/http.config'; RestaurantCrone, BackgroundRepository, RestaurantCreditTransactionRepository, + RestaurantCreditRequestRepository, RestaurantWalletService, ], imports: [