add event api
This commit is contained in:
parent
727d504f2f
commit
4ffe60112c
|
|
@ -25,7 +25,7 @@
|
||||||
- [X] 投资管理(FIFO)
|
- [X] 投资管理(FIFO)
|
||||||
- [X] 第三方账单导入(支付宝,微信,工商银行,农业银行)
|
- [X] 第三方账单导入(支付宝,微信,工商银行,农业银行)
|
||||||
- [X] 分期记账
|
- [X] 分期记账
|
||||||
- [ ] 事件
|
- [X] 事件
|
||||||
|
|
||||||
## 如何使用
|
## 如何使用
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,15 @@ func BeanReportAllPrices(ledgerConfig *Config) string {
|
||||||
return string(output)
|
return string(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BeanReportAllEvents(ledgerConfig *Config) string {
|
||||||
|
beanFilePath := GetLedgerEventsFilePath(ledgerConfig.DataPath)
|
||||||
|
|
||||||
|
LogInfo(ledgerConfig.Mail, "bean-report "+beanFilePath+" events")
|
||||||
|
cmd := exec.Command("bean-report", beanFilePath, "events")
|
||||||
|
output, _ := cmd.Output()
|
||||||
|
return string(output)
|
||||||
|
}
|
||||||
|
|
||||||
func bqlRawQuery(ledgerConfig *Config, selectBql string, queryParamsPtr *QueryParams, queryResultPtr interface{}) (string, error) {
|
func bqlRawQuery(ledgerConfig *Config, selectBql string, queryParamsPtr *QueryParams, queryResultPtr interface{}) (string, error) {
|
||||||
var bql string
|
var bql string
|
||||||
if selectBql == "" {
|
if selectBql == "" {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
package script
|
package script
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FileIfExist(filePath string) bool {
|
func FileIfExist(filePath string) bool {
|
||||||
|
|
@ -59,6 +61,60 @@ func AppendFileInNewLine(filePath string, content string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeleteLinesWithText(filePath string, textToDelete string) error {
|
||||||
|
// 打开文件以供读写
|
||||||
|
file, err := os.OpenFile(filePath, os.O_RDWR, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// 创建一个缓冲读取器
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
|
||||||
|
// 创建一个字符串切片,用于保存文件的每一行
|
||||||
|
var lines []string
|
||||||
|
|
||||||
|
// 逐行读取文件内容
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
|
||||||
|
// 检查行是否包含要删除的文本
|
||||||
|
if !strings.Contains(line, textToDelete) {
|
||||||
|
lines = append(lines, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭文件
|
||||||
|
file.Close()
|
||||||
|
|
||||||
|
// 重新打开文件以供写入
|
||||||
|
file, err = os.OpenFile(filePath, os.O_RDWR|os.O_TRUNC, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// 创建一个写入器
|
||||||
|
writer := bufio.NewWriter(file)
|
||||||
|
|
||||||
|
// 将修改后的内容写回文件
|
||||||
|
for _, line := range lines {
|
||||||
|
_, err := writer.WriteString(line + "\n")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新缓冲区,确保所有数据被写入文件
|
||||||
|
err = writer.Flush()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func CreateFile(filePath string) error {
|
func CreateFile(filePath string) error {
|
||||||
if _, e := os.Stat(filePath); os.IsNotExist(e) {
|
if _, e := os.Stat(filePath); os.IsNotExist(e) {
|
||||||
_ = os.MkdirAll(filepath.Dir(filePath), os.ModePerm)
|
_ = os.MkdirAll(filepath.Dir(filePath), os.ModePerm)
|
||||||
|
|
|
||||||
|
|
@ -56,3 +56,13 @@ func GetLedgerIndexFilePath(dataPath string) string {
|
||||||
LogInfo(dataPath, dataPath+"/index.bean")
|
LogInfo(dataPath, dataPath+"/index.bean")
|
||||||
return dataPath + "/index.bean"
|
return dataPath + "/index.bean"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetLedgerIncludesFilePath(dataPath string) string {
|
||||||
|
LogInfo(dataPath, dataPath+"/includes.bean")
|
||||||
|
return dataPath + "/includes.bean"
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLedgerEventsFilePath(dataPath string) string {
|
||||||
|
LogInfo(dataPath, dataPath+"/event/events.bean")
|
||||||
|
return dataPath + "/event/events.bean"
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func isWindows() bool {
|
func isWindows() bool {
|
||||||
|
return false
|
||||||
os := runtime.GOOS
|
os := runtime.GOOS
|
||||||
return os == "windows"
|
return os == "windows"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,9 @@ func RegisterRouter(router *gin.Engine) {
|
||||||
authorized.GET("/transaction/template", service.QueryTransactionTemplates)
|
authorized.GET("/transaction/template", service.QueryTransactionTemplates)
|
||||||
authorized.POST("/transaction/template", service.AddTransactionTemplate)
|
authorized.POST("/transaction/template", service.AddTransactionTemplate)
|
||||||
authorized.DELETE("/transaction/template", service.DeleteTransactionTemplate)
|
authorized.DELETE("/transaction/template", service.DeleteTransactionTemplate)
|
||||||
authorized.GET("/event/page", service.GetAllEvents)
|
authorized.GET("/event/all", service.GetAllEvents)
|
||||||
authorized.POST("/event", service.AddEvent)
|
authorized.POST("/event", service.AddEvent)
|
||||||
|
authorized.DELETE("/event", service.DeleteEvent)
|
||||||
authorized.GET("/tags", service.QueryTags)
|
authorized.GET("/tags", service.QueryTags)
|
||||||
authorized.GET("/file/dir", service.QueryLedgerSourceFileDir)
|
authorized.GET("/file/dir", service.QueryLedgerSourceFileDir)
|
||||||
authorized.GET("/file/content", service.QueryLedgerSourceFileContent)
|
authorized.GET("/file/content", service.QueryLedgerSourceFileContent)
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ type accountPosition struct {
|
||||||
func QueryAllAccount(c *gin.Context) {
|
func QueryAllAccount(c *gin.Context) {
|
||||||
ledgerConfig := script.GetLedgerConfigFromContext(c)
|
ledgerConfig := script.GetLedgerConfigFromContext(c)
|
||||||
|
|
||||||
bql := fmt.Sprintf("select '\\', account, '\\', sum(convert(value(position), '%s')) as market_position, '\\', sum(value(position)) as position, '\\'", ledgerConfig.OperatingCurrency)
|
bql := fmt.Sprintf("select '\\', account, '\\', sum(convert(value(position), '%s')) as market_position, '\\', sum(convert(value(position), currency)) as position, '\\'", ledgerConfig.OperatingCurrency)
|
||||||
accountPositions := make([]accountPosition, 0)
|
accountPositions := make([]accountPosition, 0)
|
||||||
err := script.BQLQueryListByCustomSelect(ledgerConfig, bql, nil, &accountPositions)
|
err := script.BQLQueryListByCustomSelect(ledgerConfig, bql, nil, &accountPositions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,79 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import "github.com/gin-gonic/gin"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/beancount-gs/script"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Date string `json:"date"`
|
Date string `form:"date" binding:"required" json:"date"`
|
||||||
Type string `json:"type"`
|
Type string `form:"type" binding:"required" json:"type"`
|
||||||
Description string `json:"description"`
|
Description string `form:"description" binding:"required" json:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllEvents(c *gin.Context) {
|
func GetAllEvents(c *gin.Context) {
|
||||||
OK(c, nil)
|
ledgerConfig := script.GetLedgerConfigFromContext(c)
|
||||||
|
output := script.BeanReportAllEvents(ledgerConfig)
|
||||||
|
script.LogInfo(ledgerConfig.Mail, output)
|
||||||
|
|
||||||
|
events := make([]Event, 0)
|
||||||
|
lines := strings.Split(output, "\n")
|
||||||
|
// foreach lines
|
||||||
|
for idx, line := range lines {
|
||||||
|
if idx < 2 || idx > len(lines)-3 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Trim(line, " ") == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// split line by " "
|
||||||
|
words := strings.Fields(line)
|
||||||
|
events = append(events, Event{
|
||||||
|
Date: words[0],
|
||||||
|
Type: words[1],
|
||||||
|
Description: words[2],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
OK(c, events)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEvent(c *gin.Context) {
|
func AddEvent(c *gin.Context) {
|
||||||
|
var event Event
|
||||||
|
if err := c.ShouldBindJSON(&event); err != nil {
|
||||||
|
BadRequest(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ledgerConfig := script.GetLedgerConfigFromContext(c)
|
||||||
|
filePath := script.GetLedgerEventsFilePath(ledgerConfig.DataPath)
|
||||||
|
|
||||||
|
line := fmt.Sprintf("%s event \"%s\" \"%s\"", event.Date, event.Type, event.Description)
|
||||||
|
// 写入文件
|
||||||
|
err := script.AppendFileInNewLine(filePath, line)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
OK(c, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteEvent(c *gin.Context) {
|
||||||
|
var event Event
|
||||||
|
if err := c.ShouldBindJSON(&event); err != nil {
|
||||||
|
BadRequest(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ledgerConfig := script.GetLedgerConfigFromContext(c)
|
||||||
|
filePath := script.GetLedgerEventsFilePath(ledgerConfig.DataPath)
|
||||||
|
|
||||||
|
line := fmt.Sprintf("%s event \"%s\" \"%s\"", event.Date, event.Type, event.Description)
|
||||||
|
err := script.DeleteLinesWithText(filePath, line)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
OK(c, nil)
|
OK(c, nil)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,3 +10,5 @@ include "./price/prices.bean"
|
||||||
include "./history.bean"
|
include "./history.bean"
|
||||||
; 新的数据(按月拆分)
|
; 新的数据(按月拆分)
|
||||||
include "./month/months.bean"
|
include "./month/months.bean"
|
||||||
|
; 事件数据
|
||||||
|
include "./event/events.bean"
|
||||||
Loading…
Reference in New Issue