193 lines
6.3 KiB
PHP
193 lines
6.3 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Airline;
|
|
use App\Models\ImportedFlight;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
class FlightImportController extends Controller
|
|
{
|
|
|
|
const array FLIGHT_CLASSES = [
|
|
0 => 'Please Select',
|
|
1 => 'Economy',
|
|
2 => 'Business',
|
|
3 => 'First',
|
|
4 => 'Premium Economy',
|
|
5 => 'Private',
|
|
];
|
|
|
|
const array SEAT_TYPES = [
|
|
0 => 'Please Select',
|
|
1 => 'Window',
|
|
2 => 'Middle',
|
|
3 => 'Aisle',
|
|
];
|
|
|
|
const array FLIGHT_REASONS = [
|
|
0 => 'Please Select',
|
|
1 => 'Pleasure',
|
|
2 => 'Business',
|
|
3 => 'Crew',
|
|
4 => 'Other',
|
|
];
|
|
|
|
private function formatTime(?string $time): string
|
|
{
|
|
if (!$time) return '00:00';
|
|
|
|
[$hours, $minutes] = explode(':', $time);
|
|
return str_pad($hours, 2, '0', STR_PAD_LEFT) . ':' . $minutes;
|
|
}
|
|
|
|
public function getPossibleAirlines(string $airlineQuery) {
|
|
preg_match('/\((\w{2,3})\/(\w{3,4})\)/', $airlineQuery, $matches);
|
|
$iata = $matches[1] ?? null;
|
|
$icao = $matches[2] ?? null;
|
|
|
|
$airlines = Airline::when($iata || $icao, function ($query) use ($iata, $icao) {
|
|
$query->orderByRaw("
|
|
CASE
|
|
WHEN \"IATA_code\" = ? AND \"ICAO_code\" = ? THEN 0
|
|
WHEN \"IATA_code\" = ? THEN 1
|
|
WHEN \"ICAO_code\" = ? THEN 2
|
|
ELSE 3
|
|
END
|
|
", [$iata, $icao, $iata, $icao])
|
|
->where(function ($q) use ($iata, $icao) {
|
|
$q->where('IATA_code', $iata)
|
|
->orWhere('ICAO_code', $icao);
|
|
});
|
|
})
|
|
->orderByDesc('active')
|
|
->limit(10)
|
|
->get(['id', 'name', 'IATA_code', 'ICAO_code'])
|
|
->map(fn($a) => [
|
|
'value' => $a->id,
|
|
'title' => "{$a->name} ({$a->IATA_code}/{$a->ICAO_code})",
|
|
])
|
|
->values()
|
|
->toArray();
|
|
|
|
return [
|
|
'airline_options' => $airlines,
|
|
'raw_airline' => $airlineQuery,
|
|
];
|
|
}
|
|
|
|
public function reconcile(Request $request)
|
|
{
|
|
$user = Auth::user();
|
|
|
|
$flightToReconcile = ImportedFlight::where('user_id', $user->id)->orderBy('id')->first();
|
|
|
|
if (!$flightToReconcile) {
|
|
return null;
|
|
}
|
|
|
|
$date = null;
|
|
if ($flightToReconcile->date) {
|
|
$date = Carbon::createFromFormat('m-d-y', $flightToReconcile->date)->format('Y-m-d');
|
|
}
|
|
|
|
|
|
return [
|
|
'flight_classes' => collect(self::FLIGHT_CLASSES)->map(fn($title, $value) => [
|
|
'value' => $value,
|
|
'title' => $title,
|
|
])->values(),
|
|
'flight_reasons' => collect(self::FLIGHT_REASONS)->map(fn($title, $value) => [
|
|
'value' => $value,
|
|
'title' => $title,
|
|
])->values(),
|
|
'seat_types' => collect(self::SEAT_TYPES)->map(fn($title, $value) => [
|
|
'value' => $value,
|
|
'title' => $title,
|
|
])->values(),
|
|
|
|
'flight_number' => $flightToReconcile->flight_number ?? '',
|
|
'date' => $date ?? '',
|
|
'dep_time' => $this->formatTime($flightToReconcile->dep_time),
|
|
'arr_time' => $this->formatTime($flightToReconcile->arr_time),
|
|
'duration' => $this->formatTime($flightToReconcile->duration),
|
|
'registration' => $flightToReconcile->registration ?? '',
|
|
'note' => $flightToReconcile->note ?? '',
|
|
'seat_number' => $flightToReconcile->seat_number ?? '',
|
|
'flight_class' => $flightToReconcile->flight_class ?? '',
|
|
'seat_type' => $flightToReconcile->seat_type ?? '',
|
|
'flight_reason' => $flightToReconcile->flight_reason ?? '',
|
|
'airline_options' => $this->getPossibleAirlines($flightToReconcile->airline ?? '')['airline_options'],
|
|
];
|
|
}
|
|
public function store(Request $request)
|
|
{
|
|
try {
|
|
$request->validate([
|
|
'csv' => ['required', 'file', 'mimes:csv,txt', 'max:10240'],
|
|
]);
|
|
|
|
$path = $request->file('csv')->getRealPath();
|
|
$handle = fopen($path, 'r');
|
|
|
|
fgetcsv($handle);
|
|
|
|
// Read and normalise header row
|
|
$headers = array_map(
|
|
fn($h) => strtolower(trim(str_replace(' ', '_', $h))),
|
|
fgetcsv($handle)
|
|
);
|
|
|
|
\Log::debug('CSV headers', $headers);
|
|
$firstRow = fgetcsv($handle);
|
|
\Log::debug('First row', $firstRow ?? ['empty']);
|
|
\Log::debug('Header count: ' . count($headers) . ', Row count: ' . count($firstRow ?? []));
|
|
|
|
$map = [
|
|
'date' => 'date',
|
|
'flight_number' => 'flight_number',
|
|
'from' => 'from',
|
|
'to' => 'to',
|
|
'dep_time' => 'dep_time',
|
|
'arr_time' => 'arr_time',
|
|
'duration' => 'duration',
|
|
'airline' => 'airline',
|
|
'aircraft' => 'aircraft',
|
|
'registration' => 'registration',
|
|
'seat_number' => 'seat_number',
|
|
'seat_type' => 'seat_type',
|
|
'flight_class' => 'flight_class',
|
|
'flight_reason' => 'flight_reason',
|
|
'note' => 'note',
|
|
];
|
|
|
|
$userId = Auth::id();
|
|
$imported = 0;
|
|
|
|
while (($row = fgetcsv($handle)) !== false) {
|
|
if (count($row) !== count($headers)) {
|
|
continue; // skip malformed rows
|
|
}
|
|
|
|
$raw = array_combine($headers, $row);
|
|
$data = ['user_id' => $userId];
|
|
|
|
foreach ($map as $csvKey => $column) {
|
|
$data[$column] = $raw[$csvKey] ?? null;
|
|
}
|
|
|
|
ImportedFlight::create($data);
|
|
$imported++;
|
|
}
|
|
|
|
fclose($handle);
|
|
|
|
return response()->json(['imported' => $imported]);
|
|
} catch (\Exception $e) {
|
|
return response()->json(['message' => $e->getMessage()], 500);
|
|
}
|
|
}
|
|
}
|