@endif
@can('super-admin')
@php
$isLocal = preg_match('/\d+\.\d+\.\d+\.\d+/', config('app.url')) === 1;
// Only show sync settings on local servers, not on API servers
$showSyncSettings = !$isApiServer;
@endphp
@if($showSyncSettings)
{{__('messages.settings.sync_settings')}}
{{__('messages.settings.sync_settings_description')}}
sync
check_circle
{{__('messages.common.update_success')}}
close
@php
$isLocal = preg_match('/\d+\.\d+\.\d+\.\d+/', config('app.url')) === 1;
// Only local servers can control sync settings
// API servers (stage/prod) can only view city sync status
$canControlSync = $isLocal && !$isApiServer;
// Always fetch fresh settings to avoid cache issues - refresh to get latest sync_last_at
\Cache::forget('settings'); // Clear cache first
$settings = \App\Models\Setting::first();
if ($settings) {
$settings->refresh(); // Force refresh to get latest sync_last_at and sync_interval_minutes
}
$syncEnabled = $settings && $settings->sync_enabled == 1;
// Use old() only if form validation failed, otherwise use fresh database value
$syncInterval = old('sync_interval_minutes');
if ($syncInterval === null) {
$syncInterval = $settings ? (int)$settings->sync_interval_minutes : 5;
}
$lastSyncAt = $settings ? $settings->sync_last_at : null;
$syncStatus = $settings ? $settings->sync_status : 'pending';
$liveUrl = old('sync_live_url', $settings ? $settings->sync_live_url : 'https://qflow.prod.api.alho.cloud');
// For prod/staging: determine if sync is active based on recent sync data
$syncActive = false;
if (!$isLocal && $lastSyncAt) {
$lastSync = \Carbon\Carbon::parse($lastSyncAt);
$syncActive = $lastSync->isAfter(now()->subDay()); // Active if synced within last 24 hours
}
@endphp
@if($canControlSync)
@else
@php
// Get all cities and their detailed sync status
$cities = \App\Models\City::withCount([
'queues' => function($query) {
$query->whereNotNull('city_id');
},
'calls' => function($query) {
$query->whereNotNull('city_id');
},
'messages' => function($query) {
$query->whereNotNull('city_id');
},
'locations' => function($query) {
$query->whereNotNull('city_id');
}
])->get();
// Get detailed sync information per city
$citySyncDetails = [];
foreach ($cities as $city) {
// Sync run observability (latest success/failure)
$lastSuccessRun = null;
$lastFailedRun = null;
try {
if (\Schema::hasTable('city_sync_runs')) {
$lastSuccessRun = \DB::table('city_sync_runs')
->where('city_id', $city->id)
->where('status', 'success')
->orderByDesc('finished_at')
->first();
$lastFailedRun = \DB::table('city_sync_runs')
->where('city_id', $city->id)
->where('status', 'failed')
->orderByDesc('finished_at')
->first();
}
} catch (\Throwable $e) {
// ignore
}
// Get last update times for each data type
$lastQueue = \App\Models\Queue::where('city_id', $city->id)->latest('updated_at')->first();
$lastCall = \App\Models\Call::where('city_id', $city->id)->latest('updated_at')->first();
$lastMessage = \App\Models\Message::where('city_id', $city->id)->latest('updated_at')->first();
$lastLocation = \App\Models\Location::where('city_id', $city->id)->latest('updated_at')->first();
// Get counters, services, and users counts through location relationship
$countersCount = \App\Models\Counter::whereHas('location', function($q) use ($city) {
$q->where('city_id', $city->id);
})->count();
$servicesCount = \App\Models\Service::whereHas('location', function($q) use ($city) {
$q->where('city_id', $city->id);
})->count();
$usersCount = \App\Models\User::whereHas('location', function($q) use ($city) {
$q->where('city_id', $city->id);
})->count();
// Get last update times
$lastCounter = \App\Models\Counter::whereHas('location', function($q) use ($city) {
$q->where('city_id', $city->id);
})->latest('updated_at')->first();
$lastService = \App\Models\Service::whereHas('location', function($q) use ($city) {
$q->where('city_id', $city->id);
})->latest('updated_at')->first();
$lastUser = \App\Models\User::whereHas('location', function($q) use ($city) {
$q->where('city_id', $city->id);
})->latest('updated_at')->first();
// Get overall last sync (most recent update)
$lastSync = collect([
$lastQueue?->updated_at,
$lastCall?->updated_at,
$lastMessage?->updated_at,
$lastLocation?->updated_at,
$lastCounter?->updated_at,
$lastService?->updated_at,
$lastUser?->updated_at
])->filter()->max();
$citySyncDetails[$city->id] = [
'last_queue' => $lastQueue?->updated_at,
'last_call' => $lastCall?->updated_at,
'last_message' => $lastMessage?->updated_at,
'last_location' => $lastLocation?->updated_at,
'last_counter' => $lastCounter?->updated_at,
'last_service' => $lastService?->updated_at,
'last_user' => $lastUser?->updated_at,
'last_sync' => $lastSync,
'counters_count' => $countersCount,
'services_count' => $servicesCount,
'users_count' => $usersCount,
'last_success_run' => $lastSuccessRun,
'last_failed_run' => $lastFailedRun,
];
}
@endphp
info
City Sync Status
This page shows the sync status for each city. Sync is managed from local servers only.
@if($cities->count() > 0)
@foreach($cities as $city)
@php
$details = $citySyncDetails[$city->id] ?? [];
$lastSync = $details['last_sync'] ?? null;
$isHealthy = $lastSync && $lastSync->isAfter(now()->subDay());
$hasData = $city->queues_count > 0 || $city->calls_count > 0 || $city->messages_count > 0 || $city->locations_count > 0;
// Determine status color
if ($isHealthy && $hasData) {
$statusColor = 'green';
$statusText = 'Healthy';
$statusIcon = 'check_circle';
} elseif ($hasData) {
$statusColor = 'yellow';
$statusText = 'Stale';
$statusIcon = 'warning';
} else {
$statusColor = 'gray';
$statusText = 'No Data';
$statusIcon = 'info';
}
@endphp
{{ $city->name }}
Code: {{ strtoupper($city->code) }}
Last Sync
@if($lastSync)
{{ $lastSync->diffForHumans() }}
@else
Never
@endif
@if(isset($details['last_success_run']) && $details['last_success_run'])
Last success:
{{ \Carbon\Carbon::parse($details['last_success_run']->finished_at)->diffForHumans() }}
@if(!empty($details['last_success_run']->duration_ms))
({{ (int)$details['last_success_run']->duration_ms }}ms)
@endif
@endif
@if(isset($details['last_failed_run']) && $details['last_failed_run'])
Last failure:
{{ \Carbon\Carbon::parse($details['last_failed_run']->finished_at)->diffForHumans() }}
@endif
{{ $statusIcon }}
{{ $statusText }}
expand_more
{{ number_format($city->queues_count) }}
Queues
{{ number_format($city->calls_count) }}
Calls
{{ number_format($city->messages_count) }}
Messages
{{ number_format($city->locations_count) }}
Locations
{{ number_format($details['counters_count']) }}
Counters
{{ number_format($details['services_count']) }}
Services
{{ number_format($details['users_count']) }}
Users
data_usage
Data Sync Details
queue
Queues
{{ number_format($city->queues_count) }}
@if($details['last_queue'])
Updated {{ $details['last_queue']->diffForHumans() }}
@else
Never
@endif
phone
Calls
{{ number_format($city->calls_count) }}
@if($details['last_call'])
Updated {{ $details['last_call']->diffForHumans() }}
@else
Never
@endif
message
Messages
{{ number_format($city->messages_count) }}
@if($details['last_message'])
Updated {{ $details['last_message']->diffForHumans() }}
@else
Never
@endif
place
Locations
{{ number_format($city->locations_count) }}
@if($details['last_location'])
Updated {{ $details['last_location']->diffForHumans() }}
@else
Never
@endif
info
Additional Information
desktop_windows
Counters
{{ number_format($details['counters_count']) }}
@if($details['last_counter'])
Updated {{ $details['last_counter']->diffForHumans() }}
@else
Never
@endif
business_center
Services
{{ number_format($details['services_count']) }}
@if($details['last_service'])
Updated {{ $details['last_service']->diffForHumans() }}
@else
Never
@endif
people
Users
{{ number_format($details['users_count']) }}
@if($details['last_user'])
Updated {{ $details['last_user']->diffForHumans() }}
@else
Never
@endif
Overall Status
Sync Health
{{ $statusText }}
@if($lastSync)
Last synchronized: {{ $lastSync->format('M d, Y H:i:s') }}
@endif
@endforeach
@else
location_city
No cities found. Cities will appear here once they start syncing data.
@endif
@endif
@endif
@endcan
@if($isApiServer)