add:import alipay payroll

This commit is contained in:
BaoXuebin 2021-12-12 22:42:07 +08:00
parent 49ad1435bc
commit 54ef138d90
3 changed files with 115 additions and 13 deletions

View File

@ -76,6 +76,7 @@ func RegisterRouter(router *gin.Engine) {
authorized.GET("/stats/month/total", service.StatsMonthTotal) authorized.GET("/stats/month/total", service.StatsMonthTotal)
authorized.GET("/transaction", service.QueryTransactions) authorized.GET("/transaction", service.QueryTransactions)
authorized.POST("/transaction", service.AddTransactions) authorized.POST("/transaction", service.AddTransactions)
authorized.POST("/transaction/batch", service.AddBatchTransactions)
authorized.GET("/transaction/payee", service.QueryTransactionPayees) authorized.GET("/transaction/payee", service.QueryTransactionPayees)
authorized.GET("/transaction/template", service.QueryTransactionTemplates) authorized.GET("/transaction/template", service.QueryTransactionTemplates)
authorized.POST("/transaction/template", service.AddTransactionTemplate) authorized.POST("/transaction/template", service.AddTransactionTemplate)
@ -84,6 +85,7 @@ func RegisterRouter(router *gin.Engine) {
authorized.GET("/file/dir", service.QueryLedgerSourceFileDir) authorized.GET("/file/dir", service.QueryLedgerSourceFileDir)
authorized.GET("/file/content", service.QueryLedgerSourceFileContent) authorized.GET("/file/content", service.QueryLedgerSourceFileContent)
authorized.POST("/file", service.UpdateLedgerSourceFileContent) authorized.POST("/file", service.UpdateLedgerSourceFileContent)
authorized.POST("/import/alipay", service.ImportAliPayCSV)
} }
} }

60
service/import.go Normal file
View File

@ -0,0 +1,60 @@
package service
import (
"bufio"
"encoding/csv"
"github.com/beancount-gs/script"
"github.com/gin-gonic/gin"
"golang.org/x/text/encoding/simplifiedchinese"
"io"
"strings"
)
func ImportAliPayCSV(c *gin.Context) {
ledgerConfig := script.GetLedgerConfigFromContext(c)
file, _ := c.FormFile("file")
f, _ := file.Open()
reader := csv.NewReader(simplifiedchinese.GBK.NewDecoder().Reader(bufio.NewReader(f)))
result := make([]Transaction, 0)
currency := "CNY"
currencySymbol := script.GetCommoditySymbol(currency)
for {
lines, err := reader.Read()
if err == io.EOF {
break
} else if err != nil {
script.LogError(ledgerConfig.Mail, err.Error())
}
if len(lines) > 11 {
fields := strings.Fields(lines[2])
status := strings.Trim(lines[15], " ")
account := ""
if status == "已收入" {
account = "Income:"
} else if status == "已支出" {
account = "Expenses:"
} else {
continue
}
if len(fields) >= 2 {
result = append(result, Transaction{
Id: strings.Trim(lines[0], " "),
Date: strings.Trim(fields[0], " "),
Payee: strings.Trim(lines[7], " "),
Narration: strings.Trim(lines[8], " "),
Number: strings.Trim(lines[9], " "),
Account: account,
Currency: currency,
CurrencySymbol: currencySymbol,
})
}
}
}
OK(c, result)
}

View File

@ -4,6 +4,7 @@ import (
"crypto/sha1" "crypto/sha1"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"github.com/beancount-gs/script" "github.com/beancount-gs/script"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -84,6 +85,25 @@ func sum(entries []AddTransactionEntryForm, openingBalances string) decimal.Deci
return sumVal return sumVal
} }
func AddBatchTransactions(c *gin.Context) {
var addTransactionForms []AddTransactionForm
if err := c.ShouldBindJSON(&addTransactionForms); err != nil {
BadRequest(c, err.Error())
return
}
result := make([]string, 0)
ledgerConfig := script.GetLedgerConfigFromContext(c)
for _, form := range addTransactionForms {
err := saveTransaction(nil, form, ledgerConfig)
if err == nil {
result = append(result, form.Date+form.Payee+form.Desc)
} else {
script.LogError(ledgerConfig.Mail, err.Error())
}
}
OK(c, result)
}
func AddTransactions(c *gin.Context) { func AddTransactions(c *gin.Context) {
var addTransactionForm AddTransactionForm var addTransactionForm AddTransactionForm
if err := c.ShouldBindJSON(&addTransactionForm); err != nil { if err := c.ShouldBindJSON(&addTransactionForm); err != nil {
@ -91,12 +111,22 @@ func AddTransactions(c *gin.Context) {
return return
} }
ledgerConfig := script.GetLedgerConfigFromContext(c) ledgerConfig := script.GetLedgerConfigFromContext(c)
err := saveTransaction(c, addTransactionForm, ledgerConfig)
if err != nil {
return
}
OK(c, nil)
}
func saveTransaction(c *gin.Context, addTransactionForm AddTransactionForm, ledgerConfig *script.Config) error {
// 账户是否平衡 // 账户是否平衡
sumVal := sum(addTransactionForm.Entries, ledgerConfig.OpeningBalances) sumVal := sum(addTransactionForm.Entries, ledgerConfig.OpeningBalances)
val, _ := decimal.NewFromString("0.01") val, _ := decimal.NewFromString("0.01")
if sumVal.Abs().GreaterThan(val) { if sumVal.Abs().GreaterThan(val) {
TransactionNotBalance(c) if c != nil {
return TransactionNotBalance(c)
}
return errors.New("transaction not balance")
} }
// 2021-09-29 * "支付宝" "黄金补仓X元" #Invest // 2021-09-29 * "支付宝" "黄金补仓X元" #Invest
@ -129,8 +159,10 @@ func AddTransactions(c *gin.Context) {
priceLine := fmt.Sprintf("%s price %s %s %s", addTransactionForm.Date, account.Currency, entry.Price, ledgerConfig.OperatingCurrency) priceLine := fmt.Sprintf("%s price %s %s %s", addTransactionForm.Date, account.Currency, entry.Price, ledgerConfig.OperatingCurrency)
err := script.AppendFileInNewLine(script.GetLedgerPriceFilePath(ledgerConfig.DataPath), priceLine) err := script.AppendFileInNewLine(script.GetLedgerPriceFilePath(ledgerConfig.DataPath), priceLine)
if err != nil { if err != nil {
InternalError(c, err.Error()) if c != nil {
return InternalError(c, err.Error())
}
return errors.New("internal error")
} }
} }
} }
@ -142,8 +174,10 @@ func AddTransactions(c *gin.Context) {
// 记账的日期 // 记账的日期
month, err := time.Parse("2006-01-02", addTransactionForm.Date) month, err := time.Parse("2006-01-02", addTransactionForm.Date)
if err != nil { if err != nil {
InternalError(c, err.Error()) if c != nil {
return InternalError(c, err.Error())
}
return errors.New("internal error")
} }
monthStr := month.Format("2006-01") monthStr := month.Format("2006-01")
filePath := fmt.Sprintf("%s/month/%s.bean", ledgerConfig.DataPath, monthStr) filePath := fmt.Sprintf("%s/month/%s.bean", ledgerConfig.DataPath, monthStr)
@ -152,23 +186,29 @@ func AddTransactions(c *gin.Context) {
if !script.FileIfExist(filePath) { if !script.FileIfExist(filePath) {
err = script.CreateFile(filePath) err = script.CreateFile(filePath)
if err != nil { if err != nil {
InternalError(c, err.Error()) if c != nil {
return InternalError(c, err.Error())
}
return errors.New("internal error")
} }
// include ./2021-11.bean // include ./2021-11.bean
err = script.AppendFileInNewLine(script.GetLedgerMonthsFilePath(ledgerConfig.DataPath), fmt.Sprintf("include \"./%s.bean\"", monthStr)) err = script.AppendFileInNewLine(script.GetLedgerMonthsFilePath(ledgerConfig.DataPath), fmt.Sprintf("include \"./%s.bean\"", monthStr))
if err != nil { if err != nil {
InternalError(c, err.Error()) if c != nil {
return InternalError(c, err.Error())
}
return errors.New("internal error")
} }
} }
err = script.AppendFileInNewLine(filePath, line) err = script.AppendFileInNewLine(filePath, line)
if err != nil { if err != nil {
InternalError(c, err.Error()) if c != nil {
return InternalError(c, err.Error())
}
return errors.New("internal error")
} }
OK(c, nil) return nil
} }
type transactionPayee struct { type transactionPayee struct {