From d89a8f4e2ede65791cfafa61ea2b238f53ae8f72 Mon Sep 17 00:00:00 2001 From: Jan Bader Date: Wed, 23 Feb 2022 14:47:40 +0000 Subject: [PATCH 1/8] Switch between payees and accounts depending on prefix --- postgres/accounts.sql.go | 41 +++++++++++++++++++++++++++++++++++ postgres/queries/accounts.sql | 6 +++++ server/autocomplete.go | 39 ++++++++++++++++++++++++--------- 3 files changed, 76 insertions(+), 10 deletions(-) diff --git a/postgres/accounts.sql.go b/postgres/accounts.sql.go index 50d1a5b..c50bc8f 100644 --- a/postgres/accounts.sql.go +++ b/postgres/accounts.sql.go @@ -127,3 +127,44 @@ func (q *Queries) GetAccountsWithBalance(ctx context.Context, budgetID uuid.UUID } return items, nil } + +const searchAccounts = `-- name: SearchAccounts :many +SELECT accounts.id, accounts.budget_id, accounts.name FROM accounts +WHERE accounts.budget_id = $1 +AND accounts.name LIKE $2 +ORDER BY accounts.name +` + +type SearchAccountsParams struct { + BudgetID uuid.UUID + Search string +} + +type SearchAccountsRow struct { + ID uuid.UUID + BudgetID uuid.UUID + Name string +} + +func (q *Queries) SearchAccounts(ctx context.Context, arg SearchAccountsParams) ([]SearchAccountsRow, error) { + rows, err := q.db.QueryContext(ctx, searchAccounts, arg.BudgetID, arg.Search) + if err != nil { + return nil, err + } + defer rows.Close() + var items []SearchAccountsRow + for rows.Next() { + var i SearchAccountsRow + 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 +} diff --git a/postgres/queries/accounts.sql b/postgres/queries/accounts.sql index fb48404..a7b969e 100644 --- a/postgres/queries/accounts.sql +++ b/postgres/queries/accounts.sql @@ -19,4 +19,10 @@ FROM accounts LEFT JOIN transactions ON transactions.account_id = accounts.id AND transactions.date < NOW() WHERE accounts.budget_id = $1 GROUP BY accounts.id, accounts.name +ORDER BY accounts.name; + +-- name: SearchAccounts :many +SELECT accounts.id, accounts.budget_id, accounts.name FROM accounts +WHERE accounts.budget_id = @budget_id +AND accounts.name LIKE @search ORDER BY accounts.name; \ No newline at end of file diff --git a/server/autocomplete.go b/server/autocomplete.go index 46dfb3c..5472430 100644 --- a/server/autocomplete.go +++ b/server/autocomplete.go @@ -2,6 +2,7 @@ package server import ( "net/http" + "strings" "git.javil.eu/jacob1123/budgeteer/postgres" "github.com/gin-gonic/gin" @@ -39,15 +40,33 @@ func (h *Handler) autocompletePayee(c *gin.Context) { } query := c.Request.URL.Query().Get("s") - searchParams := postgres.SearchPayeesParams{ - BudgetID: budgetUUID, - Search: query + "%", - } - payees, err := h.Service.SearchPayees(c.Request.Context(), searchParams) - if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) - return - } - c.JSON(http.StatusOK, payees) + transferPrefix := "Transfer" + if strings.HasPrefix(query, transferPrefix) { + searchParams := postgres.SearchAccountsParams{ + BudgetID: budgetUUID, + Search: "%" + strings.Trim(query[len(transferPrefix):], " \t\n:") + "%", + } + + accounts, err := h.Service.SearchAccounts(c.Request.Context(), searchParams) + if err != nil { + c.AbortWithError(http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, accounts) + } else { + searchParams := postgres.SearchPayeesParams{ + BudgetID: budgetUUID, + Search: query + "%", + } + + payees, err := h.Service.SearchPayees(c.Request.Context(), searchParams) + if err != nil { + c.AbortWithError(http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, payees) + } } From 28c20aacd38ae8d4cd73996b6ee59ddd72acb60b Mon Sep 17 00:00:00 2001 From: Jan Bader Date: Wed, 23 Feb 2022 21:30:28 +0000 Subject: [PATCH 2/8] Extract package --- postgres/accounts.sql.go | 3 ++- postgres/assignments.sql.go | 5 ++-- postgres/cumultative-balances.sql.go | 9 ++++--- postgres/models.go | 5 ++-- postgres/{ => numeric}/numeric.go | 30 ++++++++++++++++++++-- postgres/transactions.sql.go | 9 ++++--- postgres/ynab-export.go | 9 ++++--- postgres/ynab-import.go | 38 +++++----------------------- server/budgeting.go | 33 ++++++++++++------------ server/transaction.go | 3 ++- sqlc.yaml | 6 +++-- 11 files changed, 81 insertions(+), 69 deletions(-) rename postgres/{ => numeric}/numeric.go (85%) diff --git a/postgres/accounts.sql.go b/postgres/accounts.sql.go index c50bc8f..4d15658 100644 --- a/postgres/accounts.sql.go +++ b/postgres/accounts.sql.go @@ -6,6 +6,7 @@ package postgres import ( "context" + "git.javil.eu/jacob1123/budgeteer/postgres/numeric" "github.com/google/uuid" ) @@ -97,7 +98,7 @@ type GetAccountsWithBalanceRow struct { ID uuid.UUID Name string OnBudget bool - Balance Numeric + Balance numeric.Numeric } func (q *Queries) GetAccountsWithBalance(ctx context.Context, budgetID uuid.UUID) ([]GetAccountsWithBalanceRow, error) { diff --git a/postgres/assignments.sql.go b/postgres/assignments.sql.go index 0689a18..8602e7a 100644 --- a/postgres/assignments.sql.go +++ b/postgres/assignments.sql.go @@ -7,6 +7,7 @@ import ( "context" "time" + "git.javil.eu/jacob1123/budgeteer/postgres/numeric" "github.com/google/uuid" ) @@ -21,7 +22,7 @@ RETURNING id, category_id, date, memo, amount type CreateAssignmentParams struct { Date time.Time - Amount Numeric + Amount numeric.Numeric CategoryID uuid.UUID } @@ -65,7 +66,7 @@ type GetAllAssignmentsRow struct { Date time.Time Category string Group string - Amount Numeric + Amount numeric.Numeric } func (q *Queries) GetAllAssignments(ctx context.Context, budgetID uuid.UUID) ([]GetAllAssignmentsRow, error) { diff --git a/postgres/cumultative-balances.sql.go b/postgres/cumultative-balances.sql.go index bad7a53..3b4b636 100644 --- a/postgres/cumultative-balances.sql.go +++ b/postgres/cumultative-balances.sql.go @@ -7,6 +7,7 @@ import ( "context" "time" + "git.javil.eu/jacob1123/budgeteer/postgres/numeric" "github.com/google/uuid" ) @@ -23,10 +24,10 @@ ORDER BY COALESCE(ass.date, tra.date), COALESCE(ass.category_id, tra.category_id type GetCumultativeBalancesRow struct { Date time.Time CategoryID uuid.UUID - Assignments Numeric - AssignmentsCum Numeric - Transactions Numeric - TransactionsCum Numeric + Assignments numeric.Numeric + AssignmentsCum numeric.Numeric + Transactions numeric.Numeric + TransactionsCum numeric.Numeric } func (q *Queries) GetCumultativeBalances(ctx context.Context, budgetID uuid.UUID) ([]GetCumultativeBalancesRow, error) { diff --git a/postgres/models.go b/postgres/models.go index 81ba49b..ad4bf6b 100644 --- a/postgres/models.go +++ b/postgres/models.go @@ -7,6 +7,7 @@ import ( "fmt" "time" + "git.javil.eu/jacob1123/budgeteer/postgres/numeric" "github.com/google/uuid" ) @@ -42,7 +43,7 @@ type Assignment struct { CategoryID uuid.UUID Date time.Time Memo sql.NullString - Amount Numeric + Amount numeric.Numeric } type AssignmentsByMonth struct { @@ -81,7 +82,7 @@ type Transaction struct { ID uuid.UUID Date time.Time Memo string - Amount Numeric + Amount numeric.Numeric AccountID uuid.UUID CategoryID uuid.NullUUID PayeeID uuid.NullUUID diff --git a/postgres/numeric.go b/postgres/numeric/numeric.go similarity index 85% rename from postgres/numeric.go rename to postgres/numeric/numeric.go index 9483e87..83dbd3b 100644 --- a/postgres/numeric.go +++ b/postgres/numeric/numeric.go @@ -1,8 +1,10 @@ -package postgres +package numeric import ( "fmt" "math/big" + "strings" + "unicode/utf8" "github.com/jackc/pgtype" ) @@ -11,7 +13,7 @@ type Numeric struct { pgtype.Numeric } -func NewZeroNumeric() Numeric { +func Zero() Numeric { return Numeric{pgtype.Numeric{Exp: 0, Int: big.NewInt(0), Status: pgtype.Present, NaN: false}} } @@ -165,3 +167,27 @@ func (n Numeric) MarshalJSON() ([]byte, error) { bytesWithSeparator = append(bytesWithSeparator, bytes[split:]...) return bytesWithSeparator, nil } + +func Parse(text string) (Numeric, error) { + // Remove trailing currency + text = trimLastChar(text) + + // Unify decimal separator + text = strings.Replace(text, ",", ".", 1) + + num := Numeric{} + err := num.Set(text) + if err != nil { + return num, fmt.Errorf("parse numeric %s: %w", text, err) + } + + return num, nil +} + +func trimLastChar(s string) string { + r, size := utf8.DecodeLastRuneInString(s) + if r == utf8.RuneError && (size == 0 || size == 1) { + size = 0 + } + return s[:len(s)-size] +} diff --git a/postgres/transactions.sql.go b/postgres/transactions.sql.go index f5c813d..0b57967 100644 --- a/postgres/transactions.sql.go +++ b/postgres/transactions.sql.go @@ -7,6 +7,7 @@ import ( "context" "time" + "git.javil.eu/jacob1123/budgeteer/postgres/numeric" "github.com/google/uuid" ) @@ -20,7 +21,7 @@ RETURNING id, date, memo, amount, account_id, category_id, payee_id, group_id, s type CreateTransactionParams struct { Date time.Time Memo string - Amount Numeric + Amount numeric.Numeric AccountID uuid.UUID PayeeID uuid.NullUUID CategoryID uuid.NullUUID @@ -95,7 +96,7 @@ type GetAllTransactionsForBudgetRow struct { ID uuid.UUID Date time.Time Memo string - Amount Numeric + Amount numeric.Numeric GroupID uuid.NullUUID Status TransactionStatus Account string @@ -222,7 +223,7 @@ type GetTransactionsForAccountRow struct { ID uuid.UUID Date time.Time Memo string - Amount Numeric + Amount numeric.Numeric GroupID uuid.NullUUID Status TransactionStatus Account string @@ -281,7 +282,7 @@ WHERE id = $7 type UpdateTransactionParams struct { Date time.Time Memo string - Amount Numeric + Amount numeric.Numeric AccountID uuid.UUID PayeeID uuid.NullUUID CategoryID uuid.NullUUID diff --git a/postgres/ynab-export.go b/postgres/ynab-export.go index 2fa1a4c..eefc9dd 100644 --- a/postgres/ynab-export.go +++ b/postgres/ynab-export.go @@ -6,6 +6,7 @@ import ( "fmt" "io" + "git.javil.eu/jacob1123/budgeteer/postgres/numeric" "github.com/google/uuid" ) @@ -43,8 +44,8 @@ func (ynab *YNABExport) ExportAssignments(context context.Context, w io.Writer) assignment.Group, assignment.Category, assignment.Amount.String() + "€", - NewZeroNumeric().String() + "€", - NewZeroNumeric().String() + "€", + numeric.Zero().String() + "€", + numeric.Zero().String() + "€", } err := csv.Write(row) @@ -129,9 +130,9 @@ func GetTransactionRow(transaction GetAllTransactionsForBudgetRow) []string { row = append(row, transaction.Memo) if transaction.Amount.IsPositive() { - row = append(row, NewZeroNumeric().String()+"€", transaction.Amount.String()+"€") + row = append(row, numeric.Zero().String()+"€", transaction.Amount.String()+"€") } else { - row = append(row, transaction.Amount.String()[1:]+"€", NewZeroNumeric().String()+"€") + row = append(row, transaction.Amount.String()[1:]+"€", numeric.Zero().String()+"€") } return append(row, string(transaction.Status)) diff --git a/postgres/ynab-import.go b/postgres/ynab-import.go index 629a844..384e373 100644 --- a/postgres/ynab-import.go +++ b/postgres/ynab-import.go @@ -7,8 +7,8 @@ import ( "io" "strings" "time" - "unicode/utf8" + "git.javil.eu/jacob1123/budgeteer/postgres/numeric" "github.com/google/uuid" ) @@ -242,7 +242,7 @@ func (ynab *YNABImport) ImportRegularTransaction(context context.Context, payeeN func (ynab *YNABImport) ImportTransferTransaction(context context.Context, payeeName string, transaction CreateTransactionParams, openTransfers *[]Transfer, - account *Account, amount Numeric) error { + account *Account, amount numeric.Numeric) error { transferToAccountName := payeeName[11:] transferToAccount, err := ynab.GetAccount(context, transferToAccountName) if err != nil { @@ -295,34 +295,10 @@ func (ynab *YNABImport) ImportTransferTransaction(context context.Context, payee return nil } -func trimLastChar(s string) string { - r, size := utf8.DecodeLastRuneInString(s) - if r == utf8.RuneError && (size == 0 || size == 1) { - size = 0 - } - return s[:len(s)-size] -} - -func ParseNumeric(text string) (Numeric, error) { - // Remove trailing currency - text = trimLastChar(text) - - // Unify decimal separator - text = strings.Replace(text, ",", ".", 1) - - num := Numeric{} - err := num.Set(text) +func GetAmount(inflow string, outflow string) (numeric.Numeric, error) { + in, err := numeric.Parse(inflow) if err != nil { - return num, fmt.Errorf("parse numeric %s: %w", text, err) - } - - return num, nil -} - -func GetAmount(inflow string, outflow string) (Numeric, error) { - in, err := ParseNumeric(inflow) - if err != nil { - return in, err + return in, fmt.Errorf("parse inflow: %w", err) } if !in.IsZero() { @@ -330,9 +306,9 @@ func GetAmount(inflow string, outflow string) (Numeric, error) { } // if inflow is zero, use outflow - out, err := ParseNumeric("-" + outflow) + out, err := numeric.Parse("-" + outflow) if err != nil { - return out, err + return out, fmt.Errorf("parse outflow: %w", err) } return out, nil } diff --git a/server/budgeting.go b/server/budgeting.go index cccbbb5..b571d9c 100644 --- a/server/budgeting.go +++ b/server/budgeting.go @@ -7,6 +7,7 @@ import ( "time" "git.javil.eu/jacob1123/budgeteer/postgres" + "git.javil.eu/jacob1123/budgeteer/postgres/numeric" "github.com/gin-gonic/gin" "github.com/google/uuid" ) @@ -24,19 +25,19 @@ func getFirstOfMonthTime(date time.Time) time.Time { type CategoryWithBalance struct { *postgres.GetCategoriesRow - Available postgres.Numeric - AvailableLastMonth postgres.Numeric - Activity postgres.Numeric - Assigned postgres.Numeric + Available numeric.Numeric + AvailableLastMonth numeric.Numeric + Activity numeric.Numeric + Assigned numeric.Numeric } func NewCategoryWithBalance(category *postgres.GetCategoriesRow) CategoryWithBalance { return CategoryWithBalance{ GetCategoriesRow: category, - Available: postgres.NewZeroNumeric(), - AvailableLastMonth: postgres.NewZeroNumeric(), - Activity: postgres.NewZeroNumeric(), - Assigned: postgres.NewZeroNumeric(), + Available: numeric.Zero(), + AvailableLastMonth: numeric.Zero(), + Activity: numeric.Zero(), + Assigned: numeric.Zero(), } } @@ -101,15 +102,15 @@ func (h *Handler) budgetingForMonth(c *gin.Context) { data := struct { Categories []CategoryWithBalance - AvailableBalance postgres.Numeric + AvailableBalance numeric.Numeric }{categoriesWithBalance, availableBalance} c.JSON(http.StatusOK, data) } func (*Handler) getAvailableBalance(categories []postgres.GetCategoriesRow, budget postgres.Budget, - moneyUsed postgres.Numeric, cumultativeBalances []postgres.GetCumultativeBalancesRow, - firstOfNextMonth time.Time) postgres.Numeric { - availableBalance := postgres.NewZeroNumeric() + moneyUsed numeric.Numeric, cumultativeBalances []postgres.GetCumultativeBalancesRow, + firstOfNextMonth time.Time) numeric.Numeric { + availableBalance := numeric.Zero() for _, cat := range categories { if cat.ID != budget.IncomeCategoryID { continue @@ -161,10 +162,10 @@ func (h *Handler) budgeting(c *gin.Context) { func (h *Handler) calculateBalances(budget postgres.Budget, firstOfNextMonth time.Time, firstOfMonth time.Time, categories []postgres.GetCategoriesRow, - cumultativeBalances []postgres.GetCumultativeBalancesRow) ([]CategoryWithBalance, postgres.Numeric) { + cumultativeBalances []postgres.GetCumultativeBalancesRow) ([]CategoryWithBalance, numeric.Numeric) { categoriesWithBalance := []CategoryWithBalance{} - moneyUsed := postgres.NewZeroNumeric() + moneyUsed := numeric.Zero() for i := range categories { cat := &categories[i] // do not show hidden categories @@ -183,7 +184,7 @@ func (h *Handler) calculateBalances(budget postgres.Budget, func (*Handler) CalculateCategoryBalances(cat *postgres.GetCategoriesRow, cumultativeBalances []postgres.GetCumultativeBalancesRow, firstOfNextMonth time.Time, - moneyUsed *postgres.Numeric, firstOfMonth time.Time, budget postgres.Budget) CategoryWithBalance { + moneyUsed *numeric.Numeric, firstOfMonth time.Time, budget postgres.Budget) CategoryWithBalance { categoryWithBalance := NewCategoryWithBalance(cat) for _, bal := range cumultativeBalances { if bal.CategoryID != cat.ID { @@ -200,7 +201,7 @@ func (*Handler) CalculateCategoryBalances(cat *postgres.GetCategoriesRow, categoryWithBalance.Available = categoryWithBalance.Available.Add(bal.Transactions) if !categoryWithBalance.Available.IsPositive() && bal.Date.Before(firstOfMonth) { *moneyUsed = moneyUsed.Add(categoryWithBalance.Available) - categoryWithBalance.Available = postgres.NewZeroNumeric() + categoryWithBalance.Available = numeric.Zero() } if bal.Date.Before(firstOfMonth) { diff --git a/server/transaction.go b/server/transaction.go index 05b0595..d3cad1b 100644 --- a/server/transaction.go +++ b/server/transaction.go @@ -6,6 +6,7 @@ import ( "time" "git.javil.eu/jacob1123/budgeteer/postgres" + "git.javil.eu/jacob1123/budgeteer/postgres/numeric" "github.com/gin-gonic/gin" "github.com/google/uuid" ) @@ -35,7 +36,7 @@ func (h *Handler) newTransaction(c *gin.Context) { return } - amount := postgres.Numeric{} + amount := numeric.Numeric{} err = amount.Set(payload.Amount) if err != nil { c.AbortWithError(http.StatusBadRequest, fmt.Errorf("amount: %w", err)) diff --git a/sqlc.yaml b/sqlc.yaml index 4417ed2..00b9bc1 100644 --- a/sqlc.yaml +++ b/sqlc.yaml @@ -7,9 +7,11 @@ packages: queries: "postgres/queries/" overrides: - go_type: - type: "Numeric" + import: "git.javil.eu/jacob1123/budgeteer/postgres/numeric" + type: Numeric db_type: "pg_catalog.numeric" - go_type: - type: "Numeric" + import: "git.javil.eu/jacob1123/budgeteer/postgres/numeric" + type: Numeric db_type: "pg_catalog.numeric" nullable: true \ No newline at end of file From ea6d198bff1ef206ce8ba22e4c72b3663e9e1cd3 Mon Sep 17 00:00:00 2001 From: Jan Bader Date: Wed, 23 Feb 2022 21:52:36 +0000 Subject: [PATCH 3/8] Add some unit-tests for numeric --- postgres/numeric/numeric.go | 32 ++++++++++++-- postgres/numeric/numeric_test.go | 75 ++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 postgres/numeric/numeric_test.go diff --git a/postgres/numeric/numeric.go b/postgres/numeric/numeric.go index 83dbd3b..149c615 100644 --- a/postgres/numeric/numeric.go +++ b/postgres/numeric/numeric.go @@ -17,6 +17,19 @@ func Zero() Numeric { return Numeric{pgtype.Numeric{Exp: 0, Int: big.NewInt(0), Status: pgtype.Present, NaN: false}} } +func FromInt64(value int64) Numeric { + num := Numeric{} + num.Set(value) + return num +} + +func FromInt64WithExp(value int64, exp int32) Numeric { + num := Numeric{} + num.Set(value) + num.Exp = exp + return num +} + func (n Numeric) GetFloat64() float64 { if n.Status != pgtype.Present { return 0 @@ -168,10 +181,16 @@ func (n Numeric) MarshalJSON() ([]byte, error) { return bytesWithSeparator, nil } -func Parse(text string) (Numeric, error) { - // Remove trailing currency - text = trimLastChar(text) +func MustParse(text string) Numeric { + num, err := Parse(text) + if err != nil { + panic(err) + } + return num +} + +func Parse(text string) (Numeric, error) { // Unify decimal separator text = strings.Replace(text, ",", ".", 1) @@ -184,6 +203,13 @@ func Parse(text string) (Numeric, error) { return num, nil } +func ParseCurrency(text string) (Numeric, error) { + // Remove trailing currency + text = trimLastChar(text) + + return Parse(text) +} + func trimLastChar(s string) string { r, size := utf8.DecodeLastRuneInString(s) if r == utf8.RuneError && (size == 0 || size == 1) { diff --git a/postgres/numeric/numeric_test.go b/postgres/numeric/numeric_test.go new file mode 100644 index 0000000..50329f0 --- /dev/null +++ b/postgres/numeric/numeric_test.go @@ -0,0 +1,75 @@ +package numeric_test + +import ( + "testing" + + "git.javil.eu/jacob1123/budgeteer/postgres/numeric" +) + +type TestCaseMarshalJSON struct { + Value numeric.Numeric + Result string +} + +func TestMarshalJSON(t *testing.T) { + tests := []TestCaseMarshalJSON{ + {numeric.Zero(), `0`}, + {numeric.MustParse("1.23"), "1.23"}, + {numeric.MustParse("1,24"), "1.24"}, + {numeric.MustParse("123456789.12345"), "123456789.12345"}, + } + for _, test := range tests { + t.Run(test.Result, func(t *testing.T) { + z := test.Value + result, err := z.MarshalJSON() + if err != nil { + t.Error(err) + return + } + + if string(result) != test.Result { + t.Errorf("Expected %s, got %s", test.Result, string(result)) + return + } + }) + } +} + +type TestCaseParse struct { + Result numeric.Numeric + Value string +} + +func TestParse(t *testing.T) { + tests := []TestCaseParse{ + {numeric.Zero(), `0`}, + {numeric.FromInt64(1), `1`}, + {numeric.FromInt64WithExp(1, 1), `10`}, + {numeric.FromInt64WithExp(1, 2), `100`}, + {numeric.MustParse("1.23"), "1.23"}, + {numeric.MustParse("1,24"), "1.24"}, + {numeric.MustParse("123456789.12345"), "123456789.12345"}, + } + for _, test := range tests { + t.Run(test.Value, func(t *testing.T) { + result, err := numeric.Parse(test.Value) + if err != nil { + t.Error(err) + return + } + + if test.Result.Int.Int64() != result.Int.Int64() { + t.Errorf("Expected int %d, got %d", test.Result.Int, result.Int) + return + } + + if test.Result.Exp != result.Exp { + t.Errorf("Expected exp %d, got %d", test.Result.Exp, result.Exp) + return + } + // if string(result) != test.Result { + // return + //} + }) + } +} From f445f19233fcec425eee82eaf0dc9753edd98725 Mon Sep 17 00:00:00 2001 From: Jan Bader Date: Wed, 23 Feb 2022 22:02:29 +0000 Subject: [PATCH 4/8] Write all tests equally --- postgres/numeric/numeric_test.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/postgres/numeric/numeric_test.go b/postgres/numeric/numeric_test.go index 50329f0..e44c615 100644 --- a/postgres/numeric/numeric_test.go +++ b/postgres/numeric/numeric_test.go @@ -42,13 +42,13 @@ type TestCaseParse struct { func TestParse(t *testing.T) { tests := []TestCaseParse{ - {numeric.Zero(), `0`}, - {numeric.FromInt64(1), `1`}, + {numeric.FromInt64WithExp(0, 0), `0`}, + {numeric.FromInt64WithExp(1, 0), `1`}, {numeric.FromInt64WithExp(1, 1), `10`}, {numeric.FromInt64WithExp(1, 2), `100`}, - {numeric.MustParse("1.23"), "1.23"}, - {numeric.MustParse("1,24"), "1.24"}, - {numeric.MustParse("123456789.12345"), "123456789.12345"}, + {numeric.FromInt64WithExp(123, -2), "1.23"}, + {numeric.FromInt64WithExp(124, -2), "1,24"}, + {numeric.FromInt64WithExp(12345678912345, -5), "123456789.12345"}, } for _, test := range tests { t.Run(test.Value, func(t *testing.T) { @@ -67,9 +67,6 @@ func TestParse(t *testing.T) { t.Errorf("Expected exp %d, got %d", test.Result.Exp, result.Exp) return } - // if string(result) != test.Result { - // return - //} }) } } From 253ecd172016e9925bdc2900777434ab1d3bec5b Mon Sep 17 00:00:00 2001 From: Jan Bader Date: Wed, 23 Feb 2022 22:04:19 +0000 Subject: [PATCH 5/8] Add negative testcases --- postgres/numeric/numeric_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/postgres/numeric/numeric_test.go b/postgres/numeric/numeric_test.go index e44c615..a49ab14 100644 --- a/postgres/numeric/numeric_test.go +++ b/postgres/numeric/numeric_test.go @@ -17,6 +17,9 @@ func TestMarshalJSON(t *testing.T) { {numeric.MustParse("1.23"), "1.23"}, {numeric.MustParse("1,24"), "1.24"}, {numeric.MustParse("123456789.12345"), "123456789.12345"}, + {numeric.MustParse("-1.23"), "-1.23"}, + {numeric.MustParse("-1,24"), "-1.24"}, + {numeric.MustParse("-123456789.12345"), "-123456789.12345"}, } for _, test := range tests { t.Run(test.Result, func(t *testing.T) { @@ -49,6 +52,13 @@ func TestParse(t *testing.T) { {numeric.FromInt64WithExp(123, -2), "1.23"}, {numeric.FromInt64WithExp(124, -2), "1,24"}, {numeric.FromInt64WithExp(12345678912345, -5), "123456789.12345"}, + {numeric.FromInt64WithExp(0, 0), `-0`}, + {numeric.FromInt64WithExp(-1, 0), `-1`}, + {numeric.FromInt64WithExp(-1, 1), `-10`}, + {numeric.FromInt64WithExp(-1, 2), `-100`}, + {numeric.FromInt64WithExp(-123, -2), "-1.23"}, + {numeric.FromInt64WithExp(-124, -2), "-1,24"}, + {numeric.FromInt64WithExp(-12345678912345, -5), "-123456789.12345"}, } for _, test := range tests { t.Run(test.Value, func(t *testing.T) { From 24e5b18ded8588d4bbeeccc21748170aa51bb012 Mon Sep 17 00:00:00 2001 From: Jan Bader Date: Wed, 23 Feb 2022 22:08:47 +0000 Subject: [PATCH 6/8] Implement linter fixes --- postgres/numeric/numeric.go | 9 ++------- postgres/numeric/numeric_test.go | 10 ++++++++-- postgres/ynab-import.go | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/postgres/numeric/numeric.go b/postgres/numeric/numeric.go index 149c615..cf1ff73 100644 --- a/postgres/numeric/numeric.go +++ b/postgres/numeric/numeric.go @@ -18,16 +18,11 @@ func Zero() Numeric { } func FromInt64(value int64) Numeric { - num := Numeric{} - num.Set(value) - return num + return Numeric{Numeric: pgtype.Numeric{Int: big.NewInt(value), Status: pgtype.Present}} } func FromInt64WithExp(value int64, exp int32) Numeric { - num := Numeric{} - num.Set(value) - num.Exp = exp - return num + return Numeric{Numeric: pgtype.Numeric{Int: big.NewInt(value), Exp: exp, Status: pgtype.Present}} } func (n Numeric) GetFloat64() float64 { diff --git a/postgres/numeric/numeric_test.go b/postgres/numeric/numeric_test.go index a49ab14..b7ef5e9 100644 --- a/postgres/numeric/numeric_test.go +++ b/postgres/numeric/numeric_test.go @@ -12,6 +12,7 @@ type TestCaseMarshalJSON struct { } func TestMarshalJSON(t *testing.T) { + t.Parallel() tests := []TestCaseMarshalJSON{ {numeric.Zero(), `0`}, {numeric.MustParse("1.23"), "1.23"}, @@ -21,8 +22,10 @@ func TestMarshalJSON(t *testing.T) { {numeric.MustParse("-1,24"), "-1.24"}, {numeric.MustParse("-123456789.12345"), "-123456789.12345"}, } - for _, test := range tests { + for i := range tests { + test := tests[i] t.Run(test.Result, func(t *testing.T) { + t.Parallel() z := test.Value result, err := z.MarshalJSON() if err != nil { @@ -44,6 +47,7 @@ type TestCaseParse struct { } func TestParse(t *testing.T) { + t.Parallel() tests := []TestCaseParse{ {numeric.FromInt64WithExp(0, 0), `0`}, {numeric.FromInt64WithExp(1, 0), `1`}, @@ -60,8 +64,10 @@ func TestParse(t *testing.T) { {numeric.FromInt64WithExp(-124, -2), "-1,24"}, {numeric.FromInt64WithExp(-12345678912345, -5), "-123456789.12345"}, } - for _, test := range tests { + for i := range tests { + test := tests[i] t.Run(test.Value, func(t *testing.T) { + t.Parallel() result, err := numeric.Parse(test.Value) if err != nil { t.Error(err) diff --git a/postgres/ynab-import.go b/postgres/ynab-import.go index 384e373..83c5f9d 100644 --- a/postgres/ynab-import.go +++ b/postgres/ynab-import.go @@ -296,7 +296,7 @@ func (ynab *YNABImport) ImportTransferTransaction(context context.Context, payee } func GetAmount(inflow string, outflow string) (numeric.Numeric, error) { - in, err := numeric.Parse(inflow) + in, err := numeric.ParseCurrency(inflow) if err != nil { return in, fmt.Errorf("parse inflow: %w", err) } @@ -306,7 +306,7 @@ func GetAmount(inflow string, outflow string) (numeric.Numeric, error) { } // if inflow is zero, use outflow - out, err := numeric.Parse("-" + outflow) + out, err := numeric.ParseCurrency("-" + outflow) if err != nil { return out, fmt.Errorf("parse outflow: %w", err) } From 5f746f5889e3426d7237a9538b1cd35843c38c20 Mon Sep 17 00:00:00 2001 From: Jan Bader Date: Wed, 23 Feb 2022 22:10:16 +0000 Subject: [PATCH 7/8] Also run tests in CI --- Taskfile.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Taskfile.yml b/Taskfile.yml index 3ddda78..28f36dd 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -65,6 +65,7 @@ tasks: desc: Run CI build cmds: - task: build-prod + - go test ./... frontend: desc: Build vue frontend From 7c694fb32c5eebe944053c7a867dcd61d3f01121 Mon Sep 17 00:00:00 2001 From: Jan Bader Date: Wed, 23 Feb 2022 22:12:09 +0000 Subject: [PATCH 8/8] Skip account_test when no db available --- server/account_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/account_test.go b/server/account_test.go index fe79cba..1af33c1 100644 --- a/server/account_test.go +++ b/server/account_test.go @@ -2,6 +2,7 @@ package server import ( "encoding/json" + "fmt" "net/http" "net/http/httptest" "strings" @@ -22,7 +23,8 @@ func TestRegisterUser(t *testing.T) { //nolint:funlen t.Parallel() database, err := postgres.Connect("pgtx", "example") if err != nil { - t.Errorf("could not connect to db: %s", err) + fmt.Printf("could not connect to db: %s\n", err) + t.Skip() return }