diff --git a/src/modules/payments/controllers/payments.controller.ts b/src/modules/payments/controllers/payments.controller.ts index 5ecf0e7..1d9ca19 100644 --- a/src/modules/payments/controllers/payments.controller.ts +++ b/src/modules/payments/controllers/payments.controller.ts @@ -16,6 +16,7 @@ import { UpdatePaymentMethodDto } from '../dto/update-payment-method.dto'; import { VerifyPaymentDto } from '../dto/verify-payment.dto'; import { RestId, UserId } from 'src/common/decorators'; import { AuthGuard } from 'src/modules/auth/guards/auth.guard'; +import { API_HEADER_SLUG } from 'src/common/constants'; @ApiTags('payments') @Controller() @@ -23,20 +24,13 @@ export class PaymentsController { constructor( private readonly paymentsService: PaymentsService, private readonly paymentMethodService: PaymentMethodService, - ) { } + ) {} @UseGuards(AuthGuard) @ApiBearerAuth() @Get('public/payments/methods/restaurant') @ApiOperation({ summary: 'Get the restaurant payment methods' }) - @ApiHeader({ - name: 'X-Slug', - required: true, - schema: { - type: 'string', - default: 'zhivan', - }, - }) + @ApiHeader(API_HEADER_SLUG) @ApiNotFoundResponse({ description: 'Restaurant payment methods not found' }) getTheRestaurantPaymentMethods(@RestId() restId: string) { return this.paymentMethodService.findByRestaurant(restId); @@ -46,14 +40,7 @@ export class PaymentsController { @ApiBearerAuth() @Get('public/payments') @ApiOperation({ summary: 'Get all the restaurant payments for user' }) - @ApiHeader({ - name: 'X-Slug', - required: true, - schema: { - type: 'string', - default: 'zhivan', - }, - }) + @ApiHeader(API_HEADER_SLUG) findAllByRestaurant(@UserId() userId: string, @RestId() restId: string) { return this.paymentsService.findAllByRestaurantId(restId, userId); } @@ -63,13 +50,19 @@ export class PaymentsController { @Get('public/payments/pay-order/:orderId') @ApiOperation({ summary: 'Pay for an order' }) @ApiParam({ name: 'orderId', type: 'string', description: 'Order ID' }) - @ApiHeader({ - name: 'X-Slug', - required: true, - }) + @ApiHeader(API_HEADER_SLUG) payAnOrder(@Param('orderId') orderId: string) { return this.paymentsService.payOrder(orderId); } + + @Post('public/payments/verify') + @ApiOperation({ summary: 'Verify a payment' }) + @ApiHeader(API_HEADER_SLUG) + @ApiBody({ type: VerifyPaymentDto }) + @ApiNotFoundResponse({ description: 'Payment not found' }) + verifyPayment(@Body() verifyPaymentDto: VerifyPaymentDto) { + return this.paymentsService.verifyPayment(verifyPaymentDto.authority, verifyPaymentDto.orderId); + } // @UseGuards(AdminAuthGuard) // @ApiBearerAuth() // @Get('admin/payments/:id') @@ -152,19 +145,12 @@ export class PaymentsController { return this.paymentMethodService.remove(paymentMethodId); } - @Post('public/payments/verify') - @ApiOperation({ summary: 'Verify a payment' }) - @ApiHeader({ - name: 'X-Slug', - required: true, - schema: { - type: 'string', - default: 'zhivan', - }, - }) - @ApiBody({ type: VerifyPaymentDto }) - @ApiNotFoundResponse({ description: 'Payment not found' }) - verifyPayment(@Body() verifyPaymentDto: VerifyPaymentDto) { - return this.paymentsService.verifyPayment(verifyPaymentDto.authority, verifyPaymentDto.orderId); + @UseGuards(AdminAuthGuard) + @ApiBearerAuth() + @Post('admin/payments/verify-cash-method/:paymentId') + @ApiOperation({ summary: 'Verify cash payment ' }) + @ApiParam({ name: 'paymentId', type: 'string', description: 'Payment ID' }) + verifyCashPayment(@Param('paymentId') paymentId: string) { + return this.paymentMethodService.remove(paymentId); } } diff --git a/src/modules/payments/services/payment-method.service.ts b/src/modules/payments/services/payment-method.service.ts index bfeacf2..2a9b30c 100644 --- a/src/modules/payments/services/payment-method.service.ts +++ b/src/modules/payments/services/payment-method.service.ts @@ -57,4 +57,6 @@ export class PaymentMethodService { await this.em.removeAndFlush(paymentMethod); return paymentMethod; } + + } diff --git a/src/modules/payments/services/payments.service.ts b/src/modules/payments/services/payments.service.ts index fd07451..bd12982 100644 --- a/src/modules/payments/services/payments.service.ts +++ b/src/modules/payments/services/payments.service.ts @@ -9,6 +9,7 @@ import { UserWallet } from 'src/modules/users/entities/user-wallet.entity'; import { OrderPaymentContext } from '../interface/payment'; import { InventoryService } from 'src/modules/inventory/inventory.service'; import { OrderStatus } from 'src/modules/orders/interface/order.interface'; +import { PaymentMethod } from '../entities/payment-method.entity'; @Injectable() export class PaymentsService { @@ -212,6 +213,29 @@ export class PaymentsService { ); } + async verifyCashPayment(id: string): Promise { + const payment = await this.em.transactional(async em => { + const payment = await em.findOne(Payment, id, { populate: ['order'] }); + if (!payment) { + throw new NotFoundException('Payment not found'); + } + if (payment.method !== PaymentMethodEnum.Cash) { + throw new BadRequestException('Payment method is not cash'); + } + if (payment.status === PaymentStatusEnum.Paid) { + throw new BadRequestException('Payment already paid'); + } + payment.order.status = OrderStatus.PAID; + payment.status = PaymentStatusEnum.Paid; + payment.paidAt = new Date(); + em.persist(payment); + em.persist(payment.order); + await em.flush(); + return payment; + }); + return payment; + } + private markPaid(payment: Payment, referenceId: string) { payment.status = PaymentStatusEnum.Paid; payment.paidAt = new Date(); diff --git a/src/modules/restaurants/dto/create-restaurant.dto.ts b/src/modules/restaurants/dto/create-restaurant.dto.ts index 63a05c3..a49388e 100644 --- a/src/modules/restaurants/dto/create-restaurant.dto.ts +++ b/src/modules/restaurants/dto/create-restaurant.dto.ts @@ -1,5 +1,6 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { IsString, IsOptional, IsNumber, IsBoolean, IsArray, IsUrl, IsObject } from 'class-validator'; +import { IsString, IsOptional, IsNumber, IsBoolean, IsArray, IsUrl, IsObject, IsEnum } from 'class-validator'; +import { PlanEnum } from '../interface/plan.interface'; export class CreateRestaurantDto { @ApiProperty({ example: 'کافه ژیوان', description: 'نام رستوران' }) @@ -65,7 +66,6 @@ export class CreateRestaurantDto { @IsNumber() establishedYear?: number; - @ApiPropertyOptional({ example: '09123456789', description: 'شماره تلفن' }) @IsOptional() @IsString() @@ -151,4 +151,8 @@ export class CreateRestaurantDto { marriageDateScore: string; referrerScore: string; }; + + @ApiProperty({ example: true, description: 'PlanEnum.Base', enum: PlanEnum }) + @IsEnum(PlanEnum) + plan: PlanEnum; } diff --git a/src/modules/restaurants/entities/restaurant.entity.ts b/src/modules/restaurants/entities/restaurant.entity.ts index 85f644e..91d4a84 100644 --- a/src/modules/restaurants/entities/restaurant.entity.ts +++ b/src/modules/restaurants/entities/restaurant.entity.ts @@ -1,6 +1,7 @@ -import { Collection, Entity, Index, OneToMany, Property } from '@mikro-orm/core'; +import { Collection, Entity, Enum, Index, OneToMany, Property } from '@mikro-orm/core'; import { BaseEntity } from '../../../common/entities/base.entity'; import { Delivery } from '../../delivery/entities/delivery.entity'; +import { PlanEnum } from '../interface/plan.interface'; @Entity({ tableName: 'restaurants' }) @Index({ properties: ['isActive'] }) @@ -42,7 +43,6 @@ export class Restaurant extends BaseEntity { @Property({ nullable: true }) establishedYear?: number; - @Property({ nullable: true }) phone?: string; @@ -96,4 +96,7 @@ export class Restaurant extends BaseEntity { marriageDateScore: string; referrerScore: string; } | null = null; + + @Enum(() => PlanEnum) + plan: PlanEnum = PlanEnum.Base; } diff --git a/src/modules/restaurants/interface/plan.interface.ts b/src/modules/restaurants/interface/plan.interface.ts new file mode 100644 index 0000000..a5cb074 --- /dev/null +++ b/src/modules/restaurants/interface/plan.interface.ts @@ -0,0 +1,4 @@ +export enum PlanEnum { + Base = 'base', + Premium = 'premium', +} diff --git a/src/modules/restaurants/providers/restaurants.service.ts b/src/modules/restaurants/providers/restaurants.service.ts index 2982a03..c803379 100644 --- a/src/modules/restaurants/providers/restaurants.service.ts +++ b/src/modules/restaurants/providers/restaurants.service.ts @@ -1,7 +1,7 @@ import { Injectable, NotFoundException } from '@nestjs/common'; import { CreateRestaurantDto } from '../dto/create-restaurant.dto'; import { UpdateRestaurantDto } from '../dto/update-restaurant.dto'; - import { Restaurant } from '../entities/restaurant.entity'; +import { Restaurant } from '../entities/restaurant.entity'; import { EntityManager } from '@mikro-orm/postgresql'; import { RestRepository } from '../repositories/rest.repository'; import { RestMessage } from 'src/common/enums/message.enum'; @@ -17,6 +17,7 @@ export class RestaurantsService { const restaurant = this.em.create(Restaurant, { ...dto, isActive: true, + plan: dto.plan, }); await this.em.persistAndFlush(restaurant); diff --git a/src/seeders/data/restaurants.data.ts b/src/seeders/data/restaurants.data.ts index 7b085d6..b2cbd86 100644 --- a/src/seeders/data/restaurants.data.ts +++ b/src/seeders/data/restaurants.data.ts @@ -1,3 +1,5 @@ +import { PlanEnum } from 'src/modules/restaurants/interface/plan.interface'; + export interface RestaurantData { name: string; slug: string; @@ -18,6 +20,7 @@ export interface RestaurantData { marriageDateScore: string; referrerScore: string; }; + plan: PlanEnum.Premium; } export const restaurantsData: RestaurantData[] = [ @@ -49,6 +52,7 @@ export const restaurantsData: RestaurantData[] = [ marriageDateScore: '10000', referrerScore: '10000', }, + plan: PlanEnum.Premium, }, { name: 'بوته', @@ -78,6 +82,7 @@ export const restaurantsData: RestaurantData[] = [ marriageDateScore: '10000', referrerScore: '10000', }, + plan: PlanEnum.Premium, }, { name: 'هنر', @@ -107,5 +112,6 @@ export const restaurantsData: RestaurantData[] = [ marriageDateScore: '10000', referrerScore: '10000', }, + plan: PlanEnum.Premium, }, ];