Try to calculate balances locally
This commit is contained in:
		| @@ -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); | ||||||
		Reference in New Issue
	
	Block a user