add: impl tags, template, payee query api

This commit is contained in:
leo 2021-11-22 18:05:12 +08:00
parent 09e75df763
commit 9a0bd56cb2
5 changed files with 146 additions and 26 deletions

View File

@ -9,9 +9,12 @@ import (
)
type QueryParams struct {
Where bool `bql:"where"`
Year int `bql:"year ="`
Month int `bql:"month ="`
AccountType string `bql:"account ~"`
OrderBy string `bql:"order by"`
Limit int `bql:"limit"`
}
func BQLQueryOne(ledgerConfig *Config, queryParams *QueryParams, queryResultPtr interface{}) error {
@ -62,9 +65,9 @@ func bqlRawQuery(ledgerConfig *Config, queryParamsPtr *QueryParams, queryResultP
}
}
}
bql += " '\\'"
// 查询条件不为空时,拼接查询条件
if queryParamsPtr != nil {
bql += " '\\' WHERE"
queryParamsType := reflect.TypeOf(queryParamsPtr).Elem()
queryParamsValue := reflect.ValueOf(queryParamsPtr).Elem()
for i := 0; i < queryParamsType.NumField(); i++ {
@ -74,7 +77,13 @@ func bqlRawQuery(ledgerConfig *Config, queryParamsPtr *QueryParams, queryResultP
case reflect.String:
val := valueField.String()
if val != "" {
bql = fmt.Sprintf("%s %s '%s' AND", bql, typeField.Tag.Get("bql"), val)
if typeField.Name == "OrderBy" {
// 去除上一个条件后缀的 AND 关键字
bql = strings.Trim(bql, " AND")
bql = fmt.Sprintf("%s %s %s", bql, typeField.Tag.Get("bql"), val)
} else {
bql = fmt.Sprintf("%s %s '%s' AND", bql, typeField.Tag.Get("bql"), val)
}
}
break
case reflect.Int:
@ -83,11 +92,15 @@ func bqlRawQuery(ledgerConfig *Config, queryParamsPtr *QueryParams, queryResultP
bql = fmt.Sprintf("%s %s %d AND", bql, typeField.Tag.Get("bql"), val)
}
break
case reflect.Bool:
val := valueField.Bool()
if val {
bql = fmt.Sprintf("%s %s ", bql, typeField.Tag.Get("bql"))
}
break
}
}
bql = strings.TrimRight(bql, " AND")
} else {
bql += " '\\'"
}
return queryByBQL(ledgerConfig, bql)
}
@ -120,7 +133,10 @@ func parseResult(output string, queryResultPtr interface{}, selectOne bool) erro
}
switch field.Type.Kind() {
case reflect.String:
temp[jsonName] = strings.Trim(val, " ")
v := strings.Trim(val, " ")
if v != "" {
temp[jsonName] = v
}
break
case reflect.Array, reflect.Slice:
// 去除空格

View File

@ -13,3 +13,7 @@ func GetExampleLedgerConfigDirPath() string {
}
return currentPath + "/example"
}
func GetLedgerTransactionsTemplateFilePath(dataPath string) string {
return dataPath + "/.beancount-ns/transaction_template.json"
}

View File

@ -47,9 +47,14 @@ func RegisterRouter(router *gin.Engine) {
// need authorized
authorized.GET("/stats/months", service.MonthsList)
authorized.GET("/transactions", service.QueryTransactions)
authorized.GET("/transactions/payee", service.QueryTransactionsPayee)
authorized.GET("/transactions/template", service.QueryTransactionsTemplate)
authorized.GET("/tags", service.QueryTags)
// 兼容旧版本
authorized.GET("/entry", service.QueryTransactions)
authorized.GET("/payee", service.QueryTransactionsPayee)
authorized.GET("/transaction/template", service.QueryTransactionsTemplate)
}
}

29
service/tags.go Normal file
View File

@ -0,0 +1,29 @@
package service
import (
"github.com/beancount-gs/script"
"github.com/gin-gonic/gin"
)
type Tags struct {
Value string `bql:"distinct tags" json:"value"`
}
func QueryTags(c *gin.Context) {
ledgerConfig := script.GetLedgerConfigFromContext(c)
tags := make([]Tags, 0)
err := script.BQLQueryList(ledgerConfig, nil, &tags)
if err != nil {
InternalError(c, err.Error())
return
}
result := make([]string, 0)
for _, t := range tags {
if t.Value != "" {
result = append(result, t.Value)
}
}
OK(c, result)
}

View File

@ -1,12 +1,38 @@
package service
import (
"github.com/beancount-gs/script"
"encoding/json"
script "github.com/beancount-gs/script"
"github.com/gin-gonic/gin"
"strconv"
"strings"
)
func getQueryModel(c *gin.Context) script.QueryParams {
var queryParams script.QueryParams
var hasWhere bool
if c.Query("year") != "" {
val, err := strconv.Atoi(c.Query("year"))
if err == nil {
queryParams.Year = val
hasWhere = true
}
}
if c.Query("month") != "" {
val, err := strconv.Atoi(c.Query("month"))
if err == nil {
queryParams.Month = val
hasWhere = true
}
}
if c.Query("type") != "" {
queryParams.AccountType = c.Query("type")
hasWhere = true
}
queryParams.Where = hasWhere
return queryParams
}
type Transactions struct {
Id string `bql:"id" json:"id"`
Date string `bql:"date" json:"date"`
@ -20,29 +46,11 @@ type Transactions struct {
CommoditySymbol string `json:"commoditySymbol"`
}
func getQueryModel(c *gin.Context) script.QueryParams {
var queryParams script.QueryParams
if c.Query("year") != "" {
val, err := strconv.Atoi(c.Query("year"))
if err == nil {
queryParams.Year = val
}
}
if c.Query("month") != "" {
val, err := strconv.Atoi(c.Query("month"))
if err == nil {
queryParams.Month = val
}
}
if c.Query("type") != "" {
queryParams.AccountType = c.Query("type")
}
return queryParams
}
func QueryTransactions(c *gin.Context) {
ledgerConfig := script.GetLedgerConfigFromContext(c)
queryParams := getQueryModel(c)
// 倒序查询
queryParams.OrderBy = "date desc"
transactions := make([]Transactions, 0)
err := script.BQLQueryList(ledgerConfig, &queryParams, &transactions)
if err != nil {
@ -61,3 +69,61 @@ func QueryTransactions(c *gin.Context) {
}
OK(c, transactions)
}
type transactionsPayee struct {
Value string `bql:"distinct payee" json:"value"`
}
func QueryTransactionsPayee(c *gin.Context) {
ledgerConfig := script.GetLedgerConfigFromContext(c)
payeeList := make([]transactionsPayee, 0)
queryParams := script.QueryParams{Where: false, OrderBy: "date desc", Limit: 100}
err := script.BQLQueryList(ledgerConfig, &queryParams, &payeeList)
if err != nil {
InternalError(c, err.Error())
return
}
result := make([]string, 0)
for _, payee := range payeeList {
if payee.Value != "" {
result = append(result, payee.Value)
}
}
OK(c, result)
}
type transactionsTemplate struct {
Id string `json:"id"`
Date string `json:"date"`
TemplateName string `json:"templateName"`
Payee string `json:"payee"`
Desc string `json:"desc"`
Entries []transactionsTemplateEntity `json:"entries"`
}
type transactionsTemplateEntity struct {
Account string `json:"account"`
Commodity string `json:"commodity"`
Amount string `json:"amount"`
}
func QueryTransactionsTemplate(c *gin.Context) {
ledgerConfig := script.GetLedgerConfigFromContext(c)
filePath := script.GetLedgerTransactionsTemplateFilePath(ledgerConfig.DataPath)
if script.FileIfExist(filePath) {
bytes, err := script.ReadFile(filePath)
if err != nil {
InternalError(c, err.Error())
return
}
result := make([]transactionsTemplate, 0)
err = json.Unmarshal(bytes, &result)
if err != nil {
InternalError(c, err.Error())
return
}
OK(c, result)
} else {
OK(c, new([]string))
}
}