mirror of
https://github.com/actualbudget/actual.git
synced 2026-04-28 18:40:34 -05:00
Add daily and weekly to custom reports interval list (#2483)
* Button changes and time filters * rename on dashboard * notes * fix time filters * Sort Categories * Page title * category sort order * move button * featureflag * Highlight report name * sankey fix * VRT * remove doubled element * adjust to match master * add Year * notes * lint fix * update names * IntervalsUpdates * fixing bugs * ts updates * lint fix * merge fixes * notes * simplify lookups * Add Daily and Weekly * notes * notes * merge fix * TS fix * Change week start date based on user prefs * fix weeks * fix averages * remove $week * remove date-week * TS fixes
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
// @ts-strict-ignore
|
||||
import React, { useRef } from 'react';
|
||||
|
||||
import * as monthUtils from 'loot-core/src/shared/months';
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
|
||||
import { type CSSProperties } from '../../style';
|
||||
@@ -20,8 +19,6 @@ import { ReportTableTotals } from './graphs/tableGraph/ReportTableTotals';
|
||||
import { ReportOptions } from './ReportOptions';
|
||||
|
||||
type ChooseGraphProps = {
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
data: GroupedEntity;
|
||||
mode: string;
|
||||
graphType: string;
|
||||
@@ -34,11 +31,10 @@ type ChooseGraphProps = {
|
||||
style?: CSSProperties;
|
||||
showHiddenCategories?: boolean;
|
||||
showOffBudget?: boolean;
|
||||
intervalsCount?: number;
|
||||
};
|
||||
|
||||
export function ChooseGraph({
|
||||
startDate,
|
||||
endDate,
|
||||
data,
|
||||
mode,
|
||||
graphType,
|
||||
@@ -51,8 +47,8 @@ export function ChooseGraph({
|
||||
style,
|
||||
showHiddenCategories,
|
||||
showOffBudget,
|
||||
intervalsCount,
|
||||
}: ChooseGraphProps) {
|
||||
const intervals: string[] = monthUtils.rangeInclusive(startDate, endDate);
|
||||
const graphStyle = compact ? { ...style } : { flexGrow: 1 };
|
||||
const balanceTypeOp = ReportOptions.balanceTypeMap.get(balanceType);
|
||||
const groupByData =
|
||||
@@ -166,7 +162,7 @@ export function ChooseGraph({
|
||||
groupBy={groupBy}
|
||||
data={data[groupByData]}
|
||||
mode={mode}
|
||||
intervalsCount={intervals.length}
|
||||
intervalsCount={intervalsCount}
|
||||
compact={compact}
|
||||
style={rowStyle}
|
||||
compactStyle={compactStyle}
|
||||
@@ -177,7 +173,7 @@ export function ChooseGraph({
|
||||
data={data}
|
||||
mode={mode}
|
||||
balanceTypeOp={balanceTypeOp}
|
||||
intervalsCount={intervals.length}
|
||||
intervalsCount={intervalsCount}
|
||||
compact={compact}
|
||||
style={rowStyle}
|
||||
compactStyle={compactStyle}
|
||||
|
||||
@@ -45,24 +45,106 @@ const groupByOptions = [
|
||||
];
|
||||
|
||||
const dateRangeOptions = [
|
||||
{ description: 'This month', name: 0, Yearly: false, Monthly: true },
|
||||
{ description: 'Last month', name: 1, Yearly: false, Monthly: true },
|
||||
{ description: 'Last 3 months', name: 2, Yearly: false, Monthly: true },
|
||||
{ description: 'Last 6 months', name: 5, Yearly: false, Monthly: true },
|
||||
{ description: 'Last 12 months', name: 11, Yearly: false, Monthly: true },
|
||||
{
|
||||
description: 'This week',
|
||||
type: 'Weeks',
|
||||
name: 0,
|
||||
Yearly: false,
|
||||
Monthly: false,
|
||||
Daily: true,
|
||||
Weekly: true,
|
||||
},
|
||||
{
|
||||
description: 'Last week',
|
||||
type: 'Weeks',
|
||||
name: 1,
|
||||
Yearly: false,
|
||||
Monthly: false,
|
||||
Daily: true,
|
||||
Weekly: true,
|
||||
},
|
||||
{
|
||||
description: 'This month',
|
||||
type: 'Months',
|
||||
name: 0,
|
||||
Yearly: false,
|
||||
Monthly: true,
|
||||
Daily: true,
|
||||
Weekly: true,
|
||||
},
|
||||
{
|
||||
description: 'Last month',
|
||||
type: 'Months',
|
||||
name: 1,
|
||||
Yearly: false,
|
||||
Monthly: true,
|
||||
Daily: true,
|
||||
Weekly: true,
|
||||
},
|
||||
{
|
||||
description: 'Last 3 months',
|
||||
type: 'Months',
|
||||
name: 2,
|
||||
Yearly: false,
|
||||
Monthly: true,
|
||||
Daily: true,
|
||||
Weekly: true,
|
||||
},
|
||||
{
|
||||
description: 'Last 6 months',
|
||||
type: 'Months',
|
||||
name: 5,
|
||||
Yearly: false,
|
||||
Monthly: true,
|
||||
Daily: false,
|
||||
},
|
||||
{
|
||||
description: 'Last 12 months',
|
||||
type: 'Months',
|
||||
name: 11,
|
||||
Yearly: false,
|
||||
Monthly: true,
|
||||
Daily: false,
|
||||
},
|
||||
{
|
||||
description: 'Year to date',
|
||||
name: 'yearToDate',
|
||||
Yearly: true,
|
||||
Monthly: true,
|
||||
Daily: true,
|
||||
Weekly: true,
|
||||
},
|
||||
{
|
||||
description: 'Last year',
|
||||
name: 'lastYear',
|
||||
Yearly: true,
|
||||
Monthly: true,
|
||||
Daily: true,
|
||||
Weekly: true,
|
||||
},
|
||||
{
|
||||
description: 'All time',
|
||||
name: 'allTime',
|
||||
Yearly: true,
|
||||
Monthly: true,
|
||||
Daily: true,
|
||||
Weekly: true,
|
||||
},
|
||||
{ description: 'Last year', name: 'lastYear', Yearly: true, Monthly: true },
|
||||
{ description: 'All time', name: 'allMonths', Yearly: true, Monthly: true },
|
||||
];
|
||||
|
||||
const intervalOptions = [
|
||||
//{ value: 1, description: 'Daily', name: 'Day'},
|
||||
//{ value: 2, description: 'Weekly', name: 'Week'},
|
||||
{
|
||||
description: 'Daily',
|
||||
name: 'Day',
|
||||
format: 'yyyy-MM-dd',
|
||||
range: 'dayRangeInclusive',
|
||||
},
|
||||
{
|
||||
description: 'Weekly',
|
||||
name: 'Week',
|
||||
format: 'yyyy-MM-dd',
|
||||
range: 'weekRangeInclusive',
|
||||
},
|
||||
//{ value: 3, description: 'Fortnightly', name: 3},
|
||||
{
|
||||
description: 'Monthly',
|
||||
@@ -88,6 +170,9 @@ export const ReportOptions = {
|
||||
dateRangeMap: new Map(
|
||||
dateRangeOptions.map(item => [item.description, item.name]),
|
||||
),
|
||||
dateRangeType: new Map(
|
||||
dateRangeOptions.map(item => [item.description, item.type]),
|
||||
),
|
||||
interval: intervalOptions,
|
||||
intervalMap: new Map(
|
||||
intervalOptions.map(item => [item.description, item.name]),
|
||||
|
||||
@@ -11,6 +11,7 @@ import { View } from '../common/View';
|
||||
import { Tooltip } from '../tooltips';
|
||||
|
||||
import { CategorySelector } from './CategorySelector';
|
||||
import { defaultsList } from './disabledList';
|
||||
import { getLiveRange } from './getLiveRange';
|
||||
import { ModeButton } from './ModeButton';
|
||||
import { ReportOptions } from './ReportOptions';
|
||||
@@ -39,6 +40,7 @@ export function ReportSidebar({
|
||||
defaultItems,
|
||||
defaultModeItems,
|
||||
earliestTransaction,
|
||||
firstDayOfWeekIdx,
|
||||
}) {
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const onSelectRange = cond => {
|
||||
@@ -49,7 +51,9 @@ export function ReportSidebar({
|
||||
);
|
||||
onReportChange({ type: 'modify' });
|
||||
setDateRange(cond);
|
||||
onChangeDates(...getLiveRange(cond, earliestTransaction));
|
||||
onChangeDates(
|
||||
...getLiveRange(cond, earliestTransaction, firstDayOfWeekIdx),
|
||||
);
|
||||
};
|
||||
|
||||
const onChangeMode = cond => {
|
||||
@@ -207,7 +211,7 @@ export function ReportSidebar({
|
||||
.map(int => int.description)
|
||||
.includes(customReportItems.dateRange)
|
||||
) {
|
||||
onSelectRange('Year to date');
|
||||
onSelectRange(defaultsList.intervalRange.get(e));
|
||||
}
|
||||
}}
|
||||
options={ReportOptions.interval.map(option => [
|
||||
@@ -396,7 +400,7 @@ export function ReportSidebar({
|
||||
options={ReportOptions.dateRange
|
||||
.filter(f => f[customReportItems.interval])
|
||||
.map(option => [option.description, option.description])}
|
||||
line={customReportItems.interval === 'Monthly' && dateRangeLine}
|
||||
line={dateRangeLine > 0 && dateRangeLine}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
@@ -419,6 +423,7 @@ export function ReportSidebar({
|
||||
newValue,
|
||||
customReportItems.endDate,
|
||||
customReportItems.interval,
|
||||
firstDayOfWeekIdx,
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -448,6 +453,7 @@ export function ReportSidebar({
|
||||
customReportItems.startDate,
|
||||
newValue,
|
||||
customReportItems.interval,
|
||||
firstDayOfWeekIdx,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -64,12 +64,20 @@ export function ReportSummary({
|
||||
{monthUtils.format(
|
||||
startDate,
|
||||
ReportOptions.intervalFormat.get(interval),
|
||||
)}{' '}
|
||||
-{' '}
|
||||
{monthUtils.format(
|
||||
endDate,
|
||||
ReportOptions.intervalFormat.get(interval),
|
||||
)}
|
||||
{monthUtils.format(
|
||||
startDate,
|
||||
ReportOptions.intervalFormat.get(interval),
|
||||
) !==
|
||||
monthUtils.format(
|
||||
endDate,
|
||||
ReportOptions.intervalFormat.get(interval),
|
||||
) &&
|
||||
' to ' +
|
||||
monthUtils.format(
|
||||
endDate,
|
||||
ReportOptions.intervalFormat.get(interval),
|
||||
)}
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
const intervalOptions = [
|
||||
{
|
||||
description: 'Daily',
|
||||
defaultRange: 'This month',
|
||||
},
|
||||
{
|
||||
description: 'Weekly',
|
||||
defaultRange: 'Last 3 months',
|
||||
},
|
||||
{
|
||||
description: 'Monthly',
|
||||
defaultRange: 'Last 6 months',
|
||||
},
|
||||
{
|
||||
description: 'Yearly',
|
||||
defaultRange: 'Year to date',
|
||||
},
|
||||
];
|
||||
|
||||
const totalGraphOptions = [
|
||||
{
|
||||
description: 'TableGraph',
|
||||
@@ -123,4 +142,7 @@ export const defaultsList = {
|
||||
new Map([...item.graphs].map(f => [f.description, f.defaultType])),
|
||||
]),
|
||||
),
|
||||
intervalRange: new Map(
|
||||
intervalOptions.map(item => [item.description, item.defaultRange]),
|
||||
),
|
||||
};
|
||||
|
||||
@@ -3,7 +3,11 @@ import * as monthUtils from 'loot-core/src/shared/months';
|
||||
import { ReportOptions } from './ReportOptions';
|
||||
import { getSpecificRange, validateRange } from './reportRanges';
|
||||
|
||||
export function getLiveRange(cond: string, earliestTransaction: string) {
|
||||
export function getLiveRange(
|
||||
cond: string,
|
||||
earliestTransaction: string,
|
||||
firstDayOfWeekIdx?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
||||
) {
|
||||
let dateStart;
|
||||
let dateEnd;
|
||||
const rangeName = ReportOptions.dateRangeMap.get(cond);
|
||||
@@ -25,7 +29,7 @@ export function getLiveRange(cond: string, earliestTransaction: string) {
|
||||
'-31',
|
||||
);
|
||||
break;
|
||||
case 'allMonths':
|
||||
case 'allTime':
|
||||
dateStart = earliestTransaction;
|
||||
dateEnd = monthUtils.currentDay();
|
||||
break;
|
||||
@@ -33,7 +37,9 @@ export function getLiveRange(cond: string, earliestTransaction: string) {
|
||||
if (typeof rangeName === 'number') {
|
||||
[dateStart, dateEnd] = getSpecificRange(
|
||||
rangeName,
|
||||
cond === 'Last month' ? 0 : null,
|
||||
cond === 'Last month' || cond === 'Last week' ? 0 : null,
|
||||
ReportOptions.dateRangeType.get(cond),
|
||||
firstDayOfWeekIdx,
|
||||
);
|
||||
} else {
|
||||
break;
|
||||
|
||||
@@ -5,6 +5,7 @@ export function validateStart(
|
||||
start: string,
|
||||
end: string,
|
||||
interval?: string,
|
||||
firstDayOfWeekIdx?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
||||
) {
|
||||
let addDays;
|
||||
let dateStart;
|
||||
@@ -35,6 +36,7 @@ export function validateStart(
|
||||
dateStart,
|
||||
interval ? end : monthUtils.monthFromDate(end),
|
||||
interval,
|
||||
firstDayOfWeekIdx,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,6 +45,7 @@ export function validateEnd(
|
||||
start: string,
|
||||
end: string,
|
||||
interval?: string,
|
||||
firstDayOfWeekIdx?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
||||
) {
|
||||
let subDays;
|
||||
let dateEnd;
|
||||
@@ -73,6 +76,7 @@ export function validateEnd(
|
||||
interval ? start : monthUtils.monthFromDate(start),
|
||||
dateEnd,
|
||||
interval,
|
||||
firstDayOfWeekIdx,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -92,9 +96,16 @@ function boundedRange(
|
||||
start: string,
|
||||
end: string,
|
||||
interval?: string,
|
||||
firstDayOfWeekIdx?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
||||
) {
|
||||
let latest;
|
||||
switch (interval) {
|
||||
case 'Daily':
|
||||
latest = monthUtils.currentDay();
|
||||
break;
|
||||
case 'Weekly':
|
||||
latest = monthUtils.currentWeek(firstDayOfWeekIdx);
|
||||
break;
|
||||
case 'Monthly':
|
||||
latest = monthUtils.currentMonth() + '-31';
|
||||
break;
|
||||
@@ -115,13 +126,28 @@ function boundedRange(
|
||||
return [start, end];
|
||||
}
|
||||
|
||||
export function getSpecificRange(offset: number, addNumber: number | null) {
|
||||
export function getSpecificRange(
|
||||
offset: number,
|
||||
addNumber: number | null,
|
||||
type?: string,
|
||||
firstDayOfWeekIdx?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
||||
) {
|
||||
const currentDay = monthUtils.currentDay();
|
||||
const dateStart = monthUtils.subMonths(currentDay, offset) + '-01';
|
||||
const dateEnd = monthUtils.getMonthEnd(
|
||||
|
||||
let dateStart = monthUtils.subMonths(currentDay, offset) + '-01';
|
||||
let dateEnd = monthUtils.getMonthEnd(
|
||||
monthUtils.addMonths(dateStart, addNumber === null ? offset : addNumber) +
|
||||
'-01',
|
||||
);
|
||||
|
||||
if (type === 'Weeks') {
|
||||
dateStart = monthUtils.subWeeks(currentDay, offset);
|
||||
dateEnd = monthUtils.getWeekEnd(
|
||||
monthUtils.addWeeks(dateStart, addNumber === null ? offset : addNumber),
|
||||
firstDayOfWeekIdx,
|
||||
);
|
||||
}
|
||||
|
||||
return [dateStart, dateEnd];
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ import { fromDateRepr } from '../util';
|
||||
|
||||
export function CustomReport() {
|
||||
const categories = useCategories();
|
||||
const [_firstDayOfWeekIdx] = useLocalPref('firstDayOfWeekIdx');
|
||||
const firstDayOfWeekIdx = _firstDayOfWeekIdx || 0;
|
||||
|
||||
const [viewLegend = false, setViewLegendPref] =
|
||||
useLocalPref('reportsViewLegend');
|
||||
@@ -123,9 +125,12 @@ export function CustomReport() {
|
||||
? monthUtils[format](d.parseISO(fromDateRepr(trans.date)))
|
||||
: currentInterval;
|
||||
|
||||
const rangeProps =
|
||||
interval === 'Weekly'
|
||||
? [earliestInterval, currentInterval, firstDayOfWeekIdx]
|
||||
: [earliestInterval, currentInterval];
|
||||
const allInter = monthUtils[ReportOptions.intervalRange.get(interval)](
|
||||
earliestInterval,
|
||||
currentInterval,
|
||||
...rangeProps,
|
||||
)
|
||||
.map(inter => ({
|
||||
name: inter,
|
||||
@@ -157,8 +162,12 @@ export function CustomReport() {
|
||||
const dateStart = monthUtils[format](startDate);
|
||||
const dateEnd = monthUtils[format](endDate);
|
||||
|
||||
const rangeProps =
|
||||
interval === 'Weekly'
|
||||
? [dateStart, dateEnd, firstDayOfWeekIdx]
|
||||
: [dateStart, dateEnd];
|
||||
setIntervals(
|
||||
monthUtils[ReportOptions.intervalRange.get(interval)](dateStart, dateEnd),
|
||||
monthUtils[ReportOptions.intervalRange.get(interval)](...rangeProps),
|
||||
);
|
||||
}, [interval, startDate, endDate]);
|
||||
|
||||
@@ -180,6 +189,7 @@ export function CustomReport() {
|
||||
showHiddenCategories,
|
||||
showUncategorized,
|
||||
balanceTypeOp,
|
||||
firstDayOfWeekIdx,
|
||||
});
|
||||
}, [
|
||||
startDate,
|
||||
@@ -198,6 +208,7 @@ export function CustomReport() {
|
||||
showHiddenCategories,
|
||||
showUncategorized,
|
||||
graphType,
|
||||
firstDayOfWeekIdx,
|
||||
]);
|
||||
|
||||
const getGraphData = useMemo(() => {
|
||||
@@ -219,6 +230,7 @@ export function CustomReport() {
|
||||
payees,
|
||||
accounts,
|
||||
graphType,
|
||||
firstDayOfWeekIdx,
|
||||
setDataCheck,
|
||||
});
|
||||
}, [
|
||||
@@ -238,6 +250,7 @@ export function CustomReport() {
|
||||
showHiddenCategories,
|
||||
showUncategorized,
|
||||
graphType,
|
||||
firstDayOfWeekIdx,
|
||||
]);
|
||||
const graphData = useReport('default', getGraphData);
|
||||
const groupedData = useReport('grouped', getGroupData);
|
||||
@@ -471,6 +484,7 @@ export function CustomReport() {
|
||||
defaultItems={defaultItems}
|
||||
defaultModeItems={defaultModeItems}
|
||||
earliestTransaction={earliestTransaction}
|
||||
firstDayOfWeekIdx={firstDayOfWeekIdx}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
@@ -563,8 +577,6 @@ export function CustomReport() {
|
||||
|
||||
{dataCheck ? (
|
||||
<ChooseGraph
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
data={data}
|
||||
mode={mode}
|
||||
graphType={graphType}
|
||||
@@ -578,6 +590,7 @@ export function CustomReport() {
|
||||
compact={false}
|
||||
showHiddenCategories={showHiddenCategories}
|
||||
showOffBudget={showOffBudget}
|
||||
intervalsCount={intervals.length}
|
||||
/>
|
||||
) : (
|
||||
<LoadingIndicator message="Loading report..." />
|
||||
|
||||
@@ -101,8 +101,6 @@ export function GetCardData({
|
||||
return data?.data ? (
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
<ChooseGraph
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
data={data}
|
||||
mode={report.mode}
|
||||
graphType={report.graphType}
|
||||
|
||||
@@ -47,6 +47,7 @@ export type createCustomSpreadsheetProps = {
|
||||
payees?: PayeeEntity[];
|
||||
accounts?: AccountEntity[];
|
||||
graphType?: string;
|
||||
firstDayOfWeekIdx?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
||||
setDataCheck?: (value: boolean) => void;
|
||||
};
|
||||
|
||||
@@ -67,6 +68,7 @@ export function createCustomSpreadsheet({
|
||||
payees,
|
||||
accounts,
|
||||
graphType,
|
||||
firstDayOfWeekIdx,
|
||||
setDataCheck,
|
||||
}: createCustomSpreadsheetProps) {
|
||||
const [categoryList, categoryGroup] = categoryLists(categories);
|
||||
@@ -100,7 +102,7 @@ export function createCustomSpreadsheet({
|
||||
});
|
||||
const conditionsOpKey = conditionsOp === 'or' ? '$or' : '$and';
|
||||
|
||||
const [assets, debts] = await Promise.all([
|
||||
let [assets, debts] = await Promise.all([
|
||||
runQuery(
|
||||
makeQuery(
|
||||
'assets',
|
||||
@@ -127,11 +129,33 @@ export function createCustomSpreadsheet({
|
||||
).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 format =
|
||||
ReportOptions.intervalMap.get(interval).toLowerCase() + 'FromDate';
|
||||
const rangeProps =
|
||||
interval === 'Weekly'
|
||||
? [
|
||||
monthUtils[format](startDate),
|
||||
monthUtils[format](endDate),
|
||||
firstDayOfWeekIdx,
|
||||
]
|
||||
: [monthUtils[format](startDate), monthUtils[format](endDate)];
|
||||
const intervals = monthUtils[ReportOptions.intervalRange.get(interval)](
|
||||
monthUtils[format](startDate),
|
||||
monthUtils[format](endDate),
|
||||
...rangeProps,
|
||||
);
|
||||
|
||||
let totalAssets = 0;
|
||||
|
||||
@@ -27,6 +27,7 @@ export function createGroupedSpreadsheet({
|
||||
showHiddenCategories,
|
||||
showUncategorized,
|
||||
balanceTypeOp,
|
||||
firstDayOfWeekIdx,
|
||||
}: createCustomSpreadsheetProps) {
|
||||
const [categoryList, categoryGroup] = categoryLists(categories);
|
||||
|
||||
@@ -51,7 +52,7 @@ export function createGroupedSpreadsheet({
|
||||
});
|
||||
const conditionsOpKey = conditionsOp === 'or' ? '$or' : '$and';
|
||||
|
||||
const [assets, debts] = await Promise.all([
|
||||
let [assets, debts] = await Promise.all([
|
||||
runQuery(
|
||||
makeQuery(
|
||||
'assets',
|
||||
@@ -78,11 +79,33 @@ export function createGroupedSpreadsheet({
|
||||
).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 format =
|
||||
ReportOptions.intervalMap.get(interval).toLowerCase() + 'FromDate';
|
||||
const rangeProps =
|
||||
interval === 'Weekly'
|
||||
? [
|
||||
monthUtils[format](startDate),
|
||||
monthUtils[format](endDate),
|
||||
firstDayOfWeekIdx,
|
||||
]
|
||||
: [monthUtils[format](startDate), monthUtils[format](endDate)];
|
||||
const intervals = monthUtils[ReportOptions.intervalRange.get(interval)](
|
||||
monthUtils[format](startDate),
|
||||
monthUtils[format](endDate),
|
||||
...rangeProps,
|
||||
);
|
||||
|
||||
const groupedData: DataEntity[] = categoryGroup.map(
|
||||
|
||||
@@ -14,9 +14,15 @@ export function makeQuery(
|
||||
filters: unknown[],
|
||||
) {
|
||||
const intervalGroup =
|
||||
interval === 'Monthly' ? { $month: '$date' } : { $year: '$date' };
|
||||
interval === 'Monthly'
|
||||
? { $month: '$date' }
|
||||
: interval === 'Yearly'
|
||||
? { $year: '$date' }
|
||||
: { $day: '$date' };
|
||||
const intervalFilter =
|
||||
'$' + ReportOptions.intervalMap.get(interval)?.toLowerCase() || 'month';
|
||||
interval === 'Weekly'
|
||||
? '$day'
|
||||
: '$' + ReportOptions.intervalMap.get(interval)?.toLowerCase() || 'month';
|
||||
|
||||
const query = q('transactions')
|
||||
//Apply Category_Selector
|
||||
|
||||
@@ -600,6 +600,10 @@ const compileFunction = saveStack('function', (state, func) => {
|
||||
}
|
||||
|
||||
// date functions
|
||||
case '$day': {
|
||||
validateArgLength(args, 1);
|
||||
return castInput(state, args[0], 'date');
|
||||
}
|
||||
case '$month': {
|
||||
validateArgLength(args, 1);
|
||||
return castInput(state, args[0], 'date-month');
|
||||
|
||||
@@ -87,8 +87,14 @@ export function monthFromDate(date: DateLike): string {
|
||||
return d.format(_parse(date), 'yyyy-MM');
|
||||
}
|
||||
|
||||
export function weekFromDate(date: DateLike): string {
|
||||
return d.format(_parse(date), 'yyyy-ww');
|
||||
export function weekFromDate(
|
||||
date: DateLike,
|
||||
firstDayOfWeekIdx: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
||||
): string {
|
||||
return d.format(
|
||||
_parse(d.startOfWeek(_parse(date), { weekStartsOn: firstDayOfWeekIdx })),
|
||||
'yyyy-MM-dd',
|
||||
);
|
||||
}
|
||||
|
||||
export function dayFromDate(date: DateLike): string {
|
||||
@@ -103,6 +109,19 @@ export function currentMonth(): string {
|
||||
}
|
||||
}
|
||||
|
||||
export function currentWeek(
|
||||
firstDayOfWeekIdx?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
||||
): string {
|
||||
if (global.IS_TESTING || Platform.isPlaywright) {
|
||||
return global.currentWeek || '2017-01-01';
|
||||
} else {
|
||||
return d.format(
|
||||
_parse(d.startOfWeek(new Date(), { weekStartsOn: firstDayOfWeekIdx })),
|
||||
'yyyy-MM-dd',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function currentYear(): string {
|
||||
if (global.IS_TESTING || Platform.isPlaywright) {
|
||||
return global.currentMonth || '2017';
|
||||
@@ -169,6 +188,10 @@ export function subMonths(month: string | Date, n: number) {
|
||||
return d.format(d.subMonths(_parse(month), n), 'yyyy-MM');
|
||||
}
|
||||
|
||||
export function subWeeks(date: DateLike, n: number): string {
|
||||
return d.format(d.subWeeks(_parse(date), n), 'yyyy-MM-dd');
|
||||
}
|
||||
|
||||
export function subYears(year: string | Date, n: number) {
|
||||
return d.format(d.subYears(_parse(year), n), 'yyyy');
|
||||
}
|
||||
@@ -221,6 +244,34 @@ export function yearRangeInclusive(start: DateLike, end: DateLike): string[] {
|
||||
return _yearRange(start, end, true);
|
||||
}
|
||||
|
||||
export function _weekRange(
|
||||
start: DateLike,
|
||||
end: DateLike,
|
||||
inclusive = false,
|
||||
firstDayOfWeekIdx?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
||||
): string[] {
|
||||
const weeks: string[] = [];
|
||||
let week = weekFromDate(start, firstDayOfWeekIdx);
|
||||
while (d.isBefore(_parse(week), _parse(end))) {
|
||||
weeks.push(week);
|
||||
week = addWeeks(week, 1);
|
||||
}
|
||||
|
||||
if (inclusive) {
|
||||
weeks.push(week);
|
||||
}
|
||||
|
||||
return weeks;
|
||||
}
|
||||
|
||||
export function weekRangeInclusive(
|
||||
start: DateLike,
|
||||
end: DateLike,
|
||||
firstDayOfWeekIdx?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
||||
): string[] {
|
||||
return _weekRange(start, end, true, firstDayOfWeekIdx);
|
||||
}
|
||||
|
||||
export function _range(
|
||||
start: DateLike,
|
||||
end: DateLike,
|
||||
@@ -296,6 +347,16 @@ export function getMonthEnd(day: string): string {
|
||||
return subDays(nextMonth(day.slice(0, 7)) + '-01', 1);
|
||||
}
|
||||
|
||||
export function getWeekEnd(
|
||||
date: DateLike,
|
||||
firstDayOfWeekIdx?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
|
||||
): string {
|
||||
return d.format(
|
||||
_parse(d.endOfWeek(_parse(date), { weekStartsOn: firstDayOfWeekIdx })),
|
||||
'yyyy-MM-dd',
|
||||
);
|
||||
}
|
||||
|
||||
export function getYearStart(month: string): string {
|
||||
return getYear(month) + '-01';
|
||||
}
|
||||
|
||||
6
upcoming-release-notes/2483.md
Normal file
6
upcoming-release-notes/2483.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Enhancements
|
||||
authors: [carkom]
|
||||
---
|
||||
|
||||
Add daily and weekly to custom reports interval list.
|
||||
Reference in New Issue
Block a user