import { defineStore } from "pinia" import { GET, POST } from "../api"; import { useBudgetsStore } from "./budget"; import { useSessionStore } from "./session"; import { useTransactionsStore } from "./transactions"; interface State { Accounts: Map CurrentAccountID: string | null Categories: Map Months: Map>> Assignments: [] } export interface Account { ID: string Name: string OnBudget: boolean ClearedBalance: number WorkingBalance: number ReconciledBalance: number Transactions: string[] LastReconciled: Date } export interface Category { ID: string Group: string Name: string AvailableLastMonth: number Assigned: number Activity: number Available: number } export const useAccountStore = defineStore("budget/account", { state: (): State => ({ Accounts: new Map(), CurrentAccountID: null, Months: new Map>>(), Categories: new Map(), Assignments: [], }), getters: { AccountsList(state) { return [...state.Accounts.values()]; }, AllCategoriesForMonth: (state) => (year: number, month: number) => { const yearMap = state.Months.get(year); const monthMap = yearMap?.get(month); return [...monthMap?.values() || []]; }, CategoryGroupsForMonth(state) { return (year: number, month: number) => { const categories = this.AllCategoriesForMonth(year, month); const categoryGroups = []; let prev = undefined; for (const category of categories) { if (category.Group != prev) categoryGroups.push({ Name: category.Group, Expand: category.Group != "Hidden Categories", }); prev = category.Group; } return categoryGroups; } }, CategoriesForMonthAndGroup(state) { return (year: number, month: number, group: string) => { const categories = this.AllCategoriesForMonth(year, month); return categories.filter(x => x.Group == group); } }, GetAccount(state) { return (accountid: string) => { return this.Accounts.get(accountid); } }, CurrentAccount(state): Account | undefined { if (state.CurrentAccountID == null) return undefined; return this.GetAccount(state.CurrentAccountID); }, OnBudgetAccounts(state) { return [...state.Accounts.values()].filter(x => x.OnBudget); }, OnBudgetAccountsBalance(state): number { return this.OnBudgetAccounts.reduce((prev, curr) => prev + Number(curr.ClearedBalance), 0); }, OffBudgetAccounts(state) { return [...state.Accounts.values()].filter(x => !x.OnBudget); }, OffBudgetAccountsBalance(state): number { return this.OffBudgetAccounts.reduce((prev, curr) => prev + Number(curr.ClearedBalance), 0); }, }, actions: { async SetCurrentAccount(budgetid: string, accountid: string) { if (budgetid == null) return; this.CurrentAccountID = accountid; if (accountid == null) return; const account = this.GetAccount(accountid)!; useSessionStore().setTitle(account.Name); await this.FetchAccount(account); }, async FetchAccount(account: Account) { const result = await GET("/account/" + account.ID + "/transactions"); const response = await result.json(); const transactionsStore = useTransactionsStore() const transactions = transactionsStore.AddTransactions(response.Transactions); account.Transactions = transactions; }, async FetchMonthBudget(budgetid: string, year: number, month: number) { const result = await GET("/budget/" + budgetid + "/" + year + "/" + (month+1)); const response = await result.json(); if (response.Categories == undefined || response.Categories.length <= 0) return; this.addCategoriesForMonth(year, month, response.Categories); }, async EditAccount(accountid: string, name: string, onBudget: boolean) { const result = await POST("/account/" + accountid, JSON.stringify({ name: name, onBudget: onBudget })); const response = await result.json(); useBudgetsStore().MergeBudgetingData(response); }, addCategoriesForMonth(year: number, month: number, categories: Category[]): void { this.$patch((state) => { const yearMap = state.Months.get(year) || new Map>(); const monthMap = yearMap.get(month) || new Map(); for (const category of categories) { monthMap.set(category.ID, category); } yearMap.set(month, monthMap); state.Months.set(year, yearMap); }); }, logout() { this.$reset() }, } })