37241-vm/api/reports/income_statement.php
2026-01-03 08:40:36 +00:00

101 lines
2.7 KiB
PHP

<?php
header('Content-Type: application/json');
require_once __DIR__ . '../../../db/config.php';
//
// ## Income Statement Report (Profit & Loss)
//
// Purpose: Show financial performance (Revenue - Expenses) over a period.
//
// ---
//
// **Rule (Absolute):** Reads ONLY from `accounts` and `journal_lines` for posted entries.
// Filters for accounts of type 'revenue' and 'expense'.
//
$pdo = db();
// Optional date range filtering
$start_date = $_GET['start_date'] ?? null;
$end_date = $_GET['end_date'] ?? date('Y-m-d');
try {
$sql = <<<SQL
SELECT
a.account_code,
a.account_name,
a.account_type,
a.normal_balance,
SUM(CASE
WHEN a.normal_balance = 'debit' THEN jl.debit_amount - jl.credit_amount
ELSE jl.credit_amount - jl.debit_amount
END) as balance
FROM
accounts a
JOIN
journal_lines jl ON a.account_code = jl.account_code
JOIN
journal_entries je ON jl.journal_entry_id = je.id
WHERE
je.status = 'posted'
AND a.account_type IN ('revenue', 'expense')
SQL;
$params = [];
if ($start_date) {
$sql .= " AND je.entry_date >= :start_date";
$params[':start_date'] = $start_date;
}
if ($end_date) {
$sql .= " AND je.entry_date <= :end_date";
$params[':end_date'] = $end_date;
}
$sql .= " GROUP BY a.account_code, a.account_name, a.account_type, a.normal_balance ORDER BY a.account_type, a.account_code";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$report_lines = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Structure the report and calculate totals
$revenue_total = 0;
$expense_total = 0;
$revenues = [];
$expenses = [];
foreach ($report_lines as $line) {
if ($line['account_type'] == 'revenue') {
$revenues[] = $line;
$revenue_total += $line['balance'];
} else {
$expenses[] = $line;
$expense_total += $line['balance'];
}
}
$net_income = $revenue_total - $expense_total;
echo json_encode([
'success' => true,
'report_name' => 'Income Statement',
'generated_at' => date('c'),
'filters' => ['start_date' => $start_date, 'end_date' => $end_date],
'data' => [
'revenues' => $revenues,
'expenses' => $expenses
],
'summary' => [
'total_revenue' => $revenue_total,
'total_expense' => $expense_total,
'net_income' => $net_income
]
]);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'error' => 'Database error: ' . $e->getMessage()
]);
}