mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-13 11:20:31 +00:00
207 lines
6.6 KiB
TypeScript
207 lines
6.6 KiB
TypeScript
// @ts-nocheck
|
|
import * as R from 'ramda';
|
|
import * as moment from 'moment';
|
|
import { first, isEmpty } from 'lodash';
|
|
import {
|
|
ICashflowAccountTransaction,
|
|
ICashflowAccountTransactionsQuery,
|
|
} from '../../types/BankingTransactions.types';
|
|
import { BankTransactionStatus } from './_constants';
|
|
import { FinancialSheet } from '@/modules/FinancialStatements/common/FinancialSheet';
|
|
import { formatBankTransactionsStatus } from './_utils';
|
|
import { GetBankAccountTransactionsRepository } from './GetBankAccountTransactionsRepo.service';
|
|
import { runningBalance } from '@/utils/running-balance';
|
|
import { I18nService } from 'nestjs-i18n';
|
|
|
|
export class GetBankAccountTransactions extends FinancialSheet {
|
|
private runningBalance: any;
|
|
private query: ICashflowAccountTransactionsQuery;
|
|
private repo: GetBankAccountTransactionsRepository;
|
|
private i18n: I18nService;
|
|
|
|
/**
|
|
* Constructor method.
|
|
* @param {IAccountTransaction[]} transactions -
|
|
* @param {number} openingBalance -
|
|
* @param {ICashflowAccountTransactionsQuery} query -
|
|
*/
|
|
constructor(
|
|
repo: GetBankAccountTransactionsRepository,
|
|
query: ICashflowAccountTransactionsQuery,
|
|
i18n: I18nService,
|
|
) {
|
|
super();
|
|
|
|
this.repo = repo;
|
|
this.query = query;
|
|
this.i18n = i18n;
|
|
|
|
this.runningBalance = runningBalance(this.repo.openingBalance);
|
|
}
|
|
|
|
/**
|
|
* Retrieves the transaction status.
|
|
* @param {} transaction
|
|
* @returns {BankTransactionStatus}
|
|
*/
|
|
private getTransactionStatus(transaction: any): BankTransactionStatus {
|
|
const categorizedTrans = this.repo.uncategorizedTransactionsMapByRef.get(
|
|
`${transaction.referenceType}-${transaction.referenceId}`,
|
|
);
|
|
const matchedTrans = this.repo.matchedBankTransactionsMapByRef.get(
|
|
`${transaction.referenceType}-${transaction.referenceId}`,
|
|
);
|
|
if (!isEmpty(categorizedTrans)) {
|
|
return BankTransactionStatus.Categorized;
|
|
} else if (!isEmpty(matchedTrans)) {
|
|
return BankTransactionStatus.Matched;
|
|
} else {
|
|
return BankTransactionStatus.Manual;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieves the uncategoized transaction id from the given transaction.
|
|
* @param transaction
|
|
* @returns {number|null}
|
|
*/
|
|
private getUncategorizedTransId(transaction: any): number {
|
|
// The given transaction would be categorized, matched or not, so we'd take a look at
|
|
// the categorized transaction first to get the id if not exist, then should look at the matched
|
|
// transaction if not exist too, so the given transaction has no uncategorized transaction id.
|
|
const categorizedTrans = this.repo.uncategorizedTransactionsMapByRef.get(
|
|
`${transaction.referenceType}-${transaction.referenceId}`,
|
|
);
|
|
const matchedTrans = this.repo.matchedBankTransactionsMapByRef.get(
|
|
`${transaction.referenceType}-${transaction.referenceId}`,
|
|
);
|
|
// Relation between the transaction and matching always been one-to-one.
|
|
const firstCategorizedTrans = first(categorizedTrans);
|
|
const firstMatchedTrans = first(matchedTrans);
|
|
|
|
return (
|
|
firstCategorizedTrans?.id ||
|
|
firstMatchedTrans?.uncategorizedTransactionId ||
|
|
null
|
|
);
|
|
}
|
|
|
|
/**
|
|
*Transformes the account transaction to to cashflow transaction node.
|
|
* @param {IAccountTransaction} transaction
|
|
* @returns {ICashflowAccountTransaction}
|
|
*/
|
|
private transactionNode = (transaction: any): ICashflowAccountTransaction => {
|
|
const status = this.getTransactionStatus(transaction);
|
|
const uncategorizedTransactionId =
|
|
this.getUncategorizedTransId(transaction);
|
|
|
|
return {
|
|
date: transaction.date,
|
|
formattedDate: moment(transaction.date).format('YYYY-MM-DD'),
|
|
|
|
withdrawal: transaction.credit,
|
|
deposit: transaction.debit,
|
|
|
|
formattedDeposit: this.formatNumber(transaction.debit),
|
|
formattedWithdrawal: this.formatNumber(transaction.credit),
|
|
|
|
referenceId: transaction.referenceId,
|
|
referenceType: transaction.referenceType,
|
|
|
|
formattedTransactionType: this.i18n.t(transaction.referenceTypeFormatted),
|
|
|
|
transactionNumber: transaction.transactionNumber,
|
|
referenceNumber: transaction.referenceNumber,
|
|
|
|
runningBalance: this.runningBalance.amount(),
|
|
formattedRunningBalance: this.formatNumber(this.runningBalance.amount()),
|
|
|
|
balance: 0,
|
|
formattedBalance: '',
|
|
status,
|
|
formattedStatus: formatBankTransactionsStatus(status),
|
|
uncategorizedTransactionId,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Associate cashflow transaction node with running balance attribute.
|
|
* @param {IAccountTransaction} transaction
|
|
* @returns {ICashflowAccountTransaction}
|
|
*/
|
|
private transactionRunningBalance = (
|
|
transaction: ICashflowAccountTransaction,
|
|
): ICashflowAccountTransaction => {
|
|
const amount = transaction.deposit - transaction.withdrawal;
|
|
|
|
const biggerThanZero = R.lt(0, amount);
|
|
const lowerThanZero = R.gt(0, amount);
|
|
|
|
const absAmount = Math.abs(amount);
|
|
|
|
R.when(R.always(biggerThanZero), this.runningBalance.decrement)(absAmount);
|
|
R.when(R.always(lowerThanZero), this.runningBalance.increment)(absAmount);
|
|
|
|
const runningBalance = this.runningBalance.amount();
|
|
|
|
return {
|
|
...transaction,
|
|
runningBalance,
|
|
formattedRunningBalance: this.formatNumber(runningBalance),
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Associate to balance attribute to cashflow transaction node.
|
|
* @param {ICashflowAccountTransaction} transaction
|
|
* @returns {ICashflowAccountTransaction}
|
|
*/
|
|
private transactionBalance = (
|
|
transaction: ICashflowAccountTransaction,
|
|
): ICashflowAccountTransaction => {
|
|
const balance =
|
|
transaction.runningBalance +
|
|
transaction.withdrawal * -1 +
|
|
transaction.deposit;
|
|
|
|
return {
|
|
...transaction,
|
|
balance,
|
|
formattedBalance: this.formatNumber(balance),
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Transformes the given account transaction to cashflow report transaction.
|
|
* @param {ICashflowAccountTransaction} transaction
|
|
* @returns {ICashflowAccountTransaction}
|
|
*/
|
|
private transactionTransformer = (
|
|
transaction,
|
|
): ICashflowAccountTransaction => {
|
|
return R.compose(
|
|
this.transactionBalance,
|
|
this.transactionRunningBalance,
|
|
this.transactionNode,
|
|
)(transaction);
|
|
};
|
|
|
|
/**
|
|
* Retrieve the report transactions node.
|
|
* @param {} transactions
|
|
* @returns {ICashflowAccountTransaction[]}
|
|
*/
|
|
private transactionsNode = (transactions): ICashflowAccountTransaction[] => {
|
|
return R.map(this.transactionTransformer)(transactions);
|
|
};
|
|
|
|
/**
|
|
* Retrieve the reprot data node.
|
|
* @returns {ICashflowAccountTransaction[]}
|
|
*/
|
|
public reportData(): ICashflowAccountTransaction[] {
|
|
return this.transactionsNode(this.repo.transactions);
|
|
}
|
|
}
|