query('customerNo', '')); $customerName = trim((string) $request->query('customerName', '')); $refreshRequested = DebitorCacheControl::parseRefreshFlag($request->query('refresh', '')); if ($customerNo === '' || $customerName === '') { http_response_code(400); Router::json(['ok' => false, 'error' => 'Missing parameters']); return; } // Reuse session cache from tickets endpoint when available (avoids duplicate OData call) $sessionStore = app(SessionStoreInterface::class); $session = $sessionStore->all(); $tenantScope = DebitorCacheControl::resolveTenantScope($session); if ($refreshRequested) { DebitorCacheControl::invalidateDebitorCaches($sessionStore, $tenantScope, $customerNo, true); } $cacheKey = DebitorCacheControl::ticketsKey($tenantScope, $customerNo); $cacheTtl = DebitorCacheControl::TTL_STANDARD_SECONDS; $cached = $sessionStore->get($cacheKey); if (!$refreshRequested && is_array($cached) && isset($cached['fetched_at']) && (time() - (int) $cached['fetched_at']) < $cacheTtl) { $cachedTickets = $cached['tickets'] ?? []; if (!is_array($cachedTickets)) { $cachedTickets = []; } $summary = DebitorDetailService::summarizeTickets($cachedTickets); $summary['meta'] = [ 'cache_used' => true, 'cache_bypassed' => false, 'cache_refreshed' => false, ]; Router::json($summary); return; } // Cache miss — load via service, populate cache, then summarize $service = app(DebitorDetailService::class); $ticketsResult = $service->loadTickets($customerNo, $customerName); if (!($ticketsResult['ok'] ?? false)) { Router::json(['ok' => false, 'error' => $ticketsResult['error'] ?? 'Failed to load tickets']); return; } $tickets = $ticketsResult['tickets'] ?? []; if (!is_array($tickets)) { $tickets = []; } $sessionStore->set($cacheKey, [ 'tickets' => $tickets, 'fetched_at' => time(), ]); $summary = DebitorDetailService::summarizeTickets($tickets); $summary['meta'] = [ 'cache_used' => false, 'cache_bypassed' => $refreshRequested, 'cache_refreshed' => $refreshRequested, ]; Router::json($summary);