Add support for multi-currency transfers

This commit is contained in:
Illya Marchenko 2024-08-19 13:23:20 +03:00
parent de24343ec0
commit 1646d484fb
Signed by: stuzer05
GPG Key ID: A6ABAAA9268F9F4F
6 changed files with 40 additions and 11 deletions

@ -29,10 +29,10 @@ func ImportTransaction(monobankTransaction monobank.WebHookResponse) error {
} }
// find accounts // find accounts
account := App().Config.GetAccountByMonobankId(monobankTransaction.Data.Account) destAccount := App().Config.GetAccountByMonobankId(monobankTransaction.Data.Account)
// cancel if one of account ids is empty // cancel if one of destAccount ids is empty
if len(account.Firefly3Name) == 0 || len(account.MonobankId) == 0 { if len(destAccount.Firefly3Name) == 0 || len(destAccount.MonobankId) == 0 {
return errors.New("cannot find firefly3 or monobank ids (" + monobankTransaction.Data.Account + ")") return errors.New("cannot find firefly3 or monobank ids (" + monobankTransaction.Data.Account + ")")
} }
@ -102,7 +102,7 @@ func ImportTransaction(monobankTransaction monobank.WebHookResponse) error {
Date: time.Unix(int64(monobankTransaction.Data.StatementItem.Time), 0).Add(time.Hour * time.Duration(timezoneHoursDiff)), Date: time.Unix(int64(monobankTransaction.Data.StatementItem.Time), 0).Add(time.Hour * time.Duration(timezoneHoursDiff)),
Notes: string(monobankTransactionJson), Notes: string(monobankTransactionJson),
Amount: strconv.Itoa(int(math.Abs(math.Round(monobankTransaction.Data.StatementItem.Amount/100))) - int(math.Abs(math.Round(monobankTransaction.Data.StatementItem.CommissionRate/100)))), Amount: strconv.Itoa(int(math.Abs(math.Round(monobankTransaction.Data.StatementItem.Amount/100))) - int(math.Abs(math.Round(monobankTransaction.Data.StatementItem.CommissionRate/100)))),
SourceName: account.Firefly3Name, SourceName: destAccount.Firefly3Name,
} }
// check max sum // check max sum
@ -132,6 +132,16 @@ func ImportTransaction(monobankTransaction monobank.WebHookResponse) error {
// swap source and destination // swap source and destination
if row.Firefly3.IsUseDestinationAsSource { if row.Firefly3.IsUseDestinationAsSource {
firefly3Transaction.SourceName, firefly3Transaction.DestinationName = firefly3Transaction.DestinationName, firefly3Transaction.SourceName firefly3Transaction.SourceName, firefly3Transaction.DestinationName = firefly3Transaction.DestinationName, firefly3Transaction.SourceName
// when transfer between different currencies, convert
sourceAccount := App().Config.GetAccountByFirefly3Name(firefly3Transaction.SourceName)
if sourceAccount.Currency != destAccount.Currency {
// swap amounts
firefly3Transaction.ForeignAmount = firefly3Transaction.Amount
firefly3Transaction.Amount = strconv.Itoa(int(math.Abs(math.Round(monobankTransaction.Data.StatementItem.OperationAmount / 100))))
firefly3Transaction.ForeignCurrencyCode = destAccount.Currency
}
} }
firefly3Transactions = append(firefly3Transactions, firefly3Transaction) firefly3Transactions = append(firefly3Transactions, firefly3Transaction)
@ -145,7 +155,7 @@ func ImportTransaction(monobankTransaction monobank.WebHookResponse) error {
Notes: string(monobankTransactionJson), Notes: string(monobankTransactionJson),
Description: "Transfer fee", Description: "Transfer fee",
Amount: strconv.Itoa(int(math.Abs(math.Round(monobankTransaction.Data.StatementItem.CommissionRate / 100)))), Amount: strconv.Itoa(int(math.Abs(math.Round(monobankTransaction.Data.StatementItem.CommissionRate / 100)))),
SourceName: account.Firefly3Name, SourceName: destAccount.Firefly3Name,
}) })
} }

@ -1,18 +1,19 @@
{ {
"accounts": [ "accounts": [
{ {
"name": "Card 1",
"firefly3_id": "1", "firefly3_id": "1",
"monobank_id": "xxxxxxxxxxxxxxxxxxxxxx" "monobank_id": "xxxxxxxxxxxxxxxxxxxxxx",
"currency": "UAH"
}, },
{ {
"name": "Card 2",
"firefly3_id": "2", "firefly3_id": "2",
"monobank_id": "xxxxxxxxxxxxxxxxxxxxxx" "monobank_id": "xxxxxxxxxxxxxxxxxxxxxx",
"currency": "UAH"
}, },
{ {
"name": "Card 3", "name": "Card 3",
"firefly3_id": "3" "firefly3_id": "3",
"currency": "EUR"
} }
], ],
"transaction_types": [ "transaction_types": [

@ -8,6 +8,7 @@ type Config struct {
type ConfigAccount struct { type ConfigAccount struct {
Firefly3Name string `json:"firefly3_name,omitempty"` Firefly3Name string `json:"firefly3_name,omitempty"`
MonobankId string `json:"monobank_id,omitempty"` MonobankId string `json:"monobank_id,omitempty"`
Currency string `json:"currency,omitempty"`
} }
type ConfigTransactionTypes struct { type ConfigTransactionTypes struct {

@ -9,3 +9,13 @@ func (c *Config) GetAccountByMonobankId(q string) ConfigAccount {
return ConfigAccount{} return ConfigAccount{}
} }
func (c *Config) GetAccountByFirefly3Name(q string) ConfigAccount {
for _, row := range c.Accounts {
if row.Firefly3Name == q {
return row
}
}
return ConfigAccount{}
}

4
go.mod

@ -9,4 +9,6 @@ require (
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
) )
require golang.org/x/oauth2 v0.22.0 // indirect require (
golang.org/x/oauth2 v0.22.0 // indirect
)

5
go.sum

@ -4,10 +4,15 @@ gitea.stuzer.link/stuzer05/go-monobank v0.2303.0 h1:BDv3h9bk5Fs3iI51W+pXmjPBAQn9
gitea.stuzer.link/stuzer05/go-monobank v0.2303.0/go.mod h1:y/jOBU1U+NNR5umvDH+scrOWk0byZGZrMb4PHEehyrk= gitea.stuzer.link/stuzer05/go-monobank v0.2303.0/go.mod h1:y/jOBU1U+NNR5umvDH+scrOWk0byZGZrMb4PHEehyrk=
github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=
golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=