mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 05:40:31 +00:00
add server to monorepo.
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import { sumBy, chain, get, head } from 'lodash';
|
||||
import {
|
||||
IJournalEntry,
|
||||
IJournalPoster,
|
||||
IJournalReportEntriesGroup,
|
||||
IJournalReportQuery,
|
||||
IJournalReport,
|
||||
IContact,
|
||||
} from '@/interfaces';
|
||||
import FinancialSheet from '../FinancialSheet';
|
||||
|
||||
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,
|
||||
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(): IJournalReport {
|
||||
return this.entriesWalker(this.journal.entries);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import moment from 'moment';
|
||||
import { IJournalReportQuery, IJournalSheetMeta } from '@/interfaces';
|
||||
|
||||
import JournalSheet from './JournalSheet';
|
||||
import TenancyService from '@/services/Tenancy/TenancyService';
|
||||
import Journal from '@/services/Accounting/JournalPoster';
|
||||
import InventoryService from '@/services/Inventory/Inventory';
|
||||
import { parseBoolean, transformToMap } from 'utils';
|
||||
import { Tenant } from '@/system/models';
|
||||
|
||||
@Service()
|
||||
export default class JournalSheetService {
|
||||
@Inject()
|
||||
tenancy: TenancyService;
|
||||
|
||||
@Inject()
|
||||
inventoryService: InventoryService;
|
||||
|
||||
@Inject('logger')
|
||||
logger: any;
|
||||
|
||||
/**
|
||||
* Default journal sheet filter queyr.
|
||||
*/
|
||||
get defaultQuery() {
|
||||
return {
|
||||
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||
toDate: moment().endOf('year').format('YYYY-MM-DD'),
|
||||
fromRange: null,
|
||||
toRange: null,
|
||||
accountsIds: [],
|
||||
numberFormat: {
|
||||
noCents: false,
|
||||
divideOn1000: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the balance sheet meta.
|
||||
* @param {number} tenantId -
|
||||
* @returns {IBalanceSheetMeta}
|
||||
*/
|
||||
reportMetadata(tenantId: number): IJournalSheetMeta {
|
||||
const settings = this.tenancy.settings(tenantId);
|
||||
|
||||
const isCostComputeRunning =
|
||||
this.inventoryService.isItemsCostComputeRunning(tenantId);
|
||||
|
||||
const organizationName = settings.get({
|
||||
group: 'organization',
|
||||
key: 'name',
|
||||
});
|
||||
const baseCurrency = settings.get({
|
||||
group: 'organization',
|
||||
key: 'base_currency',
|
||||
});
|
||||
|
||||
return {
|
||||
isCostComputeRunning: parseBoolean(isCostComputeRunning, false),
|
||||
organizationName,
|
||||
baseCurrency,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Journal sheet.
|
||||
* @param {number} tenantId
|
||||
* @param {IJournalSheetFilterQuery} query
|
||||
*/
|
||||
async journalSheet(tenantId: number, query: IJournalReportQuery) {
|
||||
const i18n = this.tenancy.i18n(tenantId);
|
||||
const { accountRepository, transactionsRepository, contactRepository } =
|
||||
this.tenancy.repositories(tenantId);
|
||||
|
||||
const { AccountTransaction } = this.tenancy.models(tenantId);
|
||||
|
||||
const filter = {
|
||||
...this.defaultQuery,
|
||||
...query,
|
||||
};
|
||||
this.logger.info('[journal] trying to calculate the report.', {
|
||||
tenantId,
|
||||
filter,
|
||||
});
|
||||
|
||||
const tenant = await Tenant.query()
|
||||
.findById(tenantId)
|
||||
.withGraphFetched('metadata');
|
||||
|
||||
// Retrieve all accounts on the storage.
|
||||
const accountsGraph = await accountRepository.getDependencyGraph();
|
||||
|
||||
// Retrieve all contacts on the storage.
|
||||
const contacts = await contactRepository.all();
|
||||
const contactsByIdMap = transformToMap(contacts, 'id');
|
||||
|
||||
// Retrieve all journal transactions based on the given query.
|
||||
const transactions = await AccountTransaction.query().onBuild((query) => {
|
||||
if (filter.fromRange || filter.toRange) {
|
||||
query.modify('filterAmountRange', filter.fromRange, filter.toRange);
|
||||
}
|
||||
query.modify('filterDateRange', filter.fromDate, filter.toDate);
|
||||
query.orderBy(['date', 'createdAt', 'indexGroup', 'index']);
|
||||
|
||||
if (filter.transactionType) {
|
||||
query.where('reference_type', filter.transactionType);
|
||||
}
|
||||
if (filter.transactionType && filter.transactionId) {
|
||||
query.where('reference_id', filter.transactionId);
|
||||
}
|
||||
});
|
||||
// Transform the transactions array to journal collection.
|
||||
const transactionsJournal = Journal.fromTransactions(
|
||||
transactions,
|
||||
tenantId,
|
||||
accountsGraph
|
||||
);
|
||||
// Journal report instance.
|
||||
const journalSheetInstance = new JournalSheet(
|
||||
tenantId,
|
||||
filter,
|
||||
transactionsJournal,
|
||||
accountsGraph,
|
||||
contactsByIdMap,
|
||||
tenant.metadata.baseCurrency,
|
||||
i18n
|
||||
);
|
||||
// Retrieve journal report columns.
|
||||
const journalSheetData = journalSheetInstance.reportData();
|
||||
|
||||
return {
|
||||
data: journalSheetData,
|
||||
query: filter,
|
||||
meta: this.reportMetadata(tenantId),
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user