mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-18 16:54:25 +08:00
transaction list page supports filtering by primary category
This commit is contained in:
+46
-6
@@ -13,15 +13,17 @@ import (
|
|||||||
|
|
||||||
// TransactionsApi represents transaction api
|
// TransactionsApi represents transaction api
|
||||||
type TransactionsApi struct {
|
type TransactionsApi struct {
|
||||||
transactions *services.TransactionService
|
transactions *services.TransactionService
|
||||||
transactionTags *services.TransactionTagService
|
transactionCategories *services.TransactionCategoryService
|
||||||
|
transactionTags *services.TransactionTagService
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize a transaction api singleton instance
|
// Initialize a transaction api singleton instance
|
||||||
var (
|
var (
|
||||||
Transactions = &TransactionsApi{
|
Transactions = &TransactionsApi{
|
||||||
transactions: services.Transactions,
|
transactions: services.Transactions,
|
||||||
transactionTags: services.TransactionTags,
|
transactionCategories: services.TransactionCategories,
|
||||||
|
transactionTags: services.TransactionTags,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,7 +38,26 @@ func (a *TransactionsApi) TransactionListHandler(c *core.Context) (interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
uid := c.GetCurrentUid()
|
uid := c.GetCurrentUid()
|
||||||
transactions, err := a.transactions.GetTransactionsByMaxTime(uid, transactionListReq.MaxTime, transactionListReq.MinTime, transactionListReq.Type, transactionListReq.CategoryId, transactionListReq.AccountId, transactionListReq.Keyword, transactionListReq.Count+1, true)
|
var allCategoryIds []int64
|
||||||
|
|
||||||
|
if transactionListReq.CategoryId > 0 {
|
||||||
|
allSubCategories, err := a.transactionCategories.GetAllCategoriesByUid(uid, 0, transactionListReq.CategoryId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.WarnfWithRequestId(c, "[transactions.TransactionListHandler] get transaction category error, because %s", err.Error())
|
||||||
|
return nil, errs.ErrOperationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(allSubCategories) > 0 {
|
||||||
|
for i := 0; i < len(allSubCategories); i++ {
|
||||||
|
allCategoryIds = append(allCategoryIds, allSubCategories[i].CategoryId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allCategoryIds = append(allCategoryIds, transactionListReq.CategoryId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transactions, err := a.transactions.GetTransactionsByMaxTime(uid, transactionListReq.MaxTime, transactionListReq.MinTime, transactionListReq.Type, allCategoryIds, transactionListReq.AccountId, transactionListReq.Keyword, transactionListReq.Count+1, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ErrorfWithRequestId(c, "[transactions.TransactionListHandler] failed to get transactions earlier than \"%d\" for user \"uid:%d\", because %s", transactionListReq.MaxTime, uid, err.Error())
|
log.ErrorfWithRequestId(c, "[transactions.TransactionListHandler] failed to get transactions earlier than \"%d\" for user \"uid:%d\", because %s", transactionListReq.MaxTime, uid, err.Error())
|
||||||
@@ -108,7 +129,26 @@ func (a *TransactionsApi) TransactionMonthListHandler(c *core.Context) (interfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
uid := c.GetCurrentUid()
|
uid := c.GetCurrentUid()
|
||||||
transactions, err := a.transactions.GetTransactionsInMonthByPage(uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, transactionListReq.CategoryId, transactionListReq.AccountId, transactionListReq.Keyword, transactionListReq.Page, transactionListReq.Count)
|
var allCategoryIds []int64
|
||||||
|
|
||||||
|
if transactionListReq.CategoryId > 0 {
|
||||||
|
allSubCategories, err := a.transactionCategories.GetAllCategoriesByUid(uid, 0, transactionListReq.CategoryId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.WarnfWithRequestId(c, "[transactions.TransactionMonthListHandler] get transaction category error, because %s", err.Error())
|
||||||
|
return nil, errs.ErrOperationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(allSubCategories) > 0 {
|
||||||
|
for i := 0; i < len(allSubCategories); i++ {
|
||||||
|
allCategoryIds = append(allCategoryIds, allSubCategories[i].CategoryId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allCategoryIds = append(allCategoryIds, transactionListReq.CategoryId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transactions, err := a.transactions.GetTransactionsInMonthByPage(uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, transactionListReq.AccountId, transactionListReq.Keyword, transactionListReq.Page, transactionListReq.Count)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ErrorfWithRequestId(c, "[transactions.TransactionMonthListHandler] failed to get transactions in month \"%d-%d\" for user \"uid:%d\", because %s", transactionListReq.Year, transactionListReq.Month, uid, err.Error())
|
log.ErrorfWithRequestId(c, "[transactions.TransactionMonthListHandler] failed to get transactions in month \"%d-%d\" for user \"uid:%d\", because %s", transactionListReq.Year, transactionListReq.Month, uid, err.Error())
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package services
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
@@ -33,11 +34,11 @@ var (
|
|||||||
|
|
||||||
// GetAllTransactionsByMaxTime returns all transactions before given time
|
// GetAllTransactionsByMaxTime returns all transactions before given time
|
||||||
func (s *TransactionService) GetAllTransactionsByMaxTime(uid int64, maxTime int64, count int, noDuplicated bool) ([]*models.Transaction, error) {
|
func (s *TransactionService) GetAllTransactionsByMaxTime(uid int64, maxTime int64, count int, noDuplicated bool) ([]*models.Transaction, error) {
|
||||||
return s.GetTransactionsByMaxTime(uid, maxTime, 0, 0, 0, 0, "", count, noDuplicated)
|
return s.GetTransactionsByMaxTime(uid, maxTime, 0, 0, nil, 0, "", count, noDuplicated)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransactionsByMaxTime returns transactions before given time
|
// GetTransactionsByMaxTime returns transactions before given time
|
||||||
func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTime int64, minTime int64, transactionType models.TransactionDbType, categoryId int64, accountId int64, keyword string, count int, noDuplicated bool) ([]*models.Transaction, error) {
|
func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTime int64, minTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, count int, noDuplicated bool) ([]*models.Transaction, error) {
|
||||||
if uid <= 0 {
|
if uid <= 0 {
|
||||||
return nil, errs.ErrUserIdInvalid
|
return nil, errs.ErrUserIdInvalid
|
||||||
}
|
}
|
||||||
@@ -76,9 +77,19 @@ func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTime int64,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if categoryId > 0 {
|
if len(categoryIds) > 0 {
|
||||||
condition = condition + " AND category_id=?"
|
var conditions strings.Builder
|
||||||
conditionParams = append(conditionParams, categoryId)
|
|
||||||
|
for i := 0; i < len(categoryIds); i++ {
|
||||||
|
if i > 0 {
|
||||||
|
conditions.WriteString(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
conditions.WriteString("?")
|
||||||
|
conditionParams = append(conditionParams, categoryIds[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
condition = condition + " AND category_id IN (" + conditions.String() + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
if accountId > 0 {
|
if accountId > 0 {
|
||||||
@@ -107,7 +118,7 @@ func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTime int64,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetTransactionsInMonthByPage returns transactions in given year and month
|
// GetTransactionsInMonthByPage returns transactions in given year and month
|
||||||
func (s *TransactionService) GetTransactionsInMonthByPage(uid int64, year int, month int, transactionType models.TransactionDbType, categoryId int64, accountId int64, keyword string, page int, count int) ([]*models.Transaction, error) {
|
func (s *TransactionService) GetTransactionsInMonthByPage(uid int64, year int, month int, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, page int, count int) ([]*models.Transaction, error) {
|
||||||
if uid <= 0 {
|
if uid <= 0 {
|
||||||
return nil, errs.ErrUserIdInvalid
|
return nil, errs.ErrUserIdInvalid
|
||||||
}
|
}
|
||||||
@@ -162,9 +173,19 @@ func (s *TransactionService) GetTransactionsInMonthByPage(uid int64, year int, m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if categoryId > 0 {
|
if len(categoryIds) > 0 {
|
||||||
condition = condition + " AND category_id=?"
|
var conditions strings.Builder
|
||||||
conditionParams = append(conditionParams, categoryId)
|
|
||||||
|
for i := 0; i < len(categoryIds); i++ {
|
||||||
|
if i > 0 {
|
||||||
|
conditions.WriteString(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
conditions.WriteString("?")
|
||||||
|
conditionParams = append(conditionParams, categoryIds[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
condition = condition + " AND category_id IN (" + conditions.String() + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
if accountId > 0 {
|
if accountId > 0 {
|
||||||
|
|||||||
@@ -277,26 +277,44 @@
|
|||||||
|
|
||||||
<f7-popover class="category-popover-menu" :opened="showCategoryPopover"
|
<f7-popover class="category-popover-menu" :opened="showCategoryPopover"
|
||||||
@popover:opened="showCategoryPopover = true" @popover:closed="showCategoryPopover = false">
|
@popover:opened="showCategoryPopover = true" @popover:closed="showCategoryPopover = false">
|
||||||
<f7-list>
|
<f7-list accordion-list>
|
||||||
<f7-list-item :title="$t('All')" @click="changeCategoryFilter('0')">
|
<f7-list-item :title="$t('All')" @click="changeCategoryFilter('0')">
|
||||||
<f7-icon slot="media" f7="rectangle_badge_checkmark"></f7-icon>
|
<f7-icon slot="media" f7="rectangle_badge_checkmark"></f7-icon>
|
||||||
<f7-icon slot="after" class="list-item-checked" f7="checkmark_alt" v-if="query.categoryId === '0'"></f7-icon>
|
<f7-icon slot="after" class="list-item-checked" f7="checkmark_alt" v-if="query.categoryId === '0'"></f7-icon>
|
||||||
</f7-list-item>
|
</f7-list-item>
|
||||||
<f7-list-item v-for="category in allCategories"
|
<f7-list-item accordion-item
|
||||||
v-show="category.parentId > 0 && (!query.type || category.type === query.type - 1)"
|
v-for="category in allPrimaryCategories"
|
||||||
|
v-show="!query.type || category.type === query.type - 1"
|
||||||
:key="category.id"
|
:key="category.id"
|
||||||
:title="category.name"
|
:title="category.name"
|
||||||
@click="changeCategoryFilter(category.id)"
|
|
||||||
>
|
>
|
||||||
<f7-icon slot="media"
|
<f7-icon slot="media"
|
||||||
:icon="category.icon | categoryIcon"
|
:icon="category.icon | categoryIcon"
|
||||||
:style="category.color | categoryIconStyle('var(--default-icon-color)')">
|
:style="category.color | categoryIconStyle('var(--default-icon-color)')">
|
||||||
</f7-icon>
|
</f7-icon>
|
||||||
<f7-icon slot="after"
|
<f7-accordion-content>
|
||||||
class="list-item-checked"
|
<f7-list class="padding-left">
|
||||||
f7="checkmark_alt"
|
<f7-list-item :title="$t('All')" @click="changeCategoryFilter(category.id)">
|
||||||
v-if="query.categoryId === category.id">
|
<f7-icon slot="media" f7="rectangle_badge_checkmark"></f7-icon>
|
||||||
</f7-icon>
|
<f7-icon slot="after" class="list-item-checked" f7="checkmark_alt" v-if="query.categoryId === category.id"></f7-icon>
|
||||||
|
</f7-list-item>
|
||||||
|
<f7-list-item v-for="subCategory in category.subCategories"
|
||||||
|
:key="subCategory.id"
|
||||||
|
:title="subCategory.name"
|
||||||
|
@click="changeCategoryFilter(subCategory.id)"
|
||||||
|
>
|
||||||
|
<f7-icon slot="media"
|
||||||
|
:icon="subCategory.icon | categoryIcon"
|
||||||
|
:style="subCategory.color | categoryIconStyle('var(--default-icon-color)')">
|
||||||
|
</f7-icon>
|
||||||
|
<f7-icon slot="after"
|
||||||
|
class="list-item-checked"
|
||||||
|
f7="checkmark_alt"
|
||||||
|
v-if="query.categoryId === subCategory.id">
|
||||||
|
</f7-icon>
|
||||||
|
</f7-list-item>
|
||||||
|
</f7-list>
|
||||||
|
</f7-accordion-content>
|
||||||
</f7-list-item>
|
</f7-list-item>
|
||||||
</f7-list>
|
</f7-list>
|
||||||
</f7-popover>
|
</f7-popover>
|
||||||
@@ -388,6 +406,25 @@ export default {
|
|||||||
allCategories() {
|
allCategories() {
|
||||||
return this.$store.state.allTransactionCategoriesMap;
|
return this.$store.state.allTransactionCategoriesMap;
|
||||||
},
|
},
|
||||||
|
allPrimaryCategories() {
|
||||||
|
const primaryCategories = [];
|
||||||
|
|
||||||
|
for (let categoryId in this.$store.state.allTransactionCategoriesMap) {
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(this.$store.state.allTransactionCategoriesMap, categoryId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const category = this.$store.state.allTransactionCategoriesMap[categoryId];
|
||||||
|
|
||||||
|
if (category.parentId !== '0') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
primaryCategories.push(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
return primaryCategories;
|
||||||
|
},
|
||||||
allDateRanges() {
|
allDateRanges() {
|
||||||
return this.$constants.datetime.allDateRanges;
|
return this.$constants.datetime.allDateRanges;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user