diff --git a/src/pages/accounting/AccountingReportsPage.tsx b/src/pages/accounting/AccountingReportsPage.tsx index c948243..5ac1048 100644 --- a/src/pages/accounting/AccountingReportsPage.tsx +++ b/src/pages/accounting/AccountingReportsPage.tsx @@ -1310,6 +1310,13 @@ function BudgetVsActuals({ companyId, from, to, currency, companyName, rangeLabe const [budgetId, setBudgetId] = useState(""); useEffect(() => { if (!budgetId && budgets.length) setBudgetId(budgets[0].id); }, [budgets, budgetId]); + // Actuals comparison window — defaults to the report period, but the user can + // choose any custom date range to compare against the budget. + const [actFrom, setActFrom] = useState(from); + const [actTo, setActTo] = useState(to); + useEffect(() => { setActFrom(from); setActTo(to); }, [from, to]); + const actualsLabel = `${actFrom} to ${actTo}`; + const { data: accounts = [] } = useQuery({ queryKey: ["accounts", companyId], enabled: !!companyId, @@ -1323,18 +1330,18 @@ function BudgetVsActuals({ companyId, from, to, currency, companyName, rangeLabe }); const { data: actualsData } = useQuery({ - queryKey: ["bva-actuals", companyId, from, to], + queryKey: ["bva-actuals", companyId, actFrom, actTo], enabled: !!companyId, queryFn: async () => { const [inv, exp, txns, billItemsRes] = await Promise.all([ // All issued invoices (accrual — not filtered by payment status) - accounting.from("invoices").select("total,status,issue_date").eq("company_id", companyId).gte("issue_date", from).lte("issue_date", to).not("status", "in", '("void","draft")'), + accounting.from("invoices").select("total,status,issue_date").eq("company_id", companyId).gte("issue_date", actFrom).lte("issue_date", actTo).not("status", "in", '("void","draft")'), // Expenses table (tertiary for expense matching) - accounting.from("expenses").select("amount,category,date").eq("company_id", companyId).gte("date", from).lte("date", to), + accounting.from("expenses").select("amount,category,date").eq("company_id", companyId).gte("date", actFrom).lte("date", actTo), // Transactions with coa_account_id (primary — covers banking + receive-payments flow) - accounting.from("transactions").select("coa_account_id,amount,type").eq("company_id", companyId).gte("date", from).lte("date", to).not("coa_account_id", "is", null), + accounting.from("transactions").select("coa_account_id,amount,type").eq("company_id", companyId).gte("date", actFrom).lte("date", actTo).not("coa_account_id", "is", null), // Bill items joined to bills in range (secondary — covers bills paid via Bills page) - accounting.from("bill_items").select("account_id,amount,bills!inner(issue_date,company_id)").eq("bills.company_id", companyId).gte("bills.issue_date", from).lte("bills.issue_date", to).not("account_id", "is", null), + accounting.from("bill_items").select("account_id,amount,bills!inner(issue_date,company_id)").eq("bills.company_id", companyId).gte("bills.issue_date", actFrom).lte("bills.issue_date", actTo).not("account_id", "is", null), ]); return { invoices: inv.data ?? [], @@ -1452,7 +1459,7 @@ function BudgetVsActuals({ companyId, from, to, currency, companyName, rangeLabe return rows; }, [grouped, groupedOrdered, budgetByAcct, actualByAcct]); - const fileBase = `budget-vs-actuals-${from}-to-${to}`; + const fileBase = `budget-vs-actuals-${actFrom}-to-${actTo}`; const exportCSV = () => { const esc = (s: any) => `"${String(s).replace(/"/g, '""')}"`; @@ -1470,7 +1477,7 @@ function BudgetVsActuals({ companyId, from, to, currency, companyName, rangeLabe doc.setFont("helvetica", "bold"); doc.setFontSize(14); doc.setTextColor(33, 37, 41); doc.text("Budget vs Actuals", 40, 50); doc.setFont("helvetica", "normal"); doc.setFontSize(9); doc.setTextColor(110, 116, 122); - doc.text(`${companyName} · ${rangeLabel}`, 40, 66); + doc.text(`${companyName} · ${actualsLabel}`, 40, 66); autoTable(doc, { startY: 80, head: [["Account", "Budget", "Actual", "Variance", "Variance %"]], @@ -1502,6 +1509,12 @@ function BudgetVsActuals({ companyId, from, to, currency, companyName, rangeLabe {budgets.map((b: any) => {b.name} (FY {b.fiscal_year}))} +
+ + setActFrom(e.target.value)} className="h-9 w-40" /> + + setActTo(e.target.value)} className="h-9 w-40" /> +