Continue on ynab import
This commit is contained in:
parent
7b6914e5f2
commit
1cd2eedcb8
39
http/http.go
39
http/http.go
@ -80,12 +80,51 @@ func (h *Handler) Serve() {
|
||||
{
|
||||
transaction.Use(h.verifyLoginWithRedirect)
|
||||
transaction.POST("/new", h.newTransaction)
|
||||
transaction.POST("/import/ynab", h.importYNAB)
|
||||
}
|
||||
}
|
||||
|
||||
router.Run(":1323")
|
||||
}
|
||||
|
||||
func (h *Handler) importYNAB(c *gin.Context) {
|
||||
transactionsFile, err := c.FormFile("transactions")
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
transactions, err := transactionsFile.Open()
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
budgetID, succ := c.GetPostForm("budget_id")
|
||||
if !succ {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
budgetUUID, err := uuid.Parse(budgetID)
|
||||
if !succ {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
ynab, err := NewYNABImport(h.Service.DB, budgetUUID)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = ynab.Import(transactions)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) verifyLoginWithRedirect(c *gin.Context) {
|
||||
_, err := h.verifyLogin(c)
|
||||
if err != nil {
|
||||
|
@ -3,11 +3,13 @@ package http
|
||||
import (
|
||||
"context"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"git.javil.eu/jacob1123/budgeteer/postgres"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgtype"
|
||||
)
|
||||
|
||||
type YNABImport struct {
|
||||
@ -15,9 +17,10 @@ type YNABImport struct {
|
||||
accounts []postgres.Account
|
||||
payees []postgres.Payee
|
||||
queries *postgres.Queries
|
||||
budgetID uuid.UUID
|
||||
}
|
||||
|
||||
func NewYNABImport(q *postgres.Queries) (*YNABImport, error) {
|
||||
func NewYNABImport(q *postgres.Queries, budgetID uuid.UUID) (*YNABImport, error) {
|
||||
accounts, err := q.GetAccounts(context.Background(), uuid.UUID{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -33,24 +36,26 @@ func NewYNABImport(q *postgres.Queries) (*YNABImport, error) {
|
||||
accounts: accounts,
|
||||
payees: payees,
|
||||
queries: q,
|
||||
budgetID: budgetID,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (ynab *YNABImport) Import(q *postgres.Queries, r io.Reader) error {
|
||||
func (ynab *YNABImport) Import(r io.Reader) error {
|
||||
csv := csv.NewReader(r)
|
||||
csv.Comma = '\t'
|
||||
csv.LazyQuotes = true
|
||||
|
||||
csvData, err := csv.ReadAll()
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("could not read from tsv: %w", err)
|
||||
}
|
||||
|
||||
for _, record := range csvData {
|
||||
accountName := record[0]
|
||||
account, err := ynab.GetAccount(accountName)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("could not get account %s: %w", accountName, err)
|
||||
}
|
||||
|
||||
//flag := record[1]
|
||||
@ -58,22 +63,45 @@ func (ynab *YNABImport) Import(q *postgres.Queries, r io.Reader) error {
|
||||
dateString := record[2]
|
||||
date, err := time.Parse("02.01.2006", dateString)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("could not parse date %s: %w", dateString, err)
|
||||
}
|
||||
|
||||
payee := record[3]
|
||||
category := record[4] //also in 5 + 6 split by group/category
|
||||
payeeName := record[3]
|
||||
payeeID, err := ynab.GetPayee(payeeName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get payee %s: %w", payeeName, err)
|
||||
}
|
||||
|
||||
//category := record[4] //also in 5 + 6 split by group/category
|
||||
memo := record[7]
|
||||
|
||||
outflow := record[8]
|
||||
inflow := record[9]
|
||||
cleared := record[10]
|
||||
amount := GetAmount(inflow, outflow)
|
||||
|
||||
transaction := postgres.Transaction{
|
||||
//cleared := record[10]
|
||||
|
||||
transaction := postgres.CreateTransactionParams{
|
||||
Date: date,
|
||||
Memo: memo,
|
||||
AccountID: account.ID,
|
||||
PayeeID: payeeID,
|
||||
Amount: amount,
|
||||
}
|
||||
ynab.queries.CreateTransaction(ynab.Context, transaction)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAmount(inflow string, outflow string) pgtype.Numeric {
|
||||
// Remove currency
|
||||
inflow = inflow[:len(inflow)-1]
|
||||
outflow = outflow[:len(outflow)-1]
|
||||
|
||||
num := pgtype.Numeric{}
|
||||
num.Set(inflow)
|
||||
return num
|
||||
}
|
||||
|
||||
func (ynab *YNABImport) GetAccount(name string) (*postgres.Account, error) {
|
||||
@ -92,18 +120,22 @@ func (ynab *YNABImport) GetAccount(name string) (*postgres.Account, error) {
|
||||
return &account, nil
|
||||
}
|
||||
|
||||
func (ynab *YNABImport) GetPayee(name string) (*postgres.Payee, error) {
|
||||
func (ynab *YNABImport) GetPayee(name string) (uuid.NullUUID, error) {
|
||||
if name == "" {
|
||||
return uuid.NullUUID{}, nil
|
||||
}
|
||||
|
||||
for _, pay := range ynab.payees {
|
||||
if pay.Name == name {
|
||||
return &pay, nil
|
||||
return uuid.NullUUID{UUID: pay.ID, Valid: true}, nil
|
||||
}
|
||||
}
|
||||
|
||||
payee, err := ynab.queries.CreatePayee(ynab.Context, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return uuid.NullUUID{}, err
|
||||
}
|
||||
|
||||
ynab.payees = append(ynab.payees, payee)
|
||||
return &payee, nil
|
||||
return uuid.NullUUID{UUID: payee.ID, Valid: true}, nil
|
||||
}
|
||||
|
@ -11,13 +11,18 @@ import (
|
||||
|
||||
const createAccount = `-- name: CreateAccount :one
|
||||
INSERT INTO accounts
|
||||
(name)
|
||||
VALUES ($1)
|
||||
(name, budget_id)
|
||||
VALUES ($1, $2)
|
||||
RETURNING id, budget_id, name
|
||||
`
|
||||
|
||||
func (q *Queries) CreateAccount(ctx context.Context, name string) (Account, error) {
|
||||
row := q.db.QueryRow(ctx, createAccount, name)
|
||||
type CreateAccountParams struct {
|
||||
Name string
|
||||
BudgetID uuid.UUID
|
||||
}
|
||||
|
||||
func (q *Queries) CreateAccount(ctx context.Context, arg CreateAccountParams) (Account, error) {
|
||||
row := q.db.QueryRow(ctx, createAccount, arg.Name, arg.BudgetID)
|
||||
var i Account
|
||||
err := row.Scan(&i.ID, &i.BudgetID, &i.Name)
|
||||
return i, err
|
||||
|
@ -11,13 +11,18 @@ import (
|
||||
|
||||
const createPayee = `-- name: CreatePayee :one
|
||||
INSERT INTO payees
|
||||
(name)
|
||||
VALUES ($1)
|
||||
(name, budget_id)
|
||||
VALUES ($1, $2)
|
||||
RETURNING id, budget_id, name
|
||||
`
|
||||
|
||||
func (q *Queries) CreatePayee(ctx context.Context, name string) (Payee, error) {
|
||||
row := q.db.QueryRow(ctx, createPayee, name)
|
||||
type CreatePayeeParams struct {
|
||||
Name string
|
||||
BudgetID uuid.UUID
|
||||
}
|
||||
|
||||
func (q *Queries) CreatePayee(ctx context.Context, arg CreatePayeeParams) (Payee, error) {
|
||||
row := q.db.QueryRow(ctx, createPayee, arg.Name, arg.BudgetID)
|
||||
var i Payee
|
||||
err := row.Scan(&i.ID, &i.BudgetID, &i.Name)
|
||||
return i, err
|
||||
|
@ -1,7 +1,7 @@
|
||||
-- name: CreateAccount :one
|
||||
INSERT INTO accounts
|
||||
(name)
|
||||
VALUES ($1)
|
||||
(name, budget_id)
|
||||
VALUES ($1, $2)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetAccounts :many
|
||||
|
@ -1,7 +1,7 @@
|
||||
-- name: CreatePayee :one
|
||||
INSERT INTO payees
|
||||
(name)
|
||||
VALUES ($1)
|
||||
(name, budget_id)
|
||||
VALUES ($1, $2)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetPayees :many
|
||||
|
Loading…
x
Reference in New Issue
Block a user