158 lines
5.4 KiB
PHP
158 lines
5.4 KiB
PHP
<?php
|
|
/**
|
|
* Monthly Financial Report Script
|
|
* This script calculates financial statistics for the previous month and sends an email report.
|
|
* Run via CLI: php scripts/monthly_report.php
|
|
*/
|
|
|
|
require_once __DIR__ . '/../db/config.php';
|
|
require_once __DIR__ . '/../mail/MailService.php';
|
|
|
|
$pdo = db();
|
|
|
|
// Get settings
|
|
$settings_raw = $pdo->query("SELECT * FROM settings")->fetchAll();
|
|
$settings = [];
|
|
foreach ($settings_raw as $s) {
|
|
$settings[$s['setting_key']] = $s['setting_value'];
|
|
}
|
|
|
|
$recipient = $settings['report_recipient_email'] ?? getenv('MAIL_TO');
|
|
|
|
if (empty($recipient)) {
|
|
die("Error: No recipient email configured in settings or environment.\n");
|
|
}
|
|
|
|
// Calculate last month date range
|
|
$start_date = date('Y-m-01', strtotime('first day of last month'));
|
|
$end_date = date('Y-m-t', strtotime('last month'));
|
|
$month_name = date('F Y', strtotime('last month'));
|
|
|
|
// Fetch statistics for the period
|
|
$stats = [];
|
|
|
|
// 1. Total Donations
|
|
$stmt = $pdo->prepare("SELECT SUM(amount) as total, COUNT(*) as count FROM donations WHERE status = 'paid' AND created_at BETWEEN ? AND ?");
|
|
$stmt->execute([$start_date . ' 00:00:00', $end_date . ' 23:59:59']);
|
|
$donation_stats = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
$stats['total_amount'] = $donation_stats['total'] ?? 0;
|
|
$stats['total_count'] = $donation_stats['count'] ?? 0;
|
|
|
|
// 2. Donations by Category
|
|
$stmt = $pdo->prepare("
|
|
SELECT c.name, SUM(d.amount) as total
|
|
FROM donations d
|
|
JOIN cases cs ON d.case_id = cs.id
|
|
JOIN categories c ON cs.category_id = c.id
|
|
WHERE d.status = 'paid' AND d.created_at BETWEEN ? AND ?
|
|
GROUP BY c.id
|
|
ORDER BY total DESC
|
|
");
|
|
$stmt->execute([$start_date . ' 00:00:00', $end_date . ' 23:59:59']);
|
|
$stats['by_category'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// 3. Top Cases
|
|
$stmt = $pdo->prepare("
|
|
SELECT cs.title, SUM(d.amount) as total
|
|
FROM donations d
|
|
JOIN cases cs ON d.case_id = cs.id
|
|
WHERE d.status = 'paid' AND d.created_at BETWEEN ? AND ?
|
|
GROUP BY cs.id
|
|
ORDER BY total DESC
|
|
LIMIT 5
|
|
");
|
|
$stmt->execute([$start_date . ' 00:00:00', $end_date . ' 23:59:59']);
|
|
$stats['top_cases'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// Build HTML Email
|
|
$html = "
|
|
<html>
|
|
<head>
|
|
<style>
|
|
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; color: #333; }
|
|
.container { max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e0e0e0; border-radius: 10px; }
|
|
.header { text-align: center; margin-bottom: 30px; border-bottom: 2px solid #059669; padding-bottom: 10px; }
|
|
.header h1 { color: #059669; margin: 0; }
|
|
.summary-box { background: #f9f9f9; padding: 20px; border-radius: 8px; margin-bottom: 20px; text-align: center; }
|
|
.stat-value { font-size: 24px; font-weight: bold; color: #059669; }
|
|
table { width: 100%; border-collapse: collapse; margin-top: 10px; }
|
|
th, td { text-align: left; padding: 12px; border-bottom: 1px solid #eee; }
|
|
th { background: #f4f4f4; }
|
|
.footer { margin-top: 30px; font-size: 12px; color: #777; text-align: center; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class='container'>
|
|
<div class='header'>
|
|
<h1>Monthly Financial Summary</h1>
|
|
<p>Period: {$month_name}</p>
|
|
</div>
|
|
|
|
<div class='summary-box'>
|
|
<div style='display: inline-block; width: 45%;'>
|
|
<p style='margin: 0; color: #666;'>Total Donations</p>
|
|
<div class='stat-value'>$" . number_format($stats['total_amount'], 2) . "</div>
|
|
</div>
|
|
<div style='display: inline-block; width: 45%; border-left: 1px solid #ddd;'>
|
|
<p style='margin: 0; color: #666;'>Donation Count</p>
|
|
<div class='stat-value'>{$stats['total_count']}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h3>Donations by Category</h3>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Category</th>
|
|
<th>Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>";
|
|
|
|
foreach ($stats['by_category'] as $cat) {
|
|
$html .= "<tr><td>" . htmlspecialchars($cat['name']) . "</td><td>$" . number_format($cat['total'], 2) . "</td></tr>";
|
|
}
|
|
|
|
$html .= "
|
|
</tbody>
|
|
</table>
|
|
|
|
<h3>Top 5 Performing Cases</h3>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Case Title</th>
|
|
<th>Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>";
|
|
|
|
foreach ($stats['top_cases'] as $case) {
|
|
$html .= "<tr><td>" . htmlspecialchars($case['title']) . "</td><td>$" . number_format($case['total'], 2) . "</td></tr>";
|
|
}
|
|
|
|
$html .= "
|
|
</tbody>
|
|
</table>
|
|
|
|
<div class='footer'>
|
|
<p>This is an automated report from your CharityHub Admin Panel.</p>
|
|
<p>© " . date('Y') . " CharityHub. All rights reserved.</p>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>";
|
|
|
|
// Send Email
|
|
$subject = "Financial Summary Report - {$month_name}";
|
|
$plain_text = "Monthly Financial Summary for {$month_name}\n\nTotal Amount: $" . number_format($stats['total_amount'], 2) . "\nTotal Count: {$stats['total_count']}\n\nPlease view the HTML version for detailed breakdown.";
|
|
|
|
$res = MailService::sendMail($recipient, $subject, $html, $plain_text);
|
|
|
|
if (!empty($res['success'])) {
|
|
echo "Report sent successfully to {$recipient} for {$month_name}.\n";
|
|
} else {
|
|
echo "Failed to send report: " . ($res['error'] ?? 'Unknown error') . "\n";
|
|
}
|
|
|