add: impl tags, template, payee query api
This commit is contained in:
parent
09e75df763
commit
9a0bd56cb2
|
|
@ -9,9 +9,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type QueryParams struct {
|
type QueryParams struct {
|
||||||
|
Where bool `bql:"where"`
|
||||||
Year int `bql:"year ="`
|
Year int `bql:"year ="`
|
||||||
Month int `bql:"month ="`
|
Month int `bql:"month ="`
|
||||||
AccountType string `bql:"account ~"`
|
AccountType string `bql:"account ~"`
|
||||||
|
OrderBy string `bql:"order by"`
|
||||||
|
Limit int `bql:"limit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func BQLQueryOne(ledgerConfig *Config, queryParams *QueryParams, queryResultPtr interface{}) error {
|
func BQLQueryOne(ledgerConfig *Config, queryParams *QueryParams, queryResultPtr interface{}) error {
|
||||||
|
|
@ -62,9 +65,9 @@ func bqlRawQuery(ledgerConfig *Config, queryParamsPtr *QueryParams, queryResultP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bql += " '\\'"
|
||||||
// 查询条件不为空时,拼接查询条件
|
// 查询条件不为空时,拼接查询条件
|
||||||
if queryParamsPtr != nil {
|
if queryParamsPtr != nil {
|
||||||
bql += " '\\' WHERE"
|
|
||||||
queryParamsType := reflect.TypeOf(queryParamsPtr).Elem()
|
queryParamsType := reflect.TypeOf(queryParamsPtr).Elem()
|
||||||
queryParamsValue := reflect.ValueOf(queryParamsPtr).Elem()
|
queryParamsValue := reflect.ValueOf(queryParamsPtr).Elem()
|
||||||
for i := 0; i < queryParamsType.NumField(); i++ {
|
for i := 0; i < queryParamsType.NumField(); i++ {
|
||||||
|
|
@ -74,8 +77,14 @@ func bqlRawQuery(ledgerConfig *Config, queryParamsPtr *QueryParams, queryResultP
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
val := valueField.String()
|
val := valueField.String()
|
||||||
if val != "" {
|
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)
|
bql = fmt.Sprintf("%s %s '%s' AND", bql, typeField.Tag.Get("bql"), val)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
val := valueField.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)
|
bql = fmt.Sprintf("%s %s %d AND", bql, typeField.Tag.Get("bql"), val)
|
||||||
}
|
}
|
||||||
break
|
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")
|
bql = strings.TrimRight(bql, " AND")
|
||||||
} else {
|
|
||||||
bql += " '\\'"
|
|
||||||
}
|
}
|
||||||
return queryByBQL(ledgerConfig, bql)
|
return queryByBQL(ledgerConfig, bql)
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +133,10 @@ func parseResult(output string, queryResultPtr interface{}, selectOne bool) erro
|
||||||
}
|
}
|
||||||
switch field.Type.Kind() {
|
switch field.Type.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
temp[jsonName] = strings.Trim(val, " ")
|
v := strings.Trim(val, " ")
|
||||||
|
if v != "" {
|
||||||
|
temp[jsonName] = v
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case reflect.Array, reflect.Slice:
|
case reflect.Array, reflect.Slice:
|
||||||
// 去除空格
|
// 去除空格
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,7 @@ func GetExampleLedgerConfigDirPath() string {
|
||||||
}
|
}
|
||||||
return currentPath + "/example"
|
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
|
// need authorized
|
||||||
authorized.GET("/stats/months", service.MonthsList)
|
authorized.GET("/stats/months", service.MonthsList)
|
||||||
authorized.GET("/transactions", service.QueryTransactions)
|
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("/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
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/beancount-gs/script"
|
"encoding/json"
|
||||||
|
script "github.com/beancount-gs/script"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"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 {
|
type Transactions struct {
|
||||||
Id string `bql:"id" json:"id"`
|
Id string `bql:"id" json:"id"`
|
||||||
Date string `bql:"date" json:"date"`
|
Date string `bql:"date" json:"date"`
|
||||||
|
|
@ -20,29 +46,11 @@ type Transactions struct {
|
||||||
CommoditySymbol string `json:"commoditySymbol"`
|
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) {
|
func QueryTransactions(c *gin.Context) {
|
||||||
ledgerConfig := script.GetLedgerConfigFromContext(c)
|
ledgerConfig := script.GetLedgerConfigFromContext(c)
|
||||||
queryParams := getQueryModel(c)
|
queryParams := getQueryModel(c)
|
||||||
|
// 倒序查询
|
||||||
|
queryParams.OrderBy = "date desc"
|
||||||
transactions := make([]Transactions, 0)
|
transactions := make([]Transactions, 0)
|
||||||
err := script.BQLQueryList(ledgerConfig, &queryParams, &transactions)
|
err := script.BQLQueryList(ledgerConfig, &queryParams, &transactions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -61,3 +69,61 @@ func QueryTransactions(c *gin.Context) {
|
||||||
}
|
}
|
||||||
OK(c, transactions)
|
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