Use monobank api package
This commit is contained in:
parent
476191a828
commit
0f2a98ed07
10
go.mod
10
go.mod
@ -3,9 +3,15 @@ module stuzer.link/monobank-firefly3-bot
|
||||
go 1.22.2
|
||||
|
||||
require (
|
||||
gitea.stuzer.link/stuzer05/go-firefly3.git v0.0.0-20240410091455-7a9f9e825950
|
||||
gitea.stuzer.link/stuzer05/go-firefly3 v0.0.0-20240410091657-a7ef9d02ecd9
|
||||
github.com/antihax/optional v1.0.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/vtopc/go-monobank v0.21.0
|
||||
)
|
||||
|
||||
require golang.org/x/oauth2 v0.19.0 // indirect
|
||||
require (
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 // indirect
|
||||
github.com/vtopc/epoch v1.3.0 // indirect
|
||||
github.com/vtopc/go-rest v0.3.0 // indirect
|
||||
golang.org/x/oauth2 v0.19.0 // indirect
|
||||
)
|
||||
|
28
go.sum
28
go.sum
@ -1,10 +1,34 @@
|
||||
gitea.stuzer.link/stuzer05/go-firefly3.git v0.0.0-20240410091455-7a9f9e825950 h1:pVK3w7DcomY/twRVAgXors2XgiPqOM/1iudMRbDLPfs=
|
||||
gitea.stuzer.link/stuzer05/go-firefly3.git v0.0.0-20240410091455-7a9f9e825950/go.mod h1:r5Ijsq//fNw+3RqJ9XSZLtHkWxrm04G3qwR/SAjbpdY=
|
||||
gitea.stuzer.link/stuzer05/go-firefly3 v0.0.0-20240410091657-a7ef9d02ecd9 h1:YudeO7GocpdRDagqvVjbYEPXK3X2JSwYp2ZCnKyo5jQ=
|
||||
gitea.stuzer.link/stuzer05/go-firefly3 v0.0.0-20240410091657-a7ef9d02ecd9/go.mod h1:t1fQbrfn3dmJPLVsoX3Pof9/3xcSBIYpYl/Iz6qBH5E=
|
||||
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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU=
|
||||
github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 h1:3GIJYXQDAKpLEFriGFN8SbSffak10UXHGdIcFaMPykY=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0/go.mod h1:3s92l0paYkZoIHuj4X93Teg/HB7eGM9x/zokGw+u4mY=
|
||||
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/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/vtopc/epoch v1.3.0 h1:grB1J6FJVfIMbK6GY0LpOO86R4rQZ4oVwHa08USBPKA=
|
||||
github.com/vtopc/epoch v1.3.0/go.mod h1:oQJwg81RJ2bCV01D4ImQ+cwpcRDUNc66x/9A/6I2RYU=
|
||||
github.com/vtopc/go-monobank v0.21.0 h1:pW3mX7XvhJIZjJEGEzVFcPI+cD3yAIir/fFA5ei4Zlo=
|
||||
github.com/vtopc/go-monobank v0.21.0/go.mod h1:gTC/lAouMpz9WfHnXF3RC0JdEPZwnl7P4vBG+htKT3c=
|
||||
github.com/vtopc/go-rest v0.3.0 h1:kP+5UNeTVQxwRX3tXe/XByuntwZmKArv5/uMdEf1WKo=
|
||||
github.com/vtopc/go-rest v0.3.0/go.mod h1:t7XPUz57Z+U66vsVIjEm89Uw/NZf486JVAFhq6+mZps=
|
||||
golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
|
||||
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
12
http.go
12
http.go
@ -3,30 +3,30 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
monobank "github.com/vtopc/go-monobank"
|
||||
"io"
|
||||
"net/http"
|
||||
monobank "stuzer.link/monobank-firefly3-bot/monobank/api/webhook/models"
|
||||
)
|
||||
|
||||
func readRequestBody(r *http.Request) (monobank.Transaction, error) {
|
||||
func readRequestBody(r *http.Request) (monobank.WebHookResponse, error) {
|
||||
// read body bytes
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return monobank.Transaction{}, err
|
||||
return monobank.WebHookResponse{}, err
|
||||
}
|
||||
|
||||
LogString(string(body))
|
||||
|
||||
// check empty body
|
||||
if len(string(body)) == 0 {
|
||||
return monobank.Transaction{}, errors.New("empty body")
|
||||
return monobank.WebHookResponse{}, errors.New("empty body")
|
||||
}
|
||||
|
||||
// parse body
|
||||
var transaction monobank.Transaction
|
||||
var transaction monobank.WebHookResponse
|
||||
err = json.Unmarshal(body, &transaction)
|
||||
if err != nil {
|
||||
return monobank.Transaction{}, err
|
||||
return monobank.WebHookResponse{}, err
|
||||
}
|
||||
|
||||
return transaction, nil
|
||||
|
23
main.go
23
main.go
@ -1,10 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/joho/godotenv"
|
||||
monobank "github.com/vtopc/go-monobank"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -61,24 +62,12 @@ func main() {
|
||||
webhookUrl := `https://` + os.Getenv("MONOBANK_WEBHOOK_DOMAIN") + webhookLocalUrl
|
||||
|
||||
// register monobank webhook
|
||||
req, err := http.NewRequest("POST", "https://api.monobank.ua/personal/webhook", bytes.NewBuffer([]byte(`{"webHookUrl":"`+webhookUrl+`"}`)))
|
||||
monobankClient := monobank.NewPersonalClient(nil).WithAuth(monobank.NewPersonalAuthorizer(os.Getenv("MONOBANK_TOKEN")))
|
||||
err := monobankClient.SetWebHook(context.Background(), webhookUrl)
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatalln("failed to register monobank webhook")
|
||||
}
|
||||
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
req.Header.Add("X-Token", os.Getenv("MONOBANK_TOKEN"))
|
||||
|
||||
res, err := (&http.Client{}).Do(req)
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
log.Fatalf("failed to register monobank webhook")
|
||||
}
|
||||
res.Body.Close()
|
||||
|
||||
// set webhook
|
||||
http.HandleFunc(webhookLocalUrl, handleWebhook)
|
||||
|
||||
@ -87,7 +76,7 @@ func main() {
|
||||
fmt.Println("webhook url " + webhookUrl)
|
||||
err = http.ListenAndServe(os.Getenv("LISTEN"), nil)
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatalln(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
package models
|
||||
|
||||
type ClientInfo struct {
|
||||
ClientID string `json:"clientId"`
|
||||
Name string `json:"name"`
|
||||
WebHookURL string `json:"webHookUrl"`
|
||||
Permissions string `json:"permissions"`
|
||||
Accounts []Account `json:"accounts_list"`
|
||||
Jars []Jar `json:"jars"`
|
||||
}
|
||||
|
||||
type Account struct {
|
||||
ID string `json:"id"`
|
||||
SendID string `json:"sendId"`
|
||||
Balance int `json:"balance"`
|
||||
CreditLimit int `json:"creditLimit"`
|
||||
Type string `json:"type"`
|
||||
CurrencyCode int `json:"currencyCode"`
|
||||
CashbackType string `json:"cashbackType"`
|
||||
MaskedPan []string `json:"maskedPan"`
|
||||
Iban string `json:"iban"`
|
||||
}
|
||||
|
||||
type Jar struct {
|
||||
ID string `json:"id"`
|
||||
SendID string `json:"sendId"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
CurrencyCode int `json:"currencyCode"`
|
||||
Balance int `json:"balance"`
|
||||
Goal int `json:"goal"`
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"main/monobank"
|
||||
models2 "main/monobank/api/client_info/models"
|
||||
)
|
||||
|
||||
func ClientInfo() (models2.ClientInfo, error) {
|
||||
data := models2.ClientInfo{}
|
||||
|
||||
responseJson, err := monobank.Request("GET", "https://api.monobank.ua/personal/client-info", struct{}{})
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
json.Unmarshal([]byte(responseJson), &data)
|
||||
|
||||
return data, nil
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package models
|
||||
|
||||
type StatementRequest struct {
|
||||
Account string `json:"account"`
|
||||
From int `json:"from"`
|
||||
To int `json:"to"`
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package models
|
||||
|
||||
type Statement struct {
|
||||
ID string `json:"id"`
|
||||
Time int `json:"time"`
|
||||
Description string `json:"description"`
|
||||
Mcc int `json:"mcc"`
|
||||
OriginalMcc int `json:"originalMcc"`
|
||||
Hold bool `json:"hold"`
|
||||
Amount int `json:"amount"`
|
||||
OperationAmount int `json:"operationAmount"`
|
||||
CurrencyCode int `json:"currencyCode"`
|
||||
CommissionRate int `json:"commissionRate"`
|
||||
CashbackAmount int `json:"cashbackAmount"`
|
||||
Balance int `json:"balance"`
|
||||
Comment string `json:"comment"`
|
||||
ReceiptID string `json:"receiptId"`
|
||||
InvoiceID string `json:"invoiceId"`
|
||||
CounterEdrpou string `json:"counterEdrpou"`
|
||||
CounterIban string `json:"counterIban"`
|
||||
CounterName string `json:"counterName"`
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"main/monobank"
|
||||
models2 "main/monobank/api/statement/models"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func Statement(request models2.StatementRequest) ([]models2.Statement, error) {
|
||||
data := []models2.Statement{}
|
||||
|
||||
responseJson, err := monobank.Request("GET", "https://api.monobank.ua/personal/statement/"+request.Account+"/"+strconv.Itoa(request.From)+"/"+strconv.Itoa(request.To), struct{}{})
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
json.Unmarshal([]byte(responseJson), &data)
|
||||
|
||||
return data, nil
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package models
|
||||
|
||||
type Data struct {
|
||||
Account string `json:"account"`
|
||||
StatementItem StatementItem `json:"statementItem"`
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package models
|
||||
|
||||
type StatementItem struct {
|
||||
ID string `json:"id"`
|
||||
Time int `json:"time"`
|
||||
Description string `json:"description"`
|
||||
Mcc int `json:"mcc"`
|
||||
OriginalMcc int `json:"originalMcc"`
|
||||
Amount int `json:"amount"`
|
||||
OperationAmount int `json:"operationAmount"`
|
||||
CurrencyCode int `json:"currencyCode"`
|
||||
CommissionRate int `json:"commissionRate"`
|
||||
CashbackAmount int `json:"cashbackAmount"`
|
||||
Balance int `json:"balance"`
|
||||
Hold bool `json:"hold"`
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package models
|
||||
|
||||
type Transaction struct {
|
||||
Type string `json:"type"`
|
||||
Data Data `json:"data"`
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package monobank
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func Request(method string, url string, data interface{}) (string, error) {
|
||||
apiMonabankToken := os.Getenv("MONOBANK_TOKEN")
|
||||
|
||||
json, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
r, err := http.NewRequest(method, url, bytes.NewBuffer(json))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
r.Header.Add("Accept", "application/vnd.api+json")
|
||||
r.Header.Add("Content-Type", "application/json")
|
||||
r.Header.Add("X-Token", apiMonabankToken)
|
||||
|
||||
client := &http.Client{}
|
||||
res, err := client.Do(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
body, _ := io.ReadAll(res.Body)
|
||||
return string(body), nil
|
||||
}
|
31
webhook.go
31
webhook.go
@ -5,27 +5,24 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gitea.stuzer.link/stuzer05/go-firefly3.git"
|
||||
firefly3 "gitea.stuzer.link/stuzer05/go-firefly3"
|
||||
"github.com/antihax/optional"
|
||||
monobank "github.com/vtopc/go-monobank"
|
||||
"math"
|
||||
"net/http"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
monobank "stuzer.link/monobank-firefly3-bot/monobank/api/webhook/models"
|
||||
"time"
|
||||
)
|
||||
|
||||
func handleWebhook(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
|
||||
firefly3TransactionTypeWithdrawal := firefly3.WITHDRAWAL_TransactionTypeProperty
|
||||
firefly3TransactionTypeDeposit := firefly3.DEPOSIT_TransactionTypeProperty
|
||||
firefly3TransactionTypeTransfer := firefly3.TRANSFER_TransactionTypeProperty
|
||||
|
||||
// read request
|
||||
var monobankTransaction monobank.Transaction
|
||||
monobankTransaction, err = readRequestBody(r)
|
||||
monobankTransaction, err := readRequestBody(r)
|
||||
if err != nil {
|
||||
LogString(err.Error())
|
||||
w.WriteHeader(http.StatusOK)
|
||||
@ -50,11 +47,11 @@ func handleWebhook(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// find accounts
|
||||
account := ConfigGetAccountByMonobankId(config, monobankTransaction.Data.Account)
|
||||
account := ConfigGetAccountByMonobankId(config, monobankTransaction.Data.AccountID)
|
||||
|
||||
// cancel if one of account ids is empty
|
||||
if len(account.Firefly3Name) == 0 || len(account.MonobankId) == 0 {
|
||||
LogString("cannot find firefly3 or monobank ids (" + monobankTransaction.Data.Account + ")")
|
||||
LogString("cannot find firefly3 or monobank ids (" + monobankTransaction.Data.AccountID + ")")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
@ -72,7 +69,7 @@ func handleWebhook(w http.ResponseWriter, r *http.Request) {
|
||||
for _, row := range config.TransactionTypes {
|
||||
|
||||
// is refund
|
||||
if slices.Contains(row.NamesRefund, monobankTransaction.Data.StatementItem.Description) {
|
||||
if slices.Contains(row.NamesRefund, monobankTransaction.Data.Transaction.Description) {
|
||||
opts := firefly3.TransactionsApiListTransactionOpts{
|
||||
Limit: optional.NewInt32(999),
|
||||
Type_: optional.NewInterface("withdrawal"),
|
||||
@ -107,9 +104,9 @@ func handleWebhook(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// find transaction
|
||||
sum := int(math.Abs(math.Round(float64(monobankTransaction.Data.StatementItem.Amount/100)))) - int(math.Abs(math.Round(float64(monobankTransaction.Data.StatementItem.CommissionRate/100))))
|
||||
sum := int(math.Abs(math.Round(float64(monobankTransaction.Amount/100)))) - int(math.Abs(math.Round(float64(monobankTransaction.CommissionRate/100))))
|
||||
sum2, _ := strconv.ParseFloat(tRow.Amount, 64)
|
||||
if slices.Contains(row.Names, monobankTransaction.Data.StatementItem.Description) && sum == int(sum2) {
|
||||
if slices.Contains(row.Names, monobankTransaction.Description) && sum == int(sum2) {
|
||||
// delete transaction
|
||||
opts := firefly3.TransactionsApiDeleteTransactionOpts{}
|
||||
firefly3Client.TransactionsApi.DeleteTransaction(context.Background(), tRows.Id, &opts)
|
||||
@ -121,15 +118,15 @@ func handleWebhook(w http.ResponseWriter, r *http.Request) {
|
||||
break
|
||||
} else {
|
||||
// check name & mcc
|
||||
if !(slices.Contains(row.Names, monobankTransaction.Data.StatementItem.Description) || slices.Contains(row.MccCodes, monobankTransaction.Data.StatementItem.Mcc)) {
|
||||
if !(slices.Contains(row.Names, monobankTransaction.Data.Transaction.Description) || slices.Contains(row.MccCodes, int(monobankTransaction.Data.Transaction.MCC))) {
|
||||
continue
|
||||
}
|
||||
|
||||
// create firefly3 transaction
|
||||
firefly3Transaction := firefly3.TransactionSplitStore{
|
||||
Date: time.Unix(int64(monobankTransaction.Data.StatementItem.Time), 0).Add(time.Hour * 2),
|
||||
Date: time.Unix(monobankTransaction.Data.Transaction.Time.Unix(), 0).Add(time.Hour * 2),
|
||||
Notes: string(monobankTransactionJson),
|
||||
Amount: strconv.Itoa(int(math.Abs(math.Round(float64(monobankTransaction.Data.StatementItem.Amount/100)))) - int(math.Abs(math.Round(float64(monobankTransaction.Data.StatementItem.CommissionRate/100))))),
|
||||
Amount: strconv.Itoa(int(math.Abs(math.Round(float64(monobankTransaction.Data.Transaction.Amount/100)))) - int(math.Abs(math.Round(float64(monobankTransaction.Data.Transaction.CommissionRate/100))))),
|
||||
SourceName: account.Firefly3Name,
|
||||
}
|
||||
|
||||
@ -166,13 +163,13 @@ func handleWebhook(w http.ResponseWriter, r *http.Request) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if monobankTransaction.Data.StatementItem.CommissionRate > 0 {
|
||||
if monobankTransaction.Data.Transaction.CommissionRate > 0 {
|
||||
firefly3Transactions = append(firefly3Transactions, firefly3.TransactionSplitStore{
|
||||
Type_: &firefly3TransactionTypeWithdrawal,
|
||||
Date: time.Unix(int64(monobankTransaction.Data.StatementItem.Time), 0).Add(time.Hour * 2),
|
||||
Date: time.Unix(monobankTransaction.Data.Transaction.Time.Unix(), 0).Add(time.Hour * 2),
|
||||
Notes: string(monobankTransactionJson),
|
||||
Description: "Transfer fee",
|
||||
Amount: strconv.Itoa(int(math.Abs(math.Round(float64(monobankTransaction.Data.StatementItem.CommissionRate / 100))))),
|
||||
Amount: strconv.Itoa(int(math.Abs(math.Round(float64(monobankTransaction.Data.Transaction.CommissionRate / 100))))),
|
||||
SourceName: account.Firefly3Name,
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user