add: impl tags, template, payee query api
This commit is contained in:
parent
09e75df763
commit
9a0bd56cb2
|
|
@ -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,8 +77,14 @@ func bqlRawQuery(ledgerConfig *Config, queryParamsPtr *QueryParams, queryResultP
|
|||
case reflect.String:
|
||||
val := valueField.String()
|
||||
if 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:
|
||||
val := valueField.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:
|
||||
// 去除空格
|
||||
|
|
|
|||
|
|
@ -13,3 +13,7 @@ func GetExampleLedgerConfigDirPath() string {
|
|||
}
|
||||
return currentPath + "/example"
|
||||
}
|
||||
|
||||
func GetLedgerTransactionsTemplateFilePath(dataPath string) string {
|
||||
return dataPath + "/.beancount-ns/transaction_template.json"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue