mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 01:40:01 +00:00
Reports: drop Income Statement, add Monthly columns view to P&L
The Income Statement was a duplicate of the P&L, so removed it from the report menu. The P&L now has a 'Monthly columns' toggle that renders the same multi-period (by month/quarter/year) breakdown the income statement provided — relabeled 'Profit & Loss'. Default P&L view is unchanged (single period). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -53,7 +53,6 @@ const FINANCIAL: ReportId[] = ["pnl", "balance-sheet", "cash-flow", "movement-of
|
||||
const GROUPS = [
|
||||
{ name: "Business Overview", reports: [
|
||||
{ id: "pnl" as ReportId, name: "Profit & Loss" },
|
||||
{ id: "income-statement" as ReportId, name: "Income Statement" },
|
||||
{ id: "balance-sheet" as ReportId, name: "Balance Sheet" },
|
||||
{ id: "cash-flow" as ReportId, name: "Cash Flow Statement" },
|
||||
{ id: "movement-of-equity" as ReportId, name: "Movement of Equity" },
|
||||
@@ -329,6 +328,7 @@ export default function AccountingReportsPage({ association }: { association?: {
|
||||
// Toggles
|
||||
const [showCodes, setShowCodes] = useState(false);
|
||||
const [showZero, setShowZero] = useState(false);
|
||||
const [pnlMonthView, setPnlMonthView] = useState(false);
|
||||
|
||||
const { data: companyMeta } = useQuery({
|
||||
queryKey: ["company-fy", cid],
|
||||
@@ -469,7 +469,8 @@ export default function AccountingReportsPage({ association }: { association?: {
|
||||
}, [active, arOpen, data, flat, structured, cur, activeMeta.name]);
|
||||
|
||||
// Reports whose export is handled internally (own PDF/CSV buttons inside the component)
|
||||
const hasOwnExport = active === "trial-balance" || active === "general-ledger" || active === "budget-vs-actuals" || active === "income-statement"
|
||||
const hasOwnExport = active === "trial-balance" || active === "general-ledger" || active === "budget-vs-actuals"
|
||||
|| (active === "pnl" && pnlMonthView)
|
||||
|| active === "ar-aging-property" || active === "prepaid-homeowners" || active === "cash-disbursement";
|
||||
const anyExportable = !!(structured || flat || exportFlat);
|
||||
|
||||
@@ -646,6 +647,9 @@ export default function AccountingReportsPage({ association }: { association?: {
|
||||
<div className="flex flex-wrap gap-4 border-t pt-3">
|
||||
<Toggle id="t-codes" checked={showCodes} onChange={setShowCodes} label="Account codes" />
|
||||
<Toggle id="t-zero" checked={showZero} onChange={setShowZero} label="Zero-balance accounts" />
|
||||
{active === "pnl" && (
|
||||
<Toggle id="t-pnl-month" checked={pnlMonthView} onChange={setPnlMonthView} label="Monthly columns" />
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -653,7 +657,7 @@ export default function AccountingReportsPage({ association }: { association?: {
|
||||
{active === "budget-vs-actuals" && (
|
||||
<BudgetVsActuals companyId={cid} from={from} to={to} currency={cur} companyName={associationName ?? "Company"} rangeLabel={rangeLabel} logoUrl={logoUrl} />
|
||||
)}
|
||||
{active === "income-statement" && (
|
||||
{active === "pnl" && pnlMonthView && (
|
||||
<IncomeStatementReport companyId={cid} companyName={associationName ?? "Company"} from={from} to={to} currency={cur} logoUrl={logoUrl} />
|
||||
)}
|
||||
{active === "trial-balance" && (
|
||||
@@ -679,7 +683,7 @@ export default function AccountingReportsPage({ association }: { association?: {
|
||||
<ReconciliationReport d={data} currency={cur} />
|
||||
</ReportSheet>
|
||||
)}
|
||||
{isFinancial && (
|
||||
{isFinancial && !(active === "pnl" && pnlMonthView) && (
|
||||
!data ? (
|
||||
<Card><CardContent className="p-6"><div className="py-8 text-center text-sm text-muted-foreground">Loading…</div></CardContent></Card>
|
||||
) : structured ? (
|
||||
@@ -927,7 +931,7 @@ function IncomeStatementReport({ companyId, companyName, from, to, currency, log
|
||||
const doc = new jsPDF({ unit: "pt", format: "letter", orientation: "landscape" });
|
||||
const logo = await loadBrandedLogo(logoUrl);
|
||||
const startY = drawBrandedHeader(doc, {
|
||||
logo, title: "Income Statement", subtitle,
|
||||
logo, title: "Profit & Loss", subtitle,
|
||||
metaLines: [{ label: "Properties:", value: companyName }],
|
||||
});
|
||||
const head = [["Account", ...periods.map((p) => p.label), "Total"]];
|
||||
@@ -973,7 +977,7 @@ function IncomeStatementReport({ companyId, companyName, from, to, currency, log
|
||||
},
|
||||
});
|
||||
drawBrandedFooter(doc);
|
||||
doc.save(`income-statement-${gran}-${from}-to-${to}.pdf`);
|
||||
doc.save(`profit-loss-${gran}-${from}-to-${to}.pdf`);
|
||||
};
|
||||
|
||||
const exportCsv = () => {
|
||||
@@ -997,7 +1001,7 @@ function IncomeStatementReport({ companyId, companyName, from, to, currency, log
|
||||
const blob = new Blob([lines.join("\n")], { type: "text/csv" });
|
||||
const a = document.createElement("a");
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.download = `income-statement-${gran}-${from}-to-${to}.csv`;
|
||||
a.download = `profit-loss-${gran}-${from}-to-${to}.csv`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(a.href);
|
||||
};
|
||||
@@ -1034,7 +1038,7 @@ function IncomeStatementReport({ companyId, companyName, from, to, currency, log
|
||||
) : !hasRows ? (
|
||||
<Card><CardContent className="p-8 text-center text-sm text-muted-foreground">No income or expense activity in this range.</CardContent></Card>
|
||||
) : (
|
||||
<ReportSheet title="Income Statement" subtitle={subtitle} companyName={companyName} logoUrl={logoUrl}>
|
||||
<ReportSheet title="Profit & Loss" subtitle={subtitle} companyName={companyName} logoUrl={logoUrl}>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
|
||||
Reference in New Issue
Block a user