Try to calculate balances locally
This commit is contained in:
parent
625e0635fd
commit
13993b6b5a
@ -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,
|
||||||
|
60
postgres/cumultative-balances.sql.go
Normal file
60
postgres/cumultative-balances.sql.go
Normal 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
|
||||||
|
}
|
8
postgres/queries/cumultative-balances.sql
Normal file
8
postgres/queries/cumultative-balances.sql
Normal 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);
|
Loading…
x
Reference in New Issue
Block a user