mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-20 17:54:30 +08:00
support setting timezone type in reconciliation statement dialog / page
This commit is contained in:
@@ -3,11 +3,12 @@ import { computed } from 'vue';
|
|||||||
import { useI18n } from '@/locales/helpers.ts';
|
import { useI18n } from '@/locales/helpers.ts';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
type DateTime,
|
||||||
type UnixTimeRange,
|
type UnixTimeRange,
|
||||||
type YearUnixTime,
|
type YearUnixTime,
|
||||||
type YearQuarterUnixTime,
|
type YearQuarterUnixTime,
|
||||||
type YearMonthUnixTime,
|
type YearMonthUnixTime,
|
||||||
YearMonthDayUnixTime,
|
YearMonthDayUnixTime
|
||||||
} from '@/core/datetime.ts';
|
} from '@/core/datetime.ts';
|
||||||
import type { FiscalYearUnixTime } from '@/core/fiscalyear.ts';
|
import type { FiscalYearUnixTime } from '@/core/fiscalyear.ts';
|
||||||
import { ChartDateAggregationType } from '@/core/statistics.ts';
|
import { ChartDateAggregationType } from '@/core/statistics.ts';
|
||||||
@@ -19,13 +20,14 @@ import { sumAmounts } from '@/lib/numeral.ts';
|
|||||||
import {
|
import {
|
||||||
parseDateTimeFromUnixTime,
|
parseDateTimeFromUnixTime,
|
||||||
getGregorianCalendarYearAndMonthFromUnixTime,
|
getGregorianCalendarYearAndMonthFromUnixTime,
|
||||||
getYearFirstUnixTimeBySpecifiedUnixTime,
|
getYearFirstDateTimeBySpecifiedDateTime,
|
||||||
getQuarterFirstUnixTimeBySpecifiedUnixTime,
|
getQuarterFirstTimeTimeBySpecifiedUnixTime,
|
||||||
getMonthFirstUnixTimeBySpecifiedUnixTime,
|
getMonthFirstDateTimeBySpecifiedUnixTime,
|
||||||
getDayFirstUnixTimeBySpecifiedUnixTime,
|
getDayFirstDateTimeBySpecifiedUnixTime,
|
||||||
getAllDaysStartAndEndUnixTimes,
|
getAllDaysStartAndEndUnixTimes,
|
||||||
getFiscalYearStartUnixTime
|
getFiscalYearStartDateTime
|
||||||
} from '@/lib/datetime.ts';
|
} from '@/lib/datetime.ts';
|
||||||
|
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
|
||||||
import { getAllDateRangesByYearMonthRange } from '@/lib/statistics.ts';
|
import { getAllDateRangesByYearMonthRange } from '@/lib/statistics.ts';
|
||||||
|
|
||||||
export interface AccountBalanceUnixTimeAndBalanceRange extends UnixTimeRange {
|
export interface AccountBalanceUnixTimeAndBalanceRange extends UnixTimeRange {
|
||||||
@@ -47,6 +49,7 @@ export interface AccountBalanceTrendsChartItem {
|
|||||||
export interface CommonAccountBalanceTrendsChartProps {
|
export interface CommonAccountBalanceTrendsChartProps {
|
||||||
items: TransactionReconciliationStatementResponseItem[] | undefined;
|
items: TransactionReconciliationStatementResponseItem[] | undefined;
|
||||||
dateAggregationType: number;
|
dateAggregationType: number;
|
||||||
|
timezoneUsedForDateRange: number;
|
||||||
fiscalYearStart: number;
|
fiscalYearStart: number;
|
||||||
account: AccountInfoResponse;
|
account: AccountInfoResponse;
|
||||||
}
|
}
|
||||||
@@ -117,29 +120,40 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dayDataItemsMap: Record<number, TransactionReconciliationStatementResponseItem[]> = {};
|
const dayDataItemsMap: Record<string, TransactionReconciliationStatementResponseItem[]> = {};
|
||||||
|
|
||||||
for (const dateItem of props.items) {
|
for (const dateItem of props.items) {
|
||||||
let dateRangeMinUnixTime = 0;
|
let minDateTime: DateTime;
|
||||||
|
let displayDate = '';
|
||||||
|
let transactionTimeUtfOffset: number | undefined = undefined;
|
||||||
|
|
||||||
|
if (props.timezoneUsedForDateRange === TimezoneTypeForStatistics.TransactionTimezone.type) {
|
||||||
|
transactionTimeUtfOffset = dateItem.utcOffset;
|
||||||
|
}
|
||||||
|
|
||||||
if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
|
if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
|
||||||
dateRangeMinUnixTime = getYearFirstUnixTimeBySpecifiedUnixTime(dateItem.time);
|
minDateTime = getYearFirstDateTimeBySpecifiedDateTime(dateItem.time, transactionTimeUtfOffset);
|
||||||
|
displayDate = formatDateTimeToGregorianLikeShortYear(minDateTime);
|
||||||
} else if (props.dateAggregationType === ChartDateAggregationType.FiscalYear.type) {
|
} else if (props.dateAggregationType === ChartDateAggregationType.FiscalYear.type) {
|
||||||
dateRangeMinUnixTime = getFiscalYearStartUnixTime(dateItem.time, props.fiscalYearStart);
|
minDateTime = getFiscalYearStartDateTime(dateItem.time, props.fiscalYearStart, transactionTimeUtfOffset);
|
||||||
|
displayDate = formatDateTimeToGregorianLikeFiscalYear(minDateTime);
|
||||||
} else if (props.dateAggregationType === ChartDateAggregationType.Quarter.type) {
|
} else if (props.dateAggregationType === ChartDateAggregationType.Quarter.type) {
|
||||||
dateRangeMinUnixTime = getQuarterFirstUnixTimeBySpecifiedUnixTime(dateItem.time);
|
minDateTime = getQuarterFirstTimeTimeBySpecifiedUnixTime(dateItem.time, transactionTimeUtfOffset);
|
||||||
|
displayDate = formatDateTimeToGregorianLikeYearQuarter(minDateTime);
|
||||||
} else if (props.dateAggregationType === ChartDateAggregationType.Month.type) {
|
} else if (props.dateAggregationType === ChartDateAggregationType.Month.type) {
|
||||||
dateRangeMinUnixTime = getMonthFirstUnixTimeBySpecifiedUnixTime(dateItem.time);
|
minDateTime = getMonthFirstDateTimeBySpecifiedUnixTime(dateItem.time, transactionTimeUtfOffset);
|
||||||
|
displayDate = formatDateTimeToGregorianLikeShortYearMonth(minDateTime);
|
||||||
} else if (props.dateAggregationType === ChartDateAggregationType.Day.type) {
|
} else if (props.dateAggregationType === ChartDateAggregationType.Day.type) {
|
||||||
dateRangeMinUnixTime = getDayFirstUnixTimeBySpecifiedUnixTime(dateItem.time);
|
minDateTime = getDayFirstDateTimeBySpecifiedUnixTime(dateItem.time, transactionTimeUtfOffset);
|
||||||
|
displayDate = formatDateTimeToShortDate(minDateTime);
|
||||||
} else {
|
} else {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataItems: TransactionReconciliationStatementResponseItem[] = dayDataItemsMap[dateRangeMinUnixTime] || [];
|
const dataItems: TransactionReconciliationStatementResponseItem[] = dayDataItemsMap[displayDate] || [];
|
||||||
dataItems.push(dateItem);
|
dataItems.push(dateItem);
|
||||||
|
|
||||||
dayDataItemsMap[dateRangeMinUnixTime] = dataItems;
|
dayDataItemsMap[displayDate] = dataItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastOpeningBalance = dataDateRange.value.minUnixTimeOpeningBalance;
|
let lastOpeningBalance = dataDateRange.value.minUnixTimeOpeningBalance;
|
||||||
@@ -150,7 +164,6 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
let lastAverageBalance = lastClosingBalance;
|
let lastAverageBalance = lastClosingBalance;
|
||||||
|
|
||||||
for (const dateRange of allDateRanges.value) {
|
for (const dateRange of allDateRanges.value) {
|
||||||
const dataItems = dayDataItemsMap[dateRange.minUnixTime];
|
|
||||||
const minDateTime = parseDateTimeFromUnixTime(dateRange.minUnixTime);
|
const minDateTime = parseDateTimeFromUnixTime(dateRange.minUnixTime);
|
||||||
|
|
||||||
let displayDate = '';
|
let displayDate = '';
|
||||||
@@ -169,6 +182,8 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dataItems = dayDataItemsMap[displayDate];
|
||||||
|
|
||||||
if (isArray(dataItems)) {
|
if (isArray(dataItems)) {
|
||||||
if (dataItems.length < 1) {
|
if (dataItems.length < 1) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
</f7-list>
|
</f7-list>
|
||||||
|
|
||||||
<f7-list class="margin-top-half" media-list virtual-list :virtual-list-params="{ items: allVirtualListItems, renderExternal, height: 'auto' }"
|
<f7-list class="margin-top-half" media-list virtual-list :virtual-list-params="{ items: allVirtualListItems, renderExternal, height: 'auto' }"
|
||||||
:key="`account-balance-trends-${dateAggregationType}`"
|
:key="`account-balance-trends-${dateAggregationType}-${timezoneUsedForDateRange}`"
|
||||||
v-else-if="!loading && allVirtualListItems && allVirtualListItems.length > 0">
|
v-else-if="!loading && allVirtualListItems && allVirtualListItems.length > 0">
|
||||||
<ul>
|
<ul>
|
||||||
<f7-list-item class="account-balance-trends-list-item"
|
<f7-list-item class="account-balance-trends-list-item"
|
||||||
|
|||||||
+17
-1
@@ -2,6 +2,18 @@ import type { TypeAndName, TypeAndDisplayName } from '@/core/base.ts';
|
|||||||
import type { CalendarType, ChineseCalendarLocaleData, PersianCalendarLocaleData } from '@/core/calendar.ts';
|
import type { CalendarType, ChineseCalendarLocaleData, PersianCalendarLocaleData } from '@/core/calendar.ts';
|
||||||
import type { NumeralSystem } from '@/core/numeral.ts';
|
import type { NumeralSystem } from '@/core/numeral.ts';
|
||||||
|
|
||||||
|
export type DateTimeUnit = 'years' | 'months' | 'days' | 'hours' | 'minutes' | 'seconds';
|
||||||
|
|
||||||
|
export interface DateTimeSetObject {
|
||||||
|
year?: number;
|
||||||
|
month?: number;
|
||||||
|
dayOfMonth?: number;
|
||||||
|
hour?: number;
|
||||||
|
minute?: number;
|
||||||
|
second?: number;
|
||||||
|
millisecond?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface DateTime {
|
export interface DateTime {
|
||||||
getUnixTime(): number;
|
getUnixTime(): number;
|
||||||
getLocalizedCalendarYear(options: DateTimeFormatOptions): string;
|
getLocalizedCalendarYear(options: DateTimeFormatOptions): string;
|
||||||
@@ -28,7 +40,11 @@ export interface DateTime {
|
|||||||
getSecond(): number;
|
getSecond(): number;
|
||||||
getDisplayAMPM(options: DateTimeFormatOptions): string;
|
getDisplayAMPM(options: DateTimeFormatOptions): string;
|
||||||
getTimezoneUtcOffsetMinutes(): number;
|
getTimezoneUtcOffsetMinutes(): number;
|
||||||
getDateTimeAfterDays(day: number): DateTime;
|
setTimezoneByUtcOffsetMinutes(offsetMinutes: number): DateTime;
|
||||||
|
setTimezoneByIANATimeZoneName(zoneName: string): DateTime;
|
||||||
|
add(amount: number, unit: DateTimeUnit): DateTime;
|
||||||
|
subtract(amount: number, unit: DateTimeUnit): DateTime;
|
||||||
|
set(value: DateTimeSetObject): DateTime;
|
||||||
toGregorianCalendarYearMonthDay(): YearMonthDay;
|
toGregorianCalendarYearMonthDay(): YearMonthDay;
|
||||||
toGregorianCalendarYear0BasedMonth(): Year0BasedMonth;
|
toGregorianCalendarYear0BasedMonth(): Year0BasedMonth;
|
||||||
format(format: string, options: DateTimeFormatOptions): string;
|
format(format: string, options: DateTimeFormatOptions): string;
|
||||||
|
|||||||
+102
-97
@@ -12,6 +12,8 @@ import {
|
|||||||
CalendarType
|
CalendarType
|
||||||
} from '@/core/calendar.ts';
|
} from '@/core/calendar.ts';
|
||||||
import {
|
import {
|
||||||
|
type DateTimeUnit,
|
||||||
|
type DateTimeSetObject,
|
||||||
type DateTime,
|
type DateTime,
|
||||||
type DateTimeFormatOptions,
|
type DateTimeFormatOptions,
|
||||||
type TextualYearMonth,
|
type TextualYearMonth,
|
||||||
@@ -307,8 +309,32 @@ class MomentDateTime implements DateTime {
|
|||||||
return this.instance.utcOffset();
|
return this.instance.utcOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getDateTimeAfterDays(days: number): DateTime {
|
public setTimezoneByUtcOffsetMinutes(ufcOffset: number): DateTime {
|
||||||
return MomentDateTime.of(this.instance.clone().add(days, 'days'));
|
return MomentDateTime.of(this.instance.clone().tz(getFixedTimezoneName(ufcOffset)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public setTimezoneByIANATimeZoneName(timezoneName: string): DateTime {
|
||||||
|
return MomentDateTime.of(this.instance.clone().tz(timezoneName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public add(amount: number, unit: DateTimeUnit): DateTime {
|
||||||
|
return MomentDateTime.of(this.instance.clone().add(amount, unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
public subtract(amount: number, unit: DateTimeUnit): DateTime {
|
||||||
|
return MomentDateTime.of(this.instance.clone().subtract(amount, unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
public set(value: DateTimeSetObject): DateTime {
|
||||||
|
return MomentDateTime.of(this.instance.clone().set({
|
||||||
|
year: value.year,
|
||||||
|
month: isDefined(value.month) ? value.month - 1 : undefined,
|
||||||
|
date: value.dayOfMonth,
|
||||||
|
hour: value.hour,
|
||||||
|
minute: value.minute,
|
||||||
|
second: value.second,
|
||||||
|
millisecond: value.millisecond
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public toGregorianCalendarYearMonthDay(): YearMonthDay {
|
public toGregorianCalendarYearMonthDay(): YearMonthDay {
|
||||||
@@ -378,6 +404,14 @@ class MomentDateTime implements DateTime {
|
|||||||
return new MomentDateTime(instance);
|
return new MomentDateTime(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ofUnixTime(unixTime: number): DateTime {
|
||||||
|
return new MomentDateTime(moment.unix(unixTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ofFullDateTime(year: number, month: number, day: number, hour: number, minute: number, second: number, millisecond: number): DateTime {
|
||||||
|
return new MomentDateTime(moment().set({ year: year, month: month - 1, date: day, hour: hour, minute: minute, second: second, millisecond: millisecond }));
|
||||||
|
}
|
||||||
|
|
||||||
public static now(): DateTime {
|
public static now(): DateTime {
|
||||||
return new MomentDateTime(moment());
|
return new MomentDateTime(moment());
|
||||||
}
|
}
|
||||||
@@ -560,45 +594,39 @@ export function getUnixTimeFromLocalDatetime(datetime: Date): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getSameDateTimeWithCurrentTimezone(dateTime: DateTime): DateTime {
|
export function getSameDateTimeWithCurrentTimezone(dateTime: DateTime): DateTime {
|
||||||
const newDateTime = moment().set({
|
return MomentDateTime.now().set({
|
||||||
year: dateTime.getGregorianCalendarYear(),
|
year: dateTime.getGregorianCalendarYear(),
|
||||||
month: dateTime.getGregorianCalendarMonth() - 1,
|
month: dateTime.getGregorianCalendarMonth(),
|
||||||
date: dateTime.getGregorianCalendarDay(),
|
dayOfMonth: dateTime.getGregorianCalendarDay(),
|
||||||
hour: dateTime.getHour(),
|
hour: dateTime.getHour(),
|
||||||
minute: dateTime.getMinute(),
|
minute: dateTime.getMinute(),
|
||||||
second: dateTime.getSecond(),
|
second: dateTime.getSecond(),
|
||||||
millisecond: 0
|
millisecond: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
return MomentDateTime.of(newDateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSameDateTimeWithBrowserTimezone(dateTime: DateTime): DateTime {
|
export function getSameDateTimeWithBrowserTimezone(dateTime: DateTime): DateTime {
|
||||||
const newDateTime = moment().tz(getBrowserTimezoneName()).set({
|
return MomentDateTime.now().setTimezoneByIANATimeZoneName(getBrowserTimezoneName()).set({
|
||||||
year: dateTime.getGregorianCalendarYear(),
|
year: dateTime.getGregorianCalendarYear(),
|
||||||
month: dateTime.getGregorianCalendarMonth() - 1,
|
month: dateTime.getGregorianCalendarMonth(),
|
||||||
date: dateTime.getGregorianCalendarDay(),
|
dayOfMonth: dateTime.getGregorianCalendarDay(),
|
||||||
hour: dateTime.getHour(),
|
|
||||||
minute: dateTime.getMinute(),
|
|
||||||
second: dateTime.getSecond(),
|
|
||||||
millisecond: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
return MomentDateTime.of(newDateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getSameDateTimeWithTimezoneOffset(dateTime: DateTime, utcOffset: number): DateTime {
|
|
||||||
const newDateTime = moment().tz(getFixedTimezoneName(utcOffset)).set({
|
|
||||||
year: dateTime.getGregorianCalendarYear(),
|
|
||||||
month: dateTime.getGregorianCalendarMonth() - 1,
|
|
||||||
date: dateTime.getGregorianCalendarDay(),
|
|
||||||
hour: dateTime.getHour(),
|
hour: dateTime.getHour(),
|
||||||
minute: dateTime.getMinute(),
|
minute: dateTime.getMinute(),
|
||||||
second: dateTime.getSecond(),
|
second: dateTime.getSecond(),
|
||||||
millisecond: 0
|
millisecond: 0
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return MomentDateTime.of(newDateTime);
|
export function getSameDateTimeWithTimezoneOffset(dateTime: DateTime, utcOffset: number): DateTime {
|
||||||
|
return MomentDateTime.now().setTimezoneByUtcOffsetMinutes(utcOffset).set({
|
||||||
|
year: dateTime.getGregorianCalendarYear(),
|
||||||
|
month: dateTime.getGregorianCalendarMonth(),
|
||||||
|
dayOfMonth: dateTime.getGregorianCalendarDay(),
|
||||||
|
hour: dateTime.getHour(),
|
||||||
|
minute: dateTime.getMinute(),
|
||||||
|
second: dateTime.getSecond(),
|
||||||
|
millisecond: 0
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentDateTime(): DateTime {
|
export function getCurrentDateTime(): DateTime {
|
||||||
@@ -610,20 +638,19 @@ export function getCurrentUnixTime(): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getYearMonthDayDateTime(year: number, month: number, day: number): DateTime {
|
export function getYearMonthDayDateTime(year: number, month: number, day: number): DateTime {
|
||||||
const date = moment().set({ year: year, month: month - 1, date: day, hour: 0, minute: 0, second: 0, millisecond: 0 });
|
return MomentDateTime.ofFullDateTime(year, month, day, 0, 0, 0, 0);
|
||||||
return MomentDateTime.of(date);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseDateTimeFromUnixTime(unixTime: number): DateTime {
|
export function parseDateTimeFromUnixTime(unixTime: number): DateTime {
|
||||||
return MomentDateTime.of(moment.unix(unixTime));
|
return MomentDateTime.ofUnixTime(unixTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseDateTimeFromUnixTimeWithBrowserTimezone(unixTime: number): DateTime {
|
export function parseDateTimeFromUnixTimeWithBrowserTimezone(unixTime: number): DateTime {
|
||||||
return MomentDateTime.of(moment.unix(unixTime).tz(getBrowserTimezoneName()));
|
return MomentDateTime.ofUnixTime(unixTime).setTimezoneByIANATimeZoneName(getBrowserTimezoneName());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseDateTimeFromUnixTimeWithTimezoneOffset(unixTime: number, utcOffset: number): DateTime {
|
export function parseDateTimeFromUnixTimeWithTimezoneOffset(unixTime: number, utcOffset: number): DateTime {
|
||||||
return MomentDateTime.of(moment.unix(unixTime).tz(getFixedTimezoneName(utcOffset)));
|
return MomentDateTime.ofUnixTime(unixTime).setTimezoneByUtcOffsetMinutes(utcOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseDateTimeFromKnownDateTimeFormat(dateTime: string, format: KnownDateTimeFormat): DateTime | undefined {
|
export function parseDateTimeFromKnownDateTimeFormat(dateTime: string, format: KnownDateTimeFormat): DateTime | undefined {
|
||||||
@@ -804,27 +831,21 @@ export function getThisYearLastUnixTime(): number {
|
|||||||
return moment.unix(getThisYearFirstUnixTime()).add(1, 'years').subtract(1, 'seconds').unix();
|
return moment.unix(getThisYearFirstUnixTime()).add(1, 'years').subtract(1, 'seconds').unix();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getYearFirstUnixTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): number {
|
export function getYearFirstDateTimeBySpecifiedDateTime(unixTime: number, utcOffset?: number): DateTime {
|
||||||
let date = moment.unix(unixTime);
|
let date = moment.unix(unixTime);
|
||||||
|
|
||||||
if (isNumber(utcOffset)) {
|
if (isNumber(utcOffset)) {
|
||||||
date = date.tz(getFixedTimezoneName(utcOffset));
|
date = date.tz(getFixedTimezoneName(utcOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
return date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(date.dayOfYear() - 1, 'days').unix();
|
return MomentDateTime.of(date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(date.dayOfYear() - 1, 'days'));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getYearLastUnixTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): number {
|
export function getYearLastDateTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): DateTime {
|
||||||
let date = moment.unix(getYearFirstUnixTimeBySpecifiedUnixTime(unixTime, utcOffset));
|
return getYearFirstDateTimeBySpecifiedDateTime(unixTime, utcOffset).add(1, 'years').subtract(1, 'seconds');
|
||||||
|
|
||||||
if (isNumber(utcOffset)) {
|
|
||||||
date = date.tz(getFixedTimezoneName(utcOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
return date.add(1, 'years').subtract(1, 'seconds').unix();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getQuarterFirstUnixTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): number {
|
export function getQuarterFirstTimeTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): DateTime {
|
||||||
let date = moment.unix(unixTime);
|
let date = moment.unix(unixTime);
|
||||||
|
|
||||||
if (isNumber(utcOffset)) {
|
if (isNumber(utcOffset)) {
|
||||||
@@ -834,57 +855,39 @@ export function getQuarterFirstUnixTimeBySpecifiedUnixTime(unixTime: number, utc
|
|||||||
date = date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
|
date = date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
|
||||||
const month = date.month();
|
const month = date.month();
|
||||||
const quarterStartMonth = Math.floor(month / 3) * 3;
|
const quarterStartMonth = Math.floor(month / 3) * 3;
|
||||||
return date.set({ month: quarterStartMonth, date: 1 }).unix();
|
return MomentDateTime.of(date.set({ month: quarterStartMonth, date: 1 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getQuarterLastUnixTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): number {
|
export function getQuarterLastTimeTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): DateTime {
|
||||||
let date = moment.unix(getQuarterFirstUnixTimeBySpecifiedUnixTime(unixTime, utcOffset));
|
return getQuarterFirstTimeTimeBySpecifiedUnixTime(unixTime, utcOffset).add(3, 'months').subtract(1, 'seconds');
|
||||||
|
|
||||||
if (isNumber(utcOffset)) {
|
|
||||||
date = date.tz(getFixedTimezoneName(utcOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
return date.add(3, 'months').subtract(1, 'seconds').unix();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMonthFirstUnixTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): number {
|
export function getMonthFirstDateTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): DateTime {
|
||||||
let date = moment.unix(unixTime);
|
let date = moment.unix(unixTime);
|
||||||
|
|
||||||
if (isNumber(utcOffset)) {
|
if (isNumber(utcOffset)) {
|
||||||
date = date.tz(getFixedTimezoneName(utcOffset));
|
date = date.tz(getFixedTimezoneName(utcOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
return date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(date.date() - 1, 'days').unix();
|
return MomentDateTime.of(date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).subtract(date.date() - 1, 'days'));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMonthLastUnixTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): number {
|
export function getMonthLastDateTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): DateTime {
|
||||||
let date = moment.unix(getMonthFirstUnixTimeBySpecifiedUnixTime(unixTime, utcOffset));
|
return getMonthFirstDateTimeBySpecifiedUnixTime(unixTime, utcOffset).add(1, 'months').subtract(1, 'seconds');
|
||||||
|
|
||||||
if (isNumber(utcOffset)) {
|
|
||||||
date = date.tz(getFixedTimezoneName(utcOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
return date.add(1, 'months').subtract(1, 'seconds').unix();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDayFirstUnixTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): number {
|
export function getDayFirstDateTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): DateTime {
|
||||||
let date = moment.unix(unixTime);
|
let date = moment.unix(unixTime);
|
||||||
|
|
||||||
if (isNumber(utcOffset)) {
|
if (isNumber(utcOffset)) {
|
||||||
date = date.tz(getFixedTimezoneName(utcOffset));
|
date = date.tz(getFixedTimezoneName(utcOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
return date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).unix();
|
return MomentDateTime.of(date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDayLastUnixTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): number {
|
export function getDayLastDateTimeBySpecifiedUnixTime(unixTime: number, utcOffset?: number): DateTime {
|
||||||
let date = moment.unix(unixTime);
|
return getDayFirstDateTimeBySpecifiedUnixTime(unixTime, utcOffset).add(1, 'days').subtract(1, 'seconds');
|
||||||
|
|
||||||
if (isNumber(utcOffset)) {
|
|
||||||
date = date.tz(getFixedTimezoneName(utcOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
return date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).add(1, 'days').subtract(1, 'seconds').unix();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getYearFirstUnixTime(year: number): number {
|
export function getYearFirstUnixTime(year: number): number {
|
||||||
@@ -1114,11 +1117,11 @@ export function getAllDaysStartAndEndUnixTimes(startUnixTime: number, endUnixTim
|
|||||||
|
|
||||||
while (unixTime <= endUnixTime) {
|
while (unixTime <= endUnixTime) {
|
||||||
const currentDateTime = parseDateTimeFromUnixTime(unixTime);
|
const currentDateTime = parseDateTimeFromUnixTime(unixTime);
|
||||||
const currentDayMinUnixTime = getDayFirstUnixTimeBySpecifiedUnixTime(unixTime);
|
const currentDayMinDateTime = getDayFirstDateTimeBySpecifiedUnixTime(unixTime);
|
||||||
const currentDayMaxUnixTime = getDayLastUnixTimeBySpecifiedUnixTime(unixTime);
|
const currentDayMaxDateTime = getDayLastDateTimeBySpecifiedUnixTime(unixTime);
|
||||||
|
|
||||||
allYearMonthDayTimes.push(YearMonthDayUnixTime.of(currentDateTime.toGregorianCalendarYearMonthDay(), currentDayMinUnixTime, currentDayMaxUnixTime));
|
allYearMonthDayTimes.push(YearMonthDayUnixTime.of(currentDateTime.toGregorianCalendarYearMonthDay(), currentDayMinDateTime.getUnixTime(), currentDayMaxDateTime.getUnixTime()));
|
||||||
unixTime = currentDayMaxUnixTime + 1;
|
unixTime = currentDayMaxDateTime.getUnixTime() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return allYearMonthDayTimes;
|
return allYearMonthDayTimes;
|
||||||
@@ -1450,14 +1453,14 @@ export function getFullMonthDateRange(minTime: number, maxTime: number, firstDay
|
|||||||
return getDateRangeByDateType(DateRange.ThisMonth.type, firstDayOfWeek, fiscalYearStart);
|
return getDateRangeByDateType(DateRange.ThisMonth.type, firstDayOfWeek, fiscalYearStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
const monthFirstUnixTime = getMonthFirstUnixTimeBySpecifiedUnixTime(minTime);
|
const monthFirstDateTime = getMonthFirstDateTimeBySpecifiedUnixTime(minTime);
|
||||||
const monthLastUnixTime = getMonthLastUnixTimeBySpecifiedUnixTime(minTime);
|
const monthLastDateTime = getMonthLastDateTimeBySpecifiedUnixTime(minTime);
|
||||||
const dateType = getDateTypeByDateRange(monthFirstUnixTime, monthLastUnixTime, firstDayOfWeek, fiscalYearStart, DateRangeScene.Normal);
|
const dateType = getDateTypeByDateRange(monthFirstDateTime.getUnixTime(), monthLastDateTime.getUnixTime(), firstDayOfWeek, fiscalYearStart, DateRangeScene.Normal);
|
||||||
|
|
||||||
const dateRange: TimeRangeAndDateType = {
|
const dateRange: TimeRangeAndDateType = {
|
||||||
dateType: dateType,
|
dateType: dateType,
|
||||||
maxTime: monthLastUnixTime,
|
maxTime: monthLastDateTime.getUnixTime(),
|
||||||
minTime: monthFirstUnixTime
|
minTime: monthFirstDateTime.getUnixTime()
|
||||||
};
|
};
|
||||||
|
|
||||||
return dateRange;
|
return dateRange;
|
||||||
@@ -1487,8 +1490,8 @@ export function getCombinedDateAndTimeValues(date: Date, numeralSystem: NumeralS
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getValidMonthDayOrCurrentDayShortDate(unixTime: number, currentShortDate: string): TextualYearMonthDay {
|
export function getValidMonthDayOrCurrentDayShortDate(unixTime: number, currentShortDate: string): TextualYearMonthDay {
|
||||||
const currentTime = moment();
|
const currentTime = getCurrentDateTime();
|
||||||
const monthLastTime = moment.unix(getMonthLastUnixTimeBySpecifiedUnixTime(unixTime));
|
const monthLastTime = getMonthLastDateTimeBySpecifiedUnixTime(unixTime);
|
||||||
|
|
||||||
if (currentShortDate) {
|
if (currentShortDate) {
|
||||||
const yearMonthDay = currentShortDate.split('-');
|
const yearMonthDay = currentShortDate.split('-');
|
||||||
@@ -1496,17 +1499,17 @@ export function getValidMonthDayOrCurrentDayShortDate(unixTime: number, currentS
|
|||||||
if (yearMonthDay.length === 3) {
|
if (yearMonthDay.length === 3) {
|
||||||
const currentDay = parseInt(yearMonthDay[2] as string);
|
const currentDay = parseInt(yearMonthDay[2] as string);
|
||||||
|
|
||||||
if (currentDay < monthLastTime.date()) {
|
if (currentDay < monthLastTime.getGregorianCalendarDay()) {
|
||||||
return MomentDateTime.of(monthLastTime.set({ date: currentDay })).getGregorianCalendarYearDashMonthDashDay();
|
return monthLastTime.set({ dayOfMonth: currentDay }).getGregorianCalendarYearDashMonthDashDay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monthLastTime.year() === currentTime.year() && monthLastTime.month() === currentTime.month()) {
|
if (monthLastTime.getGregorianCalendarYear() === currentTime.getGregorianCalendarYear() && monthLastTime.getGregorianCalendarMonth() === currentTime.getGregorianCalendarMonth()) {
|
||||||
return MomentDateTime.of(currentTime).getGregorianCalendarYearDashMonthDashDay();
|
return currentTime.getGregorianCalendarYearDashMonthDashDay();
|
||||||
}
|
}
|
||||||
|
|
||||||
return MomentDateTime.of(monthLastTime).getGregorianCalendarYearDashMonthDashDay();
|
return monthLastTime.getGregorianCalendarYearDashMonthDashDay();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isDateRangeMatchFullYears(minTime: number, maxTime: number): boolean {
|
export function isDateRangeMatchFullYears(minTime: number, maxTime: number): boolean {
|
||||||
@@ -1567,7 +1570,7 @@ export function getFiscalYearFromUnixTime(unixTime: number, fiscalYearStartValue
|
|||||||
return year + 1;
|
return year + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFiscalYearStartUnixTime(unixTime: number, fiscalYearStartValue: number, utcOffset?: number): number {
|
export function getFiscalYearStartDateTime(unixTime: number, fiscalYearStartValue: number, utcOffset?: number): DateTime {
|
||||||
let date = moment.unix(unixTime);
|
let date = moment.unix(unixTime);
|
||||||
|
|
||||||
if (isNumber(utcOffset)) {
|
if (isNumber(utcOffset)) {
|
||||||
@@ -1582,7 +1585,7 @@ export function getFiscalYearStartUnixTime(unixTime: number, fiscalYearStartValu
|
|||||||
finalDate = finalDate.tz(getFixedTimezoneName(utcOffset));
|
finalDate = finalDate.tz(getFixedTimezoneName(utcOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
return finalDate.year(date.year()).month(0).date(1).hour(0).minute(0).second(0).millisecond(0).unix();
|
return MomentDateTime.of(finalDate.year(date.year()).month(0).date(1).hour(0).minute(0).second(0).millisecond(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
let fiscalYearStart = FiscalYearStart.valueOf(fiscalYearStartValue);
|
let fiscalYearStart = FiscalYearStart.valueOf(fiscalYearStartValue);
|
||||||
@@ -1611,7 +1614,7 @@ export function getFiscalYearStartUnixTime(unixTime: number, fiscalYearStartValu
|
|||||||
finalDate = finalDate.tz(getFixedTimezoneName(utcOffset));
|
finalDate = finalDate.tz(getFixedTimezoneName(utcOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
return finalDate.set({
|
return MomentDateTime.of(finalDate.set({
|
||||||
year: startYear,
|
year: startYear,
|
||||||
month: fiscalYearStart.month - 1, // 0-index
|
month: fiscalYearStart.month - 1, // 0-index
|
||||||
date: fiscalYearStart.day,
|
date: fiscalYearStart.day,
|
||||||
@@ -1619,17 +1622,19 @@ export function getFiscalYearStartUnixTime(unixTime: number, fiscalYearStartValu
|
|||||||
minute: 0,
|
minute: 0,
|
||||||
second: 0,
|
second: 0,
|
||||||
millisecond: 0,
|
millisecond: 0,
|
||||||
}).unix();
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFiscalYearEndDateTime(unixTime: number, fiscalYearStart: number, utcOffset?: number): DateTime {
|
||||||
|
return getFiscalYearStartDateTime(unixTime, fiscalYearStart, utcOffset).add(1, 'years').subtract(1, 'seconds');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFiscalYearStartUnixTime(unixTime: number, fiscalYearStart: number, utcOffset?: number): number {
|
||||||
|
return getFiscalYearStartDateTime(unixTime, fiscalYearStart, utcOffset).getUnixTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFiscalYearEndUnixTime(unixTime: number, fiscalYearStart: number, utcOffset?: number): number {
|
export function getFiscalYearEndUnixTime(unixTime: number, fiscalYearStart: number, utcOffset?: number): number {
|
||||||
let date = moment.unix(getFiscalYearStartUnixTime(unixTime, fiscalYearStart));
|
return getFiscalYearEndDateTime(unixTime, fiscalYearStart, utcOffset).getUnixTime();
|
||||||
|
|
||||||
if (isNumber(utcOffset)) {
|
|
||||||
date = date.tz(getFixedTimezoneName(utcOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
return date.add(1, 'years').subtract(1, 'seconds').unix();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentFiscalYear(fiscalYearStart: number, utcOffset?: number): number {
|
export function getCurrentFiscalYear(fiscalYearStart: number, utcOffset?: number): number {
|
||||||
|
|||||||
@@ -772,7 +772,7 @@ export const useStatisticsStore = defineStore('statistics', () => {
|
|||||||
// fill in missing days with last known balance
|
// fill in missing days with last known balance
|
||||||
for (let i = 1; i <= missingDays; i++) {
|
for (let i = 1; i <= missingDays; i++) {
|
||||||
const missingStatisticResponseItems: TransactionStatisticResponseItem[] = [];
|
const missingStatisticResponseItems: TransactionStatisticResponseItem[] = [];
|
||||||
const dateTime: DateTime = lastAssetTrendItemDate.getDateTimeAfterDays(i);
|
const dateTime: DateTime = lastAssetTrendItemDate.add(i, 'days');
|
||||||
|
|
||||||
for (const item of values(lastAssetTrendItemMap)) {
|
for (const item of values(lastAssetTrendItemMap)) {
|
||||||
const statisticResponseItem: TransactionStatisticResponseItem = {
|
const statisticResponseItem: TransactionStatisticResponseItem = {
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
|
|||||||
|
|
||||||
import type { TypeAndDisplayName } from '@/core/base.ts';
|
import type { TypeAndDisplayName } from '@/core/base.ts';
|
||||||
import type { WeekDayValue } from '@/core/datetime.ts';
|
import type { WeekDayValue } from '@/core/datetime.ts';
|
||||||
|
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
|
||||||
import { TransactionType } from '@/core/transaction.ts';
|
import { TransactionType } from '@/core/transaction.ts';
|
||||||
import { StatisticsAnalysisType } from '@/core/statistics.ts';
|
import { StatisticsAnalysisType, ChartDateAggregationType } from '@/core/statistics.ts';
|
||||||
import { KnownFileType } from '@/core/file.ts';
|
import { KnownFileType } from '@/core/file.ts';
|
||||||
|
|
||||||
import type { Account } from '@/models/account.ts';
|
import type { Account } from '@/models/account.ts';
|
||||||
import type { TransactionCategory } from '@/models/transaction_category.ts';
|
import type { TransactionCategory } from '@/models/transaction_category.ts';
|
||||||
import type {
|
import type {
|
||||||
@@ -33,6 +35,7 @@ export function useReconciliationStatementPageBase() {
|
|||||||
tt,
|
tt,
|
||||||
getAllAccountBalanceTrendChartTypes,
|
getAllAccountBalanceTrendChartTypes,
|
||||||
getAllStatisticsDateAggregationTypesWithShortName,
|
getAllStatisticsDateAggregationTypesWithShortName,
|
||||||
|
getAllTimezoneTypesUsedForStatistics,
|
||||||
formatDateTimeToLongDateTime,
|
formatDateTimeToLongDateTime,
|
||||||
formatDateTimeToLongDate,
|
formatDateTimeToLongDate,
|
||||||
formatDateTimeToShortTime,
|
formatDateTimeToShortTime,
|
||||||
@@ -49,6 +52,8 @@ export function useReconciliationStatementPageBase() {
|
|||||||
const startTime = ref<number>(0);
|
const startTime = ref<number>(0);
|
||||||
const endTime = ref<number>(0);
|
const endTime = ref<number>(0);
|
||||||
const reconciliationStatements = ref<TransactionReconciliationStatementResponseWithInfo | undefined>(undefined);
|
const reconciliationStatements = ref<TransactionReconciliationStatementResponseWithInfo | undefined>(undefined);
|
||||||
|
const chartDataDateAggregationType = ref<number>(ChartDateAggregationType.Day.type);
|
||||||
|
const timezoneUsedForDateRange = ref<number>(TimezoneTypeForStatistics.ApplicationTimezone.type);
|
||||||
|
|
||||||
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
|
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
|
||||||
const fiscalYearStart = computed<number>(() => userStore.currentUserFiscalYearStart);
|
const fiscalYearStart = computed<number>(() => userStore.currentUserFiscalYearStart);
|
||||||
@@ -56,6 +61,7 @@ export function useReconciliationStatementPageBase() {
|
|||||||
|
|
||||||
const allChartTypes = computed<TypeAndDisplayName[]>(() => getAllAccountBalanceTrendChartTypes());
|
const allChartTypes = computed<TypeAndDisplayName[]>(() => getAllAccountBalanceTrendChartTypes());
|
||||||
const allDateAggregationTypes = computed<TypeAndDisplayName[]>(() => getAllStatisticsDateAggregationTypesWithShortName(StatisticsAnalysisType.AssetTrends));
|
const allDateAggregationTypes = computed<TypeAndDisplayName[]>(() => getAllStatisticsDateAggregationTypesWithShortName(StatisticsAnalysisType.AssetTrends));
|
||||||
|
const allTimezoneTypesUsedForDateRange = computed<TypeAndDisplayName[]>(() => getAllTimezoneTypesUsedForStatistics());
|
||||||
|
|
||||||
const currentAccount = computed(() => allAccountsMap.value[accountId.value]);
|
const currentAccount = computed(() => allAccountsMap.value[accountId.value]);
|
||||||
const currentAccountCurrency = computed<string>(() => currentAccount.value?.currency ?? defaultCurrency.value);
|
const currentAccountCurrency = computed<string>(() => currentAccount.value?.currency ?? defaultCurrency.value);
|
||||||
@@ -286,12 +292,15 @@ export function useReconciliationStatementPageBase() {
|
|||||||
startTime,
|
startTime,
|
||||||
endTime,
|
endTime,
|
||||||
reconciliationStatements,
|
reconciliationStatements,
|
||||||
|
chartDataDateAggregationType,
|
||||||
|
timezoneUsedForDateRange,
|
||||||
// computed states
|
// computed states
|
||||||
firstDayOfWeek,
|
firstDayOfWeek,
|
||||||
fiscalYearStart,
|
fiscalYearStart,
|
||||||
defaultCurrency,
|
defaultCurrency,
|
||||||
allChartTypes,
|
allChartTypes,
|
||||||
allDateAggregationTypes,
|
allDateAggregationTypes,
|
||||||
|
allTimezoneTypesUsedForDateRange,
|
||||||
currentAccount,
|
currentAccount,
|
||||||
currentAccountCurrency,
|
currentAccountCurrency,
|
||||||
isCurrentLiabilityAccount,
|
isCurrentLiabilityAccount,
|
||||||
|
|||||||
@@ -44,6 +44,14 @@
|
|||||||
:title="dateAggregationType.displayName"
|
:title="dateAggregationType.displayName"
|
||||||
@click="chartDataDateAggregationType = dateAggregationType.type"
|
@click="chartDataDateAggregationType = dateAggregationType.type"
|
||||||
v-for="dateAggregationType in allDateAggregationTypes"></v-list-item>
|
v-for="dateAggregationType in allDateAggregationTypes"></v-list-item>
|
||||||
|
<v-divider class="my-2"/>
|
||||||
|
<v-list-subheader :title="tt('Timezone Used for Date Range')"/>
|
||||||
|
<v-list-item :key="timezoneType.type" :value="timezoneType.type"
|
||||||
|
:prepend-icon="timezoneTypeIconMap[timezoneType.type]"
|
||||||
|
:append-icon="timezoneUsedForDateRange === timezoneType.type ? mdiCheck : undefined"
|
||||||
|
:title="timezoneType.displayName"
|
||||||
|
v-for="timezoneType in allTimezoneTypesUsedForDateRange"
|
||||||
|
@click="timezoneUsedForDateRange = timezoneType.type"></v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
@@ -227,6 +235,7 @@
|
|||||||
<account-balance-trends-chart
|
<account-balance-trends-chart
|
||||||
:type="chartType"
|
:type="chartType"
|
||||||
:date-aggregation-type="chartDataDateAggregationType"
|
:date-aggregation-type="chartDataDateAggregationType"
|
||||||
|
:timezone-used-for-date-range="timezoneUsedForDateRange"
|
||||||
:fiscal-year-start="fiscalYearStart"
|
:fiscal-year-start="fiscalYearStart"
|
||||||
:items="[]"
|
:items="[]"
|
||||||
:legend-name="isCurrentLiabilityAccount ? tt('Account Outstanding Balance') : tt('Account Balance')"
|
:legend-name="isCurrentLiabilityAccount ? tt('Account Outstanding Balance') : tt('Account Balance')"
|
||||||
@@ -238,6 +247,7 @@
|
|||||||
<account-balance-trends-chart
|
<account-balance-trends-chart
|
||||||
:type="chartType"
|
:type="chartType"
|
||||||
:date-aggregation-type="chartDataDateAggregationType"
|
:date-aggregation-type="chartDataDateAggregationType"
|
||||||
|
:timezone-used-for-date-range="timezoneUsedForDateRange"
|
||||||
:fiscal-year-start="fiscalYearStart"
|
:fiscal-year-start="fiscalYearStart"
|
||||||
:items="reconciliationStatements?.transactions"
|
:items="reconciliationStatements?.transactions"
|
||||||
:legend-name="isCurrentLiabilityAccount ? tt('Account Outstanding Balance') : tt('Account Balance')"
|
:legend-name="isCurrentLiabilityAccount ? tt('Account Outstanding Balance') : tt('Account Balance')"
|
||||||
@@ -280,6 +290,7 @@ import { useTransactionsStore } from '@/stores/transaction.ts';
|
|||||||
|
|
||||||
import type { NameNumeralValue } from '@/core/base.ts';
|
import type { NameNumeralValue } from '@/core/base.ts';
|
||||||
import type { NumeralSystem } from '@/core/numeral.ts';
|
import type { NumeralSystem } from '@/core/numeral.ts';
|
||||||
|
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
|
||||||
import { TransactionType } from '@/core/transaction.ts';
|
import { TransactionType } from '@/core/transaction.ts';
|
||||||
import { AccountBalanceTrendChartType, ChartDateAggregationType } from '@/core/statistics.ts';
|
import { AccountBalanceTrendChartType, ChartDateAggregationType } from '@/core/statistics.ts';
|
||||||
import { KnownFileType } from '@/core/file.ts';
|
import { KnownFileType } from '@/core/file.ts';
|
||||||
@@ -300,6 +311,8 @@ import {
|
|||||||
mdiChartWaterfall,
|
mdiChartWaterfall,
|
||||||
mdiCalendarTodayOutline,
|
mdiCalendarTodayOutline,
|
||||||
mdiCalendarMonthOutline,
|
mdiCalendarMonthOutline,
|
||||||
|
mdiHomeClockOutline,
|
||||||
|
mdiInvoiceTextClockOutline,
|
||||||
mdiLayersTripleOutline,
|
mdiLayersTripleOutline,
|
||||||
mdiInvoiceTextPlusOutline,
|
mdiInvoiceTextPlusOutline,
|
||||||
mdiInvoiceTextEditOutline,
|
mdiInvoiceTextEditOutline,
|
||||||
@@ -323,9 +336,12 @@ const {
|
|||||||
startTime,
|
startTime,
|
||||||
endTime,
|
endTime,
|
||||||
reconciliationStatements,
|
reconciliationStatements,
|
||||||
|
chartDataDateAggregationType,
|
||||||
|
timezoneUsedForDateRange,
|
||||||
fiscalYearStart,
|
fiscalYearStart,
|
||||||
allChartTypes,
|
allChartTypes,
|
||||||
allDateAggregationTypes,
|
allDateAggregationTypes,
|
||||||
|
allTimezoneTypesUsedForDateRange,
|
||||||
currentAccount,
|
currentAccount,
|
||||||
currentAccountCurrency,
|
currentAccountCurrency,
|
||||||
isCurrentLiabilityAccount,
|
isCurrentLiabilityAccount,
|
||||||
@@ -366,6 +382,11 @@ const chartDataDateAggregationTypeIconMap = {
|
|||||||
[ChartDateAggregationType.FiscalYear.type]: mdiLayersTripleOutline,
|
[ChartDateAggregationType.FiscalYear.type]: mdiLayersTripleOutline,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const timezoneTypeIconMap = {
|
||||||
|
[TimezoneTypeForStatistics.ApplicationTimezone.type]: mdiHomeClockOutline,
|
||||||
|
[TimezoneTypeForStatistics.TransactionTimezone.type]: mdiInvoiceTextClockOutline
|
||||||
|
};
|
||||||
|
|
||||||
const amountInputDialog = useTemplateRef<AmountInputDialogType>('amountInputDialog');
|
const amountInputDialog = useTemplateRef<AmountInputDialogType>('amountInputDialog');
|
||||||
const snackbar = useTemplateRef<SnackBarType>('snackbar');
|
const snackbar = useTemplateRef<SnackBarType>('snackbar');
|
||||||
const editDialog = useTemplateRef<EditDialogType>('editDialog');
|
const editDialog = useTemplateRef<EditDialogType>('editDialog');
|
||||||
@@ -376,7 +397,6 @@ const currentPage = ref<number>(1);
|
|||||||
const countPerPage = ref<number>(10);
|
const countPerPage = ref<number>(10);
|
||||||
const showAccountBalanceTrendsCharts = ref<boolean>(false);
|
const showAccountBalanceTrendsCharts = ref<boolean>(false);
|
||||||
const chartType = ref<number>(AccountBalanceTrendChartType.Default.type);
|
const chartType = ref<number>(AccountBalanceTrendChartType.Default.type);
|
||||||
const chartDataDateAggregationType = ref<number>(ChartDateAggregationType.Day.type);
|
|
||||||
|
|
||||||
let rejectFunc: ((reason?: unknown) => void) | null = null;
|
let rejectFunc: ((reason?: unknown) => void) | null = null;
|
||||||
|
|
||||||
@@ -462,6 +482,7 @@ function open(options: { accountId: string, startTime: number, endTime: number }
|
|||||||
showAccountBalanceTrendsCharts.value = false;
|
showAccountBalanceTrendsCharts.value = false;
|
||||||
chartType.value = AccountBalanceTrendChartType.Default.type;
|
chartType.value = AccountBalanceTrendChartType.Default.type;
|
||||||
chartDataDateAggregationType.value = ChartDateAggregationType.Day.type;
|
chartDataDateAggregationType.value = ChartDateAggregationType.Day.type;
|
||||||
|
timezoneUsedForDateRange.value = TimezoneTypeForStatistics.ApplicationTimezone.type;
|
||||||
showState.value = true;
|
showState.value = true;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
|
|||||||
@@ -691,7 +691,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
getCurrentUnixTime,
|
getCurrentUnixTime,
|
||||||
parseDateTimeFromUnixTime,
|
parseDateTimeFromUnixTime,
|
||||||
getDayFirstUnixTimeBySpecifiedUnixTime,
|
getDayFirstDateTimeBySpecifiedUnixTime,
|
||||||
getYearMonthFirstUnixTime,
|
getYearMonthFirstUnixTime,
|
||||||
getYearMonthLastUnixTime,
|
getYearMonthLastUnixTime,
|
||||||
getShiftedDateRangeAndDateType,
|
getShiftedDateRangeAndDateType,
|
||||||
@@ -1233,7 +1233,7 @@ function changeDateFilter(dateRange: TimeRangeAndDateType | number | null): void
|
|||||||
if (dateRange === DateRange.Custom.type || (isObject(dateRange) && dateRange.dateType === DateRange.Custom.type && !dateRange.minTime && !dateRange.maxTime)) { // Custom
|
if (dateRange === DateRange.Custom.type || (isObject(dateRange) && dateRange.dateType === DateRange.Custom.type && !dateRange.minTime && !dateRange.maxTime)) { // Custom
|
||||||
if (!query.value.minTime || !query.value.maxTime) {
|
if (!query.value.minTime || !query.value.maxTime) {
|
||||||
customMaxDatetime.value = getCurrentUnixTime();
|
customMaxDatetime.value = getCurrentUnixTime();
|
||||||
customMinDatetime.value = getDayFirstUnixTimeBySpecifiedUnixTime(customMaxDatetime.value);
|
customMinDatetime.value = getDayFirstDateTimeBySpecifiedUnixTime(customMaxDatetime.value).getUnixTime();
|
||||||
} else {
|
} else {
|
||||||
customMaxDatetime.value = query.value.maxTime;
|
customMaxDatetime.value = query.value.maxTime;
|
||||||
customMinDatetime.value = query.value.minTime;
|
customMinDatetime.value = query.value.minTime;
|
||||||
|
|||||||
@@ -273,6 +273,7 @@
|
|||||||
<account-balance-trends-bar-chart
|
<account-balance-trends-bar-chart
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:date-aggregation-type="chartDataDateAggregationType"
|
:date-aggregation-type="chartDataDateAggregationType"
|
||||||
|
:timezone-used-for-date-range="timezoneUsedForDateRange"
|
||||||
:fiscal-year-start="fiscalYearStart"
|
:fiscal-year-start="fiscalYearStart"
|
||||||
:items="reconciliationStatements?.transactions"
|
:items="reconciliationStatements?.transactions"
|
||||||
:account="currentAccount"
|
:account="currentAccount"
|
||||||
@@ -282,6 +283,9 @@
|
|||||||
|
|
||||||
<f7-popover class="chart-data-date-aggregation-type-popover-menu">
|
<f7-popover class="chart-data-date-aggregation-type-popover-menu">
|
||||||
<f7-list dividers>
|
<f7-list dividers>
|
||||||
|
<f7-list-item group-title>
|
||||||
|
<small>{{ tt('Time Granularity') }}</small>
|
||||||
|
</f7-list-item>
|
||||||
<f7-list-item link="#" no-chevron popover-close
|
<f7-list-item link="#" no-chevron popover-close
|
||||||
:title="dateAggregationType.displayName"
|
:title="dateAggregationType.displayName"
|
||||||
:class="{ 'list-item-selected': chartDataDateAggregationType === dateAggregationType.type }"
|
:class="{ 'list-item-selected': chartDataDateAggregationType === dateAggregationType.type }"
|
||||||
@@ -292,6 +296,20 @@
|
|||||||
<f7-icon class="list-item-checked-icon" f7="checkmark_alt" v-if="chartDataDateAggregationType === dateAggregationType.type"></f7-icon>
|
<f7-icon class="list-item-checked-icon" f7="checkmark_alt" v-if="chartDataDateAggregationType === dateAggregationType.type"></f7-icon>
|
||||||
</template>
|
</template>
|
||||||
</f7-list-item>
|
</f7-list-item>
|
||||||
|
<f7-list-item group-title>
|
||||||
|
<small>{{ tt('Timezone Used for Date Range') }}</small>
|
||||||
|
</f7-list-item>
|
||||||
|
<f7-list-item link="#" no-chevron popover-close
|
||||||
|
:title="timezoneType.displayName"
|
||||||
|
:class="{ 'list-item-selected': timezoneUsedForDateRange === timezoneType.type }"
|
||||||
|
:key="timezoneType.type"
|
||||||
|
v-for="timezoneType in allTimezoneTypesUsedForDateRange"
|
||||||
|
@click="setTimezoneUsedForDateRange(timezoneType.type)">
|
||||||
|
<template #after>
|
||||||
|
<f7-icon class="list-item-checked-icon" f7="checkmark_alt" v-if="timezoneUsedForDateRange === timezoneType.type"></f7-icon>
|
||||||
|
</template>
|
||||||
|
</f7-list-item>
|
||||||
|
|
||||||
</f7-list>
|
</f7-list>
|
||||||
</f7-popover>
|
</f7-popover>
|
||||||
|
|
||||||
@@ -352,7 +370,6 @@ import { TextDirection } from '@/core/text.ts';
|
|||||||
import { type TimeRangeAndDateType, DateRange, DateRangeScene } from '@/core/datetime.ts';
|
import { type TimeRangeAndDateType, DateRange, DateRangeScene } from '@/core/datetime.ts';
|
||||||
import { AccountType } from '@/core/account.ts';
|
import { AccountType } from '@/core/account.ts';
|
||||||
import { TransactionType } from '@/core/transaction.ts';
|
import { TransactionType } from '@/core/transaction.ts';
|
||||||
import { ChartDateAggregationType } from '@/core/statistics.ts';
|
|
||||||
import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts';
|
import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts';
|
||||||
import { type TransactionReconciliationStatementResponseItemWithInfo } from '@/models/transaction.ts';
|
import { type TransactionReconciliationStatementResponseItemWithInfo } from '@/models/transaction.ts';
|
||||||
|
|
||||||
@@ -398,9 +415,12 @@ const {
|
|||||||
startTime,
|
startTime,
|
||||||
endTime,
|
endTime,
|
||||||
reconciliationStatements,
|
reconciliationStatements,
|
||||||
|
chartDataDateAggregationType,
|
||||||
|
timezoneUsedForDateRange,
|
||||||
firstDayOfWeek,
|
firstDayOfWeek,
|
||||||
fiscalYearStart,
|
fiscalYearStart,
|
||||||
allDateAggregationTypes,
|
allDateAggregationTypes,
|
||||||
|
allTimezoneTypesUsedForDateRange,
|
||||||
isCurrentLiabilityAccount,
|
isCurrentLiabilityAccount,
|
||||||
currentAccount,
|
currentAccount,
|
||||||
currentAccountCurrency,
|
currentAccountCurrency,
|
||||||
@@ -430,7 +450,6 @@ const loading = ref<boolean>(false);
|
|||||||
const loadingError = ref<unknown | null>(null);
|
const loadingError = ref<unknown | null>(null);
|
||||||
const queryDateRangeType = ref<number>(DateRange.ThisMonth.type);
|
const queryDateRangeType = ref<number>(DateRange.ThisMonth.type);
|
||||||
const showAccountBalanceTrendsCharts = ref<boolean>(false);
|
const showAccountBalanceTrendsCharts = ref<boolean>(false);
|
||||||
const chartDataDateAggregationType = ref<number>(ChartDateAggregationType.Day.type);
|
|
||||||
const transactionToDelete = ref<TransactionReconciliationStatementResponseItemWithInfo | null>(null);
|
const transactionToDelete = ref<TransactionReconciliationStatementResponseItemWithInfo | null>(null);
|
||||||
const newClosingBalance = ref<number>(0);
|
const newClosingBalance = ref<number>(0);
|
||||||
const showCustomDateRangeSheet = ref<boolean>(false);
|
const showCustomDateRangeSheet = ref<boolean>(false);
|
||||||
@@ -671,6 +690,10 @@ function setChartDataDateAggregationType(type: number): void {
|
|||||||
chartDataDateAggregationType.value = type;
|
chartDataDateAggregationType.value = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setTimezoneUsedForDateRange(type: number): void {
|
||||||
|
timezoneUsedForDateRange.value = type;
|
||||||
|
}
|
||||||
|
|
||||||
function renderExternal(vl: unknown, vlData: ReconciliationStatementVirtualListData): void {
|
function renderExternal(vl: unknown, vlData: ReconciliationStatementVirtualListData): void {
|
||||||
virtualDataItems.value = vlData;
|
virtualDataItems.value = vlData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -637,7 +637,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
getCurrentUnixTime,
|
getCurrentUnixTime,
|
||||||
parseDateTimeFromUnixTime,
|
parseDateTimeFromUnixTime,
|
||||||
getDayFirstUnixTimeBySpecifiedUnixTime,
|
getDayFirstDateTimeBySpecifiedUnixTime,
|
||||||
getYearMonthFirstUnixTime,
|
getYearMonthFirstUnixTime,
|
||||||
getYearMonthLastUnixTime,
|
getYearMonthLastUnixTime,
|
||||||
getShiftedDateRangeAndDateType,
|
getShiftedDateRangeAndDateType,
|
||||||
@@ -1057,7 +1057,7 @@ function changeDateFilter(dateType: number): void {
|
|||||||
if (dateType === DateRange.Custom.type) { // Custom
|
if (dateType === DateRange.Custom.type) { // Custom
|
||||||
if (!query.value.minTime || !query.value.maxTime) {
|
if (!query.value.minTime || !query.value.maxTime) {
|
||||||
customMaxDatetime.value = getCurrentUnixTime();
|
customMaxDatetime.value = getCurrentUnixTime();
|
||||||
customMinDatetime.value = getDayFirstUnixTimeBySpecifiedUnixTime(customMaxDatetime.value);
|
customMinDatetime.value = getDayFirstDateTimeBySpecifiedUnixTime(customMaxDatetime.value).getUnixTime();
|
||||||
} else {
|
} else {
|
||||||
customMaxDatetime.value = query.value.maxTime;
|
customMaxDatetime.value = query.value.maxTime;
|
||||||
customMinDatetime.value = query.value.minTime;
|
customMinDatetime.value = query.value.minTime;
|
||||||
|
|||||||
Reference in New Issue
Block a user