Try to calculate balances locally

This commit is contained in:
Jan Bader 2021-12-10 18:56:56 +00:00
parent 625e0635fd
commit 13993b6b5a
3 changed files with 135 additions and 8 deletions

View File

@ -1,6 +1,7 @@
package http package http
import ( import (
"fmt"
"net/http" "net/http"
"strconv" "strconv"
"time" "time"
@ -71,24 +72,82 @@ func (h *Handler) budgeting(c *gin.Context) {
} }
categories, err := h.Service.DB.GetCategoriesWithBalance(c.Request.Context(), params) categories, err := h.Service.DB.GetCategoriesWithBalance(c.Request.Context(), params)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("load categories: %w", err))
return return
} }
availableParams := postgres.GetAvailableBalanceParams{ cumultativeBalances, err := h.Service.DB.GetCumultativeBalances(c.Request.Context(), budgetUUID)
BudgetID: budgetUUID,
FromDate: firstOfNextMonth,
}
availableBalance, err := h.Service.DB.GetAvailableBalance(c.Request.Context(), availableParams)
if err != nil { if err != nil {
c.AbortWithError(http.StatusInternalServerError, err) c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("load balances: %w", err))
return return
} }
var available float64 = 0
var added float64 = 0
var assigned float64 = 0
for i := range categories {
cat := &categories[i]
var balance float64 = 0
for _, bal := range cumultativeBalances {
if bal.CategoryID != cat.ID {
continue
}
// skip everything in the future
if !bal.Date.Before(firstOfNextMonth) {
continue
}
assigned += bal.Assignments.GetFloat64()
balance += bal.Assignments.GetFloat64()
balance += bal.Transactions.GetFloat64()
if balance < 0 && bal.Date.Before(firstOfMonth) {
added -= balance
balance = 0
}
if bal.Date.Before(firstOfMonth) {
available = balance
}
}
num := postgres.Numeric{}
num.Set(balance)
cat.Available = num
num2 := postgres.Numeric{}
num2.Set(available)
cat.AvailableLastMonth = num2
}
data := c.MustGet("data").(AlwaysNeededData)
var availableBalance float64 = 0
for _, cat := range categories {
if cat.ID != data.Budget.IncomeCategoryID {
continue
}
availableBalance = -assigned - added
for _, bal := range cumultativeBalances {
if bal.CategoryID != cat.ID {
continue
}
if !bal.Date.Before(firstOfNextMonth) {
continue
}
availableBalance += bal.Transactions.GetFloat64()
}
}
var availableBalanceNum postgres.Numeric
availableBalanceNum.Set(availableBalance)
d := BudgetingData{ d := BudgetingData{
c.MustGet("data").(AlwaysNeededData), c.MustGet("data").(AlwaysNeededData),
categories, categories,
availableBalance, availableBalanceNum,
firstOfMonth, firstOfMonth,
firstOfNextMonth, firstOfNextMonth,
firstOfPreviousMonth, firstOfPreviousMonth,

View File

@ -0,0 +1,60 @@
// Code generated by sqlc. DO NOT EDIT.
// source: cumultative-balances.sql
package postgres
import (
"context"
"time"
"github.com/google/uuid"
)
const getCumultativeBalances = `-- name: GetCumultativeBalances :many
SELECT COALESCE(ass.date, tra.date), COALESCE(ass.category_id, tra.category_id),
COALESCE(ass.amount, 0)::decimal(12,2) as assignments, SUM(ass.amount) OVER (PARTITION BY ass.category_id ORDER BY ass.date)::decimal(12,2) as assignments_cum,
COALESCE(tra.amount, 0)::decimal(12,2) as transactions, SUM(tra.amount) OVER (PARTITION BY tra.category_id ORDER BY tra.date)::decimal(12,2) as transactions_cum
FROM assignments_by_month as ass
FULL OUTER JOIN transactions_by_month as tra ON ass.date = tra.date AND ass.category_id = tra.category_id
WHERE (ass.budget_id IS NULL OR ass.budget_id = $1) AND (tra.budget_id IS NULL OR tra.budget_id = $1)
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
}
func (q *Queries) GetCumultativeBalances(ctx context.Context, budgetID uuid.UUID) ([]GetCumultativeBalancesRow, error) {
rows, err := q.db.QueryContext(ctx, getCumultativeBalances, budgetID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetCumultativeBalancesRow
for rows.Next() {
var i GetCumultativeBalancesRow
if err := rows.Scan(
&i.Date,
&i.CategoryID,
&i.Assignments,
&i.AssignmentsCum,
&i.Transactions,
&i.TransactionsCum,
); 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

@ -0,0 +1,8 @@
-- name: GetCumultativeBalances :many
SELECT COALESCE(ass.date, tra.date), COALESCE(ass.category_id, tra.category_id),
COALESCE(ass.amount, 0)::decimal(12,2) as assignments, SUM(ass.amount) OVER (PARTITION BY ass.category_id ORDER BY ass.date)::decimal(12,2) as assignments_cum,
COALESCE(tra.amount, 0)::decimal(12,2) as transactions, SUM(tra.amount) OVER (PARTITION BY tra.category_id ORDER BY tra.date)::decimal(12,2) as transactions_cum
FROM assignments_by_month as ass
FULL OUTER JOIN transactions_by_month as tra ON ass.date = tra.date AND ass.category_id = tra.category_id
WHERE (ass.budget_id IS NULL OR ass.budget_id = @budget_id) AND (tra.budget_id IS NULL OR tra.budget_id = @budget_id)
ORDER BY COALESCE(ass.date, tra.date), COALESCE(ass.category_id, tra.category_id);