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:
Bernt
2026-07-29 20:11:13 +00:00
parent f967d1a810
commit f793fc46a4
5 changed files with 138 additions and 74 deletions
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -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")
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -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>
+64
View File
@@ -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