beancount-gs/service/import.go

283 lines
6.7 KiB
Go
Raw Normal View History

2021-12-12 14:42:07 +00:00
package service
import (
"bufio"
"encoding/csv"
"errors"
2021-12-12 14:42:07 +00:00
"io"
2022-12-27 15:55:53 +00:00
"strconv"
2021-12-12 14:42:07 +00:00
"strings"
2022-12-27 15:55:53 +00:00
"time"
"github.com/beancount-gs/script"
"github.com/gin-gonic/gin"
"golang.org/x/text/encoding/simplifiedchinese"
2021-12-12 14:42:07 +00:00
)
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(ledgerConfig.Id, currency)
2021-12-12 14:42:07 +00:00
for {
lines, err := reader.Read()
if errors.Is(err, io.EOF) {
2021-12-12 14:42:07 +00:00
break
} else if err != nil {
script.LogError(ledgerConfig.Mail, err.Error())
}
if len(lines) == 17 {
transaction, err := importBrowserAliPayCSV(lines, currency, currencySymbol)
if err != nil {
script.LogInfo(ledgerConfig.Mail, err.Error())
2021-12-12 14:42:07 +00:00
continue
}
if transaction.Account == "" {
script.LogInfo(ledgerConfig.Mail, "Invalid transaction")
continue
}
result = append(result, transaction)
} else if len(lines) == 12 || len(lines) == 13 {
transaction, err := importMobileAliPayCSV(lines, currency, currencySymbol)
if err != nil {
script.LogInfo(ledgerConfig.Mail, err.Error())
continue
2021-12-12 14:42:07 +00:00
}
if transaction.Account == "" {
script.LogInfo(ledgerConfig.Mail, "Invalid transaction")
continue
}
result = append(result, transaction)
2021-12-12 14:42:07 +00:00
}
}
OK(c, result)
}
2021-12-14 13:24:39 +00:00
func importBrowserAliPayCSV(lines []string, currency string, currencySymbol string) (Transaction, error) {
dateColumn := strings.Fields(lines[2])
status := strings.Trim(lines[15], " ")
account := ""
switch status {
case "":
account = ""
case "已收入":
account = "Income:"
default:
account = "Expenses:"
}
if len(dateColumn) >= 2 {
return Transaction{
Id: strings.Trim(lines[0], " "),
Date: strings.Trim(dateColumn[0], " "),
Payee: strings.Trim(lines[7], " "),
Narration: strings.Trim(lines[8], " "),
Number: strings.Trim(lines[9], " "),
Account: account,
Currency: currency,
CurrencySymbol: currencySymbol,
}, nil
}
return Transaction{}, errors.New("parse error")
}
func importMobileAliPayCSV(lines []string, currency string, currencySymbol string) (Transaction, error) {
dateColumn := strings.Fields(lines[0])
status := strings.Trim(lines[5], " ")
account := ""
switch status {
case "":
account = ""
case "已收入":
account = "Income:"
default:
account = "Expenses:"
}
if len(dateColumn) >= 2 {
return Transaction{
Id: strings.Trim(lines[9], " "),
Date: strings.Trim(dateColumn[0], " "),
Payee: strings.Trim(lines[2], " "),
Narration: strings.Trim(lines[4], " "),
Number: strings.Trim(lines[6], " "),
Account: account,
Currency: currency,
CurrencySymbol: currencySymbol,
}, nil
}
return Transaction{}, errors.New("parse error")
}
2021-12-14 13:24:39 +00:00
func ImportWxPayCSV(c *gin.Context) {
ledgerConfig := script.GetLedgerConfigFromContext(c)
file, _ := c.FormFile("file")
f, _ := file.Open()
reader := csv.NewReader(bufio.NewReader(f))
result := make([]Transaction, 0)
currency := "CNY"
currencySymbol := script.GetCommoditySymbol(ledgerConfig.Id, currency)
2021-12-14 13:24:39 +00:00
for {
lines, err := reader.Read()
if err == io.EOF {
break
} else if err != nil {
script.LogError(ledgerConfig.Mail, err.Error())
}
if len(lines) > 8 {
fields := strings.Fields(lines[0])
status := strings.Trim(lines[4], " ")
account := ""
switch status {
case "收入":
2021-12-14 13:24:39 +00:00
account = "Income:"
case "支出":
2021-12-14 13:24:39 +00:00
account = "Expenses:"
default:
account = ""
2021-12-14 13:24:39 +00:00
}
if len(fields) >= 2 {
result = append(result, Transaction{
Id: strings.Trim(lines[8], " "),
Date: strings.Trim(fields[0], " "),
Payee: strings.Trim(lines[2], " "),
Narration: strings.Trim(lines[3], " "),
Number: strings.Trim(lines[5], "¥"),
Account: account,
Currency: currency,
CurrencySymbol: currencySymbol,
})
}
}
}
OK(c, result)
}
2022-12-27 15:55:53 +00:00
func ImportICBCCSV(c *gin.Context) {
ledgerConfig := script.GetLedgerConfigFromContext(c)
file, _ := c.FormFile("file")
f, _ := file.Open()
reader := csv.NewReader(bufio.NewReader(f))
result := make([]Transaction, 0)
currency := "CNY"
currencySymbol := script.GetCommoditySymbol(ledgerConfig.Id, currency)
2022-12-27 15:55:53 +00:00
id := 0
for {
lines, err := reader.Read()
if errors.Is(err, io.EOF) {
break
} else if err != nil {
script.LogError(ledgerConfig.Mail, err.Error())
}
if len(lines) >= 13 && lines[0] != "交易日期" {
incomeAmount := formatStr(lines[8])
expensesAmount := formatStr(lines[9])
account := ""
number := ""
switch {
case incomeAmount != "":
account = "Income:"
number = strings.ReplaceAll(incomeAmount, ",", "")
case expensesAmount != "":
account = "Expenses:"
number = strings.ReplaceAll(expensesAmount, ",", "")
default:
continue
}
id++
result = append(result, Transaction{
Id: strconv.Itoa(id),
Date: formatStr(lines[0]),
Payee: formatStr(lines[12]),
Narration: formatStr(lines[1]),
Number: number,
Account: account,
Currency: currency,
CurrencySymbol: currencySymbol,
})
}
}
OK(c, result)
}
func ImportABCCSV(c *gin.Context) {
ledgerConfig := script.GetLedgerConfigFromContext(c)
file, _ := c.FormFile("file")
f, _ := file.Open()
reader := csv.NewReader(bufio.NewReader(f))
result := make([]Transaction, 0)
currency := "CNY"
currencySymbol := script.GetCommoditySymbol(ledgerConfig.Id, currency)
2022-12-27 15:55:53 +00:00
id := 0
for {
lines, err := reader.Read()
if errors.Is(err, io.EOF) {
break
} else if err != nil {
script.LogError(ledgerConfig.Mail, err.Error())
}
if len(lines) >= 11 && lines[0] != "交易日期" {
amount := formatStr(lines[2])
account := ""
number := ""
switch {
case strings.HasPrefix(amount, "+"):
account = "Income:"
number = strings.ReplaceAll(amount, "+", "")
case strings.HasPrefix(amount, "-"):
account = "Expenses:"
number = strings.ReplaceAll(amount, "-", "")
default:
continue
}
id++
date, err := time.Parse("20060102", formatStr(lines[0]))
if err != nil {
continue
}
result = append(result, Transaction{
Id: strconv.Itoa(id),
Date: date.Format("2006-01-02"),
Payee: formatStr(lines[10]),
Narration: formatStr(lines[9]),
Number: number,
Account: account,
Currency: currency,
CurrencySymbol: currencySymbol,
})
}
}
OK(c, result)
}
func formatStr(str string) string {
str = strings.Trim(str, "\t")
return strings.Trim(str, " ")
}