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/get.json", bindApi(api.TransactionCategories.CategoryGetHandler))
|
||||
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/hide.json", bindApi(api.TransactionCategories.CategoryHideHandler))
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
var categoryModifyReq models.TransactionCategoryModifyRequest
|
||||
err := c.ShouldBindJSON(&categoryModifyReq)
|
||||
|
||||
@@ -37,6 +37,19 @@ type TransactionCategoryCreateRequest struct {
|
||||
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 TransactionCategoryType `form:"type" binding:"min=0"`
|
||||
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 {
|
||||
if category.Uid <= 0 {
|
||||
return errs.ErrUserIdInvalid
|
||||
|
||||
@@ -228,6 +228,11 @@ export default {
|
||||
comment
|
||||
});
|
||||
},
|
||||
addTransactionCategoryBatch: ({ categories }) => {
|
||||
return axios.post('v1/transaction/categories/add_batch.json', {
|
||||
categories
|
||||
});
|
||||
},
|
||||
modifyTransactionCategory: ({ id, name, icon, color, comment, hidden }) => {
|
||||
return axios.post('v1/transaction/categories/modify.json', {
|
||||
id,
|
||||
|
||||
@@ -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 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',
|
||||
|
||||
@@ -516,6 +516,7 @@ export default {
|
||||
'Unable to add category': '无法添加分类',
|
||||
'Unable to save category': '无法保存分类',
|
||||
'You have added a new category': '您已经添加新分类',
|
||||
'You have added default categories': '您已经添加默认分类',
|
||||
'You have saved this category': '您已经保存该分类',
|
||||
'Are you sure you want 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-title :title="$t('Default Categories')"></f7-nav-title>
|
||||
<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-navbar>
|
||||
|
||||
@@ -50,7 +50,7 @@ export default {
|
||||
return {
|
||||
categoryType: '',
|
||||
allCategories: [],
|
||||
saving: false
|
||||
submitting: false
|
||||
};
|
||||
},
|
||||
created() {
|
||||
@@ -94,7 +94,67 @@ export default {
|
||||
}
|
||||
},
|
||||
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: {
|
||||
|
||||
Reference in New Issue
Block a user