124 lines
3.2 KiB
TypeScript
124 lines
3.2 KiB
TypeScript
import { defineStore } from "pinia";
|
|
|
|
export const useCashStore = defineStore("cash", () => {
|
|
// 13-week cash flow events
|
|
const cashEvents = ref([]);
|
|
|
|
// Payment queue - staged payments within policy
|
|
const paymentQueue = ref([]);
|
|
|
|
// Week that first breaches minimum cushion
|
|
const firstBreachWeek = ref(null);
|
|
|
|
// Current cash and savings balances - start empty
|
|
const currentCash = ref(0);
|
|
const currentSavings = ref(0);
|
|
|
|
// Computed weekly projections
|
|
const weeklyProjections = computed(() => {
|
|
const weeks = [];
|
|
let runningBalance = currentCash.value;
|
|
|
|
for (let week = 1; week <= 13; week++) {
|
|
const weekEvents = cashEvents.value.filter((e) => e.week === week);
|
|
const weekInflow = weekEvents
|
|
.filter((e) => e.type === "Influx")
|
|
.reduce((sum, e) => sum + e.amount, 0);
|
|
const weekOutflow = weekEvents
|
|
.filter((e) => e.type === "Outflow")
|
|
.reduce((sum, e) => sum + e.amount, 0);
|
|
|
|
const net = weekInflow - weekOutflow;
|
|
runningBalance += net;
|
|
|
|
weeks.push({
|
|
number: week,
|
|
inflow: weekInflow,
|
|
outflow: weekOutflow,
|
|
net,
|
|
balance: runningBalance,
|
|
cushion: runningBalance, // Will be calculated properly later
|
|
breachesCushion: false, // Will be calculated properly later
|
|
});
|
|
}
|
|
|
|
return weeks;
|
|
});
|
|
|
|
// Actions
|
|
function addCashEvent(event) {
|
|
cashEvents.value.push({
|
|
id: Date.now().toString(),
|
|
date: event.date,
|
|
week: event.week,
|
|
type: event.type, // Influx|Outflow
|
|
amount: event.amount,
|
|
sourceRef: event.sourceRef,
|
|
policyTag: event.policyTag, // Payroll|Tax|Vendor|SavingsSweep
|
|
...event,
|
|
});
|
|
}
|
|
|
|
function updateCashEvent(id, updates) {
|
|
const event = cashEvents.value.find((e) => e.id === id);
|
|
if (event) {
|
|
Object.assign(event, updates);
|
|
}
|
|
}
|
|
|
|
function removeCashEvent(id) {
|
|
const index = cashEvents.value.findIndex((e) => e.id === id);
|
|
if (index > -1) {
|
|
cashEvents.value.splice(index, 1);
|
|
}
|
|
}
|
|
|
|
function addToPaymentQueue(payment) {
|
|
paymentQueue.value.push({
|
|
id: Date.now().toString(),
|
|
amount: payment.amount,
|
|
recipient: payment.recipient,
|
|
scheduledWeek: payment.scheduledWeek,
|
|
priority: payment.priority,
|
|
canStage: payment.canStage !== false,
|
|
...payment,
|
|
});
|
|
}
|
|
|
|
function stagePayment(paymentId, newWeek) {
|
|
const payment = paymentQueue.value.find((p) => p.id === paymentId);
|
|
if (payment && payment.canStage) {
|
|
payment.scheduledWeek = newWeek;
|
|
}
|
|
}
|
|
|
|
function updateCurrentBalances(cash, savings) {
|
|
currentCash.value = cash;
|
|
currentSavings.value = savings;
|
|
}
|
|
|
|
return {
|
|
cashEvents: readonly(cashEvents),
|
|
paymentQueue: readonly(paymentQueue),
|
|
firstBreachWeek: readonly(firstBreachWeek),
|
|
currentCash: readonly(currentCash),
|
|
currentSavings: readonly(currentSavings),
|
|
weeklyProjections,
|
|
addCashEvent,
|
|
updateCashEvent,
|
|
removeCashEvent,
|
|
addToPaymentQueue,
|
|
stagePayment,
|
|
updateCurrentBalances,
|
|
};
|
|
}, {
|
|
persist: {
|
|
key: "urgent-tools-cash",
|
|
paths: [
|
|
"currentCash",
|
|
"currentSavings",
|
|
"cashEvents",
|
|
"paymentQueue"
|
|
],
|
|
},
|
|
});
|