mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
feat(server): AP/AR aging summary table transformer
This commit is contained in:
@@ -33,10 +33,13 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
|
|||||||
return [
|
return [
|
||||||
...this.sheetNumberFormatValidationSchema,
|
...this.sheetNumberFormatValidationSchema,
|
||||||
query('as_date').optional().isISO8601(),
|
query('as_date').optional().isISO8601(),
|
||||||
query('aging_days_before').optional().isNumeric().toInt(),
|
|
||||||
query('aging_periods').optional().isNumeric().toInt(),
|
query('aging_days_before').default(30).isNumeric().toInt(),
|
||||||
|
query('aging_periods').default(3).isNumeric().toInt(),
|
||||||
|
|
||||||
query('vendors_ids').optional().isArray({ min: 1 }),
|
query('vendors_ids').optional().isArray({ min: 1 }),
|
||||||
query('vendors_ids.*').isInt({ min: 1 }).toInt(),
|
query('vendors_ids.*').isInt({ min: 1 }).toInt(),
|
||||||
|
|
||||||
query('none_zero').default(true).isBoolean().toBoolean(),
|
query('none_zero').default(true).isBoolean().toBoolean(),
|
||||||
|
|
||||||
// Filtering by branches.
|
// Filtering by branches.
|
||||||
@@ -53,6 +56,25 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
|
|||||||
const filter = this.matchedQueryData(req);
|
const filter = this.matchedQueryData(req);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const accept = this.accepts(req);
|
||||||
|
const acceptType = accept.types(['json', 'application/json+table']);
|
||||||
|
|
||||||
|
switch (acceptType) {
|
||||||
|
case 'application/json+table':
|
||||||
|
const table = await this.APAgingSummaryService.APAgingSummaryTable(
|
||||||
|
tenantId,
|
||||||
|
filter
|
||||||
|
);
|
||||||
|
return res.status(200).send({
|
||||||
|
table: {
|
||||||
|
rows: table.rows,
|
||||||
|
columns: table.columns,
|
||||||
|
},
|
||||||
|
meta: table.meta,
|
||||||
|
query: table.query,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
const { data, columns, query, meta } =
|
const { data, columns, query, meta } =
|
||||||
await this.APAgingSummaryService.APAgingSummary(tenantId, filter);
|
await this.APAgingSummaryService.APAgingSummary(tenantId, filter);
|
||||||
|
|
||||||
@@ -62,6 +84,8 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC
|
|||||||
query: this.transfromToResponse(query),
|
query: this.transfromToResponse(query),
|
||||||
meta: this.transfromToResponse(meta),
|
meta: this.transfromToResponse(meta),
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
|
|||||||
|
|
||||||
query('as_date').optional().isISO8601(),
|
query('as_date').optional().isISO8601(),
|
||||||
|
|
||||||
query('aging_days_before').optional().isInt({ max: 500 }).toInt(),
|
query('aging_days_before').default(30).isInt({ max: 500 }).toInt(),
|
||||||
query('aging_periods').optional().isInt({ max: 12 }).toInt(),
|
query('aging_periods').default(3).isInt({ max: 12 }).toInt(),
|
||||||
|
|
||||||
query('customers_ids').optional().isArray({ min: 1 }),
|
query('customers_ids').optional().isArray({ min: 1 }),
|
||||||
query('customers_ids.*').isInt({ min: 1 }).toInt(),
|
query('customers_ids.*').isInt({ min: 1 }).toInt(),
|
||||||
@@ -58,6 +58,25 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
|
|||||||
const filter = this.matchedQueryData(req);
|
const filter = this.matchedQueryData(req);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const accept = this.accepts(req);
|
||||||
|
const acceptType = accept.types(['json', 'application/json+table']);
|
||||||
|
|
||||||
|
switch (acceptType) {
|
||||||
|
case 'application/json+table':
|
||||||
|
const table = await this.ARAgingSummaryService.ARAgingSummaryTable(
|
||||||
|
tenantId,
|
||||||
|
filter
|
||||||
|
);
|
||||||
|
return res.status(200).send({
|
||||||
|
table: {
|
||||||
|
rows: table.rows,
|
||||||
|
columns: table.columns,
|
||||||
|
},
|
||||||
|
meta: table.meta,
|
||||||
|
query: table.query,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
const { data, columns, query, meta } =
|
const { data, columns, query, meta } =
|
||||||
await this.ARAgingSummaryService.ARAgingSummary(tenantId, filter);
|
await this.ARAgingSummaryService.ARAgingSummary(tenantId, filter);
|
||||||
|
|
||||||
@@ -67,6 +86,8 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC
|
|||||||
query: this.transfromToResponse(query),
|
query: this.transfromToResponse(query),
|
||||||
meta: this.transfromToResponse(meta),
|
meta: this.transfromToResponse(meta),
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +1,36 @@
|
|||||||
import {
|
import {
|
||||||
IAgingPeriod,
|
IAgingPeriod,
|
||||||
IAgingPeriodTotal,
|
IAgingPeriodTotal,
|
||||||
IAgingAmount
|
IAgingAmount,
|
||||||
|
IAgingSummaryQuery,
|
||||||
|
IAgingSummaryTotal,
|
||||||
|
IAgingSummaryContact,
|
||||||
|
IAgingSummaryData,
|
||||||
} from './AgingReport';
|
} from './AgingReport';
|
||||||
import {
|
import { INumberFormatQuery } from './FinancialStatements';
|
||||||
INumberFormatQuery
|
|
||||||
} from './FinancialStatements';
|
|
||||||
|
|
||||||
export interface IAPAgingSummaryQuery {
|
export interface IAPAgingSummaryQuery extends IAgingSummaryQuery {
|
||||||
asDate: Date | string;
|
|
||||||
agingDaysBefore: number;
|
|
||||||
agingPeriods: number;
|
|
||||||
numberFormat: INumberFormatQuery;
|
|
||||||
vendorsIds: number[];
|
vendorsIds: number[];
|
||||||
noneZero: boolean;
|
|
||||||
|
|
||||||
branchesIds?: number[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAPAgingSummaryVendor {
|
export interface IAPAgingSummaryVendor extends IAgingSummaryContact {
|
||||||
vendorName: string,
|
vendorName: string;
|
||||||
current: IAgingAmount,
|
}
|
||||||
aging: IAgingPeriodTotal[],
|
|
||||||
total: IAgingAmount,
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface IAPAgingSummaryTotal {
|
export interface IAPAgingSummaryTotal extends IAgingSummaryTotal {}
|
||||||
current: IAgingAmount,
|
|
||||||
aging: IAgingPeriodTotal[],
|
|
||||||
total: IAgingAmount,
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface IAPAgingSummaryData {
|
export interface IAPAgingSummaryData extends IAgingSummaryData {
|
||||||
vendors: IAPAgingSummaryVendor[],
|
vendors: IAPAgingSummaryVendor[];
|
||||||
total: IAPAgingSummaryTotal,
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export type IAPAgingSummaryColumns = IAgingPeriod[];
|
export type IAPAgingSummaryColumns = IAgingPeriod[];
|
||||||
|
|
||||||
|
|
||||||
export interface IARAgingSummaryMeta {
|
export interface IARAgingSummaryMeta {
|
||||||
baseCurrency: string,
|
baseCurrency: string;
|
||||||
organizationName: string,
|
organizationName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface IAPAgingSummaryMeta {
|
export interface IAPAgingSummaryMeta {
|
||||||
baseCurrency: string,
|
baseCurrency: string;
|
||||||
organizationName: string,
|
organizationName: string;
|
||||||
}
|
}
|
||||||
@@ -1,37 +1,28 @@
|
|||||||
import { IAgingPeriod, IAgingPeriodTotal, IAgingAmount } from './AgingReport';
|
import {
|
||||||
import { INumberFormatQuery } from './FinancialStatements';
|
IAgingPeriod,
|
||||||
|
IAgingSummaryQuery,
|
||||||
|
IAgingSummaryTotal,
|
||||||
|
IAgingSummaryContact,
|
||||||
|
IAgingSummaryData,
|
||||||
|
} from './AgingReport';
|
||||||
|
|
||||||
export interface IARAgingSummaryQuery {
|
export interface IARAgingSummaryQuery extends IAgingSummaryQuery {
|
||||||
asDate: Date | string;
|
|
||||||
agingDaysBefore: number;
|
|
||||||
agingPeriods: number;
|
|
||||||
numberFormat: INumberFormatQuery;
|
|
||||||
customersIds: number[];
|
customersIds: number[];
|
||||||
branchesIds: number[];
|
|
||||||
noneZero: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IARAgingSummaryCustomer {
|
export interface IARAgingSummaryCustomer extends IAgingSummaryContact {
|
||||||
customerName: string;
|
customerName: string;
|
||||||
current: IAgingAmount;
|
|
||||||
aging: IAgingPeriodTotal[];
|
|
||||||
total: IAgingAmount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IARAgingSummaryTotal {
|
export interface IARAgingSummaryTotal extends IAgingSummaryTotal {}
|
||||||
current: IAgingAmount;
|
|
||||||
aging: IAgingPeriodTotal[];
|
|
||||||
total: IAgingAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IARAgingSummaryData {
|
export interface IARAgingSummaryData extends IAgingSummaryData {
|
||||||
customers: IARAgingSummaryCustomer[];
|
customers: IARAgingSummaryCustomer[];
|
||||||
total: IARAgingSummaryTotal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IARAgingSummaryColumns = IAgingPeriod[];
|
export type IARAgingSummaryColumns = IAgingPeriod[];
|
||||||
|
|
||||||
export interface IARAgingSummaryMeta {
|
export interface IARAgingSummaryMeta {
|
||||||
organizationName: string,
|
organizationName: string;
|
||||||
baseCurrency: string,
|
baseCurrency: string;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
|
import { INumberFormatQuery } from './FinancialStatements';
|
||||||
|
|
||||||
export interface IAgingPeriodTotal extends IAgingPeriod {
|
export interface IAgingPeriodTotal extends IAgingPeriod {
|
||||||
total: IAgingAmount;
|
total: IAgingAmount;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface IAgingAmount {
|
export interface IAgingAmount {
|
||||||
amount: number;
|
amount: number;
|
||||||
@@ -20,3 +23,22 @@ export interface IAgingSummaryContact {
|
|||||||
aging: IAgingPeriodTotal[];
|
aging: IAgingPeriodTotal[];
|
||||||
total: IAgingAmount;
|
total: IAgingAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IAgingSummaryQuery {
|
||||||
|
asDate: Date | string;
|
||||||
|
agingDaysBefore: number;
|
||||||
|
agingPeriods: number;
|
||||||
|
numberFormat: INumberFormatQuery;
|
||||||
|
branchesIds: number[];
|
||||||
|
noneZero: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAgingSummaryTotal {
|
||||||
|
current: IAgingAmount;
|
||||||
|
aging: IAgingPeriodTotal[];
|
||||||
|
total: IAgingAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAgingSummaryData {
|
||||||
|
total: IAgingSummaryTotal;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import TenancyService from '@/services/Tenancy/TenancyService';
|
|||||||
import APAgingSummarySheet from './APAgingSummarySheet';
|
import APAgingSummarySheet from './APAgingSummarySheet';
|
||||||
import { Tenant } from '@/system/models';
|
import { Tenant } from '@/system/models';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
|
import APAgingSummaryTable from './APAgingSummaryTable';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class PayableAgingSummaryService {
|
export default class PayableAgingSummaryService {
|
||||||
@@ -84,7 +85,7 @@ export default class PayableAgingSummaryService {
|
|||||||
|
|
||||||
// Common query.
|
// Common query.
|
||||||
const commonQuery = (query) => {
|
const commonQuery = (query) => {
|
||||||
if (isEmpty(filter.branchesIds)) {
|
if (!isEmpty(filter.branchesIds)) {
|
||||||
query.modify('filterByBranches', filter.branchesIds);
|
query.modify('filterByBranches', filter.branchesIds);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -118,4 +119,22 @@ export default class PayableAgingSummaryService {
|
|||||||
meta: this.reportMetadata(tenantId),
|
meta: this.reportMetadata(tenantId),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {IAPAgingSummaryQuery} query
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async APAgingSummaryTable(tenantId: number, query: IAPAgingSummaryQuery) {
|
||||||
|
const report = await this.APAgingSummary(tenantId, query);
|
||||||
|
const table = new APAgingSummaryTable(report.data, query, {});
|
||||||
|
|
||||||
|
return {
|
||||||
|
columns: table.tableColumns(),
|
||||||
|
rows: table.tableRows(),
|
||||||
|
meta: report.meta,
|
||||||
|
query: report.query,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import {
|
||||||
|
IAPAgingSummaryData,
|
||||||
|
IAgingSummaryQuery,
|
||||||
|
ITableColumn,
|
||||||
|
ITableColumnAccessor,
|
||||||
|
ITableRow,
|
||||||
|
} from '@/interfaces';
|
||||||
|
import AgingSummaryTable from './AgingSummaryTable';
|
||||||
|
|
||||||
|
export default class APAgingSummaryTable extends AgingSummaryTable {
|
||||||
|
readonly report: IAPAgingSummaryData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
* @param {IARAgingSummaryData} data
|
||||||
|
* @param {IAgingSummaryQuery} query
|
||||||
|
* @param {any} i18n
|
||||||
|
*/
|
||||||
|
constructor(data: IAPAgingSummaryData, query: IAgingSummaryQuery, i18n: any) {
|
||||||
|
super(data, query, i18n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the contacts table rows.
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
get contactsRows(): ITableRow[] {
|
||||||
|
return this.contactsNodes(this.report.vendors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contact name node accessor.
|
||||||
|
* @returns {ITableColumnAccessor}
|
||||||
|
*/
|
||||||
|
get contactNameNodeAccessor(): ITableColumnAccessor {
|
||||||
|
return { key: 'vendor_name', accessor: 'vendorName' };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the contact name table column.
|
||||||
|
* @returns {ITableColumn}
|
||||||
|
*/
|
||||||
|
contactNameTableColumn = (): ITableColumn => {
|
||||||
|
return { label: 'Vendor name', key: 'vendor_name' };
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import { IARAgingSummaryQuery, IARAgingSummaryMeta } from '@/interfaces';
|
|||||||
import TenancyService from '@/services/Tenancy/TenancyService';
|
import TenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import ARAgingSummarySheet from './ARAgingSummarySheet';
|
import ARAgingSummarySheet from './ARAgingSummarySheet';
|
||||||
import { Tenant } from '@/system/models';
|
import { Tenant } from '@/system/models';
|
||||||
|
import ARAgingSummaryTable from './ARAgingSummaryTable';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class ARAgingSummaryService {
|
export default class ARAgingSummaryService {
|
||||||
@@ -89,12 +90,12 @@ export default class ARAgingSummaryService {
|
|||||||
};
|
};
|
||||||
// Retrieve all overdue sale invoices.
|
// Retrieve all overdue sale invoices.
|
||||||
const overdueSaleInvoices = await SaleInvoice.query()
|
const overdueSaleInvoices = await SaleInvoice.query()
|
||||||
.modify('dueInvoicesFromDate', filter.asDate)
|
.modify('overdueInvoicesFromDate', filter.asDate)
|
||||||
.onBuild(commonQuery);
|
.onBuild(commonQuery);
|
||||||
|
|
||||||
// Retrieve all due sale invoices.
|
// Retrieve all due sale invoices.
|
||||||
const currentInvoices = await SaleInvoice.query()
|
const currentInvoices = await SaleInvoice.query()
|
||||||
.modify('overdueInvoicesFromDate', filter.asDate)
|
.modify('dueInvoicesFromDate', filter.asDate)
|
||||||
.onBuild(commonQuery);
|
.onBuild(commonQuery);
|
||||||
|
|
||||||
// AR aging summary report instance.
|
// AR aging summary report instance.
|
||||||
@@ -117,4 +118,22 @@ export default class ARAgingSummaryService {
|
|||||||
meta: this.reportMetadata(tenantId),
|
meta: this.reportMetadata(tenantId),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param tenantId
|
||||||
|
* @param query
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async ARAgingSummaryTable(tenantId: number, query: IARAgingSummaryQuery) {
|
||||||
|
const report = await this.ARAgingSummary(tenantId, query);
|
||||||
|
const table = new ARAgingSummaryTable(report.data, query, {});
|
||||||
|
|
||||||
|
return {
|
||||||
|
columns: table.tableColumns(),
|
||||||
|
rows: table.tableRows(),
|
||||||
|
meta: report.meta,
|
||||||
|
query,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { groupBy, isEmpty, sum } from 'lodash';
|
import { Dictionary, groupBy, isEmpty, sum } from 'lodash';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import {
|
import {
|
||||||
ICustomer,
|
ICustomer,
|
||||||
@@ -54,7 +54,6 @@ export default class ARAgingSummarySheet extends AgingSummaryReport {
|
|||||||
currentSaleInvoices,
|
currentSaleInvoices,
|
||||||
'customerId'
|
'customerId'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initializes the aging periods.
|
// Initializes the aging periods.
|
||||||
this.agingPeriods = this.agingRangePeriods(
|
this.agingPeriods = this.agingRangePeriods(
|
||||||
this.query.asDate,
|
this.query.asDate,
|
||||||
@@ -189,7 +188,7 @@ export default class ARAgingSummarySheet extends AgingSummaryReport {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve AR aging summary report columns.
|
* Retrieve A/R aging summary report columns.
|
||||||
* @return {IARAgingSummaryColumns}
|
* @return {IARAgingSummaryColumns}
|
||||||
*/
|
*/
|
||||||
public reportColumns(): IARAgingSummaryColumns {
|
public reportColumns(): IARAgingSummaryColumns {
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import {
|
||||||
|
IARAgingSummaryData,
|
||||||
|
IAgingSummaryData,
|
||||||
|
IAgingSummaryQuery,
|
||||||
|
ITableColumnAccessor,
|
||||||
|
ITableRow,
|
||||||
|
} from '@/interfaces';
|
||||||
|
import AgingSummaryTable from './AgingSummaryTable';
|
||||||
|
|
||||||
|
export default class ARAgingSummaryTable extends AgingSummaryTable {
|
||||||
|
readonly report: IARAgingSummaryData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
* @param {IARAgingSummaryData} data
|
||||||
|
* @param {IAgingSummaryQuery} query
|
||||||
|
* @param {any} i18n
|
||||||
|
*/
|
||||||
|
constructor(data: IARAgingSummaryData, query: IAgingSummaryQuery, i18n: any) {
|
||||||
|
super(data, query, i18n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the contacts table rows.
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
get contactsRows(): ITableRow[] {
|
||||||
|
return this.contactsNodes(this.report.customers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contact name node accessor.
|
||||||
|
* @returns {ITableColumnAccessor}
|
||||||
|
*/
|
||||||
|
get contactNameNodeAccessor(): ITableColumnAccessor {
|
||||||
|
return { key: 'customer_name', accessor: 'customerName' };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
import * as R from 'ramda';
|
||||||
|
import {
|
||||||
|
IAgingPeriod,
|
||||||
|
IAgingSummaryContact,
|
||||||
|
IAgingSummaryData,
|
||||||
|
IAgingSummaryQuery,
|
||||||
|
IAgingSummaryTotal,
|
||||||
|
ITableColumn,
|
||||||
|
ITableColumnAccessor,
|
||||||
|
ITableRow,
|
||||||
|
} from '@/interfaces';
|
||||||
|
import { tableRowMapper } from '@/utils';
|
||||||
|
import AgingReport from './AgingReport';
|
||||||
|
import { AgingSummaryRowType } from './_constants';
|
||||||
|
|
||||||
|
export default abstract class AgingSummaryTable extends AgingReport {
|
||||||
|
protected readonly report: IAgingSummaryData;
|
||||||
|
protected readonly query: IAgingSummaryQuery;
|
||||||
|
protected readonly agingPeriods: IAgingPeriod[];
|
||||||
|
protected readonly i18n: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
* @param {IARAgingSummaryData} data
|
||||||
|
* @param {IAgingSummaryQuery} query
|
||||||
|
* @param {any} i18n
|
||||||
|
*/
|
||||||
|
constructor(data: IAgingSummaryData, query: IAgingSummaryQuery, i18n: any) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.report = data;
|
||||||
|
this.i18n = i18n;
|
||||||
|
this.query = query;
|
||||||
|
|
||||||
|
this.agingPeriods = this.agingRangePeriods(
|
||||||
|
this.query.asDate,
|
||||||
|
this.query.agingDaysBefore,
|
||||||
|
this.query.agingPeriods
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// # Accessors.
|
||||||
|
// -------------------------
|
||||||
|
/**
|
||||||
|
* Aging accessors of contact and total nodes.
|
||||||
|
* @param {IAgingSummaryContact | IAgingSummaryTotal} node
|
||||||
|
* @returns {ITableColumnAccessor[]}
|
||||||
|
*/
|
||||||
|
protected agingNodeAccessors = (
|
||||||
|
node: IAgingSummaryContact | IAgingSummaryTotal
|
||||||
|
): ITableColumnAccessor[] => {
|
||||||
|
return node.aging.map((aging, index) => ({
|
||||||
|
key: 'aging',
|
||||||
|
accessor: `aging[${index}].total.formattedAmount`,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contact name node accessor.
|
||||||
|
* @returns {ITableColumnAccessor}
|
||||||
|
*/
|
||||||
|
protected get contactNameNodeAccessor(): ITableColumnAccessor {
|
||||||
|
return { key: 'customer_name', accessor: 'customerName' };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the common columns for all report nodes.
|
||||||
|
* @param {IAgingSummaryContact}
|
||||||
|
* @returns {ITableColumnAccessor[]}
|
||||||
|
*/
|
||||||
|
protected contactNodeAccessors = (
|
||||||
|
node: IAgingSummaryContact
|
||||||
|
): ITableColumnAccessor[] => {
|
||||||
|
return R.compose(
|
||||||
|
R.concat([
|
||||||
|
this.contactNameNodeAccessor,
|
||||||
|
{ key: 'current', accessor: 'current.formattedAmount' },
|
||||||
|
...this.agingNodeAccessors(node),
|
||||||
|
{ key: 'total', accessor: 'total.formattedAmount' },
|
||||||
|
])
|
||||||
|
)([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the contact name table row.
|
||||||
|
* @param {IAgingSummaryContact} node -
|
||||||
|
* @return {ITableRow}
|
||||||
|
*/
|
||||||
|
protected contactNameNode = (node: IAgingSummaryContact): ITableRow => {
|
||||||
|
const columns = this.contactNodeAccessors(node);
|
||||||
|
const meta = {
|
||||||
|
rowTypes: [AgingSummaryRowType.Contact],
|
||||||
|
};
|
||||||
|
return tableRowMapper(node, columns, meta);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps the customers nodes to table rows.
|
||||||
|
* @param {IAgingSummaryContact[]} nodes
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
protected contactsNodes = (nodes: IAgingSummaryContact[]): ITableRow[] => {
|
||||||
|
return nodes.map(this.contactNameNode);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the common columns for all report nodes.
|
||||||
|
* @param {IAgingSummaryTotal}
|
||||||
|
* @returns {ITableColumnAccessor[]}
|
||||||
|
*/
|
||||||
|
protected totalNodeAccessors = (
|
||||||
|
node: IAgingSummaryTotal
|
||||||
|
): ITableColumnAccessor[] => {
|
||||||
|
return R.compose(
|
||||||
|
R.concat([
|
||||||
|
{ key: 'blank', value: '' },
|
||||||
|
{ key: 'current', accessor: 'current.formattedAmount' },
|
||||||
|
...this.agingNodeAccessors(node),
|
||||||
|
{ key: 'total', accessor: 'total.formattedAmount' },
|
||||||
|
])
|
||||||
|
)([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the total row of the given report total node.
|
||||||
|
* @param {IAgingSummaryTotal} node
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
protected totalNode = (node: IAgingSummaryTotal): ITableRow => {
|
||||||
|
const columns = this.totalNodeAccessors(node);
|
||||||
|
const meta = {
|
||||||
|
rowTypes: [AgingSummaryRowType.Total],
|
||||||
|
};
|
||||||
|
return tableRowMapper(node, columns, meta);
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// # Computed Rows.
|
||||||
|
// -------------------------
|
||||||
|
/**
|
||||||
|
* Retrieves the contacts table rows.
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
protected get contactsRows(): ITableRow[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table total row.
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
protected get totalRow(): ITableRow {
|
||||||
|
return this.totalNode(this.report.total);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the table rows.
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
public tableRows = (): ITableRow[] => {
|
||||||
|
return R.compose(R.concat(this.contactsRows), R.prepend(this.totalRow))([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// # Columns.
|
||||||
|
// -------------------------
|
||||||
|
/**
|
||||||
|
* Retrieves the aging table columns.
|
||||||
|
* @returns {ITableColumn[]}
|
||||||
|
*/
|
||||||
|
protected agingTableColumns = (): ITableColumn[] => {
|
||||||
|
return this.agingPeriods.map((agingPeriod) => {
|
||||||
|
return {
|
||||||
|
label: `${agingPeriod.beforeDays} - ${
|
||||||
|
agingPeriod.toDays || 'And Over'
|
||||||
|
}`,
|
||||||
|
key: 'aging_period',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the contact name table column.
|
||||||
|
* @returns {ITableColumn}
|
||||||
|
*/
|
||||||
|
protected contactNameTableColumn = (): ITableColumn => {
|
||||||
|
return { label: 'Customer name', key: 'customer_name' };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the report columns.
|
||||||
|
* @returns {ITableColumn}
|
||||||
|
*/
|
||||||
|
public tableColumns = (): ITableColumn[] => {
|
||||||
|
return [
|
||||||
|
this.contactNameTableColumn(),
|
||||||
|
{ label: 'Current', key: 'current' },
|
||||||
|
...this.agingTableColumns(),
|
||||||
|
{ label: 'Total', key: 'total' },
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export enum AgingSummaryRowType {
|
||||||
|
Contact = 'contact',
|
||||||
|
Total = 'total',
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Service, Inject } from 'typedi';
|
import { Service, Inject } from 'typedi';
|
||||||
import Knex from 'knex';
|
import { Knex } from 'knex';
|
||||||
|
import Bluebird from 'bluebird';
|
||||||
import { IVendorCreditAppliedBill } from '@/interfaces';
|
import { IVendorCreditAppliedBill } from '@/interfaces';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import Bluebird from 'bluebird';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class ApplyVendorCreditSyncBills {
|
export default class ApplyVendorCreditSyncBills {
|
||||||
@Inject()
|
@Inject()
|
||||||
tenancy: HasTenancyService;
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increment bills credited amount.
|
* Increment bills credited amount.
|
||||||
|
|||||||
Reference in New Issue
Block a user