mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
184 lines
5.2 KiB
TypeScript
184 lines
5.2 KiB
TypeScript
import { groupBy, sum, isEmpty } from 'lodash';
|
|
import * as R from 'ramda';
|
|
import AgingSummaryReport from './AgingSummary';
|
|
import {
|
|
IAPAgingSummaryQuery,
|
|
IAgingPeriod,
|
|
IBill,
|
|
IVendor,
|
|
IAPAgingSummaryData,
|
|
IAPAgingSummaryVendor,
|
|
IAPAgingSummaryColumns,
|
|
IAPAgingSummaryTotal,
|
|
} from '@/interfaces';
|
|
import { Dictionary } from 'tsyringe/dist/typings/types';
|
|
import { allPassedConditionsPass } from 'utils';
|
|
|
|
export default class APAgingSummarySheet extends AgingSummaryReport {
|
|
readonly tenantId: number;
|
|
readonly query: IAPAgingSummaryQuery;
|
|
readonly contacts: IVendor[];
|
|
readonly unpaidBills: IBill[];
|
|
readonly baseCurrency: string;
|
|
|
|
readonly overdueInvoicesByContactId: Dictionary<IBill[]>;
|
|
readonly currentInvoicesByContactId: Dictionary<IBill[]>;
|
|
|
|
readonly agingPeriods: IAgingPeriod[];
|
|
|
|
/**
|
|
* Constructor method.
|
|
* @param {number} tenantId - Tenant id.
|
|
* @param {IAPAgingSummaryQuery} query - Report query.
|
|
* @param {IVendor[]} vendors - Unpaid bills.
|
|
* @param {string} baseCurrency - Base currency of the organization.
|
|
*/
|
|
constructor(
|
|
tenantId: number,
|
|
query: IAPAgingSummaryQuery,
|
|
vendors: IVendor[],
|
|
overdueBills: IBill[],
|
|
unpaidBills: IBill[],
|
|
baseCurrency: string
|
|
) {
|
|
super();
|
|
|
|
this.tenantId = tenantId;
|
|
this.query = query;
|
|
this.numberFormat = this.query.numberFormat;
|
|
this.contacts = vendors;
|
|
this.baseCurrency = baseCurrency;
|
|
|
|
this.overdueInvoicesByContactId = groupBy(overdueBills, 'vendorId');
|
|
this.currentInvoicesByContactId = groupBy(unpaidBills, 'vendorId');
|
|
|
|
// Initializes the aging periods.
|
|
this.agingPeriods = this.agingRangePeriods(
|
|
this.query.asDate,
|
|
this.query.agingDaysBefore,
|
|
this.query.agingPeriods
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Retrieve the vendors aging and current total.
|
|
* @param {IAPAgingSummaryTotal} vendorsAgingPeriods
|
|
* @return {IAPAgingSummaryTotal}
|
|
*/
|
|
private getVendorsTotal = (vendorsAgingPeriods): IAPAgingSummaryTotal => {
|
|
const totalAgingPeriods = this.getTotalAgingPeriods(vendorsAgingPeriods);
|
|
const totalCurrent = this.getTotalCurrent(vendorsAgingPeriods);
|
|
const totalVendorsTotal = this.getTotalContactsTotals(vendorsAgingPeriods);
|
|
|
|
return {
|
|
current: this.formatTotalAmount(totalCurrent),
|
|
aging: totalAgingPeriods,
|
|
total: this.formatTotalAmount(totalVendorsTotal),
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Retrieve the vendor section data.
|
|
* @param {IVendor} vendor
|
|
* @return {IAPAgingSummaryVendor}
|
|
*/
|
|
private vendorTransformer = (vendor: IVendor): IAPAgingSummaryVendor => {
|
|
const agingPeriods = this.getContactAgingPeriods(vendor.id);
|
|
const currentTotal = this.getContactCurrentTotal(vendor.id);
|
|
const agingPeriodsTotal = this.getAgingPeriodsTotal(agingPeriods);
|
|
|
|
const amount = sum([agingPeriodsTotal, currentTotal]);
|
|
|
|
return {
|
|
vendorName: vendor.displayName,
|
|
current: this.formatAmount(currentTotal),
|
|
aging: agingPeriods,
|
|
total: this.formatTotalAmount(amount),
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Mappes the given vendor objects to vendor report node.
|
|
* @param {IVendor[]} vendors
|
|
* @returns {IAPAgingSummaryVendor[]}
|
|
*/
|
|
private vendorsMapper = (vendors: IVendor[]): IAPAgingSummaryVendor[] => {
|
|
return vendors.map(this.vendorTransformer);
|
|
};
|
|
|
|
/**
|
|
* Detarmines whether the given vendor node is none zero.
|
|
* @param {IAPAgingSummaryVendor} vendorNode
|
|
* @returns {boolean}
|
|
*/
|
|
private filterNoneZeroVendorNode = (
|
|
vendorNode: IAPAgingSummaryVendor
|
|
): boolean => {
|
|
return vendorNode.total.amount !== 0;
|
|
};
|
|
|
|
/**
|
|
* Filters vendors report nodes based on the given report query.
|
|
* @param {IAPAgingSummaryVendor} vendorNode
|
|
* @returns {boolean}
|
|
*/
|
|
private vendorNodeFilter = (vendorNode: IAPAgingSummaryVendor): boolean => {
|
|
const { noneZero } = this.query;
|
|
|
|
const conditions = [[noneZero, this.filterNoneZeroVendorNode]];
|
|
|
|
return allPassedConditionsPass(conditions)(vendorNode);
|
|
};
|
|
|
|
/**
|
|
* Filtesr the given report vendors nodes.
|
|
* @param {IAPAgingSummaryVendor[]} vendorNodes
|
|
* @returns {IAPAgingSummaryVendor[]}
|
|
*/
|
|
private vendorsFilter = (
|
|
vendorNodes: IAPAgingSummaryVendor[]
|
|
): IAPAgingSummaryVendor[] => {
|
|
return vendorNodes.filter(this.vendorNodeFilter);
|
|
};
|
|
|
|
/**
|
|
* Detarmines whether vendors nodes filter enabled.
|
|
* @returns {boolean}
|
|
*/
|
|
private isVendorNodesFilter = (): boolean => {
|
|
return isEmpty(this.query.vendorsIds);
|
|
};
|
|
|
|
/**
|
|
* Retrieve vendors aging periods.
|
|
* @return {IAPAgingSummaryVendor[]}
|
|
*/
|
|
private vendorsSection = (vendors: IVendor[]): IAPAgingSummaryVendor[] => {
|
|
return R.compose(
|
|
R.when(this.isVendorNodesFilter, this.vendorsFilter),
|
|
this.vendorsMapper
|
|
)(vendors);
|
|
};
|
|
|
|
/**
|
|
* Retrieve the A/P aging summary report data.
|
|
* @return {IAPAgingSummaryData}
|
|
*/
|
|
public reportData = (): IAPAgingSummaryData => {
|
|
const vendorsAgingPeriods = this.vendorsSection(this.contacts);
|
|
const vendorsTotal = this.getVendorsTotal(vendorsAgingPeriods);
|
|
|
|
return {
|
|
vendors: vendorsAgingPeriods,
|
|
total: vendorsTotal,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Retrieve the A/P aging summary report columns.
|
|
*/
|
|
public reportColumns = (): IAPAgingSummaryColumns => {
|
|
return this.agingPeriods;
|
|
};
|
|
}
|