mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-18 16:54:25 +08:00
add default categories backend
This commit is contained in:
@@ -189,6 +189,7 @@ func startWebServer(c *cli.Context) error {
|
|||||||
apiV1Route.GET("/transaction/categories/list.json", bindApi(api.TransactionCategories.CategoryListHandler))
|
apiV1Route.GET("/transaction/categories/list.json", bindApi(api.TransactionCategories.CategoryListHandler))
|
||||||
apiV1Route.GET("/transaction/categories/get.json", bindApi(api.TransactionCategories.CategoryGetHandler))
|
apiV1Route.GET("/transaction/categories/get.json", bindApi(api.TransactionCategories.CategoryGetHandler))
|
||||||
apiV1Route.POST("/transaction/categories/add.json", bindApi(api.TransactionCategories.CategoryCreateHandler))
|
apiV1Route.POST("/transaction/categories/add.json", bindApi(api.TransactionCategories.CategoryCreateHandler))
|
||||||
|
apiV1Route.POST("/transaction/categories/add_batch.json", bindApi(api.TransactionCategories.CategoryCreateBatchHandler))
|
||||||
apiV1Route.POST("/transaction/categories/modify.json", bindApi(api.TransactionCategories.CategoryModifyHandler))
|
apiV1Route.POST("/transaction/categories/modify.json", bindApi(api.TransactionCategories.CategoryModifyHandler))
|
||||||
apiV1Route.POST("/transaction/categories/hide.json", bindApi(api.TransactionCategories.CategoryHideHandler))
|
apiV1Route.POST("/transaction/categories/hide.json", bindApi(api.TransactionCategories.CategoryHideHandler))
|
||||||
apiV1Route.POST("/transaction/categories/move.json", bindApi(api.TransactionCategories.CategoryMoveHandler))
|
apiV1Route.POST("/transaction/categories/move.json", bindApi(api.TransactionCategories.CategoryMoveHandler))
|
||||||
|
|||||||
@@ -173,6 +173,112 @@ func (a *TransactionCategoriesApi) CategoryCreateHandler(c *core.Context) (inter
|
|||||||
return categoryResp, nil
|
return categoryResp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *TransactionCategoriesApi) CategoryCreateBatchHandler(c *core.Context) (interface{}, *errs.Error) {
|
||||||
|
var categoryCreateBatchReq models.TransactionCategoryCreateBatchRequest
|
||||||
|
err := c.ShouldBindJSON(&categoryCreateBatchReq)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.WarnfWithRequestId(c, "[transaction_categories.CategoryCreateBatchHandler] parse request failed, because %s", err.Error())
|
||||||
|
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
uid := c.GetCurrentUid()
|
||||||
|
|
||||||
|
categoryTypeMaxOrderMap := make(map[models.TransactionCategoryType]int)
|
||||||
|
categoriesMap := make(map[*models.TransactionCategory][]*models.TransactionCategory)
|
||||||
|
categoriesMap[nil] = make([]*models.TransactionCategory, len(categoryCreateBatchReq.Categories))
|
||||||
|
totalCount := 0
|
||||||
|
|
||||||
|
for i := 0; i < len(categoryCreateBatchReq.Categories); i++ {
|
||||||
|
categoryCreateReq := categoryCreateBatchReq.Categories[i]
|
||||||
|
var maxOrderId, exists = categoryTypeMaxOrderMap[categoryCreateReq.Type]
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
maxOrderId, err = a.categories.GetMaxDisplayOrder(uid, categoryCreateReq.Type)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorfWithRequestId(c, "[transaction_categories.CategoryCreateBatchHandler] failed to get max display order for user \"uid:%d\", because %s", uid, err.Error())
|
||||||
|
return nil, errs.ErrOperationFailed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
category := a.createNewCategory(uid, &models.TransactionCategoryCreateRequest{
|
||||||
|
Name: categoryCreateReq.Name,
|
||||||
|
Type: categoryCreateReq.Type,
|
||||||
|
Icon: categoryCreateReq.Icon,
|
||||||
|
Color: categoryCreateReq.Color,
|
||||||
|
}, maxOrderId+1)
|
||||||
|
|
||||||
|
categoriesMap[category] = make([]*models.TransactionCategory, len(categoryCreateReq.SubCategories))
|
||||||
|
|
||||||
|
for j := 0; j < len(categoryCreateReq.SubCategories); j++ {
|
||||||
|
subCategory := a.createNewCategory(uid, categoryCreateReq.SubCategories[j], j+1)
|
||||||
|
categoriesMap[category][j] = subCategory
|
||||||
|
totalCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
categoriesMap[nil][i] = category
|
||||||
|
categoryTypeMaxOrderMap[categoryCreateReq.Type] = maxOrderId+1
|
||||||
|
totalCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
categories, err := a.categories.CreateCategories(uid, totalCount, categoriesMap)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorfWithRequestId(c, "[transaction_categories.CategoryCreateBatchHandler] failed to create categories for user \"uid:%d\", because %s", uid, err.Error())
|
||||||
|
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.InfofWithRequestId(c, "[transaction_categories.CategoryCreateBatchHandler] user \"uid:%d\" has created categoroies successfully", uid)
|
||||||
|
|
||||||
|
categoryResps := make([]*models.TransactionCategoryInfoResponse, len(categories))
|
||||||
|
categoryRespMap := make(map[int64]*models.TransactionCategoryInfoResponse)
|
||||||
|
|
||||||
|
for i := 0; i < len(categories); i++ {
|
||||||
|
categoryResps[i] = categories[i].ToTransactionCategoryInfoResponse()
|
||||||
|
categoryRespMap[categoryResps[i].Id] = categoryResps[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(categoryResps); i++ {
|
||||||
|
categoryResp := categoryResps[i]
|
||||||
|
|
||||||
|
if categoryResp.ParentId <= models.TRANSACTION_PARENT_ID_LEVEL_ONE {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
parentCategory, parentExists := categoryRespMap[categoryResp.ParentId]
|
||||||
|
|
||||||
|
if !parentExists || parentCategory == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
parentCategory.SubCategories = append(parentCategory.SubCategories, categoryResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
finalCategoryResps := make(models.TransactionCategoryInfoResponseSlice, 0)
|
||||||
|
|
||||||
|
for i := 0; i < len(categoryResps); i++ {
|
||||||
|
if categoryResps[i].ParentId == models.TRANSACTION_PARENT_ID_LEVEL_ONE {
|
||||||
|
sort.Sort(categoryResps[i].SubCategories)
|
||||||
|
finalCategoryResps = append(finalCategoryResps, categoryResps[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(finalCategoryResps)
|
||||||
|
|
||||||
|
typeCategoryMapResponse := make(map[models.TransactionCategoryType]models.TransactionCategoryInfoResponseSlice)
|
||||||
|
|
||||||
|
for i := 0; i < len(finalCategoryResps); i++ {
|
||||||
|
category := finalCategoryResps[i]
|
||||||
|
categoryList, _ := typeCategoryMapResponse[category.Type]
|
||||||
|
|
||||||
|
categoryList = append(categoryList, category)
|
||||||
|
typeCategoryMapResponse[category.Type] = categoryList
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeCategoryMapResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *TransactionCategoriesApi) CategoryModifyHandler(c *core.Context) (interface{}, *errs.Error) {
|
func (a *TransactionCategoriesApi) CategoryModifyHandler(c *core.Context) (interface{}, *errs.Error) {
|
||||||
var categoryModifyReq models.TransactionCategoryModifyRequest
|
var categoryModifyReq models.TransactionCategoryModifyRequest
|
||||||
err := c.ShouldBindJSON(&categoryModifyReq)
|
err := c.ShouldBindJSON(&categoryModifyReq)
|
||||||
|
|||||||
@@ -37,6 +37,19 @@ type TransactionCategoryCreateRequest struct {
|
|||||||
Comment string `json:"comment" binding:"max=255"`
|
Comment string `json:"comment" binding:"max=255"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TransactionCategoryCreateBatchRequest struct {
|
||||||
|
Categories []*TransactionCategoryCreateWithSubCategories `json:"categories" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransactionCategoryCreateWithSubCategories struct {
|
||||||
|
Name string `json:"name" binding:"required,notBlank,max=32"`
|
||||||
|
Type TransactionCategoryType `json:"type" binding:"required"`
|
||||||
|
Icon int64 `json:"icon,string" binding:"min=1"`
|
||||||
|
Color string `json:"color" binding:"required,len=6,validHexRGBColor"`
|
||||||
|
Comment string `json:"comment" binding:"max=255"`
|
||||||
|
SubCategories []*TransactionCategoryCreateRequest `json:"subCategories" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
type TransactionCategoryListRequest struct {
|
type TransactionCategoryListRequest struct {
|
||||||
Type TransactionCategoryType `form:"type" binding:"min=0"`
|
Type TransactionCategoryType `form:"type" binding:"min=0"`
|
||||||
ParentId int64 `form:"parent_id,string,default=-1" binding:"min=-1"`
|
ParentId int64 `form:"parent_id,string,default=-1" binding:"min=-1"`
|
||||||
|
|||||||
@@ -150,6 +150,59 @@ func (s *TransactionCategoryService) CreateCategory(category *models.Transaction
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TransactionCategoryService) CreateCategories(uid int64, totalCount int, categories map[*models.TransactionCategory][]*models.TransactionCategory) ([]*models.TransactionCategory, error) {
|
||||||
|
if uid <= 0 {
|
||||||
|
return nil, errs.ErrUserIdInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
var allCategories []*models.TransactionCategory
|
||||||
|
primaryCategories := categories[nil]
|
||||||
|
|
||||||
|
for i := 0; i < len(primaryCategories); i++ {
|
||||||
|
primaryCategory := primaryCategories[i]
|
||||||
|
primaryCategory.CategoryId = s.GenerateUuid(uuid.UUID_TYPE_CATEGORY)
|
||||||
|
|
||||||
|
primaryCategory.Deleted = false
|
||||||
|
primaryCategory.CreatedUnixTime = time.Now().Unix()
|
||||||
|
primaryCategory.UpdatedUnixTime = time.Now().Unix()
|
||||||
|
|
||||||
|
allCategories = append(allCategories, primaryCategory)
|
||||||
|
|
||||||
|
secondaryCategories := categories[primaryCategory]
|
||||||
|
|
||||||
|
for j := 0; j < len(secondaryCategories); j++ {
|
||||||
|
secondaryCategory := secondaryCategories[j]
|
||||||
|
secondaryCategory.CategoryId = s.GenerateUuid(uuid.UUID_TYPE_CATEGORY)
|
||||||
|
secondaryCategory.ParentCategoryId = primaryCategory.CategoryId
|
||||||
|
|
||||||
|
secondaryCategory.Deleted = false
|
||||||
|
secondaryCategory.CreatedUnixTime = time.Now().Unix()
|
||||||
|
secondaryCategory.UpdatedUnixTime = time.Now().Unix()
|
||||||
|
|
||||||
|
allCategories = append(allCategories, secondaryCategory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.UserDataDB(uid).DoTransaction(func(sess *xorm.Session) error {
|
||||||
|
for i := 0; i < len(allCategories); i++ {
|
||||||
|
category := allCategories[i]
|
||||||
|
_, err := sess.Insert(category)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return allCategories, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TransactionCategoryService) ModifyCategory(category *models.TransactionCategory) error {
|
func (s *TransactionCategoryService) ModifyCategory(category *models.TransactionCategory) error {
|
||||||
if category.Uid <= 0 {
|
if category.Uid <= 0 {
|
||||||
return errs.ErrUserIdInvalid
|
return errs.ErrUserIdInvalid
|
||||||
|
|||||||
@@ -228,6 +228,11 @@ export default {
|
|||||||
comment
|
comment
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
addTransactionCategoryBatch: ({ categories }) => {
|
||||||
|
return axios.post('v1/transaction/categories/add_batch.json', {
|
||||||
|
categories
|
||||||
|
});
|
||||||
|
},
|
||||||
modifyTransactionCategory: ({ id, name, icon, color, comment, hidden }) => {
|
modifyTransactionCategory: ({ id, name, icon, color, comment, hidden }) => {
|
||||||
return axios.post('v1/transaction/categories/modify.json', {
|
return axios.post('v1/transaction/categories/modify.json', {
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -516,6 +516,7 @@ export default {
|
|||||||
'Unable to add category': 'Unable to add category',
|
'Unable to add category': 'Unable to add category',
|
||||||
'Unable to save category': 'Unable to save category',
|
'Unable to save category': 'Unable to save category',
|
||||||
'You have added a new category': 'You have added a new category',
|
'You have added a new category': 'You have added a new category',
|
||||||
|
'You have added default categories': 'You have added default categories',
|
||||||
'You have saved this category': 'You have saved this category',
|
'You have saved this category': 'You have saved this category',
|
||||||
'Are you sure you want to logout from this session?': 'Are you sure you want to logout from this session?',
|
'Are you sure you want to logout from this session?': 'Are you sure you want to logout from this session?',
|
||||||
'Unable to logout from this session': 'Unable to logout from this session',
|
'Unable to logout from this session': 'Unable to logout from this session',
|
||||||
|
|||||||
@@ -516,6 +516,7 @@ export default {
|
|||||||
'Unable to add category': '无法添加分类',
|
'Unable to add category': '无法添加分类',
|
||||||
'Unable to save category': '无法保存分类',
|
'Unable to save category': '无法保存分类',
|
||||||
'You have added a new category': '您已经添加新分类',
|
'You have added a new category': '您已经添加新分类',
|
||||||
|
'You have added default categories': '您已经添加默认分类',
|
||||||
'You have saved this category': '您已经保存该分类',
|
'You have saved this category': '您已经保存该分类',
|
||||||
'Are you sure you want to logout from this session?': '您确定要退出该会话?',
|
'Are you sure you want to logout from this session?': '您确定要退出该会话?',
|
||||||
'Unable to logout from this session': '无法退出该会话',
|
'Unable to logout from this session': '无法退出该会话',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<f7-nav-left :back-link="$t('Back')"></f7-nav-left>
|
<f7-nav-left :back-link="$t('Back')"></f7-nav-left>
|
||||||
<f7-nav-title :title="$t('Default Categories')"></f7-nav-title>
|
<f7-nav-title :title="$t('Default Categories')"></f7-nav-title>
|
||||||
<f7-nav-right>
|
<f7-nav-right>
|
||||||
<f7-link :text="$t('Save')" :class="{ 'disabled': saving }" @click="save"></f7-link>
|
<f7-link :text="$t('Save')" :class="{ 'disabled': submitting }" @click="save"></f7-link>
|
||||||
</f7-nav-right>
|
</f7-nav-right>
|
||||||
</f7-navbar>
|
</f7-navbar>
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
categoryType: '',
|
categoryType: '',
|
||||||
allCategories: [],
|
allCategories: [],
|
||||||
saving: false
|
submitting: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@@ -94,7 +94,67 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
save() {
|
save() {
|
||||||
|
const self = this;
|
||||||
|
const router = self.$f7router;
|
||||||
|
|
||||||
|
self.submitting = true;
|
||||||
|
self.$showLoading(() => self.submitting);
|
||||||
|
|
||||||
|
const categories = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < self.allCategories.length; i++) {
|
||||||
|
const categoryInfo = self.allCategories[i];
|
||||||
|
|
||||||
|
for (let j = 0; j < categoryInfo.categories.length; j++) {
|
||||||
|
const category = categoryInfo.categories[j];
|
||||||
|
const submitCategory = {
|
||||||
|
name: self.$t('category.' + category.name),
|
||||||
|
type: parseInt(categoryInfo.type),
|
||||||
|
icon: category.categoryIconId,
|
||||||
|
color: category.color,
|
||||||
|
subCategories: []
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let k = 0; k < category.subCategories.length; k++) {
|
||||||
|
const subCategory = category.subCategories[k];
|
||||||
|
submitCategory.subCategories.push({
|
||||||
|
name: self.$t('category.' + subCategory.name),
|
||||||
|
type: parseInt(categoryInfo.type),
|
||||||
|
icon: subCategory.categoryIconId,
|
||||||
|
color: subCategory.color
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
categories.push(submitCategory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.$services.addTransactionCategoryBatch({
|
||||||
|
categories: categories
|
||||||
|
}).then(response => {
|
||||||
|
self.submitting = false;
|
||||||
|
self.$hideLoading();
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
|
if (!data || !data.success || !data.result) {
|
||||||
|
self.$toast('Unable to add category');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.$toast('You have added default categories');
|
||||||
|
router.back();
|
||||||
|
}).catch(error => {
|
||||||
|
self.$logger.error('failed to save default categories', error);
|
||||||
|
|
||||||
|
self.submitting = false;
|
||||||
|
self.$hideLoading();
|
||||||
|
|
||||||
|
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||||
|
self.$toast({ error: error.response.data });
|
||||||
|
} else if (!error.processed) {
|
||||||
|
self.$toast('Unable to add category');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
|
|||||||
Reference in New Issue
Block a user