import { defineStore } from "pinia"; import { GET, POST } from "../api"; import { formatDate, groupBy } from "../date"; import { useBudgetsStore } from "./budget"; import { useAccountStore } from "./budget-account"; interface State { Transactions: Map; Reconciling: boolean; ProblematicTransactions: Array; FilteredTransactions: Array; } export interface Transaction { ID: string; Date: Date; TransferAccount: string; CategoryGroup: string; Category: string; CategoryID: string | null; Memo: string; Status: string; GroupID: string; Payee: string; PayeeID: string | null; Amount: number; Reconciled: boolean; Account: string; AccountID: string; } export const useTransactionsStore = defineStore("budget/transactions", { state: (): State => ({ Transactions: new Map(), Reconciling: false, ProblematicTransactions: new Array(), FilteredTransactions: new Array(), }), getters: { ReconcilingBalance(state): number { const accountsStore = useAccountStore(); let reconciledBalance = accountsStore.CurrentAccount!.ReconciledBalance; for (const transaction of this.TransactionsList) { if (transaction.Reconciled) reconciledBalance += transaction.Amount; } return reconciledBalance; }, TransactionsByDate(state) : Record { const accountsStore = useAccountStore(); const accountID = accountsStore.CurrentAccountID; const allTransactions = [...this.Transactions.values()].filter(x => x.AccountID == accountID); return groupBy(allTransactions, x => formatDate(x.Date)); }, TransactionsList(state) : Transaction[] { const accountsStore = useAccountStore(); const accountID = accountsStore.CurrentAccountID; const allTransactions = [...this.Transactions.values()]; return allTransactions.filter(x => x.AccountID == accountID); }, ProblematicTransactionsList(state) : Transaction[] { return [...state.ProblematicTransactions.map(x => state.Transactions!.get(x)!)]; }, FilteredTransactionsList(state) : Transaction[] { return [...state.FilteredTransactions.map(x => state.Transactions!.get(x)!)]; } }, actions: { AddTransactions(transactions: Array) { this.$patch(() => { for (const transaction of transactions) { transaction.Date = new Date(transaction.Date); this.Transactions.set(transaction.ID, transaction); } }); }, SetReconciledForAllTransactions(value: boolean) { for (const transaction of this.TransactionsList) { if (transaction.Status == "Reconciled") continue; transaction.Reconciled = value; } }, async GetProblematicTransactions() { const budgetStore = useBudgetsStore(); const result = await GET("/budget/" + budgetStore.CurrentBudgetID + "/problematic-transactions"); const response = await result.json(); const transactions = response.Transactions ?? []; this.AddTransactions(transactions); this.ProblematicTransactions = [...transactions?.map((x : Transaction) => x.ID)]; }, async GetFilteredTransactions(accountID : string | null, categoryID : string | null, payeeID : string | null, fromDate : string, toDate : string) { const budgetStore = useBudgetsStore(); const payload = JSON.stringify({ categoryId: categoryID, payeeId: payeeID, accountId: accountID, fromDate: fromDate, toDate: toDate, }); const result = await POST("/budget/" + budgetStore.CurrentBudgetID + "/filtered-transactions", payload); const response = await result.json(); const transactions = response.Transactions ?? []; this.AddTransactions(transactions); this.FilteredTransactions = [...transactions.map((x : Transaction) => x.ID)]; }, async SubmitReconcilation(reconciliationTransactionAmount: number) { const accountsStore = useAccountStore(); const account = accountsStore.CurrentAccount!; const reconciledTransactions = this.TransactionsList.filter( (x) => x.Reconciled ); for (const transaction of reconciledTransactions) { account.ReconciledBalance += transaction.Amount; transaction.Status = "Reconciled"; transaction.Reconciled = false; } const result = await POST( "/account/" + accountsStore.CurrentAccountID + "/reconcile", JSON.stringify({ transactionIDs: reconciledTransactions.map((x) => x.ID), reconciliationTransactionAmount: reconciliationTransactionAmount.toString(), }) ); const response = await result.json(); const recTrans = response.ReconciliationTransaction; if (recTrans) { this.AddTransactions([recTrans]); account.Transactions.unshift(recTrans.ID); } }, logout() { this.$reset(); }, async saveTransaction(payload: string) { const accountsStore = useAccountStore(); const result = await POST("/transaction/new", payload); const response = (await result.json()) as Transaction; this.AddTransactions([response]); accountsStore.CurrentAccount?.Transactions.unshift(response.ID); }, async editTransaction(transactionid: string, payload: string) { const result = await POST("/transaction/" + transactionid, payload); const response = (await result.json()) as Transaction; this.AddTransactions([response]); }, }, });