support displaying transactions since the last reconciled time

This commit is contained in:
MaysWind
2026-05-08 00:58:04 +08:00
parent de132dd7fd
commit 75d801f775
45 changed files with 608 additions and 107 deletions
+1
View File
@@ -375,6 +375,7 @@ func startWebServer(c *core.CliContext) error {
apiV1Route.GET("/accounts/get.json", bindApi(api.Accounts.AccountGetHandler))
apiV1Route.POST("/accounts/add.json", bindApi(api.Accounts.AccountCreateHandler))
apiV1Route.POST("/accounts/modify.json", bindApi(api.Accounts.AccountModifyHandler))
apiV1Route.POST("/accounts/update/last_reconciled_time.json", bindApi(api.Accounts.AccountUpdateLastReconciledTimeHandler))
apiV1Route.POST("/accounts/hide.json", bindApi(api.Accounts.AccountHideHandler))
apiV1Route.POST("/accounts/move.json", bindApi(api.Accounts.AccountMoveHandler))
apiV1Route.POST("/accounts/delete.json", bindApi(api.Accounts.AccountDeleteHandler))
+95 -8
View File
@@ -19,6 +19,7 @@ type AccountsApi struct {
ApiUsingConfig
ApiUsingDuplicateChecker
accounts *services.AccountService
users *services.UserService
}
// Initialize an account api singleton instance
@@ -34,6 +35,7 @@ var (
container: duplicatechecker.Container,
},
accounts: services.Accounts,
users: services.Users,
}
)
@@ -333,6 +335,16 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error
}
uid := c.GetCurrentUid()
user, err := a.users.GetUserById(c, uid)
if err != nil {
if !errs.IsCustomError(err) {
log.Errorf(c, "[accounts.AccountModifyHandler] failed to get user, because %s", err.Error())
}
return nil, errs.ErrUserNotFound
}
accountAndSubAccounts, err := a.accounts.GetAccountAndSubAccountsByAccountId(c, uid, accountModifyReq.Id)
if err != nil {
@@ -434,7 +446,11 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error
var toAddAccountBalanceTimes []int64
var toDeleteAccountIds []int64
toUpdateAccount := a.getToUpdateAccount(uid, &accountModifyReq, mainAccount, false)
toUpdateAccount, err := a.getToUpdateAccount(user, &accountModifyReq, mainAccount, false)
if err != nil {
return nil, errs.Or(err, errs.ErrOperationFailed)
}
if toUpdateAccount != nil {
if toUpdateAccount.Category != mainAccount.Category {
@@ -483,7 +499,11 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error
toAddAccountBalanceTimes = append(toAddAccountBalanceTimes, 0)
}
} else {
toUpdateSubAccount := a.getToUpdateAccount(uid, subAccountReq, accountMap[subAccountReq.Id], true)
toUpdateSubAccount, err := a.getToUpdateAccount(user, subAccountReq, accountMap[subAccountReq.Id], true)
if err != nil {
return nil, errs.Or(err, errs.ErrOperationFailed)
}
if toUpdateSubAccount != nil {
anythingUpdate = true
@@ -607,6 +627,69 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error
return accountResp, nil
}
// AccountUpdateLastReconciledTimeHandler updates last reconciled time of an existed account by request parameters for current user
func (a *AccountsApi) AccountUpdateLastReconciledTimeHandler(c *core.WebContext) (any, *errs.Error) {
var accountUpdateReq models.AccountUpdateLastReconciledTimeRequest
err := c.ShouldBindJSON(&accountUpdateReq)
if err != nil {
log.Warnf(c, "[accounts.AccountUpdateLastReconciledTimeHandler] parse request failed, because %s", err.Error())
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
}
if accountUpdateReq.Id <= 0 {
return nil, errs.ErrAccountIdInvalid
}
uid := c.GetCurrentUid()
user, err := a.users.GetUserById(c, uid)
if err != nil {
if !errs.IsCustomError(err) {
log.Errorf(c, "[accounts.AccountUpdateLastReconciledTimeHandler] failed to get user, because %s", err.Error())
}
return nil, errs.ErrUserNotFound
}
if !user.UseLastReconciledTime {
return nil, errs.ErrLastReconciledTimeIsNotEnabled
}
account, err := a.accounts.GetAccountByAccountId(c, uid, accountUpdateReq.Id)
if err != nil {
log.Errorf(c, "[accounts.AccountUpdateLastReconciledTimeHandler] failed to get account \"id:%d\" for user \"uid:%d\", because %s", accountUpdateReq.Id, uid, err.Error())
return nil, errs.Or(err, errs.ErrOperationFailed)
}
if account.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS {
return nil, errs.ErrParentAccountCannotSetLastReconciledTime
}
if account.Extend == nil {
account.Extend = &models.AccountExtend{}
}
if account.Extend.LastReconciledTime != nil && accountUpdateReq.LastReconciledTime < *account.Extend.LastReconciledTime {
return nil, errs.ErrCannotSetLastReconciledTimeBeforeCurrent
} else if account.Extend.LastReconciledTime != nil && accountUpdateReq.LastReconciledTime == *account.Extend.LastReconciledTime {
return nil, errs.ErrNothingWillBeUpdated
}
account.Extend.LastReconciledTime = &accountUpdateReq.LastReconciledTime
err = a.accounts.UpdateAccountExtend(c, uid, account)
if err != nil {
log.Errorf(c, "[accounts.AccountUpdateLastReconciledTimeHandler] failed to update last reconciled time for account \"id:%d\" of user \"uid:%d\", because %s", account.AccountId, uid, err.Error())
return nil, errs.Or(err, errs.ErrOperationFailed)
}
log.Infof(c, "[accounts.AccountUpdateLastReconciledTimeHandler] user \"uid:%d\" has updated last reconciled time \"%d\" for account \"id:%d\"", uid, account.Extend.LastReconciledTime, account.AccountId)
return true, nil
}
// AccountHideHandler hides an existed account by request parameters for current user
func (a *AccountsApi) AccountHideHandler(c *core.WebContext) (any, *errs.Error) {
var accountHideReq models.AccountHideRequest
@@ -764,7 +847,7 @@ func (a *AccountsApi) createSubAccountModels(uid int64, accountCreateReq *models
return childrenAccounts, childrenAccountBalanceTimes
}
func (a *AccountsApi) getToUpdateAccount(uid int64, accountModifyReq *models.AccountModifyRequest, oldAccount *models.Account, isSubAccount bool) *models.Account {
func (a *AccountsApi) getToUpdateAccount(user *models.User, accountModifyReq *models.AccountModifyRequest, oldAccount *models.Account, isSubAccount bool) (*models.Account, error) {
newAccountExtend := &models.AccountExtend{}
newAccountExtend.LastReconciledTime = accountModifyReq.LastReconciledTime
@@ -774,7 +857,7 @@ func (a *AccountsApi) getToUpdateAccount(uid int64, accountModifyReq *models.Acc
newAccount := &models.Account{
AccountId: oldAccount.AccountId,
Uid: uid,
Uid: user.Uid,
Name: accountModifyReq.Name,
DisplayOrder: oldAccount.DisplayOrder,
Category: accountModifyReq.Category,
@@ -791,7 +874,7 @@ func (a *AccountsApi) getToUpdateAccount(uid int64, accountModifyReq *models.Acc
newAccount.Color != oldAccount.Color ||
newAccount.Comment != oldAccount.Comment ||
newAccount.Hidden != oldAccount.Hidden {
return newAccount
return newAccount, nil
}
oldAccountExtend := oldAccount.Extend
@@ -799,16 +882,20 @@ func (a *AccountsApi) getToUpdateAccount(uid int64, accountModifyReq *models.Acc
if (newAccountExtend.LastReconciledTime != nil && (oldAccountExtend == nil || oldAccountExtend.LastReconciledTime == nil)) ||
(newAccountExtend.LastReconciledTime == nil && oldAccountExtend != nil && oldAccountExtend.LastReconciledTime != nil) ||
(newAccountExtend.LastReconciledTime != nil && oldAccountExtend != nil && oldAccountExtend.LastReconciledTime != nil && *newAccountExtend.LastReconciledTime != *oldAccountExtend.LastReconciledTime) {
return newAccount
if !user.UseLastReconciledTime {
return nil, errs.ErrLastReconciledTimeIsNotEnabled
}
return newAccount, nil
}
if (newAccountExtend.CreditCardStatementDate != nil && (oldAccountExtend == nil || oldAccountExtend.CreditCardStatementDate == nil)) ||
(newAccountExtend.CreditCardStatementDate == nil && oldAccountExtend != nil && oldAccountExtend.CreditCardStatementDate != nil) ||
(newAccountExtend.CreditCardStatementDate != nil && oldAccountExtend != nil && oldAccountExtend.CreditCardStatementDate != nil && *newAccountExtend.CreditCardStatementDate != *oldAccountExtend.CreditCardStatementDate) {
return newAccount
return newAccount, nil
}
return nil
return nil, nil
}
func (a *AccountsApi) getToDeleteSubAccountIds(accountModifyReq *models.AccountModifyRequest, mainAccount *models.Account, accountAndSubAccounts []*models.Account) []int64 {
+24 -22
View File
@@ -4,26 +4,28 @@ import "net/http"
// Error codes related to accounts
var (
ErrAccountIdInvalid = NewNormalError(NormalSubcategoryAccount, 0, http.StatusBadRequest, "account id is invalid")
ErrAccountNotFound = NewNormalError(NormalSubcategoryAccount, 1, http.StatusBadRequest, "account not found")
ErrAccountTypeInvalid = NewNormalError(NormalSubcategoryAccount, 2, http.StatusBadRequest, "account type is invalid")
ErrAccountCurrencyInvalid = NewNormalError(NormalSubcategoryAccount, 3, http.StatusBadRequest, "account currency is invalid")
ErrAccountHaveNoSubAccount = NewNormalError(NormalSubcategoryAccount, 4, http.StatusBadRequest, "account must have at least one sub-account")
ErrAccountCannotHaveSubAccounts = NewNormalError(NormalSubcategoryAccount, 5, http.StatusBadRequest, "account cannot have sub-accounts")
ErrParentAccountCannotSetCurrency = NewNormalError(NormalSubcategoryAccount, 6, http.StatusBadRequest, "parent account cannot set currency")
ErrParentAccountCannotSetBalance = NewNormalError(NormalSubcategoryAccount, 7, http.StatusBadRequest, "parent account cannot set balance")
ErrSubAccountCategoryNotEqualsToParent = NewNormalError(NormalSubcategoryAccount, 8, http.StatusBadRequest, "sub-account category not equals to parent")
ErrSubAccountTypeInvalid = NewNormalError(NormalSubcategoryAccount, 9, http.StatusBadRequest, "sub-account type invalid")
ErrSourceAccountNotFound = NewNormalError(NormalSubcategoryAccount, 11, http.StatusBadRequest, "source account not found")
ErrDestinationAccountNotFound = NewNormalError(NormalSubcategoryAccount, 12, http.StatusBadRequest, "destination account not found")
ErrAccountInUseCannotBeDeleted = NewNormalError(NormalSubcategoryAccount, 13, http.StatusBadRequest, "account is in use and cannot be deleted")
ErrAccountCategoryInvalid = NewNormalError(NormalSubcategoryAccount, 14, http.StatusBadRequest, "account category is invalid")
ErrAccountBalanceTimeNotSet = NewNormalError(NormalSubcategoryAccount, 15, http.StatusBadRequest, "account balance time is not set")
ErrCannotSetStatementDateForNonCreditCard = NewNormalError(NormalSubcategoryAccount, 16, http.StatusBadRequest, "cannot set statement date for non credit card account")
ErrCannotSetStatementDateForSubAccount = NewNormalError(NormalSubcategoryAccount, 17, http.StatusBadRequest, "cannot set statement date for sub account")
ErrSubAccountNotFound = NewNormalError(NormalSubcategoryAccount, 18, http.StatusBadRequest, "sub-account not found")
ErrSubAccountInUseCannotBeDeleted = NewNormalError(NormalSubcategoryAccount, 19, http.StatusBadRequest, "sub-account is in use and cannot be deleted")
ErrNotSupportedChangeCurrency = NewNormalError(NormalSubcategoryAccount, 20, http.StatusBadRequest, "not supported to modify account currency")
ErrNotSupportedChangeBalance = NewNormalError(NormalSubcategoryAccount, 21, http.StatusBadRequest, "not supported to modify account balance")
ErrNotSupportedChangeBalanceTime = NewNormalError(NormalSubcategoryAccount, 22, http.StatusBadRequest, "not supported to modify account balance time")
ErrAccountIdInvalid = NewNormalError(NormalSubcategoryAccount, 0, http.StatusBadRequest, "account id is invalid")
ErrAccountNotFound = NewNormalError(NormalSubcategoryAccount, 1, http.StatusBadRequest, "account not found")
ErrAccountTypeInvalid = NewNormalError(NormalSubcategoryAccount, 2, http.StatusBadRequest, "account type is invalid")
ErrAccountCurrencyInvalid = NewNormalError(NormalSubcategoryAccount, 3, http.StatusBadRequest, "account currency is invalid")
ErrAccountHaveNoSubAccount = NewNormalError(NormalSubcategoryAccount, 4, http.StatusBadRequest, "account must have at least one sub-account")
ErrAccountCannotHaveSubAccounts = NewNormalError(NormalSubcategoryAccount, 5, http.StatusBadRequest, "account cannot have sub-accounts")
ErrParentAccountCannotSetCurrency = NewNormalError(NormalSubcategoryAccount, 6, http.StatusBadRequest, "parent account cannot set currency")
ErrParentAccountCannotSetBalance = NewNormalError(NormalSubcategoryAccount, 7, http.StatusBadRequest, "parent account cannot set balance")
ErrSubAccountCategoryNotEqualsToParent = NewNormalError(NormalSubcategoryAccount, 8, http.StatusBadRequest, "sub-account category not equals to parent")
ErrSubAccountTypeInvalid = NewNormalError(NormalSubcategoryAccount, 9, http.StatusBadRequest, "sub-account type invalid")
ErrSourceAccountNotFound = NewNormalError(NormalSubcategoryAccount, 11, http.StatusBadRequest, "source account not found")
ErrDestinationAccountNotFound = NewNormalError(NormalSubcategoryAccount, 12, http.StatusBadRequest, "destination account not found")
ErrAccountInUseCannotBeDeleted = NewNormalError(NormalSubcategoryAccount, 13, http.StatusBadRequest, "account is in use and cannot be deleted")
ErrAccountCategoryInvalid = NewNormalError(NormalSubcategoryAccount, 14, http.StatusBadRequest, "account category is invalid")
ErrAccountBalanceTimeNotSet = NewNormalError(NormalSubcategoryAccount, 15, http.StatusBadRequest, "account balance time is not set")
ErrCannotSetStatementDateForNonCreditCard = NewNormalError(NormalSubcategoryAccount, 16, http.StatusBadRequest, "cannot set statement date for non credit card account")
ErrCannotSetStatementDateForSubAccount = NewNormalError(NormalSubcategoryAccount, 17, http.StatusBadRequest, "cannot set statement date for sub account")
ErrSubAccountNotFound = NewNormalError(NormalSubcategoryAccount, 18, http.StatusBadRequest, "sub-account not found")
ErrSubAccountInUseCannotBeDeleted = NewNormalError(NormalSubcategoryAccount, 19, http.StatusBadRequest, "sub-account is in use and cannot be deleted")
ErrNotSupportedChangeCurrency = NewNormalError(NormalSubcategoryAccount, 20, http.StatusBadRequest, "not supported to modify account currency")
ErrNotSupportedChangeBalance = NewNormalError(NormalSubcategoryAccount, 21, http.StatusBadRequest, "not supported to modify account balance")
ErrNotSupportedChangeBalanceTime = NewNormalError(NormalSubcategoryAccount, 22, http.StatusBadRequest, "not supported to modify account balance time")
ErrParentAccountCannotSetLastReconciledTime = NewNormalError(NormalSubcategoryAccount, 23, http.StatusBadRequest, "parent account cannot set last reconciled time")
ErrCannotSetLastReconciledTimeBeforeCurrent = NewNormalError(NormalSubcategoryAccount, 24, http.StatusBadRequest, "cannot set last reconciled time before current value")
)
+1
View File
@@ -41,4 +41,5 @@ var (
ErrCannotLoginByPassword = NewNormalError(NormalSubcategoryUser, 32, http.StatusBadRequest, "cannot login by password")
ErrUserNameIsInvalid = NewNormalError(NormalSubcategoryUser, 33, http.StatusBadRequest, "user name is invalid")
ErrNickNameIsInvalid = NewNormalError(NormalSubcategoryUser, 34, http.StatusBadRequest, "nick name is invalid")
ErrLastReconciledTimeIsNotEnabled = NewNormalError(NormalSubcategoryUser, 35, http.StatusBadRequest, "last reconciled time is not enabled")
)
+6
View File
@@ -128,6 +128,12 @@ type AccountModifyRequest struct {
ClientSessionId string `json:"clientSessionId"`
}
// AccountUpdateLastReconciledTimeRequest represents all parameters of account updating last reconciled time request
type AccountUpdateLastReconciledTimeRequest struct {
Id int64 `json:"id,string" binding:"required,min=1"`
LastReconciledTime int64 `json:"lastReconciledTime" binding:"required"`
}
// AccountListRequest represents all parameters of account listing request
type AccountListRequest struct {
VisibleOnly bool `form:"visible_only"`
+21
View File
@@ -592,6 +592,27 @@ func (s *AccountService) ModifyAccounts(c core.Context, mainAccount *models.Acco
})
}
// UpdateAccountExtend updates extend field of given account
func (s *AccountService) UpdateAccountExtend(c core.Context, uid int64, account *models.Account) error {
if uid <= 0 {
return errs.ErrUserIdInvalid
}
account.UpdatedUnixTime = time.Now().Unix()
return s.UserDataDB(uid).DoTransaction(c, func(sess *xorm.Session) error {
updatedRows, err := sess.ID(account.AccountId).Cols("extend", "updated_unix_time").Where("uid=? AND deleted=?", uid, false).Update(account)
if err != nil {
return err
} else if updatedRows < 1 {
return errs.ErrAccountNotFound
}
return nil
})
}
// HideAccount updates hidden field of given accounts
func (s *AccountService) HideAccount(c core.Context, uid int64, ids []int64, hidden bool) error {
if uid <= 0 {
+33 -23
View File
@@ -701,49 +701,54 @@ export class DateRange implements TypeAndName {
private static readonly allInstancesByType: Record<number, DateRange> = {};
// All date range
public static readonly All = new DateRange(0, 'All', false, false, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly All = new DateRange(0, 'All', false, false, false, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
// Date ranges for normal scene only
public static readonly Today = new DateRange(1, 'Today', false, false, DateRangeScene.Normal, DateRangeScene.InsightsExplorer);
public static readonly Yesterday = new DateRange(2, 'Yesterday', false, false, DateRangeScene.Normal, DateRangeScene.InsightsExplorer);
public static readonly LastSevenDays = new DateRange(3, 'Recent 7 days', false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly LastThirtyDays = new DateRange(4, 'Recent 30 days', false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly ThisWeek = new DateRange(5, 'This week', false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly LastWeek = new DateRange(6, 'Last week', false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly ThisMonth = new DateRange(7, 'This month', false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly LastMonth = new DateRange(8, 'Last month', false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly Today = new DateRange(1, 'Today', false, false, false, DateRangeScene.Normal, DateRangeScene.InsightsExplorer);
public static readonly Yesterday = new DateRange(2, 'Yesterday', false, false, false, DateRangeScene.Normal, DateRangeScene.InsightsExplorer);
public static readonly LastSevenDays = new DateRange(3, 'Recent 7 days', false, false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly LastThirtyDays = new DateRange(4, 'Recent 30 days', false, false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly ThisWeek = new DateRange(5, 'This week', false, false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly LastWeek = new DateRange(6, 'Last week', false, false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly ThisMonth = new DateRange(7, 'This month', false, false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly LastMonth = new DateRange(8, 'Last month', false, false, false, DateRangeScene.Normal, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
// Date ranges for normal and trend analysis scene
public static readonly ThisYear = new DateRange(9, 'This year', false, false, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly LastYear = new DateRange(10, 'Last year', false, false, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly ThisFiscalYear = new DateRange(11, 'This fiscal year', false, true, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly LastFiscalYear = new DateRange(12, 'Last fiscal year', false, true, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly ThisYear = new DateRange(9, 'This year', false, false, false, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly LastYear = new DateRange(10, 'Last year', false, false, false, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly ThisFiscalYear = new DateRange(11, 'This fiscal year', false, false, true, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly LastFiscalYear = new DateRange(12, 'Last fiscal year', false, false, true, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
// Billing cycle date ranges for normal scene only
public static readonly CurrentBillingCycle = new DateRange(51, 'Current Billing Cycle', true, true, DateRangeScene.Normal);
public static readonly PreviousBillingCycle = new DateRange(52, 'Previous Billing Cycle', true, true, DateRangeScene.Normal);
public static readonly CurrentBillingCycle = new DateRange(51, 'Current Billing Cycle', true, false, true, DateRangeScene.Normal);
public static readonly PreviousBillingCycle = new DateRange(52, 'Previous Billing Cycle', true, false, true, DateRangeScene.Normal);
// Last reconciled time ranges for normal scene only
public static readonly SinceLastReconciledTime = new DateRange(71, 'Since Last Reconciled Time', false, true, true, DateRangeScene.Normal)
// Date ranges for trend analysis scene only
public static readonly RecentTwelveMonths = new DateRange(101, 'Recent 12 months', false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentTwentyFourMonths = new DateRange(102, 'Recent 24 months', false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentThirtySixMonths = new DateRange(103, 'Recent 36 months', false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentTwoYears = new DateRange(104, 'Recent 2 years', false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentThreeYears = new DateRange(105, 'Recent 3 years', false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentFiveYears = new DateRange(106, 'Recent 5 years', false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentTwelveMonths = new DateRange(101, 'Recent 12 months', false, false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentTwentyFourMonths = new DateRange(102, 'Recent 24 months', false, false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentThirtySixMonths = new DateRange(103, 'Recent 36 months', false, false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentTwoYears = new DateRange(104, 'Recent 2 years', false, false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentThreeYears = new DateRange(105, 'Recent 3 years', false, false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly RecentFiveYears = new DateRange(106, 'Recent 5 years', false, false, false, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
// Custom date range
public static readonly Custom = new DateRange(255, 'Custom Date', false, true, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public static readonly Custom = new DateRange(255, 'Custom Date', false, false, true, DateRangeScene.Normal, DateRangeScene.TrendAnalysis, DateRangeScene.AssetTrends, DateRangeScene.InsightsExplorer);
public readonly type: number;
public readonly name: string;
public readonly isBillingCycle: boolean;
public readonly isLastReconciledTimeRange: boolean;
public readonly isUserCustomRange: boolean;
private readonly availableScenes: Record<number, boolean>;
private constructor(type: number, name: string, isBillingCycle: boolean, isUserCustomRange: boolean, ...availableScenes: DateRangeScene[]) {
private constructor(type: number, name: string, isBillingCycle: boolean, isLastReconciledTimeRange: boolean, isUserCustomRange: boolean, ...availableScenes: DateRangeScene[]) {
this.type = type;
this.name = name;
this.isBillingCycle = isBillingCycle;
this.isLastReconciledTimeRange = isLastReconciledTimeRange;
this.isUserCustomRange = isUserCustomRange;
this.availableScenes = {};
@@ -778,4 +783,9 @@ export class DateRange implements TypeAndName {
const dateRange = DateRange.allInstancesByType[type];
return dateRange?.isBillingCycle || false;
}
public static isLastReconciledTimeRange(type: number): boolean {
const dateRange = DateRange.allInstancesByType[type];
return dateRange?.isLastReconciledTimeRange || false;
}
}
+22
View File
@@ -1433,6 +1433,28 @@ export function getDateRangeByBillingCycleDateType(dateType: number, firstDayOfW
};
}
export function getDateRangeByLastReconciledTimeRangeDateType(dateType: number, lastReconciledTime: number | undefined | null): TimeRangeAndDateType | null {
let maxTime = 0;
let minTime = 0;
if (dateType === DateRange.SinceLastReconciledTime.type) { // Since Last Reconciled Time
if (lastReconciledTime) {
maxTime = getTodayLastUnixTime();
minTime = lastReconciledTime;
} else {
return null;
}
} else {
return null;
}
return {
dateType: dateType,
maxTime: maxTime,
minTime: minTime
};
}
export function getRecentMonthDateRanges(monthCount: number): RecentMonthDateRange[] {
const recentDateRanges: RecentMonthDateRange[] = [];
const thisMonthFirstUnixTime = getThisMonthFirstUnixTime();
+4
View File
@@ -35,6 +35,7 @@ import {
import type {
AccountCreateRequest,
AccountModifyRequest,
AccountUpdateLastReconciledTimeRequest,
AccountInfoResponse,
AccountHideRequest,
AccountMoveRequest,
@@ -506,6 +507,9 @@ export default {
modifyAccount: (req: AccountModifyRequest): ApiResponsePromise<AccountInfoResponse> => {
return axios.post<ApiResponse<AccountInfoResponse>>('v1/accounts/modify.json', req);
},
updateAccountLastReconciledTime: (req: AccountUpdateLastReconciledTimeRequest): ApiResponsePromise<boolean> => {
return axios.post<ApiResponse<boolean>>('v1/accounts/update/last_reconciled_time.json', req);
},
hideAccount: (req: AccountHideRequest): ApiResponsePromise<boolean> => {
return axios.post<ApiResponse<boolean>>('v1/accounts/hide.json', req);
},
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "Sie können sich nicht mit einem Passwort anmelden",
"user name is invalid": "Benutzername ist ungültig",
"nick name is invalid": "Benutzerspitzname ist ungültig",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Unbefugter Zugriff",
"current token is invalid": "Aktuelles Token ist ungültig",
"current token is expired": "Aktuelles Token ist abgelaufen",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Änderung der Kontowährung wird nicht unterstützt",
"not supported to modify account balance": "Änderung des Kontosaldos wird nicht unterstützt",
"not supported to modify account balance time": "Änderung der Kontosaldozeit wird nicht unterstützt",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "Transaktions-ID ist ungültig",
"transaction not found": "Transaktion nicht gefunden",
"transaction type is invalid": "Transaktionstyp ist ungültig",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "Letzte 5 Jahre",
"Previous Billing Cycle": "Vorheriger Abrechnungszeitraum",
"Current Billing Cycle": "Aktueller Abrechnungszeitraum",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Benutzerdefiniertes Datum",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Sie haben dieses Konto gespeichert",
"Unable to add account": "Konto kann nicht hinzugefügt werden",
"Unable to save account": "Konto kann nicht gespeichert werden",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Versteckte Konten anzeigen",
"Hide Hidden Accounts": "Versteckte Konten ausblenden",
"Set Accounts Included in Total": "Konten in Gesamtsumme einbeziehen",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "You cannot login by password",
"user name is invalid": "User name is invalid",
"nick name is invalid": "User nickname is invalid",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Unauthorized access",
"current token is invalid": "Current token is invalid",
"current token is expired": "Current token is expired",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Not supported to modify account currency",
"not supported to modify account balance": "Not supported to modify account balance",
"not supported to modify account balance time": "Not supported to modify account balance time",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "Transaction ID is invalid",
"transaction not found": "Transaction is not found",
"transaction type is invalid": "Transaction type is invalid",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "Recent 5 years",
"Previous Billing Cycle": "Previous Billing Cycle",
"Current Billing Cycle": "Current Billing Cycle",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Custom Date",
@@ -1941,6 +1945,9 @@
"You have saved this account": "You have saved this account",
"Unable to add account": "Unable to add account",
"Unable to save account": "Unable to save account",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Show Hidden Accounts",
"Hide Hidden Accounts": "Hide Hidden Accounts",
"Set Accounts Included in Total": "Set Accounts Included in Total",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "No puede iniciar sesión con contraseña.",
"user name is invalid": "El nombre de usuario no es válido.",
"nick name is invalid": "El apodo de usuario no es válido.",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Acceso no autorizado",
"current token is invalid": "El token actual no es válido",
"current token is expired": "El token actual ha caducado",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "No se admite la modificación de la moneda de la cuenta",
"not supported to modify account balance": "No se admite la modificación del saldo de la cuenta",
"not supported to modify account balance time": "No se admite la modificación del tiempo de saldo de la cuenta",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "El ID de transacción no es válido",
"transaction not found": "La transacción no se encuentra",
"transaction type is invalid": "El tipo de transacción no es válido",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "Últimos 5 años",
"Previous Billing Cycle": "Ciclo de facturación anterior",
"Current Billing Cycle": "Ciclo de facturación actual",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Fecha personalizada",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Has guardado esta cuenta",
"Unable to add account": "No se puede agregar la cuenta",
"Unable to save account": "No se puede guardar la cuenta",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Mostrar Cuentas Ocultas",
"Hide Hidden Accounts": "Ocultar Cuentas Ocultas",
"Set Accounts Included in Total": "Cuentas Incluidas en el Total",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "You cannot login by password",
"user name is invalid": "User name is invalid",
"nick name is invalid": "User nickname is invalid",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Accès non autorisé",
"current token is invalid": "Le token actuel est invalide",
"current token is expired": "Le token actuel a expiré",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Modification de la devise du compte non prise en charge",
"not supported to modify account balance": "Modification du solde du compte non prise en charge",
"not supported to modify account balance time": "Modification de l'heure du solde du compte non prise en charge",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "L'ID de transaction est invalide",
"transaction not found": "Transaction non trouvée",
"transaction type is invalid": "Le type de transaction est invalide",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "5 dernières années",
"Previous Billing Cycle": "Cycle de facturation précédent",
"Current Billing Cycle": "Cycle de facturation actuel",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Date personnalisée",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Vous avez enregistré ce compte",
"Unable to add account": "Impossible d'ajouter le compte",
"Unable to save account": "Impossible d'enregistrer le compte",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Afficher les comptes masqués",
"Hide Hidden Accounts": "Masquer les comptes masqués",
"Set Accounts Included in Total": "Définir les comptes inclus dans le total",
+13 -23
View File
@@ -1172,36 +1172,26 @@ export function useI18n() {
return ret;
}
function getAllDateRanges(scene: DateRangeScene, includeCustom?: boolean, includeBillingCycle?: boolean): LocalizedDateRange[] {
function getAllDateRanges(scene: DateRangeScene, { includeCustom, includeBillingCycle, includeLastReconciledTimeRange } : { includeCustom?: boolean, includeBillingCycle?: boolean, includeLastReconciledTimeRange?: boolean }): LocalizedDateRange[] {
const ret: LocalizedDateRange[] = [];
const allDateRanges = DateRange.values();
for (const dateRange of allDateRanges) {
if (!dateRange.isAvailableForScene(scene)) {
const shouldSkip: boolean = !dateRange.isAvailableForScene(scene)
|| (dateRange.isBillingCycle && !includeBillingCycle)
|| (dateRange.isLastReconciledTimeRange && !includeLastReconciledTimeRange)
|| (dateRange.type === DateRange.Custom.type && !includeCustom);
if (shouldSkip) {
continue;
}
if (dateRange.isBillingCycle) {
if (includeBillingCycle) {
ret.push({
type: dateRange.type,
displayName: t(dateRange.name),
isBillingCycle: dateRange.isBillingCycle,
isUserCustomRange: dateRange.isUserCustomRange
});
}
continue;
}
if (includeCustom || dateRange.type !== DateRange.Custom.type) {
ret.push({
type: dateRange.type,
displayName: t(dateRange.name),
isBillingCycle: dateRange.isBillingCycle,
isUserCustomRange: dateRange.isUserCustomRange
});
}
ret.push({
type: dateRange.type,
displayName: t(dateRange.name),
isBillingCycle: dateRange.isBillingCycle,
isUserCustomRange: dateRange.isUserCustomRange
});
}
return ret;
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "You cannot login by password",
"user name is invalid": "User name is invalid",
"nick name is invalid": "User nickname is invalid",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Accesso non autorizzato",
"current token is invalid": "Token corrente non valido",
"current token is expired": "Token corrente scaduto",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Not supported to modify account currency",
"not supported to modify account balance": "Not supported to modify account balance",
"not supported to modify account balance time": "Not supported to modify account balance time",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "ID transazione non valido",
"transaction not found": "Transazione non trovata",
"transaction type is invalid": "Tipo di transazione non valido",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "Ultimi 5 anni",
"Previous Billing Cycle": "Ciclo di fatturazione precedente",
"Current Billing Cycle": "Ciclo di fatturazione corrente",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Data personalizzata",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Hai salvato questo account",
"Unable to add account": "Impossibile aggiungere l'account",
"Unable to save account": "Impossibile salvare l'account",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Mostra account nascosti",
"Hide Hidden Accounts": "Nascondi account nascosti",
"Set Accounts Included in Total": "Set Accounts Included in Total",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "You cannot login by password",
"user name is invalid": "User name is invalid",
"nick name is invalid": "User nickname is invalid",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "不正アクセス",
"current token is invalid": "現在のトークンは無効です",
"current token is expired": "現在のトークンの有効期限が切れています",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Not supported to modify account currency",
"not supported to modify account balance": "Not supported to modify account balance",
"not supported to modify account balance time": "Not supported to modify account balance time",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "取引IDは無効です",
"transaction not found": "取引が見つかりません",
"transaction type is invalid": "取引タイプは無効です",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "直近5年",
"Previous Billing Cycle": "以前の請求サイクル",
"Current Billing Cycle": "現在の請求サイクル",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "カスタム日付",
@@ -1941,6 +1945,9 @@
"You have saved this account": "この口座を保存しました",
"Unable to add account": "口座を追加できません",
"Unable to save account": "口座を保存できません",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "非表示口座を表示します",
"Hide Hidden Accounts": "非表示口座を隠します",
"Set Accounts Included in Total": "Set Accounts Included in Total",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "ಪಾಸ್‌ವರ್ಡ್ ಮೂಲಕ ಲಾಗಿನ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ",
"user name is invalid": "ಬಳಕೆದಾರ ಹೆಸರು ಅಮಾನ್ಯವಾಗಿದೆ",
"nick name is invalid": "ಉಪನಾಮ ಅಮಾನ್ಯವಾಗಿದೆ",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "ಅನಧಿಕೃತ ಪ್ರವೇಶ",
"current token is invalid": "ಪ್ರಸ್ತುತ ಟೋಕನ್ ಅಮಾನ್ಯವಾಗಿದೆ",
"current token is expired": "ಪ್ರಸ್ತುತ ಟೋಕನ್ ಅವಧಿ ಮೀರಿದೆ",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "ಖಾತೆ ಕರೆನ್ಸಿಯನ್ನು ಬದಲಿಸಲು ಬೆಂಬಲಿಸಲಾಗುವುದಿಲ್ಲ",
"not supported to modify account balance": "ಖಾತೆ ಬ್ಯಾಲೆನ್ಸ್ ಬದಲಾವಣೆ ಬೆಂಬಲಿಸಲಾಗುವುದಿಲ್ಲ",
"not supported to modify account balance time": "ಖಾತೆ ಬ್ಯಾಲೆನ್ಸ್ ಸಮಯ ಬದಲಾವಣೆ ಬೆಂಬಲಿಸಲಾಗುವುದಿಲ್ಲ",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "ವಹಿವಾಟು ID ಅಮಾನ್ಯವಾಗಿದೆ",
"transaction not found": "ವಹಿವಾಟು ಸಿಕ್ಕಿಲ್ಲ",
"transaction type is invalid": "ವಹಿವಾಟಿನ ಪ್ರಕಾರ ಅಮಾನ್ಯವಾಗಿದೆ",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "ಇತ್ತೀಚಿನ 5 ವರ್ಷಗಳು",
"Previous Billing Cycle": "ಹಿಂದಿನ ಬಿಲ್ಲಿಂಗ್ ಚಕ್ರ",
"Current Billing Cycle": "ಪ್ರಸ್ತುತ ಬಿಲ್ಲಿಂಗ್ ಚಕ್ರ",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "ಕಸ್ಟಮ್ ದಿನಾಂಕ",
@@ -1941,6 +1945,9 @@
"You have saved this account": "ನೀವು ಈ ಖಾತೆಯನ್ನು ಉಳಿಸಿದ್ದೀರಿ",
"Unable to add account": "ಖಾತೆ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ",
"Unable to save account": "ಖಾತೆ ಉಳಿಸಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "ಮರೆಮಾಡಿದ ಖಾತೆಗಳನ್ನು ತೋರಿಸಿ",
"Hide Hidden Accounts": "ಮರೆಮಾಡಿದ ಖಾತೆಗಳನ್ನು ಅಡಗಿಸಿ",
"Set Accounts Included in Total": "ಒಟ್ಟು ಲೆಕ್ಕದಲ್ಲಿ ಸೇರಿಸಲಾದ ಖಾತೆಗಳನ್ನು ಸೆಟ್ ಮಾಡಿ",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "비밀번호로 로그인할 수 없습니다",
"user name is invalid": "사용자 이름이 유효하지 않습니다",
"nick name is invalid": "사용자 닉네임이 유효하지 않습니다",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "권한이 없는 접근입니다",
"current token is invalid": "현재 토큰이 유효하지 않습니다",
"current token is expired": "현재 토큰이 만료되었습니다",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "계좌 통화를 수정하는 것은 지원되지 않습니다",
"not supported to modify account balance": "계좌 잔액을 수정하는 것은 지원되지 않습니다",
"not supported to modify account balance time": "계좌 잔액 시간을 수정하는 것은 지원되지 않습니다",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "거래 ID가 유효하지 않습니다",
"transaction not found": "거래를 찾을 수 없습니다",
"transaction type is invalid": "거래 유형이 유효하지 않습니다",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "최근 5년",
"Previous Billing Cycle": "이전 청구 주기",
"Current Billing Cycle": "현재 청구 주기",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "사용자 지정 날짜",
@@ -1941,6 +1945,9 @@
"You have saved this account": "이 계좌가 저장되었습니다.",
"Unable to add account": "계좌를 추가할 수 없습니다.",
"Unable to save account": "계좌를 저장할 수 없습니다.",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "숨겨진 계좌 표시",
"Hide Hidden Accounts": "숨겨진 계좌 숨기기",
"Set Accounts Included in Total": "총계에 포함된 계좌 설정",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "You cannot login by password",
"user name is invalid": "User name is invalid",
"nick name is invalid": "User nickname is invalid",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Ongeautoriseerde toegang",
"current token is invalid": "Huidige token is ongeldig",
"current token is expired": "Huidige token is verlopen",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Wijzigen van rekeningvaluta wordt niet ondersteund",
"not supported to modify account balance": "Wijzigen van rekeningsaldo wordt niet ondersteund",
"not supported to modify account balance time": "Wijzigen van tijdstip rekeningsaldo wordt niet ondersteund",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "Transactie-ID is ongeldig",
"transaction not found": "Transactie niet gevonden",
"transaction type is invalid": "Transactietype is ongeldig",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "Afgelopen 5 jaar",
"Previous Billing Cycle": "Vorige factureringsperiode",
"Current Billing Cycle": "Huidige factureringsperiode",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Aangepaste datum",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Je hebt deze rekening opgeslagen",
"Unable to add account": "Kan rekening niet toevoegen",
"Unable to save account": "Kan rekening niet opslaan",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Verborgen rekeningen tonen",
"Hide Hidden Accounts": "Verborgen rekeningen verbergen",
"Set Accounts Included in Total": "Rekeningen kiezen voor totaal",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "Você não pode entrar com senha",
"user name is invalid": "Nome de usuário é inválido",
"nick name is invalid": "Nome de exibição é inválido",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Acesso não autorizado",
"current token is invalid": "Token atual é inválido",
"current token is expired": "Token atual está expirado",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Não é suportado modificar moeda da conta",
"not supported to modify account balance": "Não é suportado modificar saldo da conta",
"not supported to modify account balance time": "Não é suportado modificar tempo de saldo da conta",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "ID da transação é inválido",
"transaction not found": "Transação não foi encontrada",
"transaction type is invalid": "Tipo de transação é inválido",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "Últimos 5 anos",
"Previous Billing Cycle": "Ciclo de Cobrança Anterior",
"Current Billing Cycle": "Ciclo de Cobrança Atual",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Data Personalizada",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Você salvou esta conta",
"Unable to add account": "Não foi possível adicionar conta",
"Unable to save account": "Não foi possível salvar conta",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Mostrar Contas Ocultas",
"Hide Hidden Accounts": "Ocultar Contas Ocultas",
"Set Accounts Included in Total": "Definir Contas Incluídas no Total",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "Вы не можете войти с помощью пароля",
"user name is invalid": "Недействительное имя пользователя",
"nick name is invalid": "Недействительный ник пользователя",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Несанкционированный доступ",
"current token is invalid": "Текущий токен недействителен",
"current token is expired": "Текущий токен истек",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Изменение валюты счёта не поддерживается",
"not supported to modify account balance": "Изменение баланса счёта не поддерживается",
"not supported to modify account balance time": "Изменение времени баланса счёта не поддерживается",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "ID транзакции недействителен",
"transaction not found": "Транзакция не найдена",
"transaction type is invalid": "Тип транзакции недействителен",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "Последние 5 лет",
"Previous Billing Cycle": "Предыдущий расчетный период",
"Current Billing Cycle": "Текущий расчетный период",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Выбрать дату",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Вы сохранили этот счет",
"Unable to add account": "Не удалось добавить счет",
"Unable to save account": "Не удалось сохранить счет",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Показать скрытые счета",
"Hide Hidden Accounts": "Скрыть скрытые счета",
"Set Accounts Included in Total": "Включить счет в итого",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "Prijava z geslom ni mogoča",
"user name is invalid": "Uporabniško ime ni veljavno",
"nick name is invalid": "Vzdevek uporabnika ni veljaven",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Nepooblaščen dostop",
"current token is invalid": "Trenutni žeton ni veljaven",
"current token is expired": "Trenutni žeton je potekel",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Spreminjanje valute računa ni podprto",
"not supported to modify account balance": "Spreminjanje stanja računa ni podprto",
"not supported to modify account balance time": "Spreminjanje časa stanja na računu ni podprto",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "ID transakcije ni veljaven",
"transaction not found": "Transakcije ni mogoče najti",
"transaction type is invalid": "Vrsta transakcije ni veljavna",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "Zadnjih 5 let",
"Previous Billing Cycle": "Prejšnje obračunsko obdobje",
"Current Billing Cycle": "Trenutno obračunsko obdobje",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Datum po meri",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Ta račun ste shranili",
"Unable to add account": "Računa ni mogoče dodati",
"Unable to save account": "Računa ni mogoče shraniti",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Prikaži skrite račune",
"Hide Hidden Accounts": "Skrij skrite račune",
"Set Accounts Included in Total": "Nastavi račune, vključene v skupno vsoto",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "கடவுச்சொல் மூலம் உள்நுழைய முடியாது",
"user name is invalid": "பயனர் பெயர் தவறானது உள்ளது",
"nick name is invalid": "புனைப்பெயர் தவறானது உள்ளது",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "அங்கீகரிக்கப்படாத அணுகல்",
"current token is invalid": "தற்போதைய டோக்கன் தவறானது உள்ளது",
"current token is expired": "தற்போதைய டோக்கன் காலாவதியானது",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "கணக்கு நாணயம்யை மாற்ற ஆதரிக்கப்படவில்லை",
"not supported to modify account balance": "கணக்கு இருப்பு மாற்றம் ஆதரிக்கப்படவில்லை",
"not supported to modify account balance time": "கணக்கு இருப்பு நேரம் மாற்றம் ஆதரிக்கப்படவில்லை",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "பரிவர்த்தனை ID தவறானது உள்ளது",
"transaction not found": "பரிவர்த்தனை கிடைக்கவில்லை",
"transaction type is invalid": "பரிவர்த்தனையின் வகை தவறானது உள்ளது",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "சமீபத்திய 5 ஆண்டுகள்",
"Previous Billing Cycle": "முந்தைய பில்லிங் சுழற்சி",
"Current Billing Cycle": "தற்போதைய பில்லிங் சுழற்சி",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "தனிப்பயன் தேதி",
@@ -1941,6 +1945,9 @@
"You have saved this account": "நீங்கள் இந்த கணக்கை சேமித்தீர்கள்",
"Unable to add account": "கணக்கு சேர்க்க முடியவில்லை",
"Unable to save account": "கணக்கு சேமிக்க முடியவில்லை",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "மறைந்த கணக்குகளை காட்டு",
"Hide Hidden Accounts": "மறைந்த கணக்குகளை மறை",
"Set Accounts Included in Total": "மொத்தம் லெக்கத்தில் சேர்க்கப்பட்ட கணக்குகளை அமை செய்",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "You cannot login by password",
"user name is invalid": "User name is invalid",
"nick name is invalid": "User nickname is invalid",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "การเข้าถึงไม่ได้รับอนุญาต",
"current token is invalid": "โทเค็นปัจจุบันไม่ถูกต้อง",
"current token is expired": "โทเค็นปัจจุบันหมดอายุ",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "ไม่รองรับการแก้ไขสกุลเงินบัญชี",
"not supported to modify account balance": "ไม่รองรับการแก้ไขยอดเงินบัญชี",
"not supported to modify account balance time": "ไม่รองรับการแก้ไขเวลายอดเงินบัญชี",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "รหัสธุรกรรมไม่ถูกต้อง",
"transaction not found": "ไม่พบธุรกรรม",
"transaction type is invalid": "ประเภทธุรกรรมไม่ถูกต้อง",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "5 ปีที่ผ่านมา",
"Previous Billing Cycle": "รอบบิลก่อนหน้า",
"Current Billing Cycle": "รอบบิลปัจจุบัน",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "วันที่กำหนดเอง",
@@ -1941,6 +1945,9 @@
"You have saved this account": "คุณได้บันทึกบัญชีนี้แล้ว",
"Unable to add account": "ไม่สามารถเพิ่มบัญชีได้",
"Unable to save account": "ไม่สามารถบันทึกบัญชีได้",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "แสดงบัญชีที่ซ่อนอยู่",
"Hide Hidden Accounts": "ซ่อนบัญชีที่ซ่อนอยู่",
"Set Accounts Included in Total": "ตั้งค่าบัญชีที่รวมในยอดรวม",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "Şifre ile giriş yapamazsınız",
"user name is invalid": "Kullanıcı adı geçersiz",
"nick name is invalid": "Takma ad geçersiz",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Yetkisiz erişim",
"current token is invalid": "Mevcut jeton (token) geçersiz",
"current token is expired": "Mevcut jetonun (token) süresi dolmuş",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Hesap para birimini değiştirmek desteklenmiyor",
"not supported to modify account balance": "Hesap bakiyesini değiştirmek desteklenmiyor",
"not supported to modify account balance time": "Hesap bakiye zamanını değiştirmek desteklenmiyor",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "İşlem ID geçersiz",
"transaction not found": "İşlem bulunamadı",
"transaction type is invalid": "İşlem türü geçersiz",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "Son 5 yıl",
"Previous Billing Cycle": "Önceki Fatura Dönemi",
"Current Billing Cycle": "Mevcut Fatura Dönemi",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Özel Tarih",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Bu hesabı kaydettiniz",
"Unable to add account": "Hesap eklenemedi",
"Unable to save account": "Hesap kaydedilemedi",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Gizli Hesapları Göster",
"Hide Hidden Accounts": "Gizli Hesapları Gizle",
"Set Accounts Included in Total": "Toplamda Dahil Edilecek Hesapları Ayarla",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "You cannot login by password",
"user name is invalid": "User name is invalid",
"nick name is invalid": "User nickname is invalid",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Несанкціонований доступ",
"current token is invalid": "Поточний токен недійсний",
"current token is expired": "Поточний токен прострочений",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Not supported to modify account currency",
"not supported to modify account balance": "Not supported to modify account balance",
"not supported to modify account balance time": "Not supported to modify account balance time",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "ID транзакції недійсний",
"transaction not found": "Транзакцію не знайдено",
"transaction type is invalid": "Тип транзакції недійсний",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "Останні 5 років",
"Previous Billing Cycle": "Попередній розрахунковий період",
"Current Billing Cycle": "Поточний розрахунковий період",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Обрати дату",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Ви зберегли цей рахунок",
"Unable to add account": "Не вдалося додати рахунок",
"Unable to save account": "Не вдалося зберегти рахунок",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Показати приховані рахунки",
"Hide Hidden Accounts": "Приховати приховані рахунки",
"Set Accounts Included in Total": "Set Accounts Included in Total",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "You cannot login by password",
"user name is invalid": "User name is invalid",
"nick name is invalid": "User nickname is invalid",
"last reconciled time is not enabled": "Last reconciled time is not enabled",
"unauthorized access": "Truy cập trái phép",
"current token is invalid": "Mã thông báo hiện tại không hợp lệ",
"current token is expired": "Mã thông báo hiện tại đã hết hạn",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "Not supported to modify account currency",
"not supported to modify account balance": "Not supported to modify account balance",
"not supported to modify account balance time": "Not supported to modify account balance time",
"parent account cannot set last reconciled time": "Parent account cannot set last reconciled time",
"cannot set last reconciled time before current value": "Cannot set last reconciled time before current value",
"transaction id is invalid": "ID giao dịch không hợp lệ",
"transaction not found": "Không tìm thấy giao dịch",
"transaction type is invalid": "Loại giao dịch không hợp lệ",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "5 năm gần đây",
"Previous Billing Cycle": "Previous Billing Cycle",
"Current Billing Cycle": "Current Billing Cycle",
"Since Last Reconciled Time": "Since Last Reconciled Time",
"Last day": "Last day",
"last day": "last day",
"Custom Date": "Ngày tùy chỉnh",
@@ -1941,6 +1945,9 @@
"You have saved this account": "Bạn đã lưu tài khoản này",
"Unable to add account": "Không thể thêm tài khoản",
"Unable to save account": "Không thể lưu tài khoản",
"Mark as Reconciled": "Mark as Reconciled",
"Last reconciled time have been updated": "Last reconciled time have been updated",
"Unable to update last reconciled time": "Unable to update last reconciled time",
"Show Hidden Accounts": "Hiển thị tài khoản ẩn",
"Hide Hidden Accounts": "Ẩn tài khoản ẩn",
"Set Accounts Included in Total": "Set Accounts Included in Total",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "您不能使用密码登录",
"user name is invalid": "用户名无效",
"nick name is invalid": "用户昵称无效",
"last reconciled time is not enabled": "最后对账时间没有启用",
"unauthorized access": "未授权的登录",
"current token is invalid": "当前认证令牌无效",
"current token is expired": "当前认证令牌已过期",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "不支持修改账户货币",
"not supported to modify account balance": "不支持修改账户余额",
"not supported to modify account balance time": "不支持修改账户余额时间",
"parent account cannot set last reconciled time": "父账户不能设置最后对账时间",
"cannot set last reconciled time before current value": "不能将最后对账时间设置为早于当前值的时间",
"transaction id is invalid": "交易ID无效",
"transaction not found": "交易不存在",
"transaction type is invalid": "交易类型无效",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "最近5年",
"Previous Billing Cycle": "上个账单周期",
"Current Billing Cycle": "当前账单周期",
"Since Last Reconciled Time": "自最后对账时间起",
"Last day": "倒数第1日",
"last day": "倒数第1日",
"Custom Date": "自定义日期",
@@ -1941,6 +1945,9 @@
"You have saved this account": "您已经保存该账户",
"Unable to add account": "无法添加账户",
"Unable to save account": "无法保存账户",
"Mark as Reconciled": "标记为已对账",
"Last reconciled time have been updated": "最后对账时间已更新",
"Unable to update last reconciled time": "无法更新最后对账时间",
"Show Hidden Accounts": "显示隐藏的账户",
"Hide Hidden Accounts": "不显示隐藏的账户",
"Set Accounts Included in Total": "设置计入总金额的账户",
+7
View File
@@ -1112,6 +1112,7 @@
"cannot login by password": "您不能使用密碼登入",
"user name is invalid": "使用者名稱無效",
"nick name is invalid": "使用者暱稱無效",
"last reconciled time is not enabled": "最後對帳時間未啟用",
"unauthorized access": "未授權的登入",
"current token is invalid": "目前認證令牌無效",
"current token is expired": "目前認證令牌已過期",
@@ -1155,6 +1156,8 @@
"not supported to modify account currency": "不支援修改帳戶貨幣",
"not supported to modify account balance": "不支援修改帳戶餘額",
"not supported to modify account balance time": "不支援修改帳戶餘額時間",
"parent account cannot set last reconciled time": "父帳戶不能設定最後對帳時間",
"cannot set last reconciled time before current value": "不能將最後對帳時間設定為早於目前值的時間",
"transaction id is invalid": "交易ID無效",
"transaction not found": "交易不存在",
"transaction type is invalid": "交易類型無效",
@@ -1548,6 +1551,7 @@
"Recent 5 years": "最近5年",
"Previous Billing Cycle": "上個帳單週期",
"Current Billing Cycle": "當前帳單週期",
"Since Last Reconciled Time": "自最後對帳時間起",
"Last day": "倒數第1日",
"last day": "倒數第1日",
"Custom Date": "自訂日期",
@@ -1941,6 +1945,9 @@
"You have saved this account": "您已經儲存此帳戶",
"Unable to add account": "無法新增帳戶",
"Unable to save account": "無法儲存帳戶",
"Mark as Reconciled": "標記為已對帳",
"Last reconciled time have been updated": "最後對帳時間已更新",
"Unable to update last reconciled time": "無法更新最後對帳時間",
"Show Hidden Accounts": "顯示隱藏的帳戶",
"Hide Hidden Accounts": "不顯示隱藏的帳戶",
"Set Accounts Included in Total": "設定計入總金額的帳戶",
+5
View File
@@ -614,6 +614,11 @@ export interface AccountModifyRequest {
readonly clientSessionId?: string;
}
export interface AccountUpdateLastReconciledTimeRequest {
readonly id: string;
readonly lastReconciledTime: number;
}
export interface AccountInfoResponse {
readonly id: string;
readonly name: string;
+37
View File
@@ -903,6 +903,42 @@ export const useAccountsStore = defineStore('accounts', () => {
});
}
function updateAccountLastReconciledTime(accountId: string, lastReconciledTime: number): Promise<boolean> {
return new Promise((resolve, reject) => {
const account = allAccountsMap.value[accountId];
services.updateAccountLastReconciledTime({
id: accountId,
lastReconciledTime: lastReconciledTime
}).then(response => {
const data = response.data;
if (!data || !data.success || !data.result) {
reject({ message: 'Unable to last reconciled time' });
return;
}
if (account) {
account.lastReconciledTime = lastReconciledTime;
} else {
updateAccountListInvalidState(true);
}
resolve(data.result);
}).catch(error => {
logger.error('failed to update last reconciled time', error);
if (error.response && error.response.data && error.response.data.errorMessage) {
reject({ error: error.response.data });
} else if (!error.processed) {
reject({ message: 'Unable to update last reconciled time' });
} else {
reject(error);
}
});
});
}
function changeAccountDisplayOrder({ accountId, from, to, updateListOrder, updateGlobalListOrder }: { accountId: string, from: number, to: number, updateListOrder: boolean, updateGlobalListOrder: boolean }): Promise<void> {
const account = allAccountsMap.value[accountId];
@@ -1108,6 +1144,7 @@ export const useAccountsStore = defineStore('accounts', () => {
loadAllAccounts,
getAccount,
saveAccount,
updateAccountLastReconciledTime,
changeAccountDisplayOrder,
updateAccountDisplayOrders,
hideAccount,
+6 -1
View File
@@ -746,6 +746,9 @@ export const useTransactionsStore = defineStore('transactions', () => {
if (DateRange.isBillingCycle(transactionsFilter.value.dateType) &&
(!accountsStore.getAccountStatementDate(filter.accountIds) || accountsStore.getAccountStatementDate(filter.accountIds) !== accountsStore.getAccountStatementDate(transactionsFilter.value.accountIds))) {
transactionsFilter.value.dateType = DateRange.Custom.type;
} else if (DateRange.isLastReconciledTimeRange(transactionsFilter.value.dateType) &&
(!accountsStore.allAccountsMap[filter.accountIds] || accountsStore.allAccountsMap[filter.accountIds]?.lastReconciledTime !== accountsStore.allAccountsMap[transactionsFilter.value.accountIds]?.lastReconciledTime)) {
transactionsFilter.value.dateType = DateRange.Custom.type;
}
transactionsFilter.value.accountIds = filter.accountIds;
@@ -793,7 +796,9 @@ export const useTransactionsStore = defineStore('transactions', () => {
querys.push('dateType=' + transactionsFilter.value.dateType);
if (DateRange.isBillingCycle(transactionsFilter.value.dateType) || transactionsFilter.value.dateType === DateRange.Custom.type) {
if (DateRange.isBillingCycle(transactionsFilter.value.dateType)
|| DateRange.isLastReconciledTimeRange(transactionsFilter.value.dateType)
|| transactionsFilter.value.dateType === DateRange.Custom.type) {
querys.push('maxTime=' + transactionsFilter.value.maxTime);
querys.push('minTime=' + transactionsFilter.value.minTime);
}
@@ -35,6 +35,7 @@ export function useAccountListPageBase() {
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
const fiscalYearStart = computed<number>(() => userStore.currentUserFiscalYearStart);
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
const useLastReconciledTime = computed(() => userStore.currentUserUseLastReconciledTime);
const allAccounts = computed<Account[]>(() => accountsStore.allAccounts);
const allCategorizedAccountsMap = computed<Record<number, CategorizedAccount>>(() => accountsStore.allCategorizedAccountsMap);
@@ -99,6 +100,7 @@ export function useAccountListPageBase() {
firstDayOfWeek,
fiscalYearStart,
defaultCurrency,
useLastReconciledTime,
allAccounts,
allCategorizedAccountsMap,
allAccountCount,
@@ -27,6 +27,7 @@ import { replaceAll } from '@/lib/common.ts';
import {
getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffsetMinutes,
getCurrentUnixTime,
parseDateTimeFromUnixTime,
parseDateTimeFromUnixTimeWithTimezoneOffset
} from '@/lib/datetime.ts';
@@ -53,6 +54,7 @@ export function useReconciliationStatementPageBase() {
const accountId = ref<string>('');
const startTime = ref<number>(0);
const endTime = ref<number>(0);
const pageOpenTime = ref<number>(getCurrentUnixTime());
const reconciliationStatements = ref<TransactionReconciliationStatementResponseWithInfo | undefined>(undefined);
const chartDataDateAggregationType = ref<number>(ChartDateAggregationType.Day.type);
const timezoneUsedForDateRange = ref<number>(TimezoneTypeForStatistics.ApplicationTimezone.type);
@@ -61,6 +63,7 @@ export function useReconciliationStatementPageBase() {
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
const fiscalYearStart = computed<number>(() => userStore.currentUserFiscalYearStart);
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
const useLastReconciledTime = computed(() => userStore.currentUserUseLastReconciledTime);
const allChartTypes = computed<TypeAndDisplayName[]>(() => getAllAccountBalanceTrendChartTypes());
const allDateAggregationTypes = computed<TypeAndDisplayName[]>(() => getAllStatisticsDateAggregationTypesWithShortName(StatisticsAnalysisType.AssetTrends, !!currentAccountStatementDate.value));
@@ -69,8 +72,23 @@ export function useReconciliationStatementPageBase() {
const currentAccount = computed(() => allAccountsMap.value[accountId.value]);
const currentAccountCurrency = computed<string>(() => currentAccount.value?.currency ?? defaultCurrency.value);
const currentAccountStatementDate = computed<number | undefined>(() => accountsStore.getAccountStatementDate(accountId.value) || undefined);
const currentAccountLastReconciledTime = computed<number | undefined>(() => currentAccount.value?.lastReconciledTime);
const isCurrentLiabilityAccount = computed<boolean>(() => currentAccount.value?.isLiability ?? false);
const newLastReconciledTime = computed<number | undefined>(() => {
if (!currentAccount.value || !useLastReconciledTime.value) {
return undefined;
}
const actualEndTime: number = endTime.value === 0 ? pageOpenTime.value : Math.min(endTime.value, pageOpenTime.value);
if (!currentAccountLastReconciledTime.value || actualEndTime > currentAccountLastReconciledTime.value) {
return actualEndTime;
} else {
return undefined;
}
});
const exportFileName = computed<string>(() => {
const nickname = userStore.currentUserNickname;
@@ -124,6 +142,10 @@ export function useReconciliationStatementPageBase() {
}
});
function updatePageOpenTime() {
pageOpenTime.value = getCurrentUnixTime();
}
function setReconciliationStatements(response: TransactionReconciliationStatementResponse | undefined) {
if (!response) {
reconciliationStatements.value = undefined;
@@ -305,13 +327,16 @@ export function useReconciliationStatementPageBase() {
firstDayOfWeek,
fiscalYearStart,
defaultCurrency,
useLastReconciledTime,
allChartTypes,
allDateAggregationTypes,
allTimezoneTypesUsedForDateRange,
currentAccount,
currentAccountCurrency,
currentAccountStatementDate,
currentAccountLastReconciledTime,
isCurrentLiabilityAccount,
newLastReconciledTime,
exportFileName,
displayStartDateTime,
displayEndDateTime,
@@ -321,6 +346,7 @@ export function useReconciliationStatementPageBase() {
displayOpeningBalance,
displayClosingBalance,
// functions
updatePageOpenTime,
setReconciliationStatements,
getDisplayTransactionType,
getDisplayDateTime,
@@ -24,10 +24,10 @@ export function useStatisticsSettingPageBase() {
const allTimezoneTypesUsedForStatistics = computed<TypeAndDisplayName[]>(() => getAllTimezoneTypesUsedForStatistics());
const allSortingTypes = computed<TypeAndDisplayName[]>(() => getAllStatisticsSortingTypes());
const allCategoricalChartTypes = computed<TypeAndDisplayName[]>(() => getAllCategoricalChartTypes());
const allCategoricalChartDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.Normal, false));
const allCategoricalChartDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.Normal, {}));
const allTrendChartTypes = computed<TypeAndDisplayName[]>(() => getAllTrendChartTypes());
const allTrendChartDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.TrendAnalysis, false));
const allAssetTrendsChartDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.AssetTrends, false));
const allTrendChartDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.TrendAnalysis, {}));
const allAssetTrendsChartDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.AssetTrends, {}));
const defaultChartDataType = computed<number>({
get: () => settingsStore.appSettings.statistics.defaultChartDataType,
@@ -63,11 +63,11 @@ export function useStatisticsTransactionPageBase() {
const allDateRanges = computed<LocalizedDateRange[]>(() => {
if (analysisType.value === StatisticsAnalysisType.CategoricalAnalysis) {
return getAllDateRanges(DateRangeScene.Normal, true);
return getAllDateRanges(DateRangeScene.Normal, { includeCustom: true });
} else if (analysisType.value === StatisticsAnalysisType.TrendAnalysis) {
return getAllDateRanges(DateRangeScene.TrendAnalysis, true);
return getAllDateRanges(DateRangeScene.TrendAnalysis, { includeCustom: true });
} else if (analysisType.value === StatisticsAnalysisType.AssetTrends) {
return getAllDateRanges(DateRangeScene.AssetTrends, true);
return getAllDateRanges(DateRangeScene.AssetTrends, { includeCustom: true });
} else {
return [];
}
@@ -105,7 +105,11 @@ export function useTransactionListPageBase() {
const showTotalAmountInTransactionListPage = computed<boolean>(() => settingsStore.appSettings.showTotalAmountInTransactionListPage);
const showTagInTransactionListPage = computed<boolean>(() => settingsStore.appSettings.showTagInTransactionListPage);
const allDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.Normal, true, !!accountsStore.getAccountStatementDate(query.value.accountIds)));
const allDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.Normal, {
includeCustom: true,
includeBillingCycle: !!accountsStore.getAccountStatementDate(query.value.accountIds),
includeLastReconciledTimeRange: !!allAccountsMap.value[query.value.accountIds]?.lastReconciledTime
}));
const allAccounts = computed<Account[]>(() => accountsStore.allMixedPlainAccounts);
const allAccountsMap = computed<Record<string, Account>>(() => accountsStore.allAccountsMap);
+41 -2
View File
@@ -256,6 +256,12 @@
{{ tt('More') }}
<v-menu activator="parent" :open-on-hover="true">
<v-list>
<v-list-item class="text-sm" density="compact"
:title="tt('Mark as Reconciled')"
:prepend-icon="mdiReceiptTextCheckOutline"
@click="updateLastReconciledTime(element.getAccountOrSubAccount(activeSubAccount[element.id]))"
v-if="useLastReconciledTime"></v-list-item>
<v-divider class="my-2" v-if="useLastReconciledTime" />
<v-list-item class="text-sm" density="compact"
:title="tt('Move All Transactions')"
:prepend-icon="mdiSwapHorizontal"
@@ -336,7 +342,12 @@ import { AccountType, AccountCategory } from '@/core/account.ts';
import type { Account } from '@/models/account.ts';
import { isNumber } from '@/lib/common.ts';
import { getDateRangeByDateType, getDateRangeByBillingCycleDateType } from '@/lib/datetime.ts';
import {
getCurrentUnixTime,
getDateRangeByDateType,
getDateRangeByBillingCycleDateType,
getDateRangeByLastReconciledTimeRangeDateType
} from '@/lib/datetime.ts';
import {
mdiEyeOutline,
@@ -347,6 +358,7 @@ import {
mdiMenu,
mdiPencilOutline,
mdiDotsHorizontalCircleOutline,
mdiReceiptTextCheckOutline,
mdiSwapHorizontal,
mdiEraser,
mdiDeleteOutline,
@@ -376,6 +388,7 @@ const {
defaultAccountCategory,
firstDayOfWeek,
fiscalYearStart,
useLastReconciledTime,
allAccounts,
allCategorizedAccountsMap,
allAccountCount,
@@ -486,7 +499,11 @@ function accountCurrency(account: Account): string | null {
}
function accountReconciliationStatementDateRanges(account: Account): LocalizedDateRange[] {
return getAllDateRanges(DateRangeScene.Normal, true, !!accountsStore.getAccountStatementDate(account.id));
return getAllDateRanges(DateRangeScene.Normal, {
includeCustom: true,
includeBillingCycle: !!accountsStore.getAccountStatementDate(account.id),
includeLastReconciledTimeRange: !!account.lastReconciledTime
});
}
function add(): void {
@@ -533,6 +550,8 @@ function showReconciliationStatementCustomDateRangeDialog(account: Account, date
if (DateRange.isBillingCycle(dateRangeType)) {
dateRange = getDateRangeByBillingCycleDateType(dateRangeType, firstDayOfWeek.value, fiscalYearStart.value, accountsStore.getAccountStatementDate(account.id));
} else if (DateRange.isLastReconciledTimeRange(dateRangeType)) {
dateRange = getDateRangeByLastReconciledTimeRangeDateType(dateRangeType, account.lastReconciledTime);
} else {
dateRange = getDateRangeByDateType(dateRangeType, firstDayOfWeek.value, fiscalYearStart.value);
}
@@ -548,6 +567,26 @@ function showReconciliationStatementCustomDateRangeDialog(account: Account, date
});
}
function updateLastReconciledTime(account: Account): void {
loading.value = true;
accountsStore.updateAccountLastReconciledTime(account.id, getCurrentUnixTime()).then(() => {
loading.value = false;
snackbar.value?.showMessage('Last reconciled time have been updated');
if (accountsStore.accountListStateInvalid && !loading.value) {
reload(false);
}
}).catch(error => {
loading.value = false;
if (error) {
snackbar.value?.showError(error);
}
});
}
function moveAllTransactions(account: Account): void {
moveAllTransactionsDialog.value?.open(account).then(() => {
snackbar.value?.showMessage('All transactions in this account have been moved.');
@@ -1,12 +1,13 @@
<template>
<v-dialog :persistent="loading" v-model="showState">
<v-dialog :persistent="loading || updatingLastReconciledTime" v-model="showState">
<v-card class="pa-sm-1 pa-md-2">
<template #title>
<div class="d-flex align-center justify-center">
<div class="d-flex flex-wrap w-100 align-center">
<h4 class="text-h4">{{ tt('Reconciliation Statement') }}</h4>
<v-btn density="compact" color="default" variant="text" size="24"
class="ms-2" :icon="true" :loading="loading" @click="reload(true)">
class="ms-2" :icon="true" :disabled="updatingLastReconciledTime"
:loading="loading" @click="reload(true)">
<template #loader>
<v-progress-circular indeterminate size="20"/>
</template>
@@ -14,7 +15,7 @@
<v-tooltip activator="parent">{{ tt('Refresh') }}</v-tooltip>
</v-btn>
<v-switch class="bidirectional-switch ms-2 pt-1" color="secondary"
:disabled="loading"
:disabled="loading || updatingLastReconciledTime"
:label="tt('Account Balance Trends')"
v-model="showAccountBalanceTrendsCharts"
@click="showAccountBalanceTrendsCharts = !showAccountBalanceTrendsCharts">
@@ -24,7 +25,7 @@
</v-switch>
</div>
<v-btn density="comfortable" color="default" variant="text" class="ms-2"
:icon="true" :disabled="loading"
:icon="true" :disabled="loading || updatingLastReconciledTime"
v-if="showAccountBalanceTrendsCharts">
<v-icon :icon="mdiTuneVertical" />
<v-menu activator="parent">
@@ -56,7 +57,7 @@
</v-menu>
</v-btn>
<v-btn density="comfortable" color="default" variant="text" class="ms-2"
:icon="true" :disabled="loading">
:icon="true" :disabled="loading || updatingLastReconciledTime">
<v-icon :icon="mdiDotsVertical" />
<v-menu activator="parent">
<v-list>
@@ -201,7 +202,7 @@
<span>{{ getDisplayAccountBalance(item) }}</span>
</template>
<template #item.operation="{ item }">
<v-btn density="compact" variant="text" color="default" :disabled="loading || item.type === TransactionType.ModifyBalance"
<v-btn density="compact" variant="text" color="default" :disabled="loading || updatingLastReconciledTime || item.type === TransactionType.ModifyBalance"
@click="showTransaction(item)">
{{ tt('View') }}
</v-btn>
@@ -267,8 +268,14 @@
<v-card-text>
<div class="w-100 d-flex justify-center flex-wrap mt-sm-1 mt-md-2 gap-4">
<v-btn color="primary" variant="tonal"
:disabled="loading || updatingLastReconciledTime" @click="updateLastReconciledTime"
v-if="newLastReconciledTime">
{{ tt('Mark as Reconciled') }}
<v-progress-circular indeterminate size="22" class="ms-2" v-if="updatingLastReconciledTime"></v-progress-circular>
</v-btn>
<v-btn color="secondary" variant="tonal"
:disabled="loading" @click="close">{{ tt('Close') }}</v-btn>
:disabled="loading || updatingLastReconciledTime" @click="close">{{ tt('Close') }}</v-btn>
</div>
</v-card-text>
</v-card>
@@ -360,6 +367,7 @@ const {
currentAccountCurrency,
currentAccountStatementDate,
isCurrentLiabilityAccount,
newLastReconciledTime,
exportFileName,
displayStartDateTime,
displayEndDateTime,
@@ -368,6 +376,7 @@ const {
displayTotalBalance,
displayOpeningBalance,
displayClosingBalance,
updatePageOpenTime,
setReconciliationStatements,
getDisplayTransactionType,
getDisplayDateTime,
@@ -411,6 +420,7 @@ const editDialog = useTemplateRef<EditDialogType>('editDialog');
const showState = ref<boolean>(false);
const loading = ref<boolean>(false);
const updatingLastReconciledTime = ref<boolean>(false);
const currentPage = ref<number>(1);
const countPerPage = ref<number>(10);
const showAccountBalanceTrendsCharts = ref<boolean>(false);
@@ -490,6 +500,7 @@ function getTransactionTypeColor(transaction: TransactionReconciliationStatement
}
function open(options: { accountId: string, startTime: number, endTime: number }): Promise<void> {
updatePageOpenTime();
accountId.value = options.accountId;
startTime.value = options.startTime;
endTime.value = options.endTime;
@@ -657,6 +668,25 @@ function showTransaction(transaction: TransactionReconciliationStatementResponse
});
}
function updateLastReconciledTime(): void {
if (!newLastReconciledTime.value) {
return;
}
updatingLastReconciledTime.value = true;
accountsStore.updateAccountLastReconciledTime(accountId.value, newLastReconciledTime.value).then(() => {
updatingLastReconciledTime.value = false;
snackbar.value?.showMessage('Last reconciled time have been updated');
}).catch(error => {
updatingLastReconciledTime.value = false;
if (error) {
snackbar.value?.showError(error);
}
});
}
function close(): void {
rejectFunc?.();
showState.value = false;
@@ -441,7 +441,7 @@ const showTransactionCategoriesIncludedInHomePageOverviewDialog = ref<boolean>(f
const showAccountsIncludedInTotalDialog = ref<boolean>(false);
const enableDisableOptions = computed<LocalizedSwitchOption[]>(() => getAllEnableDisableOptions());
const allInsightsExplorerDefaultDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.InsightsExplorer, false));
const allInsightsExplorerDefaultDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.InsightsExplorer, {}));
const currentTheme = computed<string>({
get: () => settingsStore.appSettings.theme,
+1 -1
View File
@@ -353,7 +353,7 @@ const currentFilter = computed<TransactionExplorerFilter>(() => explorersStore.t
const currentExplorer = computed<InsightsExplorer>(() => explorersStore.currentInsightsExplorer);
const filteredTransactionsInDataTable = computed<TransactionInsightDataItem[]>(() => explorersStore.filteredTransactionsInDataTable);
const allDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.InsightsExplorer, true));
const allDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.InsightsExplorer, { includeCustom: true }));
const allTimezoneTypesUsedForDateRange = computed<TypeAndDisplayName[]>(() => getAllTimezoneTypesUsedForStatistics());
const canShiftDateRange = computed<boolean>(() => currentFilter.value.dateRangeType !== DateRange.All.type);
const displayQueryDateRangeName = computed<string>(() => formatDateRange(currentFilter.value.dateRangeType, currentFilter.value.startTime, currentFilter.value.endTime));
+4 -1
View File
@@ -711,6 +711,7 @@ import {
getDateTypeByBillingCycleDateRange,
getDateRangeByDateType,
getDateRangeByBillingCycleDateType,
getDateRangeByLastReconciledTimeRangeDateType,
getRecentDateRangeIndex,
getFullMonthDateRange,
getValidMonthDayOrCurrentDayShortDate
@@ -1102,7 +1103,7 @@ function init(initProps: TransactionListProps): void {
let dateRange: TimeRangeAndDateType | null = getDateRangeByDateType(initProps.initDateType ? parseInt(initProps.initDateType) : undefined, firstDayOfWeek.value, fiscalYearStart.value);
if (!dateRange && initProps.initDateType && initProps.initMaxTime && initProps.initMinTime &&
(DateRange.isBillingCycle(parseInt(initProps.initDateType)) || initProps.initDateType === DateRange.Custom.type.toString()) &&
(DateRange.isBillingCycle(parseInt(initProps.initDateType)) || DateRange.isLastReconciledTimeRange(parseInt(initProps.initDateType)) || initProps.initDateType === DateRange.Custom.type.toString()) &&
parseInt(initProps.initMaxTime) > 0 && parseInt(initProps.initMinTime) > 0) {
dateRange = {
dateType: parseInt(initProps.initDateType),
@@ -1264,6 +1265,8 @@ function changeDateFilter(dateRange: TimeRangeAndDateType | number | null): void
if (isNumber(dateRange)) {
if (DateRange.isBillingCycle(dateRange)) {
dateRange = getDateRangeByBillingCycleDateType(dateRange, firstDayOfWeek.value, fiscalYearStart.value, accountsStore.getAccountStatementDate(query.value.accountIds));
} else if (DateRange.isLastReconciledTimeRange(dateRange)) {
dateRange = getDateRangeByLastReconciledTimeRangeDateType(dateRange, allAccountsMap.value[query.value.accountIds]?.lastReconciledTime);
} else {
dateRange = getDateRangeByDateType(dateRange, firstDayOfWeek.value, fiscalYearStart.value);
}
+35
View File
@@ -164,6 +164,7 @@
<f7-actions close-by-outside-click close-on-escape :opened="showAccountMoreActionSheet" @actions:closed="showAccountMoreActionSheet = false">
<f7-actions-group v-if="accountForMoreActionSheet && accountForMoreActionSheet.type === AccountType.SingleAccount.type">
<f7-actions-button @click="showReconciliationStatement(accountForMoreActionSheet)">{{ tt('Reconciliation Statement') }}</f7-actions-button>
<f7-actions-button @click="updateLastReconciledTime(accountForMoreActionSheet)" v-if="useLastReconciledTime">{{ tt('Mark as Reconciled') }}</f7-actions-button>
</f7-actions-group>
<f7-actions-group v-if="accountForMoreActionSheet && accountForMoreActionSheet.type === AccountType.SingleAccount.type">
<f7-actions-button @click="moveAllTransactions(accountForMoreActionSheet)">{{ tt('Move All Transactions') }}</f7-actions-button>
@@ -175,6 +176,7 @@
v-show="showHidden || !subAccount.hidden">
<f7-actions-label>{{ subAccount.name }}</f7-actions-label>
<f7-actions-button @click="showReconciliationStatement(subAccount)">{{ tt('Reconciliation Statement') }}</f7-actions-button>
<f7-actions-button @click="updateLastReconciledTime(subAccount)" v-if="useLastReconciledTime">{{ tt('Mark as Reconciled') }}</f7-actions-button>
<f7-actions-button @click="moveAllTransactions(subAccount)">{{ tt('Move All Transactions') }}</f7-actions-button>
<f7-actions-button color="red" @click="showPasswordSheetForClearAllTransaction(subAccount)">{{ tt('Clear All Transactions') }}</f7-actions-button>
</f7-actions-group>
@@ -235,6 +237,7 @@ import { TextDirection } from '@/core/text.ts';
import { AccountType, AccountCategory } from '@/core/account.ts';
import type { Account, AccountShowingIds } from '@/models/account.ts';
import { getCurrentUnixTime } from '@/lib/datetime.ts';
import { onSwipeoutDeleted } from '@/lib/ui/mobile.ts';
const props = defineProps<{
@@ -250,6 +253,7 @@ const {
displayOrderModified,
showAccountBalance,
customAccountCategoryOrder,
useLastReconciledTime,
allCategorizedAccountsMap,
allAccountCount,
maxCategoryAccountCount,
@@ -269,6 +273,7 @@ const accountForMoreActionSheet = ref<Account | null>(null);
const accountToDelete = ref<Account | null>(null);
const accountToClearTransactions = ref<Account | null>(null);
const currentPasswordForClearData = ref<string>('');
const updatingLastReconciledTime = ref<boolean>(false);
const clearingData = ref<boolean>(false);
const showAccountMoreActionSheet = ref<boolean>(false);
const showMoreActionSheet = ref<boolean>(false);
@@ -370,6 +375,36 @@ function showReconciliationStatement(account: Account | null): void {
accountForMoreActionSheet.value = null;
}
function updateLastReconciledTime(account: Account | null): void {
if (!account) {
showAlert('An error occurred');
return;
}
updatingLastReconciledTime.value = true;
showLoading(() => updatingLastReconciledTime.value);
accountsStore.updateAccountLastReconciledTime(account.id, getCurrentUnixTime()).then(() => {
updatingLastReconciledTime.value = false;
hideLoading();
showToast('Last reconciled time have been updated');
if (accountsStore.accountListStateInvalid && !loading.value) {
reload();
}
}).catch(error => {
updatingLastReconciledTime.value = false;
hideLoading();
if (!error.processed) {
showToast(error.message || error);
}
});
showAccountMoreActionSheet.value = false;
accountForMoreActionSheet.value = null;
}
function moveAllTransactions(account: Account | null): void {
if (!account) {
showAlert('An error occurred');
@@ -1,18 +1,18 @@
<template>
<f7-page @page:afterin="onPageAfterIn">
<f7-navbar>
<f7-nav-left :class="{ 'disabled': loading }" :back-link="tt('Back')"></f7-nav-left>
<f7-nav-left :class="{ 'disabled': loading || updatingLastReconciledTime }" :back-link="tt('Back')"></f7-nav-left>
<f7-nav-title>
<span style="color: var(--f7-text-color)" v-if="!finishQuery">{{ tt('Reconciliation Statement') }}</span>
<f7-link popover-open=".display-mode-popover-menu" :class="{ 'disabled': loading }" v-if="finishQuery">
<f7-link popover-open=".display-mode-popover-menu" :class="{ 'disabled': loading || updatingLastReconciledTime }" v-if="finishQuery">
<span style="color: var(--f7-text-color)">{{ tt('Reconciliation Statement') }}</span>
<f7-icon class="page-title-bar-icon" style="opacity: 0.5"
color="gray" f7="chevron_down_circle_fill"></f7-icon>
</f7-link>
</f7-nav-title>
<f7-nav-right :class="{ 'navbar-compact-icons': true, 'disabled': loading }">
<f7-nav-right :class="{ 'navbar-compact-icons': true, 'disabled': loading || updatingLastReconciledTime }">
<f7-link icon-f7="checkmark_alt" :class="{ 'disabled': !validQuery }" @click="reload(false)" v-if="!finishQuery"></f7-link>
<f7-link icon-f7="ellipsis" :class="{ 'disabled': loading }" v-if="finishQuery" @click="showMoreActionSheet = true"></f7-link>
<f7-link icon-f7="ellipsis" :class="{ 'disabled': loading || updatingLastReconciledTime }" v-if="finishQuery" @click="showMoreActionSheet = true"></f7-link>
</f7-nav-right>
</f7-navbar>
@@ -265,7 +265,7 @@
<div></div>
<div class="align-self-flex-end">
<span style="margin-inline-end: 4px;">{{ tt('Time Granularity') }}</span>
<f7-link :class="{ 'disabled': loading }" href="#" popover-open=".chart-data-date-aggregation-type-popover-menu">{{ chartDataDateAggregationTypeDisplayName }}</f7-link>
<f7-link :class="{ 'disabled': loading || updatingLastReconciledTime }" href="#" popover-open=".chart-data-date-aggregation-type-popover-menu">{{ chartDataDateAggregationTypeDisplayName }}</f7-link>
</div>
</div>
</f7-card-header>
@@ -332,11 +332,12 @@
<f7-actions close-by-outside-click close-on-escape :opened="showMoreActionSheet" @actions:closed="showMoreActionSheet = false">
<f7-actions-group>
<f7-actions-button :class="{ 'disabled': loading }" @click="addTransaction()">{{ tt('Add Transaction') }}</f7-actions-button>
<f7-actions-button :class="{ 'disabled': loading }" @click="updateClosingBalance(undefined)">{{ tt('Update Closing Balance') }}</f7-actions-button>
<f7-actions-button :class="{ 'disabled': loading || updatingLastReconciledTime }" @click="addTransaction()">{{ tt('Add Transaction') }}</f7-actions-button>
<f7-actions-button :class="{ 'disabled': loading || updatingLastReconciledTime }" @click="updateClosingBalance(undefined)">{{ tt('Update Closing Balance') }}</f7-actions-button>
<f7-actions-button :class="{ 'disabled': loading || updatingLastReconciledTime }" @click="updateLastReconciledTime()" v-if="newLastReconciledTime">{{ tt('Mark as Reconciled') }}</f7-actions-button>
</f7-actions-group>
<f7-actions-group>
<f7-actions-button :class="{ 'disabled': loading }" @click="reload(true)">{{ tt('Refresh') }}</f7-actions-button>
<f7-actions-button :class="{ 'disabled': loading || updatingLastReconciledTime }" @click="reload(true)">{{ tt('Refresh') }}</f7-actions-button>
</f7-actions-group>
<f7-actions-group>
<f7-actions-button bold close>{{ tt('Cancel') }}</f7-actions-button>
@@ -380,7 +381,8 @@ import {
getDateTypeByDateRange,
getDateTypeByBillingCycleDateRange,
getDateRangeByDateType,
getDateRangeByBillingCycleDateType
getDateRangeByBillingCycleDateType,
getDateRangeByLastReconciledTimeRangeDateType
} from '@/lib/datetime.ts';
interface ReconciliationStatementVirtualListData {
@@ -423,9 +425,11 @@ const {
allDateAggregationTypes,
allTimezoneTypesUsedForDateRange,
isCurrentLiabilityAccount,
newLastReconciledTime,
currentAccount,
currentAccountCurrency,
currentAccountStatementDate,
currentAccountLastReconciledTime,
displayStartDateTime,
displayEndDateTime,
displayTotalInflows,
@@ -433,6 +437,7 @@ const {
displayTotalBalance,
displayOpeningBalance,
displayClosingBalance,
updatePageOpenTime,
setReconciliationStatements,
getDisplayDate,
getDisplayTime,
@@ -452,6 +457,7 @@ const loading = ref<boolean>(false);
const loadingError = ref<unknown | null>(null);
const queryDateRangeType = ref<number>(DateRange.ThisMonth.type);
const showAccountBalanceTrendsCharts = ref<boolean>(false);
const updatingLastReconciledTime = ref<boolean>(false);
const transactionToDelete = ref<TransactionReconciliationStatementResponseItemWithInfo | null>(null);
const newClosingBalance = ref<number>(0);
const showCustomDateRangeSheet = ref<boolean>(false);
@@ -465,7 +471,11 @@ const virtualDataItems = ref<ReconciliationStatementVirtualListData>({
const textDirection = computed<TextDirection>(() => getCurrentLanguageTextDirection());
const validQuery = computed(() => currentAccount.value && currentAccount.value.type === AccountType.SingleAccount.type);
const allAvailableDateRanges = computed(() => getAllDateRanges(DateRangeScene.Normal, true, !!accountsStore.getAccountStatementDate(accountId.value)));
const allAvailableDateRanges = computed(() => getAllDateRanges(DateRangeScene.Normal, {
includeCustom: true,
includeBillingCycle: !!accountsStore.getAccountStatementDate(accountId.value),
includeLastReconciledTimeRange: !!currentAccountLastReconciledTime.value
}));
const allReconciliationStatementVirtualListItems = computed<ReconciliationStatementVirtualListItem[]>(() => {
const ret: ReconciliationStatementVirtualListItem[] = [];
@@ -511,6 +521,7 @@ function init(): void {
const query = props.f7route.query;
const defaultDateRange = getDateRangeByDateType(queryDateRangeType.value, firstDayOfWeek.value, fiscalYearStart.value);
updatePageOpenTime();
finishQuery.value = false;
loading.value = false;
accountId.value = query['accountId'] || '';
@@ -537,6 +548,8 @@ function changeDateFilter(dateRangeType: number): void {
if (DateRange.isBillingCycle(dateRangeType)) {
dateRange = getDateRangeByBillingCycleDateType(dateRangeType, firstDayOfWeek.value, fiscalYearStart.value, accountsStore.getAccountStatementDate(accountId.value));
} else if (DateRange.isLastReconciledTimeRange(dateRangeType)) {
dateRange = getDateRangeByLastReconciledTimeRangeDateType(dateRangeType, currentAccountLastReconciledTime.value);
} else {
dateRange = getDateRangeByDateType(dateRangeType, firstDayOfWeek.value, fiscalYearStart.value);
}
@@ -654,6 +667,28 @@ function updateClosingBalance(balance?: number): void {
props.f7router.navigate(`/transaction/add?${params.join('&')}`);
}
function updateLastReconciledTime(): void {
if (!newLastReconciledTime.value) {
return;
}
updatingLastReconciledTime.value = true;
showLoading(() => updatingLastReconciledTime.value);
accountsStore.updateAccountLastReconciledTime(accountId.value, newLastReconciledTime.value).then(() => {
updatingLastReconciledTime.value = false;
hideLoading();
showToast('Last reconciled time have been updated');
}).catch(error => {
updatingLastReconciledTime.value = false;
hideLoading();
if (!error.processed) {
showToast(error.message || error);
}
});
}
function removeTransaction(transaction: TransactionReconciliationStatementResponseItemWithInfo | null, confirm: boolean): void {
if (!transaction) {
showAlert('An error occurred');
+4 -1
View File
@@ -653,6 +653,7 @@ import {
getDateTypeByBillingCycleDateRange,
getDateRangeByDateType,
getDateRangeByBillingCycleDateType,
getDateRangeByLastReconciledTimeRangeDateType,
getFullMonthDateRange,
getValidMonthDayOrCurrentDayShortDate
} from '@/lib/datetime.ts';
@@ -931,7 +932,7 @@ function init(): void {
let dateRange: TimeRangeAndDateType | null = getDateRangeByDateType(initQuery['dateType'] ? parseInt(initQuery['dateType']) : undefined, firstDayOfWeek.value, fiscalYearStart.value);
if (!dateRange && initQuery['dateType'] && initQuery['maxTime'] && initQuery['minTime'] &&
(DateRange.isBillingCycle(parseInt(initQuery['dateType'])) || initQuery['dateType'] === DateRange.Custom.type.toString()) &&
(DateRange.isBillingCycle(parseInt(initQuery['dateType'])) || DateRange.isLastReconciledTimeRange(parseInt(initQuery['dateType'])) || initQuery['dateType'] === DateRange.Custom.type.toString()) &&
parseInt(initQuery['maxTime']) > 0 && parseInt(initQuery['minTime']) > 0) {
dateRange = {
dateType: parseInt(initQuery['dateType']),
@@ -1087,6 +1088,8 @@ function changeDateFilter(dateType: number): void {
if (DateRange.isBillingCycle(dateType)) {
dateRange = getDateRangeByBillingCycleDateType(dateType, firstDayOfWeek.value, fiscalYearStart.value, accountsStore.getAccountStatementDate(query.value.accountIds));
} else if (DateRange.isLastReconciledTimeRange(dateType)) {
dateRange = getDateRangeByLastReconciledTimeRangeDateType(dateType, allAccountsMap.value[query.value.accountIds]?.lastReconciledTime);
} else {
dateRange = getDateRangeByDateType(dateType, firstDayOfWeek.value, fiscalYearStart.value);
}