mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-15 07:27:33 +08:00
add asset trends in statistics & analysis (#314)
This commit is contained in:
@@ -14,7 +14,7 @@ import { ChartDateAggregationType } from '@/core/statistics.ts';
|
||||
import type { AccountInfoResponse } from '@/models/account.ts';
|
||||
import type { TransactionReconciliationStatementResponseItem } from '@/models/transaction.ts';
|
||||
|
||||
import { isDefined, isArray } from '@/lib/common.ts';
|
||||
import { isArray } from '@/lib/common.ts';
|
||||
import { sumAmounts } from '@/lib/numeral.ts';
|
||||
import {
|
||||
getGregorianCalendarYearAndMonthFromUnixTime,
|
||||
@@ -45,7 +45,7 @@ export interface AccountBalanceTrendsChartItem {
|
||||
|
||||
export interface CommonAccountBalanceTrendsChartProps {
|
||||
items: TransactionReconciliationStatementResponseItem[] | undefined;
|
||||
dateAggregationType?: number;
|
||||
dateAggregationType: number;
|
||||
fiscalYearStart: number;
|
||||
account: AccountInfoResponse;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!isDefined(props.dateAggregationType)) {
|
||||
if (props.dateAggregationType === ChartDateAggregationType.Day.type) {
|
||||
return getAllDaysStartAndEndUnixTimes(dataDateRange.value.minUnixTime, dataDateRange.value.maxUnixTime);
|
||||
} else {
|
||||
const startYearMonth = getGregorianCalendarYearAndMonthFromUnixTime(dataDateRange.value.minUnixTime);
|
||||
@@ -129,8 +129,10 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
||||
dateRangeMinUnixTime = getQuarterFirstUnixTimeBySpecifiedUnixTime(dateItem.time);
|
||||
} else if (props.dateAggregationType === ChartDateAggregationType.Month.type) {
|
||||
dateRangeMinUnixTime = getMonthFirstUnixTimeBySpecifiedUnixTime(dateItem.time);
|
||||
} else {
|
||||
} else if (props.dateAggregationType === ChartDateAggregationType.Day.type) {
|
||||
dateRangeMinUnixTime = getDayFirstUnixTimeBySpecifiedUnixTime(dateItem.time);
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
|
||||
const dataItems: TransactionReconciliationStatementResponseItem[] = dayDataItemsMap[dateRangeMinUnixTime] || [];
|
||||
@@ -159,8 +161,10 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
||||
displayDate = formatUnixTimeToGregorianLikeYearQuarter(dateRange.minUnixTime);
|
||||
} else if (props.dateAggregationType === ChartDateAggregationType.Month.type) {
|
||||
displayDate = formatUnixTimeToGregorianLikeShortYearMonth(dateRange.minUnixTime);
|
||||
} else {
|
||||
} else if (props.dateAggregationType === ChartDateAggregationType.Day.type) {
|
||||
displayDate = formatUnixTimeToShortDate(dateRange.minUnixTime);
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (isArray(dataItems)) {
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useI18n } from '@/locales/helpers.ts';
|
||||
|
||||
import type {
|
||||
TextualYearMonth,
|
||||
Year1BasedMonth,
|
||||
YearMonthDay,
|
||||
TimeRangeAndDateType,
|
||||
YearUnixTime,
|
||||
YearQuarterUnixTime,
|
||||
YearMonthUnixTime,
|
||||
YearMonthDayUnixTime
|
||||
} from '@/core/datetime.ts';
|
||||
import type { FiscalYearUnixTime } from '@/core/fiscalyear.ts';
|
||||
import { ChartDataAggregationType, ChartDateAggregationType } from '@/core/statistics.ts';
|
||||
import type { YearMonthItems, YearMonthDayItems } from '@/models/transaction.ts';
|
||||
|
||||
import {
|
||||
getYearMonthDayDateTime,
|
||||
getGregorianCalendarYearAndMonthFromUnixTime,
|
||||
getAllDaysStartAndEndUnixTimes
|
||||
} from '@/lib/datetime.ts';
|
||||
import {
|
||||
getAllDateRangesFromItems,
|
||||
getAllDateRangesByYearMonthRange
|
||||
} from '@/lib/statistics.ts';
|
||||
|
||||
export type TrendsChartDateType = 'daily' | 'monthly';
|
||||
|
||||
interface TrendsChartTypes {
|
||||
daily: {
|
||||
ItemsType: YearMonthDayItems<YearMonthDay>;
|
||||
DateTimeRangeType: number;
|
||||
MonthRangeType: undefined;
|
||||
};
|
||||
monthly: {
|
||||
ItemsType: YearMonthItems<Year1BasedMonth>;
|
||||
DateTimeRangeType: undefined;
|
||||
MonthRangeType: TextualYearMonth | '';
|
||||
};
|
||||
}
|
||||
|
||||
export interface CommonTrendsChartProps<T extends TrendsChartDateType> {
|
||||
chartMode: T;
|
||||
items: TrendsChartTypes[T]['ItemsType'][];
|
||||
stacked?: boolean;
|
||||
startTime: TrendsChartTypes[T]['DateTimeRangeType'];
|
||||
endTime: TrendsChartTypes[T]['DateTimeRangeType'];
|
||||
startYearMonth: TrendsChartTypes[T]['MonthRangeType'];
|
||||
endYearMonth: TrendsChartTypes[T]['MonthRangeType'];
|
||||
fiscalYearStart: number;
|
||||
sortingType: number;
|
||||
dataAggregationType: ChartDataAggregationType;
|
||||
dateAggregationType: number;
|
||||
idField?: string;
|
||||
nameField: string;
|
||||
valueField: string;
|
||||
colorField?: string;
|
||||
hiddenField?: string;
|
||||
displayOrdersField?: string;
|
||||
translateName?: boolean;
|
||||
defaultCurrency?: string;
|
||||
enableClickItem?: boolean;
|
||||
}
|
||||
|
||||
export interface TrendsBarChartClickEvent {
|
||||
itemId: string;
|
||||
dateRange: TimeRangeAndDateType;
|
||||
}
|
||||
|
||||
function buildDailyAllDateRanges(props: CommonTrendsChartProps<'daily'>): YearUnixTime[] | FiscalYearUnixTime[] | YearQuarterUnixTime[] | YearMonthUnixTime[] | YearMonthDayUnixTime[] {
|
||||
let startTime: number = props.startTime;
|
||||
let endTime: number = props.endTime;
|
||||
|
||||
if ((!startTime || !endTime) && props.items && props.items.length) {
|
||||
let minUnixTime = Number.MAX_SAFE_INTEGER, maxUnixTime = 0;
|
||||
|
||||
for (const accountItem of props.items) {
|
||||
for (const dataItem of accountItem.items) {
|
||||
const dateTime = getYearMonthDayDateTime(dataItem.year, dataItem.month, dataItem.day);
|
||||
const unixTime = dateTime.getUnixTime();
|
||||
|
||||
if (unixTime < minUnixTime) {
|
||||
minUnixTime = unixTime;
|
||||
}
|
||||
|
||||
if (unixTime > maxUnixTime) {
|
||||
maxUnixTime = unixTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minUnixTime < Number.MAX_SAFE_INTEGER && maxUnixTime > 0) {
|
||||
startTime = minUnixTime;
|
||||
endTime = maxUnixTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (props.dateAggregationType === ChartDateAggregationType.Day.type) {
|
||||
return getAllDaysStartAndEndUnixTimes(startTime, endTime);
|
||||
} else {
|
||||
const startYearMonth = getGregorianCalendarYearAndMonthFromUnixTime(startTime);
|
||||
const endYearMonth = getGregorianCalendarYearAndMonthFromUnixTime(endTime);
|
||||
return getAllDateRangesByYearMonthRange(startYearMonth, endYearMonth, props.fiscalYearStart, props.dateAggregationType);
|
||||
}
|
||||
}
|
||||
|
||||
function buildMonthlyAllDateRanges(props: CommonTrendsChartProps<'monthly'>): YearUnixTime[] | FiscalYearUnixTime[] | YearQuarterUnixTime[] | YearMonthUnixTime[] {
|
||||
return getAllDateRangesFromItems(props.items, props.startYearMonth, props.endYearMonth, props.fiscalYearStart, props.dateAggregationType);
|
||||
}
|
||||
|
||||
export function useTrendsChartBase<T extends TrendsChartDateType>(props: CommonTrendsChartProps<T>) {
|
||||
const { tt } = useI18n();
|
||||
|
||||
const allDateRanges = computed<YearUnixTime[] | FiscalYearUnixTime[] | YearQuarterUnixTime[] | YearMonthUnixTime[] | YearMonthDayUnixTime[]>(() => {
|
||||
if (props.chartMode === 'daily') {
|
||||
return buildDailyAllDateRanges(props as CommonTrendsChartProps<'daily'>);
|
||||
} else if (props.chartMode === 'monthly') {
|
||||
return buildMonthlyAllDateRanges(props as CommonTrendsChartProps<'monthly'>);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
function getItemName(name: string): string {
|
||||
return props.translateName ? tt(name) : name;
|
||||
}
|
||||
|
||||
return {
|
||||
// computed states
|
||||
allDateRanges,
|
||||
// functions
|
||||
getItemName
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user