199 lines
8.2 KiB
PHP
199 lines
8.2 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../db/config.php';
|
|
require_once __DIR__ . '/../includes/functions.php';
|
|
require_once __DIR__ . '/../includes/WablasService.php';
|
|
|
|
// Enable error logging for cron
|
|
ini_set('log_errors', 1);
|
|
$logFile = __DIR__ . '/../storage/cron_debug.log';
|
|
ini_set('error_log', $logFile);
|
|
|
|
// Helper to log with timestamp
|
|
function cron_log($msg) {
|
|
global $logFile;
|
|
file_put_contents($logFile, "[" . date('Y-m-d H:i:s') . "] " . $msg . "\n", FILE_APPEND);
|
|
}
|
|
|
|
// Helper to format currency
|
|
function format_currency_custom($amount, $settings) {
|
|
$symbol = $settings['currency_symbol'] ?? '$';
|
|
$decimals = (int)($settings['currency_decimals'] ?? 3);
|
|
$position = $settings['currency_position'] ?? 'after';
|
|
|
|
$formatted = number_format((float)$amount, $decimals);
|
|
return ($position === 'after') ? "$formatted $symbol" : "$symbol $formatted";
|
|
}
|
|
|
|
try {
|
|
$settings = get_company_settings();
|
|
|
|
if (empty($settings['whatsapp_report_enabled']) || empty($settings['whatsapp_report_number']) || empty($settings['whatsapp_report_time'])) {
|
|
exit;
|
|
}
|
|
|
|
$timezone = !empty($settings['timezone']) ? $settings['timezone'] : 'UTC';
|
|
date_default_timezone_set($timezone);
|
|
|
|
$pdo = db();
|
|
|
|
// Use UTC strategy for consistent querying
|
|
// 1. Calculate Local Start/End of Today
|
|
$nowDt = new DateTime('now', new DateTimeZone($timezone));
|
|
|
|
$startLocal = clone $nowDt;
|
|
$startLocal->setTime(0, 0, 0);
|
|
|
|
$endLocal = clone $nowDt;
|
|
$endLocal->setTime(23, 59, 59);
|
|
|
|
// 2. Convert to UTC strings for DB query
|
|
$startUtc = clone $startLocal;
|
|
$startUtc->setTimezone(new DateTimeZone('UTC'));
|
|
$strStartUtc = $startUtc->format('Y-m-d H:i:s');
|
|
|
|
$endUtc = clone $endLocal;
|
|
$endUtc->setTimezone(new DateTimeZone('UTC'));
|
|
$strEndUtc = $endUtc->format('Y-m-d H:i:s');
|
|
|
|
// 3. Set DB Session to UTC so it interprets our UTC strings correctly
|
|
try {
|
|
$pdo->exec("SET time_zone = '+00:00'");
|
|
} catch (Exception $e) {
|
|
cron_log("Warning: Could not set MySQL timezone to UTC: " . $e->getMessage());
|
|
}
|
|
|
|
$reportTime = $settings['whatsapp_report_time'];
|
|
$lastReportFile = __DIR__ . '/../storage/last_daily_report.txt';
|
|
$lastReportDate = file_exists($lastReportFile) ? trim(file_get_contents($lastReportFile)) : '';
|
|
|
|
// Check schedule relative to Local Time
|
|
$targetTodayDt = clone $nowDt;
|
|
$timeParts = explode(':', $reportTime);
|
|
$targetTodayDt->setTime((int)$timeParts[0], (int)($timeParts[1] ?? 0), 0);
|
|
|
|
$diffToday = $nowDt->getTimestamp() - $targetTodayDt->getTimestamp();
|
|
|
|
// Run if within 15 mins of schedule AND not already run for this local date
|
|
if ($diffToday >= 0 && $diffToday <= 900 && $lastReportDate !== $nowDt->format('Y-m-d')) {
|
|
cron_log("Condition met: sending daily report for " . $nowDt->format('Y-m-d'));
|
|
cron_log("Querying UTC Range: $strStartUtc to $strEndUtc");
|
|
|
|
$todayDisplay = $nowDt->format('Y-m-d');
|
|
$companyName = $settings['company_name'] ?? 'Company';
|
|
|
|
// --- 1. Global Stats ---
|
|
// Total Revenue
|
|
$stmt = $pdo->prepare("SELECT SUM(total_amount) FROM orders WHERE created_at >= ? AND created_at <= ? AND status != 'cancelled'");
|
|
$stmt->execute([$strStartUtc, $strEndUtc]);
|
|
$totalRevenue = $stmt->fetchColumn() ?: 0;
|
|
|
|
// Total Orders
|
|
$stmt = $pdo->prepare("SELECT COUNT(*) FROM orders WHERE created_at >= ? AND created_at <= ? AND status != 'cancelled'");
|
|
$stmt->execute([$strStartUtc, $strEndUtc]);
|
|
$totalOrders = $stmt->fetchColumn() ?: 0;
|
|
|
|
// --- 2. Build Message Header ---
|
|
$message = "๐ *Daily Summary Report* ๐\n";
|
|
$message .= "๐ข *" . $companyName . "*\n";
|
|
$message .= "๐
Date: " . $todayDisplay . "\n";
|
|
$message .= "--------------------------------\n";
|
|
$message .= "๐ *Total Orders:* " . $totalOrders . "\n";
|
|
$message .= "๐ฐ *Total Revenue:* " . format_currency_custom($totalRevenue, $settings) . "\n";
|
|
|
|
// --- 3. Per-Outlet Stats ---
|
|
// Fetch outlets dynamically from DB
|
|
$stmtOutlets = $pdo->query("SELECT id, name, name_ar FROM outlets WHERE is_deleted = 0 ORDER BY id ASC");
|
|
$outlets = $stmtOutlets->fetchAll();
|
|
cron_log("Fetched " . count($outlets) . " outlets from database.");
|
|
|
|
foreach ($outlets as $outlet) {
|
|
$outletId = $outlet['id'];
|
|
$outletName = !empty($outlet['name_ar']) ? $outlet['name_ar'] : $outlet['name'];
|
|
|
|
// Outlet Revenue
|
|
$stmtRev = $pdo->prepare("SELECT SUM(total_amount) FROM orders WHERE outlet_id = ? AND created_at >= ? AND created_at <= ? AND status != 'cancelled'");
|
|
$stmtRev->execute([$outletId, $strStartUtc, $strEndUtc]);
|
|
$outletRevenue = $stmtRev->fetchColumn() ?: 0;
|
|
|
|
$message .= "\n๐ช *" . $outletName . " Total:* " . format_currency_custom($outletRevenue, $settings) . "\n";
|
|
|
|
// Staff Breakdown
|
|
$message .= "๐งโ๐ณ *Staff Breakdown:*
|
|
";
|
|
|
|
$stmtStaff = $pdo->prepare("
|
|
SELECT u.username, u.full_name, COUNT(o.id) as order_count, SUM(o.total_amount) as revenue
|
|
FROM orders o
|
|
LEFT JOIN users u ON o.user_id = u.id
|
|
WHERE o.outlet_id = ? AND o.created_at >= ? AND o.created_at <= ? AND o.status != 'cancelled'
|
|
GROUP BY o.user_id
|
|
");
|
|
$stmtStaff->execute([$outletId, $strStartUtc, $strEndUtc]);
|
|
$staffStats = $stmtStaff->fetchAll();
|
|
|
|
if (empty($staffStats)) {
|
|
$message .= "- No staff sales\n";
|
|
} else {
|
|
foreach ($staffStats as $stat) {
|
|
$staffName = !empty($stat['full_name']) ? $stat['full_name'] : ($stat['username'] ?? 'Unknown');
|
|
$message .= "- " . $staffName . ": " . format_currency_custom($stat['revenue'], $settings) . " (" . $stat['order_count'] . " orders)\n";
|
|
}
|
|
}
|
|
|
|
// Payment Breakdown
|
|
$message .= "๐ณ *Payment Breakdown:*
|
|
";
|
|
|
|
$stmtPayment = $pdo->prepare("
|
|
SELECT pt.name, SUM(o.total_amount) as revenue
|
|
FROM orders o
|
|
LEFT JOIN payment_types pt ON o.payment_type_id = pt.id
|
|
WHERE o.outlet_id = ? AND o.created_at >= ? AND o.created_at <= ? AND o.status != 'cancelled'
|
|
GROUP BY o.payment_type_id
|
|
");
|
|
$stmtPayment->execute([$outletId, $strStartUtc, $strEndUtc]);
|
|
$paymentStats = $stmtPayment->fetchAll();
|
|
|
|
if (empty($paymentStats)) {
|
|
$message .= "- No payments\n";
|
|
} else {
|
|
foreach ($paymentStats as $stat) {
|
|
$paymentName = $stat['name'] ?? 'Unknown';
|
|
$message .= "- " . $paymentName . ": " . format_currency_custom($stat['revenue'], $settings) . "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
$message .= "--------------------------------\n";
|
|
$message .= "Generated automatically at " . $nowDt->format('H:i:s') . "\n";
|
|
$message .= "Source: " . ($settings['company_name'] ?? 'System') . " Database";
|
|
|
|
// --- 4. Send Message ---
|
|
$wablas = new WablasService($pdo);
|
|
$recipients = explode(',', $settings['whatsapp_report_number']);
|
|
$anySuccess = false;
|
|
|
|
foreach ($recipients as $recipient) {
|
|
$recipient = trim($recipient);
|
|
if (empty($recipient)) continue;
|
|
|
|
cron_log("Sending detailed report to: " . $recipient);
|
|
$result = $wablas->sendMessage($recipient, $message);
|
|
|
|
if (!empty($result['success']) && $result['success'] == true) {
|
|
cron_log("Report sent successfully to " . $recipient);
|
|
$anySuccess = true;
|
|
} else {
|
|
cron_log("Failed to send report to " . $recipient . ": " . ($result['message'] ?? 'Unknown error'));
|
|
}
|
|
}
|
|
|
|
if ($anySuccess) {
|
|
file_put_contents($lastReportFile, $todayDisplay);
|
|
}
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
cron_log("CRITICAL ERROR: " . $e->getMessage());
|
|
}
|