Merge pull request 'Improve available balance and show overspent last month' (#54) from available-balance into master
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #54
This commit is contained in:
commit
e1c6bd22d5
@ -11,10 +11,10 @@ RETURNING id;
|
|||||||
-- name: UpdateTransaction :exec
|
-- name: UpdateTransaction :exec
|
||||||
UPDATE transactions
|
UPDATE transactions
|
||||||
SET date = $1,
|
SET date = $1,
|
||||||
memo = $2,
|
memo = $2,
|
||||||
amount = $3,
|
amount = $3,
|
||||||
payee_id = $4,
|
payee_id = $4,
|
||||||
category_id = $5
|
category_id = $5
|
||||||
WHERE id = $6;
|
WHERE id = $6;
|
||||||
|
|
||||||
-- name: SetTransactionReconciled :exec
|
-- name: SetTransactionReconciled :exec
|
||||||
|
@ -294,10 +294,10 @@ func (q *Queries) SetTransactionReconciled(ctx context.Context, id uuid.UUID) er
|
|||||||
const updateTransaction = `-- name: UpdateTransaction :exec
|
const updateTransaction = `-- name: UpdateTransaction :exec
|
||||||
UPDATE transactions
|
UPDATE transactions
|
||||||
SET date = $1,
|
SET date = $1,
|
||||||
memo = $2,
|
memo = $2,
|
||||||
amount = $3,
|
amount = $3,
|
||||||
payee_id = $4,
|
payee_id = $4,
|
||||||
category_id = $5
|
category_id = $5
|
||||||
WHERE id = $6
|
WHERE id = $6
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -66,16 +66,17 @@ func (h *Handler) getBudgetingViewForMonth(ctx context.Context, budget postgres.
|
|||||||
return BudgetingForMonthResponse{}, fmt.Errorf("error loading balances: %w", err)
|
return BudgetingForMonthResponse{}, fmt.Errorf("error loading balances: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
categoriesWithBalance, moneyUsed := h.calculateBalances(budget, month, categories, cumultativeBalances)
|
categoriesWithBalance, moneyUsed, overspentLastMonth := h.calculateBalances(budget, month, categories, cumultativeBalances)
|
||||||
availableBalance := h.getAvailableBalance(budget, month, moneyUsed, cumultativeBalances)
|
availableBalance := h.getAvailableBalance(budget, month, moneyUsed, cumultativeBalances)
|
||||||
|
|
||||||
data := BudgetingForMonthResponse{categoriesWithBalance, availableBalance}
|
data := BudgetingForMonthResponse{categoriesWithBalance, availableBalance, overspentLastMonth}
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type BudgetingForMonthResponse struct {
|
type BudgetingForMonthResponse struct {
|
||||||
Categories []CategoryWithBalance
|
Categories []CategoryWithBalance
|
||||||
AvailableBalance numeric.Numeric
|
AvailableBalance numeric.Numeric
|
||||||
|
OverspentLastMonth numeric.Numeric
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Handler) getAvailableBalance(budget postgres.Budget, month Month,
|
func (*Handler) getAvailableBalance(budget postgres.Budget, month Month,
|
||||||
@ -135,10 +136,11 @@ func (h *Handler) getBudget(c *gin.Context, budgetUUID uuid.UUID) {
|
|||||||
|
|
||||||
func (h *Handler) calculateBalances(budget postgres.Budget, month Month,
|
func (h *Handler) calculateBalances(budget postgres.Budget, month Month,
|
||||||
categories []postgres.GetCategoriesRow, cumultativeBalances []postgres.GetCumultativeBalancesRow,
|
categories []postgres.GetCategoriesRow, cumultativeBalances []postgres.GetCumultativeBalancesRow,
|
||||||
) ([]CategoryWithBalance, numeric.Numeric) {
|
) ([]CategoryWithBalance, numeric.Numeric, numeric.Numeric) {
|
||||||
categoriesWithBalance := []CategoryWithBalance{}
|
categoriesWithBalance := []CategoryWithBalance{}
|
||||||
|
|
||||||
moneyUsed := numeric.Zero()
|
moneyUsed := numeric.Zero()
|
||||||
|
overspentLastMonth := numeric.Zero()
|
||||||
categories = append(categories, postgres.GetCategoriesRow{
|
categories = append(categories, postgres.GetCategoriesRow{
|
||||||
Group: "Income",
|
Group: "Income",
|
||||||
Name: "No Category",
|
Name: "No Category",
|
||||||
@ -172,6 +174,9 @@ func (h *Handler) calculateBalances(budget postgres.Budget, month Month,
|
|||||||
categoryWithBalance.AvailableLastMonth.AddI(bal.Transactions)
|
categoryWithBalance.AvailableLastMonth.AddI(bal.Transactions)
|
||||||
if !categoryWithBalance.AvailableLastMonth.IsPositive() {
|
if !categoryWithBalance.AvailableLastMonth.IsPositive() {
|
||||||
moneyUsed.AddI(categoryWithBalance.AvailableLastMonth)
|
moneyUsed.AddI(categoryWithBalance.AvailableLastMonth)
|
||||||
|
if month.Previous().InPresent(bal.Date) {
|
||||||
|
overspentLastMonth.AddI(categoryWithBalance.AvailableLastMonth)
|
||||||
|
}
|
||||||
categoryWithBalance.AvailableLastMonth = numeric.Zero()
|
categoryWithBalance.AvailableLastMonth = numeric.Zero()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,5 +184,5 @@ func (h *Handler) calculateBalances(budget postgres.Budget, month Month,
|
|||||||
categoriesWithBalance = append(categoriesWithBalance, categoryWithBalance)
|
categoriesWithBalance = append(categoriesWithBalance, categoryWithBalance)
|
||||||
}
|
}
|
||||||
|
|
||||||
return categoriesWithBalance, moneyUsed
|
return categoriesWithBalance, moneyUsed, overspentLastMonth
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,22 @@ func (m Month) FirstOfMonth() time.Time {
|
|||||||
return time.Date(m.Year, time.Month(m.Month), 1, 0, 0, 0, 0, time.Now().Location())
|
return time.Date(m.Year, time.Month(m.Month), 1, 0, 0, 0, 0, time.Now().Location())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Month) Previous() Month {
|
||||||
|
if m.Month == int(time.January) {
|
||||||
|
return Month{Year: m.Year - 1, Month: int(time.December)}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Month{Year: m.Year, Month: m.Month - 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Month) Next() Month {
|
||||||
|
if m.Month == int(time.December) {
|
||||||
|
return Month{Year: m.Year + 1, Month: int(time.January)}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Month{Year: m.Year, Month: m.Month + 1}
|
||||||
|
}
|
||||||
|
|
||||||
func (m Month) InFuture(date time.Time) bool {
|
func (m Month) InFuture(date time.Time) bool {
|
||||||
if m.Year < date.Year() {
|
if m.Year < date.Year() {
|
||||||
return true
|
return true
|
||||||
|
@ -78,29 +78,54 @@ const budgeted = computed(() => accountStore.GetBudgeted(selected.value.Year, se
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h1>Budget for {{ selected.Month + 1 }}/{{ selected.Year }}</h1>
|
<h1>Budget for {{ selected.Month + 1 }}/{{ selected.Year }}</h1>
|
||||||
<span>
|
<table class="inline-block">
|
||||||
Available last month:
|
<tr>
|
||||||
<Currency
|
<td>
|
||||||
:value="accountStore.GetIncomeAvailable(previous.Year, previous.Month)"
|
Available last month:
|
||||||
/>
|
</td>
|
||||||
</span><br>
|
<td class="text-right">
|
||||||
<span>Available balance:
|
<Currency :value="accountStore.Available-accountStore.OverspentLastMonth+budgeted.Assigned+budgeted.Deassigned" />
|
||||||
<Currency
|
</td>
|
||||||
:value="accountStore.GetIncomeAvailable(selected.Year, selected.Month)"
|
</tr>
|
||||||
/>
|
<tr>
|
||||||
</span><br>
|
<td>
|
||||||
<span>Budgeted this month:
|
Overspent last month:
|
||||||
<Currency :value="budgeted.Assigned" /> - <Currency :value="-budgeted.Deassigned" /> = <Currency :value="budgeted.Assigned+budgeted.Deassigned" />
|
</td>
|
||||||
</span><br>
|
<td class="text-right">
|
||||||
<span>Income:
|
<Currency :value="accountStore.OverspentLastMonth" />
|
||||||
<Currency
|
</td>
|
||||||
:value="budgeted.Income"
|
</tr>
|
||||||
/> <Currency
|
<tr>
|
||||||
:value="budgeted.Spent"
|
<td>
|
||||||
/> = <Currency
|
Budgeted this month:
|
||||||
:value="budgeted.Income + budgeted.Spent"
|
</td>
|
||||||
/>
|
<td class="text-right">
|
||||||
</span><br>
|
<Currency :value="budgeted.Assigned+budgeted.Deassigned" />
|
||||||
|
</td>
|
||||||
|
<td class="text-sm pl-2">
|
||||||
|
= <Currency :value="budgeted.Assigned" /> - <Currency :value="-budgeted.Deassigned" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="font-bold">
|
||||||
|
<td class="py-2">
|
||||||
|
Available balance:
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<Currency :value="accountStore.Available" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Activity:
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<Currency :value="budgeted.Income + budgeted.Spent" />
|
||||||
|
</td>
|
||||||
|
<td class="text-sm pl-2">
|
||||||
|
= <Currency :value="budgeted.Income" /> - <Currency :value="-1 * budgeted.Spent" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
<div>
|
<div>
|
||||||
<router-link
|
<router-link
|
||||||
:to="'/budget/' + CurrentBudgetID + '/budgeting/' + previous.Year + '/' + previous.Month"
|
:to="'/budget/' + CurrentBudgetID + '/budgeting/' + previous.Year + '/' + previous.Month"
|
||||||
|
@ -9,7 +9,8 @@ interface State {
|
|||||||
CurrentAccountID: string | null;
|
CurrentAccountID: string | null;
|
||||||
Categories: Map<string, Category>;
|
Categories: Map<string, Category>;
|
||||||
Months: Map<number, Map<number, Map<string, Category>>>;
|
Months: Map<number, Map<number, Map<string, Category>>>;
|
||||||
Available: Map<number, Map<number, number>>;
|
Available: number,
|
||||||
|
OverspentLastMonth: number,
|
||||||
Assignments: [];
|
Assignments: [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +52,8 @@ export const useAccountStore = defineStore("budget/account", {
|
|||||||
Accounts: new Map<string, Account>(),
|
Accounts: new Map<string, Account>(),
|
||||||
CurrentAccountID: null,
|
CurrentAccountID: null,
|
||||||
Months: new Map<number, Map<number, Map<string, Category>>>(),
|
Months: new Map<number, Map<number, Map<string, Category>>>(),
|
||||||
Available: new Map<number, Map<number, number>>(),
|
Available: 0,
|
||||||
|
OverspentLastMonth: 0,
|
||||||
Categories: new Map<string, Category>(),
|
Categories: new Map<string, Category>(),
|
||||||
Assignments: [],
|
Assignments: [],
|
||||||
}),
|
}),
|
||||||
@ -107,12 +109,6 @@ export const useAccountStore = defineStore("budget/account", {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
GetIncomeAvailable(state) {
|
|
||||||
return (year: number, month: number) => {
|
|
||||||
const yearMapAv = this.Available.get(year);
|
|
||||||
return yearMapAv?.get(month);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
CategoryGroupsForMonth(state) {
|
CategoryGroupsForMonth(state) {
|
||||||
return (year: number, month: number) => {
|
return (year: number, month: number) => {
|
||||||
const categories = this.AllCategoriesForMonth(year, month);
|
const categories = this.AllCategoriesForMonth(year, month);
|
||||||
@ -215,7 +211,7 @@ export const useAccountStore = defineStore("budget/account", {
|
|||||||
response.Categories.length <= 0
|
response.Categories.length <= 0
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
this.addCategoriesForMonth(year, month, response.Categories, response.AvailableBalance);
|
this.addCategoriesForMonth(year, month, response.Categories, response.AvailableBalance, response.OverspentLastMonth);
|
||||||
},
|
},
|
||||||
async EditAccount(
|
async EditAccount(
|
||||||
accountid: string,
|
accountid: string,
|
||||||
@ -242,7 +238,8 @@ export const useAccountStore = defineStore("budget/account", {
|
|||||||
year: number,
|
year: number,
|
||||||
month: number,
|
month: number,
|
||||||
categories: Category[],
|
categories: Category[],
|
||||||
available: number
|
available: number,
|
||||||
|
overspentLastMonth: number,
|
||||||
): void {
|
): void {
|
||||||
this.$patch((state) => {
|
this.$patch((state) => {
|
||||||
const yearMap =
|
const yearMap =
|
||||||
@ -257,11 +254,8 @@ export const useAccountStore = defineStore("budget/account", {
|
|||||||
yearMap.set(month, monthMap);
|
yearMap.set(month, monthMap);
|
||||||
state.Months.set(year, yearMap);
|
state.Months.set(year, yearMap);
|
||||||
|
|
||||||
const yearMapAv =
|
state.Available = available;
|
||||||
state.Available.get(year) ||
|
state.OverspentLastMonth = overspentLastMonth;
|
||||||
new Map<number, number>();
|
|
||||||
yearMapAv.set(month, available);
|
|
||||||
state.Available.set(year, yearMapAv);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
logout() {
|
logout() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user