Continue migration to echo

This commit is contained in:
Jan Bader 2022-08-20 22:23:42 +00:00
parent b573553424
commit 1a11555075
10 changed files with 168 additions and 199 deletions

View File

@ -5,7 +5,6 @@ import (
"time" "time"
"git.javil.eu/jacob1123/budgeteer/postgres" "git.javil.eu/jacob1123/budgeteer/postgres"
"github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
@ -18,19 +17,17 @@ type FilterTransactionsRequest struct {
ToDate time.Time `json:"to_date"` ToDate time.Time `json:"to_date"`
} }
func (h *Handler) filteredTransactions(c *echo.Context) { func (h *Handler) filteredTransactions(c echo.Context) error {
budgetID := c.Param("budgetid") budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return
} }
var request FilterTransactionsRequest var request FilterTransactionsRequest
err = c.BindJSON(&request) err = c.Bind(&request)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return
} }
params := postgres.GetFilteredTransactionsParams{ params := postgres.GetFilteredTransactionsParams{
@ -43,13 +40,12 @@ func (h *Handler) filteredTransactions(c *echo.Context) {
params.AccountID, params.FilterAccount = accountID.UUID, filterAccount params.AccountID, params.FilterAccount = accountID.UUID, filterAccount
params.PayeeID, params.FilterPayee = parseEmptyUUID(request.PayeeID) params.PayeeID, params.FilterPayee = parseEmptyUUID(request.PayeeID)
transactions, err := h.Service.GetFilteredTransactions(c.Request.Context(), params) transactions, err := h.Service.GetFilteredTransactions(c.Request().Context(), params)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return
} }
c.JSON(http.StatusOK, TransactionsResponse{nil, transactions}) return c.JSON(http.StatusOK, TransactionsResponse{nil, transactions})
} }
func parseEmptyUUID(value string) (uuid.NullUUID, bool) { func parseEmptyUUID(value string) (uuid.NullUUID, bool) {
@ -65,21 +61,19 @@ func parseEmptyUUID(value string) (uuid.NullUUID, bool) {
return uuid.NullUUID{val, true}, true return uuid.NullUUID{val, true}, true
} }
func (h *Handler) problematicTransactions(c *gin.Context) { func (h *Handler) problematicTransactions(c echo.Context) error {
budgetID := c.Param("budgetid") budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return
} }
transactions, err := h.Service.GetProblematicTransactions(c.Request.Context(), budgetUUID) transactions, err := h.Service.GetProblematicTransactions(c.Request().Context(), budgetUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return err
return
} }
c.JSON(http.StatusOK, TransactionsResponse{nil, transactions}) return c.JSON(http.StatusOK, TransactionsResponse{nil, transactions})
} }
func (h *Handler) transactionsForAccount(c echo.Context) error { func (h *Handler) transactionsForAccount(c echo.Context) error {
@ -113,19 +107,17 @@ type EditAccountRequest struct {
IsOpen bool `json:"isOpen"` IsOpen bool `json:"isOpen"`
} }
func (h *Handler) editAccount(c *gin.Context) { func (h *Handler) editAccount(c echo.Context) error {
accountID := c.Param("accountid") accountID := c.Param("accountid")
accountUUID, err := uuid.Parse(accountID) accountUUID, err := uuid.Parse(accountID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return
} }
var request EditAccountRequest var request EditAccountRequest
err = c.BindJSON(&request) err = c.Bind(&request)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return
} }
updateParams := postgres.UpdateAccountParams{ updateParams := postgres.UpdateAccountParams{
@ -134,11 +126,10 @@ func (h *Handler) editAccount(c *gin.Context) {
IsOpen: request.IsOpen, IsOpen: request.IsOpen,
ID: accountUUID, ID: accountUUID,
} }
account, err := h.Service.UpdateAccount(c.Request.Context(), updateParams) account, err := h.Service.UpdateAccount(c.Request().Context(), updateParams)
if err != nil { if err != nil {
c.AbortWithError(http.StatusNotFound, err) return echo.NewHTTPError(http.StatusNotFound, err)
return
} }
h.getBudget(c, account.BudgetID) return h.getBudget(c, account.BudgetID)
} }

View File

@ -4,63 +4,66 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4"
"github.com/pressly/goose/v3" "github.com/pressly/goose/v3"
) )
func (h *Handler) clearDatabase(c *gin.Context) { func (h *Handler) clearDatabase(c echo.Context) error {
if err := goose.Reset(h.Service.DB, "schema"); err != nil { if err := goose.Reset(h.Service.DB, "schema"); err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
} }
if err := goose.Up(h.Service.DB, "schema"); err != nil { if err := goose.Up(h.Service.DB, "schema"); err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
}
} }
func (h *Handler) deleteBudget(c *gin.Context) { return nil
}
func (h *Handler) deleteBudget(c echo.Context) error {
budgetID := c.Param("budgetid") budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if err != nil { if err != nil {
c.AbortWithStatus(http.StatusBadRequest) return echo.NewHTTPError(http.StatusBadRequest, err)
return
} }
h.clearBudgetData(c, budgetUUID) err = h.clearBudgetData(c, budgetUUID)
err = h.Service.DeleteBudget(c.Request.Context(), budgetUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return err
return
}
} }
func (h *Handler) clearBudgetData(c *gin.Context, budgetUUID uuid.UUID) { err = h.Service.DeleteBudget(c.Request().Context(), budgetUUID)
rows, err := h.Service.DeleteAllAssignments(c.Request.Context(), budgetUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return err
return }
return nil
}
func (h *Handler) clearBudgetData(c echo.Context, budgetUUID uuid.UUID) error {
rows, err := h.Service.DeleteAllAssignments(c.Request().Context(), budgetUUID)
if err != nil {
return err
} }
fmt.Printf("Deleted %d assignments\n", rows) fmt.Printf("Deleted %d assignments\n", rows)
rows, err = h.Service.DeleteAllTransactions(c.Request.Context(), budgetUUID) rows, err = h.Service.DeleteAllTransactions(c.Request().Context(), budgetUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return err
return
} }
fmt.Printf("Deleted %d transactions\n", rows) fmt.Printf("Deleted %d transactions\n", rows)
return nil
} }
func (h *Handler) clearBudget(c *gin.Context) { func (h *Handler) clearBudget(c echo.Context) error {
budgetID := c.Param("budgetid") budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if err != nil { if err != nil {
c.AbortWithStatus(http.StatusBadRequest) return echo.NewHTTPError(http.StatusBadRequest, err)
return
} }
h.clearBudgetData(c, budgetUUID) return h.clearBudgetData(c, budgetUUID)
} }

View File

@ -5,63 +5,58 @@ import (
"strings" "strings"
"git.javil.eu/jacob1123/budgeteer/postgres" "git.javil.eu/jacob1123/budgeteer/postgres"
"github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4"
) )
func (h *Handler) autocompleteAccounts(c *gin.Context) { func (h *Handler) autocompleteAccounts(c echo.Context) error {
budgetID := c.Param("budgetid") budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, ErrorResponse{"budgetid missing from URL"}) return echo.NewHTTPError(http.StatusBadRequest, "budgetid missing from URL")
return
} }
query := c.Request.URL.Query().Get("s") query := c.Request().URL.Query().Get("s")
searchParams := postgres.SearchAccountsParams{ searchParams := postgres.SearchAccountsParams{
BudgetID: budgetUUID, BudgetID: budgetUUID,
Search: "%" + query + "%", Search: "%" + query + "%",
} }
categories, err := h.Service.SearchAccounts(c.Request.Context(), searchParams) categories, err := h.Service.SearchAccounts(c.Request().Context(), searchParams)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return err
return
} }
c.JSON(http.StatusOK, categories) return c.JSON(http.StatusOK, categories)
} }
func (h *Handler) autocompleteCategories(c *gin.Context) { func (h *Handler) autocompleteCategories(c echo.Context) error {
budgetID := c.Param("budgetid") budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, ErrorResponse{"budgetid missing from URL"}) return echo.NewHTTPError(http.StatusBadRequest, "budgetid missing from URL")
return
} }
query := c.Request.URL.Query().Get("s") query := c.Request().URL.Query().Get("s")
searchParams := postgres.SearchCategoriesParams{ searchParams := postgres.SearchCategoriesParams{
BudgetID: budgetUUID, BudgetID: budgetUUID,
Search: "%" + query + "%", Search: "%" + query + "%",
} }
categories, err := h.Service.SearchCategories(c.Request.Context(), searchParams) categories, err := h.Service.SearchCategories(c.Request().Context(), searchParams)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return
} }
c.JSON(http.StatusOK, categories) return c.JSON(http.StatusOK, categories)
} }
func (h *Handler) autocompletePayee(c *gin.Context) { func (h *Handler) autocompletePayee(c echo.Context) error {
budgetID := c.Param("budgetid") budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, ErrorResponse{"budgetid missing from URL"}) return echo.NewHTTPError(http.StatusBadRequest, "budgetid missing from URL")
return
} }
query := c.Request.URL.Query().Get("s") query := c.Request().URL.Query().Get("s")
transferPrefix := "Transfer" transferPrefix := "Transfer"
if strings.HasPrefix(query, transferPrefix) { if strings.HasPrefix(query, transferPrefix) {
@ -70,25 +65,23 @@ func (h *Handler) autocompletePayee(c *gin.Context) {
Search: "%" + strings.Trim(query[len(transferPrefix):], " \t\n:") + "%", Search: "%" + strings.Trim(query[len(transferPrefix):], " \t\n:") + "%",
} }
accounts, err := h.Service.SearchAccounts(c.Request.Context(), searchParams) accounts, err := h.Service.SearchAccounts(c.Request().Context(), searchParams)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return err
return }
return c.JSON(http.StatusOK, accounts)
} }
c.JSON(http.StatusOK, accounts)
} else {
searchParams := postgres.SearchPayeesParams{ searchParams := postgres.SearchPayeesParams{
BudgetID: budgetUUID, BudgetID: budgetUUID,
Search: query + "%", Search: query + "%",
} }
payees, err := h.Service.SearchPayees(c.Request.Context(), searchParams) payees, err := h.Service.SearchPayees(c.Request().Context(), searchParams)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return err
return
} }
c.JSON(http.StatusOK, payees) return c.JSON(http.StatusOK, payees)
}
} }

View File

@ -3,17 +3,17 @@ package server
import ( import (
"net/http" "net/http"
"github.com/gin-gonic/gin" "github.com/labstack/echo/v4"
) )
type newBudgetInformation struct { type newBudgetInformation struct {
Name string `json:"name"` Name string `json:"name"`
} }
func (h *Handler) newBudget(c *gin.Context) { func (h *Handler) newBudget(c echo.Context) error {
var newBudget newBudgetInformation var newBudget newBudgetInformation
if err := c.BindJSON(&newBudget); err != nil { if err := c.BindJSON(&newBudget); err != nil {
c.AbortWithError(http.StatusNotAcceptable, err) return echo.NewHTTPError(http.StatusNotAcceptable, err)
return return
} }
@ -23,9 +23,9 @@ func (h *Handler) newBudget(c *gin.Context) {
} }
userID := MustGetToken(c).GetID() userID := MustGetToken(c).GetID()
budget, err := h.Service.NewBudget(c.Request.Context(), newBudget.Name, userID) budget, err := h.Service.NewBudget(c.Request().Context(), newBudget.Name, userID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }

View File

@ -7,8 +7,8 @@ import (
"git.javil.eu/jacob1123/budgeteer/postgres" "git.javil.eu/jacob1123/budgeteer/postgres"
"git.javil.eu/jacob1123/budgeteer/postgres/numeric" "git.javil.eu/jacob1123/budgeteer/postgres/numeric"
"github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4"
) )
type CategoryWithBalance struct { type CategoryWithBalance struct {
@ -27,7 +27,7 @@ func NewCategoryWithBalance(category *postgres.GetCategoriesRow) CategoryWithBal
} }
} }
func (h *Handler) budgetingForMonth(c *gin.Context) { func (h *Handler) budgetingForMonth(c echo.Context) error {
budgetID := c.Param("budgetid") budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if err != nil { if err != nil {
@ -35,9 +35,9 @@ func (h *Handler) budgetingForMonth(c *gin.Context) {
return return
} }
budget, err := h.Service.GetBudget(c.Request.Context(), budgetUUID) budget, err := h.Service.GetBudget(c.Request().Context(), budgetUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return return
} }
@ -47,9 +47,9 @@ func (h *Handler) budgetingForMonth(c *gin.Context) {
return return
} }
data, err := h.getBudgetingViewForMonth(c.Request.Context(), budget, month) data, err := h.getBudgetingViewForMonth(c.Request().Context(), budget, month)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
c.JSON(http.StatusOK, data) c.JSON(http.StatusOK, data)
@ -105,33 +105,30 @@ type BudgetingResponse struct {
Budget postgres.Budget Budget postgres.Budget
} }
func (h *Handler) budget(c *gin.Context) { func (h *Handler) budget(c echo.Context) error {
budgetID := c.Param("budgetid") budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, ErrorResponse{"budgetid missing from URL"}) return echo.NewHTTPError(http.StatusBadRequest, "budgetid missing from URL")
return
} }
h.getBudget(c, budgetUUID) return h.getBudget(c, budgetUUID)
} }
func (h *Handler) getBudget(c *gin.Context, budgetUUID uuid.UUID) { func (h *Handler) getBudget(c echo.Context, budgetUUID uuid.UUID) error {
budget, err := h.Service.GetBudget(c.Request.Context(), budgetUUID) budget, err := h.Service.GetBudget(c.Request().Context(), budgetUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusNotFound, err) return echo.NewHTTPError(http.StatusNotFound, err)
return
} }
accounts, err := h.Service.GetAccountsWithBalance(c.Request.Context(), budgetUUID) accounts, err := h.Service.GetAccountsWithBalance(c.Request().Context(), budgetUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return err
return
} }
data := BudgetingResponse{accounts, budget} data := BudgetingResponse{accounts, budget}
c.JSON(http.StatusOK, data) return c.JSON(http.StatusOK, data)
} }
func (h *Handler) calculateBalances(budget postgres.Budget, month Month, func (h *Handler) calculateBalances(budget postgres.Budget, month Month,

View File

@ -6,15 +6,15 @@ import (
"git.javil.eu/jacob1123/budgeteer/postgres" "git.javil.eu/jacob1123/budgeteer/postgres"
"git.javil.eu/jacob1123/budgeteer/postgres/numeric" "git.javil.eu/jacob1123/budgeteer/postgres/numeric"
"github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4"
) )
type SetCategoryAssignmentRequest struct { type SetCategoryAssignmentRequest struct {
Assigned float64 Assigned float64
} }
func (h *Handler) setCategoryAssignment(c *gin.Context) { func (h *Handler) setCategoryAssignment(c echo.Context) error {
categoryID := c.Param("categoryid") categoryID := c.Param("categoryid")
categoryUUID, err := uuid.Parse(categoryID) categoryUUID, err := uuid.Parse(categoryID)
if err != nil { if err != nil {
@ -25,20 +25,20 @@ func (h *Handler) setCategoryAssignment(c *gin.Context) {
var request SetCategoryAssignmentRequest var request SetCategoryAssignmentRequest
err = c.BindJSON(&request) err = c.BindJSON(&request)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("invalid payload: %w", err)) return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("invalid payload: %w", err))
return return
} }
date, err := getDate(c) date, err := getDate(c)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("date invalid: %w", err)) return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("date invalid: %w", err))
return return
} }
var amount numeric.Numeric var amount numeric.Numeric
err = amount.Set(request.Assigned) err = amount.Set(request.Assigned)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("parse amount: %w", err)) return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("parse amount: %w", err))
return return
} }
@ -47,9 +47,9 @@ func (h *Handler) setCategoryAssignment(c *gin.Context) {
Date: date.FirstOfMonth(), Date: date.FirstOfMonth(),
Amount: amount, Amount: amount,
} }
err = h.Service.UpdateAssignment(c.Request.Context(), updateArgs) err = h.Service.UpdateAssignment(c.Request().Context(), updateArgs)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("update assignment: %w", err)) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("update assignment: %w", err))
return return
} }
} }

View File

@ -33,14 +33,6 @@ func (h *Handler) Serve() {
} }
} }
type ErrorResponse struct {
Message string
}
type SuccessResponse struct {
Message string
}
// LoadRoutes initializes all the routes. // LoadRoutes initializes all the routes.
func (h *Handler) LoadRoutes(router *echo.Echo) { func (h *Handler) LoadRoutes(router *echo.Echo) {
router.Use(enableCachingForStaticFiles()) router.Use(enableCachingForStaticFiles())

View File

@ -8,8 +8,8 @@ import (
"git.javil.eu/jacob1123/budgeteer/postgres" "git.javil.eu/jacob1123/budgeteer/postgres"
"git.javil.eu/jacob1123/budgeteer/postgres/numeric" "git.javil.eu/jacob1123/budgeteer/postgres/numeric"
"github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4"
) )
type ReconcileTransactionsRequest struct { type ReconcileTransactionsRequest struct {
@ -22,68 +22,60 @@ type ReconcileTransactionsResponse struct {
ReconciliationTransaction *postgres.DisplayTransaction ReconciliationTransaction *postgres.DisplayTransaction
} }
func (h *Handler) reconcileTransactions(c *gin.Context) { func (h *Handler) reconcileTransactions(c echo.Context) error {
accountID := c.Param("accountid") accountID := c.Param("accountid")
accountUUID, err := uuid.Parse(accountID) accountUUID, err := uuid.Parse(accountID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return
} }
var request ReconcileTransactionsRequest var request ReconcileTransactionsRequest
err = c.BindJSON(&request) err = c.Bind(&request)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("parse request: %w", err)) return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("parse request: %w", err))
return
} }
var amount numeric.Numeric var amount numeric.Numeric
err = amount.Set(request.ReconcilationTransactionAmount) err = amount.Set(request.ReconcilationTransactionAmount)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("parse request: %w", err)) return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("parse request: %w", err))
return
} }
tx, err := h.Service.BeginTx(c.Request.Context(), &sql.TxOptions{}) tx, err := h.Service.BeginTx(c.Request().Context(), &sql.TxOptions{})
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("begin tx: %w", err)) return fmt.Errorf("begin tx: %w", err)
return
} }
db := h.Service.WithTx(tx) db := h.Service.WithTx(tx)
for _, transactionID := range request.TransactionIDs { for _, transactionID := range request.TransactionIDs {
err := db.SetTransactionReconciled(c.Request.Context(), transactionID) err := db.SetTransactionReconciled(c.Request().Context(), transactionID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("update transaction: %w", err)) return fmt.Errorf("update transaction: %w", err)
return
} }
} }
reconciliationTransaction, err := h.CreateReconcilationTransaction(amount, accountUUID, db, c) reconciliationTransaction, err := h.CreateReconcilationTransaction(amount, accountUUID, db, c)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("insert new transaction: %w", err)) return fmt.Errorf("insert new transaction: %w", err)
return
} }
err = h.Service.SetLastReconciled(c.Request.Context(), accountUUID) err = h.Service.SetLastReconciled(c.Request().Context(), accountUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("set last reconciled: %w", err)) return fmt.Errorf("set last reconciled: %w", err)
return
} }
err = tx.Commit() err = tx.Commit()
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("commit: %w", err)) return fmt.Errorf("commit: %w", err)
return
} }
c.JSON(http.StatusOK, ReconcileTransactionsResponse{ return c.JSON(http.StatusOK, ReconcileTransactionsResponse{
Message: fmt.Sprintf("Set status for %d transactions", len(request.TransactionIDs)), Message: fmt.Sprintf("Set status for %d transactions", len(request.TransactionIDs)),
ReconciliationTransaction: reconciliationTransaction, ReconciliationTransaction: reconciliationTransaction,
}) })
} }
func (*Handler) CreateReconcilationTransaction(amount numeric.Numeric, accountUUID uuid.UUID, db *postgres.Queries, c *gin.Context) (*postgres.DisplayTransaction, error) { func (*Handler) CreateReconcilationTransaction(amount numeric.Numeric, accountUUID uuid.UUID, db *postgres.Queries, c echo.Context) (*postgres.DisplayTransaction, error) {
if amount.IsZero() { if amount.IsZero() {
return nil, nil //nolint: nilnil return nil, nil //nolint: nilnil
} }
@ -95,12 +87,12 @@ func (*Handler) CreateReconcilationTransaction(amount numeric.Numeric, accountUU
AccountID: accountUUID, AccountID: accountUUID,
Status: "Reconciled", Status: "Reconciled",
} }
transactionUUID, err := db.CreateTransaction(c.Request.Context(), createTransaction) transactionUUID, err := db.CreateTransaction(c.Request().Context(), createTransaction)
if err != nil { if err != nil {
return nil, fmt.Errorf("insert new transaction: %w", err) return nil, fmt.Errorf("insert new transaction: %w", err)
} }
transaction, err := db.GetTransaction(c.Request.Context(), transactionUUID) transaction, err := db.GetTransaction(c.Request().Context(), transactionUUID)
if err != nil { if err != nil {
return nil, fmt.Errorf("get created transaction: %w", err) return nil, fmt.Errorf("get created transaction: %w", err)
} }

View File

@ -10,6 +10,7 @@ import (
"git.javil.eu/jacob1123/budgeteer/postgres/numeric" "git.javil.eu/jacob1123/budgeteer/postgres/numeric"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4"
) )
type NewTransactionPayload struct { type NewTransactionPayload struct {
@ -27,17 +28,17 @@ type NewTransactionPayload struct {
State string `json:"state"` State string `json:"state"`
} }
func (h *Handler) updateTransaction(c *gin.Context) { func (h *Handler) updateTransaction(c echo.Context) error {
var payload NewTransactionPayload var payload NewTransactionPayload
err := c.BindJSON(&payload) err := c.BindJSON(&payload)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return return
} }
amount, err := numeric.Parse(payload.Amount) amount, err := numeric.Parse(payload.Amount)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("amount: %w", err)) return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("amount: %w", err))
return return
} }
@ -51,17 +52,17 @@ func (h *Handler) updateTransaction(c *gin.Context) {
h.UpdateTransaction(payload, amount, transactionUUID, c) h.UpdateTransaction(payload, amount, transactionUUID, c)
} }
func (h *Handler) newTransaction(c *gin.Context) { func (h *Handler) newTransaction(c echo.Context) error {
var payload NewTransactionPayload var payload NewTransactionPayload
err := c.BindJSON(&payload) err := c.BindJSON(&payload)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return return
} }
amount, err := numeric.Parse(payload.Amount) amount, err := numeric.Parse(payload.Amount)
if err != nil { if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("amount: %w", err)) return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("amount: %w", err))
return return
} }
@ -77,39 +78,39 @@ func (h *Handler) newTransaction(c *gin.Context) {
if payload.Payee.Type == "account" { if payload.Payee.Type == "account" {
groupID, err := h.CreateTransferForOtherAccount(newTransaction, amount, payload, c) groupID, err := h.CreateTransferForOtherAccount(newTransaction, amount, payload, c)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
newTransaction.GroupID = groupID newTransaction.GroupID = groupID
} else { } else {
payeeID, err := GetPayeeID(c.Request.Context(), payload, h) payeeID, err := GetPayeeID(c.Request().Context(), payload, h)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("create payee: %w", err)) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("create payee: %w", err))
} }
newTransaction.PayeeID = payeeID newTransaction.PayeeID = payeeID
} }
transactionUUID, err := h.Service.CreateTransaction(c.Request.Context(), newTransaction) transactionUUID, err := h.Service.CreateTransaction(c.Request().Context(), newTransaction)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("create transaction: %w", err)) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("create transaction: %w", err))
return return
} }
transaction, err := h.Service.GetTransaction(c.Request.Context(), transactionUUID) transaction, err := h.Service.GetTransaction(c.Request().Context(), transactionUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("get transaction: %w", err)) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("get transaction: %w", err))
return return
} }
c.JSON(http.StatusOK, transaction) c.JSON(http.StatusOK, transaction)
} }
func (h *Handler) UpdateTransaction(payload NewTransactionPayload, amount numeric.Numeric, transactionUUID uuid.UUID, c *gin.Context) { func (h *Handler) UpdateTransaction(payload NewTransactionPayload, amount numeric.Numeric, transactionUUID uuid.UUID, c echo.Context) error {
if amount.IsZero() { if amount.IsZero() {
err := h.Service.DeleteTransaction(c.Request.Context(), transactionUUID) err := h.Service.DeleteTransaction(c.Request().Context(), transactionUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("delete transaction: %w", err)) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("delete transaction: %w", err))
} }
return return
} }
@ -123,15 +124,15 @@ func (h *Handler) UpdateTransaction(payload NewTransactionPayload, amount numeri
ID: transactionUUID, ID: transactionUUID,
} }
err := h.Service.UpdateTransaction(c.Request.Context(), editTransaction) err := h.Service.UpdateTransaction(c.Request().Context(), editTransaction)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("edit transaction: %w", err)) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("edit transaction: %w", err))
return return
} }
transaction, err := h.Service.GetTransaction(c.Request.Context(), transactionUUID) transaction, err := h.Service.GetTransaction(c.Request().Context(), transactionUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("get transaction: %w", err)) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("get transaction: %w", err))
return return
} }
@ -146,7 +147,7 @@ func (h *Handler) CreateTransferForOtherAccount(newTransaction postgres.CreateTr
// transfer does not need category. Either it's account is off-budget or no category was supplied. // transfer does not need category. Either it's account is off-budget or no category was supplied.
newTransaction.CategoryID = uuid.NullUUID{} newTransaction.CategoryID = uuid.NullUUID{}
_, err := h.Service.CreateTransaction(c.Request.Context(), newTransaction) _, err := h.Service.CreateTransaction(c.Request().Context(), newTransaction)
if err != nil { if err != nil {
return uuid.NullUUID{}, fmt.Errorf("create transfer transaction: %w", err) return uuid.NullUUID{}, fmt.Errorf("create transfer transaction: %w", err)
} }

View File

@ -4,11 +4,11 @@ import (
"net/http" "net/http"
"git.javil.eu/jacob1123/budgeteer/postgres" "git.javil.eu/jacob1123/budgeteer/postgres"
"github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4"
) )
func (h *Handler) importYNAB(c *gin.Context) { func (h *Handler) importYNAB(c echo.Context) error {
budgetID, succ := c.Params.Get("budgetid") budgetID, succ := c.Params.Get("budgetid")
if !succ { if !succ {
c.AbortWithStatusJSON(http.StatusBadRequest, ErrorResponse{"no budget_id specified"}) c.AbortWithStatusJSON(http.StatusBadRequest, ErrorResponse{"no budget_id specified"})
@ -17,54 +17,54 @@ func (h *Handler) importYNAB(c *gin.Context) {
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if !succ { if !succ {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return return
} }
ynab, err := postgres.NewYNABImport(c.Request.Context(), h.Service.Queries, budgetUUID) ynab, err := postgres.NewYNABImport(c.Request().Context(), h.Service.Queries, budgetUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
transactionsFile, err := c.FormFile("transactions") transactionsFile, err := c.FormFile("transactions")
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
transactions, err := transactionsFile.Open() transactions, err := transactionsFile.Open()
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
err = ynab.ImportTransactions(c.Request.Context(), transactions) err = ynab.ImportTransactions(c.Request().Context(), transactions)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
assignmentsFile, err := c.FormFile("assignments") assignmentsFile, err := c.FormFile("assignments")
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
assignments, err := assignmentsFile.Open() assignments, err := assignmentsFile.Open()
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
err = ynab.ImportAssignments(c.Request.Context(), assignments) err = ynab.ImportAssignments(c.Request().Context(), assignments)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
} }
func (h *Handler) exportYNABTransactions(c *gin.Context) { func (h *Handler) exportYNABTransactions(c echo.Context) error {
budgetID, succ := c.Params.Get("budgetid") budgetID, succ := c.Params.Get("budgetid")
if !succ { if !succ {
c.AbortWithStatusJSON(http.StatusBadRequest, ErrorResponse{"no budget_id specified"}) c.AbortWithStatusJSON(http.StatusBadRequest, ErrorResponse{"no budget_id specified"})
@ -73,24 +73,24 @@ func (h *Handler) exportYNABTransactions(c *gin.Context) {
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if !succ { if !succ {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return return
} }
ynab, err := postgres.NewYNABExport(c.Request.Context(), h.Service.Queries, budgetUUID) ynab, err := postgres.NewYNABExport(c.Request().Context(), h.Service.Queries, budgetUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
err = ynab.ExportTransactions(c.Request.Context(), c.Writer) err = ynab.ExportTransactions(c.Request().Context(), c.Writer)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
} }
func (h *Handler) exportYNABAssignments(c *gin.Context) { func (h *Handler) exportYNABAssignments(c echo.Context) error {
budgetID, succ := c.Params.Get("budgetid") budgetID, succ := c.Params.Get("budgetid")
if !succ { if !succ {
c.AbortWithStatusJSON(http.StatusBadRequest, ErrorResponse{"no budget_id specified"}) c.AbortWithStatusJSON(http.StatusBadRequest, ErrorResponse{"no budget_id specified"})
@ -99,19 +99,19 @@ func (h *Handler) exportYNABAssignments(c *gin.Context) {
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
if !succ { if !succ {
c.AbortWithError(http.StatusBadRequest, err) return echo.NewHTTPError(http.StatusBadRequest, err)
return return
} }
ynab, err := postgres.NewYNABExport(c.Request.Context(), h.Service.Queries, budgetUUID) ynab, err := postgres.NewYNABExport(c.Request().Context(), h.Service.Queries, budgetUUID)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
err = ynab.ExportAssignments(c.Request.Context(), c.Writer) err = ynab.ExportAssignments(c.Request().Context(), c.Writer)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) return echo.NewHTTPError(http.StatusInternalServerError, err)
return return
} }
} }