2021-12-12 14:42:07 +00:00
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bufio"
|
|
|
|
|
"encoding/csv"
|
2022-03-19 07:44:15 +00:00
|
|
|
"errors"
|
2021-12-12 14:42:07 +00:00
|
|
|
"github.com/beancount-gs/script"
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
"golang.org/x/text/encoding/simplifiedchinese"
|
|
|
|
|
"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"
|
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(currency)
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
lines, err := reader.Read()
|
2022-07-26 14:09:27 +00:00
|
|
|
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())
|
|
|
|
|
}
|
2022-03-19 07:44:15 +00:00
|
|
|
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
|
|
|
|
|
}
|
2022-07-26 14:09:27 +00:00
|
|
|
if transaction.Account == "" {
|
|
|
|
|
script.LogInfo(ledgerConfig.Mail, "Invalid transaction")
|
|
|
|
|
continue
|
|
|
|
|
}
|
2022-03-19 07:44:15 +00:00
|
|
|
result = append(result, transaction)
|
|
|
|
|
} else if len(lines) == 12 {
|
|
|
|
|
transaction, err := importMobileAliPayCSV(lines, currency, currencySymbol)
|
|
|
|
|
if err != nil {
|
|
|
|
|
script.LogInfo(ledgerConfig.Mail, err.Error())
|
|
|
|
|
continue
|
2021-12-12 14:42:07 +00:00
|
|
|
}
|
2022-07-26 14:09:27 +00:00
|
|
|
if transaction.Account == "" {
|
|
|
|
|
script.LogInfo(ledgerConfig.Mail, "Invalid transaction")
|
|
|
|
|
continue
|
|
|
|
|
}
|
2022-03-19 07:44:15 +00:00
|
|
|
result = append(result, transaction)
|
2021-12-12 14:42:07 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OK(c, result)
|
|
|
|
|
}
|
2021-12-14 13:24:39 +00:00
|
|
|
|
2022-03-19 07:44:15 +00:00
|
|
|
func importBrowserAliPayCSV(lines []string, currency string, currencySymbol string) (Transaction, error) {
|
|
|
|
|
dateColumn := strings.Fields(lines[2])
|
|
|
|
|
status := strings.Trim(lines[15], " ")
|
|
|
|
|
account := ""
|
2022-07-26 14:09:27 +00:00
|
|
|
if status == "" {
|
|
|
|
|
account = ""
|
|
|
|
|
} else if status == "已收入" {
|
2022-03-19 07:44:15 +00:00
|
|
|
account = "Income:"
|
|
|
|
|
} else {
|
|
|
|
|
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[10])
|
|
|
|
|
status := strings.Trim(lines[0], " ")
|
|
|
|
|
account := ""
|
2022-07-26 14:09:27 +00:00
|
|
|
if status == "" {
|
|
|
|
|
account = ""
|
|
|
|
|
} else if status == "支出" {
|
2022-03-19 07:44:15 +00:00
|
|
|
account = "Expenses:"
|
|
|
|
|
} else {
|
|
|
|
|
account = "Income:"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(dateColumn) >= 2 {
|
|
|
|
|
return Transaction{
|
|
|
|
|
Id: strings.Trim(lines[8], " "),
|
|
|
|
|
Date: strings.Trim(dateColumn[0], " "),
|
|
|
|
|
Payee: strings.Trim(lines[1], " "),
|
|
|
|
|
Narration: strings.Trim(lines[3], " "),
|
|
|
|
|
Number: strings.Trim(lines[5], " "),
|
|
|
|
|
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(currency)
|
|
|
|
|
|
|
|
|
|
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 := ""
|
|
|
|
|
if status == "收入" {
|
|
|
|
|
account = "Income:"
|
|
|
|
|
} else if status == "支出" {
|
|
|
|
|
account = "Expenses:"
|
|
|
|
|
} else {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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(currency)
|
|
|
|
|
|
|
|
|
|
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(currency)
|
|
|
|
|
|
|
|
|
|
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, " ")
|
|
|
|
|
}
|