This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
import { Migration } from '@mikro-orm/migrations';
|
||||
|
||||
export class Migration20260615140000_add_card_owner_to_payment_methods extends Migration {
|
||||
|
||||
override async up(): Promise<void> {
|
||||
this.addSql(`alter table "payment_methods" add column "card_owner" varchar(255) null;`);
|
||||
}
|
||||
|
||||
override async down(): Promise<void> {
|
||||
this.addSql(`alter table "payment_methods" drop column "card_owner";`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -745,6 +745,7 @@ export const enum PaymentMessage {
|
||||
PAYMENT_METHOD_NOT_CASH = 'روش پرداخت نقدی نیست',
|
||||
PAYMENT_METHOD_NOT_CREDIT_CARD = 'روش پرداخت کارت به کارت نیست',
|
||||
CARD_NUMBER_REQUIRED = 'شماره کارت برای پرداخت کارت به کارت الزامی است',
|
||||
CARD_OWNER_REQUIRED = 'نام صاحب کارت برای پرداخت کارت به کارت الزامی است',
|
||||
PAYMENT_ALREADY_PAID = 'پرداخت قبلا انجام شده است',
|
||||
EXISTING_PENDING_PAYMENT_MISMATCH = 'پرداخت در انتظار موجود با روش پرداخت سفارش مطابقت ندارد',
|
||||
ZARINPAL_INVALID_RESPONSE = 'پاسخ نامعتبر از API زرینپال',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IsString, IsOptional, IsBoolean, IsNumber, IsEnum } from 'class-validator';
|
||||
import { IsString, IsOptional, IsBoolean, IsNumber, IsEnum, ValidateIf, IsNotEmpty } from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { PaymentMethodEnum, PaymentGatewayEnum } from '../interface/payment';
|
||||
|
||||
@@ -23,6 +23,12 @@ export class CreatePaymentMethodDto {
|
||||
@IsString()
|
||||
cardNumber?: string;
|
||||
|
||||
@ApiProperty({ description: 'Card owner name for card-to-card payments', required: false })
|
||||
@ValidateIf((dto: CreatePaymentMethodDto) => dto.method === PaymentMethodEnum.CreditCard)
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
cardOwner?: string;
|
||||
|
||||
@ApiProperty({ description: 'Is payment method enabled', required: false, default: true })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
|
||||
@@ -23,6 +23,9 @@ export class PaymentMethod extends BaseEntity {
|
||||
@Property({ nullable: true })
|
||||
cardNumber?: string;
|
||||
|
||||
@Property({ nullable: true })
|
||||
cardOwner?: string;
|
||||
|
||||
@Property({ default: true })
|
||||
enabled: boolean = true;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
|
||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { PaymentMethod } from '../entities/payment-method.entity';
|
||||
import { PaymentMethodRepository } from '../repositories/payment-method.repository';
|
||||
@@ -7,6 +7,7 @@ import { UpdatePaymentMethodDto } from '../dto/update-payment-method.dto';
|
||||
import { RequiredEntityData } from '@mikro-orm/core';
|
||||
import { PaymentMessage } from 'src/common/enums/message.enum';
|
||||
import { RestaurantsService } from 'src/modules/restaurants/providers/restaurants.service';
|
||||
import { PaymentMethodEnum } from '../interface/payment';
|
||||
|
||||
@Injectable()
|
||||
export class PaymentMethodService {
|
||||
@@ -18,7 +19,8 @@ export class PaymentMethodService {
|
||||
|
||||
async create(restId: string, createPaymentMethodDto: CreatePaymentMethodDto): Promise<PaymentMethod> {
|
||||
// Check if restaurant exists
|
||||
const restaurant = await this.restaurantsService.findOneOrFail(restId)
|
||||
const restaurant = await this.restaurantsService.findOneOrFail(restId);
|
||||
this.assertCreditCardOwner(createPaymentMethodDto.method, createPaymentMethodDto.cardOwner);
|
||||
|
||||
const paymentMethod = this.paymentMethodRepository.create({
|
||||
restaurant,
|
||||
@@ -43,10 +45,17 @@ export class PaymentMethodService {
|
||||
async update(id: string, updatePaymentMethodDto: UpdatePaymentMethodDto): Promise<PaymentMethod> {
|
||||
const paymentMethod = await this.findOneOrFail(id);
|
||||
this.em.assign(paymentMethod, updatePaymentMethodDto);
|
||||
this.assertCreditCardOwner(paymentMethod.method, paymentMethod.cardOwner);
|
||||
await this.em.flush();
|
||||
return paymentMethod;
|
||||
}
|
||||
|
||||
private assertCreditCardOwner(method: PaymentMethodEnum, cardOwner?: string): void {
|
||||
if (method === PaymentMethodEnum.CreditCard && !cardOwner?.trim()) {
|
||||
throw new BadRequestException(PaymentMessage.CARD_OWNER_REQUIRED);
|
||||
}
|
||||
}
|
||||
|
||||
async remove(id: string): Promise<PaymentMethod> {
|
||||
const paymentMethod = await this.findOneOrFail(id);
|
||||
await this.em.removeAndFlush(paymentMethod);
|
||||
|
||||
@@ -83,6 +83,10 @@ export class PaymentsService {
|
||||
throw new BadRequestException(PaymentMessage.CARD_NUMBER_REQUIRED);
|
||||
}
|
||||
|
||||
if (pm.method === PaymentMethodEnum.CreditCard && !pm.cardOwner?.trim()) {
|
||||
throw new BadRequestException(PaymentMessage.CARD_OWNER_REQUIRED);
|
||||
}
|
||||
|
||||
return {
|
||||
order,
|
||||
amount: order.total,
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface PaymentMethodData {
|
||||
order: number;
|
||||
gateway: PaymentGatewayEnum | null;
|
||||
cardNumber?: string;
|
||||
cardOwner?: string;
|
||||
merchantId?: string;
|
||||
}
|
||||
|
||||
@@ -40,5 +41,6 @@ export const paymentMethodsData: PaymentMethodData[] = [
|
||||
order: 4,
|
||||
gateway: null,
|
||||
cardNumber: '6037991234567890',
|
||||
cardOwner: 'صاحب کارت',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -23,6 +23,7 @@ export class PaymentMethodsSeeder {
|
||||
order: methodData.order,
|
||||
gateway: methodData.gateway,
|
||||
cardNumber: methodData.cardNumber,
|
||||
cardOwner: methodData.cardOwner,
|
||||
merchantId: methodData.merchantId,
|
||||
});
|
||||
em.persist(paymentMethod);
|
||||
@@ -32,7 +33,8 @@ export class PaymentMethodsSeeder {
|
||||
existing.description !== methodData.description ||
|
||||
existing.enabled !== methodData.enabled ||
|
||||
existing.order !== methodData.order ||
|
||||
existing.cardNumber !== methodData.cardNumber
|
||||
existing.cardNumber !== methodData.cardNumber ||
|
||||
existing.cardOwner !== methodData.cardOwner
|
||||
) {
|
||||
existing.description = methodData.description;
|
||||
existing.enabled = methodData.enabled;
|
||||
@@ -43,6 +45,9 @@ export class PaymentMethodsSeeder {
|
||||
if (methodData.cardNumber !== undefined) {
|
||||
existing.cardNumber = methodData.cardNumber;
|
||||
}
|
||||
if (methodData.cardOwner !== undefined) {
|
||||
existing.cardOwner = methodData.cardOwner;
|
||||
}
|
||||
if (methodData.merchantId !== undefined) {
|
||||
existing.merchantId = methodData.merchantId;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user