mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 12:50:38 +00:00
feat: always show some sections in balance sheet.
This commit is contained in:
@@ -324,6 +324,7 @@ export default class JournalPoster implements IJournalPoster {
|
||||
transactions.forEach((transaction) => {
|
||||
this.entries.push({
|
||||
...transaction,
|
||||
referenceTypeFormatted: transaction.referenceTypeFormatted,
|
||||
account: transaction.accountId,
|
||||
accountNormal: get(transaction, 'account.type.normal'),
|
||||
});
|
||||
@@ -417,7 +418,7 @@ export default class JournalPoster implements IJournalPoster {
|
||||
* @param {Number} account -
|
||||
* @param {Date|String} closingDate -
|
||||
*/
|
||||
getTrialBalance(accountId, closingDate, dateType) {
|
||||
getTrialBalance(accountId, closingDate) {
|
||||
const momentClosingDate = moment(closingDate);
|
||||
const result = {
|
||||
credit: 0,
|
||||
@@ -426,8 +427,8 @@ export default class JournalPoster implements IJournalPoster {
|
||||
};
|
||||
this.entries.forEach((entry) => {
|
||||
if (
|
||||
(!momentClosingDate.isAfter(entry.date, dateType) &&
|
||||
!momentClosingDate.isSame(entry.date, dateType)) ||
|
||||
(!momentClosingDate.isAfter(entry.date, 'day') &&
|
||||
!momentClosingDate.isSame(entry.date, 'day')) ||
|
||||
(entry.account !== accountId && accountId)
|
||||
) {
|
||||
return;
|
||||
@@ -478,8 +479,8 @@ export default class JournalPoster implements IJournalPoster {
|
||||
accountId: number,
|
||||
contactId: number,
|
||||
contactType: string,
|
||||
closingDate: Date|string,
|
||||
openingDate: Date|string,
|
||||
closingDate?: Date|string,
|
||||
openingDate?: Date|string,
|
||||
) {
|
||||
const momentClosingDate = moment(closingDate);
|
||||
const momentOpeningDate = moment(openingDate);
|
||||
|
||||
@@ -85,7 +85,7 @@ export default class BalanceSheetStatement extends FinancialSheet {
|
||||
* @return {IBalanceSheetAccountTotal[]}
|
||||
*/
|
||||
private getSectionTotalPeriods(
|
||||
sections: Array<IBalanceSheetAccount|IBalanceSheetSection>
|
||||
sections: Array<IBalanceSheetAccount | IBalanceSheetSection>
|
||||
): IBalanceSheetAccountTotal[] {
|
||||
return this.dateRangeSet.map((date, index) => {
|
||||
const amount = sumBy(sections, `totalPeriods[${index}].amount`);
|
||||
@@ -203,8 +203,8 @@ export default class BalanceSheetStatement extends FinancialSheet {
|
||||
|
||||
/**
|
||||
* Mappes the structure sections.
|
||||
* @param {IBalanceSheetStructureSection} structure
|
||||
* @param {IAccount} accounts
|
||||
* @param {IBalanceSheetStructureSection} structure
|
||||
* @param {IAccount} accounts
|
||||
*/
|
||||
private structureSectionMapper(
|
||||
structure: IBalanceSheetStructureSection,
|
||||
@@ -238,12 +238,12 @@ export default class BalanceSheetStatement extends FinancialSheet {
|
||||
name: structure.name,
|
||||
sectionType: structure.sectionType,
|
||||
type: structure.type,
|
||||
...(structure.type === 'accounts_section')
|
||||
...(structure.type === 'accounts_section'
|
||||
? this.structureRelatedAccountsMapper(
|
||||
structure._accountsTypesRelated,
|
||||
structure.accountsTypesRelated,
|
||||
accounts
|
||||
)
|
||||
: this.structureSectionMapper(structure, accounts),
|
||||
: this.structureSectionMapper(structure, accounts)),
|
||||
};
|
||||
return result;
|
||||
}
|
||||
@@ -259,13 +259,30 @@ export default class BalanceSheetStatement extends FinancialSheet {
|
||||
): IBalanceSheetSection[] {
|
||||
return (
|
||||
reportStructure
|
||||
.map((structure: IBalanceSheetStructureSection) =>
|
||||
this.balanceSheetStructureMapper(structure, balanceSheetAccounts)
|
||||
)
|
||||
// Filter the structure sections that have no children.
|
||||
.map((structure: IBalanceSheetStructureSection) => {
|
||||
const sheetSection = this.balanceSheetStructureMapper(
|
||||
structure,
|
||||
balanceSheetAccounts
|
||||
);
|
||||
return [sheetSection, structure];
|
||||
})
|
||||
// Filter the structure sections that have no children and not always show.
|
||||
.filter(
|
||||
(structure: IBalanceSheetSection) =>
|
||||
structure.children.length > 0 || structure._forceShow
|
||||
([sheetSection, structure]: [
|
||||
IBalanceSheetSection,
|
||||
IBalanceSheetStructureSection
|
||||
]) => {
|
||||
return sheetSection.children.length > 0 || structure.alwaysShow;
|
||||
}
|
||||
)
|
||||
// Mappes the balance sheet scetions only
|
||||
.map(
|
||||
([sheetSection, structure]: [
|
||||
IBalanceSheetSection,
|
||||
IBalanceSheetStructureSection
|
||||
]) => {
|
||||
return sheetSection;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -295,6 +312,10 @@ export default class BalanceSheetStatement extends FinancialSheet {
|
||||
* @return {IBalanceSheetSection[]}
|
||||
*/
|
||||
public reportData(): IBalanceSheetSection[] {
|
||||
// Returns nothing if there is no entries in the journal between the given period.
|
||||
if (this.journalFinancial.entries.length === 0) {
|
||||
return [];
|
||||
}
|
||||
return this.balanceSheetStructureWalker(
|
||||
BalanceSheetStructure,
|
||||
this.accounts
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { sumBy, chain } from 'lodash';
|
||||
import { sumBy, chain, omit } from 'lodash';
|
||||
import {
|
||||
IJournalEntry,
|
||||
IJournalPoster,
|
||||
IJournalReportEntriesGroup,
|
||||
IJournalReportQuery,
|
||||
IJournalReport
|
||||
} from "interfaces";
|
||||
import FinancialSheet from "../FinancialSheet";
|
||||
IJournalReport,
|
||||
} from 'interfaces';
|
||||
import FinancialSheet from '../FinancialSheet';
|
||||
import { AccountTransaction } from 'models';
|
||||
|
||||
export default class JournalSheet extends FinancialSheet {
|
||||
tenantId: number;
|
||||
@@ -16,14 +17,14 @@ export default class JournalSheet extends FinancialSheet {
|
||||
|
||||
/**
|
||||
* Constructor method.
|
||||
* @param {number} tenantId
|
||||
* @param {IJournalPoster} journal
|
||||
* @param {number} tenantId
|
||||
* @param {IJournalPoster} journal
|
||||
*/
|
||||
constructor(
|
||||
tenantId: number,
|
||||
query: IJournalReportQuery,
|
||||
journal: IJournalPoster,
|
||||
baseCurrency: string,
|
||||
baseCurrency: string
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -34,23 +35,38 @@ export default class JournalSheet extends FinancialSheet {
|
||||
this.baseCurrency = baseCurrency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mappes the journal entries.
|
||||
* @param {IJournalEntry[]} entries -
|
||||
*/
|
||||
entriesMapper(
|
||||
entries: IJournalEntry[],
|
||||
) {
|
||||
return entries.map((entry: IJournalEntry) => {
|
||||
return {
|
||||
...omit(entry, 'account'),
|
||||
currencyCode: this.baseCurrency,
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping journal entries groups.
|
||||
* @param {IJournalEntry[]} entriesGroup -
|
||||
* @param {string} key -
|
||||
* @return {IJournalReportEntriesGroup}
|
||||
*/
|
||||
entriesGroupMapper(
|
||||
entriesGroupsMapper(
|
||||
entriesGroup: IJournalEntry[],
|
||||
key: string,
|
||||
key: string
|
||||
): IJournalReportEntriesGroup {
|
||||
const totalCredit = sumBy(entriesGroup, 'credit');
|
||||
const totalDebit = sumBy(entriesGroup, 'debit');
|
||||
|
||||
return {
|
||||
id: key,
|
||||
entries: entriesGroup,
|
||||
|
||||
entries: this.entriesMapper(entriesGroup),
|
||||
|
||||
currencyCode: this.baseCurrency,
|
||||
|
||||
credit: totalCredit,
|
||||
@@ -63,16 +79,15 @@ export default class JournalSheet extends FinancialSheet {
|
||||
|
||||
/**
|
||||
* Mapping the journal entries to entries groups.
|
||||
* @param {IJournalEntry[]} entries
|
||||
* @param {IJournalEntry[]} entries
|
||||
* @return {IJournalReportEntriesGroup[]}
|
||||
*/
|
||||
entriesWalker(entries: IJournalEntry[]): IJournalReportEntriesGroup[] {
|
||||
return chain(entries)
|
||||
.groupBy((entry) => `${entry.referenceId}-${entry.referenceType}`)
|
||||
.map((
|
||||
entriesGroup: IJournalEntry[],
|
||||
key: string
|
||||
) => this.entriesGroupMapper(entriesGroup, key))
|
||||
.map((entriesGroup: IJournalEntry[], key: string) =>
|
||||
this.entriesGroupsMapper(entriesGroup, key)
|
||||
)
|
||||
.value();
|
||||
}
|
||||
|
||||
@@ -83,4 +98,4 @@ export default class JournalSheet extends FinancialSheet {
|
||||
reportData(): IJournalReport {
|
||||
return this.entriesWalker(this.journal.entries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
ITrialBalanceSheetQuery,
|
||||
ITrialBalanceAccount,
|
||||
@@ -8,7 +7,7 @@ import {
|
||||
import FinancialSheet from '../FinancialSheet';
|
||||
import { flatToNestedArray } from 'utils';
|
||||
|
||||
export default class TrialBalanceSheet extends FinancialSheet{
|
||||
export default class TrialBalanceSheet extends FinancialSheet {
|
||||
tenantId: number;
|
||||
query: ITrialBalanceSheetQuery;
|
||||
accounts: IAccount & { type: IAccountType }[];
|
||||
@@ -17,17 +16,17 @@ export default class TrialBalanceSheet extends FinancialSheet{
|
||||
|
||||
/**
|
||||
* Constructor method.
|
||||
* @param {number} tenantId
|
||||
* @param {ITrialBalanceSheetQuery} query
|
||||
* @param {IAccount[]} accounts
|
||||
* @param journalFinancial
|
||||
* @param {number} tenantId
|
||||
* @param {ITrialBalanceSheetQuery} query
|
||||
* @param {IAccount[]} accounts
|
||||
* @param journalFinancial
|
||||
*/
|
||||
constructor(
|
||||
tenantId: number,
|
||||
query: ITrialBalanceSheetQuery,
|
||||
accounts: IAccount & { type: IAccountType }[],
|
||||
journalFinancial: any,
|
||||
baseCurrency: string,
|
||||
baseCurrency: string
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -42,13 +41,15 @@ export default class TrialBalanceSheet extends FinancialSheet{
|
||||
|
||||
/**
|
||||
* Account mapper.
|
||||
* @param {IAccount} account
|
||||
* @param {IAccount} account
|
||||
*/
|
||||
private accountMapper(account: IAccount & { type: IAccountType }): ITrialBalanceAccount {
|
||||
private accountMapper(
|
||||
account: IAccount & { type: IAccountType }
|
||||
): ITrialBalanceAccount {
|
||||
const trial = this.journalFinancial.getTrialBalanceWithDepands(account.id);
|
||||
|
||||
// Retrieve all entries that associated to the given account.
|
||||
const entries = this.journalFinancial.getAccountEntries(account.id)
|
||||
const entries = this.journalFinancial.getAccountEntries(account.id);
|
||||
|
||||
return {
|
||||
id: account.id,
|
||||
@@ -71,29 +72,35 @@ export default class TrialBalanceSheet extends FinancialSheet{
|
||||
|
||||
/**
|
||||
* Accounts walker.
|
||||
* @param {IAccount[]} accounts
|
||||
* @param {IAccount[]} accounts
|
||||
*/
|
||||
private accountsWalker(
|
||||
accounts: IAccount & { type: IAccountType }[]
|
||||
): ITrialBalanceAccount[] {
|
||||
const flattenAccounts = accounts
|
||||
// Mapping the trial balance accounts sections.
|
||||
.map((account: IAccount & { type: IAccountType }) => this.accountMapper(account))
|
||||
|
||||
.map((account: IAccount & { type: IAccountType }) =>
|
||||
this.accountMapper(account)
|
||||
)
|
||||
// Filter accounts that have no transaction when `noneTransactions` is on.
|
||||
.filter((trialAccount: ITrialBalanceAccount): boolean =>
|
||||
!(!trialAccount.hasTransactions && this.query.noneTransactions),
|
||||
.filter(
|
||||
(trialAccount: ITrialBalanceAccount): boolean =>
|
||||
!(!trialAccount.hasTransactions && this.query.noneTransactions)
|
||||
)
|
||||
// Filter accounts that have zero total amount when `noneZero` is on.
|
||||
.filter(
|
||||
(trialAccount: ITrialBalanceAccount): boolean =>
|
||||
!(trialAccount.credit === 0 && trialAccount.debit === 0 && this.query.noneZero)
|
||||
);
|
||||
|
||||
return flatToNestedArray(
|
||||
flattenAccounts,
|
||||
{ id: 'id', parentId: 'parentAccountId' },
|
||||
);
|
||||
!(
|
||||
trialAccount.credit === 0 &&
|
||||
trialAccount.debit === 0 &&
|
||||
this.query.noneZero
|
||||
)
|
||||
);
|
||||
|
||||
return flatToNestedArray(flattenAccounts, {
|
||||
id: 'id',
|
||||
parentId: 'parentAccountId',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,4 +109,4 @@ export default class TrialBalanceSheet extends FinancialSheet{
|
||||
public reportData() {
|
||||
return this.accountsWalker(this.accounts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Service, Inject } from "typedi";
|
||||
import { Service, Inject } from 'typedi';
|
||||
import moment from 'moment';
|
||||
import TenancyService from 'services/Tenancy/TenancyService';
|
||||
import { ITrialBalanceSheetQuery, ITrialBalanceStatement } from 'interfaces';
|
||||
import TrialBalanceSheet from "./TrialBalanceSheet";
|
||||
import TrialBalanceSheet from './TrialBalanceSheet';
|
||||
import Journal from 'services/Accounting/JournalPoster';
|
||||
|
||||
@Service()
|
||||
export default class TrialBalanceSheetService {
|
||||
|
||||
@Inject()
|
||||
tenancy: TenancyService;
|
||||
|
||||
@@ -36,16 +35,15 @@ export default class TrialBalanceSheetService {
|
||||
/**
|
||||
* Retrieve trial balance sheet statement.
|
||||
* -------------
|
||||
* @param {number} tenantId
|
||||
* @param {IBalanceSheetQuery} query
|
||||
*
|
||||
* @param {number} tenantId
|
||||
* @param {IBalanceSheetQuery} query
|
||||
*
|
||||
* @return {IBalanceSheetStatement}
|
||||
*/
|
||||
public async trialBalanceSheet(
|
||||
tenantId: number,
|
||||
query: ITrialBalanceSheetQuery,
|
||||
query: ITrialBalanceSheetQuery
|
||||
): Promise<ITrialBalanceStatement> {
|
||||
|
||||
const filter = {
|
||||
...this.defaultQuery,
|
||||
...query,
|
||||
@@ -57,10 +55,15 @@ export default class TrialBalanceSheetService {
|
||||
|
||||
// Settings tenant service.
|
||||
const settings = this.tenancy.settings(tenantId);
|
||||
const baseCurrency = settings.get({ group: 'organization', key: 'base_currency' });
|
||||
|
||||
this.logger.info('[trial_balance_sheet] trying to calcualte the report.', { tenantId, filter });
|
||||
const baseCurrency = settings.get({
|
||||
group: 'organization',
|
||||
key: 'base_currency',
|
||||
});
|
||||
|
||||
this.logger.info('[trial_balance_sheet] trying to calcualte the report.', {
|
||||
tenantId,
|
||||
filter,
|
||||
});
|
||||
// Retrieve all accounts on the storage.
|
||||
const accounts = await accountRepository.all('type');
|
||||
const accountsGraph = await accountRepository.getDependencyGraph();
|
||||
@@ -72,8 +75,11 @@ export default class TrialBalanceSheetService {
|
||||
sumationCreditDebit: true,
|
||||
});
|
||||
// Transform transactions array to journal collection.
|
||||
const transactionsJournal = Journal.fromTransactions(transactions, tenantId, accountsGraph);
|
||||
|
||||
const transactionsJournal = Journal.fromTransactions(
|
||||
transactions,
|
||||
tenantId,
|
||||
accountsGraph
|
||||
);
|
||||
// Trial balance report instance.
|
||||
const trialBalanceInstance = new TrialBalanceSheet(
|
||||
tenantId,
|
||||
@@ -88,6 +94,6 @@ export default class TrialBalanceSheetService {
|
||||
return {
|
||||
data: trialBalanceSheetData,
|
||||
query: filter,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user