diff --git a/cmd/webserver.go b/cmd/webserver.go index 7b5feffc..0823f209 100644 --- a/cmd/webserver.go +++ b/cmd/webserver.go @@ -324,7 +324,6 @@ func startWebServer(c *cli.Context) error { apiV1Route.GET("/transaction/templates/list.json", bindApi(api.TransactionTemplates.TemplateListHandler)) apiV1Route.GET("/transaction/templates/get.json", bindApi(api.TransactionTemplates.TemplateGetHandler)) apiV1Route.POST("/transaction/templates/add.json", bindApi(api.TransactionTemplates.TemplateCreateHandler)) - apiV1Route.POST("/transaction/templates/modify_name.json", bindApi(api.TransactionTemplates.TemplateModifyNameHandler)) apiV1Route.POST("/transaction/templates/modify.json", bindApi(api.TransactionTemplates.TemplateModifyHandler)) apiV1Route.POST("/transaction/templates/hide.json", bindApi(api.TransactionTemplates.TemplateHideHandler)) apiV1Route.POST("/transaction/templates/move.json", bindApi(api.TransactionTemplates.TemplateMoveHandler)) diff --git a/pkg/api/transaction_templates.go b/pkg/api/transaction_templates.go index d6810496..1869f45b 100644 --- a/pkg/api/transaction_templates.go +++ b/pkg/api/transaction_templates.go @@ -36,6 +36,11 @@ func (a *TransactionTemplatesApi) TemplateListHandler(c *core.Context) (any, *er return nil, errs.NewIncompleteOrIncorrectSubmissionError(err) } + if templateListReq.TemplateType < models.TRANSACTION_TEMPLATE_TYPE_NORMAL || templateListReq.TemplateType > models.TRANSACTION_TEMPLATE_TYPE_NORMAL { + log.WarnfWithRequestId(c, "[transaction_templates.TemplateListHandler] template type invalid, type is %d", templateListReq.TemplateType) + return nil, errs.ErrTransactionTemplateTypeInvalid + } + uid := c.GetCurrentUid() templates, err := a.templates.GetAllTemplatesByUid(c, uid, templateListReq.TemplateType) @@ -90,6 +95,16 @@ func (a *TransactionTemplatesApi) TemplateCreateHandler(c *core.Context) (any, * return nil, errs.NewIncompleteOrIncorrectSubmissionError(err) } + if templateCreateReq.TemplateType < models.TRANSACTION_TEMPLATE_TYPE_NORMAL || templateCreateReq.TemplateType > models.TRANSACTION_TEMPLATE_TYPE_NORMAL { + log.WarnfWithRequestId(c, "[transaction_templates.TemplateCreateHandler] template type invalid, type is %d", templateCreateReq.TemplateType) + return nil, errs.ErrTransactionTemplateTypeInvalid + } + + if templateCreateReq.Type <= models.TRANSACTION_TYPE_MODIFY_BALANCE || templateCreateReq.Type > models.TRANSACTION_TYPE_TRANSFER { + log.WarnfWithRequestId(c, "[transaction_templates.TemplateCreateHandler] transaction type invalid, type is %d", templateCreateReq.Type) + return nil, errs.ErrTransactionTypeInvalid + } + uid := c.GetCurrentUid() maxOrderId, err := a.templates.GetMaxDisplayOrder(c, uid, templateCreateReq.TemplateType) @@ -139,50 +154,6 @@ func (a *TransactionTemplatesApi) TemplateCreateHandler(c *core.Context) (any, * return templateResp, nil } -// TemplateModifyNameHandler updates the name of an existed transaction template by request parameters for current user -func (a *TransactionTemplatesApi) TemplateModifyNameHandler(c *core.Context) (any, *errs.Error) { - var templateModifyReq models.TransactionTemplateModifyNameRequest - err := c.ShouldBindJSON(&templateModifyReq) - - if err != nil { - log.WarnfWithRequestId(c, "[transaction_templates.TemplateModifyNameHandler] parse request failed, because %s", err.Error()) - return nil, errs.NewIncompleteOrIncorrectSubmissionError(err) - } - - uid := c.GetCurrentUid() - template, err := a.templates.GetTemplateByTemplateId(c, uid, templateModifyReq.Id) - - if err != nil { - log.ErrorfWithRequestId(c, "[transaction_templates.TemplateModifyNameHandler] failed to get template \"id:%d\" for user \"uid:%d\", because %s", templateModifyReq.Id, uid, err.Error()) - return nil, errs.Or(err, errs.ErrOperationFailed) - } - - if templateModifyReq.Name == template.Name { - return nil, errs.ErrNothingWillBeUpdated - } - - newTemplate := &models.TransactionTemplate{ - TemplateId: template.TemplateId, - Uid: template.Uid, - Name: templateModifyReq.Name, - } - - err = a.templates.ModifyTemplateName(c, newTemplate) - - if err != nil { - log.ErrorfWithRequestId(c, "[transaction_templates.TemplateModifyNameHandler] failed to update template \"id:%d\" for user \"uid:%d\", because %s", templateModifyReq.Id, uid, err.Error()) - return nil, errs.Or(err, errs.ErrOperationFailed) - } - - log.InfofWithRequestId(c, "[transaction_templates.TemplateModifyNameHandler] user \"uid:%d\" has updated template \"id:%d\" successfully", uid, templateModifyReq.Id) - - serverUtcOffset := utils.GetServerTimezoneOffsetMinutes() - template.Name = newTemplate.Name - templateResp := template.ToTransactionTemplateInfoResponse(serverUtcOffset) - - return templateResp, nil -} - // TemplateModifyHandler saves an existed transaction template by request parameters for current user func (a *TransactionTemplatesApi) TemplateModifyHandler(c *core.Context) (any, *errs.Error) { var templateModifyReq models.TransactionTemplateModifyRequest @@ -193,6 +164,11 @@ func (a *TransactionTemplatesApi) TemplateModifyHandler(c *core.Context) (any, * return nil, errs.NewIncompleteOrIncorrectSubmissionError(err) } + if templateModifyReq.Type <= models.TRANSACTION_TYPE_MODIFY_BALANCE || templateModifyReq.Type > models.TRANSACTION_TYPE_TRANSFER { + log.WarnfWithRequestId(c, "[transaction_templates.TemplateModifyHandler] transaction type invalid, type is %d", templateModifyReq.Type) + return nil, errs.ErrTransactionTypeInvalid + } + uid := c.GetCurrentUid() template, err := a.templates.GetTemplateByTemplateId(c, uid, templateModifyReq.Id) @@ -204,6 +180,7 @@ func (a *TransactionTemplatesApi) TemplateModifyHandler(c *core.Context) (any, * newTemplate := &models.TransactionTemplate{ TemplateId: template.TemplateId, Uid: uid, + Name: templateModifyReq.Name, Type: templateModifyReq.Type, CategoryId: templateModifyReq.CategoryId, AccountId: templateModifyReq.SourceAccountId, @@ -215,7 +192,8 @@ func (a *TransactionTemplatesApi) TemplateModifyHandler(c *core.Context) (any, * Comment: templateModifyReq.Comment, } - if newTemplate.Type == template.Type && + if newTemplate.Name == template.Name && + newTemplate.Type == template.Type && newTemplate.CategoryId == template.CategoryId && newTemplate.AccountId == template.AccountId && newTemplate.TagIds == template.TagIds && @@ -237,7 +215,7 @@ func (a *TransactionTemplatesApi) TemplateModifyHandler(c *core.Context) (any, * log.InfofWithRequestId(c, "[transaction_templates.TemplateModifyHandler] user \"uid:%d\" has updated template \"id:%d\" successfully", uid, templateModifyReq.Id) serverUtcOffset := utils.GetServerTimezoneOffsetMinutes() - newTemplate.Name = template.Name + newTemplate.TemplateType = template.TemplateType newTemplate.DisplayOrder = template.DisplayOrder newTemplate.Hidden = template.Hidden templateResp := newTemplate.ToTransactionTemplateInfoResponse(serverUtcOffset) @@ -326,10 +304,18 @@ func (a *TransactionTemplatesApi) TemplateDeleteHandler(c *core.Context) (any, * func (a *TransactionTemplatesApi) createNewTemplateModel(uid int64, templateCreateReq *models.TransactionTemplateCreateRequest, order int32) *models.TransactionTemplate { return &models.TransactionTemplate{ - Uid: uid, - TemplateType: templateCreateReq.TemplateType, - Name: templateCreateReq.Name, - Type: models.TRANSACTION_TYPE_EXPENSE, - DisplayOrder: order, + Uid: uid, + TemplateType: templateCreateReq.TemplateType, + Name: templateCreateReq.Name, + Type: templateCreateReq.Type, + CategoryId: templateCreateReq.CategoryId, + AccountId: templateCreateReq.SourceAccountId, + TagIds: strings.Join(templateCreateReq.TagIds, ","), + Amount: templateCreateReq.SourceAmount, + RelatedAccountId: templateCreateReq.DestinationAccountId, + RelatedAccountAmount: templateCreateReq.DestinationAmount, + HideAmount: templateCreateReq.HideAmount, + Comment: templateCreateReq.Comment, + DisplayOrder: order, } } diff --git a/pkg/errs/transaction_template.go b/pkg/errs/transaction_template.go index 9f150327..cbc2d683 100644 --- a/pkg/errs/transaction_template.go +++ b/pkg/errs/transaction_template.go @@ -4,6 +4,7 @@ import "net/http" // Error codes related to transaction templates var ( - ErrTransactionTemplateIdInvalid = NewNormalError(NormalSubcategoryTemplate, 0, http.StatusBadRequest, "transaction template id is invalid") - ErrTransactionTemplateNotFound = NewNormalError(NormalSubcategoryTemplate, 1, http.StatusBadRequest, "transaction template not found") + ErrTransactionTemplateIdInvalid = NewNormalError(NormalSubcategoryTemplate, 0, http.StatusBadRequest, "transaction template id is invalid") + ErrTransactionTemplateNotFound = NewNormalError(NormalSubcategoryTemplate, 1, http.StatusBadRequest, "transaction template not found") + ErrTransactionTemplateTypeInvalid = NewNormalError(NormalSubcategoryTemplate, 2, http.StatusBadRequest, "transaction template type is invalid") ) diff --git a/pkg/models/transaction_template.go b/pkg/models/transaction_template.go index 7dc90dde..50d66bd1 100644 --- a/pkg/models/transaction_template.go +++ b/pkg/models/transaction_template.go @@ -39,7 +39,7 @@ type TransactionTemplate struct { // TransactionTemplateListRequest represents all parameters of transaction template list request type TransactionTemplateListRequest struct { - TemplateType TransactionTemplateType `form:"templateType" binding:"required,min=1,max=1"` + TemplateType TransactionTemplateType `form:"templateType"` } // TransactionTemplateGetRequest represents all parameters of transaction template getting request @@ -49,9 +49,18 @@ type TransactionTemplateGetRequest struct { // TransactionTemplateCreateRequest represents all parameters of transaction template creation request type TransactionTemplateCreateRequest struct { - TemplateType TransactionTemplateType `json:"templateType" binding:"required,min=1,max=1"` - Name string `json:"name" binding:"required,notBlank,max=32"` - ClientSessionId string `json:"clientSessionId"` + TemplateType TransactionTemplateType `json:"templateType"` + Name string `json:"name" binding:"required,notBlank,max=32"` + Type TransactionType `json:"type" binding:"required"` + CategoryId int64 `json:"categoryId,string" binding:"required,min=1"` + SourceAccountId int64 `json:"sourceAccountId,string" binding:"required,min=1"` + DestinationAccountId int64 `json:"destinationAccountId,string" binding:"min=0"` + SourceAmount int64 `json:"sourceAmount" binding:"min=-99999999999,max=99999999999"` + DestinationAmount int64 `json:"destinationAmount" binding:"min=-99999999999,max=99999999999"` + HideAmount bool `json:"hideAmount"` + TagIds []string `json:"tagIds"` + Comment string `json:"comment" binding:"max=255"` + ClientSessionId string `json:"clientSessionId"` } // TransactionTemplateModifyNameRequest represents all parameters of transaction template name modification request @@ -63,8 +72,9 @@ type TransactionTemplateModifyNameRequest struct { // TransactionTemplateModifyRequest represents all parameters of transaction template modification request type TransactionTemplateModifyRequest struct { Id int64 `json:"id,string" binding:"required,min=1"` + Name string `json:"name" binding:"required,notBlank,max=32"` Type TransactionType `json:"type" binding:"required"` - CategoryId int64 `json:"categoryId,string"` + CategoryId int64 `json:"categoryId,string" binding:"required,min=1"` SourceAccountId int64 `json:"sourceAccountId,string" binding:"required,min=1"` DestinationAccountId int64 `json:"destinationAccountId,string" binding:"min=0"` SourceAmount int64 `json:"sourceAmount" binding:"min=-99999999999,max=99999999999"` diff --git a/pkg/services/transaction_templates.go b/pkg/services/transaction_templates.go index 21de77cb..9b2e8da8 100644 --- a/pkg/services/transaction_templates.go +++ b/pkg/services/transaction_templates.go @@ -125,28 +125,7 @@ func (s *TransactionTemplateService) ModifyTemplate(c *core.Context, template *m template.UpdatedUnixTime = time.Now().Unix() return s.UserDataDB(template.Uid).DoTransaction(c, func(sess *xorm.Session) error { - updatedRows, err := sess.ID(template.TemplateId).Cols("type", "category_id", "account_id", "tag_ids", "amount", "related_account_id", "related_account_amount", "hide_amount", "comment", "updated_unix_time").Where("uid=? AND deleted=?", template.Uid, false).Update(template) - - if err != nil { - return err - } else if updatedRows < 1 { - return errs.ErrTransactionTemplateNotFound - } - - return err - }) -} - -// ModifyTemplateName updates the name of an existed transaction template model to database -func (s *TransactionTemplateService) ModifyTemplateName(c *core.Context, template *models.TransactionTemplate) error { - if template.Uid <= 0 { - return errs.ErrUserIdInvalid - } - - template.UpdatedUnixTime = time.Now().Unix() - - return s.UserDataDB(template.Uid).DoTransaction(c, func(sess *xorm.Session) error { - updatedRows, err := sess.ID(template.TemplateId).Cols("name", "updated_unix_time").Where("uid=? AND deleted=?", template.Uid, false).Update(template) + updatedRows, err := sess.ID(template.TemplateId).Cols("name", "type", "category_id", "account_id", "tag_ids", "amount", "related_account_id", "related_account_amount", "hide_amount", "comment", "updated_unix_time").Where("uid=? AND deleted=?", template.Uid, false).Update(template) if err != nil { return err diff --git a/src/lib/services.js b/src/lib/services.js index b668adec..96186e55 100644 --- a/src/lib/services.js +++ b/src/lib/services.js @@ -523,22 +523,26 @@ export default { getTransactionTemplate: ({ id }) => { return axios.get('v1/transaction/templates/get.json?id=' + id); }, - addTransactionTemplate: ({ templateType, name, clientSessionId }) => { + addTransactionTemplate: ({ templateType, name, type, categoryId, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, comment, clientSessionId }) => { return axios.post('v1/transaction/templates/add.json', { templateType, name, + type, + categoryId, + sourceAccountId, + destinationAccountId, + sourceAmount, + destinationAmount, + hideAmount, + tagIds, + comment, clientSessionId }); }, - modifyTransactionNameTemplate: ({ id, name }) => { - return axios.post('v1/transaction/templates/modify_name.json', { - id, - name - }); - }, - modifyTransactionTemplate: ({ id, type, categoryId, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, comment }) => { + modifyTransactionTemplate: ({ id, name, type, categoryId, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, comment }) => { return axios.post('v1/transaction/templates/modify.json', { id, + name, type, categoryId, sourceAccountId, diff --git a/src/locales/en.js b/src/locales/en.js index 6c2740c2..630d26e0 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -702,6 +702,9 @@ export default { 'transaction tag is in use and cannot be deleted': 'Transaction tag is in use and it cannot be deleted', 'transaction tag index not found': 'Transaction tag index is not found', 'data export not allowed': 'User data export is not allowed', + 'transaction template id is invalid': 'Transaction template ID is invalid', + 'transaction template not found': 'Transaction template is not found', + 'transaction template type is invalid': 'Transaction template type is invalid', 'query items cannot be blank': 'There are no query items', 'query items too much': 'There are too many query items', 'query items have invalid item': 'There is invalid item in query items', @@ -738,6 +741,7 @@ export default { 'month': 'Month', 'page': 'Page Index', 'count': 'Count', + 'templateType': 'Template Type', 'comment': 'Description', }, 'parameterizedError': { @@ -788,7 +792,6 @@ export default { 'Show': 'Show', 'Hide': 'Hide', 'Version': 'Version', - 'Modify Name': 'Modify Name', 'Edit': 'Edit', 'Remove': 'Remove', 'Delete': 'Delete', @@ -1021,6 +1024,7 @@ export default { 'Transactions': 'Transactions', 'Add Transaction': 'Add Transaction', 'Edit Transaction': 'Edit Transaction', + 'Add Transaction Template': 'Add Transaction Template', 'Edit Transaction Template': 'Edit Transaction Template', 'Modify Balance': 'Modify Balance', 'Expense Amount': 'Expense Amount', @@ -1278,6 +1282,7 @@ export default { 'Template list has been updated': 'Template list has been updated', 'Unable to add template': 'Unable to add template', 'Unable to save template': 'Unable to save template', + 'You have added a new template': 'You have added a new template', 'Unable to move template': 'Unable to move template', 'Unable to retrieve template': 'Unable to retrieve template', 'Unable to hide this template': 'Unable to hide this template', diff --git a/src/locales/zh_Hans.js b/src/locales/zh_Hans.js index a31f076a..c82b2532 100644 --- a/src/locales/zh_Hans.js +++ b/src/locales/zh_Hans.js @@ -702,6 +702,9 @@ export default { 'transaction tag is in use and cannot be deleted': '交易标签正在被使用,无法删除', 'transaction tag index not found': '交易标签索引不存在', 'data export not allowed': '不允许用户数据导出', + 'transaction template id is invalid': '交易模板ID无效', + 'transaction template not found': '交易模板不存在', + 'transaction template type is invalid': '交易模板类型无效', 'query items cannot be blank': '请求项目不能为空', 'query items too much': '请求项目过多', 'query items have invalid item': '请求项目中有非法项目', @@ -738,6 +741,7 @@ export default { 'month': '月份', 'page': '页码索引', 'count': '数量', + 'templateType': '模板类型', 'comment': '描述', }, 'parameterizedError': { @@ -788,7 +792,6 @@ export default { 'Show': '显示', 'Hide': '隐藏', 'Version': '版本', - 'Modify Name': '修改名称', 'Edit': '编辑', 'Remove': '移除', 'Delete': '删除', @@ -1021,6 +1024,7 @@ export default { 'Transactions': '交易', 'Add Transaction': '添加交易', 'Edit Transaction': '编辑交易', + 'Add Transaction Template': '添加交易模板', 'Edit Transaction Template': '编辑交易模板', 'Modify Balance': '修改余额', 'Expense Amount': '支出金额', @@ -1278,6 +1282,7 @@ export default { 'Template list has been updated': '模板列表已更新', 'Unable to add template': '无法添加模板', 'Unable to save template': '无法保存模板', + 'You have added a new template': '您已经添加新模板', 'Unable to move template': '无法移动模板', 'Unable to retrieve template': '无法获取模板', 'Unable to hide this template': '无法隐藏该模板', diff --git a/src/stores/transactionTemplate.js b/src/stores/transactionTemplate.js index e2661bf1..e706be42 100644 --- a/src/stores/transactionTemplate.js +++ b/src/stores/transactionTemplate.js @@ -129,13 +129,6 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates', } }, actions: { - generateNewTransactionTemplateModel(templateType) { - return { - id: '', - templateType: templateType, - name: '' - }; - }, updateTransactionTemplateListInvalidState(templateType, invalidState) { this.transactionTemplateListStatesInvalid[templateType] = invalidState; }, @@ -217,59 +210,12 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates', }); }); }, - saveTemplateName({ template }) { - const self = this; - - return new Promise((resolve, reject) => { - let promise = null; - - if (!template.id) { - promise = services.addTransactionTemplate(template); - } else { - promise = services.modifyTransactionNameTemplate(template); - } - - promise.then(response => { - const data = response.data; - - if (!data || !data.success || !data.result) { - if (!template.id) { - reject({ message: 'Unable to add template' }); - } else { - reject({ message: 'Unable to save template' }); - } - return; - } - - if (!template.id) { - addTemplateToTransactionTemplateList(self, template.templateType, data.result); - } else { - updateTemplateInTransactionTemplateList(self, template.templateType, data.result); - } - - resolve(data.result); - }).catch(error => { - logger.error('failed to save template', error); - - if (error.response && error.response.data && error.response.data.errorMessage) { - reject({ error: error.response.data }); - } else if (!error.processed) { - if (!template.id) { - reject({ message: 'Unable to add template' }); - } else { - reject({ message: 'Unable to save template' }); - } - } else { - reject(error); - } - }); - }); - }, - modifyTemplateContent({ template }) { + saveTemplateContent({ template, isEdit, clientSessionId }) { const self = this; const submitTemplate = { - id: template.id, + templateType: template.templateType, + name: template.name, type: template.type, sourceAccountId: template.sourceAccountId, sourceAmount: template.sourceAmount, @@ -280,6 +226,10 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates', comment: template.comment }; + if (clientSessionId) { + submitTemplate.clientSessionId = clientSessionId; + } + if (template.type === transactionConstants.allTransactionTypes.Expense) { submitTemplate.categoryId = template.expenseCategory; } else if (template.type === transactionConstants.allTransactionTypes.Income) { @@ -292,16 +242,36 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates', return Promise.reject('An error occurred'); } + if (isEdit) { + submitTemplate.id = template.id; + } + return new Promise((resolve, reject) => { - services.modifyTransactionTemplate(submitTemplate).then(response => { + let promise = null; + + if (!submitTemplate.id) { + promise = services.addTransactionTemplate(submitTemplate); + } else { + promise = services.modifyTransactionTemplate(submitTemplate); + } + + promise.then(response => { const data = response.data; if (!data || !data.success || !data.result) { - reject({ message: 'Unable to save template' }); + if (!submitTemplate.id) { + reject({ message: 'Unable to add template' }); + } else { + reject({ message: 'Unable to save template' }); + } return; } - updateTemplateInTransactionTemplateList(self, template.templateType, data.result); + if (!submitTemplate.id) { + addTemplateToTransactionTemplateList(self, template.templateType, data.result); + } else { + updateTemplateInTransactionTemplateList(self, template.templateType, data.result); + } resolve(data.result); }).catch(error => { @@ -310,7 +280,11 @@ export const useTransactionTemplatesStore = defineStore('transactionTemplates', if (error.response && error.response.data && error.response.data.errorMessage) { reject({ error: error.response.data }); } else if (!error.processed) { - reject({ message: 'Unable to save template' }); + if (!submitTemplate.id) { + reject({ message: 'Unable to add template' }); + } else { + reject({ message: 'Unable to save template' }); + } } else { reject(error); } diff --git a/src/views/desktop/templates/ListPage.vue b/src/views/desktop/templates/ListPage.vue index 95f194be..70332f2b 100644 --- a/src/views/desktop/templates/ListPage.vue +++ b/src/views/desktop/templates/ListPage.vue @@ -6,12 +6,12 @@
{{ $t('Transaction Templates') }} {{ $t('Add') }} + :disabled="loading || updating" @click="add">{{ $t('Add') }} {{ $t('Save Display Order') }}