Files
bigcapital/packages/server/src/services/FinancialStatements/JournalSheet/JournalSheet.ts
2024-01-07 18:48:14 +02:00

142 lines
3.7 KiB
TypeScript

import { sumBy, chain, get, head } from 'lodash';
import {
IJournalEntry,
IJournalPoster,
IJournalReportEntriesGroup,
IJournalReportQuery,
IJournalReport,
IContact,
IJournalTableData,
} from '@/interfaces';
import FinancialSheet from '../FinancialSheet';
import moment from 'moment';
export default class JournalSheet extends FinancialSheet {
readonly tenantId: number;
readonly journal: IJournalPoster;
readonly query: IJournalReportQuery;
readonly baseCurrency: string;
readonly contactsById: Map<number | string, IContact>;
/**
* Constructor method.
* @param {number} tenantId
* @param {IJournalPoster} journal
*/
constructor(
tenantId: number,
query: IJournalReportQuery,
journal: IJournalPoster,
accountsGraph: any,
contactsById: Map<number | string, IContact>,
baseCurrency: string,
i18n
) {
super();
this.tenantId = tenantId;
this.journal = journal;
this.query = query;
this.numberFormat = this.query.numberFormat;
this.accountsGraph = accountsGraph;
this.contactsById = contactsById;
this.baseCurrency = baseCurrency;
this.i18n = i18n;
}
/**
* Entry mapper.
* @param {IJournalEntry} entry
*/
entryMapper(entry: IJournalEntry) {
const account = this.accountsGraph.getNodeData(entry.accountId);
const contact = this.contactsById.get(entry.contactId);
return {
entryId: entry.id,
index: entry.index,
note: entry.note,
contactName: get(contact, 'displayName'),
contactType: get(contact, 'contactService'),
accountName: account.name,
accountCode: account.code,
transactionNumber: entry.transactionNumber,
currencyCode: this.baseCurrency,
formattedCredit: this.formatNumber(entry.credit),
formattedDebit: this.formatNumber(entry.debit),
credit: entry.credit,
debit: entry.debit,
createdAt: entry.createdAt,
};
}
/**
* Mappes the journal entries.
* @param {IJournalEntry[]} entries -
*/
entriesMapper(entries: IJournalEntry[]) {
return entries.map(this.entryMapper.bind(this));
}
/**
* Mapping journal entries groups.
* @param {IJournalEntry[]} entriesGroup -
* @param {string} key -
* @return {IJournalReportEntriesGroup}
*/
entriesGroupsMapper(
entriesGroup: IJournalEntry[],
groupEntry: IJournalEntry
): IJournalReportEntriesGroup {
const totalCredit = sumBy(entriesGroup, 'credit');
const totalDebit = sumBy(entriesGroup, 'debit');
return {
date: groupEntry.date,
dateFormatted: moment(groupEntry.date).format('YYYY MMM DD'),
referenceType: groupEntry.referenceType,
referenceId: groupEntry.referenceId,
referenceTypeFormatted: this.i18n.__(groupEntry.referenceTypeFormatted),
entries: this.entriesMapper(entriesGroup),
currencyCode: this.baseCurrency,
credit: totalCredit,
debit: totalDebit,
formattedCredit: this.formatTotalNumber(totalCredit),
formattedDebit: this.formatTotalNumber(totalDebit),
};
}
/**
* Mapping the journal entries to entries groups.
* @param {IJournalEntry[]} entries
* @return {IJournalReportEntriesGroup[]}
*/
entriesWalker(entries: IJournalEntry[]): IJournalReportEntriesGroup[] {
return chain(entries)
.groupBy((entry) => `${entry.referenceId}-${entry.referenceType}`)
.map((entriesGroup: IJournalEntry[], key: string) => {
const headEntry = head(entriesGroup);
return this.entriesGroupsMapper(entriesGroup, headEntry);
})
.value();
}
/**
* Retrieve journal report.
* @return {IJournalReport}
*/
reportData(): IJournalTableData {
return this.entriesWalker(this.journal.entries);
}
}