import { runQuery } from 'loot-core/src/client/query-helpers'; import { type useSpreadsheet } from 'loot-core/src/client/SpreadsheetProvider'; import { send } from 'loot-core/src/platform/client/fetch'; import * as monthUtils from 'loot-core/src/shared/months'; import { type GroupedEntity } from 'loot-core/src/types/models/reports'; import { categoryLists, type QueryDataEntity, ReportOptions, } from '../ReportOptions'; import { type createCustomSpreadsheetProps } from './custom-spreadsheet'; import { filterEmptyRows } from './filterEmptyRows'; import { makeQuery } from './makeQuery'; import { recalculate } from './recalculate'; export function createGroupedSpreadsheet({ startDate, endDate, interval, categories, conditions = [], conditionsOp, showEmpty, showOffBudget, showHiddenCategories, showUncategorized, balanceTypeOp, firstDayOfWeekIdx, }: createCustomSpreadsheetProps) { const [categoryList, categoryGroup] = categoryLists(categories); return async ( spreadsheet: ReturnType, setData: (data: GroupedEntity[]) => void, ) => { if (categoryList.length === 0) { return; } const { filters } = await send('make-filters-from-conditions', { conditions: conditions.filter(cond => !cond.customName), }); const conditionsOpKey = conditionsOp === 'or' ? '$or' : '$and'; let assets: QueryDataEntity[]; let debts: QueryDataEntity[]; [assets, debts] = await Promise.all([ runQuery( makeQuery( 'assets', startDate, endDate, interval, conditionsOpKey, filters, ), ).then(({ data }) => data), runQuery( makeQuery( 'debts', startDate, endDate, interval, conditionsOpKey, filters, ), ).then(({ data }) => data), ]); if (interval === 'Weekly') { debts = debts.map(d => { return { ...d, date: monthUtils.weekFromDate(d.date, firstDayOfWeekIdx), }; }); assets = assets.map(d => { return { ...d, date: monthUtils.weekFromDate(d.date, firstDayOfWeekIdx), }; }); } const intervals = interval === 'Weekly' ? monthUtils.weekRangeInclusive(startDate, endDate, firstDayOfWeekIdx) : monthUtils[ ReportOptions.intervalRange.get(interval) || 'rangeInclusive' ](startDate, endDate); const groupedData: GroupedEntity[] = categoryGroup.map( group => { const grouped = recalculate({ item: group, intervals, assets, debts, groupByLabel: 'categoryGroup', showOffBudget, showHiddenCategories, showUncategorized, startDate, endDate, }); const stackedCategories = group.categories && group.categories.map(item => { const calc = recalculate({ item, intervals, assets, debts, groupByLabel: 'category', showOffBudget, showHiddenCategories, showUncategorized, startDate, endDate, }); return { ...calc }; }); return { ...grouped, categories: stackedCategories && stackedCategories.filter(i => filterEmptyRows({ showEmpty, data: i, balanceTypeOp }), ), }; }, [startDate, endDate], ); setData( groupedData.filter(i => filterEmptyRows({ showEmpty, data: i, balanceTypeOp }), ), ); }; }