chore: complete payment system
This commit is contained in:
@@ -75,6 +75,7 @@ export const enum CommonMessage {
|
|||||||
DELETED = "با موفقیت حذف شد",
|
DELETED = "با موفقیت حذف شد",
|
||||||
ID_REQUIRED = "شناسه مورد نیاز است",
|
ID_REQUIRED = "شناسه مورد نیاز است",
|
||||||
ID_SHOULD_BE_UUID = "شناسه باید یک یو یو آی دی باشد",
|
ID_SHOULD_BE_UUID = "شناسه باید یک یو یو آی دی باشد",
|
||||||
|
PaymentTypeQueryNotEmpty = "نوع پرداخت نمیتواند خالی باشد",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum CategoryMessage {
|
export const enum CategoryMessage {
|
||||||
@@ -198,7 +199,7 @@ export const enum WalletMessage {
|
|||||||
DEPOSIT_WALLET_IPG = "شارژ کیف پول از طریق درگاه",
|
DEPOSIT_WALLET_IPG = "شارژ کیف پول از طریق درگاه",
|
||||||
TRANSFER_METHOD_REQUIRED = "روش انتفال اجباری است",
|
TRANSFER_METHOD_REQUIRED = "روش انتفال اجباری است",
|
||||||
GATEWAY_ID_SHOULD_BE_UUID = "آیدی درگاه پرداخت باید UUID باشد",
|
GATEWAY_ID_SHOULD_BE_UUID = "آیدی درگاه پرداخت باید UUID باشد",
|
||||||
// DEPOSIT_WITH_TRANSFER = "DEPOSIT_WITH_TRANSFER",
|
DEPOSIT_WALLET_TRANSFER = "شارژ کیف پول از طریق انتقال بانکی",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum PaymentMessage {
|
export const enum PaymentMessage {
|
||||||
@@ -225,6 +226,16 @@ export const enum PaymentMessage {
|
|||||||
BANK_ACCOUNT_NOT_FOUND = "حساب بانکی پیدا نشد",
|
BANK_ACCOUNT_NOT_FOUND = "حساب بانکی پیدا نشد",
|
||||||
DEPOSIT_CREATED = "درخواست واریز ثبت شد",
|
DEPOSIT_CREATED = "درخواست واریز ثبت شد",
|
||||||
VALIDATED_BEFORE = "این پرداخت قبلا تایید شده است",
|
VALIDATED_BEFORE = "این پرداخت قبلا تایید شده است",
|
||||||
|
DEPOSIT_NOT_FOUND = "درخواست واریز پیدا نشد",
|
||||||
|
PAYMENT_NOT_FOUND = "پرداخت پیدا نشد",
|
||||||
|
DEPOSIT_APPROVED = "درخواست واریز تایید شد",
|
||||||
|
DEPOSIT_REJECTED = "درخواست واریز رد شد",
|
||||||
|
REJECT_COMMENT_REQUIRED = "توضیحات رد درخواست واریز مورد نیاز است",
|
||||||
|
REJECT_COMMENT_STRING = "توضیحات رد درخواست واریز باید یک رشته باشد",
|
||||||
|
REJECT_COMMENT_LENGTH = "توضیحات رد درخواست واریز باید بین ۳ تا ۲۵۰ کاراکتر باشد",
|
||||||
|
TRANSFER_METHOD_NOT_ALLOWED = "روش انتقال انتخابی مجاز نیست",
|
||||||
|
DEPOSIT_ALREADY_APPROVED = "درخواست واریز قبلا تایید شده است",
|
||||||
|
DEPOSIT_ALREADY_REJECTED = "درخواسن واریز قبلا رد شده است",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum SettingMessageEnum {
|
export const enum SettingMessageEnum {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ApiProperty } from "@nestjs/swagger";
|
|||||||
import { IsEnum, IsInt, IsNotEmpty, IsUUID, IsUrl, Min } from "class-validator";
|
import { IsEnum, IsInt, IsNotEmpty, IsUUID, IsUrl, Min } from "class-validator";
|
||||||
|
|
||||||
import { WalletMessage } from "../../../common/enums/message.enum";
|
import { WalletMessage } from "../../../common/enums/message.enum";
|
||||||
import { TransferMethod } from "../enums/payment-type.enum";
|
import { TransferType } from "../enums/payment-type.enum";
|
||||||
|
|
||||||
export class DepositDto {
|
export class DepositDto {
|
||||||
@IsNotEmpty({ message: WalletMessage.AMOUNT_REQUIRED })
|
@IsNotEmpty({ message: WalletMessage.AMOUNT_REQUIRED })
|
||||||
@@ -36,7 +36,7 @@ export class TransferDepositDto extends DepositDto {
|
|||||||
bankAccountId: string;
|
bankAccountId: string;
|
||||||
|
|
||||||
@IsNotEmpty({ message: WalletMessage.TRANSFER_METHOD_REQUIRED })
|
@IsNotEmpty({ message: WalletMessage.TRANSFER_METHOD_REQUIRED })
|
||||||
@IsEnum(TransferMethod)
|
@IsEnum(TransferType)
|
||||||
@ApiProperty({ description: "transfer method", example: TransferMethod.CARD_TO_CARD, enum: TransferMethod })
|
@ApiProperty({ description: "transfer method", example: TransferType.CARD_TO_CARD, enum: TransferType })
|
||||||
method: TransferMethod;
|
method: TransferType;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
|
import { IsEnum, IsNotEmpty } from "class-validator";
|
||||||
|
|
||||||
|
import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
||||||
|
import { CommonMessage } from "../../../common/enums/message.enum";
|
||||||
|
import { TransferType } from "../enums/payment-type.enum";
|
||||||
|
|
||||||
|
export class PaymentTransactionQueryDto extends PaginationDto {
|
||||||
|
@IsNotEmpty({ message: CommonMessage.PaymentTypeQueryNotEmpty })
|
||||||
|
@IsEnum(TransferType)
|
||||||
|
@ApiProperty({
|
||||||
|
description: `payment type ${TransferType.CARD_TO_CARD} ${TransferType.SHEBA} `,
|
||||||
|
enum: TransferType,
|
||||||
|
example: TransferType.CARD_TO_CARD,
|
||||||
|
})
|
||||||
|
type: TransferType;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
|
import { IsNotEmpty, IsString, Length } from "class-validator";
|
||||||
|
|
||||||
|
import { PaymentMessage } from "../../../common/enums/message.enum";
|
||||||
|
|
||||||
|
export class RejectDepositRequestDto {
|
||||||
|
@IsNotEmpty({ message: PaymentMessage.REJECT_COMMENT_REQUIRED })
|
||||||
|
@IsString({ message: PaymentMessage.REJECT_COMMENT_STRING })
|
||||||
|
@Length(3, 250, { message: PaymentMessage.REJECT_COMMENT_LENGTH })
|
||||||
|
@ApiProperty({ description: "Comment for rejecting the deposit request", example: "The receipt is not clear" })
|
||||||
|
comment: string;
|
||||||
|
}
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
|
import Decimal from "decimal.js";
|
||||||
import { Column, Entity, ManyToOne } from "typeorm";
|
import { Column, Entity, ManyToOne } from "typeorm";
|
||||||
|
|
||||||
import { BankAccount } from "./bank-account.entity";
|
import { BankAccount } from "./bank-account.entity";
|
||||||
import { BaseEntity } from "../../../common/entities/base.entity";
|
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||||
|
import { DecimalTransformer } from "../../../common/transformers/decimal.transformer";
|
||||||
import { User } from "../../users/entities/user.entity";
|
import { User } from "../../users/entities/user.entity";
|
||||||
|
import { DepositRequestStatus } from "../enums/deposit-request-status.enum";
|
||||||
|
import { TransferType } from "../enums/payment-type.enum";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class DepositRequest extends BaseEntity {
|
export class DepositRequest extends BaseEntity {
|
||||||
@@ -14,4 +18,16 @@ export class DepositRequest extends BaseEntity {
|
|||||||
|
|
||||||
@Column({ type: "varchar", length: 250, nullable: false })
|
@Column({ type: "varchar", length: 250, nullable: false })
|
||||||
receiptUrl: string;
|
receiptUrl: string;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 250, nullable: true })
|
||||||
|
comment: string;
|
||||||
|
|
||||||
|
@Column({ type: "enum", enum: TransferType, nullable: false })
|
||||||
|
type: TransferType;
|
||||||
|
|
||||||
|
@Column({ type: "decimal", precision: 16, scale: 2, nullable: false, transformer: new DecimalTransformer() })
|
||||||
|
amount: Decimal;
|
||||||
|
|
||||||
|
@Column({ type: "enum", enum: DepositRequestStatus, default: DepositRequestStatus.PENDING })
|
||||||
|
status: DepositRequestStatus;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,11 @@
|
|||||||
import Decimal from "decimal.js";
|
import Decimal from "decimal.js";
|
||||||
import { Column, Entity, ManyToOne } from "typeorm";
|
import { Column, Entity, ManyToOne } from "typeorm";
|
||||||
|
|
||||||
import { BankAccount } from "./bank-account.entity";
|
|
||||||
import { PaymentGateway } from "./payment-gateway.entity";
|
import { PaymentGateway } from "./payment-gateway.entity";
|
||||||
import { BaseEntity } from "../../../common/entities/base.entity";
|
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||||
import { DecimalTransformer } from "../../../common/transformers/decimal.transformer";
|
import { DecimalTransformer } from "../../../common/transformers/decimal.transformer";
|
||||||
import { User } from "../../users/entities/user.entity";
|
import { User } from "../../users/entities/user.entity";
|
||||||
import { PaymentStatus } from "../enums/payment-status.enum";
|
import { PaymentStatus } from "../enums/payment-status.enum";
|
||||||
import { PaymentType } from "../enums/payment-type.enum";
|
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Payment extends BaseEntity {
|
export class Payment extends BaseEntity {
|
||||||
@@ -24,15 +22,9 @@ export class Payment extends BaseEntity {
|
|||||||
@Column({ type: "enum", enum: PaymentStatus, default: PaymentStatus.PENDING })
|
@Column({ type: "enum", enum: PaymentStatus, default: PaymentStatus.PENDING })
|
||||||
status: PaymentStatus;
|
status: PaymentStatus;
|
||||||
|
|
||||||
@Column({ type: "enum", enum: PaymentType, nullable: false })
|
|
||||||
type: PaymentType;
|
|
||||||
|
|
||||||
@ManyToOne(() => User, (user) => user.payments, { nullable: false, onDelete: "RESTRICT" })
|
@ManyToOne(() => User, (user) => user.payments, { nullable: false, onDelete: "RESTRICT" })
|
||||||
user: User;
|
user: User;
|
||||||
|
|
||||||
@ManyToOne(() => PaymentGateway, { nullable: true, onDelete: "SET NULL" })
|
@ManyToOne(() => PaymentGateway, { nullable: false, onDelete: "RESTRICT" })
|
||||||
paymentGateway?: PaymentGateway;
|
paymentGateway: PaymentGateway;
|
||||||
|
|
||||||
@ManyToOne(() => BankAccount, { nullable: true, onDelete: "SET NULL" })
|
|
||||||
bankAccount?: BankAccount; // for CARD_TO_CARD or SHEBA transfers
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export enum DepositRequestStatus {
|
||||||
|
PENDING = "PENDING",
|
||||||
|
APPROVED = "APPROVED",
|
||||||
|
REJECTED = "REJECTED",
|
||||||
|
}
|
||||||
@@ -1,10 +1,5 @@
|
|||||||
export enum PaymentType {
|
export enum TransferType {
|
||||||
CARD_TO_CARD = "CARD_TO_CARD",
|
|
||||||
GATEWAY = "GATEWAY",
|
|
||||||
SHEBA = "SHEBA",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum TransferMethod {
|
|
||||||
CARD_TO_CARD = "CARD_TO_CARD",
|
CARD_TO_CARD = "CARD_TO_CARD",
|
||||||
SHEBA = "SHEBA",
|
SHEBA = "SHEBA",
|
||||||
|
// GATEWAY = "GATEWAY",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,17 @@ import { ApiOperation, ApiTags } from "@nestjs/swagger";
|
|||||||
|
|
||||||
import { CreateBankAccountDto } from "./DTO/create-bankaccount.dto";
|
import { CreateBankAccountDto } from "./DTO/create-bankaccount.dto";
|
||||||
import { GatewayDepositDto, TransferDepositDto } from "./DTO/deposit-wallet.dto";
|
import { GatewayDepositDto, TransferDepositDto } from "./DTO/deposit-wallet.dto";
|
||||||
|
import { PaymentTransactionQueryDto } from "./DTO/payment-transaction-query.dto";
|
||||||
import { SearchTransactionQueryDto } from "./DTO/search-transaction-query.dto";
|
import { SearchTransactionQueryDto } from "./DTO/search-transaction-query.dto";
|
||||||
import { UpdateBankAccountDto } from "./DTO/update-bankaccount.dto";
|
import { UpdateBankAccountDto } from "./DTO/update-bankaccount.dto";
|
||||||
|
import { RejectDepositRequestDto } from "./DTO/update-deposit-request-status.dto";
|
||||||
import { VerifyParamDto, VerifyQueryDto } from "./DTO/verify-payment.dto";
|
import { VerifyParamDto, VerifyQueryDto } from "./DTO/verify-payment.dto";
|
||||||
import { PaymentsService } from "./providers/payments.service";
|
import { PaymentsService } from "./providers/payments.service";
|
||||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||||
import { Pagination } from "../../common/decorators/pagination.decorator";
|
import { Pagination } from "../../common/decorators/pagination.decorator";
|
||||||
import { Roles } from "../../common/decorators/roles.decorator";
|
import { Roles } from "../../common/decorators/roles.decorator";
|
||||||
import { UserDec } from "../../common/decorators/user.decorator";
|
import { UserDec } from "../../common/decorators/user.decorator";
|
||||||
|
import { PaginationDto } from "../../common/DTO/pagination.dto";
|
||||||
import { ParamDto } from "../../common/DTO/param.dto";
|
import { ParamDto } from "../../common/DTO/param.dto";
|
||||||
import { Role } from "../users/entities/role.entity";
|
import { Role } from "../users/entities/role.entity";
|
||||||
import { RoleEnum } from "../users/enums/role.enum";
|
import { RoleEnum } from "../users/enums/role.enum";
|
||||||
@@ -43,11 +46,39 @@ export class PaymentsController {
|
|||||||
return this.paymentsService.chargeWalletWithTransfer(depositDto, userId);
|
return this.paymentsService.chargeWalletWithTransfer(depositDto, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation({ summary: "get deposit request of users" })
|
@ApiOperation({ summary: "get deposit request of users ==> admin route" })
|
||||||
@AuthGuards()
|
@AuthGuards()
|
||||||
|
@Pagination()
|
||||||
@Roles(RoleEnum.ADMIN)
|
@Roles(RoleEnum.ADMIN)
|
||||||
@Get("deposit/transfer")
|
@Get("deposit/transfer")
|
||||||
getDepositRequests() {}
|
getDepositRequests(@Query() queryDto: PaymentTransactionQueryDto) {
|
||||||
|
return this.paymentsService.getDepositRequests(queryDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "get deposit gateway payment ==> admin route" })
|
||||||
|
@AuthGuards()
|
||||||
|
@Pagination()
|
||||||
|
@Roles(RoleEnum.ADMIN)
|
||||||
|
@Get("deposit/gateway")
|
||||||
|
getDepositGatewayPayment(@Query() queryDto: PaginationDto) {
|
||||||
|
return this.paymentsService.getDepositGatewayPayment(queryDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "approve deposit request ==> admin route" })
|
||||||
|
@AuthGuards()
|
||||||
|
@Roles(RoleEnum.ADMIN)
|
||||||
|
@Post("deposit/transfer/approve/:id")
|
||||||
|
approverDepositRequest(@Param() paramDto: ParamDto) {
|
||||||
|
return this.paymentsService.approverDepositRequest(paramDto.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "reject deposit request ==> admin route" })
|
||||||
|
@AuthGuards()
|
||||||
|
@Roles(RoleEnum.ADMIN)
|
||||||
|
@Post("deposit/transfer/reject/:id")
|
||||||
|
rejectDepositRequest(@Param() paramDto: ParamDto, @Body() rejectDto: RejectDepositRequestDto) {
|
||||||
|
return this.paymentsService.rejectDepositRequest(paramDto.id, rejectDto);
|
||||||
|
}
|
||||||
|
|
||||||
@ApiOperation({ summary: "get transaction for admin" })
|
@ApiOperation({ summary: "get transaction for admin" })
|
||||||
@AuthGuards()
|
@AuthGuards()
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { randomUUID } from "node:crypto";
|
|
||||||
|
|
||||||
import { InjectQueue } from "@nestjs/bullmq";
|
import { InjectQueue } from "@nestjs/bullmq";
|
||||||
import { BadRequestException, HttpException, Injectable, InternalServerErrorException } from "@nestjs/common";
|
import { BadRequestException, HttpException, Injectable, InternalServerErrorException } from "@nestjs/common";
|
||||||
import { Queue } from "bullmq";
|
import { Queue } from "bullmq";
|
||||||
@@ -7,25 +5,31 @@ import { Queue } from "bullmq";
|
|||||||
import Decimal from "decimal.js";
|
import Decimal from "decimal.js";
|
||||||
import { DataSource, Not, QueryRunner } from "typeorm";
|
import { DataSource, Not, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
||||||
import { CommonMessage, PaymentMessage, UserMessage, WalletMessage } from "../../../common/enums/message.enum";
|
import { CommonMessage, PaymentMessage, UserMessage, WalletMessage } from "../../../common/enums/message.enum";
|
||||||
import { Role } from "../../users/entities/role.entity";
|
import { Role } from "../../users/entities/role.entity";
|
||||||
import { User } from "../../users/entities/user.entity";
|
import { User } from "../../users/entities/user.entity";
|
||||||
import { RoleEnum } from "../../users/enums/role.enum";
|
import { RoleEnum } from "../../users/enums/role.enum";
|
||||||
|
import { PaginationUtils } from "../../utils/providers/pagination.utils";
|
||||||
|
import { Wallet } from "../../wallets/entities/wallet.entity";
|
||||||
import { WalletsService } from "../../wallets/providers/wallets.service";
|
import { WalletsService } from "../../wallets/providers/wallets.service";
|
||||||
import { PAYMENT } from "../constants";
|
import { PAYMENT } from "../constants";
|
||||||
import { CreateBankAccountDto } from "../DTO/create-bankaccount.dto";
|
import { CreateBankAccountDto } from "../DTO/create-bankaccount.dto";
|
||||||
import { GatewayDepositDto, TransferDepositDto } from "../DTO/deposit-wallet.dto";
|
import { GatewayDepositDto, TransferDepositDto } from "../DTO/deposit-wallet.dto";
|
||||||
|
import { PaymentTransactionQueryDto } from "../DTO/payment-transaction-query.dto";
|
||||||
import { SearchTransactionQueryDto } from "../DTO/search-transaction-query.dto";
|
import { SearchTransactionQueryDto } from "../DTO/search-transaction-query.dto";
|
||||||
import { UpdateBankAccountDto } from "../DTO/update-bankaccount.dto";
|
import { UpdateBankAccountDto } from "../DTO/update-bankaccount.dto";
|
||||||
|
import { RejectDepositRequestDto } from "../DTO/update-deposit-request-status.dto";
|
||||||
import { VerifyQueryDto } from "../DTO/verify-payment.dto";
|
import { VerifyQueryDto } from "../DTO/verify-payment.dto";
|
||||||
import { BankAccount } from "../entities/bank-account.entity";
|
import { BankAccount } from "../entities/bank-account.entity";
|
||||||
import { DepositRequest } from "../entities/deposit-request.entity";
|
import { DepositRequest } from "../entities/deposit-request.entity";
|
||||||
import { PaymentGateway } from "../entities/payment-gateway.entity";
|
import { PaymentGateway } from "../entities/payment-gateway.entity";
|
||||||
import { Payment } from "../entities/payment.entity";
|
import { Payment } from "../entities/payment.entity";
|
||||||
|
import { DepositRequestStatus } from "../enums/deposit-request-status.enum";
|
||||||
import { PaymentStatus } from "../enums/payment-status.enum";
|
import { PaymentStatus } from "../enums/payment-status.enum";
|
||||||
import { PaymentType } from "../enums/payment-type.enum";
|
|
||||||
import { PaymentGatewayFactory } from "../factories/payment.factory";
|
import { PaymentGatewayFactory } from "../factories/payment.factory";
|
||||||
import { BankAccountsRepository } from "../repositories/bank-accounts.repository";
|
import { BankAccountsRepository } from "../repositories/bank-accounts.repository";
|
||||||
|
import { DepositRequestsRepository } from "../repositories/deposit-requests.repository";
|
||||||
import { PaymentGatewaysRepository } from "../repositories/payment-gateway.repository";
|
import { PaymentGatewaysRepository } from "../repositories/payment-gateway.repository";
|
||||||
import { PaymentsRepository } from "../repositories/payments.repository";
|
import { PaymentsRepository } from "../repositories/payments.repository";
|
||||||
import { GatewayType } from "../types/gateway.type";
|
import { GatewayType } from "../types/gateway.type";
|
||||||
@@ -39,6 +43,7 @@ export class PaymentsService {
|
|||||||
private readonly paymentsRepository: PaymentsRepository,
|
private readonly paymentsRepository: PaymentsRepository,
|
||||||
private readonly bankAccountsRepository: BankAccountsRepository,
|
private readonly bankAccountsRepository: BankAccountsRepository,
|
||||||
private readonly walletsService: WalletsService,
|
private readonly walletsService: WalletsService,
|
||||||
|
private readonly depositRequestsRepository: DepositRequestsRepository,
|
||||||
private dataSource: DataSource,
|
private dataSource: DataSource,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@@ -75,7 +80,6 @@ export class PaymentsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//*********************************** */
|
//*********************************** */
|
||||||
//TODO:complete this
|
|
||||||
async chargeWalletWithTransfer(depositDto: TransferDepositDto, userId: string) {
|
async chargeWalletWithTransfer(depositDto: TransferDepositDto, userId: string) {
|
||||||
const queryRunner = this.dataSource.createQueryRunner();
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
await queryRunner.connect();
|
await queryRunner.connect();
|
||||||
@@ -87,16 +91,17 @@ export class PaymentsService {
|
|||||||
|
|
||||||
const user = await queryRunner.manager.findOneBy(User, { id: userId });
|
const user = await queryRunner.manager.findOneBy(User, { id: userId });
|
||||||
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||||
//
|
|
||||||
const reference = randomUUID();
|
// if (method === TransferType.GATEWAY) throw new BadRequestException(PaymentMessage.TRANSFER_METHOD_NOT_ALLOWED);
|
||||||
const paymentType = method as unknown as PaymentType;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
const payment = queryRunner.manager.create(Payment, { amount, reference, user, type: paymentType, bankAccount });
|
const depositRequest = queryRunner.manager.create(DepositRequest, {
|
||||||
|
bankAccount,
|
||||||
await queryRunner.manager.save(Payment, payment);
|
user,
|
||||||
//
|
receiptUrl: transferReceiptUrl,
|
||||||
const depositRequest = queryRunner.manager.create(DepositRequest, { bankAccount, user, receiptUrl: transferReceiptUrl });
|
amount,
|
||||||
|
type: method,
|
||||||
|
});
|
||||||
|
|
||||||
await queryRunner.manager.save(DepositRequest, depositRequest);
|
await queryRunner.manager.save(DepositRequest, depositRequest);
|
||||||
|
|
||||||
@@ -134,6 +139,7 @@ export class PaymentsService {
|
|||||||
relations: ["user"],
|
relations: ["user"],
|
||||||
// lock: { mode: "pessimistic_write" },
|
// lock: { mode: "pessimistic_write" },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!payment) throw new BadRequestException(PaymentMessage.PAYMENT_NOT_FOUND_WITH_REF);
|
if (!payment) throw new BadRequestException(PaymentMessage.PAYMENT_NOT_FOUND_WITH_REF);
|
||||||
if (payment.status === PaymentStatus.COMPLETED) throw new BadRequestException(PaymentMessage.VALIDATED_BEFORE);
|
if (payment.status === PaymentStatus.COMPLETED) throw new BadRequestException(PaymentMessage.VALIDATED_BEFORE);
|
||||||
|
|
||||||
@@ -184,12 +190,12 @@ export class PaymentsService {
|
|||||||
async createGatewayPaymentForUser(user: User, amount: number, reference: string, gatewayId: string, queryRunner: QueryRunner) {
|
async createGatewayPaymentForUser(user: User, amount: number, reference: string, gatewayId: string, queryRunner: QueryRunner) {
|
||||||
//
|
//
|
||||||
const payment = queryRunner.manager.create(Payment, {
|
const payment = queryRunner.manager.create(Payment, {
|
||||||
type: PaymentType.GATEWAY,
|
|
||||||
amount,
|
amount,
|
||||||
reference,
|
reference,
|
||||||
user,
|
user,
|
||||||
paymentGateway: { id: gatewayId },
|
paymentGateway: { id: gatewayId },
|
||||||
});
|
});
|
||||||
|
//
|
||||||
await queryRunner.manager.save(Payment, payment);
|
await queryRunner.manager.save(Payment, payment);
|
||||||
this.paymentQueue.add(PAYMENT.PAYMENT_START, { payment }, { delay: 1000 });
|
this.paymentQueue.add(PAYMENT.PAYMENT_START, { payment }, { delay: 1000 });
|
||||||
|
|
||||||
@@ -287,4 +293,132 @@ export class PaymentsService {
|
|||||||
async getTransactions(queryDto: SearchTransactionQueryDto) {
|
async getTransactions(queryDto: SearchTransactionQueryDto) {
|
||||||
return this.walletsService.getTransactionsForAdmin(queryDto);
|
return this.walletsService.getTransactionsForAdmin(queryDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//*********************************** */
|
||||||
|
async getDepositRequests(queryDto: PaymentTransactionQueryDto) {
|
||||||
|
const { limit, skip } = PaginationUtils(queryDto);
|
||||||
|
const { type } = queryDto;
|
||||||
|
|
||||||
|
const queryBuilder = this.depositRequestsRepository
|
||||||
|
.createQueryBuilder("depositRequest")
|
||||||
|
.leftJoinAndSelect("depositRequest.user", "user")
|
||||||
|
.leftJoinAndSelect("depositRequest.bankAccount", "bankAccount")
|
||||||
|
.orderBy("depositRequest.createdAt", "DESC")
|
||||||
|
.skip(skip)
|
||||||
|
.take(limit);
|
||||||
|
|
||||||
|
if (type) {
|
||||||
|
queryBuilder.andWhere("depositRequest.type = :type", { type });
|
||||||
|
}
|
||||||
|
|
||||||
|
const [depositRequests, count] = await queryBuilder.getManyAndCount();
|
||||||
|
|
||||||
|
return {
|
||||||
|
depositRequests,
|
||||||
|
count,
|
||||||
|
paginate: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//*********************************** */
|
||||||
|
|
||||||
|
async getDepositGatewayPayment(queryDto: PaginationDto) {
|
||||||
|
const { limit, skip } = PaginationUtils(queryDto);
|
||||||
|
|
||||||
|
const queryBuilder = this.paymentsRepository
|
||||||
|
.createQueryBuilder("payment")
|
||||||
|
.leftJoinAndSelect("payment.user", "user")
|
||||||
|
.leftJoinAndSelect("payment.paymentGateway", "paymentGateway")
|
||||||
|
.orderBy("payment.createdAt", "DESC")
|
||||||
|
.skip(skip)
|
||||||
|
.take(limit);
|
||||||
|
|
||||||
|
const [payments, count] = await queryBuilder.getManyAndCount();
|
||||||
|
|
||||||
|
return {
|
||||||
|
payments,
|
||||||
|
count,
|
||||||
|
paginate: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//*********************************** */
|
||||||
|
|
||||||
|
async getDepositRequestById(depositId: string) {
|
||||||
|
const depositRequest = await this.depositRequestsRepository.findOneBy({ id: depositId });
|
||||||
|
if (!depositRequest) throw new BadRequestException(PaymentMessage.DEPOSIT_NOT_FOUND);
|
||||||
|
|
||||||
|
return {
|
||||||
|
depositRequest,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//*********************************** */
|
||||||
|
async approverDepositRequest(depositId: string) {
|
||||||
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
|
await queryRunner.connect();
|
||||||
|
await queryRunner.startTransaction();
|
||||||
|
try {
|
||||||
|
const depositRequest = await queryRunner.manager.findOne(DepositRequest, {
|
||||||
|
where: { id: depositId },
|
||||||
|
lock: { mode: "pessimistic_write" },
|
||||||
|
});
|
||||||
|
if (!depositRequest) throw new BadRequestException(PaymentMessage.DEPOSIT_NOT_FOUND);
|
||||||
|
|
||||||
|
if (depositRequest.status === DepositRequestStatus.APPROVED) throw new BadRequestException(PaymentMessage.DEPOSIT_ALREADY_APPROVED);
|
||||||
|
|
||||||
|
const wallet = await queryRunner.manager.findOneBy(Wallet, { user: depositRequest.user });
|
||||||
|
if (!wallet) throw new BadRequestException(WalletMessage.WALLET_NOT_FOUND);
|
||||||
|
|
||||||
|
await queryRunner.manager.update(Wallet, { id: wallet.id }, { balance: new Decimal(wallet.balance).add(depositRequest.amount) });
|
||||||
|
|
||||||
|
await queryRunner.manager.update(DepositRequest, { id: depositRequest.id }, { status: DepositRequestStatus.APPROVED });
|
||||||
|
|
||||||
|
await this.walletsService.createDepositTransaction(depositRequest.amount, wallet.id, queryRunner);
|
||||||
|
|
||||||
|
await queryRunner.commitTransaction();
|
||||||
|
return {
|
||||||
|
message: PaymentMessage.DEPOSIT_APPROVED,
|
||||||
|
depositRequest,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
await queryRunner.rollbackTransaction();
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
await queryRunner.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//*********************************** */
|
||||||
|
async rejectDepositRequest(depositId: string, rejectDto: RejectDepositRequestDto) {
|
||||||
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
|
await queryRunner.connect();
|
||||||
|
await queryRunner.startTransaction();
|
||||||
|
try {
|
||||||
|
const depositRequest = await queryRunner.manager.findOne(DepositRequest, {
|
||||||
|
where: { id: depositId },
|
||||||
|
lock: { mode: "pessimistic_write" },
|
||||||
|
});
|
||||||
|
if (!depositRequest) throw new BadRequestException(PaymentMessage.DEPOSIT_NOT_FOUND);
|
||||||
|
|
||||||
|
if (depositRequest.status === DepositRequestStatus.REJECTED) throw new BadRequestException(PaymentMessage.DEPOSIT_ALREADY_REJECTED);
|
||||||
|
|
||||||
|
await queryRunner.manager.update(
|
||||||
|
DepositRequest,
|
||||||
|
{ id: depositRequest.id },
|
||||||
|
{ status: DepositRequestStatus.REJECTED, comment: rejectDto.comment },
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.commitTransaction();
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: PaymentMessage.DEPOSIT_REJECTED,
|
||||||
|
depositRequest,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
await queryRunner.rollbackTransaction();
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
await queryRunner.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,13 +169,8 @@ export class TicketsService {
|
|||||||
where: {
|
where: {
|
||||||
...(queryDto.status && { status: queryDto.status }),
|
...(queryDto.status && { status: queryDto.status }),
|
||||||
},
|
},
|
||||||
relations: {
|
relations: ["category", "user"],
|
||||||
category: true,
|
order: { createdAt: "DESC" as const },
|
||||||
user: true,
|
|
||||||
},
|
|
||||||
order: {
|
|
||||||
createdAt: "DESC" as const,
|
|
||||||
},
|
|
||||||
skip,
|
skip,
|
||||||
take: limit,
|
take: limit,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -59,6 +59,26 @@ export class WalletsService {
|
|||||||
}
|
}
|
||||||
//*********************************** */
|
//*********************************** */
|
||||||
|
|
||||||
|
async createDepositTransaction(amount: Decimal, walletId: string, queryRunner: QueryRunner) {
|
||||||
|
// const wallet = await queryRunner.manager.findOne(Wallet, { where: { user: { id: userId } }, lock: { mode: "pessimistic_write" } });
|
||||||
|
// if (!wallet) throw new BadRequestException(WalletMessage.WALLET_NOT_FOUND);
|
||||||
|
|
||||||
|
const transaction = queryRunner.manager.create(WalletTransaction, {
|
||||||
|
amount,
|
||||||
|
wallet: { id: walletId },
|
||||||
|
type: TransactionType.DEPOSIT,
|
||||||
|
description: WalletMessage.DEPOSIT_WALLET_TRANSFER,
|
||||||
|
});
|
||||||
|
|
||||||
|
// wallet.balance = new Decimal(wallet.balance).add(transaction.amount);
|
||||||
|
// await queryRunner.manager.save(Wallet, wallet);
|
||||||
|
|
||||||
|
await queryRunner.manager.save(WalletTransaction, transaction);
|
||||||
|
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
//*********************************** */
|
||||||
|
|
||||||
async getTransaction(userId: string, paginationDto: PaginationDto) {
|
async getTransaction(userId: string, paginationDto: PaginationDto) {
|
||||||
const { skip, limit } = PaginationUtils(paginationDto);
|
const { skip, limit } = PaginationUtils(paginationDto);
|
||||||
|
|
||||||
@@ -129,7 +149,7 @@ export class WalletsService {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if (queryDto.q) {
|
if (queryDto.q) {
|
||||||
queryBuilder.andWhere("(transaction.description LIKE :q LIKE :q OR user.name LIKE :q OR user.family LIKE :q)", {
|
queryBuilder.andWhere("(transaction.description LIKE :q OR user.firstName LIKE :q OR user.lastName LIKE :q)", {
|
||||||
q: `%${queryDto.q}%`,
|
q: `%${queryDto.q}%`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user