From ffa2a2a806079ed94ed64aa34d7959c75c14aeeb Mon Sep 17 00:00:00 2001 From: mahyargdz Date: Sat, 8 Feb 2025 14:18:51 +0330 Subject: [PATCH] chore: complete payment system --- src/common/enums/message.enum.ts | 13 +- .../payments/DTO/deposit-wallet.dto.ts | 8 +- .../DTO/payment-transaction-query.dto.ts | 17 ++ .../DTO/update-deposit-request-status.dto.ts | 12 ++ .../entities/deposit-request.entity.ts | 16 ++ .../payments/entities/payment.entity.ts | 12 +- .../enums/deposit-request-status.enum.ts | 5 + .../payments/enums/payment-type.enum.ts | 9 +- src/modules/payments/payments.controller.ts | 35 +++- .../payments/providers/payments.service.ts | 160 ++++++++++++++++-- .../tickets/providers/tickets.service.ts | 9 +- .../wallets/providers/wallets.service.ts | 22 ++- 12 files changed, 273 insertions(+), 45 deletions(-) create mode 100644 src/modules/payments/DTO/payment-transaction-query.dto.ts create mode 100644 src/modules/payments/DTO/update-deposit-request-status.dto.ts create mode 100644 src/modules/payments/enums/deposit-request-status.enum.ts diff --git a/src/common/enums/message.enum.ts b/src/common/enums/message.enum.ts index a8f0bd1..e94720d 100644 --- a/src/common/enums/message.enum.ts +++ b/src/common/enums/message.enum.ts @@ -75,6 +75,7 @@ export const enum CommonMessage { DELETED = "با موفقیت حذف شد", ID_REQUIRED = "شناسه مورد نیاز است", ID_SHOULD_BE_UUID = "شناسه باید یک یو یو آی دی باشد", + PaymentTypeQueryNotEmpty = "نوع پرداخت نمی‌تواند خالی باشد", } export const enum CategoryMessage { @@ -198,7 +199,7 @@ export const enum WalletMessage { DEPOSIT_WALLET_IPG = "شارژ کیف پول از طریق درگاه", TRANSFER_METHOD_REQUIRED = "روش انتفال اجباری است", GATEWAY_ID_SHOULD_BE_UUID = "آیدی درگاه پرداخت باید UUID باشد", - // DEPOSIT_WITH_TRANSFER = "DEPOSIT_WITH_TRANSFER", + DEPOSIT_WALLET_TRANSFER = "شارژ کیف پول از طریق انتقال بانکی", } export const enum PaymentMessage { @@ -225,6 +226,16 @@ export const enum PaymentMessage { BANK_ACCOUNT_NOT_FOUND = "حساب بانکی پیدا نشد", DEPOSIT_CREATED = "درخواست واریز ثبت شد", 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 { diff --git a/src/modules/payments/DTO/deposit-wallet.dto.ts b/src/modules/payments/DTO/deposit-wallet.dto.ts index 9350240..554574f 100644 --- a/src/modules/payments/DTO/deposit-wallet.dto.ts +++ b/src/modules/payments/DTO/deposit-wallet.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty } from "@nestjs/swagger"; import { IsEnum, IsInt, IsNotEmpty, IsUUID, IsUrl, Min } from "class-validator"; import { WalletMessage } from "../../../common/enums/message.enum"; -import { TransferMethod } from "../enums/payment-type.enum"; +import { TransferType } from "../enums/payment-type.enum"; export class DepositDto { @IsNotEmpty({ message: WalletMessage.AMOUNT_REQUIRED }) @@ -36,7 +36,7 @@ export class TransferDepositDto extends DepositDto { bankAccountId: string; @IsNotEmpty({ message: WalletMessage.TRANSFER_METHOD_REQUIRED }) - @IsEnum(TransferMethod) - @ApiProperty({ description: "transfer method", example: TransferMethod.CARD_TO_CARD, enum: TransferMethod }) - method: TransferMethod; + @IsEnum(TransferType) + @ApiProperty({ description: "transfer method", example: TransferType.CARD_TO_CARD, enum: TransferType }) + method: TransferType; } diff --git a/src/modules/payments/DTO/payment-transaction-query.dto.ts b/src/modules/payments/DTO/payment-transaction-query.dto.ts new file mode 100644 index 0000000..7904072 --- /dev/null +++ b/src/modules/payments/DTO/payment-transaction-query.dto.ts @@ -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; +} diff --git a/src/modules/payments/DTO/update-deposit-request-status.dto.ts b/src/modules/payments/DTO/update-deposit-request-status.dto.ts new file mode 100644 index 0000000..f0b7c6f --- /dev/null +++ b/src/modules/payments/DTO/update-deposit-request-status.dto.ts @@ -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; +} diff --git a/src/modules/payments/entities/deposit-request.entity.ts b/src/modules/payments/entities/deposit-request.entity.ts index 3ac4734..26d3659 100644 --- a/src/modules/payments/entities/deposit-request.entity.ts +++ b/src/modules/payments/entities/deposit-request.entity.ts @@ -1,8 +1,12 @@ +import Decimal from "decimal.js"; import { Column, Entity, ManyToOne } from "typeorm"; import { BankAccount } from "./bank-account.entity"; import { BaseEntity } from "../../../common/entities/base.entity"; +import { DecimalTransformer } from "../../../common/transformers/decimal.transformer"; import { User } from "../../users/entities/user.entity"; +import { DepositRequestStatus } from "../enums/deposit-request-status.enum"; +import { TransferType } from "../enums/payment-type.enum"; @Entity() export class DepositRequest extends BaseEntity { @@ -14,4 +18,16 @@ export class DepositRequest extends BaseEntity { @Column({ type: "varchar", length: 250, nullable: false }) 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; } diff --git a/src/modules/payments/entities/payment.entity.ts b/src/modules/payments/entities/payment.entity.ts index 226a4a0..c7cc4d8 100644 --- a/src/modules/payments/entities/payment.entity.ts +++ b/src/modules/payments/entities/payment.entity.ts @@ -2,13 +2,11 @@ import Decimal from "decimal.js"; import { Column, Entity, ManyToOne } from "typeorm"; -import { BankAccount } from "./bank-account.entity"; import { PaymentGateway } from "./payment-gateway.entity"; import { BaseEntity } from "../../../common/entities/base.entity"; import { DecimalTransformer } from "../../../common/transformers/decimal.transformer"; import { User } from "../../users/entities/user.entity"; import { PaymentStatus } from "../enums/payment-status.enum"; -import { PaymentType } from "../enums/payment-type.enum"; @Entity() export class Payment extends BaseEntity { @@ -24,15 +22,9 @@ export class Payment extends BaseEntity { @Column({ type: "enum", enum: PaymentStatus, default: PaymentStatus.PENDING }) status: PaymentStatus; - @Column({ type: "enum", enum: PaymentType, nullable: false }) - type: PaymentType; - @ManyToOne(() => User, (user) => user.payments, { nullable: false, onDelete: "RESTRICT" }) user: User; - @ManyToOne(() => PaymentGateway, { nullable: true, onDelete: "SET NULL" }) - paymentGateway?: PaymentGateway; - - @ManyToOne(() => BankAccount, { nullable: true, onDelete: "SET NULL" }) - bankAccount?: BankAccount; // for CARD_TO_CARD or SHEBA transfers + @ManyToOne(() => PaymentGateway, { nullable: false, onDelete: "RESTRICT" }) + paymentGateway: PaymentGateway; } diff --git a/src/modules/payments/enums/deposit-request-status.enum.ts b/src/modules/payments/enums/deposit-request-status.enum.ts new file mode 100644 index 0000000..88a6ada --- /dev/null +++ b/src/modules/payments/enums/deposit-request-status.enum.ts @@ -0,0 +1,5 @@ +export enum DepositRequestStatus { + PENDING = "PENDING", + APPROVED = "APPROVED", + REJECTED = "REJECTED", +} diff --git a/src/modules/payments/enums/payment-type.enum.ts b/src/modules/payments/enums/payment-type.enum.ts index 97cf002..da869ce 100644 --- a/src/modules/payments/enums/payment-type.enum.ts +++ b/src/modules/payments/enums/payment-type.enum.ts @@ -1,10 +1,5 @@ -export enum PaymentType { - CARD_TO_CARD = "CARD_TO_CARD", - GATEWAY = "GATEWAY", - SHEBA = "SHEBA", -} - -export enum TransferMethod { +export enum TransferType { CARD_TO_CARD = "CARD_TO_CARD", SHEBA = "SHEBA", + // GATEWAY = "GATEWAY", } diff --git a/src/modules/payments/payments.controller.ts b/src/modules/payments/payments.controller.ts index 62000ac..90ebe53 100644 --- a/src/modules/payments/payments.controller.ts +++ b/src/modules/payments/payments.controller.ts @@ -3,14 +3,17 @@ import { ApiOperation, ApiTags } from "@nestjs/swagger"; import { CreateBankAccountDto } from "./DTO/create-bankaccount.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 { UpdateBankAccountDto } from "./DTO/update-bankaccount.dto"; +import { RejectDepositRequestDto } from "./DTO/update-deposit-request-status.dto"; import { VerifyParamDto, VerifyQueryDto } from "./DTO/verify-payment.dto"; import { PaymentsService } from "./providers/payments.service"; import { AuthGuards } from "../../common/decorators/auth-guard.decorator"; import { Pagination } from "../../common/decorators/pagination.decorator"; import { Roles } from "../../common/decorators/roles.decorator"; import { UserDec } from "../../common/decorators/user.decorator"; +import { PaginationDto } from "../../common/DTO/pagination.dto"; import { ParamDto } from "../../common/DTO/param.dto"; import { Role } from "../users/entities/role.entity"; import { RoleEnum } from "../users/enums/role.enum"; @@ -43,11 +46,39 @@ export class PaymentsController { return this.paymentsService.chargeWalletWithTransfer(depositDto, userId); } - @ApiOperation({ summary: "get deposit request of users" }) + @ApiOperation({ summary: "get deposit request of users ==> admin route" }) @AuthGuards() + @Pagination() @Roles(RoleEnum.ADMIN) @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" }) @AuthGuards() diff --git a/src/modules/payments/providers/payments.service.ts b/src/modules/payments/providers/payments.service.ts index 0d10bf8..8993207 100644 --- a/src/modules/payments/providers/payments.service.ts +++ b/src/modules/payments/providers/payments.service.ts @@ -1,5 +1,3 @@ -import { randomUUID } from "node:crypto"; - import { InjectQueue } from "@nestjs/bullmq"; import { BadRequestException, HttpException, Injectable, InternalServerErrorException } from "@nestjs/common"; import { Queue } from "bullmq"; @@ -7,25 +5,31 @@ import { Queue } from "bullmq"; import Decimal from "decimal.js"; import { DataSource, Not, QueryRunner } from "typeorm"; +import { PaginationDto } from "../../../common/DTO/pagination.dto"; import { CommonMessage, PaymentMessage, UserMessage, WalletMessage } from "../../../common/enums/message.enum"; import { Role } from "../../users/entities/role.entity"; import { User } from "../../users/entities/user.entity"; 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 { PAYMENT } from "../constants"; import { CreateBankAccountDto } from "../DTO/create-bankaccount.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 { UpdateBankAccountDto } from "../DTO/update-bankaccount.dto"; +import { RejectDepositRequestDto } from "../DTO/update-deposit-request-status.dto"; import { VerifyQueryDto } from "../DTO/verify-payment.dto"; import { BankAccount } from "../entities/bank-account.entity"; import { DepositRequest } from "../entities/deposit-request.entity"; import { PaymentGateway } from "../entities/payment-gateway.entity"; import { Payment } from "../entities/payment.entity"; +import { DepositRequestStatus } from "../enums/deposit-request-status.enum"; import { PaymentStatus } from "../enums/payment-status.enum"; -import { PaymentType } from "../enums/payment-type.enum"; import { PaymentGatewayFactory } from "../factories/payment.factory"; import { BankAccountsRepository } from "../repositories/bank-accounts.repository"; +import { DepositRequestsRepository } from "../repositories/deposit-requests.repository"; import { PaymentGatewaysRepository } from "../repositories/payment-gateway.repository"; import { PaymentsRepository } from "../repositories/payments.repository"; import { GatewayType } from "../types/gateway.type"; @@ -39,6 +43,7 @@ export class PaymentsService { private readonly paymentsRepository: PaymentsRepository, private readonly bankAccountsRepository: BankAccountsRepository, private readonly walletsService: WalletsService, + private readonly depositRequestsRepository: DepositRequestsRepository, private dataSource: DataSource, ) {} @@ -75,7 +80,6 @@ export class PaymentsService { } //*********************************** */ - //TODO:complete this async chargeWalletWithTransfer(depositDto: TransferDepositDto, userId: string) { const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); @@ -87,16 +91,17 @@ export class PaymentsService { const user = await queryRunner.manager.findOneBy(User, { id: userId }); if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND); - // - const reference = randomUUID(); - const paymentType = method as unknown as PaymentType; + + // if (method === TransferType.GATEWAY) throw new BadRequestException(PaymentMessage.TRANSFER_METHOD_NOT_ALLOWED); // - const payment = queryRunner.manager.create(Payment, { amount, reference, user, type: paymentType, bankAccount }); - - await queryRunner.manager.save(Payment, payment); - // - const depositRequest = queryRunner.manager.create(DepositRequest, { bankAccount, user, receiptUrl: transferReceiptUrl }); + const depositRequest = queryRunner.manager.create(DepositRequest, { + bankAccount, + user, + receiptUrl: transferReceiptUrl, + amount, + type: method, + }); await queryRunner.manager.save(DepositRequest, depositRequest); @@ -134,6 +139,7 @@ export class PaymentsService { relations: ["user"], // lock: { mode: "pessimistic_write" }, }); + if (!payment) throw new BadRequestException(PaymentMessage.PAYMENT_NOT_FOUND_WITH_REF); 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) { // const payment = queryRunner.manager.create(Payment, { - type: PaymentType.GATEWAY, amount, reference, user, paymentGateway: { id: gatewayId }, }); + // await queryRunner.manager.save(Payment, payment); this.paymentQueue.add(PAYMENT.PAYMENT_START, { payment }, { delay: 1000 }); @@ -287,4 +293,132 @@ export class PaymentsService { async getTransactions(queryDto: SearchTransactionQueryDto) { 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(); + } + } } diff --git a/src/modules/tickets/providers/tickets.service.ts b/src/modules/tickets/providers/tickets.service.ts index 91b9204..7be5b6f 100644 --- a/src/modules/tickets/providers/tickets.service.ts +++ b/src/modules/tickets/providers/tickets.service.ts @@ -169,13 +169,8 @@ export class TicketsService { where: { ...(queryDto.status && { status: queryDto.status }), }, - relations: { - category: true, - user: true, - }, - order: { - createdAt: "DESC" as const, - }, + relations: ["category", "user"], + order: { createdAt: "DESC" as const }, skip, take: limit, }; diff --git a/src/modules/wallets/providers/wallets.service.ts b/src/modules/wallets/providers/wallets.service.ts index 1597762..09d7416 100644 --- a/src/modules/wallets/providers/wallets.service.ts +++ b/src/modules/wallets/providers/wallets.service.ts @@ -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) { const { skip, limit } = PaginationUtils(paginationDto); @@ -129,7 +149,7 @@ export class WalletsService { // } 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}%`, }); }