mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-11-26 00:24:54 +00:00
75 lines
3.0 KiB
TypeScript
75 lines
3.0 KiB
TypeScript
import { forwardRef, Inject, 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 { Account } from '../entities/account.entity';
|
|
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,
|
|
@Inject(forwardRef(() => CardService)) 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;
|
|
}
|
|
|
|
async createInternalChildTransaction(cardId: string, amount: number) {
|
|
const card = await this.cardService.getCardById(cardId);
|
|
const transaction = await this.transactionRepository.createInternalChildTransaction(card, amount);
|
|
return transaction;
|
|
}
|
|
|
|
async calculateAvailableSpendingLimitForParent(account: Account): Promise<number> {
|
|
const internalTransactionSum = await this.transactionRepository.findInternalTransactionTotal(account.id);
|
|
return new Decimal(account.balance).minus(internalTransactionSum).toNumber();
|
|
}
|
|
|
|
private async findExistingTransaction(transactionId: string, accountReference: string): Promise<Transaction | null> {
|
|
const existingTransaction = await this.transactionRepository.findTransactionByReference(
|
|
transactionId,
|
|
accountReference,
|
|
);
|
|
|
|
return existingTransaction;
|
|
}
|
|
}
|