Files
bigcapital/packages/server/src/services/FinancialStatements/CustomerBalanceSummary/CustomerBalanceSummaryService.ts
2024-10-26 12:39:48 +02:00

128 lines
3.5 KiB
TypeScript

import { Inject, Service } from 'typedi';
import moment from 'moment';
import * as R from 'ramda';
import {
ICustomerBalanceSummaryService,
ICustomerBalanceSummaryQuery,
ICustomerBalanceSummaryStatement,
ICustomer,
ILedgerEntry,
} from '@/interfaces';
import { CustomerBalanceSummaryReport } from './CustomerBalanceSummary';
import Ledger from '@/services/Accounting/Ledger';
import CustomerBalanceSummaryRepository from './CustomerBalanceSummaryRepository';
import { Tenant } from '@/system/models';
import { CustomerBalanceSummaryMeta } from './CustomerBalanceSummaryMeta';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import events from '@/subscribers/events';
@Service()
export class CustomerBalanceSummaryService
implements ICustomerBalanceSummaryService
{
@Inject()
private reportRepository: CustomerBalanceSummaryRepository;
@Inject()
private customerBalanceSummaryMeta: CustomerBalanceSummaryMeta;
@Inject()
private eventPublisher: EventPublisher;
/**
* Defaults balance sheet filter query.
* @return {ICustomerBalanceSummaryQuery}
*/
private get defaultQuery(): ICustomerBalanceSummaryQuery {
return {
asDate: moment().format('YYYY-MM-DD'),
numberFormat: {
precision: 2,
divideOn1000: false,
showZero: false,
formatMoney: 'total',
negativeFormat: 'mines',
},
percentageColumn: false,
noneZero: false,
noneTransactions: true,
};
}
/**
* Retrieve the customers ledger entries mapped from accounts transactions.
* @param {number} tenantId
* @param {Date|string} asDate
* @returns {Promise<ILedgerEntry[]>}
*/
private async getReportCustomersEntries(
tenantId: number,
asDate: Date | string
): Promise<ILedgerEntry[]> {
const transactions = await this.reportRepository.getCustomersTransactions(
tenantId,
asDate
);
const commonProps = { accountNormal: 'debit', date: asDate };
return R.map(R.merge(commonProps))(transactions);
}
/**
* Retrieve the statment of customer balance summary report.
* @param {number} tenantId
* @param {ICustomerBalanceSummaryQuery} query
* @return {Promise<ICustomerBalanceSummaryStatement>}
*/
public async customerBalanceSummary(
tenantId: number,
query: ICustomerBalanceSummaryQuery
): Promise<ICustomerBalanceSummaryStatement> {
const tenant = await Tenant.query()
.findById(tenantId)
.withGraphFetched('metadata');
// Merges the default query and request query.
const filter = { ...this.defaultQuery, ...query };
// Retrieve the customers list ordered by the display name.
const customers = await this.reportRepository.getCustomers(
tenantId,
query.customersIds
);
// Retrieve the customers debit/credit totals.
const customersEntries = await this.getReportCustomersEntries(
tenantId,
filter.asDate
);
// Ledger query.
const ledger = new Ledger(customersEntries);
// Report instance.
const report = new CustomerBalanceSummaryReport(
ledger,
customers,
filter,
tenant.metadata.baseCurrency
);
// Retrieve the customer balance summary meta.
const meta = await this.customerBalanceSummaryMeta.meta(tenantId, filter);
// Triggers `onCustomerBalanceSummaryViewed` event.
await this.eventPublisher.emitAsync(
events.reports.onCustomerBalanceSummaryViewed,
{
tenant,
query,
}
);
return {
data: report.reportData(),
query: filter,
meta,
};
}
}