update summery report

This commit is contained in:
Flatlogic Bot 2026-03-20 06:38:22 +00:00
parent 2130c9f23a
commit 60d2f356c7
4 changed files with 39 additions and 30 deletions

View File

@ -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('<?= get_base_url() ?>api/auto_backup.php').catch(err => console.error('Auto backup trigger failed', err));
// Trigger daily report cron
fetch('<?= get_base_url() ?>api/daily_report_cron.php').catch(err => console.error('Daily report cron failed', err));
}
});
</script>
</body>

View File

@ -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)]);
}

View File

@ -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);

1
patch.php Normal file
View File

@ -0,0 +1 @@