opti: multi commodity
This commit is contained in:
parent
29ca04a476
commit
a40875e78b
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue