import { Injectable, UnprocessableEntityException } from '@nestjs/common'; import Decimal from 'decimal.js'; import { Transactional } from 'typeorm-transactional'; import { AccountTransactionWebhookRequest, CardTransactionWebhookRequest, } from '~/common/modules/neoleap/dtos/requests'; import { Transaction } from '../entities/transaction.entity'; import { TransactionRepository } from '../repositories/transaction.repository'; import { AccountService } from './account.service'; import { CardService } from './card.service'; @Injectable() export class TransactionService { constructor( private readonly transactionRepository: TransactionRepository, private readonly accountService: AccountService, private readonly cardService: CardService, ) {} @Transactional() async createCardTransaction(body: CardTransactionWebhookRequest) { const card = await this.cardService.getCardByVpan(body.cardId); const existingTransaction = await this.findExistingTransaction(body.transactionId, card.account.accountReference); if (existingTransaction) { throw new UnprocessableEntityException('TRANSACTION.ALREADY_EXISTS'); } const transaction = await this.transactionRepository.createCardTransaction(card, body); const total = new Decimal(body.transactionAmount).plus(body.billingAmount).plus(body.fees).plus(body.vatOnFees); await this.accountService.decreaseAccountBalance(card.account.accountReference, total.toNumber()); return transaction; } @Transactional() async createAccountTransaction(body: AccountTransactionWebhookRequest) { const account = await this.accountService.getAccountByAccountNumber(body.accountId); const existingTransaction = await this.findExistingTransaction(body.transactionId, account.accountReference); if (existingTransaction) { throw new UnprocessableEntityException('TRANSACTION.ALREADY_EXISTS'); } const transaction = await this.transactionRepository.createAccountTransaction(account, body); await this.accountService.creditAccountBalance(account.accountReference, body.amount); return transaction; } private async findExistingTransaction(transactionId: string, accountReference: string): Promise { const existingTransaction = await this.transactionRepository.findTransactionByReference( transactionId, accountReference, ); return existingTransaction; } }