package ynab import ( "fmt" "net/url" "time" ) // Reference: https://api.ynab.com/v1#/Transactions/ type BaseTransaction struct { Type string `json:"type,omitempty"` ParentTransactionID interface{} `json:"parent_transaction_id,omitempty"` ID string `json:"id,omitempty"` Date string `json:"date,omitempty"` Amount int `json:"amount,omitempty"` Memo string `json:"memo,omitempty"` Cleared string `json:"cleared,omitempty"` Approved bool `json:"approved,omitempty"` FlagColor interface{} `json:"flag_color,omitempty"` AccountID string `json:"account_id,omitempty"` AccountName string `json:"account_name,omitempty"` PayeeID string `json:"payee_id,omitempty"` PayeeName string `json:"payee_name,omitempty"` CategoryID string `json:"category_id,omitempty"` CategoryName string `json:"category_name,omitempty"` TransferAccountID interface{} `json:"transfer_account_id,omitempty"` TransferTransactionID interface{} `json:"transfer_transaction_id,omitempty"` MatchedTransactionID interface{} `json:"matched_transaction_id,omitempty"` ImportID string `json:"import_id,omitempty"` Deleted bool `json:"deleted,omitempty"` } // Used for single transaction responses type Transaction struct { Data struct { TransactionIDs []string `json:"transaction_ids,omitempty"` Transaction BaseTransaction `json:"transaction"` ServerKnowledge int `json:"server_knowledge,omitempty"` } } // Used for single transaction requests type TransactionRequest struct { Transaction BaseTransaction `json:"transaction,omitempty"` } // Used for multiple transaction requests / responses type Transactions struct { Data struct { Transactions []BaseTransaction `json:"transactions"` ServerKnowledge int `json:"server_knowledge"` } `json:"data"` } // Accepts a YNAB account ID and timestamp and returns all transactions in that account // since the date provided func (c *Client) GetAccountTransactions(accountID string, sinceDate time.Time) (*Transactions, error) { response := Transactions{} urlQuery := url.Values{} urlQuery.Add("since_date", sinceDate.Format("2006-01-02")) err := c.get(fmt.Sprintf("/accounts/%s/transactions", accountID), &response, urlQuery) if err != nil { return nil, fmt.Errorf("failed to get account transactions: %v", err) } return &response, nil } // Accepts a YNAB account ID and returns the transaction ID, amount and an error for the // the first transaction found with Payee Name "Capital Gains or Losses" func (c *Client) GetTodayYnabCapitalGainsTransaction(accountID string) (string, int, error) { ynabTransactions, err := c.GetAccountTransactions(accountID, time.Now()) if err != nil { return "", 0, fmt.Errorf("failed to get ynab transactions: %v", err) } for _, transaction := range ynabTransactions.Data.Transactions { if transaction.PayeeName != "Capital Gains or Losses" { continue } return transaction.ID, transaction.Amount, nil } return "", 0, nil } // Accepts a YNAB account ID and transaction amount and creates a new YNAB transaction func (c *Client) CreateTodayYNABCapitalGainsTransaction(accountID string, amount int) error { transaction := TransactionRequest{} transaction.Transaction.AccountID = accountID transaction.Transaction.Amount = amount transaction.Transaction.Date = time.Now().Format("2006-01-02") transaction.Transaction.Cleared = "cleared" transaction.Transaction.Approved = true transaction.Transaction.PayeeName = "Capital Gains or Losses" response := &Transaction{} err := c.post("/transactions", response, transaction) if err != nil { return fmt.Errorf("failed to post transaction: %v", err) } return nil } // Accepts a YNAB account ID, transaction ID and transaction amount and updates the YNAB transaction with the matching ID func (c *Client) UpdateTodayYNABCapitalGainsTransaction(accountID string, transactionID string, amount int) error { transaction := TransactionRequest{} transaction.Transaction.AccountID = accountID transaction.Transaction.ID = transactionID transaction.Transaction.Amount = amount transaction.Transaction.Date = time.Now().Format("2006-01-02") transaction.Transaction.Cleared = "cleared" transaction.Transaction.Approved = true transaction.Transaction.PayeeName = "Capital Gains or Losses" response := &Transaction{} err := c.put(fmt.Sprintf("/transactions/%s", transactionID), response, transaction) if err != nil { return fmt.Errorf("failed to put transaction: %v", err) } return nil }