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

@ -30,14 +30,21 @@ type Config struct {
}
type Account struct {
Acc string `json:"account"`
StartDate string `json:"startDate"`
Currency string `json:"currency,omitempty"`
MarketNumber string `json:"marketNumber,omitempty"`
MarketCurrency string `json:"marketCurrency,omitempty"`
MarketCurrencySymbol string `json:"marketCurrencySymbol,omitempty"`
EndDate string `json:"endDate,omitempty"`
Type *AccountType `json:"type,omitempty"`
Acc string `json:"account"`
StartDate string `json:"startDate"`
Currency string `json:"currency,omitempty"`
Positions []AccountPosition `json:"positions,omitempty"`
MarketNumber string `json:"marketNumber,omitempty"`
MarketCurrency string `json:"marketCurrency,omitempty"`
MarketCurrencySymbol string `json:"marketCurrencySymbol,omitempty"`
EndDate string `json:"endDate,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 {
@ -371,11 +378,27 @@ func EqualServerSecret(secret string) bool {
func GetCommoditySymbol(commodity string) string {
switch commodity {
case "CNY":
return ""
return "¥"
case "USD":
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 {

View File

@ -5,6 +5,7 @@ import (
"fmt"
"github.com/beancount-gs/script"
"github.com/gin-gonic/gin"
"regexp"
"sort"
"strings"
"time"
@ -23,14 +24,15 @@ func QueryValidAccount(c *gin.Context) {
}
type accountPosition struct {
Account string `json:"account"`
Position string `json:"position"`
Account string `json:"account"`
MarketPosition string `json:"market_position"`
Position string `json:"position"`
}
func QueryAllAccount(c *gin.Context) {
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)
err := script.BQLQueryListByCustomSelect(ledgerConfig, bql, nil, &accountPositions)
if err != nil {
@ -54,18 +56,51 @@ func QueryAllAccount(c *gin.Context) {
key := account.Acc
typ := script.GetAccountType(ledgerConfig.Id, key)
account.Type = &typ
position := strings.Trim(accountPositionMap[key].Position, " ")
if position != "" {
fields := strings.Fields(position)
marketPosition := strings.Trim(accountPositionMap[key].MarketPosition, " ")
if marketPosition != "" {
fields := strings.Fields(marketPosition)
account.MarketNumber = fields[0]
account.MarketCurrency = fields[1]
account.MarketCurrencySymbol = script.GetCommoditySymbol(fields[1])
}
position := strings.Trim(accountPositionMap[key].Position, " ")
if position != "" {
account.Positions = parseAccountPositions(position)
}
result = append(result, account)
}
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) {
ledgerConfig := script.GetLedgerConfigFromContext(c)
accountTypes := script.GetLedgerAccountTypes(ledgerConfig.Id)

View File

@ -171,11 +171,16 @@ func saveTransaction(c *gin.Context, addTransactionForm AddTransactionForm, ledg
} else {
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 {
autoBalance = true
autoBalance = false
// 汇率值小于等于0则不进行汇率转换
if entry.Price.LessThanOrEqual(zero) {
continue
}
// 根据 number 的正负来判断是买入还是卖出
if entry.Number.GreaterThan(decimal.NewFromInt(0)) {
if entry.Number.GreaterThan(zero) {
// {351.729 CNY, 2021-09-29}
line += fmt.Sprintf(" {%s %s, %s}", entry.Price, ledgerConfig.OperatingCurrency, addTransactionForm.Date)
} else {