opti: multi commodity

This commit is contained in:
BaoXuebin 2023-12-05 16:21:12 +08:00
parent 29ca04a476
commit a40875e78b
3 changed files with 81 additions and 18 deletions

View File

@ -33,6 +33,7 @@ type Account struct {
Acc string `json:"account"` Acc string `json:"account"`
StartDate string `json:"startDate"` StartDate string `json:"startDate"`
Currency string `json:"currency,omitempty"` Currency string `json:"currency,omitempty"`
Positions []AccountPosition `json:"positions,omitempty"`
MarketNumber string `json:"marketNumber,omitempty"` MarketNumber string `json:"marketNumber,omitempty"`
MarketCurrency string `json:"marketCurrency,omitempty"` MarketCurrency string `json:"marketCurrency,omitempty"`
MarketCurrencySymbol string `json:"marketCurrencySymbol,omitempty"` MarketCurrencySymbol string `json:"marketCurrencySymbol,omitempty"`
@ -40,6 +41,12 @@ type Account struct {
Type *AccountType `json:"type,omitempty"` Type *AccountType `json:"type,omitempty"`
} }
type AccountPosition struct {
Number string `json:"number,omitempty"`
Currency string `json:"currency,omitempty"`
CurrencySymbol string `json:"currencySymbol,omitempty"`
}
type AccountType struct { type AccountType struct {
Key string `json:"key"` Key string `json:"key"`
Name string `json:"name"` Name string `json:"name"`
@ -371,11 +378,27 @@ func EqualServerSecret(secret string) bool {
func GetCommoditySymbol(commodity string) string { func GetCommoditySymbol(commodity string) string {
switch commodity { switch commodity {
case "CNY": case "CNY":
return "" return "¥"
case "USD": case "USD":
return "$" return "$"
case "EUR":
return "€"
case "JPY":
return "¥"
case "GBP":
return "£"
case "AUD":
return "$"
case "CAD":
return "$"
case "INR":
return "₹"
case "RUB":
return "₽"
case "BRL":
return "R$"
} }
return "" return commodity
} }
func GetAccountPrefix(account string) string { func GetAccountPrefix(account string) string {

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"github.com/beancount-gs/script" "github.com/beancount-gs/script"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"regexp"
"sort" "sort"
"strings" "strings"
"time" "time"
@ -24,13 +25,14 @@ func QueryValidAccount(c *gin.Context) {
type accountPosition struct { type accountPosition struct {
Account string `json:"account"` Account string `json:"account"`
MarketPosition string `json:"market_position"`
Position string `json:"position"` Position string `json:"position"`
} }
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')), '\\'", ledgerConfig.OperatingCurrency) bql := fmt.Sprintf("select '\\', account, '\\', sum(convert(value(position), '%s')) as market_position, '\\', sum(value(position)) 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 {
@ -54,18 +56,51 @@ func QueryAllAccount(c *gin.Context) {
key := account.Acc key := account.Acc
typ := script.GetAccountType(ledgerConfig.Id, key) typ := script.GetAccountType(ledgerConfig.Id, key)
account.Type = &typ account.Type = &typ
position := strings.Trim(accountPositionMap[key].Position, " ") marketPosition := strings.Trim(accountPositionMap[key].MarketPosition, " ")
if position != "" { if marketPosition != "" {
fields := strings.Fields(position) fields := strings.Fields(marketPosition)
account.MarketNumber = fields[0] account.MarketNumber = fields[0]
account.MarketCurrency = fields[1] account.MarketCurrency = fields[1]
account.MarketCurrencySymbol = script.GetCommoditySymbol(fields[1]) account.MarketCurrencySymbol = script.GetCommoditySymbol(fields[1])
} }
position := strings.Trim(accountPositionMap[key].Position, " ")
if position != "" {
account.Positions = parseAccountPositions(position)
}
result = append(result, account) result = append(result, account)
} }
OK(c, result) OK(c, result)
} }
func parseAccountPositions(input string) []script.AccountPosition {
// 使用正则表达式提取数字、货币代码和金额
re := regexp.MustCompile(`(-?\d+\.\d+) (\w+)`)
matches := re.FindAllStringSubmatch(input, -1)
var positions []script.AccountPosition
// 遍历匹配项并创建 AccountPosition
for _, match := range matches {
number := match[1]
currency := match[2]
// 获取货币符号
symbol := script.GetCommoditySymbol(currency)
// 创建 AccountPosition
position := script.AccountPosition{
Number: number,
Currency: currency,
CurrencySymbol: symbol,
}
// 添加到切片中
positions = append(positions, position)
}
return positions
}
func QueryAccountType(c *gin.Context) { func QueryAccountType(c *gin.Context) {
ledgerConfig := script.GetLedgerConfigFromContext(c) ledgerConfig := script.GetLedgerConfigFromContext(c)
accountTypes := script.GetLedgerAccountTypes(ledgerConfig.Id) accountTypes := script.GetLedgerAccountTypes(ledgerConfig.Id)

View File

@ -171,11 +171,16 @@ func saveTransaction(c *gin.Context, addTransactionForm AddTransactionForm, ledg
} else { } else {
line += fmt.Sprintf("\r\n %s %s %s", entry.Account, entry.Number.Round(2).StringFixedBank(2), account.Currency) line += fmt.Sprintf("\r\n %s %s %s", entry.Account, entry.Number.Round(2).StringFixedBank(2), account.Currency)
} }
zero := decimal.NewFromInt(0)
// 判断是否涉及多币种的转换 // 判断是否涉及多币种的转换
if account.Currency != ledgerConfig.OperatingCurrency && entry.Account != ledgerConfig.OpeningBalances { if account.Currency != ledgerConfig.OperatingCurrency && entry.Account != ledgerConfig.OpeningBalances {
autoBalance = true autoBalance = false
// 汇率值小于等于0则不进行汇率转换
if entry.Price.LessThanOrEqual(zero) {
continue
}
// 根据 number 的正负来判断是买入还是卖出 // 根据 number 的正负来判断是买入还是卖出
if entry.Number.GreaterThan(decimal.NewFromInt(0)) { if entry.Number.GreaterThan(zero) {
// {351.729 CNY, 2021-09-29} // {351.729 CNY, 2021-09-29}
line += fmt.Sprintf(" {%s %s, %s}", entry.Price, ledgerConfig.OperatingCurrency, addTransactionForm.Date) line += fmt.Sprintf(" {%s %s, %s}", entry.Price, ledgerConfig.OperatingCurrency, addTransactionForm.Date)
} else { } else {