2022-05-30 11:34:25 +00:00
|
|
|
import { Fyo, t } from 'fyo';
|
2022-05-18 07:04:33 +00:00
|
|
|
import { Action } from 'fyo/model/types';
|
2022-05-14 08:46:05 +00:00
|
|
|
import { ModelNameEnum } from 'models/types';
|
|
|
|
import { Report } from 'reports/Report';
|
|
|
|
import { GroupedMap, LedgerEntry, RawLedgerEntry } from 'reports/types';
|
|
|
|
import { QueryFilter } from 'utils/db/types';
|
2022-11-07 07:15:38 +00:00
|
|
|
import { safeParseFloat, safeParseInt } from 'utils/index';
|
2022-05-18 07:04:33 +00:00
|
|
|
import getCommonExportActions from './commonExporter';
|
2022-05-14 08:46:05 +00:00
|
|
|
|
|
|
|
type GroupByKey = 'account' | 'party' | 'referenceName';
|
|
|
|
|
|
|
|
export abstract class LedgerReport extends Report {
|
|
|
|
static title = t`General Ledger`;
|
|
|
|
static reportName = 'general-ledger';
|
|
|
|
|
|
|
|
_rawData: LedgerEntry[] = [];
|
2022-05-30 11:34:25 +00:00
|
|
|
shouldRefresh: boolean = false;
|
|
|
|
|
|
|
|
constructor(fyo: Fyo) {
|
|
|
|
super(fyo);
|
|
|
|
this._setObservers();
|
|
|
|
}
|
|
|
|
|
|
|
|
_setObservers() {
|
|
|
|
const listener = () => (this.shouldRefresh = true);
|
|
|
|
|
|
|
|
this.fyo.doc.observer.on(
|
|
|
|
`sync:${ModelNameEnum.AccountingLedgerEntry}`,
|
|
|
|
listener
|
|
|
|
);
|
|
|
|
|
|
|
|
this.fyo.doc.observer.on(
|
|
|
|
`delete:${ModelNameEnum.AccountingLedgerEntry}`,
|
|
|
|
listener
|
|
|
|
);
|
|
|
|
}
|
2022-05-14 08:46:05 +00:00
|
|
|
|
|
|
|
_getGroupByKey() {
|
|
|
|
let groupBy: GroupByKey = 'referenceName';
|
|
|
|
if (this.groupBy && this.groupBy !== 'none') {
|
|
|
|
groupBy = this.groupBy as GroupByKey;
|
|
|
|
}
|
|
|
|
return groupBy;
|
|
|
|
}
|
|
|
|
|
|
|
|
_getGroupedMap(sort: boolean, groupBy?: GroupByKey): GroupedMap {
|
|
|
|
groupBy ??= this._getGroupByKey();
|
|
|
|
/**
|
|
|
|
* Sort rows by ascending or descending
|
|
|
|
*/
|
|
|
|
if (sort) {
|
|
|
|
this._rawData.sort((a, b) => {
|
|
|
|
if (this.ascending) {
|
|
|
|
return +a.date! - +b.date!;
|
|
|
|
}
|
|
|
|
|
|
|
|
return +b.date! - +a.date!;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Map remembers the order of insertion
|
|
|
|
* ∴ presorting maintains grouping order
|
|
|
|
*/
|
|
|
|
const map: GroupedMap = new Map();
|
|
|
|
for (const entry of this._rawData) {
|
|
|
|
const groupingKey = entry[groupBy];
|
|
|
|
if (!map.has(groupingKey)) {
|
|
|
|
map.set(groupingKey, []);
|
|
|
|
}
|
|
|
|
|
|
|
|
map.get(groupingKey)!.push(entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
|
|
|
async _setRawData() {
|
|
|
|
const fields = [
|
|
|
|
'name',
|
|
|
|
'account',
|
|
|
|
'date',
|
|
|
|
'debit',
|
|
|
|
'credit',
|
|
|
|
'referenceType',
|
|
|
|
'referenceName',
|
|
|
|
'party',
|
|
|
|
'reverted',
|
|
|
|
'reverts',
|
|
|
|
];
|
|
|
|
|
|
|
|
const filters = await this._getQueryFilters();
|
|
|
|
const entries = (await this.fyo.db.getAllRaw(
|
|
|
|
ModelNameEnum.AccountingLedgerEntry,
|
|
|
|
{
|
|
|
|
fields,
|
|
|
|
filters,
|
2023-01-05 05:44:05 +00:00
|
|
|
orderBy: ['date', 'created'],
|
2022-05-14 08:46:05 +00:00
|
|
|
order: this.ascending ? 'asc' : 'desc',
|
|
|
|
}
|
|
|
|
)) as RawLedgerEntry[];
|
|
|
|
|
|
|
|
this._rawData = entries.map((entry) => {
|
|
|
|
return {
|
2022-11-07 07:15:38 +00:00
|
|
|
name: safeParseInt(entry.name),
|
2022-05-14 08:46:05 +00:00
|
|
|
account: entry.account,
|
|
|
|
date: new Date(entry.date),
|
2022-11-07 07:15:38 +00:00
|
|
|
debit: safeParseFloat(entry.debit),
|
|
|
|
credit: safeParseFloat(entry.credit),
|
2022-05-14 08:46:05 +00:00
|
|
|
balance: 0,
|
|
|
|
referenceType: entry.referenceType,
|
|
|
|
referenceName: entry.referenceName,
|
|
|
|
party: entry.party,
|
|
|
|
reverted: Boolean(entry.reverted),
|
|
|
|
reverts: entry.reverts,
|
|
|
|
} as LedgerEntry;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract _getQueryFilters(): Promise<QueryFilter>;
|
2022-05-18 07:04:33 +00:00
|
|
|
|
|
|
|
getActions(): Action[] {
|
|
|
|
return getCommonExportActions(this);
|
|
|
|
}
|
2022-05-14 08:46:05 +00:00
|
|
|
}
|