2023-11-12 19:04:22 +00:00
|
|
|
package ynab
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2023-11-12 23:50:46 +00:00
|
|
|
"log"
|
2023-11-12 19:04:22 +00:00
|
|
|
"net/url"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Reference: https://api.ynab.com/v1#/Accounts/
|
|
|
|
|
|
|
|
type Accounts struct {
|
|
|
|
Data struct {
|
|
|
|
Account struct {
|
|
|
|
ID string `json:"id"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
Type string `json:"type"`
|
|
|
|
OnBudget bool `json:"on_budget"`
|
|
|
|
Closed bool `json:"closed"`
|
|
|
|
Note interface{} `json:"note"`
|
|
|
|
Balance int `json:"balance"`
|
|
|
|
ClearedBalance int `json:"cleared_balance"`
|
|
|
|
UnclearedBalance int `json:"uncleared_balance"`
|
|
|
|
TransferPayeeID string `json:"transfer_payee_id"`
|
|
|
|
DirectImportLinked bool `json:"direct_import_linked"`
|
|
|
|
DirectImportInError bool `json:"direct_import_in_error"`
|
|
|
|
Deleted bool `json:"deleted"`
|
|
|
|
} `json:"account"`
|
|
|
|
ServerKnowledge int `json:"server_knowledge"`
|
|
|
|
} `json:"data"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) GetAccount(accountID string) (*Accounts, error) {
|
|
|
|
response := Accounts{}
|
|
|
|
|
|
|
|
err := c.get(fmt.Sprintf("/accounts/%s", accountID), &response, url.Values{})
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to get accounts: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &response, nil
|
|
|
|
}
|
2023-11-12 23:50:46 +00:00
|
|
|
|
|
|
|
// Creates a "Capital Gains or Losses" adjustment transaction or updates an existing one if it exists to ensure the account balance
|
|
|
|
// for the accountID provided equals the balance provided
|
|
|
|
func (c *Client) SetAccountBalance(accountID string, balance int) error {
|
|
|
|
|
|
|
|
ynabTransactionID, ynabTransactionAmount, err := c.getTodayYnabCapitalGainsTransaction(accountID)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to get ynab capital gains transaction ID: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ynabAccount, err := c.GetAccount(accountID)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to get ynab account with id '%s': %v", accountID, err)
|
|
|
|
}
|
|
|
|
|
2023-11-16 03:18:18 +00:00
|
|
|
if balance == ynabAccount.Data.Account.ClearedBalance {
|
2023-11-14 01:45:35 +00:00
|
|
|
return nil // The YNAB account already has the balance we're requesting, so there is no need to do anything
|
|
|
|
}
|
|
|
|
|
2023-11-16 03:18:18 +00:00
|
|
|
balanceDelta := balance - ynabAccount.Data.Account.ClearedBalance
|
2023-11-12 23:50:46 +00:00
|
|
|
balanceDelta += ynabTransactionAmount // Take into account the existing transaction
|
|
|
|
if balanceDelta == 0 {
|
|
|
|
return nil // If balanceDelta is 0 do not create a transaction i.e. market is closed today
|
|
|
|
}
|
|
|
|
|
|
|
|
if ynabTransactionID == "" {
|
|
|
|
// there is no transaction - so create a new one
|
|
|
|
err = c.createTodayYNABCapitalGainsTransaction(accountID, balanceDelta)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to create YNAB capital gains transaction for account ID '%s': %v", accountID, err)
|
|
|
|
}
|
|
|
|
log.Printf("Creating new capital gains transaction for YNAB account '%s' for amount: %d", accountID, balanceDelta)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// there is an existing transaction - so update the existing one
|
2023-11-13 04:40:00 +00:00
|
|
|
|
2023-11-12 23:50:46 +00:00
|
|
|
err = c.updateTodayYNABCapitalGainsTransaction(accountID, ynabTransactionID, balanceDelta)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to update YNAB capital gains transaction for account ID '%s': %v", accountID, err)
|
|
|
|
}
|
|
|
|
log.Printf("Updating existing capital gains transaction for YNAB account '%s' for amount: %d", accountID, balanceDelta)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|