Skip to content

Commit f058a57

Browse files
committed
feat: sum available for budgeting
1 parent 2e14b83 commit f058a57

File tree

6 files changed

+46
-2
lines changed

6 files changed

+46
-2
lines changed

api/docs.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2676,6 +2676,10 @@ const docTemplate = `{
26762676
"models.BudgetMonth": {
26772677
"type": "object",
26782678
"properties": {
2679+
"available": {
2680+
"type": "number",
2681+
"example": 217.34
2682+
},
26792683
"budgeted": {
26802684
"type": "number",
26812685
"example": 2100

api/swagger.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2664,6 +2664,10 @@
26642664
"models.BudgetMonth": {
26652665
"type": "object",
26662666
"properties": {
2667+
"available": {
2668+
"type": "number",
2669+
"example": 217.34
2670+
},
26672671
"budgeted": {
26682672
"type": "number",
26692673
"example": 2100

api/swagger.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,9 @@ definitions:
430430
type: object
431431
models.BudgetMonth:
432432
properties:
433+
available:
434+
example: 217.34
435+
type: number
433436
budgeted:
434437
example: 2100
435438
type: number

pkg/controllers/budget.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,13 +358,21 @@ func GetBudgetMonth(c *gin.Context) {
358358
return
359359
}
360360

361+
// Get the available sum for budgeting
362+
available, err := budget.Available(month.Month)
363+
if err != nil {
364+
httperrors.Handler(c, err)
365+
return
366+
}
367+
361368
c.JSON(http.StatusOK, BudgetMonthResponse{Data: models.BudgetMonth{
362369
ID: budget.ID,
363370
Name: budget.Name,
364371
Month: month.Month,
365372
Income: income,
366373
Budgeted: budgeted,
367374
Envelopes: envelopeMonths,
375+
Available: available,
368376
}})
369377
}
370378

pkg/models/budget.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type BudgetMonth struct {
3131
Month time.Time `json:"month" example:"2006-05-01T00:00:00.000000Z"` // This is always set to 00:00 UTC on the first of the month.
3232
Budgeted decimal.Decimal `json:"budgeted" example:"2100"`
3333
Income decimal.Decimal `json:"income" example:"2317.34"`
34+
Available decimal.Decimal `json:"available" example:"217.34"`
3435
Envelopes []EnvelopeMonth `json:"envelopes"`
3536
}
3637

@@ -88,6 +89,26 @@ func (b Budget) Income(t time.Time) (decimal.Decimal, error) {
8889
return income.Decimal, nil
8990
}
9091

92+
// Available calculates the amount that is available to be budgeted in the specified monht.
93+
func (b Budget) Available(month time.Time) (decimal.Decimal, error) {
94+
income, err := b.TotalIncome(month)
95+
if err != nil {
96+
return decimal.Zero, err
97+
}
98+
99+
overspent, err := b.Overspent(month)
100+
if err != nil {
101+
return decimal.Zero, err
102+
}
103+
104+
budgeted, err := b.TotalBudgeted(month)
105+
if err != nil {
106+
return decimal.Zero, err
107+
}
108+
109+
return income.Sub(overspent).Sub(budgeted), nil
110+
}
111+
91112
// TotalIncome calculates the total income over all time.
92113
func (b Budget) TotalIncome(month time.Time) (decimal.Decimal, error) {
93114
// Only use the year and month values, everything else is reset to the start
@@ -169,7 +190,7 @@ func (b Budget) Overspent(month time.Time) (decimal.Decimal, error) {
169190

170191
var overspent decimal.Decimal
171192
for _, envelope := range envelopes {
172-
spent := envelope.Spent(month)
193+
spent := envelope.Spent(month.AddDate(0, -1, 0))
173194
if spent.IsNegative() {
174195
overspent = overspent.Add(spent.Neg())
175196
}

pkg/models/budget_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,11 @@ func (suite *TestSuiteEnv) TestBudgetCalculations() {
275275
// Verify overspent calculation for month with spend
276276
overspent, err = budget.Overspent(marchFifteenthTwentyTwentyTwo)
277277
assert.Nil(suite.T(), err)
278-
assert.True(suite.T(), overspent.Equal(decimal.NewFromFloat(130.62)), "Overspent is %s, should be 130.62", overspent)
278+
assert.True(suite.T(), overspent.Equal(decimal.NewFromFloat(20)), "Overspent is %s, should be 20", overspent)
279+
280+
available, err := budget.Available(marchFifteenthTwentyTwentyTwo)
281+
assert.Nil(suite.T(), err)
282+
assert.True(suite.T(), available.Equal(decimal.NewFromFloat(4513)), "Available is %s, should be 4513", available)
279283
}
280284

281285
func (suite *TestSuiteEnv) TestMonthIncomeNoTransactions() {

0 commit comments

Comments
 (0)