153 lines
6.0 KiB
PHP
153 lines
6.0 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\DTOs\FlightStatData;
|
|
use App\Models\Aircraft;
|
|
use App\Models\IataEquipmentCode;
|
|
use App\Models\Notification;
|
|
use App\Models\UserFlight;
|
|
use App\Services\FlightStatsService;
|
|
use Carbon\Carbon;
|
|
use Carbon\CarbonImmutable;
|
|
use Illuminate\Console\Attributes\Description;
|
|
use Illuminate\Console\Attributes\Signature;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
#[Signature('app:update-departed-flights')]
|
|
#[Description('Command description')]
|
|
class UpdateDepartedFlights extends Command
|
|
{
|
|
|
|
public function __construct(protected FlightStatsService $flightStats)
|
|
{
|
|
parent::__construct();
|
|
}
|
|
|
|
protected function notifyDataError(UserFlight $flight): void
|
|
{
|
|
Notification::create([
|
|
'user_id' => $flight->user_id,
|
|
'title' => "Auto update failed for {$flight->flight_number}",
|
|
'body' => "There was an error fetching flight data for {$flight->flight_number}. Please manually check the aircraft type, registration and departure/arrival times.",
|
|
'url' => '/flights/' . $flight->id . '/edit'
|
|
]);
|
|
|
|
$flight->update(['auto_update' => false]);
|
|
}
|
|
|
|
/**
|
|
* Execute the console command.
|
|
*/
|
|
public function handle(): void
|
|
{
|
|
$now = now()->utc();
|
|
|
|
$userFlights = UserFlight::where('arrival_date', '<=', $now->copy()->subHour()->toDateTimeString())
|
|
->where('auto_update', true)
|
|
->whereNotNull('flight_number')
|
|
->get();
|
|
|
|
$this->info("Found {$userFlights->count()} flights.");
|
|
|
|
foreach ($userFlights as $flight) {
|
|
preg_match('/^([A-Z]{2,3})(\d+)$/i', $flight->flight_number, $matches);
|
|
|
|
if (empty($matches)) {
|
|
$this->warn("Could not parse flight number: {$flight->flight_number}");
|
|
$this->notifyDataError($flight);
|
|
continue;
|
|
}
|
|
|
|
$airlineCode = strtoupper($matches[1]);
|
|
$flightNumber = $matches[2];
|
|
|
|
$arrivalDate = $flight->arrival_date->setTimezone($flight->arrivalAirport->timezone);
|
|
|
|
$data = $this->flightStats->fetchFlightData($airlineCode, $flightNumber, $arrivalDate);
|
|
|
|
if (!$data) {
|
|
$this->warn("No flight data returned for {$airlineCode}{$flightNumber}");
|
|
$this->notifyDataError($flight);
|
|
continue;
|
|
}
|
|
|
|
if ($data->departure_iata !== $flight->departureAirport->iata_code ||
|
|
$data->arrival_iata !== $flight->arrivalAirport->iata_code) {
|
|
$this->warn("Airport mismatch for {$airlineCode}{$flightNumber} — API: {$data->departure_iata}→{$data->arrival_iata}, expected: {$flight->departureAirport->iata_code}→{$flight->arrivalAirport->iata_code}");
|
|
$this->notifyDataError($flight);
|
|
|
|
continue;
|
|
}
|
|
|
|
$updates = [];
|
|
|
|
if ($data->aircraft_registration && $data->aircraft_registration !== $flight->aircraft_registration) {
|
|
$updates['aircraft_registration'] = $data->aircraft_registration;
|
|
}
|
|
|
|
if ($data->estimated_departure_utc?->ne($flight->departure_date)) {
|
|
$updates['departure_date'] = $data->estimated_departure_utc;
|
|
}
|
|
|
|
if ($data->estimated_arrival_utc?->ne($flight->arrival_date)) {
|
|
$updates['arrival_date'] = $data->estimated_arrival_utc;
|
|
}
|
|
|
|
if ($data->equipment_iata) {
|
|
$currentAircraft = $flight->aircraft;
|
|
|
|
if ($currentAircraft?->iata_code !== $data->equipment_iata) {
|
|
$match = $this->flightStats->guessAircraftFromIata($data->equipment_iata);
|
|
|
|
if ($match) {
|
|
$updates['aircraft_id'] = $match->id;
|
|
} else {
|
|
Log::info("No aircraft match for IATA code {$data->equipment_iata} on flight {$airlineCode}{$flightNumber}");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($updates)) {
|
|
$flight->update($updates);
|
|
$this->info("Updated flight {$airlineCode}{$flightNumber}: " . implode(', ', array_keys($updates)));
|
|
|
|
$changeDescriptions = [];
|
|
if (isset($updates['aircraft_registration'])) {
|
|
$changeDescriptions[] = "Registration updated to {$updates['aircraft_registration']}";
|
|
}
|
|
if (isset($updates['departure_date'])) {
|
|
$changeDescriptions[] = "Departure updated to {$updates['departure_date']}";
|
|
}
|
|
if (isset($updates['arrival_date'])) {
|
|
$changeDescriptions[] = "Arrival updated to {$updates['arrival_date']}";
|
|
}
|
|
if (isset($updates['aircraft_id'])) {
|
|
$aircraft = Aircraft::find($updates['aircraft_id']);
|
|
$changeDescriptions[] = "Aircraft type updated to {$aircraft->display_name_short}";
|
|
}
|
|
|
|
Notification::create([
|
|
'user_id' => $flight->user_id,
|
|
'title' => "Flight {$airlineCode}{$flightNumber} updated",
|
|
'body' => implode("\n", $changeDescriptions),
|
|
'url' => '/u/'. $flight->user->name . '/flight/'. $flight->id,
|
|
]);
|
|
} else {
|
|
$this->info("No changes for {$airlineCode}{$flightNumber}");
|
|
|
|
Notification::create([
|
|
'user_id' => $flight->user_id,
|
|
'title' => "Flight {$airlineCode}{$flightNumber} updated — no changes",
|
|
'body' => "Your flight was completed and no updates were made to aircraft, registration, or departure/arrival times.",
|
|
'url' => '/u/'. $flight->user->name . '/flight/'. $flight->id,
|
|
]);
|
|
}
|
|
|
|
$flight->update(['auto_update' => false]);
|
|
}
|
|
}
|
|
}
|