import { Inject, Service } from 'typedi'; import { omit } from 'lodash'; import TenancyService from '@/services/Tenancy/TenancyService'; import { IBill, IBillPayment, IBillReceivePageEntry } from '@/interfaces'; import { ERRORS } from './constants'; import { ServiceError } from '@/exceptions'; @Service() export default class BillPaymentsPages { @Inject() private tenancy: TenancyService; /** * Retrieve bill payment with associated metadata. * @param {number} billPaymentId - The bill payment id. * @return {object} */ public async getBillPaymentEditPage( tenantId: number, billPaymentId: number ): Promise<{ billPayment: Omit; entries: IBillReceivePageEntry[]; }> { const { BillPayment, Bill } = this.tenancy.models(tenantId); const billPayment = await BillPayment.query() .findById(billPaymentId) .withGraphFetched('entries.bill') .withGraphFetched('attachments'); // Throw not found the bill payment. if (!billPayment) { throw new ServiceError(ERRORS.PAYMENT_MADE_NOT_FOUND); } const paymentEntries = billPayment.entries.map((entry) => ({ ...this.mapBillToPageEntry(entry.bill), dueAmount: entry.bill.dueAmount + entry.paymentAmount, paymentAmount: entry.paymentAmount, })); const resPayableBills = await Bill.query() .modify('opened') .modify('dueBills') .where('vendor_id', billPayment.vendorId) .whereNotIn( 'id', billPayment.entries.map((e) => e.billId) ) .orderBy('bill_date', 'ASC'); // Mapping the payable bills to entries. const restPayableEntries = resPayableBills.map(this.mapBillToPageEntry); const entries = [...paymentEntries, ...restPayableEntries]; return { billPayment: omit(billPayment, ['entries']), entries, }; } /** * Retrieve the payable entries of the new page once vendor be selected. * @param {number} tenantId * @param {number} vendorId */ public async getNewPageEntries( tenantId: number, vendorId: number ): Promise { const { Bill } = this.tenancy.models(tenantId); // Retrieve all payable bills that associated to the payment made transaction. const payableBills = await Bill.query() .modify('opened') .modify('dueBills') .where('vendor_id', vendorId) .orderBy('bill_date', 'ASC'); return payableBills.map(this.mapBillToPageEntry); } /** * Retrive edit page invoices entries from the given sale invoices models. * @param {ISaleInvoice[]} invoices - Invoices. * @return {IPaymentReceiveEditPageEntry} */ private mapBillToPageEntry(bill: IBill): IBillReceivePageEntry { return { entryType: 'invoice', billId: bill.id, billNo: bill.billNumber, amount: bill.amount, dueAmount: bill.dueAmount, totalPaymentAmount: bill.paymentAmount, paymentAmount: bill.paymentAmount, currencyCode: bill.currencyCode, date: bill.billDate, }; } }