mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-15 07:27:33 +08:00
support displaying transactions since the last reconciled time
This commit is contained in:
+95
-8
@@ -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
@@ -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")
|
||||
)
|
||||
|
||||
@@ -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")
|
||||
)
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user