Use Numeric in JSON output

This commit is contained in:
Jan Bader 2022-02-06 22:12:48 +00:00
parent 5763409aa8
commit 487aa89f18
11 changed files with 258 additions and 118 deletions

54
http/autocomplete.go Normal file
View File

@ -0,0 +1,54 @@
package http
import (
"fmt"
"net/http"
"git.javil.eu/jacob1123/budgeteer/postgres"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
func (h *Handler) autocompleteCategories(c *gin.Context) {
budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID)
if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("budgetid missing from URL"))
return
}
query := c.Request.URL.Query().Get("s")
searchParams := postgres.SearchCategoriesParams{
BudgetID: budgetUUID,
Search: "%" + query + "%",
}
categories, err := h.Service.SearchCategories(c.Request.Context(), searchParams)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
c.JSON(http.StatusOK, categories)
}
func (h *Handler) autocompletePayee(c *gin.Context) {
budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID)
if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("budgetid missing from URL"))
return
}
query := c.Request.URL.Query().Get("s")
searchParams := postgres.SearchPayeesParams{
BudgetID: budgetUUID,
Search: query + "%",
}
payees, err := h.Service.SearchPayees(c.Request.Context(), searchParams)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
c.JSON(http.StatusOK, payees)
}

View File

@ -24,10 +24,10 @@ func getFirstOfMonthTime(date time.Time) time.Time {
type CategoryWithBalance struct { type CategoryWithBalance struct {
*postgres.GetCategoriesRow *postgres.GetCategoriesRow
Available float64 Available postgres.Numeric
AvailableLastMonth float64 AvailableLastMonth postgres.Numeric
Activity float64 Activity postgres.Numeric
Assigned float64 Assigned postgres.Numeric
} }
func getDate(c *gin.Context) (time.Time, error) { func getDate(c *gin.Context) (time.Time, error) {
@ -51,50 +51,6 @@ func getDate(c *gin.Context) (time.Time, error) {
return getFirstOfMonth(year, month, time.Now().Location()), nil return getFirstOfMonth(year, month, time.Now().Location()), nil
} }
func (h *Handler) autocompleteCategories(c *gin.Context) {
budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID)
if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("budgetid missing from URL"))
return
}
query := c.Request.URL.Query().Get("s")
searchParams := postgres.SearchCategoriesParams{
BudgetID: budgetUUID,
Search: "%" + query + "%",
}
categories, err := h.Service.SearchCategories(c.Request.Context(), searchParams)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
c.JSON(http.StatusOK, categories)
}
func (h *Handler) autocompletePayee(c *gin.Context) {
budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID)
if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("budgetid missing from URL"))
return
}
query := c.Request.URL.Query().Get("s")
searchParams := postgres.SearchPayeesParams{
BudgetID: budgetUUID,
Search: query + "%",
}
payees, err := h.Service.SearchPayees(c.Request.Context(), searchParams)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
c.JSON(http.StatusOK, payees)
}
func (h *Handler) budgetingForMonth(c *gin.Context) { func (h *Handler) budgetingForMonth(c *gin.Context) {
budgetID := c.Param("budgetid") budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID) budgetUUID, err := uuid.Parse(budgetID)
@ -134,7 +90,7 @@ func (h *Handler) budgetingForMonth(c *gin.Context) {
return return
} }
var availableBalance float64 = 0 availableBalance := postgres.NewZeroNumeric()
for _, cat := range categories { for _, cat := range categories {
if cat.ID != budget.IncomeCategoryID { if cat.ID != budget.IncomeCategoryID {
continue continue
@ -150,13 +106,13 @@ func (h *Handler) budgetingForMonth(c *gin.Context) {
continue continue
} }
availableBalance += bal.Transactions.GetFloat64() availableBalance = availableBalance.Add(bal.Transactions)
} }
} }
data := struct { data := struct {
Categories []CategoryWithBalance Categories []CategoryWithBalance
AvailableBalance float64 AvailableBalance postgres.Numeric
}{categoriesWithBalance, availableBalance} }{categoriesWithBalance, availableBalance}
c.JSON(http.StatusOK, data) c.JSON(http.StatusOK, data)
@ -182,39 +138,36 @@ func (h *Handler) budgeting(c *gin.Context) {
return return
} }
categories, err := h.Service.GetCategories(c.Request.Context(), budgetUUID)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
data := struct { data := struct {
Budget postgres.Budget Accounts []postgres.GetAccountsWithBalanceRow
Accounts []postgres.GetAccountsWithBalanceRow Budget postgres.Budget
Categories []postgres.GetCategoriesRow }{accounts, budget}
}{
Accounts: accounts,
Budget: budget,
Categories: categories,
}
c.JSON(http.StatusOK, data) c.JSON(http.StatusOK, data)
} }
func (h *Handler) calculateBalances(c *gin.Context, budget postgres.Budget, firstOfNextMonth time.Time, firstOfMonth time.Time, categories []postgres.GetCategoriesRow, cumultativeBalances []postgres.GetCumultativeBalancesRow) ([]CategoryWithBalance, float64, error) { func (h *Handler) calculateBalances(c *gin.Context, budget postgres.Budget, firstOfNextMonth time.Time, firstOfMonth time.Time, categories []postgres.GetCategoriesRow, cumultativeBalances []postgres.GetCumultativeBalancesRow) ([]CategoryWithBalance, postgres.Numeric, error) {
categoriesWithBalance := []CategoryWithBalance{} categoriesWithBalance := []CategoryWithBalance{}
hiddenCategory := CategoryWithBalance{ hiddenCategory := CategoryWithBalance{
GetCategoriesRow: &postgres.GetCategoriesRow{ GetCategoriesRow: &postgres.GetCategoriesRow{
Name: "", Name: "",
Group: "Hidden Categories", Group: "Hidden Categories",
}, },
Available: postgres.NewZeroNumeric(),
AvailableLastMonth: postgres.NewZeroNumeric(),
Activity: postgres.NewZeroNumeric(),
Assigned: postgres.NewZeroNumeric(),
} }
var moneyUsed float64 = 0 moneyUsed := postgres.NewZeroNumeric()
for i := range categories { for i := range categories {
cat := &categories[i] cat := &categories[i]
categoryWithBalance := CategoryWithBalance{ categoryWithBalance := CategoryWithBalance{
GetCategoriesRow: cat, GetCategoriesRow: cat,
Available: postgres.NewZeroNumeric(),
AvailableLastMonth: postgres.NewZeroNumeric(),
Activity: postgres.NewZeroNumeric(),
Assigned: postgres.NewZeroNumeric(),
} }
for _, bal := range cumultativeBalances { for _, bal := range cumultativeBalances {
if bal.CategoryID != cat.ID { if bal.CategoryID != cat.ID {
@ -225,29 +178,29 @@ func (h *Handler) calculateBalances(c *gin.Context, budget postgres.Budget, firs
continue continue
} }
moneyUsed -= bal.Assignments.GetFloat64() moneyUsed = moneyUsed.Sub(bal.Assignments)
categoryWithBalance.Available += bal.Assignments.GetFloat64() categoryWithBalance.Available = categoryWithBalance.Available.Add(bal.Assignments)
categoryWithBalance.Available += bal.Transactions.GetFloat64() categoryWithBalance.Available = categoryWithBalance.Available.Add(bal.Transactions)
if categoryWithBalance.Available < 0 && bal.Date.Before(firstOfMonth) { if !categoryWithBalance.Available.IsPositive() && bal.Date.Before(firstOfMonth) {
moneyUsed += categoryWithBalance.Available moneyUsed = moneyUsed.Add(categoryWithBalance.Available)
categoryWithBalance.Available = 0 categoryWithBalance.Available = postgres.NewZeroNumeric()
} }
if bal.Date.Before(firstOfMonth) { if bal.Date.Before(firstOfMonth) {
categoryWithBalance.AvailableLastMonth = categoryWithBalance.Available categoryWithBalance.AvailableLastMonth = categoryWithBalance.Available
} else if bal.Date.Before(firstOfNextMonth) { } else if bal.Date.Before(firstOfNextMonth) {
categoryWithBalance.Activity = bal.Transactions.GetFloat64() categoryWithBalance.Activity = bal.Transactions
categoryWithBalance.Assigned = bal.Assignments.GetFloat64() categoryWithBalance.Assigned = bal.Assignments
} }
} }
// do not show hidden categories // do not show hidden categories
if cat.Group == "Hidden Categories" { if cat.Group == "Hidden Categories" {
hiddenCategory.Available += categoryWithBalance.Available hiddenCategory.Available = hiddenCategory.Available.Add(categoryWithBalance.Available)
hiddenCategory.AvailableLastMonth += categoryWithBalance.AvailableLastMonth hiddenCategory.AvailableLastMonth = hiddenCategory.AvailableLastMonth.Add(categoryWithBalance.AvailableLastMonth)
hiddenCategory.Activity += categoryWithBalance.Activity hiddenCategory.Activity = hiddenCategory.Activity.Add(categoryWithBalance.Activity)
hiddenCategory.Assigned += categoryWithBalance.Assigned hiddenCategory.Assigned = hiddenCategory.Assigned.Add(categoryWithBalance.Assigned)
continue continue
} }

View File

@ -64,6 +64,7 @@ func (h *Handler) Serve() {
authenticated.GET("/account/:accountid/transactions", h.transactionsForAccount) authenticated.GET("/account/:accountid/transactions", h.transactionsForAccount)
authenticated.GET("/admin/clear-database", h.clearDatabase) authenticated.GET("/admin/clear-database", h.clearDatabase)
authenticated.GET("/budget/:budgetid", h.budgeting) authenticated.GET("/budget/:budgetid", h.budgeting)
authenticated.GET("/budget/:budgetid/:year/:month", h.budgetingForMonth)
authenticated.GET("/budget/:budgetid/autocomplete/payees", h.autocompletePayee) authenticated.GET("/budget/:budgetid/autocomplete/payees", h.autocompletePayee)
authenticated.GET("/budget/:budgetid/autocomplete/categories", h.autocompleteCategories) authenticated.GET("/budget/:budgetid/autocomplete/categories", h.autocompleteCategories)
authenticated.DELETE("/budget/:budgetid", h.deleteBudget) authenticated.DELETE("/budget/:budgetid", h.deleteBudget)

View File

@ -1,11 +1,20 @@
package postgres package postgres
import "github.com/jackc/pgtype" import (
"fmt"
"math/big"
"github.com/jackc/pgtype"
)
type Numeric struct { type Numeric struct {
pgtype.Numeric pgtype.Numeric
} }
func NewZeroNumeric() Numeric {
return Numeric{pgtype.Numeric{Exp: 0, Int: big.NewInt(0), Status: pgtype.Present, NaN: false}}
}
func (n Numeric) GetFloat64() float64 { func (n Numeric) GetFloat64() float64 {
if n.Status != pgtype.Present { if n.Status != pgtype.Present {
return 0 return 0
@ -33,3 +42,83 @@ func (n Numeric) IsZero() bool {
float := n.GetFloat64() float := n.GetFloat64()
return float == 0 return float == 0
} }
func (n Numeric) MatchExp(exp int32) Numeric {
diffExp := exp - n.Exp
factor := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(int64(diffExp)), nil)
return Numeric{pgtype.Numeric{
Exp: exp,
Int: big.NewInt(0).Mul(n.Int, factor),
Status: n.Status,
NaN: n.NaN,
}}
}
func (n Numeric) Sub(o Numeric) Numeric {
if n.Exp > o.Exp {
o = o.MatchExp(n.Exp)
} else if n.Exp < o.Exp {
n = n.MatchExp(o.Exp)
}
if o.Exp == n.Exp {
return Numeric{pgtype.Numeric{
Exp: n.Exp,
Int: big.NewInt(0).Sub(o.Int, n.Int),
}}
}
panic("Cannot subtract with different exponents")
}
func (n Numeric) Add(o Numeric) Numeric {
fmt.Println("N", n, "O", o)
if n.Exp > o.Exp {
o = o.MatchExp(n.Exp)
} else if n.Exp < o.Exp {
n = n.MatchExp(o.Exp)
}
fmt.Println("NM", n, "OM", o)
if o.Exp == n.Exp {
return Numeric{pgtype.Numeric{
Exp: n.Exp,
Int: big.NewInt(0).Add(o.Int, n.Int),
}}
}
panic("Cannot add with different exponents")
}
func (n Numeric) MarshalJSON() ([]byte, error) {
if n.Int.Int64() == 0 {
return []byte("\"0\""), nil
}
s := fmt.Sprintf("%d", n.Int)
bytes := []byte(s)
exp := n.Exp
for exp > 0 {
bytes = append(bytes, byte('0'))
exp--
}
if exp == 0 {
return bytes, nil
}
length := int32(len(bytes))
var bytesWithSeparator []byte
exp = -exp
for length <= exp {
bytes = append(bytes, byte('0'))
length++
}
split := length - exp
bytesWithSeparator = append(bytesWithSeparator, bytes[:split]...)
bytesWithSeparator = append(bytesWithSeparator, byte('.'))
bytesWithSeparator = append(bytesWithSeparator, bytes[split:]...)
return bytesWithSeparator, nil
}

View File

@ -0,0 +1,12 @@
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
props: ["value"]
})
</script>
<template>
<span :class="value < 0 ? 'negative' : ''">{{value.toLocaleString(undefined, {minimumFractionDigits: 2,})}} </span>
</template>

View File

@ -14,11 +14,6 @@ export default defineComponent({
}, },
components: { Autocomplete }, components: { Autocomplete },
props: ["budgetid", "accountid"], props: ["budgetid", "accountid"],
watch: {
Payee() {
console.log(this.$data.Payee);
}
},
methods: { methods: {
saveTransaction(e : MouseEvent) { saveTransaction(e : MouseEvent) {
e.preventDefault(); e.preventDefault();
@ -34,8 +29,7 @@ export default defineComponent({
}), }),
headers: this.$store.getters.AuthHeaders, headers: this.$store.getters.AuthHeaders,
}) })
.then(x => x.json()) .then(x => x.json());
.then(x => console.log(x));
}, },
} }
}) })

View File

@ -1,8 +1,10 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from "vue" import { defineComponent } from "vue"
import Currency from "../components/Currency.vue"
export default defineComponent({ export default defineComponent({
props: ['budgetid', 'accountid'], props: ["budgetid", "accountid"],
components: { Currency }
}) })
</script> </script>
@ -21,14 +23,14 @@ export default defineComponent({
On-Budget Accounts On-Budget Accounts
<div v-for="account in $store.getters.OnBudgetAccounts" class="flex flex-row justify-between px-3"> <div v-for="account in $store.getters.OnBudgetAccounts" class="flex flex-row justify-between px-3">
<router-link :to="'/budget/'+budgetid+'/account/'+account.ID">{{account.Name}}</router-link> <router-link :to="'/budget/'+budgetid+'/account/'+account.ID">{{account.Name}}</router-link>
<span :class="account.Balance.Int < 0 ? 'negative' : ''">{{(account.Balance.Int / 100).toLocaleString(undefined, {minimumFractionDigits: 2,})}} </span> <Currency :value="account.Balance" />
</div> </div>
</li> </li>
<li class="bg-red-200 rounded-lg m-1 p-1 px-3"> <li class="bg-red-200 rounded-lg m-1 p-1 px-3">
Off-Budget Accounts Off-Budget Accounts
<div v-for="account in $store.getters.OffBudgetAccounts" class="flex flex-row justify-between px-3"> <div v-for="account in $store.getters.OffBudgetAccounts" class="flex flex-row justify-between px-3">
<router-link :to="'/budget/'+budgetid+'/account/'+account.ID">{{account.Name}}</router-link> <router-link :to="'/budget/'+budgetid+'/account/'+account.ID">{{account.Name}}</router-link>
<span :class="account.Balance.Int < 0 ? 'negative' : ''">{{account.Balance.Int / 100}}</span> <Currency :value="account.Balance" />
</div> </div>
</li> </li>
<li class="bg-red-200 rounded-lg m-1 p-1 px-3"> <li class="bg-red-200 rounded-lg m-1 p-1 px-3">

View File

@ -1,38 +1,53 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from "vue"; import { defineComponent } from "vue";
import { FETCH_MONTH_BUDGET } from "../store/action-types";
import { TITLE } from "../store/mutation-types"; import { TITLE } from "../store/mutation-types";
import Currency from "../components/Currency.vue";
export default defineComponent({ export default defineComponent({
mounted() { mounted() {
this.$store.commit(TITLE, "Budget for " + this.month + " " + this.year) this.$store.commit(TITLE, "Budget for " + this.month + " " + this.year);
return this.$store.dispatch(FETCH_MONTH_BUDGET, { budgetid: this.budgetid, year: this.$data.Year, month: this.$data.Month });
},
watch: {
year() {
return this.$store.dispatch(FETCH_MONTH_BUDGET, { budgetid: this.budgetid, year: this.$data.Year, month: this.$data.Month });
},
month() {
return this.$store.dispatch(FETCH_MONTH_BUDGET, { budgetid: this.budgetid, year: this.$data.Year, month: this.$data.Month });
},
}, },
props: ["budgetid", "year", "month"], props: ["budgetid", "year", "month"],
data() { data() {
return { return {
Year: this.year || new Date().getFullYear(), Year: (this.year || new Date().getFullYear()) as number,
Month: this.month || new Date().getMonth() Month: (this.month || new Date().getMonth()) as number
} };
}, },
computed: { computed: {
Categories() {
return this.$store.getters.Categories(this.$data.Year, this.$data.Month);
},
previous() { previous() {
return { return {
Year: new Date(this.$data.Year, this.$data.Month - 1, 1).getFullYear(), Year: new Date(this.$data.Year, this.$data.Month - 1, 1).getFullYear(),
Month: new Date(this.$data.Year, this.$data.Month - 1, 1).getMonth(), Month: new Date(this.$data.Year, this.$data.Month - 1, 1).getMonth(),
} };
}, },
current() { current() {
return { return {
Year: new Date().getFullYear(), Year: new Date().getFullYear(),
Month: new Date().getMonth(), Month: new Date().getMonth(),
} };
}, },
next() { next() {
return { return {
Year: new Date(this.$data.Year, this.$data.Month + 1, 1).getFullYear(), Year: new Date(this.$data.Year, this.$data.Month + 1, 1).getFullYear(),
Month: new Date(this.$data.Year, this.$data.Month + 1, 1).getMonth(), Month: new Date(this.$data.Year, this.$data.Month + 1, 1).getMonth(),
} };
} }
} },
components: { Currency }
}) })
/*{{define "title"}} /*{{define "title"}}
@ -42,7 +57,7 @@ export default defineComponent({
<template> <template>
<h1> <h1>
Budget for {{current.Month}}/{{current.Year}} Budget for {{Month}}/{{Year}}
</h1> </h1>
<div> <div>
<router-link :to="'/budget/'+$store.getters.CurrentBudget.ID +'/' + previous.Year + '/' + previous.Month">Previous Month</router-link> - <router-link :to="'/budget/'+$store.getters.CurrentBudget.ID +'/' + previous.Year + '/' + previous.Month">Previous Month</router-link> -
@ -60,15 +75,15 @@ export default defineComponent({
<th>Activity</th> <th>Activity</th>
<th>Available</th> <th>Available</th>
</tr> </tr>
<tr v-for="category in $store.getters.Categories(2022, 1)"> <tr v-for="category in Categories">
<td>{{category.Group}}</td> <td>{{category.Group}}</td>
<td>{{category.Name}}</td> <td>{{category.Name}}</td>
<td></td> <td></td>
<td></td> <td></td>
<td>{{category.AvailableLastMonth}}</td> <td class="text-right"><Currency :value="category.AvailableLastMonth" /></td>
<td>{{category.Assigned}}</td> <td class="text-right"><Currency :value="category.Assigned" /></td>
<td>{{category.Activity}}</td> <td class="text-right"><Currency :value="category.Activity" /></td>
<td>{{category.Available}}</td> <td class="text-right"><Currency :value="category.Available" /></td>
</tr> </tr>
</table> </table>
</template> </template>

View File

@ -5,6 +5,7 @@ export const NEW_BUDGET = "New budget";
export const SET_CURRENT_BUDGET = "Set current budget"; export const SET_CURRENT_BUDGET = "Set current budget";
export const SET_CURRENT_ACCOUNT = "Set current account"; export const SET_CURRENT_ACCOUNT = "Set current account";
export const FETCH_BUDGET = "Fetch budget"; export const FETCH_BUDGET = "Fetch budget";
export const FETCH_MONTH_BUDGET = "Fetch budget for month";
export const LOGIN = 'Log in'; export const LOGIN = 'Log in';
export const REGISTER = 'Register'; export const REGISTER = 'Register';
export const FETCH_ACCOUNT = "Fetch account"; export const FETCH_ACCOUNT = "Fetch account";

View File

@ -1,11 +1,12 @@
import { Module } from "vuex"; import { Module } from "vuex";
import { FETCH_ACCOUNT, FETCH_BUDGET, SET_CURRENT_ACCOUNT } from "../action-types"; import { FETCH_ACCOUNT, FETCH_BUDGET, FETCH_MONTH_BUDGET, SET_CURRENT_ACCOUNT } from "../action-types";
import { LOGOUT, TITLE } from "../mutation-types"; import { LOGOUT, TITLE } from "../mutation-types";
export interface BudgetState { export interface BudgetState {
Accounts: Map<string, Account>, Accounts: Map<string, Account>,
CurrentAccountID?: string, CurrentAccountID?: string,
Categories: Map<string, Category>, Categories: Map<string, Category>,
Months: Map<number, Map<number, Map<string, Category>>>,
Transactions: [], Transactions: [],
Assignments: [] Assignments: []
} }
@ -28,6 +29,7 @@ export const budgetStore : Module<BudgetState, any> = {
state: { state: {
Accounts: new Map<string, Account>(), Accounts: new Map<string, Account>(),
CurrentAccountID: undefined, CurrentAccountID: undefined,
Months: new Map<number, Map<number, Map<string, Category>>>(),
Categories: new Map<string, Category>(), Categories: new Map<string, Category>(),
Transactions: [], Transactions: [],
Assignments: [] Assignments: []
@ -61,6 +63,17 @@ export const budgetStore : Module<BudgetState, any> = {
addCategory(state, category) { addCategory(state, category) {
state.Categories.set(category.ID, category); state.Categories.set(category.ID, category);
}, },
addCategoriesForMonth(state, {year, month, categories}) {
const yearMap = state.Months.get(year) || new Map<number, Map<string, Category>>();
state.Months.set(year, yearMap);
const monthMap = yearMap.get(month) || new Map<string, Category>();
yearMap.set(month, monthMap);
for (const category of categories){
monthMap.set(category.ID, category);
}
},
setCurrentAccountID(state, accountid) { setCurrentAccountID(state, accountid) {
state.CurrentAccountID = accountid; state.CurrentAccountID = accountid;
}, },
@ -74,7 +87,8 @@ export const budgetStore : Module<BudgetState, any> = {
return state.Accounts.values(); return state.Accounts.values();
}, },
Categories: (state) => (year : number, month : number) => { Categories: (state) => (year : number, month : number) => {
return state.Categories.values(); const yearMap = state.Months.get(year);
return yearMap?.get(month)?.values();
}, },
CurrentAccount(state) : Account | undefined { CurrentAccount(state) : Account | undefined {
if (state.CurrentAccountID == null) if (state.CurrentAccountID == null)
@ -113,5 +127,20 @@ export const budgetStore : Module<BudgetState, any> = {
const response = await result.json(); const response = await result.json();
commit("setTransactions", response.Transactions); commit("setTransactions", response.Transactions);
}, },
async [FETCH_BUDGET]({ state, commit, dispatch, rootState }, budgetid) {
const result = await dispatch("GET", { path: "/budget/" + budgetid });
const response = await result.json();
for (const account of response.Accounts || []) {
commit("addAccount", account);
}
for (const category of response.Categories || []) {
commit("addCategory", category);
}
},
async [FETCH_MONTH_BUDGET]({state, commit, dispatch, rootState }, {budgetid, month, year}) {
const result = await dispatch("GET", { path: "/budget/" + budgetid + "/" + year + "/" + month});
const response = await result.json();
commit("addCategoriesForMonth", {year, month, categories: response.Categories})
}
} }
} }

View File

@ -130,16 +130,6 @@ export const store = createStore<State>({
await dispatch(FETCH_BUDGET, budgetid) await dispatch(FETCH_BUDGET, budgetid)
}, },
async [FETCH_BUDGET]({ state, commit, dispatch, rootState }, budgetid) {
const result = await dispatch("GET", { path: "/budget/" + budgetid });
const response = await result.json();
for (const account of response.Accounts || []) {
commit("addAccount", account);
}
for (const category of response.Categories || []) {
commit("addCategory", category);
}
},
}, },
getters: { getters: {
Budgets(state) { Budgets(state) {