Import category

This commit is contained in:
Jan Bader 2021-12-06 20:19:38 +00:00
parent 674028d394
commit 495bc2b7c3
7 changed files with 274 additions and 32 deletions

View File

@ -14,11 +14,13 @@ import (
) )
type YNABImport struct { type YNABImport struct {
Context context.Context Context context.Context
accounts []postgres.Account accounts []postgres.Account
payees []postgres.Payee payees []postgres.Payee
queries *postgres.Queries categories []postgres.GetCategoriesRow
budgetID uuid.UUID categoryGroups []postgres.CategoryGroup
queries *postgres.Queries
budgetID uuid.UUID
} }
func NewYNABImport(q *postgres.Queries, budgetID uuid.UUID) (*YNABImport, error) { func NewYNABImport(q *postgres.Queries, budgetID uuid.UUID) (*YNABImport, error) {
@ -32,12 +34,24 @@ func NewYNABImport(q *postgres.Queries, budgetID uuid.UUID) (*YNABImport, error)
return nil, err return nil, err
} }
categories, err := q.GetCategories(context.Background(), budgetID)
if err != nil {
return nil, err
}
categoryGroups, err := q.GetCategoryGroups(context.Background(), budgetID)
if err != nil {
return nil, err
}
return &YNABImport{ return &YNABImport{
Context: context.Background(), Context: context.Background(),
accounts: accounts, accounts: accounts,
payees: payees, payees: payees,
queries: q, categories: categories,
budgetID: budgetID, categoryGroups: categoryGroups,
queries: q,
budgetID: budgetID,
}, nil }, nil
} }
@ -74,7 +88,12 @@ func (ynab *YNABImport) Import(r io.Reader) error {
return fmt.Errorf("could not get payee %s: %w", payeeName, err) return fmt.Errorf("could not get payee %s: %w", payeeName, err)
} }
//category := record[4] //also in 5 + 6 split by group/category categoryGroup, categoryName := record[5], record[6] //also in 5 + 6 split by group/category
category, err := ynab.GetCategory(categoryGroup, categoryName)
if err != nil {
return fmt.Errorf("could not get category %s: %w", payeeName, err)
}
memo := record[7] memo := record[7]
outflow := record[8] outflow := record[8]
@ -87,11 +106,12 @@ func (ynab *YNABImport) Import(r io.Reader) error {
//cleared := record[10] //cleared := record[10]
transaction := postgres.CreateTransactionParams{ transaction := postgres.CreateTransactionParams{
Date: date, Date: date,
Memo: memo, Memo: memo,
AccountID: account.ID, AccountID: account.ID,
PayeeID: payeeID, PayeeID: payeeID,
Amount: amount, CategoryID: category,
Amount: amount,
} }
_, err = ynab.queries.CreateTransaction(ynab.Context, transaction) _, err = ynab.queries.CreateTransaction(ynab.Context, transaction)
if err != nil { if err != nil {
@ -172,3 +192,54 @@ func (ynab *YNABImport) GetPayee(name string) (uuid.NullUUID, error) {
ynab.payees = append(ynab.payees, payee) ynab.payees = append(ynab.payees, payee)
return uuid.NullUUID{UUID: payee.ID, Valid: true}, nil return uuid.NullUUID{UUID: payee.ID, Valid: true}, nil
} }
func (ynab *YNABImport) GetCategory(group string, name string) (uuid.NullUUID, error) {
if group == "" || name == "" {
return uuid.NullUUID{}, nil
}
for _, category := range ynab.categories {
if category.Name == name && category.Group == group {
return uuid.NullUUID{UUID: category.ID, Valid: true}, nil
}
}
for _, categoryGroup := range ynab.categoryGroups {
if categoryGroup.Name == group {
createCategory := postgres.CreateCategoryParams{Name: name, CategoryGroupID: categoryGroup.ID}
category, err := ynab.queries.CreateCategory(ynab.Context, createCategory)
if err != nil {
return uuid.NullUUID{}, err
}
getCategory := postgres.GetCategoriesRow{
ID: category.ID,
CategoryGroupID: category.CategoryGroupID,
Name: category.Name,
Group: categoryGroup.Name,
}
ynab.categories = append(ynab.categories, getCategory)
return uuid.NullUUID{UUID: category.ID, Valid: true}, nil
}
}
categoryGroup, err := ynab.queries.CreateCategoryGroup(ynab.Context, postgres.CreateCategoryGroupParams{Name: name, BudgetID: ynab.budgetID})
if err != nil {
return uuid.NullUUID{}, err
}
ynab.categoryGroups = append(ynab.categoryGroups, categoryGroup)
category, err := ynab.queries.CreateCategory(ynab.Context, postgres.CreateCategoryParams{Name: name, CategoryGroupID: categoryGroup.ID})
if err != nil {
return uuid.NullUUID{}, err
}
getCategory := postgres.GetCategoriesRow{
ID: category.ID,
CategoryGroupID: category.CategoryGroupID,
Name: category.Name,
Group: categoryGroup.Name,
}
ynab.categories = append(ynab.categories, getCategory)
return uuid.NullUUID{UUID: category.ID, Valid: true}, nil
}

117
postgres/categories.sql.go Normal file
View File

@ -0,0 +1,117 @@
// Code generated by sqlc. DO NOT EDIT.
// source: categories.sql
package postgres
import (
"context"
"github.com/google/uuid"
)
const createCategory = `-- name: CreateCategory :one
INSERT INTO categories
(name, category_group_id)
VALUES ($1, $2)
RETURNING id, category_group_id, name
`
type CreateCategoryParams struct {
Name string
CategoryGroupID uuid.UUID
}
func (q *Queries) CreateCategory(ctx context.Context, arg CreateCategoryParams) (Category, error) {
row := q.db.QueryRowContext(ctx, createCategory, arg.Name, arg.CategoryGroupID)
var i Category
err := row.Scan(&i.ID, &i.CategoryGroupID, &i.Name)
return i, err
}
const createCategoryGroup = `-- name: CreateCategoryGroup :one
INSERT INTO category_groups
(name, budget_id)
VALUES ($1, $2)
RETURNING id, budget_id, name
`
type CreateCategoryGroupParams struct {
Name string
BudgetID uuid.UUID
}
func (q *Queries) CreateCategoryGroup(ctx context.Context, arg CreateCategoryGroupParams) (CategoryGroup, error) {
row := q.db.QueryRowContext(ctx, createCategoryGroup, arg.Name, arg.BudgetID)
var i CategoryGroup
err := row.Scan(&i.ID, &i.BudgetID, &i.Name)
return i, err
}
const getCategories = `-- name: GetCategories :many
SELECT categories.id, categories.category_group_id, categories.name, category_groups.name as group FROM categories
INNER JOIN category_groups ON categories.category_group_id = category_groups.id
WHERE category_groups.budget_id = $1
`
type GetCategoriesRow struct {
ID uuid.UUID
CategoryGroupID uuid.UUID
Name string
Group string
}
func (q *Queries) GetCategories(ctx context.Context, budgetID uuid.UUID) ([]GetCategoriesRow, error) {
rows, err := q.db.QueryContext(ctx, getCategories, budgetID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetCategoriesRow
for rows.Next() {
var i GetCategoriesRow
if err := rows.Scan(
&i.ID,
&i.CategoryGroupID,
&i.Name,
&i.Group,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getCategoryGroups = `-- name: GetCategoryGroups :many
SELECT category_groups.id, category_groups.budget_id, category_groups.name FROM category_groups
WHERE category_groups.budget_id = $1
`
func (q *Queries) GetCategoryGroups(ctx context.Context, budgetID uuid.UUID) ([]CategoryGroup, error) {
rows, err := q.db.QueryContext(ctx, getCategoryGroups, budgetID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []CategoryGroup
for rows.Next() {
var i CategoryGroup
if err := rows.Scan(&i.ID, &i.BudgetID, &i.Name); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

View File

@ -21,6 +21,18 @@ type Budget struct {
LastModification sql.NullTime LastModification sql.NullTime
} }
type Category struct {
ID uuid.UUID
CategoryGroupID uuid.UUID
Name string
}
type CategoryGroup struct {
ID uuid.UUID
BudgetID uuid.UUID
Name string
}
type Payee struct { type Payee struct {
ID uuid.UUID ID uuid.UUID
BudgetID uuid.UUID BudgetID uuid.UUID
@ -28,12 +40,13 @@ type Payee struct {
} }
type Transaction struct { type Transaction struct {
ID uuid.UUID ID uuid.UUID
Date time.Time Date time.Time
Memo string Memo string
Amount Numeric Amount Numeric
AccountID uuid.UUID AccountID uuid.UUID
PayeeID uuid.NullUUID CategoryID uuid.NullUUID
PayeeID uuid.NullUUID
} }
type User struct { type User struct {

View File

@ -0,0 +1,20 @@
-- name: CreateCategoryGroup :one
INSERT INTO category_groups
(name, budget_id)
VALUES ($1, $2)
RETURNING *;
-- name: GetCategoryGroups :many
SELECT category_groups.* FROM category_groups
WHERE category_groups.budget_id = $1;
-- name: CreateCategory :one
INSERT INTO categories
(name, category_group_id)
VALUES ($1, $2)
RETURNING *;
-- name: GetCategories :many
SELECT categories.*, category_groups.name as group FROM categories
INNER JOIN category_groups ON categories.category_group_id = category_groups.id
WHERE category_groups.budget_id = $1;

View File

@ -1,7 +1,7 @@
-- name: CreateTransaction :one -- name: CreateTransaction :one
INSERT INTO transactions INSERT INTO transactions
(date, memo, amount, account_id, payee_id) (date, memo, amount, account_id, payee_id, category_id)
VALUES ($1, $2, $3, $4, $5) VALUES ($1, $2, $3, $4, $5, $6)
RETURNING *; RETURNING *;
-- name: GetTransactionsForBudget :many -- name: GetTransactionsForBudget :many

View File

@ -33,6 +33,7 @@ CREATE TABLE payees (
budget_id uuid NOT NULL, budget_id uuid NOT NULL,
name varchar(50) NOT NULL name varchar(50) NOT NULL
); );
ALTER TABLE "payees" ADD FOREIGN KEY ("budget_id") REFERENCES "budgets" ("id");
CREATE TABLE transactions ( CREATE TABLE transactions (
id uuid DEFAULT uuid_generate_v4() PRIMARY KEY, id uuid DEFAULT uuid_generate_v4() PRIMARY KEY,
@ -40,10 +41,27 @@ CREATE TABLE transactions (
memo text NOT NULL, memo text NOT NULL,
amount decimal(12,2) NOT NULL, amount decimal(12,2) NOT NULL,
account_id uuid NOT NULL, account_id uuid NOT NULL,
category_id uuid,
payee_id uuid payee_id uuid
); );
ALTER TABLE "transactions" ADD FOREIGN KEY ("account_id") REFERENCES "accounts" ("id"); ALTER TABLE "transactions" ADD FOREIGN KEY ("account_id") REFERENCES "accounts" ("id");
ALTER TABLE "transactions" ADD FOREIGN KEY ("payee_id") REFERENCES "payees" ("id"); ALTER TABLE "transactions" ADD FOREIGN KEY ("payee_id") REFERENCES "payees" ("id");
ALTER TABLE "transactions" ADD FOREIGN KEY ("category_id") REFERENCES "categories" ("id");
CREATE TABLE category_groups (
id uuid DEFAULT uuid_generate_v4() PRIMARY KEY,
budget_id uuid NOT NULL,
name varchar(50) NOT NULL
);
ALTER TABLE "category_groups" ADD FOREIGN KEY ("budget_id") REFERENCES "budgets" ("id");
CREATE TABLE categories (
id uuid DEFAULT uuid_generate_v4() PRIMARY KEY,
category_group_id uuid NOT NULL,
name varchar(50) NOT NULL
);
ALTER TABLE "categories" ADD FOREIGN KEY ("category_group_id") REFERENCES "category_group" ("id");
-- +goose Down -- +goose Down
DROP TABLE transactions; DROP TABLE transactions;

View File

@ -12,17 +12,18 @@ import (
const createTransaction = `-- name: CreateTransaction :one const createTransaction = `-- name: CreateTransaction :one
INSERT INTO transactions INSERT INTO transactions
(date, memo, amount, account_id, payee_id) (date, memo, amount, account_id, payee_id, category_id)
VALUES ($1, $2, $3, $4, $5) VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, date, memo, amount, account_id, payee_id RETURNING id, date, memo, amount, account_id, category_id, payee_id
` `
type CreateTransactionParams struct { type CreateTransactionParams struct {
Date time.Time Date time.Time
Memo string Memo string
Amount Numeric Amount Numeric
AccountID uuid.UUID AccountID uuid.UUID
PayeeID uuid.NullUUID PayeeID uuid.NullUUID
CategoryID uuid.NullUUID
} }
func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionParams) (Transaction, error) { func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionParams) (Transaction, error) {
@ -32,6 +33,7 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
arg.Amount, arg.Amount,
arg.AccountID, arg.AccountID,
arg.PayeeID, arg.PayeeID,
arg.CategoryID,
) )
var i Transaction var i Transaction
err := row.Scan( err := row.Scan(
@ -40,6 +42,7 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
&i.Memo, &i.Memo,
&i.Amount, &i.Amount,
&i.AccountID, &i.AccountID,
&i.CategoryID,
&i.PayeeID, &i.PayeeID,
) )
return i, err return i, err