update payment
This commit is contained in:
@@ -12,15 +12,17 @@ import { OrderStatus } from './interface/order-status';
|
|||||||
import { PaymentStatus } from '../payments/interface/payment-status';
|
import { PaymentStatus } from '../payments/interface/payment-status';
|
||||||
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';
|
// import { PaymentGatewayService } from '../payments/services/payment-gateway.service.tss';
|
||||||
|
import { PaymentsService } from '../payments/services/payments.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OrdersService {
|
export class OrdersService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly em: EntityManager,
|
private readonly em: EntityManager,
|
||||||
private readonly cartService: CartService,
|
private readonly cartService: CartService,
|
||||||
|
private readonly paymentsService: PaymentsService,
|
||||||
private readonly RestaurantPaymentMethodRepository: RestaurantPaymentMethodRepository,
|
private readonly RestaurantPaymentMethodRepository: RestaurantPaymentMethodRepository,
|
||||||
private readonly paymentGatewayService: PaymentGatewayService,
|
// private readonly paymentGatewayService: PaymentGatewayService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async create(userId: string, restaurantId: string) {
|
async create(userId: string, restaurantId: string) {
|
||||||
@@ -76,24 +78,25 @@ export class OrdersService {
|
|||||||
|
|
||||||
// Flush all changes
|
// Flush all changes
|
||||||
await em.flush();
|
await em.flush();
|
||||||
|
let paymentUrl: string | null = null;
|
||||||
// Check if payment method is online and redirect to payment gateway
|
// Check if payment method is online and redirect to payment gateway
|
||||||
if (validationResult.paymentMethod.paymentMethod.isOnline) {
|
if (validationResult.paymentMethod.paymentMethod.isOnline) {
|
||||||
const paymentRedirect = this.paymentGatewayService.generateRedirectUrl(order, validationResult.paymentMethod);
|
const result = await this.paymentsService.initializePayment(
|
||||||
|
validationResult.paymentMethod.id,
|
||||||
|
order.total,
|
||||||
|
order.id,
|
||||||
|
);
|
||||||
// await this.cartService.clearCart(userId, restaurantId);
|
// await this.cartService.clearCart(userId, restaurantId);
|
||||||
|
|
||||||
// Return order with redirect URL for online payment
|
// Return order with redirect URL for online payment
|
||||||
return {
|
paymentUrl = result.paymentUrl;
|
||||||
order,
|
|
||||||
redirectUrl: paymentRedirect.redirectUrl,
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
// await this.cartService.clearCart(userId, restaurantId);
|
// await this.cartService.clearCart(userId, restaurantId);
|
||||||
// For offline payment methods (cash on delivery, etc.), order is created and pending
|
// For offline payment methods (cash on delivery, etc.), order is created and pending
|
||||||
// Payment status will be updated when payment is confirmed
|
// Payment status will be updated when payment is confirmed
|
||||||
// TODO: Implement offline payment confirmation flow if needed
|
// TODO: Implement offline payment confirmation flow if needed
|
||||||
}
|
}
|
||||||
return { order };
|
return { order, paymentUrl };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,15 +38,15 @@ export class PaymentsController {
|
|||||||
return this.restaurantPaymentMethodService.findByRestaurant(restId);
|
return this.restaurantPaymentMethodService.findByRestaurant(restId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
// @UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
// @ApiBearerAuth()
|
||||||
@Post('admin/payments')
|
// @Post('admin/payments')
|
||||||
@ApiOperation({ summary: 'Create a new payment' })
|
// @ApiOperation({ summary: 'Create a new payment' })
|
||||||
@ApiBody({ type: CreatePaymentDto })
|
// @ApiBody({ type: CreatePaymentDto })
|
||||||
@ApiCreatedResponse({ description: 'Payment created successfully' })
|
// @ApiCreatedResponse({ description: 'Payment created successfully' })
|
||||||
createPayment(@Body() createPaymentDto: CreatePaymentDto) {
|
// createPayment(@Body() createPaymentDto: CreatePaymentDto) {
|
||||||
return this.paymentsService.create(createPaymentDto);
|
// return this.paymentsService.create(createPaymentDto);
|
||||||
}
|
// }
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@@ -56,16 +56,16 @@ export class PaymentsController {
|
|||||||
findAllPayments() {
|
findAllPayments() {
|
||||||
return this.paymentsService.findAll();
|
return this.paymentsService.findAll();
|
||||||
}
|
}
|
||||||
@UseGuards(AdminAuthGuard)
|
// @UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
// @ApiBearerAuth()
|
||||||
@Get('admin/payments/:id')
|
// @Get('admin/payments/:id')
|
||||||
@ApiOperation({ summary: 'Get a payment by ID' })
|
// @ApiOperation({ summary: 'Get a payment by ID' })
|
||||||
@ApiParam({ name: 'id', type: 'number', description: 'Payment ID' })
|
// @ApiParam({ name: 'id', type: 'number', description: 'Payment ID' })
|
||||||
@ApiOkResponse({ description: 'Payment found' })
|
// @ApiOkResponse({ description: 'Payment found' })
|
||||||
@ApiNotFoundResponse({ description: 'Payment not found' })
|
// @ApiNotFoundResponse({ description: 'Payment not found' })
|
||||||
findOnePayment(@Param('id') id: string) {
|
// findOnePayment(@Param('id') id: string) {
|
||||||
return this.paymentsService.findOne(+id);
|
// return this.paymentsService.findById(+id);
|
||||||
}
|
// }
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@Patch('admin/payments/:id')
|
@Patch('admin/payments/:id')
|
||||||
|
|||||||
@@ -38,5 +38,5 @@ export class CreatePaymentMethodDto {
|
|||||||
@ApiProperty({ description: 'Callback URL for payment method', required: false })
|
@ApiProperty({ description: 'Callback URL for payment method', required: false })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
callbackUrl?: string;
|
paymentUrl?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
import { IsNumber } from 'class-validator';
|
import { IsNumber, IsString } from 'class-validator';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
export class CreatePaymentDto {
|
export class CreatePaymentDto {
|
||||||
@ApiProperty({ description: 'Example field (placeholder)' })
|
@ApiProperty({ description: 'Payment amount' })
|
||||||
@IsNumber()
|
@IsNumber()
|
||||||
exampleField: number;
|
amount: number;
|
||||||
}
|
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Payment authority' })
|
||||||
|
@IsString()
|
||||||
|
restaurantPaymentId: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Payment gateway' })
|
||||||
|
@IsString()
|
||||||
|
gateway: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export class PaymentMethod extends BaseEntity {
|
|||||||
@Property({ type: 'int', nullable: true })
|
@Property({ type: 'int', nullable: true })
|
||||||
order?: number;
|
order?: number;
|
||||||
|
|
||||||
|
|
||||||
@Property({ nullable: true })
|
@Property({ nullable: true })
|
||||||
callbackUrl?: string;
|
paymentUrl?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,37 @@
|
|||||||
export class Payment {
|
import { Entity, ManyToOne, Property, Enum } from '@mikro-orm/core';
|
||||||
exampleField: number;
|
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||||
|
import { Order } from '../../orders/entities/order.entity';
|
||||||
|
import { PaymentStatus } from '../interface/payment-status';
|
||||||
|
|
||||||
|
@Entity({ tableName: 'payments' })
|
||||||
|
export class Payment extends BaseEntity {
|
||||||
|
@ManyToOne(() => Order)
|
||||||
|
order!: Order;
|
||||||
|
|
||||||
|
@Property({ type: 'decimal', precision: 10, scale: 0 })
|
||||||
|
amount!: number;
|
||||||
|
|
||||||
|
@Property({ unique: true })
|
||||||
|
authority!: string;
|
||||||
|
|
||||||
|
@Property()
|
||||||
|
gateway!: string;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
refId?: string;
|
||||||
|
|
||||||
|
@Enum(() => PaymentStatus)
|
||||||
|
status!: PaymentStatus;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
cardPan?: string;
|
||||||
|
|
||||||
|
@Property({ type: 'json' })
|
||||||
|
verifyResponse?: Record<string, any>;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
paidAt: Date;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
failedAt: Date;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ export class RestaurantPaymentMethod extends BaseEntity {
|
|||||||
@Property({ nullable: true })
|
@Property({ nullable: true })
|
||||||
merchantId?: string;
|
merchantId?: string;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
callbackUrl?: string;
|
||||||
|
|
||||||
@Property({ type: 'boolean', default: true })
|
@Property({ type: 'boolean', default: true })
|
||||||
isActive: boolean = true;
|
isActive: boolean = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,3 +4,17 @@ export enum PaymentStatus {
|
|||||||
Failed = 'failed',
|
Failed = 'failed',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IPaymentRequest {
|
||||||
|
amount: number;
|
||||||
|
callbackUrl: string;
|
||||||
|
merchantId: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPaymentResponse {
|
||||||
|
code: number;
|
||||||
|
message: string;
|
||||||
|
authority: string;
|
||||||
|
fee_type: string;
|
||||||
|
fee: number;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { PaymentMethodService } from './services/payment-method.service';
|
|||||||
import { RestaurantPaymentMethod } from './entities/restaurant-payment-method.entity';
|
import { RestaurantPaymentMethod } from './entities/restaurant-payment-method.entity';
|
||||||
import { RestaurantPaymentMethodRepository } from './repositories/restaurant-payment-method.repository';
|
import { RestaurantPaymentMethodRepository } from './repositories/restaurant-payment-method.repository';
|
||||||
import { RestaurantPaymentMethodService } from './services/restaurant-payment-method.service';
|
import { RestaurantPaymentMethodService } from './services/restaurant-payment-method.service';
|
||||||
import { PaymentGatewayService } from './services/payment-gateway.service';
|
// 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';
|
||||||
import { AuthModule } from '../auth/auth.module';
|
import { AuthModule } from '../auth/auth.module';
|
||||||
@@ -22,7 +22,7 @@ import { JwtModule } from '@nestjs/jwt';
|
|||||||
PaymentMethodRepository,
|
PaymentMethodRepository,
|
||||||
RestaurantPaymentMethodService,
|
RestaurantPaymentMethodService,
|
||||||
RestaurantPaymentMethodRepository,
|
RestaurantPaymentMethodRepository,
|
||||||
PaymentGatewayService,
|
// PaymentGatewayService,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
PaymentMethodRepository,
|
PaymentMethodRepository,
|
||||||
@@ -30,7 +30,7 @@ import { JwtModule } from '@nestjs/jwt';
|
|||||||
RestaurantPaymentMethodRepository,
|
RestaurantPaymentMethodRepository,
|
||||||
RestaurantPaymentMethodService,
|
RestaurantPaymentMethodService,
|
||||||
PaymentsService,
|
PaymentsService,
|
||||||
PaymentGatewayService,
|
// PaymentGatewayService,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PaymentsModule {}
|
export class PaymentsModule {}
|
||||||
|
|||||||
@@ -1,23 +1,111 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||||
import { CreatePaymentDto } from '../dto/create-payment.dto';
|
import { RestaurantPaymentMethod } from '../entities/restaurant-payment-method.entity';
|
||||||
import { UpdatePaymentDto } from '../dto/update-payment.dto';
|
import axios from 'axios';
|
||||||
|
import { IPaymentRequest, IPaymentResponse, PaymentStatus } from '../interface/payment-status';
|
||||||
|
import { Payment } from '../entities/payment.entity';
|
||||||
|
import { EntityManager, RequiredEntityData } from '@mikro-orm/core';
|
||||||
|
import { Order } from '../../orders/entities/order.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PaymentsService {
|
export class PaymentsService {
|
||||||
create(createPaymentDto: CreatePaymentDto) {
|
constructor(private readonly em: EntityManager) {}
|
||||||
return 'This action adds a new payment';
|
|
||||||
|
async initializePayment(
|
||||||
|
restaurantPaymentMethodId: string,
|
||||||
|
amount: number,
|
||||||
|
orderId: string,
|
||||||
|
): Promise<{ paymentUrl: string }> {
|
||||||
|
// Validate amount
|
||||||
|
if (amount <= 0) {
|
||||||
|
throw new BadRequestException('Amount must be greater than zero');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate order exists
|
||||||
|
const order = await this.em.findOne(Order, { id: orderId });
|
||||||
|
if (!order) {
|
||||||
|
throw new NotFoundException('Order not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load restaurant payment method with payment method relationship
|
||||||
|
const restaurantPaymentMethod = await this.em.findOne(
|
||||||
|
RestaurantPaymentMethod,
|
||||||
|
{ id: restaurantPaymentMethodId },
|
||||||
|
{ populate: ['paymentMethod'] },
|
||||||
|
);
|
||||||
|
if (!restaurantPaymentMethod) {
|
||||||
|
throw new NotFoundException('Restaurant payment method not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!restaurantPaymentMethod.paymentMethod?.isOnline) {
|
||||||
|
throw new BadRequestException('Payment method is not online');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!restaurantPaymentMethod.callbackUrl) {
|
||||||
|
throw new BadRequestException('Callback URL is not configured');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!restaurantPaymentMethod.merchantId) {
|
||||||
|
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
|
||||||
|
const payment = this.em.create(Payment, {
|
||||||
|
amount,
|
||||||
|
authority: gatewayResponse.authority,
|
||||||
|
order: this.em.getReference(Order, orderId),
|
||||||
|
gateway: restaurantPaymentMethod.paymentMethod.name,
|
||||||
|
status: PaymentStatus.Pending,
|
||||||
|
} as RequiredEntityData<Payment>);
|
||||||
|
|
||||||
|
await this.em.persistAndFlush(payment);
|
||||||
|
|
||||||
|
// Return payment URL
|
||||||
|
const paymentUrl = `${restaurantPaymentMethod.paymentMethod.paymentUrl}/${gatewayResponse.authority}`;
|
||||||
|
return { paymentUrl };
|
||||||
|
}
|
||||||
|
|
||||||
|
private async requestToPaymentGateway(
|
||||||
|
gatewayPaymentUrl: string,
|
||||||
|
requestPayment: IPaymentRequest,
|
||||||
|
): Promise<IPaymentResponse> {
|
||||||
|
const response = await axios.post<IPaymentResponse>(gatewayPaymentUrl, requestPayment);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
update(_id: number, _updatePaymentDto: unknown) {
|
||||||
|
return `This action updates a #${_id} payment`;
|
||||||
}
|
}
|
||||||
|
|
||||||
findAll() {
|
findAll() {
|
||||||
return `This action returns all payments`;
|
return this.em.find(Payment, {});
|
||||||
}
|
|
||||||
|
|
||||||
findOne(id: number) {
|
|
||||||
return `This action returns a #${id} payment`;
|
|
||||||
}
|
|
||||||
|
|
||||||
update(id: number, updatePaymentDto: UpdatePaymentDto) {
|
|
||||||
return `This action updates a #${id} payment`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(id: number) {
|
remove(id: number) {
|
||||||
|
|||||||
@@ -94,18 +94,57 @@ export class DatabaseSeeder extends Seeder {
|
|||||||
const superAdmin = await em.findOne(Role, { name: 'superAdmin' });
|
const superAdmin = await em.findOne(Role, { name: 'superAdmin' });
|
||||||
|
|
||||||
// 3. Create Payment Methods
|
// 3. Create Payment Methods
|
||||||
const zarinpalPaymentMethod = await em.findOne(PaymentMethod, { keyName: 'zarinpal' });
|
const paymentMethodsData = [
|
||||||
if (!zarinpalPaymentMethod) {
|
{
|
||||||
const paymentMethod = em.create(PaymentMethod, {
|
name: 'پرداخت در محل',
|
||||||
|
keyName: 'payment-on-delivery',
|
||||||
|
description: 'پرداخت در محل تحویل',
|
||||||
|
isActive: true,
|
||||||
|
order: 1,
|
||||||
|
isOnline: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'نقدی',
|
||||||
|
keyName: 'cash',
|
||||||
|
description: 'پرداخت نقدی',
|
||||||
|
isActive: true,
|
||||||
|
order: 2,
|
||||||
|
isOnline: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
name: 'زرینپال',
|
name: 'زرینپال',
|
||||||
keyName: 'zarinpal',
|
keyName: 'zarinpal',
|
||||||
description: 'درگاه پرداخت زرینپال',
|
description: 'درگاه پرداخت زرینپال',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
order: 1,
|
order: 3,
|
||||||
isOnline: true,
|
isOnline: true,
|
||||||
callbackUrl: 'https://www.zarinpal.com/pg/StartPay',
|
paymentUrl: 'https://www.zarinpal.com/pg/StartPay',
|
||||||
});
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const methodData of paymentMethodsData) {
|
||||||
|
let paymentMethod = await em.findOne(PaymentMethod, { keyName: methodData.keyName });
|
||||||
|
if (!paymentMethod) {
|
||||||
|
paymentMethod = em.create(PaymentMethod, methodData);
|
||||||
em.persist(paymentMethod);
|
em.persist(paymentMethod);
|
||||||
|
} else {
|
||||||
|
// Update existing payment method if needed
|
||||||
|
if (
|
||||||
|
paymentMethod.name !== methodData.name ||
|
||||||
|
paymentMethod.description !== methodData.description ||
|
||||||
|
paymentMethod.isOnline !== methodData.isOnline ||
|
||||||
|
paymentMethod.order !== methodData.order
|
||||||
|
) {
|
||||||
|
paymentMethod.name = methodData.name;
|
||||||
|
paymentMethod.description = methodData.description;
|
||||||
|
paymentMethod.isOnline = methodData.isOnline;
|
||||||
|
paymentMethod.order = methodData.order;
|
||||||
|
if (methodData.paymentUrl) {
|
||||||
|
paymentMethod.paymentUrl = methodData.paymentUrl;
|
||||||
|
}
|
||||||
|
em.persist(paymentMethod);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await em.flush();
|
await em.flush();
|
||||||
@@ -211,7 +250,7 @@ export class DatabaseSeeder extends Seeder {
|
|||||||
const boote = await em.findOne(Restaurant, { slug: 'boote' });
|
const boote = await em.findOne(Restaurant, { slug: 'boote' });
|
||||||
|
|
||||||
// 5.5. Create Restaurant Payment Methods
|
// 5.5. Create Restaurant Payment Methods
|
||||||
const allRestaurants = [zhivan, boote].filter(Boolean) as Restaurant[];
|
const allRestaurants = await em.find(Restaurant, {});
|
||||||
const allPaymentMethods = await em.find(PaymentMethod, { isActive: true });
|
const allPaymentMethods = await em.find(PaymentMethod, { isActive: true });
|
||||||
|
|
||||||
for (const restaurant of allRestaurants) {
|
for (const restaurant of allRestaurants) {
|
||||||
|
|||||||
Reference in New Issue
Block a user