feat: Add Income Statement to DashboardPage + fix account types
- Add Income Statement section with Revenue and Expenses tables - Color-code revenue (green) and expenses (red) - Show Net Income prominently at bottom - Fix SQL query to use LOWER() for case-insensitive matching - Update account types in DB (asset/liability/revenue/expense/equity) - Balance Sheet and Income Statement now work correctly
This commit is contained in:
Binary file not shown.
@@ -147,7 +147,7 @@ func (c *RobustClient) GetIncomeStatement(ctx context.Context, period string) (*
|
|||||||
FROM boc_chart_of_accounts a
|
FROM boc_chart_of_accounts a
|
||||||
LEFT JOIN boc_journal_lines jl ON a.id = jl.account_id
|
LEFT JOIN boc_journal_lines jl ON a.id = jl.account_id
|
||||||
LEFT JOIN boc_journal_entries je ON jl.entry_id = je.id AND je.entry_date >= $1::date AND je.entry_date < ($1::date + INTERVAL '1 month')
|
LEFT JOIN boc_journal_entries je ON jl.entry_id = je.id AND je.entry_date >= $1::date AND je.entry_date < ($1::date + INTERVAL '1 month')
|
||||||
WHERE a.account_type IN ('Revenue', 'Expense')
|
WHERE LOWER(a.account_type) IN ('revenue', 'expense')
|
||||||
GROUP BY a.id, a.account_code, a.name, a.account_type
|
GROUP BY a.id, a.account_code, a.name, a.account_type
|
||||||
ORDER BY a.account_code
|
ORDER BY a.account_code
|
||||||
`, period+"-01")
|
`, period+"-01")
|
||||||
|
|||||||
+72
-72
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
||||||
<script type="module" crossorigin src="/assets/index-DkrQA2Vo.js"></script>
|
<script type="module" crossorigin src="/assets/index-ieB3Tw4c.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-oHhMI01Z.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-oHhMI01Z.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -321,6 +321,70 @@ export function DashboardPage() {
|
|||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/* Income Statement */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader
|
||||||
|
title="Income Statement (Resultaträkning)"
|
||||||
|
subtitle="Revenue and expenses for period 2026-02"
|
||||||
|
/>
|
||||||
|
<div className="grid grid-cols-1 xl:grid-cols-2 gap-6 p-6">
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold mb-4 text-success">Revenue (Intäkter)</h3>
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Code</TableHead>
|
||||||
|
<TableHead>Name</TableHead>
|
||||||
|
<TableHead className="text-right">Amount</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{ledgerAccounts.filter(a => a.account_type === 'revenue').map((account) => (
|
||||||
|
<TableRow key={account.code}>
|
||||||
|
<TableCell>{account.code}</TableCell>
|
||||||
|
<TableCell>{account.name}</TableCell>
|
||||||
|
<TableCell className="text-right text-success">
|
||||||
|
{formatCurrency(Math.abs(account.balance))}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold mb-4 text-danger">Expenses (Kostnader)</h3>
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Code</TableHead>
|
||||||
|
<TableHead>Name</TableHead>
|
||||||
|
<TableHead className="text-right">Amount</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{ledgerAccounts.filter(a => a.account_type === 'expense').map((account) => (
|
||||||
|
<TableRow key={account.code}>
|
||||||
|
<TableCell>{account.code}</TableCell>
|
||||||
|
<TableCell>{account.name}</TableCell>
|
||||||
|
<TableCell className="text-right text-danger">
|
||||||
|
{formatCurrency(account.balance)}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="border-t p-6">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<span className="text-lg font-semibold">Net Income:</span>
|
||||||
|
<span className={`text-2xl font-bold ${netIncome >= 0 ? 'text-success' : 'text-danger'}`}>
|
||||||
|
{formatCurrency(netIncome)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
{/* Recent Deals */}
|
{/* Recent Deals */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
|
|||||||
Reference in New Issue
Block a user