diff --git a/cmd/webserver.go b/cmd/webserver.go
index 92070dd3..fbbd153d 100644
--- a/cmd/webserver.go
+++ b/cmd/webserver.go
@@ -161,6 +161,7 @@ func startWebServer(c *cli.Context) error {
// Accounts
apiV1Route.GET("/accounts/list.json", bindApi(api.Accounts.AccountListHandler))
apiV1Route.POST("/accounts/add.json", bindApi(api.Accounts.AccountCreateHandler))
+ apiV1Route.POST("/accounts/delete.json", bindApi(api.Accounts.AccountDeleteHandler))
}
}
diff --git a/pkg/api/accounts.go b/pkg/api/accounts.go
index d1210258..8bbb398a 100644
--- a/pkg/api/accounts.go
+++ b/pkg/api/accounts.go
@@ -124,6 +124,27 @@ func (a *AccountsApi) AccountCreateHandler(c *core.Context) (interface{}, *errs.
return accountInfoResp, nil
}
+func (a *AccountsApi) AccountDeleteHandler(c *core.Context) (interface{}, *errs.Error) {
+ var accountDeleteReq models.AccountDeleteRequest
+ err := c.ShouldBindJSON(&accountDeleteReq)
+
+ if err != nil {
+ log.WarnfWithRequestId(c, "[accounts.AccountDeleteHandler] parse request failed, because %s", err.Error())
+ return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
+ }
+
+ uid := c.GetCurrentUid()
+ err = a.accounts.DeleteAccounts(uid, []int64{accountDeleteReq.Id})
+
+ if err != nil {
+ log.ErrorfWithRequestId(c, "[accounts.AccountDeleteHandler] failed to delete account \"id:%s\" for user \"uid:%d\", because %s", accountDeleteReq.Id, uid, err.Error())
+ return nil, errs.Or(err, errs.ErrOperationFailed)
+ }
+
+ log.InfofWithRequestId(c, "[accounts.AccountDeleteHandler] user \"uid:%d\" has deleted account \"id:%s\"", uid, accountDeleteReq.Id)
+ return true, nil
+}
+
func (a *AccountsApi) createNewAccount(uid int64, accountCreateReq *models.AccountCreateRequest, order int) *models.Account {
return &models.Account{
Uid: uid,
diff --git a/pkg/models/account.go b/pkg/models/account.go
index e24f48f9..16271a46 100644
--- a/pkg/models/account.go
+++ b/pkg/models/account.go
@@ -51,6 +51,10 @@ type AccountCreateRequest struct {
SubAccounts []*AccountCreateRequest `json:"subAccounts" binding:"omitempty"`
}
+type AccountDeleteRequest struct {
+ Id int64 `json:"id,string" binding:"required,min=1"`
+}
+
type AccountInfoResponse struct {
Id int64 `json:"id,string"`
Name string `json:"name"`
diff --git a/pkg/services/accounts.go b/pkg/services/accounts.go
index 44fc0b7e..aace7b9d 100644
--- a/pkg/services/accounts.go
+++ b/pkg/services/accounts.go
@@ -121,3 +121,27 @@ func (s *AccountService) CreateAccounts(mainAccount *models.Account, childrenAcc
return nil
})
}
+
+func (s *AccountService) DeleteAccounts(uid int64, ids []int64) error {
+ if uid <= 0 {
+ return errs.ErrUserIdInvalid
+ }
+
+ now := time.Now().Unix()
+
+ updateModel := &models.Account{
+ Deleted: true,
+ UpdatedUnixTime: now,
+ DeletedUnixTime: now,
+ }
+
+ return s.UserDataDB(uid).DoTransaction(func(sess *xorm.Session) error {
+ deletedRows, err := sess.Cols("deleted", "deleted_unix_time").In("account_id", ids).Where("uid=? AND deleted=?", uid, false).Update(updateModel)
+
+ if deletedRows < 1 {
+ return errs.ErrAccountNotFound
+ }
+
+ return err
+ })
+}
diff --git a/src/lib/services.js b/src/lib/services.js
index 0834e2e0..169e3418 100644
--- a/src/lib/services.js
+++ b/src/lib/services.js
@@ -174,4 +174,9 @@ export default {
subAccounts
});
},
+ deleteAccount: ({ id }) => {
+ return axios.post('v1/accounts/delete.json', {
+ id
+ });
+ },
};
diff --git a/src/locales/en.js b/src/locales/en.js
index 026654ac..c0d6dd3f 100644
--- a/src/locales/en.js
+++ b/src/locales/en.js
@@ -212,6 +212,7 @@ export default {
'account cannot have sub accounts': 'Account cannot have sub accounts',
},
'parameter': {
+ 'id': 'ID',
'username': 'Username',
'password': 'Password',
'passcode': 'Passcode',
@@ -322,6 +323,8 @@ export default {
'Account currency cannot be empty': 'Account currency cannot be empty',
'You have added a new account': 'You have added a new account',
'Unable to add account': 'Unable to add account',
+ 'Are you sure you want to delete this account?': 'Are you sure you want to delete this account?',
+ 'Unable to delete this account': 'Unable to delete this account',
'User Profile': 'User Profile',
'Language': 'Language',
'Enable Thousands Separator': 'Enable Thousands Separator',
diff --git a/src/locales/zh_Hans.js b/src/locales/zh_Hans.js
index d337d4f2..460d31bc 100644
--- a/src/locales/zh_Hans.js
+++ b/src/locales/zh_Hans.js
@@ -212,6 +212,7 @@ export default {
'account cannot have sub accounts': '账户不能包含子账户',
},
'parameter': {
+ 'id': 'ID',
'username': '用户名',
'password': '密码',
'passcode': '验证码',
@@ -322,6 +323,8 @@ export default {
'Account currency cannot be empty': '账户货币不能为空',
'You have added a new account': '您已经添加新账户',
'Unable to add account': '无法添加账户',
+ 'Are you sure you want to delete this account?': '您确定要删除该账户吗?',
+ 'Unable to delete this account': '无法删除该账户',
'User Profile': '用户信息',
'Language': '语言',
'Enable Thousands Separator': '启用千位分隔符',
diff --git a/src/views/mobile/accounts/AccountList.vue b/src/views/mobile/accounts/AccountList.vue
index 0a04aeb6..773820b9 100644
--- a/src/views/mobile/accounts/AccountList.vue
+++ b/src/views/mobile/accounts/AccountList.vue
@@ -41,7 +41,8 @@
{{ $t(accountCategory.name) }}
-
@@ -140,8 +141,48 @@ export default {
edit() {
},
- remove() {
+ remove(account) {
+ const self = this;
+ const app = self.$f7;
+ const $$ = app.$;
+ self.$confirm('Are you sure you want to delete this account?', () => {
+ self.$showLoading();
+
+ self.$services.deleteAccount({
+ id: account.id
+ }).then(response => {
+ self.$hideLoading();
+ const data = response.data;
+
+ if (!data || !data.success || !data.result) {
+ self.$alert('Unable to delete this account');
+ return;
+ }
+
+ app.swipeout.delete($$(`#${self.$options.filters.accountDomId(account)}`), () => {
+ const accountList = self.accounts[account.category];
+ for (let i = 0; i < accountList.length; i++) {
+ if (accountList[i].id === account.id) {
+ accountList.splice(i, 1);
+ }
+ }
+ });
+ }).catch(error => {
+ self.$hideLoading();
+
+ if (error.response && error.response.data && error.response.data.errorMessage) {
+ self.$alert({error: error.response.data});
+ } else if (!error.processed) {
+ self.$alert('Unable to delete this account');
+ }
+ });
+ });
+ }
+ },
+ filters: {
+ accountDomId(account) {
+ return 'account_' + account.id;
}
}
};