diff --git a/app/Http/Controllers/Admin/FlightController.php b/app/Http/Controllers/Admin/FlightController.php index 12e1b2d4..a435278e 100644 --- a/app/Http/Controllers/Admin/FlightController.php +++ b/app/Http/Controllers/Admin/FlightController.php @@ -15,6 +15,7 @@ use App\Repositories\FareRepository; use App\Repositories\FlightFieldRepository; use App\Repositories\FlightRepository; use App\Repositories\SubfleetRepository; +use App\Services\ExporterService; use App\Services\FareService; use App\Services\FlightService; use App\Services\ImporterService; @@ -310,6 +311,27 @@ class FlightController extends Controller return redirect(route('admin.flights.index')); } + /** + * Run the flight exporter + * @param Request $request + * @return \Symfony\Component\HttpFoundation\BinaryFileResponse + * @throws \League\Csv\Exception + */ + public function export(Request $request) + { + $exporter = app(ExporterService::class); + $path = storage_path('app/import/export_flight.csv'); + + $flights = $this->flightRepo->all(); + $exporter->exportFlights($flights, $path); + + return response() + ->download($path, 'flights.csv', [ + 'content-type' => 'text/csv', + ]) + ->deleteFileAfterSend(true); + } + /** * * @param Request $request diff --git a/app/Interfaces/ImportExport.php b/app/Interfaces/ImportExport.php index 98722e35..c9392d5f 100644 --- a/app/Interfaces/ImportExport.php +++ b/app/Interfaces/ImportExport.php @@ -17,26 +17,6 @@ class ImportExport */ public static $columns = []; - /** - * Need to implement in a child class! - * @throws \RuntimeException - */ - public function export() - { - throw new \RuntimeException('Calling export, needs to be implemented in child!'); - } - - /** - * Need to implement in a child class! - * @param array $row - * @param $index - * @throws \RuntimeException - */ - public function import(array $row, $index) - { - throw new \RuntimeException('Calling import, needs to be implemented in child!'); - } - /** * Get the airline from the ICAO * @param $code @@ -118,4 +98,48 @@ class ImportExport return $ret; } + + /** + * @param $obj + * @return mixed + */ + public function objectToMultiString($obj) + { + if(!\is_array($obj)) { + return $obj; + } + + $ret_list = []; + foreach ($obj as $key => $val) { + if(is_numeric($key) && !\is_array($val)) { + $ret_list[] = $val; + continue; + } + + $key = trim($key); + + if(!\is_array($val)) { + $val = trim($val); + $ret_list[] = "{$key}={$val}"; + } else { + $q = []; + foreach($val as $subkey => $subval) { + if(is_numeric($subkey)) { + $q[] = $subval; + } else { + $q[] = "{$subkey}={$subval}"; + } + } + + $q = implode('&', $q); + if(!empty($q)) { + $ret_list[] = "{$key}?{$q}"; + } else { + $ret_list[] = $key; + } + } + } + + return implode(';', $ret_list); + } } diff --git a/app/Models/Flight.php b/app/Models/Flight.php index 4c937802..70206fa3 100644 --- a/app/Models/Flight.php +++ b/app/Models/Flight.php @@ -16,6 +16,7 @@ use PhpUnitsOfMeasure\Exception\NonStringUnitName; * @property mixed route_code * @property mixed route_leg * @property Collection field_values + * @property Collection fares */ class Flight extends Model { diff --git a/app/Routes/admin.php b/app/Routes/admin.php index 57a604b8..c5d5dce6 100644 --- a/app/Routes/admin.php +++ b/app/Routes/admin.php @@ -32,6 +32,7 @@ Route::group([ Route::resource('finances', 'FinanceController'); # flights and aircraft associations + Route::get('flights/export', 'FlightController@export')->name('flights.export'); Route::match(['get', 'post'], 'flights/import', 'FlightController@import')->name('flights.import'); Route::match(['get', 'post', 'put', 'delete'], 'flights/{id}/fares', 'FlightController@fares'); Route::match(['get', 'post', 'put', 'delete'], 'flights/{id}/fields', 'FlightController@field_values'); diff --git a/app/Services/ExporterService.php b/app/Services/ExporterService.php new file mode 100644 index 00000000..0560c79f --- /dev/null +++ b/app/Services/ExporterService.php @@ -0,0 +1,72 @@ +flightRepo = $flightRepo; + } + + /** + * @param $csv_file + * @return Writer + */ + public function openCsv($csv_file): Writer + { + $writer = Writer::createFromPath($csv_file, 'w+'); + CharsetConverter::addTo($writer, 'utf-8', 'iso-8859-15'); + return $writer; + } + + /** + * Run the actual importer + * @param Collection $collection + * @param Writer $writer + * @param ImportExport $exporter + * @return bool + * @throws \League\Csv\CannotInsertRecord + */ + protected function runExport(Collection $collection, Writer $writer, ImportExport $exporter): bool + { + $writer->insertOne($exporter->getColumns()); + foreach ($collection as $row) { + $writer->insertOne($exporter->export($row)); + } + + return true; + } + + /** + * Export all of the flights + * @param Collection $flights + * @param string $csv_file + * @return mixed + * @throws \League\Csv\Exception + */ + public function exportFlights($flights, $csv_file) + { + $writer = $this->openCsv($csv_file); + + $exporter = new FlightExporter(); + return $this->runExport($flights, $writer, $exporter); + } +} diff --git a/app/Services/FareService.php b/app/Services/FareService.php index 7d2e1bbc..3bb51020 100644 --- a/app/Services/FareService.php +++ b/app/Services/FareService.php @@ -98,6 +98,12 @@ class FareService extends Service { $flight->fares()->syncWithoutDetaching([$fare->id]); + foreach($override as $key => $item) { + if(!$item) { + unset($override[$key]); + } + } + # modify any pivot values? if (\count($override) > 0) { $flight->fares()->updateExistingPivot($fare->id, $override); diff --git a/app/Services/Import/FlightExporter.php b/app/Services/Import/FlightExporter.php new file mode 100644 index 00000000..e454ee9e --- /dev/null +++ b/app/Services/Import/FlightExporter.php @@ -0,0 +1,107 @@ +{$column}; + } + + # Modify special fields + $ret['airline'] = $ret['airline']->icao; + $ret['distance'] = $ret['distance']->toNumber(); + + $ret['fares'] = $this->getFares($flight); + $ret['fields'] = $this->getFields($flight); + $ret['subfleets'] = $this->getSubfleets($flight); + + return $ret; + } + + /** + * Return any custom fares that have been made to this flight + * @param Flight $flight + * @return string + */ + protected function getFares(Flight &$flight): string + { + $fares = []; + foreach($flight->fares as $fare) { + $fare_export = []; + if($fare->pivot->price) { + $fare_export['price'] = $fare->pivot->price; + } + + if ($fare->pivot->cost) { + $fare_export['cost'] = $fare->pivot->cost; + } + + if ($fare->pivot->capacity) { + $fare_export['capacity'] = $fare->pivot->capacity; + } + + $fares[$fare->code] = $fare_export; + } + + return $this->objectToMultiString($fares); + } + + /** + * Parse all of the subfields + * @param Flight $flight + * @return string + */ + protected function getFields(Flight &$flight): string + { + $ret = []; + foreach ($flight->field_values as $field) { + $ret[$field->name] = $field->value; + } + + return $this->objectToMultiString($ret); + } + + /** + * Create the list of subfleets that are associated here + * @param Flight $flight + * @return string + */ + protected function getSubfleets(Flight &$flight): string + { + $subfleets = []; + foreach($flight->subfleets as $subfleet) { + $subfleets[] = $subfleet->type; + } + + return $this->objectToMultiString($subfleets); + } +} diff --git a/resources/views/admin/flights/index.blade.php b/resources/views/admin/flights/index.blade.php index 97163a23..a993e48c 100644 --- a/resources/views/admin/flights/index.blade.php +++ b/resources/views/admin/flights/index.blade.php @@ -2,6 +2,7 @@ @section('title', 'Flights') @section('actions') +