payment
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { Entity, ManyToOne, OneToMany, Property, Collection, Cascade, Enum } from '@mikro-orm/core';
|
import { Entity, ManyToOne, OneToMany, Property, Collection, Cascade, Enum } from '@mikro-orm/core';
|
||||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||||
import { PaymentStatus } from '../../payments/interface/payment-status';
|
import { PaymentStatusEnum } from '../../payments/interface/payment';
|
||||||
import { OrderStatus } from '../interface/order-status';
|
import { OrderStatus } from '../interface/order-status';
|
||||||
import { User } from '../../users/entities/user.entity';
|
import { User } from '../../users/entities/user.entity';
|
||||||
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
||||||
@@ -55,6 +55,6 @@ export class Order extends BaseEntity {
|
|||||||
@Enum(() => OrderStatus)
|
@Enum(() => OrderStatus)
|
||||||
status!: OrderStatus;
|
status!: OrderStatus;
|
||||||
|
|
||||||
@Enum(() => PaymentStatus)
|
@Enum(() => PaymentStatusEnum)
|
||||||
paymentStatus!: PaymentStatus;
|
paymentStatus!: PaymentStatusEnum;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { UserAddress } from '../users/entities/user-address.entity';
|
|||||||
import { RestaurantPaymentMethod } from '../payments/entities/restaurant-payment-method.entity';
|
import { RestaurantPaymentMethod } from '../payments/entities/restaurant-payment-method.entity';
|
||||||
import { CartService } from '../cart/providers/cart.service';
|
import { CartService } from '../cart/providers/cart.service';
|
||||||
import { OrderStatus } from './interface/order-status';
|
import { OrderStatus } from './interface/order-status';
|
||||||
import { PaymentStatus } from '../payments/interface/payment-status';
|
import { PaymentStatusEnum } from '../payments/interface/payment';
|
||||||
import { Cart } from '../cart/interfaces/cart.interface';
|
import { Cart } from '../cart/interfaces/cart.interface';
|
||||||
import { RestaurantPaymentMethodRepository } from '../payments/repositories/restaurant-payment-method.repository';
|
import { RestaurantPaymentMethodRepository } from '../payments/repositories/restaurant-payment-method.repository';
|
||||||
// import { PaymentGatewayService } from '../payments/services/payment-gateway.service.tss';
|
// import { PaymentGatewayService } from '../payments/services/payment-gateway.service.tss';
|
||||||
@@ -59,7 +59,7 @@ export class OrdersService {
|
|||||||
total: cart.total || 0,
|
total: cart.total || 0,
|
||||||
totalItems: cart.totalItems || 0,
|
totalItems: cart.totalItems || 0,
|
||||||
status: OrderStatus.Pending,
|
status: OrderStatus.Pending,
|
||||||
paymentStatus: PaymentStatus.Pending,
|
paymentStatus: PaymentStatusEnum.Pending,
|
||||||
});
|
});
|
||||||
|
|
||||||
em.persist(order);
|
em.persist(order);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards } from '@nestjs/common';
|
import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards } from '@nestjs/common';
|
||||||
import { PaymentsService } from '../services/payments.service';
|
import { PaymentsService } from '../services/payments.service';
|
||||||
import { CreatePaymentDto } from '../dto/create-payment.dto';
|
|
||||||
import { UpdatePaymentDto } from '../dto/update-payment.dto';
|
import { UpdatePaymentDto } from '../dto/update-payment.dto';
|
||||||
import {
|
import {
|
||||||
ApiTags,
|
ApiTags,
|
||||||
@@ -14,9 +13,8 @@ import {
|
|||||||
} from '@nestjs/swagger';
|
} from '@nestjs/swagger';
|
||||||
import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard';
|
import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard';
|
||||||
import { PaymentMethodService } from '../services/payment-method.service';
|
import { PaymentMethodService } from '../services/payment-method.service';
|
||||||
import { RestaurantPaymentMethodService } from '../services/restaurant-payment-method.service';
|
import { CreatePaymentMethodDto } from '../dto/create-payment-method.dto';
|
||||||
import { CreateRestaurantPaymentMethodDto } from '../dto/create-restaurant-payment-method.dto';
|
import { UpdatePaymentMethodDto } from '../dto/update-payment-method.dto';
|
||||||
import { UpdateRestaurantPaymentMethodDto } from '../dto/update-restaurant-payment-method.dto';
|
|
||||||
import { RestId } from 'src/common/decorators';
|
import { RestId } from 'src/common/decorators';
|
||||||
import { AuthGuard } from 'src/modules/auth/guards/auth.guard';
|
import { AuthGuard } from 'src/modules/auth/guards/auth.guard';
|
||||||
|
|
||||||
@@ -26,7 +24,6 @@ export class PaymentsController {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly paymentsService: PaymentsService,
|
private readonly paymentsService: PaymentsService,
|
||||||
private readonly paymentMethodService: PaymentMethodService,
|
private readonly paymentMethodService: PaymentMethodService,
|
||||||
private readonly restaurantPaymentMethodService: RestaurantPaymentMethodService,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
@UseGuards(AuthGuard)
|
||||||
@@ -35,19 +32,9 @@ export class PaymentsController {
|
|||||||
@ApiOperation({ summary: 'Get the restaurant payment methods' })
|
@ApiOperation({ summary: 'Get the restaurant payment methods' })
|
||||||
@ApiNotFoundResponse({ description: 'Restaurant payment methods not found' })
|
@ApiNotFoundResponse({ description: 'Restaurant payment methods not found' })
|
||||||
getTheRestaurantPaymentMethods(@RestId() restId: string) {
|
getTheRestaurantPaymentMethods(@RestId() restId: string) {
|
||||||
return this.restaurantPaymentMethodService.findByRestaurant(restId);
|
return this.paymentMethodService.findByRestaurant(restId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @UseGuards(AdminAuthGuard)
|
|
||||||
// @ApiBearerAuth()
|
|
||||||
// @Post('admin/payments')
|
|
||||||
// @ApiOperation({ summary: 'Create a new payment' })
|
|
||||||
// @ApiBody({ type: CreatePaymentDto })
|
|
||||||
// @ApiCreatedResponse({ description: 'Payment created successfully' })
|
|
||||||
// createPayment(@Body() createPaymentDto: CreatePaymentDto) {
|
|
||||||
// return this.paymentsService.create(createPaymentDto);
|
|
||||||
// }
|
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@Get('admin/payments')
|
@Get('admin/payments')
|
||||||
@@ -93,78 +80,57 @@ export class PaymentsController {
|
|||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@Get('admin/payments/methods')
|
@Get('admin/payments/methods')
|
||||||
@ApiOperation({ summary: 'Get all payment methods' })
|
@ApiOperation({ summary: 'Get restaurant all payment methods' })
|
||||||
@ApiOkResponse({ description: 'List of all payment methods' })
|
@ApiOkResponse({ description: 'List of restaurant payment methods' })
|
||||||
findAll() {
|
@ApiNotFoundResponse({ description: 'Restaurant payment methods not found' })
|
||||||
return this.paymentMethodService.findAll();
|
findByRestaurant(@RestId() restId: string) {
|
||||||
|
return this.paymentMethodService.findByRestaurant(restId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@Get('admin/payments/methods/:id')
|
@Post('admin/payments/methods')
|
||||||
@ApiOperation({ summary: 'Get a payment method by ID' })
|
@ApiOperation({ summary: 'Create a new restaurant payment method' })
|
||||||
@ApiParam({ name: 'id', type: 'string', description: 'Payment method ID' })
|
@ApiBody({ type: CreatePaymentMethodDto })
|
||||||
|
@ApiCreatedResponse({ description: 'Restaurant payment method created successfully' })
|
||||||
|
createRestaurantPaymentMethod(@RestId() restId: string, @Body() createPaymentMethodDto: CreatePaymentMethodDto) {
|
||||||
|
return this.paymentMethodService.create(restId, createPaymentMethodDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseGuards(AdminAuthGuard)
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@Get('admin/payments/methods/:paymentMethodId')
|
||||||
|
@ApiOperation({ summary: 'Get restaurant payment method by ID' })
|
||||||
|
@ApiParam({ name: 'paymentMethodId', type: 'string', description: 'Payment method ID' })
|
||||||
@ApiOkResponse({ description: 'Payment method found' })
|
@ApiOkResponse({ description: 'Payment method found' })
|
||||||
@ApiNotFoundResponse({ description: 'Payment method not found' })
|
@ApiNotFoundResponse({ description: 'Payment method not found' })
|
||||||
findOne(@Param('id') id: string) {
|
findOneRestaurantPaymentMethod(@Param('paymentMethodId') paymentMethodId: string) {
|
||||||
return this.paymentMethodService.findOne(id);
|
return this.paymentMethodService.findOne(paymentMethodId);
|
||||||
}
|
|
||||||
|
|
||||||
/** restaurant payment methods */
|
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@Post('admin/payments/methods/restaurant')
|
|
||||||
@ApiOperation({ summary: 'Create a new restaurant payment method' })
|
|
||||||
@ApiBody({ type: CreateRestaurantPaymentMethodDto })
|
|
||||||
@ApiCreatedResponse({ description: 'Restaurant payment method created successfully' })
|
|
||||||
create(@RestId() restId: string, @Body() createRestaurantPaymentMethodDto: CreateRestaurantPaymentMethodDto) {
|
|
||||||
return this.restaurantPaymentMethodService.create(restId, createRestaurantPaymentMethodDto);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@Get('admin/payments/methods/restaurant/:restaurantPaymentMethodId')
|
@Patch('admin/payments/methods/:paymentMethodId')
|
||||||
@ApiOperation({ summary: 'Get restaurant payment method by payment method ID' })
|
|
||||||
@ApiParam({ name: 'restaurantPaymentMethodId', type: 'string', description: 'restaurantPaymentMethodId method ID' })
|
|
||||||
@ApiOkResponse({ description: 'List of restaurant payment methods for the payment method' })
|
|
||||||
findByPaymentMethod(@Param('restaurantPaymentMethodId') restaurantPaymentMethodId: string) {
|
|
||||||
return this.restaurantPaymentMethodService.findByPaymentMethod(restaurantPaymentMethodId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@Get('admin/payments/methods/restaurant')
|
|
||||||
@ApiOperation({ summary: 'Get restaurant all payment methods ' })
|
|
||||||
@ApiOkResponse({ description: 'Restaurant payment method found' })
|
|
||||||
@ApiNotFoundResponse({ description: 'Restaurant payment method not found' })
|
|
||||||
findByRestaurant(@RestId() restId: string) {
|
|
||||||
return this.restaurantPaymentMethodService.findByRestaurant(restId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@Patch('admin/payments/methods/restaurant/:restaurantPaymentMethodId')
|
|
||||||
@ApiOperation({ summary: 'Update a restaurant payment method' })
|
@ApiOperation({ summary: 'Update a restaurant payment method' })
|
||||||
@ApiParam({ name: 'restaurantPaymentMethodId', type: 'string', description: 'Restaurant payment method ID' })
|
@ApiParam({ name: 'paymentMethodId', type: 'string', description: 'Payment method ID' })
|
||||||
@ApiBody({ type: UpdateRestaurantPaymentMethodDto })
|
@ApiBody({ type: UpdatePaymentMethodDto })
|
||||||
@ApiOkResponse({ description: 'Restaurant payment method updated successfully' })
|
@ApiOkResponse({ description: 'Restaurant payment method updated successfully' })
|
||||||
@ApiNotFoundResponse({ description: 'Restaurant payment method not found' })
|
@ApiNotFoundResponse({ description: 'Restaurant payment method not found' })
|
||||||
update(
|
updateRestaurantPaymentMethod(
|
||||||
@Param('restaurantPaymentMethodId') restaurantPaymentMethodId: string,
|
@Param('paymentMethodId') paymentMethodId: string,
|
||||||
@Body() updateRestaurantPaymentMethodDto: UpdateRestaurantPaymentMethodDto,
|
@Body() updatePaymentMethodDto: UpdatePaymentMethodDto,
|
||||||
) {
|
) {
|
||||||
return this.restaurantPaymentMethodService.update(restaurantPaymentMethodId, updateRestaurantPaymentMethodDto);
|
return this.paymentMethodService.update(paymentMethodId, updatePaymentMethodDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@Delete('admin/payments/methods/restaurant/:restaurantPaymentMethodId')
|
@Delete('admin/payments/methods/:paymentMethodId')
|
||||||
@ApiOperation({ summary: 'Delete a restaurant payment method' })
|
@ApiOperation({ summary: 'Delete a restaurant payment method' })
|
||||||
@ApiParam({ name: 'restaurantPaymentMethodId', type: 'string', description: 'Restaurant payment method ID' })
|
@ApiParam({ name: 'paymentMethodId', type: 'string', description: 'Payment method ID' })
|
||||||
@ApiOkResponse({ description: 'Restaurant payment method deleted successfully' })
|
@ApiOkResponse({ description: 'Restaurant payment method deleted successfully' })
|
||||||
@ApiNotFoundResponse({ description: 'Restaurant payment method not found' })
|
@ApiNotFoundResponse({ description: 'Restaurant payment method not found' })
|
||||||
remove(@Param('restaurantPaymentMethodId') restaurantPaymentMethodId: string) {
|
removeRestaurantPaymentMethod(@Param('paymentMethodId') paymentMethodId: string) {
|
||||||
return this.restaurantPaymentMethodService.remove(restaurantPaymentMethodId);
|
return this.paymentMethodService.remove(paymentMethodId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,38 @@
|
|||||||
import { IsString, IsOptional, IsBoolean, IsNumber } from 'class-validator';
|
import { IsString, IsOptional, IsBoolean, IsNumber, IsEnum } from 'class-validator';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { PaymentMethodEnum, PaymentGatewayEnum } from '../interface/payment';
|
||||||
|
|
||||||
export class CreatePaymentMethodDto {
|
export class CreatePaymentMethodDto {
|
||||||
@ApiProperty({ description: 'Payment method name' })
|
@ApiProperty({ description: 'Payment method title' })
|
||||||
@IsString()
|
@IsString()
|
||||||
name!: string;
|
title!: string;
|
||||||
|
|
||||||
@ApiProperty({ description: 'English Payment method name' })
|
@ApiProperty({ description: 'Payment method', enum: PaymentMethodEnum })
|
||||||
@IsString()
|
@IsEnum(PaymentMethodEnum)
|
||||||
keyName!: string;
|
method!: PaymentMethodEnum;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Payment gateway', enum: PaymentGatewayEnum, required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsEnum(PaymentGatewayEnum)
|
||||||
|
gateway?: PaymentGatewayEnum | null;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Payment method description', required: false })
|
@ApiProperty({ description: 'Payment method description', required: false })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Payment method icon', required: false })
|
@ApiProperty({ description: 'Is payment method enabled', required: false, default: true })
|
||||||
@IsOptional()
|
|
||||||
@IsString()
|
|
||||||
icon?: string;
|
|
||||||
|
|
||||||
@ApiProperty({ description: 'Is payment method active', required: false, default: true })
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
isActive?: boolean;
|
enabled?: boolean;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Is payment method online', required: false, default: true })
|
@ApiProperty({ description: 'Display order', required: false, default: 0 })
|
||||||
@IsOptional()
|
|
||||||
@IsBoolean()
|
|
||||||
isOnline?: boolean;
|
|
||||||
|
|
||||||
@ApiProperty({ description: 'Display order', required: false })
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsNumber()
|
@IsNumber()
|
||||||
order?: number;
|
order?: number;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Callback URL for payment method', required: false })
|
@ApiProperty({ description: 'Merchant ID', required: false })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
paymentUrl?: string;
|
merchantId?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,27 @@
|
|||||||
import { IsNumber, IsString } from 'class-validator';
|
import { IsEnum, IsNumber, IsOptional, IsString } from 'class-validator';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { PaymentGatewayEnum, PaymentMethodEnum } from '../interface/payment';
|
||||||
|
|
||||||
export class CreatePaymentDto {
|
export class CreatePaymentDto {
|
||||||
|
@ApiProperty({ description: 'Order ID' })
|
||||||
|
@IsString()
|
||||||
|
orderId: string;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Payment amount' })
|
@ApiProperty({ description: 'Payment amount' })
|
||||||
@IsNumber()
|
@IsNumber()
|
||||||
amount: number;
|
amount: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Payment method' })
|
||||||
|
@IsEnum(PaymentMethodEnum)
|
||||||
|
paymentMethod: PaymentMethodEnum;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Payment authority' })
|
@ApiProperty({ description: 'Payment authority' })
|
||||||
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
restaurantPaymentId: string;
|
merchantId?: string | null;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Payment gateway' })
|
@ApiProperty({ description: 'Payment gateway' })
|
||||||
@IsString()
|
@IsOptional()
|
||||||
gateway: string;
|
@IsEnum(PaymentGatewayEnum)
|
||||||
|
gateway?: PaymentGatewayEnum | null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
import { IsString, IsOptional, IsBoolean } from 'class-validator';
|
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
|
|
||||||
export class CreateRestaurantPaymentMethodDto {
|
|
||||||
@ApiProperty({ description: 'Payment method ID' })
|
|
||||||
@IsString()
|
|
||||||
paymentMethodId!: string;
|
|
||||||
|
|
||||||
@ApiProperty({ description: 'Merchant ID', required: false })
|
|
||||||
@IsOptional()
|
|
||||||
@IsString()
|
|
||||||
merchantId?: string;
|
|
||||||
|
|
||||||
@ApiProperty({ description: 'Is active', required: false, default: true })
|
|
||||||
@IsOptional()
|
|
||||||
@IsBoolean()
|
|
||||||
isActive?: boolean;
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,5 @@
|
|||||||
import { PartialType } from '@nestjs/mapped-types';
|
import { PartialType } from '@nestjs/mapped-types';
|
||||||
import { CreatePaymentMethodDto } from './create-payment-method.dto';
|
import { CreatePaymentMethodDto } from './create-payment-method.dto';
|
||||||
import { IsString } from 'class-validator';
|
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
|
|
||||||
export class UpdatePaymentMethodDto extends PartialType(CreatePaymentMethodDto) {
|
export class UpdatePaymentMethodDto extends PartialType(CreatePaymentMethodDto) {}
|
||||||
@ApiProperty({ description: 'Payment method ID' })
|
|
||||||
@IsString()
|
|
||||||
id!: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,4 +8,3 @@ export class UpdatePaymentDto extends PartialType(CreatePaymentDto) {
|
|||||||
@IsNumber()
|
@IsNumber()
|
||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import { PartialType } from '@nestjs/mapped-types';
|
|
||||||
import { CreateRestaurantPaymentMethodDto } from './create-restaurant-payment-method.dto';
|
|
||||||
|
|
||||||
|
|
||||||
export class UpdateRestaurantPaymentMethodDto extends PartialType(CreateRestaurantPaymentMethodDto) {}
|
|
||||||
@@ -1,30 +1,31 @@
|
|||||||
import { Entity, Property } from '@mikro-orm/core';
|
import { Entity, Enum, ManyToOne, Property } from '@mikro-orm/core';
|
||||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||||
|
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
|
||||||
|
import { PaymentGatewayEnum, PaymentMethodEnum } from '../interface/payment';
|
||||||
|
|
||||||
@Entity({ tableName: 'payment_methods' })
|
@Entity({ tableName: 'payment_methods' })
|
||||||
export class PaymentMethod extends BaseEntity {
|
export class PaymentMethod extends BaseEntity {
|
||||||
@Property()
|
@ManyToOne(() => Restaurant)
|
||||||
name!: string;
|
restaurant!: Restaurant;
|
||||||
|
|
||||||
@Property()
|
@Property()
|
||||||
keyName!: string;
|
title!: string;
|
||||||
|
|
||||||
|
@Enum(() => PaymentMethodEnum)
|
||||||
|
method!: PaymentMethodEnum;
|
||||||
|
|
||||||
|
@Enum(() => PaymentGatewayEnum)
|
||||||
|
gateway: PaymentGatewayEnum | null = null;
|
||||||
|
|
||||||
@Property({ nullable: true })
|
@Property({ nullable: true })
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
@Property({ nullable: true })
|
|
||||||
icon?: string;
|
|
||||||
|
|
||||||
@Property({ default: true })
|
@Property({ default: true })
|
||||||
isActive: boolean = true;
|
enabled: boolean = true;
|
||||||
|
|
||||||
@Property({ default: true })
|
|
||||||
isOnline: boolean = true;
|
|
||||||
|
|
||||||
@Property({ type: 'int', nullable: true })
|
|
||||||
order?: number;
|
|
||||||
|
|
||||||
|
@Property({ type: 'integer', default: 0 })
|
||||||
|
order: number = 0;
|
||||||
|
|
||||||
@Property({ nullable: true })
|
@Property({ nullable: true })
|
||||||
paymentUrl?: string;
|
merchantId?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Entity, ManyToOne, Property, Enum } from '@mikro-orm/core';
|
import { Entity, ManyToOne, Property, Enum } from '@mikro-orm/core';
|
||||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||||
import { Order } from '../../orders/entities/order.entity';
|
import { Order } from '../../orders/entities/order.entity';
|
||||||
import { PaymentStatus } from '../interface/payment-status';
|
import { PaymentGatewayEnum, PaymentStatusEnum } from '../interface/payment';
|
||||||
|
|
||||||
@Entity({ tableName: 'payments' })
|
@Entity({ tableName: 'payments' })
|
||||||
export class Payment extends BaseEntity {
|
export class Payment extends BaseEntity {
|
||||||
@@ -14,17 +14,17 @@ export class Payment extends BaseEntity {
|
|||||||
@Property({ unique: true })
|
@Property({ unique: true })
|
||||||
authority!: string;
|
authority!: string;
|
||||||
|
|
||||||
@Property()
|
@Enum(() => PaymentGatewayEnum)
|
||||||
gateway!: string;
|
gateway?: PaymentGatewayEnum | null = null;
|
||||||
|
|
||||||
@Property({ nullable: true })
|
@Property({ nullable: true })
|
||||||
refId?: string;
|
refId?: string | null = null;
|
||||||
|
|
||||||
@Enum(() => PaymentStatus)
|
@Enum(() => PaymentStatusEnum)
|
||||||
status!: PaymentStatus;
|
status!: PaymentStatusEnum;
|
||||||
|
|
||||||
@Property({ nullable: true })
|
@Property({ nullable: true })
|
||||||
cardPan?: string;
|
cardPan?: string | null = null;
|
||||||
|
|
||||||
@Property({ type: 'json' })
|
@Property({ type: 'json' })
|
||||||
verifyResponse?: Record<string, any>;
|
verifyResponse?: Record<string, any>;
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
import { Entity, ManyToOne, Unique, Property } from '@mikro-orm/core';
|
|
||||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
|
||||||
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
|
||||||
import { PaymentMethod } from './payment-method.entity';
|
|
||||||
|
|
||||||
@Entity({ tableName: 'restaurant_payment_methods' })
|
|
||||||
@Unique({ properties: ['restaurant', 'paymentMethod'] })
|
|
||||||
export class RestaurantPaymentMethod extends BaseEntity {
|
|
||||||
@ManyToOne(() => Restaurant)
|
|
||||||
restaurant!: Restaurant;
|
|
||||||
|
|
||||||
@ManyToOne(() => PaymentMethod)
|
|
||||||
paymentMethod!: PaymentMethod;
|
|
||||||
|
|
||||||
// Add merchant ID for payment gateway providers (e.g., ZarinPal)
|
|
||||||
@Property({ nullable: true })
|
|
||||||
merchantId?: string;
|
|
||||||
|
|
||||||
@Property({ nullable: true })
|
|
||||||
callbackUrl?: string;
|
|
||||||
|
|
||||||
@Property({ type: 'boolean', default: true })
|
|
||||||
isActive: boolean = true;
|
|
||||||
}
|
|
||||||
+13
-1
@@ -1,14 +1,26 @@
|
|||||||
export enum PaymentStatus {
|
export enum PaymentMethodEnum {
|
||||||
|
Online = 'Online',
|
||||||
|
Cash = 'Cash',
|
||||||
|
CardOnDelivery = 'CardOnDelivery',
|
||||||
|
Wallet = 'Wallet',
|
||||||
|
}
|
||||||
|
export enum PaymentStatusEnum {
|
||||||
Pending = 'pending',
|
Pending = 'pending',
|
||||||
Paid = 'paid',
|
Paid = 'paid',
|
||||||
Failed = 'failed',
|
Failed = 'failed',
|
||||||
}
|
}
|
||||||
|
export enum PaymentGatewayEnum {
|
||||||
|
ZarinPal = 'zarinpal',
|
||||||
|
}
|
||||||
|
|
||||||
export interface IPaymentRequest {
|
export interface IPaymentRequest {
|
||||||
amount: number;
|
amount: number;
|
||||||
callbackUrl: string;
|
callbackUrl: string;
|
||||||
merchantId: string;
|
merchantId: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
metadata: {
|
||||||
|
orderId: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPaymentResponse {
|
export interface IPaymentResponse {
|
||||||
@@ -4,9 +4,6 @@ import { MikroOrmModule } from '@mikro-orm/nestjs';
|
|||||||
import { PaymentMethod } from './entities/payment-method.entity';
|
import { PaymentMethod } from './entities/payment-method.entity';
|
||||||
import { PaymentMethodRepository } from './repositories/payment-method.repository';
|
import { PaymentMethodRepository } from './repositories/payment-method.repository';
|
||||||
import { PaymentMethodService } from './services/payment-method.service';
|
import { PaymentMethodService } from './services/payment-method.service';
|
||||||
import { RestaurantPaymentMethod } from './entities/restaurant-payment-method.entity';
|
|
||||||
import { RestaurantPaymentMethodRepository } from './repositories/restaurant-payment-method.repository';
|
|
||||||
import { RestaurantPaymentMethodService } from './services/restaurant-payment-method.service';
|
|
||||||
// import { PaymentGatewayService } from './services/payment-gateway.service.tss';
|
// import { PaymentGatewayService } from './services/payment-gateway.service.tss';
|
||||||
import { Restaurant } from '../restaurants/entities/restaurant.entity';
|
import { Restaurant } from '../restaurants/entities/restaurant.entity';
|
||||||
import { PaymentsController } from './controllers/payments.controller';
|
import { PaymentsController } from './controllers/payments.controller';
|
||||||
@@ -14,21 +11,17 @@ import { AuthModule } from '../auth/auth.module';
|
|||||||
import { JwtModule } from '@nestjs/jwt';
|
import { JwtModule } from '@nestjs/jwt';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [MikroOrmModule.forFeature([PaymentMethod, RestaurantPaymentMethod, Restaurant]), AuthModule, JwtModule],
|
imports: [MikroOrmModule.forFeature([PaymentMethod, Restaurant]), AuthModule, JwtModule],
|
||||||
controllers: [PaymentsController],
|
controllers: [PaymentsController],
|
||||||
providers: [
|
providers: [
|
||||||
PaymentsService,
|
PaymentsService,
|
||||||
PaymentMethodService,
|
PaymentMethodService,
|
||||||
PaymentMethodRepository,
|
PaymentMethodRepository,
|
||||||
RestaurantPaymentMethodService,
|
|
||||||
RestaurantPaymentMethodRepository,
|
|
||||||
// PaymentGatewayService,
|
// PaymentGatewayService,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
PaymentMethodRepository,
|
PaymentMethodRepository,
|
||||||
PaymentMethodService,
|
PaymentMethodService,
|
||||||
RestaurantPaymentMethodRepository,
|
|
||||||
RestaurantPaymentMethodService,
|
|
||||||
PaymentsService,
|
PaymentsService,
|
||||||
// PaymentGatewayService,
|
// PaymentGatewayService,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
||||||
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
|
|
||||||
import { RestaurantPaymentMethod } from '../entities/restaurant-payment-method.entity';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class RestaurantPaymentMethodRepository extends EntityRepository<RestaurantPaymentMethod> {
|
|
||||||
constructor(readonly em: EntityManager) {
|
|
||||||
super(em, RestaurantPaymentMethod);
|
|
||||||
}
|
|
||||||
async findOneWithPopulate(id: string): Promise<RestaurantPaymentMethod> {
|
|
||||||
const restaurantPaymentMethod = await this.findOne({ id }, { populate: ['restaurant', 'paymentMethod'] });
|
|
||||||
if (!restaurantPaymentMethod) {
|
|
||||||
throw new NotFoundException('Restaurant payment method not found');
|
|
||||||
}
|
|
||||||
// await restaurantPaymentMethod.restaurant.load();
|
|
||||||
// await restaurantPaymentMethod.paymentMethod.load();
|
|
||||||
return restaurantPaymentMethod;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
|
||||||
import { EntityManager } from '@mikro-orm/postgresql';
|
import { EntityManager } from '@mikro-orm/postgresql';
|
||||||
import { PaymentMethod } from '../entities/payment-method.entity';
|
import { PaymentMethod } from '../entities/payment-method.entity';
|
||||||
import { PaymentMethodRepository } from '../repositories/payment-method.repository';
|
import { PaymentMethodRepository } from '../repositories/payment-method.repository';
|
||||||
import { CreatePaymentMethodDto } from '../dto/create-payment-method.dto';
|
import { CreatePaymentMethodDto } from '../dto/create-payment-method.dto';
|
||||||
import { UpdatePaymentMethodDto } from '../dto/update-payment-method.dto';
|
import { UpdatePaymentMethodDto } from '../dto/update-payment-method.dto';
|
||||||
import { RequiredEntityData } from '@mikro-orm/core';
|
import { RequiredEntityData } from '@mikro-orm/core';
|
||||||
|
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PaymentMethodService {
|
export class PaymentMethodService {
|
||||||
@@ -13,26 +14,40 @@ export class PaymentMethodService {
|
|||||||
private readonly em: EntityManager,
|
private readonly em: EntityManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async create(createPaymentMethodDto: CreatePaymentMethodDto): Promise<PaymentMethod> {
|
async create(restId: string, createPaymentMethodDto: CreatePaymentMethodDto): Promise<PaymentMethod> {
|
||||||
const paymentMethod = this.paymentMethodRepository.create(
|
// Check if restaurant exists
|
||||||
createPaymentMethodDto as unknown as RequiredEntityData<PaymentMethod>,
|
const restaurant = await this.em.findOne(Restaurant, { id: restId });
|
||||||
);
|
if (!restaurant) {
|
||||||
|
throw new NotFoundException(`Restaurant with ID ${restId} not found`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const paymentMethod = this.paymentMethodRepository.create({
|
||||||
|
restaurant,
|
||||||
|
...createPaymentMethodDto,
|
||||||
|
} as unknown as RequiredEntityData<PaymentMethod>);
|
||||||
await this.em.persistAndFlush(paymentMethod);
|
await this.em.persistAndFlush(paymentMethod);
|
||||||
return paymentMethod;
|
return paymentMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(): Promise<PaymentMethod[]> {
|
async findAll(): Promise<PaymentMethod[]> {
|
||||||
return this.paymentMethodRepository.findAll();
|
return this.paymentMethodRepository.findAll({ populate: ['restaurant'] });
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne(id: string): Promise<PaymentMethod> {
|
async findOne(id: string): Promise<PaymentMethod> {
|
||||||
const paymentMethod = await this.paymentMethodRepository.findOne({ id });
|
const paymentMethod = await this.paymentMethodRepository.findOne({ id }, { populate: ['restaurant'] });
|
||||||
if (!paymentMethod) {
|
if (!paymentMethod) {
|
||||||
throw new NotFoundException(`PaymentMethod with ID ${id} not found`);
|
throw new NotFoundException(`PaymentMethod with ID ${id} not found`);
|
||||||
}
|
}
|
||||||
return paymentMethod;
|
return paymentMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findByRestaurant(restaurantId: string): Promise<PaymentMethod[]> {
|
||||||
|
return this.paymentMethodRepository.find(
|
||||||
|
{ restaurant: { id: restaurantId } },
|
||||||
|
{ populate: ['restaurant'] },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async update(id: string, updatePaymentMethodDto: UpdatePaymentMethodDto): Promise<PaymentMethod> {
|
async update(id: string, updatePaymentMethodDto: UpdatePaymentMethodDto): Promise<PaymentMethod> {
|
||||||
const paymentMethod = await this.findOne(id);
|
const paymentMethod = await this.findOne(id);
|
||||||
this.em.assign(paymentMethod, updatePaymentMethodDto);
|
this.em.assign(paymentMethod, updatePaymentMethodDto);
|
||||||
|
|||||||
@@ -1,17 +1,24 @@
|
|||||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||||
import { RestaurantPaymentMethod } from '../entities/restaurant-payment-method.entity';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { IPaymentRequest, IPaymentResponse, PaymentStatus } from '../interface/payment-status';
|
import {
|
||||||
|
IPaymentRequest,
|
||||||
|
IPaymentResponse,
|
||||||
|
PaymentGatewayEnum,
|
||||||
|
PaymentMethodEnum,
|
||||||
|
PaymentStatusEnum,
|
||||||
|
} from '../interface/payment';
|
||||||
import { Payment } from '../entities/payment.entity';
|
import { Payment } from '../entities/payment.entity';
|
||||||
import { EntityManager, RequiredEntityData } from '@mikro-orm/core';
|
import { EntityManager, RequiredEntityData } from '@mikro-orm/core';
|
||||||
import { Order } from '../../orders/entities/order.entity';
|
import { Order } from '../../orders/entities/order.entity';
|
||||||
|
import { PaymentMethod } from '../entities/payment-method.entity';
|
||||||
|
import { CreatePaymentDto } from '../dto/create-payment.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PaymentsService {
|
export class PaymentsService {
|
||||||
constructor(private readonly em: EntityManager) {}
|
constructor(private readonly em: EntityManager) {}
|
||||||
|
|
||||||
async initializePayment(
|
async initializePayment(
|
||||||
restaurantPaymentMethodId: string,
|
paymentMethodId: string,
|
||||||
amount: number,
|
amount: number,
|
||||||
orderId: string,
|
orderId: string,
|
||||||
): Promise<{ paymentUrl: string | null }> {
|
): Promise<{ paymentUrl: string | null }> {
|
||||||
@@ -27,78 +34,97 @@ export class PaymentsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load restaurant payment method with payment method relationship
|
// Load restaurant payment method with payment method relationship
|
||||||
const restaurantPaymentMethod = await this.em.findOne(
|
const paymentMethod = await this.em.findOne(PaymentMethod, { id: paymentMethodId }, { populate: ['restaurant'] });
|
||||||
RestaurantPaymentMethod,
|
if (!paymentMethod) {
|
||||||
{ id: restaurantPaymentMethodId },
|
throw new NotFoundException('Payment method not found');
|
||||||
{ populate: ['paymentMethod'] },
|
|
||||||
);
|
|
||||||
if (!restaurantPaymentMethod) {
|
|
||||||
throw new NotFoundException('Restaurant payment method not found');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!restaurantPaymentMethod.paymentMethod?.isOnline) {
|
if (paymentMethod.method !== PaymentMethodEnum.Online && !paymentMethod.merchantId) {
|
||||||
return { paymentUrl: null };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!restaurantPaymentMethod.callbackUrl) {
|
|
||||||
throw new BadRequestException('Callback URL is not configured');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!restaurantPaymentMethod.merchantId) {
|
|
||||||
throw new BadRequestException('Merchant ID is not provided');
|
throw new BadRequestException('Merchant ID is not provided');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!restaurantPaymentMethod.paymentMethod?.paymentUrl) {
|
|
||||||
throw new BadRequestException('Payment URL is not configured');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request to payment gateway with error handling
|
|
||||||
let gatewayResponse: IPaymentResponse;
|
|
||||||
try {
|
|
||||||
gatewayResponse = await this.requestToPaymentGateway(restaurantPaymentMethod.paymentMethod.paymentUrl, {
|
|
||||||
amount,
|
|
||||||
callbackUrl: restaurantPaymentMethod.callbackUrl,
|
|
||||||
merchantId: restaurantPaymentMethod.merchantId,
|
|
||||||
description: `Payment for order #${orderId}`,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
||||||
throw new BadRequestException(`Failed to connect to payment gateway: ${errorMessage}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check gateway response code (typically 100 means success for Iranian gateways)
|
|
||||||
if (gatewayResponse.code !== 100 && gatewayResponse.code !== 0) {
|
|
||||||
throw new BadRequestException(`Payment gateway error: ${gatewayResponse.message || 'Unknown error'}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gatewayResponse.authority) {
|
|
||||||
throw new BadRequestException('Payment gateway did not return an authority token');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create payment record and save authority
|
// Create payment record and save authority
|
||||||
const payment = this.em.create(Payment, {
|
const restaurantDomain = paymentMethod.restaurant.domain;
|
||||||
|
const { authority } = await this.createPayment(restaurantDomain, {
|
||||||
amount,
|
amount,
|
||||||
authority: gatewayResponse.authority,
|
orderId,
|
||||||
order: this.em.getReference(Order, orderId),
|
paymentMethod: paymentMethod.method,
|
||||||
gateway: restaurantPaymentMethod.paymentMethod.name,
|
merchantId: paymentMethod.merchantId ?? null,
|
||||||
status: PaymentStatus.Pending,
|
gateway: paymentMethod.gateway as PaymentGatewayEnum | null,
|
||||||
} as RequiredEntityData<Payment>);
|
});
|
||||||
|
|
||||||
await this.em.persistAndFlush(payment);
|
const paymentUrl = this.zarinpalPaymentUrl(paymentMethod.gateway, authority);
|
||||||
|
|
||||||
// Return payment URL
|
|
||||||
const paymentUrl = `${restaurantPaymentMethod.paymentMethod.paymentUrl}/${gatewayResponse.authority}`;
|
|
||||||
return { paymentUrl };
|
return { paymentUrl };
|
||||||
}
|
}
|
||||||
|
|
||||||
private async requestToPaymentGateway(
|
async createPayment(domain: string, dto: CreatePaymentDto) {
|
||||||
gatewayPaymentUrl: string,
|
const { amount, orderId, merchantId, gateway, paymentMethod } = dto;
|
||||||
requestPayment: IPaymentRequest,
|
|
||||||
): Promise<IPaymentResponse> {
|
const { authority } = await this.requestToGateway(paymentMethod, amount, orderId, merchantId, domain, gateway);
|
||||||
|
|
||||||
|
const payment = this.em.create(Payment, {
|
||||||
|
amount,
|
||||||
|
authority: authority,
|
||||||
|
order: this.em.getReference(Order, orderId),
|
||||||
|
gateway,
|
||||||
|
status: PaymentStatusEnum.Pending,
|
||||||
|
} as RequiredEntityData<Payment>);
|
||||||
|
|
||||||
|
await this.em.persistAndFlush(payment);
|
||||||
|
return { authority, payment };
|
||||||
|
}
|
||||||
|
|
||||||
|
async requestToGateway(
|
||||||
|
paymentMethod: PaymentMethodEnum,
|
||||||
|
amount: number,
|
||||||
|
orderId: string,
|
||||||
|
merchantId: string | null | undefined,
|
||||||
|
domain: string,
|
||||||
|
gateway: PaymentGatewayEnum | null | undefined,
|
||||||
|
): Promise<{ authority: string | null }> {
|
||||||
|
if (paymentMethod === PaymentMethodEnum.Online && merchantId) {
|
||||||
|
const callbackUrl = `${domain}/payments/callback`;
|
||||||
|
if (gateway === PaymentGatewayEnum.ZarinPal) {
|
||||||
|
try {
|
||||||
|
const gatewayResponse = await this.requestToZarinPalGateway({
|
||||||
|
amount,
|
||||||
|
merchantId,
|
||||||
|
description: `Payment for order #${orderId}`,
|
||||||
|
callbackUrl,
|
||||||
|
metadata: {
|
||||||
|
orderId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// Check gateway response code (typically 100 means success for Iranian gateways)
|
||||||
|
if (gatewayResponse.code !== 100 && gatewayResponse.code !== 0) {
|
||||||
|
throw new BadRequestException(`Payment gateway error: ${gatewayResponse.message || 'Unknown error'}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gatewayResponse.authority) {
|
||||||
|
throw new BadRequestException('Payment gateway did not return an authority token');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||||
|
throw new BadRequestException(`Failed to connect to payment gateway: ${errorMessage}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { authority: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
private async requestToZarinPalGateway(requestPayment: IPaymentRequest): Promise<IPaymentResponse> {
|
||||||
|
const gatewayPaymentUrl = 'https://payment.zarinpal.com/pg/v4/payment/request.json';
|
||||||
const response = await axios.post<IPaymentResponse>(gatewayPaymentUrl, requestPayment);
|
const response = await axios.post<IPaymentResponse>(gatewayPaymentUrl, requestPayment);
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zarinpalPaymentUrl(gateway: PaymentGatewayEnum | null, authority: string | null) {
|
||||||
|
if (gateway === PaymentGatewayEnum.ZarinPal) {
|
||||||
|
return `https://payment.zarinpal.com/pg/StartPay/${authority}`;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
update(_id: number, _updatePaymentDto: unknown) {
|
update(_id: number, _updatePaymentDto: unknown) {
|
||||||
return `This action updates a #${_id} payment`;
|
return `This action updates a #${_id} payment`;
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
|
|
||||||
import { EntityManager } from '@mikro-orm/postgresql';
|
|
||||||
import { RestaurantPaymentMethod } from '../entities/restaurant-payment-method.entity';
|
|
||||||
import { RestaurantPaymentMethodRepository } from '../repositories/restaurant-payment-method.repository';
|
|
||||||
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
|
||||||
import { PaymentMethod } from '../entities/payment-method.entity';
|
|
||||||
import { CreateRestaurantPaymentMethodDto } from '../dto/create-restaurant-payment-method.dto';
|
|
||||||
import { UpdateRestaurantPaymentMethodDto } from '../dto/update-restaurant-payment-method.dto';
|
|
||||||
import { RequiredEntityData } from '@mikro-orm/core';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class RestaurantPaymentMethodService {
|
|
||||||
constructor(
|
|
||||||
private readonly restaurantPaymentMethodRepository: RestaurantPaymentMethodRepository,
|
|
||||||
private readonly em: EntityManager,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async create(
|
|
||||||
restId: string,
|
|
||||||
createRestaurantPaymentMethodDto: CreateRestaurantPaymentMethodDto,
|
|
||||||
): Promise<RestaurantPaymentMethod> {
|
|
||||||
// Check if restaurant exists
|
|
||||||
const restaurant = await this.em.findOne(Restaurant, { id: restId });
|
|
||||||
if (!restaurant) {
|
|
||||||
throw new NotFoundException(`Restaurant with ID ${restId} not found`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if payment method exists
|
|
||||||
const paymentMethod = await this.em.findOne(PaymentMethod, {
|
|
||||||
id: createRestaurantPaymentMethodDto.paymentMethodId,
|
|
||||||
});
|
|
||||||
if (!paymentMethod) {
|
|
||||||
throw new NotFoundException(
|
|
||||||
`PaymentMethod with ID ${createRestaurantPaymentMethodDto.paymentMethodId} not found`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the relationship already exists
|
|
||||||
const existing = await this.restaurantPaymentMethodRepository.findOne({
|
|
||||||
restaurant: { id: restId },
|
|
||||||
paymentMethod: { id: createRestaurantPaymentMethodDto.paymentMethodId },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (existing) {
|
|
||||||
throw new ConflictException('This payment method is already assigned to this restaurant');
|
|
||||||
}
|
|
||||||
|
|
||||||
const restaurantPaymentMethod = this.restaurantPaymentMethodRepository.create({
|
|
||||||
restaurant,
|
|
||||||
paymentMethod,
|
|
||||||
merchantId: createRestaurantPaymentMethodDto.merchantId,
|
|
||||||
isActive: createRestaurantPaymentMethodDto.isActive ?? true,
|
|
||||||
} as unknown as RequiredEntityData<RestaurantPaymentMethod>);
|
|
||||||
|
|
||||||
await this.em.persistAndFlush(restaurantPaymentMethod);
|
|
||||||
return restaurantPaymentMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
async findAll(): Promise<RestaurantPaymentMethod[]> {
|
|
||||||
return this.restaurantPaymentMethodRepository.findAll({ populate: ['restaurant', 'paymentMethod'] });
|
|
||||||
}
|
|
||||||
|
|
||||||
async findByRestaurant(restaurantId: string): Promise<RestaurantPaymentMethod[]> {
|
|
||||||
return this.restaurantPaymentMethodRepository.find(
|
|
||||||
{ restaurant: { id: restaurantId } },
|
|
||||||
{ populate: ['restaurant', 'paymentMethod'] },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async findByPaymentMethod(restPaymentMethodId: string): Promise<RestaurantPaymentMethod | null> {
|
|
||||||
return this.restaurantPaymentMethodRepository.findOneOrFail(
|
|
||||||
{ id: restPaymentMethodId },
|
|
||||||
{ populate: ['restaurant', 'paymentMethod'] },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async findOne(id: string): Promise<RestaurantPaymentMethod> {
|
|
||||||
const restaurantPaymentMethod = await this.restaurantPaymentMethodRepository.findOne(
|
|
||||||
{ id },
|
|
||||||
{ populate: ['restaurant', 'paymentMethod'] },
|
|
||||||
);
|
|
||||||
if (!restaurantPaymentMethod) {
|
|
||||||
throw new NotFoundException(`RestaurantPaymentMethod with ID ${id} not found`);
|
|
||||||
}
|
|
||||||
return restaurantPaymentMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
async update(
|
|
||||||
id: string,
|
|
||||||
updateRestaurantPaymentMethodDto: UpdateRestaurantPaymentMethodDto,
|
|
||||||
): Promise<RestaurantPaymentMethod> {
|
|
||||||
const restaurantPaymentMethod = await this.findOne(id);
|
|
||||||
|
|
||||||
if (updateRestaurantPaymentMethodDto.paymentMethodId) {
|
|
||||||
const paymentMethod = await this.em.findOne(PaymentMethod, {
|
|
||||||
id: updateRestaurantPaymentMethodDto.paymentMethodId,
|
|
||||||
});
|
|
||||||
if (!paymentMethod) {
|
|
||||||
throw new NotFoundException(
|
|
||||||
`PaymentMethod with ID ${updateRestaurantPaymentMethodDto.paymentMethodId} not found`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the new relationship already exists
|
|
||||||
const existing = await this.restaurantPaymentMethodRepository.findOne({
|
|
||||||
restaurant: { id: restaurantPaymentMethod.restaurant.id },
|
|
||||||
paymentMethod: { id: updateRestaurantPaymentMethodDto.paymentMethodId },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (existing && existing.id !== id) {
|
|
||||||
throw new ConflictException('This payment method is already assigned to this restaurant');
|
|
||||||
}
|
|
||||||
|
|
||||||
restaurantPaymentMethod.paymentMethod = paymentMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update merchantId and isActive if provided
|
|
||||||
if (updateRestaurantPaymentMethodDto.merchantId !== undefined) {
|
|
||||||
restaurantPaymentMethod.merchantId = updateRestaurantPaymentMethodDto.merchantId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updateRestaurantPaymentMethodDto.isActive !== undefined) {
|
|
||||||
restaurantPaymentMethod.isActive = updateRestaurantPaymentMethodDto.isActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.em.flush();
|
|
||||||
return restaurantPaymentMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
async remove(id: string): Promise<RestaurantPaymentMethod> {
|
|
||||||
const restaurantPaymentMethod = await this.findOne(id);
|
|
||||||
await this.em.removeAndFlush(restaurantPaymentMethod);
|
|
||||||
return restaurantPaymentMethod;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -77,6 +77,9 @@ export class Restaurant extends BaseEntity {
|
|||||||
@Property({ type: 'decimal', default: 0 })
|
@Property({ type: 'decimal', default: 0 })
|
||||||
vat?: number = 0;
|
vat?: number = 0;
|
||||||
|
|
||||||
|
@Property()
|
||||||
|
domain!: string;
|
||||||
|
|
||||||
// --- روشهای ارسال ---
|
// --- روشهای ارسال ---
|
||||||
@OneToMany(() => Delivery, delivery => delivery.restaurant)
|
@OneToMany(() => Delivery, delivery => delivery.restaurant)
|
||||||
deliveries = new Collection<Delivery>(this);
|
deliveries = new Collection<Delivery>(this);
|
||||||
|
|||||||
Reference in New Issue
Block a user