add default categories backend

This commit is contained in:
MaysWind
2020-12-04 02:42:52 +08:00
parent 9c18bc650e
commit c5cc4dee56
8 changed files with 242 additions and 2 deletions
+1
View File
@@ -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))
+106
View File
@@ -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)
+13
View File
@@ -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"`
+53
View File
@@ -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
+5
View File
@@ -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,
+1
View File
@@ -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',
+1
View File
@@ -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: {