Przebudowa działania geolokalizacji. Zgoda na menu bez lokalizacji.

This commit is contained in:
2026-05-31 00:00:39 +02:00
parent 8de221ba79
commit 04aaa6e321
7 changed files with 517 additions and 28 deletions

View File

@@ -24,7 +24,7 @@ if (!isAdminLoggedIn()) {
}
$range = isset($_GET['days']) ? trim((string)$_GET['days']) : '7';
$allowedRanges = ['7', '30', '90', 'all', 'this_year', 'last_year'];
$allowedRanges = ['today', '7', '30', '90', 'all', 'this_year', 'last_year'];
if (!in_array($range, $allowedRanges, true)) {
$range = '7';
}
@@ -36,6 +36,15 @@ $now = new DateTimeImmutable('now');
switch ($range) {
case 'all':
break;
case 'today':
$start = new DateTimeImmutable('today');
$end = $start->modify('+1 day');
$whereWindow = ' AND created_at >= :start_at AND created_at < :end_at';
$baseParams = [
':start_at' => $start->format('Y-m-d H:i:s'),
':end_at' => $end->format('Y-m-d H:i:s'),
];
break;
case 'this_year':
$start = new DateTimeImmutable(date('Y-01-01 00:00:00'));
$end = $start->modify('+1 year');
@@ -108,7 +117,7 @@ try {
COUNT(*) AS total
FROM analytics_events
WHERE 1=1 {$whereWindow}
AND event_name IN ('qr_scan','session_start','view_menu','bill_dialog_opened','bill_request_sent','waiter_call_requested')
AND event_name IN ('qr_scan','session_start','view_menu','bill_dialog_opened','bill_request_sent','waiter_call_requested','menu_only_entered','geo_gate_prompted','geo_retry_from_menu')
GROUP BY event_name
";
$stmtFunnel = $pdo->prepare($sqlFunnel);
@@ -157,7 +166,6 @@ try {
created_at,
session_id,
table_id,
zone,
device_type,
browser,
JSON_UNQUOTE(JSON_EXTRACT(payload_json, '$.ipAddress')) AS ip_address
@@ -186,6 +194,7 @@ try {
SELECT
session_id,
MAX(CASE WHEN event_name = 'session_start' THEN 1 ELSE 0 END) AS reached_app,
MAX(CASE WHEN event_name = 'menu_only_entered' THEN 1 ELSE 0 END) AS menu_only,
MAX(CASE WHEN event_name = 'view_menu' THEN 1 ELSE 0 END) AS entered_menu
FROM analytics_events
WHERE session_id IN ({$placeholders})
@@ -196,22 +205,87 @@ try {
while ($flagRow = $stmtSessionFlags->fetch()) {
$sessionOutcomes[$flagRow['session_id']] = [
'reached_app' => (int) $flagRow['reached_app'],
'menu_only' => (int) $flagRow['menu_only'],
'entered_menu' => (int) $flagRow['entered_menu'],
];
}
$sqlVisitHistory = "
SELECT session_id, created_at
FROM analytics_events
WHERE event_name = 'qr_scan'
AND session_id IN ({$placeholders})
ORDER BY session_id ASC, created_at ASC
";
$stmtVisitHistory = $pdo->prepare($sqlVisitHistory);
$stmtVisitHistory->execute($sessionIds);
$visitHistoryBySession = [];
while ($visitRow = $stmtVisitHistory->fetch()) {
$sid = trim((string) ($visitRow['session_id'] ?? ''));
if ($sid === '') {
continue;
}
if (!isset($visitHistoryBySession[$sid])) {
$visitHistoryBySession[$sid] = [];
}
$visitHistoryBySession[$sid][] = (string) $visitRow['created_at'];
}
} else {
$visitHistoryBySession = [];
}
foreach ($recentOpens as &$openRow) {
$sid = trim((string) ($openRow['session_id'] ?? ''));
$flags = $sessionOutcomes[$sid] ?? ['reached_app' => 0, 'entered_menu' => 0];
$flags = $sessionOutcomes[$sid] ?? ['reached_app' => 0, 'menu_only' => 0, 'entered_menu' => 0];
$openRow['reached_app'] = $flags['reached_app'];
$openRow['menu_only'] = $flags['menu_only'];
$openRow['entered_menu'] = $flags['entered_menu'];
$visitTimes = $visitHistoryBySession[$sid] ?? [];
$openAt = (string) ($openRow['created_at'] ?? '');
$visitNumber = 0;
foreach ($visitTimes as $visitAt) {
if ($visitAt <= $openAt) {
$visitNumber++;
}
}
if ($visitNumber < 1 && $openAt !== '') {
$visitNumber = 1;
}
$openRow['visitor_id_short'] = $sid !== '' ? substr($sid, 0, 8) : null;
$openRow['visitor_visit_number'] = $visitNumber;
$openRow['visitor_total_visits'] = count($visitTimes);
$openRow['visitor_first_seen_at'] = $visitTimes[0] ?? null;
$openRow['visitor_is_returning'] = $visitNumber > 1 ? 1 : 0;
}
unset($openRow);
$sqlVisitorSummary = "
SELECT
COUNT(DISTINCT session_id) AS unique_visitors,
SUM(CASE WHEN scan_count > 1 THEN 1 ELSE 0 END) AS returning_visitors
FROM (
SELECT session_id, COUNT(*) AS scan_count
FROM analytics_events
WHERE event_name = 'qr_scan' {$whereWindow}
GROUP BY session_id
) visitor_counts
";
$stmtVisitorSummary = $pdo->prepare($sqlVisitorSummary);
$stmtVisitorSummary->execute($baseParams);
$visitorSummaryRow = $stmtVisitorSummary->fetch() ?: [
'unique_visitors' => 0,
'returning_visitors' => 0,
];
$uniqueVisitors = (int) $visitorSummaryRow['unique_visitors'];
$returningVisitors = (int) $visitorSummaryRow['returning_visitors'];
$sqlQueueSummary = "
SELECT
COUNT(*) AS total_actions,
SUM(CASE WHEN message_type = 'waiter_call' THEN 1 ELSE 0 END) AS waiter_calls,
SUM(CASE WHEN message_type = 'bill_request' THEN 1 ELSE 0 END) AS bill_requests,
SUM(CASE WHEN api_sent = 0 THEN 1 ELSE 0 END) AS pending_api,
SUM(CASE WHEN status_kds = 0 THEN 1 ELSE 0 END) AS pending_kds,
SUM(CASE WHEN status_kds = 1 THEN 1 ELSE 0 END) AS done_kds
@@ -222,6 +296,8 @@ try {
$stmtQueueSummary->execute($baseParams);
$queueSummary = $stmtQueueSummary->fetch() ?: [
'total_actions' => 0,
'waiter_calls' => 0,
'bill_requests' => 0,
'pending_api' => 0,
'pending_kds' => 0,
'done_kds' => 0,
@@ -263,6 +339,9 @@ try {
'bill_dialog_opened' => (int)($funnelMap['bill_dialog_opened'] ?? 0),
'bill_request_sent' => (int)($funnelMap['bill_request_sent'] ?? 0),
'waiter_call_requested' => (int)($funnelMap['waiter_call_requested'] ?? 0),
'menu_only_entered' => (int)($funnelMap['menu_only_entered'] ?? 0),
'geo_gate_prompted' => (int)($funnelMap['geo_gate_prompted'] ?? 0),
'geo_retry_from_menu' => (int)($funnelMap['geo_retry_from_menu'] ?? 0),
],
'geolocation' => [
'passed' => (int)$geo['geo_passed'],
@@ -270,9 +349,15 @@ try {
'bypass' => (int)$geo['geo_bypass'],
],
'deviceStats' => $deviceStats,
'visitorSummary' => [
'uniqueVisitors' => $uniqueVisitors,
'returningVisitors' => $returningVisitors,
],
'recentOpens' => $recentOpens,
'guestQueueSummary' => [
'total' => (int)$queueSummary['total_actions'],
'waiterCalls' => (int)$queueSummary['waiter_calls'],
'billRequests' => (int)$queueSummary['bill_requests'],
'pendingApi' => (int)$queueSummary['pending_api'],
'pendingKds' => (int)$queueSummary['pending_kds'],
'doneKds' => (int)$queueSummary['done_kds'],