mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-18 08:44:25 +08:00
display year-over-year and period-over-period growth rates in account balance trends chart in account reconciliation statements on desktop version
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
|
|
||||||
import { useI18n } from '@/locales/helpers.ts';
|
import { useI18n } from '@/locales/helpers.ts';
|
||||||
|
|
||||||
@@ -28,7 +28,10 @@ import {
|
|||||||
getFiscalYearStartDateTime
|
getFiscalYearStartDateTime
|
||||||
} from '@/lib/datetime.ts';
|
} from '@/lib/datetime.ts';
|
||||||
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
|
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
|
||||||
import { getAllDateRangesByYearMonthRange } from '@/lib/statistics.ts';
|
import {
|
||||||
|
getAllDateRangesByYearMonthRange,
|
||||||
|
getDateRangeKeyWithYearOffset
|
||||||
|
} from '@/lib/statistics.ts';
|
||||||
|
|
||||||
export interface AccountBalanceUnixTimeAndBalanceRange extends UnixTimeRange {
|
export interface AccountBalanceUnixTimeAndBalanceRange extends UnixTimeRange {
|
||||||
minUnixTimeOpeningBalance: number;
|
minUnixTimeOpeningBalance: number;
|
||||||
@@ -37,6 +40,8 @@ export interface AccountBalanceUnixTimeAndBalanceRange extends UnixTimeRange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AccountBalanceTrendsChartItem {
|
export interface AccountBalanceTrendsChartItem {
|
||||||
|
dateRangeKey: string;
|
||||||
|
lastYearDateRangeKey: string;
|
||||||
displayDate: string;
|
displayDate: string;
|
||||||
openingBalance: number;
|
openingBalance: number;
|
||||||
closingBalance: number;
|
closingBalance: number;
|
||||||
@@ -65,6 +70,9 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
formatDateTimeToGregorianLikeFiscalYear
|
formatDateTimeToGregorianLikeFiscalYear
|
||||||
} = useI18n();
|
} = useI18n();
|
||||||
|
|
||||||
|
const showYearOverYearOnTooltip = ref<boolean>(true);
|
||||||
|
const showPeriodOverPeriodOnTooltip = computed<boolean>(() => props.dateAggregationType === ChartDateAggregationType.Day.type || props.dateAggregationType === ChartDateAggregationType.Month.type || props.dateAggregationType === ChartDateAggregationType.Quarter.type);
|
||||||
|
|
||||||
const dataDateRange = computed<AccountBalanceUnixTimeAndBalanceRange | null>(() => {
|
const dataDateRange = computed<AccountBalanceUnixTimeAndBalanceRange | null>(() => {
|
||||||
if (!props.items || props.items.length < 1) {
|
if (!props.items || props.items.length < 1) {
|
||||||
return null;
|
return null;
|
||||||
@@ -187,6 +195,8 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
}
|
}
|
||||||
|
|
||||||
const dataItems = dayDataItemsMap[displayDate];
|
const dataItems = dayDataItemsMap[displayDate];
|
||||||
|
const dateRangeKey = getDateRangeKeyWithYearOffset(dateRange, props.dateAggregationType) ?? '';
|
||||||
|
const lastYearDateRangeKey = getDateRangeKeyWithYearOffset(dateRange, props.dateAggregationType, -1) ?? '';
|
||||||
|
|
||||||
if (isArray(dataItems)) {
|
if (isArray(dataItems)) {
|
||||||
if (dataItems.length < 1) {
|
if (dataItems.length < 1) {
|
||||||
@@ -243,6 +253,8 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret.push({
|
ret.push({
|
||||||
|
dateRangeKey: dateRangeKey,
|
||||||
|
lastYearDateRangeKey: lastYearDateRangeKey,
|
||||||
displayDate: displayDate,
|
displayDate: displayDate,
|
||||||
openingBalance: lastOpeningBalance,
|
openingBalance: lastOpeningBalance,
|
||||||
closingBalance: lastClosingBalance,
|
closingBalance: lastClosingBalance,
|
||||||
@@ -260,6 +272,18 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const allDataItemsMap = computed<Record<string, AccountBalanceTrendsChartItem>>(() => {
|
||||||
|
const ret: Record<string, AccountBalanceTrendsChartItem> = {};
|
||||||
|
|
||||||
|
for (const item of allDataItems.value) {
|
||||||
|
if (item.dateRangeKey) {
|
||||||
|
ret[item.dateRangeKey] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
const allDisplayDateRanges = computed<string[]>(() => {
|
const allDisplayDateRanges = computed<string[]>(() => {
|
||||||
if (!allDataItems.value || allDataItems.value.length < 1) {
|
if (!allDataItems.value || allDataItems.value.length < 1) {
|
||||||
return [];
|
return [];
|
||||||
@@ -269,9 +293,13 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
// states
|
||||||
|
showYearOverYearOnTooltip,
|
||||||
|
showPeriodOverPeriodOnTooltip,
|
||||||
// computed states
|
// computed states
|
||||||
allDateRanges,
|
allDateRanges,
|
||||||
allDataItems,
|
allDataItems,
|
||||||
|
allDataItemsMap,
|
||||||
allDisplayDateRanges
|
allDisplayDateRanges
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
|
|
||||||
import { useUserStore } from '@/stores/user.ts';
|
import { useUserStore } from '@/stores/user.ts';
|
||||||
|
|
||||||
import { type NameValue, itemAndIndex } from '@/core/base.ts';
|
import { type NameNumeralValue, itemAndIndex } from '@/core/base.ts';
|
||||||
import { TextDirection } from '@/core/text.ts';
|
import { TextDirection } from '@/core/text.ts';
|
||||||
import type { ColorStyleValue } from '@/core/color.ts';
|
import type { ColorStyleValue } from '@/core/color.ts';
|
||||||
import { ThemeType } from '@/core/theme.ts';
|
import { ThemeType } from '@/core/theme.ts';
|
||||||
@@ -52,8 +52,19 @@ interface AccountBalanceTrendsChartDataItem {
|
|||||||
const props = defineProps<DesktopAccountBalanceTrendsChartProps>();
|
const props = defineProps<DesktopAccountBalanceTrendsChartProps>();
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { tt, getCurrentLanguageTextDirection, formatAmountToLocalizedNumeralsWithCurrency } = useI18n();
|
const {
|
||||||
const { allDataItems, allDisplayDateRanges } = useAccountBalanceTrendsChartBase(props);
|
tt,
|
||||||
|
getCurrentLanguageTextDirection,
|
||||||
|
formatAmountToLocalizedNumeralsWithCurrency,
|
||||||
|
formatPercentToLocalizedNumerals
|
||||||
|
} = useI18n();
|
||||||
|
const {
|
||||||
|
showYearOverYearOnTooltip,
|
||||||
|
showPeriodOverPeriodOnTooltip,
|
||||||
|
allDataItems,
|
||||||
|
allDataItemsMap,
|
||||||
|
allDisplayDateRanges
|
||||||
|
} = useAccountBalanceTrendsChartBase(props);
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
@@ -189,105 +200,74 @@ const chartOptions = computed<object>(() => {
|
|||||||
color: isDarkMode.value ? '#eee' : '#333'
|
color: isDarkMode.value ? '#eee' : '#333'
|
||||||
},
|
},
|
||||||
formatter: (params: CallbackDataParams[]) => {
|
formatter: (params: CallbackDataParams[]) => {
|
||||||
|
const dataIndex = params[0]!.dataIndex;
|
||||||
|
const dataItem: AccountBalanceTrendsChartItem = allDataItems.value[dataIndex] as AccountBalanceTrendsChartItem;
|
||||||
|
const yearOverYearDataItem: AccountBalanceTrendsChartItem | undefined = showYearOverYearOnTooltip.value ? allDataItemsMap.value[dataItem.lastYearDateRangeKey] : undefined;
|
||||||
|
const periodOverPeriodDataItem: AccountBalanceTrendsChartItem | undefined = showPeriodOverPeriodOnTooltip.value ? allDataItems.value[dataIndex - 1] : undefined;
|
||||||
|
|
||||||
|
let header: string = params[0]!.name;
|
||||||
|
let displayItems: NameNumeralValue[] = [];
|
||||||
|
let yearOverYearDataItemDisplayItems: NameNumeralValue[] | undefined = undefined;
|
||||||
|
let periodOverPeriodDataItemDisplayItems: NameNumeralValue[] | undefined = undefined;
|
||||||
|
let separatorLineIndex: number | undefined = undefined;
|
||||||
|
|
||||||
if (props.type === AccountBalanceTrendChartType.Boxplot.type) {
|
if (props.type === AccountBalanceTrendChartType.Boxplot.type) {
|
||||||
const dataIndex = params[0]!.dataIndex;
|
header += ` ${props.legendName}`;
|
||||||
const dataItem = allDataItems.value[dataIndex] as AccountBalanceTrendsChartItem;
|
displayItems = getBoxplotChartTooltip(dataItem);
|
||||||
const displayItems: NameValue[] = [
|
yearOverYearDataItemDisplayItems = yearOverYearDataItem ? getBoxplotChartTooltip(yearOverYearDataItem) : undefined;
|
||||||
{
|
periodOverPeriodDataItemDisplayItems = periodOverPeriodDataItem ? getBoxplotChartTooltip(periodOverPeriodDataItem) : undefined;
|
||||||
name: tt('Minimum Balance'),
|
separatorLineIndex = 5;
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.minimumBalance, props.account.currency)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: tt('Q1 Balance (First Quartile)'),
|
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.q1Balance, props.account.currency)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: tt('Median Balance'),
|
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.medianBalance, props.account.currency)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: tt('Q3 Balance (Third Quartile)'),
|
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.q3Balance, props.account.currency)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: tt('Maximum Balance'),
|
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.maximumBalance, props.account.currency)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: tt('Opening Balance'),
|
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.openingBalance, props.account.currency)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: tt('Closing Balance'),
|
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.closingBalance, props.account.currency)
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
let tooltip = `${params[0]!.name} ${props.legendName}<br/>`;
|
|
||||||
|
|
||||||
for (const [displayItem, index] of itemAndIndex(displayItems)) {
|
|
||||||
if (index === 5) {
|
|
||||||
tooltip += '<div style="border-bottom: ' + (isDarkMode.value ? '#eee' : '#333') + ' dashed 1px"></div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
tooltip += `<div><span class="chart-pointer" style="background-color: #${DEFAULT_CHART_COLORS[index]}"></span>`
|
|
||||||
+ `<span>${displayItem.name}</span><span class="ms-5" style="float: inline-end">${displayItem.value}</span>`
|
|
||||||
+ `</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tooltip;
|
|
||||||
} else if (props.type === AccountBalanceTrendChartType.Candlestick.type) {
|
} else if (props.type === AccountBalanceTrendChartType.Candlestick.type) {
|
||||||
const dataIndex = params[0]!.dataIndex;
|
header += ` ${props.legendName}`;
|
||||||
const dataItem = allDataItems.value[dataIndex] as AccountBalanceTrendsChartItem;
|
displayItems = getCandlestickChartTooltip(dataItem);
|
||||||
const displayItems: NameValue[] = [
|
yearOverYearDataItemDisplayItems = yearOverYearDataItem ? getCandlestickChartTooltip(yearOverYearDataItem) : undefined;
|
||||||
{
|
periodOverPeriodDataItemDisplayItems = periodOverPeriodDataItem ? getCandlestickChartTooltip(periodOverPeriodDataItem) : undefined;
|
||||||
name: tt('Opening Balance'),
|
separatorLineIndex = 4;
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.openingBalance, props.account.currency)
|
} else {
|
||||||
},
|
displayItems = getDefaultChartTooltip(dataItem);
|
||||||
{
|
yearOverYearDataItemDisplayItems = yearOverYearDataItem ? getDefaultChartTooltip(yearOverYearDataItem) : undefined;
|
||||||
name: tt('Closing Balance'),
|
periodOverPeriodDataItemDisplayItems = periodOverPeriodDataItem ? getDefaultChartTooltip(periodOverPeriodDataItem) : undefined;
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.closingBalance, props.account.currency)
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
name: tt('Minimum Balance'),
|
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.minimumBalance, props.account.currency)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: tt('Maximum Balance'),
|
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.maximumBalance, props.account.currency)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: tt('Median Balance'),
|
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.medianBalance, props.account.currency)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: tt('Average Balance'),
|
|
||||||
value: formatAmountToLocalizedNumeralsWithCurrency(dataItem.averageBalance, props.account.currency)
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
let tooltip = `${params[0]!.name} ${props.legendName}<br/>`;
|
const totalColumnCount = 2 + (yearOverYearDataItemDisplayItems && yearOverYearDataItemDisplayItems.length ? 1 : 0) + (periodOverPeriodDataItemDisplayItems && periodOverPeriodDataItemDisplayItems.length ? 1 : 0);
|
||||||
|
let tooltip = `<table class="chart-tooltip-table"><tbody><tr><td colspan="2">${header}</td>`;
|
||||||
|
|
||||||
for (const [displayItem, index] of itemAndIndex(displayItems)) {
|
if (yearOverYearDataItemDisplayItems && yearOverYearDataItemDisplayItems.length) {
|
||||||
if (index === 4) {
|
tooltip += `<td><span class="ms-5" style="float: inline-end">${tt('Year-over-Year')}</span></td>`;
|
||||||
tooltip += '<div style="border-bottom: ' + (isDarkMode.value ? '#eee' : '#333') + ' dashed 1px"></div>';
|
}
|
||||||
}
|
|
||||||
|
|
||||||
tooltip += `<div><span class="chart-pointer" style="background-color: #${DEFAULT_CHART_COLORS[index]}"></span>`
|
if (periodOverPeriodDataItemDisplayItems && periodOverPeriodDataItemDisplayItems.length) {
|
||||||
+ `<span>${displayItem.name}</span><span class="ms-5" style="float: inline-end">${displayItem.value}</span>`
|
tooltip += `<td><span class="ms-5" style="float: inline-end">${tt('Period-over-Period')}</span></td>`;
|
||||||
+ `</div>`;
|
}
|
||||||
|
|
||||||
|
tooltip += '</tr>';
|
||||||
|
|
||||||
|
for (const [displayItem, index] of itemAndIndex(displayItems)) {
|
||||||
|
const displayValue = formatAmountToLocalizedNumeralsWithCurrency(displayItem.value, props.account.currency);
|
||||||
|
tooltip += `<tr><td><span class="chart-pointer" style="background-color: #${DEFAULT_CHART_COLORS[index]}"></span>`
|
||||||
|
+ `<span>${displayItem.name}</span></td><td><span class="ms-5" style="float: inline-end">${displayValue}</span></td>`;
|
||||||
|
|
||||||
|
if (yearOverYearDataItemDisplayItems && yearOverYearDataItemDisplayItems.length && yearOverYearDataItemDisplayItems[index]) {
|
||||||
|
const yearOverYearDisplayItem = yearOverYearDataItemDisplayItems[index];
|
||||||
|
const displayGrowthRate = formatDisplayChangeRate(displayItem.value, yearOverYearDisplayItem.value);
|
||||||
|
tooltip += `<td><span class="ms-5" style="float: inline-end">${displayGrowthRate}</span></td>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tooltip;
|
if (periodOverPeriodDataItemDisplayItems && periodOverPeriodDataItemDisplayItems.length && periodOverPeriodDataItemDisplayItems[index]) {
|
||||||
} else {
|
const periodOverPeriodDisplayItem = periodOverPeriodDataItemDisplayItems[index];
|
||||||
const amount = params[0]!.data as number;
|
const displayGrowthRate = formatDisplayChangeRate(displayItem.value, periodOverPeriodDisplayItem.value);
|
||||||
const value = formatAmountToLocalizedNumeralsWithCurrency(amount, props.account.currency);
|
tooltip += `<td><span class="ms-5" style="float: inline-end">${displayGrowthRate}</span></td>`;
|
||||||
|
}
|
||||||
|
|
||||||
return `${params[0]!.name}<br/>`
|
tooltip += '</tr>';
|
||||||
+ '<div><span class="chart-pointer" style="background-color: #' + DEFAULT_CHART_COLORS[0] + '"></span>'
|
|
||||||
+ `<span>${props.legendName}</span><span class="ms-5" style="float: inline-end">${value}</span>`
|
if (separatorLineIndex !== undefined && index === separatorLineIndex - 1) {
|
||||||
+ '</div>';
|
tooltip += `<tr><td colspan="${totalColumnCount}" style="border-bottom: ${(isDarkMode.value ? '#eee' : '#333')} dashed 1px"></td></tr>`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tooltip += `</tbody></table>`;
|
||||||
|
return tooltip;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
@@ -332,6 +312,91 @@ const chartOptions = computed<object>(() => {
|
|||||||
series: allSeries.value
|
series: allSeries.value
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getBoxplotChartTooltip(dataItem: AccountBalanceTrendsChartItem): NameNumeralValue[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: tt('Minimum Balance'),
|
||||||
|
value: dataItem.minimumBalance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Q1 Balance (First Quartile)'),
|
||||||
|
value: dataItem.q1Balance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Median Balance'),
|
||||||
|
value: dataItem.medianBalance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Q3 Balance (Third Quartile)'),
|
||||||
|
value: dataItem.q3Balance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Maximum Balance'),
|
||||||
|
value: dataItem.maximumBalance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Opening Balance'),
|
||||||
|
value: dataItem.openingBalance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Closing Balance'),
|
||||||
|
value: dataItem.closingBalance
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCandlestickChartTooltip(dataItem: AccountBalanceTrendsChartItem): NameNumeralValue[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: tt('Opening Balance'),
|
||||||
|
value: dataItem.openingBalance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Closing Balance'),
|
||||||
|
value: dataItem.closingBalance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Minimum Balance'),
|
||||||
|
value: dataItem.minimumBalance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Maximum Balance'),
|
||||||
|
value: dataItem.maximumBalance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Median Balance'),
|
||||||
|
value: dataItem.medianBalance
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Average Balance'),
|
||||||
|
value: dataItem.averageBalance
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultChartTooltip(dataItem: AccountBalanceTrendsChartItem): NameNumeralValue[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: props.legendName,
|
||||||
|
value: dataItem.closingBalance
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function formatDisplayChangeRate(current: number, reference: number): string {
|
||||||
|
if (reference === 0 && current === 0) {
|
||||||
|
return formatPercentToLocalizedNumerals(0, 2, '<0.01');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reference === 0) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
const rate = (current - reference) / reference * 100;
|
||||||
|
return formatPercentToLocalizedNumerals(rate, 2, '<0.01');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ import {
|
|||||||
getDateTypeByDateRange,
|
getDateTypeByDateRange,
|
||||||
getFiscalYearFromUnixTime
|
getFiscalYearFromUnixTime
|
||||||
} from '@/lib/datetime.ts';
|
} from '@/lib/datetime.ts';
|
||||||
|
import {
|
||||||
|
getDateRangeKeyWithYearOffset
|
||||||
|
} from '@/lib/statistics.ts';
|
||||||
|
|
||||||
type AxisChartType = InstanceType<typeof AxisChart>;
|
type AxisChartType = InstanceType<typeof AxisChart>;
|
||||||
|
|
||||||
@@ -297,19 +300,11 @@ function getSeriesId(item: Record<string, unknown>): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getDateRangeKey(dateRange: YearUnixTime | FiscalYearUnixTime | YearQuarterUnixTime | YearMonthUnixTime | YearMonthDayUnixTime, yearOffset?: number): string | undefined {
|
function getDateRangeKey(dateRange: YearUnixTime | FiscalYearUnixTime | YearQuarterUnixTime | YearMonthUnixTime | YearMonthDayUnixTime, yearOffset?: number): string | undefined {
|
||||||
if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
|
if (props.dateAggregationType === ChartDateAggregationType.Day.type && props.chartMode !== 'daily') {
|
||||||
return (dateRange.year + (yearOffset ?? 0)).toString();
|
|
||||||
} else if (props.dateAggregationType === ChartDateAggregationType.FiscalYear.type && 'year' in dateRange) {
|
|
||||||
return (dateRange.year + (yearOffset ?? 0)).toString();
|
|
||||||
} else if (props.dateAggregationType === ChartDateAggregationType.Quarter.type && 'quarter' in dateRange) {
|
|
||||||
return `${dateRange.year + (yearOffset ?? 0)}-${dateRange.quarter}`;
|
|
||||||
} else if (props.dateAggregationType === ChartDateAggregationType.Month.type && 'month0base' in dateRange) {
|
|
||||||
return `${dateRange.year + (yearOffset ?? 0)}-${dateRange.month0base + 1}`;
|
|
||||||
} else if (props.dateAggregationType === ChartDateAggregationType.Day.type && 'day' in dateRange && props.chartMode === 'daily') {
|
|
||||||
return `${dateRange.year + (yearOffset ?? 0)}-${dateRange.month}-${dateRange.day}`;
|
|
||||||
} else {
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return getDateRangeKeyWithYearOffset(dateRange, props.dateAggregationType, yearOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDisplayChangeRate(current: number, reference: number): string {
|
function formatDisplayChangeRate(current: number, reference: number): string {
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ const allVirtualListItems = computed<MobileAccountBalanceTrendsChartItem[]>(() =
|
|||||||
|
|
||||||
const finalDataItem: MobileAccountBalanceTrendsChartItem = {
|
const finalDataItem: MobileAccountBalanceTrendsChartItem = {
|
||||||
index: index,
|
index: index,
|
||||||
|
dateRangeKey: dataItem.dateRangeKey,
|
||||||
|
lastYearDateRangeKey: dataItem.lastYearDateRangeKey,
|
||||||
displayDate: dataItem.displayDate,
|
displayDate: dataItem.displayDate,
|
||||||
openingBalance: dataItem.openingBalance,
|
openingBalance: dataItem.openingBalance,
|
||||||
closingBalance: dataItem.closingBalance,
|
closingBalance: dataItem.closingBalance,
|
||||||
|
|||||||
+32
-3
@@ -1,6 +1,19 @@
|
|||||||
import type { TextualYearMonth, Year1BasedMonth, YearUnixTime, YearQuarterUnixTime, YearMonthUnixTime } from '@/core/datetime.ts';
|
import {
|
||||||
import type { FiscalYearUnixTime } from '@/core/fiscalyear.ts';
|
type TextualYearMonth,
|
||||||
import { ChartSortingType, ChartDateAggregationType } from '@/core/statistics.ts';
|
type Year1BasedMonth,
|
||||||
|
type YearUnixTime,
|
||||||
|
type YearQuarterUnixTime,
|
||||||
|
type YearMonthUnixTime,
|
||||||
|
YearMonthDayUnixTime
|
||||||
|
} from '@/core/datetime.ts';
|
||||||
|
import {
|
||||||
|
type FiscalYearUnixTime
|
||||||
|
} from '@/core/fiscalyear.ts';
|
||||||
|
import {
|
||||||
|
ChartSortingType,
|
||||||
|
ChartDateAggregationType
|
||||||
|
} from '@/core/statistics.ts';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
YearMonthItems,
|
YearMonthItems,
|
||||||
SortableTransactionStatisticDataItem
|
SortableTransactionStatisticDataItem
|
||||||
@@ -88,3 +101,19 @@ export function getAllDateRangesByYearMonthRange(startYearMonth: Year1BasedMonth
|
|||||||
return getAllMonthsStartAndEndUnixTimes(startYearMonth, endYearMonth);
|
return getAllMonthsStartAndEndUnixTimes(startYearMonth, endYearMonth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getDateRangeKeyWithYearOffset(dateRange: YearUnixTime | FiscalYearUnixTime | YearQuarterUnixTime | YearMonthUnixTime | YearMonthDayUnixTime, dateAggregationType: number, yearOffset?: number): string | undefined {
|
||||||
|
if (dateAggregationType === ChartDateAggregationType.Year.type) {
|
||||||
|
return (dateRange.year + (yearOffset ?? 0)).toString();
|
||||||
|
} else if (dateAggregationType === ChartDateAggregationType.FiscalYear.type && 'year' in dateRange) {
|
||||||
|
return (dateRange.year + (yearOffset ?? 0)).toString();
|
||||||
|
} else if (dateAggregationType === ChartDateAggregationType.Quarter.type && 'quarter' in dateRange) {
|
||||||
|
return `${dateRange.year + (yearOffset ?? 0)}-${dateRange.quarter}`;
|
||||||
|
} else if (dateAggregationType === ChartDateAggregationType.Month.type && 'month0base' in dateRange) {
|
||||||
|
return `${dateRange.year + (yearOffset ?? 0)}-${dateRange.month0base + 1}`;
|
||||||
|
} else if (dateAggregationType === ChartDateAggregationType.Day.type && 'day' in dateRange) {
|
||||||
|
return `${dateRange.year + (yearOffset ?? 0)}-${dateRange.month}-${dateRange.day}`;
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user