import * as moment from 'moment'; import { sumBy } from 'lodash'; import { BillPayment } from '../models/BillPayment'; import { AccountNormal } from '@/interfaces/Account'; import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types'; import { Ledger } from '@/modules/Ledger/Ledger'; export class BillPaymentGL { private billPayment: BillPayment; private APAccountId: number; private gainLossAccountId: number; private baseCurrency: string; constructor(billPayment: BillPayment) { this.billPayment = billPayment; } /** * Sets the A/P account ID. * @param {number} APAccountId - * @returns {BillPaymentGL} */ setAPAccountId(APAccountId: number) { this.APAccountId = APAccountId; return this; } /** * Sets the gain/loss account ID. * @param {number} gainLossAccountId - * @returns {BillPaymentGL} */ setGainLossAccountId(gainLossAccountId: number) { this.gainLossAccountId = gainLossAccountId; return this; } /** * Sets the base currency. * @param {string} baseCurrency - * @returns {BillPaymentGL} */ setBaseCurrency(baseCurrency: string) { this.baseCurrency = baseCurrency; return this; } /** * Retrieves the payment common entry. */ private get paymentCommonEntry() { const formattedDate = moment(this.billPayment.paymentDate).format( 'YYYY-MM-DD', ); return { debit: 0, credit: 0, exchangeRate: this.billPayment.exchangeRate, currencyCode: this.billPayment.currencyCode, transactionId: this.billPayment.id, transactionType: 'BillPayment', transactionNumber: this.billPayment.paymentNumber, referenceNumber: this.billPayment.reference, date: formattedDate, createdAt: this.billPayment.createdAt, branchId: this.billPayment.branchId, }; } /** * Calculates the payment total exchange gain/loss. * @param {IBillPayment} paymentReceive - Payment receive with entries. * @returns {number} */ private get paymentExGainOrLoss(): number { return sumBy(this.billPayment.entries, (entry) => { const paymentLocalAmount = entry.paymentAmount * this.billPayment.exchangeRate; const invoicePayment = entry.paymentAmount * entry.bill.exchangeRate; return invoicePayment - paymentLocalAmount; }); } /** * Retrieves the payment exchange gain/loss entries. * @returns {ILedgerEntry[]} */ private get paymentExGainOrLossEntries(): ILedgerEntry[] { const commonEntry = this.paymentCommonEntry; const totalExGainOrLoss = this.paymentExGainOrLoss; const absExGainOrLoss = Math.abs(totalExGainOrLoss); return totalExGainOrLoss ? [ { ...commonEntry, currencyCode: this.baseCurrency, exchangeRate: 1, credit: totalExGainOrLoss > 0 ? absExGainOrLoss : 0, debit: totalExGainOrLoss < 0 ? absExGainOrLoss : 0, accountId: this.gainLossAccountId, index: 2, indexGroup: 20, accountNormal: AccountNormal.DEBIT, }, { ...commonEntry, currencyCode: this.baseCurrency, exchangeRate: 1, debit: totalExGainOrLoss > 0 ? absExGainOrLoss : 0, credit: totalExGainOrLoss < 0 ? absExGainOrLoss : 0, accountId: this.APAccountId, index: 3, accountNormal: AccountNormal.DEBIT, }, ] : []; } /** * Retrieves the payment deposit GL entry. * @param {IBillPayment} billPayment * @returns {ILedgerEntry} */ private get paymentGLEntry(): ILedgerEntry { const commonEntry = this.paymentCommonEntry; return { ...commonEntry, credit: this.billPayment.localAmount, accountId: this.billPayment.paymentAccountId, accountNormal: AccountNormal.DEBIT, index: 2, }; } /** * Retrieves the payment GL payable entry. * @returns {ILedgerEntry} */ private get paymentGLPayableEntry(): ILedgerEntry { const commonEntry = this.paymentCommonEntry; return { ...commonEntry, exchangeRate: this.billPayment.exchangeRate, debit: this.billPayment.localAmount, contactId: this.billPayment.vendorId, accountId: this.APAccountId, accountNormal: AccountNormal.CREDIT, index: 1, }; } /** * Retrieves the payment GL entries. * @param {IBillPayment} billPayment * @param {number} APAccountId * @returns {ILedgerEntry[]} */ private get paymentGLEntries(): ILedgerEntry[] { // Retrieves the payment deposit entry. const paymentEntry = this.paymentGLEntry; // Retrieves the payment debit A/R entry. const payableEntry = this.paymentGLPayableEntry; // Retrieves the exchange gain/loss entries. const exGainLossEntries = this.paymentExGainOrLossEntries; return [paymentEntry, payableEntry, ...exGainLossEntries]; }; /** * Retrieves the bill payment ledger. * @param {IBillPayment} billPayment * @param {number} APAccountId * @returns {Ledger} */ public getBillPaymentLedger(): Ledger { const entries = this.paymentGLEntries; return new Ledger(entries); } }