From 60d2f356c722b2ba12128d30c72913f7a197baf3 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Fri, 20 Mar 2026 06:38:22 +0000 Subject: [PATCH] update summery report --- admin/includes/footer.php | 10 ------- api/daily_report_cron.php | 56 ++++++++++++++++++++++++++------------- assets/js/main.js | 2 -- patch.php | 1 + 4 files changed, 39 insertions(+), 30 deletions(-) create mode 100644 patch.php diff --git a/admin/includes/footer.php b/admin/includes/footer.php index 6c7c9e2..0251726 100644 --- a/admin/includes/footer.php +++ b/admin/includes/footer.php @@ -45,16 +45,6 @@ }); }); - // Trigger crons occasionally (max once per hour per browser) - const lastCron = localStorage.getItem('last_cron_trigger'); - const now = Date.now(); - if (!lastCron || (now - parseInt(lastCron)) > 3600000) { - localStorage.setItem('last_cron_trigger', now.toString()); - // Trigger auto backup in background - fetch('api/auto_backup.php').catch(err => console.error('Auto backup trigger failed', err)); - // Trigger daily report cron - fetch('api/daily_report_cron.php').catch(err => console.error('Daily report cron failed', err)); - } }); diff --git a/api/daily_report_cron.php b/api/daily_report_cron.php index bdfdb23..6eb78e6 100644 --- a/api/daily_report_cron.php +++ b/api/daily_report_cron.php @@ -6,6 +6,10 @@ require_once __DIR__ . '/../includes/WablasService.php'; session_write_close(); header("Content-Type: application/json"); +// Enable error logging for cron +ini_set('log_errors', 1); +ini_set('error_log', __DIR__ . '/../storage/cron_errors.log'); + try { $settings = get_company_settings(); @@ -14,35 +18,52 @@ try { exit; } - $timezone = $settings['timezone'] ?? 'UTC'; + $timezone = !empty($settings['timezone']) ? $settings['timezone'] : 'UTC'; date_default_timezone_set($timezone); - $reportTime = $settings['whatsapp_report_time']; + $reportTime = $settings['whatsapp_report_time']; // e.g. "23:59:00" or "23:59" $lastReportFile = __DIR__ . '/../storage/last_daily_report.txt'; if (!is_dir(dirname($lastReportFile))) { - mkdir(dirname($lastReportFile), 0755, true); + mkdir(dirname($lastReportFile), 0775, true); } $lastReportDate = file_exists($lastReportFile) ? trim(file_get_contents($lastReportFile)) : ''; - $now = time(); - $todayDate = date('Y-m-d', $now); - $targetTodayTime = strtotime($todayDate . ' ' . $reportTime); + $nowDt = new DateTime('now', new DateTimeZone($timezone)); + $todayDateStr = $nowDt->format('Y-m-d'); - $yesterdayDate = date('Y-m-d', strtotime('-1 day', $now)); - $targetYesterdayTime = strtotime($yesterdayDate . ' ' . $reportTime); + $targetTodayDt = clone $nowDt; + $timeParts = explode(':', $reportTime); + // Ignore seconds from the configuration, start matching exactly at the given minute + $targetTodayDt->setTime((int)$timeParts[0], (int)($timeParts[1] ?? 0), 0); + + $targetYesterdayDt = clone $targetTodayDt; + $targetYesterdayDt->modify('-1 day'); + $yesterdayDateStr = $targetYesterdayDt->format('Y-m-d'); + + // Calculate time difference in seconds between now and the target scheduled times + $diffToday = $nowDt->getTimestamp() - $targetTodayDt->getTimestamp(); + $diffYesterday = $nowDt->getTimestamp() - $targetYesterdayDt->getTimestamp(); $reportDateToRun = null; - if ($now >= $targetTodayTime && $lastReportDate !== $todayDate) { - $reportDateToRun = $todayDate; - } elseif ($now >= $targetYesterdayTime && $lastReportDate !== $yesterdayDate && $lastReportDate !== $todayDate) { - $reportDateToRun = $yesterdayDate; + // We allow a strict 15-minute window (900 seconds) to catch delayed cron executions. + // If the diff is negative, the target time hasn't happened yet. + // If the diff is > 900, we missed it by a lot (e.g. system was deployed or turned on hours later), + // so we simply ignore it and wait for the NEXT proper scheduled time. + if ($diffToday >= 0 && $diffToday <= 900 && $lastReportDate !== $todayDateStr) { + $reportDateToRun = $todayDateStr; + } elseif ($diffYesterday >= 0 && $diffYesterday <= 900 && $lastReportDate !== $yesterdayDateStr && $lastReportDate !== $todayDateStr) { + $reportDateToRun = $yesterdayDateStr; } + // Optional: write a small heartbeat log so user/admin knows cron is checking correctly + $hb = "Timezone: $timezone | Now: " . $nowDt->format('Y-m-d H:i:s') . " | TargetToday: " . $targetTodayDt->format('Y-m-d H:i:s') . " | TargetYest: " . $targetYesterdayDt->format('Y-m-d H:i:s') . " | DiffToday: $diffToday | DiffYest: $diffYesterday | LastSent: $lastReportDate\n"; + file_put_contents(__DIR__ . '/../storage/cron_heartbeat.log', $hb); + if (!$reportDateToRun) { - echo json_encode(['status' => 'skipped', 'reason' => 'No report due or already sent']); + echo json_encode(['status' => 'skipped', 'reason' => 'No report due within the allowed window or already sent', 'now' => $nowDt->format('Y-m-d H:i:s')]); exit; } @@ -51,7 +72,7 @@ try { // GENERATE REPORT $pdo = db(); - // Get all completed orders for today + // Get all non-cancelled orders for the report date $stmt = $pdo->prepare( "SELECT o.id, o.total_amount as total, o.payment_type_id, o.user_id, o.outlet_id, @@ -62,7 +83,7 @@ try { LEFT JOIN payment_types pt ON o.payment_type_id = pt.id LEFT JOIN users u ON o.user_id = u.id LEFT JOIN outlets outl ON o.outlet_id = outl.id - WHERE DATE(o.created_at) = ? AND o.status = 'completed'" + WHERE DATE(o.created_at) = ? AND o.status != 'cancelled'" ); $stmt->execute([$currentDate]); $orders = $stmt->fetchAll(PDO::FETCH_ASSOC); @@ -151,9 +172,8 @@ try { } $message .= "--------------------------------\n"; - $message .= "Generated automatically at " . date('H:i:s'); + $message .= "Generated automatically at " . $nowDt->format('H:i:s'); - // Send via Wablas // Write immediately to prevent duplicate triggers file_put_contents($lastReportFile, $currentDate); @@ -178,7 +198,7 @@ try { if ($successCount > 0) { echo json_encode(['status' => 'success', 'message' => 'Report sent to ' . $successCount . ' number(s)']); } else { - // Revert on failure + // Revert on failure so it tries again next minute if (file_exists($lastReportFile)) { unlink($lastReportFile); } echo json_encode(['status' => 'error', 'message' => implode(', ', $errors)]); } diff --git a/assets/js/main.js b/assets/js/main.js index b474384..232d351 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -7,8 +7,6 @@ document.addEventListener('DOMContentLoaded', () => { const now = Date.now(); if (!lastCron || (now - parseInt(lastCron)) > 3600000) { localStorage.setItem('last_cron_trigger_pos', now.toString()); - fetch('api/daily_report_cron.php').catch(e => console.error(e)); - fetch('api/auto_backup.php').catch(e => console.error(e)); } }, 5000); diff --git a/patch.php b/patch.php new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/patch.php @@ -0,0 +1 @@ +