Files
fgueryandGitHub 9b637f957e feat(EN-186): save balances via Tink and Plaid plugins (#559)
* feat: added fetchBalances capability to Tink

* chore: quick refacto of fetch_open_banking_data for clarity

* chore: start on splitting fetch_open_banking_data between components

* chore: revert change on handle_webhook

* feat: added DataToFetch field to the fetchOpenBankingData to support fetching balance (by different ways too)

* feat: fetch balance from accounts api

* fix: try to store psuID and connectionID in account

* chore: improve docker env

* feat: balances work now, but PSPBalance does not have psuID + connectionID

* feat: make sure we store PSUID for balances as well

* feat(EN-185): handle Plaid balances from accounts

* feat: fix up plaid balance fetching

* fix: air rebuilding was sometime failing; this aims to fix it

* fix: linting

* fix: update go version to be the same as the docker image

* chore: remove unused go install flags

* fix: make OpenBankingDataToFetchAccountsAndBalances test a bit more explicit

* fix: added extra null checks as required

* chore: remove duplicated test

* fix: code review comments

* fix: improve translate_plaid_amount to also return asset

* chore: added tests for amount_utils

* fix: make fetch open banking activity fail when child workflow fail
2025-10-07 10:15:07 +00:00

73 lines
1.9 KiB
Go

package plaid
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/formancehq/payments/internal/connectors/plugins/public/plaid/client"
"github.com/formancehq/payments/internal/models"
"github.com/plaid/plaid-go/v34/plaid"
)
func (p *Plugin) fetchNextBalances(ctx context.Context, req models.FetchNextBalancesRequest) (models.FetchNextBalancesResponse, error) {
var pspAccount models.PSPAccount
if err := json.Unmarshal(req.FromPayload, &pspAccount); err != nil {
return models.FetchNextBalancesResponse{}, err
}
pspBalance, err := toPSPBalance(pspAccount)
if err != nil {
return models.FetchNextBalancesResponse{}, err
}
pspBalances := make([]models.PSPBalance, 0, 1)
pspBalances = append(pspBalances, pspBalance)
return models.FetchNextBalancesResponse{
Balances: pspBalances,
}, nil
}
func toPSPBalance(
pspAccount models.PSPAccount,
) (models.PSPBalance, error) {
var account plaid.AccountBase
if err := json.Unmarshal(pspAccount.Raw, &account); err != nil {
return models.PSPBalance{}, err
}
balance := account.Balances
if !balance.Current.IsSet() || balance.Current.Get() == nil {
return models.PSPBalance{}, fmt.Errorf("balance is not set")
}
amountF := *balance.Current.Get()
var curr string
if balance.IsoCurrencyCode.IsSet() && balance.IsoCurrencyCode.Get() != nil {
curr = *balance.IsoCurrencyCode.Get()
} else {
curr = balance.GetUnofficialCurrencyCode()
}
amount, assetName, err := client.TranslatePlaidAmount(amountF, curr)
if err != nil {
return models.PSPBalance{}, err
}
lastUpdated := balance.GetLastUpdatedDatetime()
if lastUpdated.IsZero() {
lastUpdated = time.Now()
}
return models.PSPBalance{
AccountReference: account.AccountId,
CreatedAt: lastUpdated.UTC(),
Amount: amount,
Asset: assetName,
PsuID: pspAccount.PsuID,
OpenBankingConnectionID: pspAccount.OpenBankingConnectionID,
}, nil
}