Add importers in console and admin for flights/aircraft/subfleets and airport #194
This commit is contained in:
59
app/Console/Commands/ImportCsv.php
Normal file
59
app/Console/Commands/ImportCsv.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Console\Command;
|
||||
use App\Services\ImporterService;
|
||||
|
||||
/**
|
||||
* Class ImportCsv
|
||||
* @package App\Console\Commands
|
||||
*/
|
||||
class ImportCsv extends Command
|
||||
{
|
||||
protected $signature = 'phpvms:csv-import {type} {file}';
|
||||
protected $description = 'Import from a CSV file';
|
||||
|
||||
private $importer;
|
||||
|
||||
/**
|
||||
* Import constructor.
|
||||
* @param ImporterService $importer
|
||||
*/
|
||||
public function __construct(ImporterService $importer)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->importer = $importer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|void
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$type = $this->argument('type');
|
||||
$file = $this->argument('file');
|
||||
|
||||
if (\in_array($type, ['flight', 'flights'])) {
|
||||
$status = $this->importer->importFlights($file);
|
||||
} elseif ($type === 'aircraft') {
|
||||
$status = $this->importer->importAircraft($file);
|
||||
} elseif (\in_array($type, ['airport', 'airports'])) {
|
||||
$status = $this->importer->importAirports($file);
|
||||
} elseif ($type === 'subfleet') {
|
||||
$status = $this->importer->importSubfleets($file);
|
||||
}
|
||||
|
||||
foreach($status['success'] as $line) {
|
||||
$this->info($line);
|
||||
}
|
||||
|
||||
foreach ($status['failed'] as $line) {
|
||||
$this->error($line);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@ use Faker\Generator as Faker;
|
||||
$factory->define(App\Models\Fare::class, function (Faker $faker) {
|
||||
return [
|
||||
'id' => null,
|
||||
'code' => $faker->text(5),
|
||||
'name' => $faker->text(20),
|
||||
'code' => $faker->unique()->text(50),
|
||||
'name' => $faker->text(50),
|
||||
'price' => $faker->randomFloat(2, 100, 1000),
|
||||
'cost' => function (array $fare) {
|
||||
return round($fare['price'] / 2);
|
||||
|
||||
@@ -14,7 +14,7 @@ class CreateFaresTable extends Migration
|
||||
{
|
||||
Schema::create('fares', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('code', 50);
|
||||
$table->string('code', 50)->unique();
|
||||
$table->string('name', 50);
|
||||
$table->unsignedDecimal('price')->nullable()->default(0.00);
|
||||
$table->unsignedDecimal('cost')->nullable()->default(0.00);
|
||||
|
||||
@@ -13,8 +13,8 @@ class CreateSubfleetTables extends Migration
|
||||
Schema::create('subfleets', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->unsignedInteger('airline_id')->nullable();
|
||||
$table->string('type', 50)->unique();
|
||||
$table->string('name', 50);
|
||||
$table->string('type', 50);
|
||||
$table->unsignedTinyInteger('fuel_type')->nullable();
|
||||
$table->unsignedDecimal('ground_handling_multiplier')->nullable()->default(100);
|
||||
$table->unsignedDecimal('cargo_capacity')->nullable();
|
||||
|
||||
@@ -10,9 +10,12 @@ use App\Models\Enums\AircraftStatus;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Subfleet;
|
||||
use App\Repositories\AircraftRepository;
|
||||
use App\Services\ImporterService;
|
||||
use Flash;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
use Prettus\Repository\Criteria\RequestCriteria;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class AircraftController
|
||||
@@ -20,16 +23,20 @@ use Prettus\Repository\Criteria\RequestCriteria;
|
||||
*/
|
||||
class AircraftController extends Controller
|
||||
{
|
||||
private $aircraftRepo;
|
||||
private $aircraftRepo,
|
||||
$importSvc;
|
||||
|
||||
/**
|
||||
* AircraftController constructor.
|
||||
* @param AircraftRepository $aircraftRepo
|
||||
* @param ImporterService $importSvc
|
||||
*/
|
||||
public function __construct(
|
||||
AircraftRepository $aircraftRepo
|
||||
AircraftRepository $aircraftRepo,
|
||||
ImporterService $importSvc
|
||||
) {
|
||||
$this->aircraftRepo = $aircraftRepo;
|
||||
$this->importSvc = $importSvc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,7 +74,6 @@ class AircraftController extends Controller
|
||||
$aircraft = $this->aircraftRepo->create($attrs);
|
||||
|
||||
Flash::success('Aircraft saved successfully.');
|
||||
|
||||
return redirect(route('admin.aircraft.edit', ['id' => $aircraft->id]));
|
||||
}
|
||||
|
||||
@@ -80,7 +86,6 @@ class AircraftController extends Controller
|
||||
|
||||
if (empty($aircraft)) {
|
||||
Flash::error('Aircraft not found');
|
||||
|
||||
return redirect(route('admin.aircraft.index'));
|
||||
}
|
||||
|
||||
@@ -119,7 +124,6 @@ class AircraftController extends Controller
|
||||
|
||||
if (empty($aircraft)) {
|
||||
Flash::error('Aircraft not found');
|
||||
|
||||
return redirect(route('admin.aircraft.index'));
|
||||
}
|
||||
|
||||
@@ -127,7 +131,6 @@ class AircraftController extends Controller
|
||||
$this->aircraftRepo->update($attrs, $id);
|
||||
|
||||
Flash::success('Aircraft updated successfully.');
|
||||
|
||||
return redirect(route('admin.aircraft.index'));
|
||||
}
|
||||
|
||||
@@ -140,17 +143,43 @@ class AircraftController extends Controller
|
||||
|
||||
if (empty($aircraft)) {
|
||||
Flash::error('Aircraft not found');
|
||||
|
||||
return redirect(route('admin.aircraft.index'));
|
||||
}
|
||||
|
||||
$this->aircraftRepo->delete($id);
|
||||
|
||||
Flash::success('Aircraft deleted successfully.');
|
||||
|
||||
return redirect(route('admin.aircraft.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function import(Request $request)
|
||||
{
|
||||
$logs = [
|
||||
'success' => [],
|
||||
'failed' => [],
|
||||
];
|
||||
|
||||
if ($request->isMethod('post')) {
|
||||
$path = Storage::putFileAs(
|
||||
'import', $request->file('csv_file'), 'aircraft'
|
||||
);
|
||||
|
||||
$path = storage_path('app/'.$path);
|
||||
Log::info('Uploaded flights import file to '.$path);
|
||||
$logs = $this->importSvc->importAircraft($path);
|
||||
}
|
||||
|
||||
return view('admin.aircraft.import', [
|
||||
'logs' => $logs,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Aircraft|null $aircraft
|
||||
* @return mixed
|
||||
|
||||
@@ -9,10 +9,13 @@ use App\Models\Airport;
|
||||
use App\Models\Expense;
|
||||
use App\Repositories\AirportRepository;
|
||||
use App\Repositories\Criteria\WhereCriteria;
|
||||
use App\Services\ImporterService;
|
||||
use Flash;
|
||||
use Illuminate\Http\Request;
|
||||
use Jackiedo\Timezonelist\Facades\Timezonelist;
|
||||
use Log;
|
||||
use Response;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class AirportController
|
||||
@@ -20,15 +23,19 @@ use Response;
|
||||
*/
|
||||
class AirportController extends Controller
|
||||
{
|
||||
private $airportRepo;
|
||||
private $airportRepo,
|
||||
$importSvc;
|
||||
|
||||
/**
|
||||
* @param AirportRepository $airportRepo
|
||||
* @param ImporterService $importSvc
|
||||
*/
|
||||
public function __construct(
|
||||
AirportRepository $airportRepo
|
||||
AirportRepository $airportRepo,
|
||||
ImporterService $importSvc
|
||||
) {
|
||||
$this->airportRepo = $airportRepo;
|
||||
$this->importSvc = $importSvc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,17 +169,43 @@ class AirportController extends Controller
|
||||
|
||||
if (empty($airport)) {
|
||||
Flash::error('Airport not found');
|
||||
|
||||
return redirect(route('admin.airports.index'));
|
||||
}
|
||||
|
||||
$this->airportRepo->delete($id);
|
||||
|
||||
Flash::success('Airport deleted successfully.');
|
||||
|
||||
return redirect(route('admin.airports.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function import(Request $request)
|
||||
{
|
||||
$logs = [
|
||||
'success' => [],
|
||||
'failed' => [],
|
||||
];
|
||||
|
||||
if ($request->isMethod('post')) {
|
||||
$path = Storage::putFileAs(
|
||||
'import', $request->file('csv_file'), 'airports'
|
||||
);
|
||||
|
||||
$path = storage_path('app/'.$path);
|
||||
Log::info('Uploaded flights import file to '.$path);
|
||||
$logs = $this->importSvc->importAirports($path);
|
||||
}
|
||||
|
||||
return view('admin.airports.import', [
|
||||
'logs' => $logs,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Airport|null $airport
|
||||
* @return mixed
|
||||
|
||||
@@ -17,11 +17,13 @@ use App\Repositories\FlightRepository;
|
||||
use App\Repositories\SubfleetRepository;
|
||||
use App\Services\FareService;
|
||||
use App\Services\FlightService;
|
||||
use App\Services\ImporterService;
|
||||
use App\Support\Units\Time;
|
||||
use Flash;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
use Response;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class FlightController
|
||||
@@ -36,6 +38,7 @@ class FlightController extends Controller
|
||||
$flightFieldRepo,
|
||||
$fareSvc,
|
||||
$flightSvc,
|
||||
$importSvc,
|
||||
$subfleetRepo;
|
||||
|
||||
/**
|
||||
@@ -44,9 +47,10 @@ class FlightController extends Controller
|
||||
* @param AirportRepository $airportRepo
|
||||
* @param FareRepository $fareRepo
|
||||
* @param FlightRepository $flightRepo
|
||||
* @param FlightFieldRepository $flightFieldRepository
|
||||
* @param FlightFieldRepository $flightFieldRepo
|
||||
* @param FareService $fareSvc
|
||||
* @param FlightService $flightSvc
|
||||
* @param ImporterService $importSvc
|
||||
* @param SubfleetRepository $subfleetRepo
|
||||
*/
|
||||
public function __construct(
|
||||
@@ -57,6 +61,7 @@ class FlightController extends Controller
|
||||
FlightFieldRepository $flightFieldRepo,
|
||||
FareService $fareSvc,
|
||||
FlightService $flightSvc,
|
||||
ImporterService $importSvc,
|
||||
SubfleetRepository $subfleetRepo
|
||||
) {
|
||||
$this->airlineRepo = $airlineRepo;
|
||||
@@ -66,6 +71,7 @@ class FlightController extends Controller
|
||||
$this->flightFieldRepo = $flightFieldRepo;
|
||||
$this->fareSvc = $fareSvc;
|
||||
$this->flightSvc = $flightSvc;
|
||||
$this->importSvc = $importSvc;
|
||||
$this->subfleetRepo = $subfleetRepo;
|
||||
}
|
||||
|
||||
@@ -304,6 +310,34 @@ class FlightController extends Controller
|
||||
return redirect(route('admin.flights.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function import(Request $request)
|
||||
{
|
||||
$logs = [
|
||||
'success' => [],
|
||||
'failed' => [],
|
||||
];
|
||||
|
||||
if ($request->isMethod('post')) {
|
||||
$path = Storage::putFileAs(
|
||||
'import', $request->file('csv_file'), 'flights'
|
||||
);
|
||||
|
||||
$path = storage_path('app/'.$path);
|
||||
Log::info('Uploaded flights import file to '.$path);
|
||||
$logs = $this->importSvc->importFlights($path);
|
||||
}
|
||||
|
||||
return view('admin.flights.import', [
|
||||
'logs' => $logs,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $flight
|
||||
* @return mixed
|
||||
|
||||
@@ -15,10 +15,13 @@ use App\Repositories\RankRepository;
|
||||
use App\Repositories\SubfleetRepository;
|
||||
use App\Services\FareService;
|
||||
use App\Services\FleetService;
|
||||
use App\Services\ImporterService;
|
||||
use Flash;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
use Prettus\Repository\Criteria\RequestCriteria;
|
||||
use Response;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class SubfleetController
|
||||
@@ -30,6 +33,7 @@ class SubfleetController extends Controller
|
||||
$fareRepo,
|
||||
$fareSvc,
|
||||
$fleetSvc,
|
||||
$importSvc,
|
||||
$rankRepo,
|
||||
$subfleetRepo;
|
||||
|
||||
@@ -37,23 +41,26 @@ class SubfleetController extends Controller
|
||||
* SubfleetController constructor.
|
||||
* @param AircraftRepository $aircraftRepo
|
||||
* @param FleetService $fleetSvc
|
||||
* @param RankRepository $rankRepo
|
||||
* @param SubfleetRepository $subfleetRepo
|
||||
* @param FareRepository $fareRepo
|
||||
* @param FareService $fareSvc
|
||||
* @param ImporterService $importSvc
|
||||
* @param RankRepository $rankRepo
|
||||
* @param SubfleetRepository $subfleetRepo
|
||||
*/
|
||||
public function __construct(
|
||||
AircraftRepository $aircraftRepo,
|
||||
FleetService $fleetSvc,
|
||||
RankRepository $rankRepo,
|
||||
SubfleetRepository $subfleetRepo,
|
||||
FareRepository $fareRepo,
|
||||
FareService $fareSvc
|
||||
FareService $fareSvc,
|
||||
ImporterService $importSvc,
|
||||
RankRepository $rankRepo,
|
||||
SubfleetRepository $subfleetRepo
|
||||
) {
|
||||
$this->aircraftRepo = $aircraftRepo;
|
||||
$this->fareRepo = $fareRepo;
|
||||
$this->fareSvc = $fareSvc;
|
||||
$this->fleetSvc = $fleetSvc;
|
||||
$this->importSvc = $importSvc;
|
||||
$this->rankRepo = $rankRepo;
|
||||
$this->subfleetRepo = $subfleetRepo;
|
||||
}
|
||||
@@ -133,7 +140,6 @@ class SubfleetController extends Controller
|
||||
$subfleet = $this->subfleetRepo->create($input);
|
||||
|
||||
Flash::success('Subfleet saved successfully.');
|
||||
|
||||
return redirect(route('admin.subfleets.edit', ['id' => $subfleet->id]));
|
||||
}
|
||||
|
||||
@@ -148,12 +154,10 @@ class SubfleetController extends Controller
|
||||
|
||||
if (empty($subfleet)) {
|
||||
Flash::error('Subfleet not found');
|
||||
|
||||
return redirect(route('admin.subfleets.index'));
|
||||
}
|
||||
|
||||
$avail_fares = $this->getAvailFares($subfleet);
|
||||
|
||||
return view('admin.subfleets.show', [
|
||||
'subfleet' => $subfleet,
|
||||
'avail_fares' => $avail_fares,
|
||||
@@ -171,7 +175,6 @@ class SubfleetController extends Controller
|
||||
|
||||
if (empty($subfleet)) {
|
||||
Flash::error('Subfleet not found');
|
||||
|
||||
return redirect(route('admin.subfleets.index'));
|
||||
}
|
||||
|
||||
@@ -200,14 +203,12 @@ class SubfleetController extends Controller
|
||||
|
||||
if (empty($subfleet)) {
|
||||
Flash::error('Subfleet not found');
|
||||
|
||||
return redirect(route('admin.subfleets.index'));
|
||||
}
|
||||
|
||||
$this->subfleetRepo->update($request->all(), $id);
|
||||
|
||||
Flash::success('Subfleet updated successfully.');
|
||||
|
||||
return redirect(route('admin.subfleets.index'));
|
||||
}
|
||||
|
||||
@@ -222,7 +223,6 @@ class SubfleetController extends Controller
|
||||
|
||||
if (empty($subfleet)) {
|
||||
Flash::error('Subfleet not found');
|
||||
|
||||
return redirect(route('admin.subfleets.index'));
|
||||
}
|
||||
|
||||
@@ -231,17 +231,43 @@ class SubfleetController extends Controller
|
||||
$aircraft = $this->aircraftRepo->findWhere(['subfleet_id' => $id], ['id']);
|
||||
if ($aircraft->count() > 0) {
|
||||
Flash::error('There are aircraft still assigned to this subfleet, you can\'t delete it!')->important();
|
||||
|
||||
return redirect(route('admin.subfleets.index'));
|
||||
}
|
||||
|
||||
$this->subfleetRepo->delete($id);
|
||||
|
||||
Flash::success('Subfleet deleted successfully.');
|
||||
|
||||
return redirect(route('admin.subfleets.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function import(Request $request)
|
||||
{
|
||||
$logs = [
|
||||
'success' => [],
|
||||
'failed' => [],
|
||||
];
|
||||
|
||||
if ($request->isMethod('post')) {
|
||||
$path = Storage::putFileAs(
|
||||
'import', $request->file('csv_file'), 'subfleets'
|
||||
);
|
||||
|
||||
$path = storage_path('app/'.$path);
|
||||
Log::info('Uploaded flights import file to '.$path);
|
||||
$logs = $this->importSvc->importSubfleets($path);
|
||||
}
|
||||
|
||||
return view('admin.subfleets.import', [
|
||||
'logs' => $logs,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Subfleet $subfleet
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
@@ -251,7 +277,6 @@ class SubfleetController extends Controller
|
||||
$subfleet->refresh();
|
||||
|
||||
$avail_ranks = $this->getAvailRanks($subfleet);
|
||||
|
||||
return view('admin.subfleets.ranks', [
|
||||
'subfleet' => $subfleet,
|
||||
'avail_ranks' => $avail_ranks,
|
||||
@@ -267,7 +292,6 @@ class SubfleetController extends Controller
|
||||
$subfleet->refresh();
|
||||
|
||||
$avail_fares = $this->getAvailFares($subfleet);
|
||||
|
||||
return view('admin.subfleets.fares', [
|
||||
'subfleet' => $subfleet,
|
||||
'avail_fares' => $avail_fares,
|
||||
@@ -321,7 +345,6 @@ class SubfleetController extends Controller
|
||||
protected function return_expenses_view(?Subfleet $subfleet)
|
||||
{
|
||||
$subfleet->refresh();
|
||||
|
||||
return view('admin.subfleets.expenses', [
|
||||
'subfleet' => $subfleet,
|
||||
]);
|
||||
@@ -377,7 +400,6 @@ class SubfleetController extends Controller
|
||||
$subfleet = $this->subfleetRepo->findWithoutFail($id);
|
||||
if (empty($subfleet)) {
|
||||
return $this->return_fares_view($subfleet);
|
||||
//return view('admin.aircraft.fares', ['fares' => []]);
|
||||
}
|
||||
|
||||
if ($request->isMethod('get')) {
|
||||
|
||||
121
app/Interfaces/ImportExport.php
Normal file
121
app/Interfaces/ImportExport.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace App\Interfaces;
|
||||
|
||||
use App\Models\Airline;
|
||||
|
||||
/**
|
||||
* Common functionality used across all of the importers
|
||||
* @package App\Interfaces
|
||||
*/
|
||||
class ImportExport
|
||||
{
|
||||
public $status;
|
||||
|
||||
/**
|
||||
* Hold the columns for the particular table
|
||||
*/
|
||||
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
|
||||
* @return \App\Models\Airline
|
||||
*/
|
||||
public function getAirline($code)
|
||||
{
|
||||
return Airline::where('icao', $code)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns()
|
||||
{
|
||||
return static::$columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a key-value pair to an array
|
||||
* @param $kvp_str
|
||||
* @param array $arr
|
||||
*/
|
||||
protected function kvpToArray($kvp_str, array &$arr)
|
||||
{
|
||||
$item = explode('=', $kvp_str);
|
||||
if (\count($item) === 1) { # just a list?
|
||||
$arr[] = trim($item[0]);
|
||||
} else { # actually a key-value pair
|
||||
$k = trim($item[0]);
|
||||
$v = trim($item[1]);
|
||||
$arr[$k] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a multi column values field. E.g:
|
||||
* Y?price=200&cost=100; F?price=1200
|
||||
* or
|
||||
* gate=B32;cost index=100
|
||||
*
|
||||
* Converted into a multi-dimensional array
|
||||
*
|
||||
* @param $field
|
||||
* @return array|string
|
||||
*/
|
||||
public function parseMultiColumnValues($field)
|
||||
{
|
||||
$ret = [];
|
||||
$split_values = explode(';', $field);
|
||||
|
||||
# No multiple values in here, just a straight value
|
||||
if (\count($split_values) === 1) {
|
||||
return [$split_values[0]];
|
||||
}
|
||||
|
||||
foreach ($split_values as $value) {
|
||||
# This isn't in the query string format, so it's
|
||||
# just a straight key-value pair set
|
||||
if (strpos($value, '?') === false) {
|
||||
$this->kvpToArray($value, $ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
# This contains the query string, which turns it
|
||||
# into the multi-level array
|
||||
|
||||
$query_str = explode('?', $value);
|
||||
$parent = trim($query_str[0]);
|
||||
|
||||
$children = [];
|
||||
$kvp = explode('&', trim($query_str[1]));
|
||||
foreach ($kvp as $items) {
|
||||
$this->kvpToArray($items, $children);
|
||||
}
|
||||
|
||||
$ret[$parent] = $children;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use App\Models\Enums\AircraftStatus;
|
||||
use App\Models\Traits\ExpensableTrait;
|
||||
|
||||
/**
|
||||
* @property int id
|
||||
* @property mixed subfleet_id
|
||||
* @property string name
|
||||
* @property string icao
|
||||
@@ -38,8 +39,6 @@ class Aircraft extends Model
|
||||
|
||||
/**
|
||||
* The attributes that should be casted to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'subfleet_id' => 'integer',
|
||||
@@ -50,8 +49,6 @@ class Aircraft extends Model
|
||||
|
||||
/**
|
||||
* Validation rules
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $rules = [
|
||||
'subfleet_id' => 'required',
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Models\Traits\JournalTrait;
|
||||
|
||||
/**
|
||||
* Class Airline
|
||||
* @property mixed id
|
||||
* @property string code
|
||||
* @property string icao
|
||||
* @property string iata
|
||||
|
||||
@@ -19,4 +19,31 @@ class FlightType extends Enum
|
||||
FlightType::CARGO => 'Cargo',
|
||||
FlightType::CHARTER => 'Charter',
|
||||
];
|
||||
|
||||
/**
|
||||
* Return value from P, C or H
|
||||
* @param $code
|
||||
* @return int
|
||||
*/
|
||||
public static function getFromCode($code): int
|
||||
{
|
||||
if(is_numeric($code)) {
|
||||
return (int) $code;
|
||||
}
|
||||
|
||||
$code = strtolower($code);
|
||||
if($code === 'p') {
|
||||
return self::PASSENGER;
|
||||
}
|
||||
|
||||
if ($code === 'c') {
|
||||
return self::CARGO;
|
||||
}
|
||||
|
||||
if($code === 'h') {
|
||||
return self::CHARTER;
|
||||
}
|
||||
|
||||
return self::PASSENGER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class Fare extends Model
|
||||
];
|
||||
|
||||
public static $rules = [
|
||||
'code' => 'required',
|
||||
'code' => 'required|unique',
|
||||
'name' => 'required',
|
||||
];
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ class Subfleet extends Model
|
||||
|
||||
protected $fillable = [
|
||||
'airline_id',
|
||||
'name',
|
||||
'type',
|
||||
'name',
|
||||
'fuel_type',
|
||||
'ground_handling_multiplier',
|
||||
'cargo_capacity',
|
||||
@@ -40,8 +40,8 @@ class Subfleet extends Model
|
||||
];
|
||||
|
||||
protected static $rules = [
|
||||
'type' => 'required|unique',
|
||||
'name' => 'required',
|
||||
'type' => 'required',
|
||||
'ground_handling_multiplier' => 'nullable|numeric',
|
||||
];
|
||||
|
||||
|
||||
@@ -10,15 +10,17 @@ Route::group([
|
||||
Route::resource('airlines', 'AirlinesController');
|
||||
|
||||
Route::match(['get', 'post', 'put'], 'airports/fuel', 'AirportController@fuel');
|
||||
Route::resource('airports', 'AirportController');
|
||||
Route::match(['get', 'post'], 'airports/import', 'AirportController@import')->name('airports.import');
|
||||
Route::match(['get', 'post', 'put', 'delete'], 'airports/{id}/expenses', 'AirportController@expenses');
|
||||
Route::resource('airports', 'AirportController');
|
||||
|
||||
# Awards
|
||||
Route::resource('awards', 'AwardController');
|
||||
|
||||
# aircraft and fare associations
|
||||
Route::resource('aircraft', 'AircraftController');
|
||||
Route::match(['get', 'post'], 'aircraft/import', 'AircraftController@import')->name('aircraft.import');
|
||||
Route::match(['get', 'post', 'put', 'delete'], 'aircraft/{id}/expenses', 'AircraftController@expenses');
|
||||
Route::resource('aircraft', 'AircraftController');
|
||||
|
||||
# expenses
|
||||
Route::resource('expenses', 'ExpenseController');
|
||||
@@ -30,10 +32,11 @@ Route::group([
|
||||
Route::resource('finances', 'FinanceController');
|
||||
|
||||
# flights and aircraft associations
|
||||
Route::resource('flights', 'FlightController');
|
||||
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');
|
||||
Route::match(['get', 'post', 'put', 'delete'], 'flights/{id}/subfleets', 'FlightController@subfleets');
|
||||
Route::resource('flights', 'FlightController');
|
||||
|
||||
Route::resource('flightfields', 'FlightFieldController');
|
||||
|
||||
@@ -55,10 +58,11 @@ Route::group([
|
||||
Route::match(['post', 'put'], 'settings', 'SettingsController@update')->name('settings.update');
|
||||
|
||||
# subfleet
|
||||
Route::resource('subfleets', 'SubfleetController');
|
||||
Route::match(['get', 'post'], 'subfleets/import', 'SubfleetController@import')->name('subfleets.import');
|
||||
Route::match(['get', 'post', 'put', 'delete'], 'subfleets/{id}/expenses', 'SubfleetController@expenses');
|
||||
Route::match(['get', 'post', 'put', 'delete'], 'subfleets/{id}/fares', 'SubfleetController@fares');
|
||||
Route::match(['get', 'post', 'put', 'delete'], 'subfleets/{id}/ranks', 'SubfleetController@ranks');
|
||||
Route::resource('subfleets', 'SubfleetController');
|
||||
|
||||
Route::resource('users', 'UserController');
|
||||
Route::get('users/{id}/regen_apikey',
|
||||
|
||||
@@ -114,15 +114,15 @@ class FlightService extends Service
|
||||
|
||||
/**
|
||||
* Update any custom PIREP fields
|
||||
* @param Flight $flight_id
|
||||
* @param array $field_values
|
||||
* @param Flight $flight
|
||||
* @param array $field_values
|
||||
*/
|
||||
public function updateCustomFields(Flight $flight_id, array $field_values): void
|
||||
public function updateCustomFields(Flight $flight, array $field_values): void
|
||||
{
|
||||
foreach ($field_values as $fv) {
|
||||
FlightFieldValue::updateOrCreate(
|
||||
[
|
||||
'flight_id' => $flight_id,
|
||||
'flight_id' => $flight->id,
|
||||
'name' => $fv['name'],
|
||||
],
|
||||
[
|
||||
|
||||
90
app/Services/Import/AircraftImporter.php
Normal file
90
app/Services/Import/AircraftImporter.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Import;
|
||||
|
||||
use App\Interfaces\ImportExport;
|
||||
use App\Models\Aircraft;
|
||||
use App\Models\Enums\AircraftState;
|
||||
use App\Models\Enums\AircraftStatus;
|
||||
use App\Models\Subfleet;
|
||||
use App\Support\ICAO;
|
||||
|
||||
/**
|
||||
* Import aircraft
|
||||
* @package App\Services\Import
|
||||
*/
|
||||
class AircraftImporter extends ImportExport
|
||||
{
|
||||
/**
|
||||
* All of the columns that are in the CSV import
|
||||
* Should match the database fields, for the most part
|
||||
*/
|
||||
public static $columns = [
|
||||
'subfleet',
|
||||
'name',
|
||||
'registration',
|
||||
'hex_code',
|
||||
'status',
|
||||
];
|
||||
|
||||
/**
|
||||
* Find the subfleet specified, or just create it on the fly
|
||||
* @param $type
|
||||
* @return Subfleet|\Illuminate\Database\Eloquent\Model|null|object|static
|
||||
*/
|
||||
protected function getSubfleet($type)
|
||||
{
|
||||
$subfleet = Subfleet::where(['type' => $type])->first();
|
||||
if (!$subfleet) {
|
||||
$subfleet = new Subfleet([
|
||||
'type' => $type,
|
||||
'name' => $type,
|
||||
]);
|
||||
|
||||
$subfleet->save();
|
||||
}
|
||||
|
||||
return $subfleet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a flight, parse out the different rows
|
||||
* @param array $row
|
||||
* @param int $index
|
||||
* @return bool
|
||||
*/
|
||||
public function import(array $row, $index)
|
||||
{
|
||||
$subfleet = $this->getSubfleet($row['subfleet']);
|
||||
|
||||
$row['subfleet_id'] = $subfleet->id;
|
||||
|
||||
# Generate a hex code
|
||||
if(!$row['hex_code']) {
|
||||
$row['hex_code'] = ICAO::createHexCode();
|
||||
}
|
||||
|
||||
# Set a default status
|
||||
if($row['status'] === null) {
|
||||
$row['status'] = AircraftStatus::ACTIVE;
|
||||
}
|
||||
|
||||
# Just set its state right now as parked
|
||||
$row['state'] = AircraftState::PARKED;
|
||||
|
||||
# Try to add or update
|
||||
$aircraft = Aircraft::firstOrNew([
|
||||
'registration' => $row['registration'],
|
||||
], $row);
|
||||
|
||||
try {
|
||||
$aircraft->save();
|
||||
} catch(\Exception $e) {
|
||||
$this->status = 'Error in row '.$index.': '.$e->getMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->status = 'Imported '.$row['registration'].' '.$row['name'];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
55
app/Services/Import/AirportImporter.php
Normal file
55
app/Services/Import/AirportImporter.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Import;
|
||||
|
||||
use App\Interfaces\ImportExport;
|
||||
use App\Models\Airport;
|
||||
|
||||
/**
|
||||
* Import airports
|
||||
* @package App\Services\Import
|
||||
*/
|
||||
class AirportImporter extends ImportExport
|
||||
{
|
||||
/**
|
||||
* All of the columns that are in the CSV import
|
||||
* Should match the database fields, for the most part
|
||||
*/
|
||||
public static $columns = [
|
||||
'iata',
|
||||
'icao',
|
||||
'name',
|
||||
'location',
|
||||
'country',
|
||||
'timezone',
|
||||
'hub',
|
||||
'lat',
|
||||
'lon',
|
||||
];
|
||||
|
||||
/**
|
||||
* Import a flight, parse out the different rows
|
||||
* @param array $row
|
||||
* @param int $index
|
||||
* @return bool
|
||||
*/
|
||||
public function import(array $row, $index)
|
||||
{
|
||||
$row['id'] = $row['icao'];
|
||||
$row['hub'] = get_truth_state($row['hub']);
|
||||
|
||||
$airport = Airport::firstOrNew([
|
||||
'id' => $row['icao']
|
||||
], $row);
|
||||
|
||||
try {
|
||||
$airport->save();
|
||||
} catch(\Exception $e) {
|
||||
$this->status = 'Error in row '.$index.': '.$e->getMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->status = 'Imported ' . $row['icao'];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
168
app/Services/Import/FlightImporter.php
Normal file
168
app/Services/Import/FlightImporter.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Import;
|
||||
|
||||
use App\Interfaces\ImportExport;
|
||||
use App\Models\Enums\FlightType;
|
||||
use App\Models\Fare;
|
||||
use App\Models\Flight;
|
||||
use App\Models\Subfleet;
|
||||
use App\Repositories\AirlineRepository;
|
||||
use App\Services\FareService;
|
||||
use App\Services\FlightService;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* The flight importer can be imported or export. Operates on rows
|
||||
*
|
||||
* @package App\Services\Import
|
||||
*/
|
||||
class FlightImporter extends ImportExport
|
||||
{
|
||||
/**
|
||||
* All of the columns that are in the CSV import
|
||||
* Should match the database fields, for the most part
|
||||
*/
|
||||
public static $columns = [
|
||||
'airline',
|
||||
'flight_number',
|
||||
'route_code',
|
||||
'route_leg',
|
||||
'dpt_airport_id',
|
||||
'arr_airport_id',
|
||||
'alt_airport_id',
|
||||
'days',
|
||||
'dpt_time',
|
||||
'arr_time',
|
||||
'level',
|
||||
'distance',
|
||||
'flight_time',
|
||||
'flight_type',
|
||||
'route',
|
||||
'notes',
|
||||
'active',
|
||||
'subfleets',
|
||||
'fares',
|
||||
'fields',
|
||||
];
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private $airlineRepo,
|
||||
$fareSvc,
|
||||
$flightSvc;
|
||||
|
||||
/**
|
||||
* FlightImportExporter constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->airlineRepo = app(AirlineRepository::class);
|
||||
$this->fareSvc = app(FareService::class);
|
||||
$this->flightSvc = app(FlightService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a flight, parse out the different rows
|
||||
* @param array $row
|
||||
* @param int $index
|
||||
* @return bool
|
||||
*/
|
||||
public function import(array $row, $index)
|
||||
{
|
||||
// Get the airline ID from the ICAO code
|
||||
$airline = $this->getAirline($row['airline']);
|
||||
|
||||
// Try to find this flight
|
||||
$flight = Flight::firstOrNew([
|
||||
'airline_id' => $airline->id,
|
||||
'flight_number' => $row['flight_number'],
|
||||
'route_code' => $row['route_code'],
|
||||
'route_leg' => $row['route_leg'],
|
||||
], $row);
|
||||
|
||||
// Any specific transformations
|
||||
// Flight type can be set to P - Passenger, C - Cargo, or H - Charter
|
||||
$flight->setAttribute('flight_type', FlightType::getFromCode($row['flight_type']));
|
||||
$flight->setAttribute('active', get_truth_state($row['active']));
|
||||
|
||||
try {
|
||||
$flight->save();
|
||||
} catch (\Exception $e) {
|
||||
$this->status = 'Error in row '.$index.': '.$e->getMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->processSubfleets($flight, $row['subfleets']);
|
||||
$this->processFares($flight, $row['fares']);
|
||||
$this->processFields($flight, $row['fields']);
|
||||
|
||||
$this->status = 'Imported row '.$index;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse out all of the subfleets and associate them to the flight
|
||||
* The subfleet is created if it doesn't exist
|
||||
* @param Flight $flight
|
||||
* @param $col
|
||||
*/
|
||||
protected function processSubfleets(Flight &$flight, $col): void
|
||||
{
|
||||
$count = 0;
|
||||
$subfleets = $this->parseMultiColumnValues($col);
|
||||
foreach($subfleets as $subfleet_type) {
|
||||
$subfleet = Subfleet::firstOrNew(
|
||||
['type' => $subfleet_type],
|
||||
['name' => $subfleet_type]
|
||||
);
|
||||
|
||||
$subfleet->save();
|
||||
|
||||
# sync
|
||||
$flight->subfleets()->syncWithoutDetaching([$subfleet->id]);
|
||||
$count ++;
|
||||
}
|
||||
|
||||
Log::info('Subfleets added/processed: '.$count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all of the fares in the multi-format
|
||||
* @param Flight $flight
|
||||
* @param $col
|
||||
*/
|
||||
protected function processFares(Flight &$flight, $col): void
|
||||
{
|
||||
$fares = $this->parseMultiColumnValues($col);
|
||||
foreach ($fares as $fare_code => $fare_attributes) {
|
||||
if (\is_int($fare_code)) {
|
||||
$fare_code = $fare_attributes;
|
||||
$fare_attributes = [];
|
||||
}
|
||||
|
||||
$fare = Fare::firstOrNew(['code' => $fare_code], ['name' => $fare_code]);
|
||||
$this->fareSvc->setForFlight($flight, $fare, $fare_attributes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all of the subfields
|
||||
* @param Flight $flight
|
||||
* @param $col
|
||||
*/
|
||||
protected function processFields(Flight &$flight, $col): void
|
||||
{
|
||||
$pass_fields = [];
|
||||
$fields = $this->parseMultiColumnValues($col);
|
||||
foreach($fields as $field_name => $field_value) {
|
||||
$pass_fields[] = [
|
||||
'name' => $field_name,
|
||||
'value' => $field_value,
|
||||
];
|
||||
}
|
||||
|
||||
$this->flightSvc->updateCustomFields($flight, $pass_fields);
|
||||
}
|
||||
}
|
||||
54
app/Services/Import/SubfleetImporter.php
Normal file
54
app/Services/Import/SubfleetImporter.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Import;
|
||||
|
||||
use App\Interfaces\ImportExport;
|
||||
use App\Models\Subfleet;
|
||||
|
||||
/**
|
||||
* Import subfleets
|
||||
* @package App\Services\Import
|
||||
*/
|
||||
class SubfleetImporter extends ImportExport
|
||||
{
|
||||
/**
|
||||
* All of the columns that are in the CSV import
|
||||
* Should match the database fields, for the most part
|
||||
*/
|
||||
public static $columns = [
|
||||
'airline',
|
||||
'type',
|
||||
'name',
|
||||
];
|
||||
|
||||
/**
|
||||
* Import a flight, parse out the different rows
|
||||
* @param array $row
|
||||
* @param int $index
|
||||
* @return bool
|
||||
*/
|
||||
public function import(array $row, $index)
|
||||
{
|
||||
$airline = $this->getAirline($row['airline']);
|
||||
if(!$airline) {
|
||||
$this->status = 'Airline '.$row['airline'].' not found, row: '.$index;
|
||||
return false;
|
||||
}
|
||||
|
||||
$row['airline_id'] = $airline->id;
|
||||
|
||||
$subfleet = Subfleet::firstOrNew([
|
||||
'type' => $row['type']
|
||||
], $row);
|
||||
|
||||
try {
|
||||
$subfleet->save();
|
||||
} catch(\Exception $e) {
|
||||
$this->status = 'Error in row '.$index.': '.$e->getMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->status = 'Imported ' . $row['type'];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,15 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Interfaces\ImportExport;
|
||||
use App\Interfaces\Service;
|
||||
use App\Models\Airport;
|
||||
use App\Repositories\FlightRepository;
|
||||
use App\Services\Import\AircraftImporter;
|
||||
use App\Services\Import\AirportImporter;
|
||||
use App\Services\Import\FlightImporter;
|
||||
use App\Services\Import\SubfleetImporter;
|
||||
use League\Csv\Reader;
|
||||
|
||||
/**
|
||||
* Class ImporterService
|
||||
@@ -24,75 +31,140 @@ class ImporterService extends Service
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a key-value pair to an array
|
||||
* @param $kvp_str
|
||||
* @param array $arr
|
||||
* @param $csv_file
|
||||
* @return Reader
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
protected function setKvp($kvp_str, array &$arr)
|
||||
public function openCsv($csv_file)
|
||||
{
|
||||
$item = explode('=', $kvp_str);
|
||||
if (\count($item) === 1) { # just a list?
|
||||
$arr[] = trim($item[0]);
|
||||
} else { # actually a key-value pair
|
||||
$k = trim($item[0]);
|
||||
$v = trim($item[1]);
|
||||
$arr[$k] = $v;
|
||||
}
|
||||
$reader = Reader::createFromPath($csv_file);
|
||||
$reader->setDelimiter(',');
|
||||
$reader->setEnclosure('"');
|
||||
|
||||
return $reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a multi column values field. E.g:
|
||||
* Y?price=200&cost=100; F?price=1200
|
||||
* or
|
||||
* gate=B32;cost index=100
|
||||
*
|
||||
* Converted into a multi-dimensional array
|
||||
*
|
||||
* @param $field
|
||||
* @return array|string
|
||||
* Run the actual importer
|
||||
* @param Reader $reader
|
||||
* @param ImportExport $importer
|
||||
* @return array
|
||||
*/
|
||||
public function parseMultiColumnValues($field)
|
||||
protected function runImport(Reader $reader, ImportExport $importer): array
|
||||
{
|
||||
$ret = [];
|
||||
$split_values = explode(';', $field);
|
||||
$import_report = [
|
||||
'success' => [],
|
||||
'failed' => [],
|
||||
];
|
||||
|
||||
# No multiple values in here, just a straight value
|
||||
if (\count($split_values) === 1) {
|
||||
return $split_values[0];
|
||||
}
|
||||
$cols = $importer->getColumns();
|
||||
$first_header = $cols[0];
|
||||
|
||||
foreach ($split_values as $value) {
|
||||
# This isn't in the query string format, so it's
|
||||
# just a straight key-value pair set
|
||||
if (strpos($value, '?') === false) {
|
||||
$this->setKvp($value, $ret);
|
||||
$records = $reader->getRecords($cols);
|
||||
foreach ($records as $offset => $row) {
|
||||
// check if the first row being read is the header
|
||||
if ($row[$first_header] === $first_header) {
|
||||
continue;
|
||||
}
|
||||
|
||||
# This contains the query string, which turns it
|
||||
# into the multi-level array
|
||||
|
||||
$query_str = explode('?', $value);
|
||||
$parent = trim($query_str[0]);
|
||||
|
||||
$children = [];
|
||||
$kvp = explode('&', trim($query_str[1]));
|
||||
foreach ($kvp as $items) {
|
||||
$this->setKvp($items, $children);
|
||||
$success = $importer->import($row, $offset);
|
||||
if ($success) {
|
||||
$import_report['success'][] = $importer->status;
|
||||
} else {
|
||||
$import_report['failed'][] = $importer->status;
|
||||
}
|
||||
|
||||
$ret[$parent] = $children;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
return $import_report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import aircraft
|
||||
* @param string $csv_file
|
||||
* @param bool $delete_previous
|
||||
* @return mixed
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function importAircraft($csv_file, bool $delete_previous = true)
|
||||
{
|
||||
if ($delete_previous) {
|
||||
# TODO: delete airports
|
||||
}
|
||||
|
||||
$reader = $this->openCsv($csv_file);
|
||||
if (!$reader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$importer = new AircraftImporter();
|
||||
return $this->runImport($reader, $importer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import airports
|
||||
* @param string $csv_file
|
||||
* @param bool $delete_previous
|
||||
* @return mixed
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function importAirports($csv_file, bool $delete_previous = true)
|
||||
{
|
||||
if ($delete_previous) {
|
||||
Airport::truncate();
|
||||
}
|
||||
|
||||
$reader = $this->openCsv($csv_file);
|
||||
if (!$reader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$importer = new AirportImporter();
|
||||
return $this->runImport($reader, $importer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import flights
|
||||
* @param $csv_str
|
||||
* @param bool $delete_previous
|
||||
* @param string $csv_file
|
||||
* @param bool $delete_previous
|
||||
* @return mixed
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function importFlights($csv_str, bool $delete_previous = true)
|
||||
public function importFlights($csv_file, bool $delete_previous = true)
|
||||
{
|
||||
if ($delete_previous) {
|
||||
# TODO: Delete all from: flights, flight_field_values
|
||||
}
|
||||
|
||||
$reader = $this->openCsv($csv_file);
|
||||
if (!$reader) {
|
||||
# TODO: Throw an error
|
||||
return false;
|
||||
}
|
||||
|
||||
$importer = new FlightImporter();
|
||||
return $this->runImport($reader, $importer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import subfleets
|
||||
* @param string $csv_file
|
||||
* @param bool $delete_previous
|
||||
* @return mixed
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function importSubfleets($csv_file, bool $delete_previous = true)
|
||||
{
|
||||
if ($delete_previous) {
|
||||
# TODO: Cleanup subfleet data
|
||||
}
|
||||
|
||||
$reader = $this->openCsv($csv_file);
|
||||
if (!$reader) {
|
||||
# TODO: Throw an error
|
||||
return false;
|
||||
}
|
||||
|
||||
$importer = new SubfleetImporter();
|
||||
return $this->runImport($reader, $importer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
"markrogoyski/math-php": "^0.38.0",
|
||||
"akaunting/money": "^1.0",
|
||||
"igaster/laravel-theme": "^2.0",
|
||||
"anhskohbo/no-captcha": "^3.0"
|
||||
"anhskohbo/no-captcha": "^3.0",
|
||||
"league/csv": "^9.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~7.0",
|
||||
|
||||
189
composer.lock
generated
189
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "55cf432213722ec0f7ad7f80a4edc648",
|
||||
"content-hash": "833c46d2dbb420462272d9a86fa28ff9",
|
||||
"packages": [
|
||||
{
|
||||
"name": "akaunting/money",
|
||||
@@ -168,7 +168,7 @@
|
||||
"Arrilot\\Widgets\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -223,7 +223,7 @@
|
||||
"Cache\\Adapter\\Common\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -291,7 +291,7 @@
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -353,7 +353,7 @@
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -408,7 +408,7 @@
|
||||
"Cache\\TagInterop\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -527,7 +527,7 @@
|
||||
"Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -643,7 +643,7 @@
|
||||
"Cron\\": "src/Cron/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -703,7 +703,7 @@
|
||||
"Egulias\\EmailValidator\\": "EmailValidator"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -795,7 +795,7 @@
|
||||
"Firebase\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
@@ -863,7 +863,7 @@
|
||||
"src/Google/Service/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
@@ -945,7 +945,7 @@
|
||||
"Google\\Auth\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
@@ -999,7 +999,7 @@
|
||||
"GuzzleHttp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1057,7 +1057,7 @@
|
||||
"src/functions_include.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1112,7 +1112,7 @@
|
||||
"src/functions_include.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1174,7 +1174,7 @@
|
||||
"Hashids\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1309,7 +1309,7 @@
|
||||
"Irazasyed\\LaravelGAMP\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1356,7 +1356,7 @@
|
||||
"Jackiedo\\Timezonelist\\": "src/Jackiedo/Timezonelist"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1409,7 +1409,7 @@
|
||||
"stubs/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1460,7 +1460,7 @@
|
||||
"Joshbrw\\LaravelModuleInstaller\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1493,7 +1493,7 @@
|
||||
"Traitor\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1552,7 +1552,7 @@
|
||||
"src/Laracasts/Flash/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1753,7 +1753,7 @@
|
||||
"src/helpers.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -1771,6 +1771,73 @@
|
||||
"homepage": "https://laravelcollective.com",
|
||||
"time": "2018-02-12T14:19:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/csv",
|
||||
"version": "9.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/csv.git",
|
||||
"reference": "0d0b12f1a0093a6c39014a5d118f6ba4274539ee"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/csv/zipball/0d0b12f1a0093a6c39014a5d118f6ba4274539ee",
|
||||
"reference": "0d0b12f1a0093a6c39014a5d118f6ba4274539ee",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=7.0.10"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"friendsofphp/php-cs-fixer": "^2.0",
|
||||
"phpstan/phpstan": "^0.9.2",
|
||||
"phpstan/phpstan-phpunit": "^0.9.4",
|
||||
"phpstan/phpstan-strict-rules": "^0.9.0",
|
||||
"phpunit/phpunit": "^6.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-iconv": "Needed to ease transcoding CSV using iconv stream filters"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "9.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Csv\\": "src"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ignace Nyamagana Butera",
|
||||
"email": "nyamsprod@gmail.com",
|
||||
"homepage": "https://github.com/nyamsprod/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Csv data manipulation made easy in PHP",
|
||||
"homepage": "http://csv.thephpleague.com",
|
||||
"keywords": [
|
||||
"csv",
|
||||
"export",
|
||||
"filter",
|
||||
"import",
|
||||
"read",
|
||||
"write"
|
||||
],
|
||||
"time": "2018-03-12T07:20:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem",
|
||||
"version": "1.0.43",
|
||||
@@ -1961,7 +2028,7 @@
|
||||
"League\\ISO3166\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -2154,7 +2221,7 @@
|
||||
"VaCentral\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -2311,7 +2378,7 @@
|
||||
"src/helpers.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -2420,7 +2487,7 @@
|
||||
"Http\\Discovery\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -2473,7 +2540,7 @@
|
||||
"PhpUnitsOfMeasure\\": "source/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -2532,7 +2599,7 @@
|
||||
"phpseclib\\": "phpseclib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -2688,7 +2755,7 @@
|
||||
"PragmaRX\\Yaml\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -2749,7 +2816,7 @@
|
||||
"Prettus\\Repository\\": "src/Prettus/Repository/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -2838,7 +2905,7 @@
|
||||
"Psr\\Cache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -3102,7 +3169,7 @@
|
||||
"Ramsey\\Uuid\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -3385,7 +3452,7 @@
|
||||
"Spatie\\Pjax\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -4036,7 +4103,7 @@
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -4092,7 +4159,7 @@
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -4611,7 +4678,7 @@
|
||||
"TheIconic\\Tracking\\GoogleAnalytics\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -4656,7 +4723,7 @@
|
||||
"TijsVerkoyen\\CssToInlineStyles\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
@@ -4697,7 +4764,7 @@
|
||||
"Tivie\\OS\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"APACHE 2.0"
|
||||
],
|
||||
@@ -4815,7 +4882,7 @@
|
||||
"src/vierbergenlars/SemVer/internal.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -4920,7 +4987,7 @@
|
||||
"Webpatser\\Uuid": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -4976,7 +5043,7 @@
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -5047,7 +5114,7 @@
|
||||
"Barryvdh\\LaravelIdeHelper\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -5204,7 +5271,7 @@
|
||||
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -5274,7 +5341,7 @@
|
||||
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -5331,7 +5398,7 @@
|
||||
"Whoops\\": "src/Whoops/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -5479,7 +5546,7 @@
|
||||
"JakubOnderka\\PhpConsoleColor": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-2-Clause"
|
||||
],
|
||||
@@ -5523,7 +5590,7 @@
|
||||
"JakubOnderka\\PhpConsoleHighlighter": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -5632,7 +5699,7 @@
|
||||
"src/DeepCopy/deep_copy.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -5683,7 +5750,7 @@
|
||||
"NunoMaduro\\Collision\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -5902,7 +5969,7 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -5998,7 +6065,7 @@
|
||||
"Prophecy\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -6068,7 +6135,7 @@
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
@@ -6116,7 +6183,7 @@
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
@@ -6207,7 +6274,7 @@
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
@@ -6257,7 +6324,7 @@
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
@@ -6391,7 +6458,7 @@
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
@@ -6488,7 +6555,7 @@
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
@@ -6551,7 +6618,7 @@
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
@@ -7101,7 +7168,7 @@
|
||||
"Webmozart\\Assert\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
@@ -7155,7 +7222,7 @@
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"notification-url": "http://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache2"
|
||||
],
|
||||
|
||||
@@ -1,46 +1,8 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default filesystem disk that should be used
|
||||
| by the framework. A "local" driver, as well as a variety of cloud
|
||||
| based drivers are available for your choosing. Just store away!
|
||||
|
|
||||
| Supported: "local", "ftp", "s3", "rackspace"
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => 'local',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cloud Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Many applications store files both locally and in the cloud. For this
|
||||
| reason, you may specify a default "cloud" driver here. This driver
|
||||
| will be bound as the Cloud disk implementation in the container.
|
||||
|
|
||||
*/
|
||||
|
||||
'cloud' => 's3',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Filesystem Disks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure as many filesystem "disks" as you wish, and you
|
||||
| may even configure multiple disks of the same driver. Defaults have
|
||||
| been setup for each driver as an example of the required options.
|
||||
|
|
||||
*/
|
||||
|
||||
'disks' => [
|
||||
|
||||
'local' => [
|
||||
@@ -50,7 +12,7 @@ return [
|
||||
|
||||
'public' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/public'),
|
||||
'root' => app_path('public/assets/upload'),
|
||||
'visibility' => 'public',
|
||||
],
|
||||
|
||||
@@ -61,7 +23,5 @@ return [
|
||||
'region' => 'your-region',
|
||||
'bucket' => 'your-bucket',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
5
resources/views/admin/aircraft/import.blade.php
Normal file
5
resources/views/admin/aircraft/import.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
@extends('admin.app')
|
||||
@section('title', 'Import Aircraft')
|
||||
@section('content')
|
||||
@include('admin.shared.import', ['route' => 'admin.aircraft.import'])
|
||||
@endsection
|
||||
@@ -1,17 +1,10 @@
|
||||
@extends('admin.app')
|
||||
|
||||
@section('title', 'Aircraft')
|
||||
|
||||
@section('actions')
|
||||
<li>
|
||||
<a href="{{ url('/admin/subfleets') }}">
|
||||
<i class="ti-files"></i>
|
||||
Subfleets</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route('admin.aircraft.create') }}">
|
||||
<i class="ti-plus"></i>
|
||||
New Aircraft</a>
|
||||
</li>
|
||||
<li><a href="{{ route('admin.aircraft.import') }}"><i class="ti-plus"></i>Import from CSV</a></li>
|
||||
<li><a href="{{ url('/admin/subfleets') }}"><i class="ti-files"></i>Subfleets</a></li>
|
||||
<li><a href="{{ route('admin.aircraft.create') }}"><i class="ti-plus"></i>New Aircraft</a></li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
|
||||
5
resources/views/admin/airports/import.blade.php
Normal file
5
resources/views/admin/airports/import.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
@extends('admin.app')
|
||||
@section('title', 'Import Airports')
|
||||
@section('content')
|
||||
@include('admin.shared.import', ['route' => 'admin.airports.import'])
|
||||
@endsection
|
||||
@@ -1,12 +1,9 @@
|
||||
@extends('admin.app')
|
||||
|
||||
@section('title', 'Airports')
|
||||
|
||||
@section('actions')
|
||||
<li>
|
||||
<a href="{{ route('admin.airports.create') }}">
|
||||
<i class="ti-plus"></i>
|
||||
Add New</a>
|
||||
</li>
|
||||
<li><a href="{{ route('admin.airports.import') }}"><i class="ti-plus"></i>Import from CSV</a></li>
|
||||
<li><a href="{{ route('admin.airports.create') }}"><i class="ti-plus"></i>Add New</a></li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
|
||||
5
resources/views/admin/flights/import.blade.php
Normal file
5
resources/views/admin/flights/import.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
@extends('admin.app')
|
||||
@section('title', 'Import Flights')
|
||||
@section('content')
|
||||
@include('admin.shared.import', ['route' => 'admin.flights.import'])
|
||||
@endsection
|
||||
@@ -1,7 +1,8 @@
|
||||
@extends('admin.app')
|
||||
|
||||
@section('title', 'Flights')
|
||||
|
||||
@section('actions')
|
||||
<li><a href="{{ route('admin.flights.import') }}"><i class="ti-plus"></i>Import from CSV</a></li>
|
||||
<li><a href="{{ route('admin.flightfields.index') }}"><i class="ti-plus"></i>Fields</a></li>
|
||||
<li>
|
||||
<a href="{{ route('admin.flights.create') }}">
|
||||
|
||||
32
resources/views/admin/shared/import.blade.php
Normal file
32
resources/views/admin/shared/import.blade.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<div class="card border-blue-bottom">
|
||||
<div class="content">
|
||||
{{ Form::open(['method' => 'post', 'route' => $route, 'files' => true]) }}
|
||||
|
||||
<div class="row">
|
||||
<div class="form-group col-12">
|
||||
{{ Form::label('csv_file', 'Chose a CSV file to import') }}
|
||||
{{ Form::file('csv_file', ['accept' => '.csv']) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<div class="text-right">
|
||||
{{ Form::button('Start Import', ['type' => 'submit', 'class' => 'btn btn-success']) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ Form::close() }}
|
||||
|
||||
<div class="form-group col-md-12">
|
||||
<h4>Logs</h4>
|
||||
@foreach($logs['success'] as $line)
|
||||
<p>{{ $line }}</p>
|
||||
@endforeach
|
||||
|
||||
<h4>Errors</h4>
|
||||
@foreach($logs['failed'] as $line)
|
||||
<p>{{ $line }}</p>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
5
resources/views/admin/subfleets/import.blade.php
Normal file
5
resources/views/admin/subfleets/import.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
@extends('admin.app')
|
||||
@section('title', 'Import Subfleets')
|
||||
@section('content')
|
||||
@include('admin.shared.import', ['route' => 'admin.subfleets.import'])
|
||||
@endsection
|
||||
@@ -2,6 +2,8 @@
|
||||
@section('title', 'Subfleets')
|
||||
|
||||
@section('actions')
|
||||
<li><a href="{{ route('admin.subfleets.import') }}"><i class="ti-plus"></i>Import from CSV</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route('admin.subfleets.create') }}">
|
||||
<i class="ti-plus"></i>Add New</a>
|
||||
|
||||
1
storage/app/.gitignore
vendored
1
storage/app/.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
*
|
||||
!import/
|
||||
!public/
|
||||
!.gitignore
|
||||
.xml
|
||||
|
||||
2
storage/app/import/.gitignore
vendored
Executable file
2
storage/app/import/.gitignore
vendored
Executable file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
@@ -1,16 +1,50 @@
|
||||
<?php
|
||||
|
||||
use App\Services\FareService;
|
||||
use App\Models\Enums\FlightType;
|
||||
|
||||
/**
|
||||
* Class ImporterTest
|
||||
*/
|
||||
class ImporterTest extends TestCase
|
||||
{
|
||||
protected $importerSvc;
|
||||
private $importBaseClass,
|
||||
$importSvc,
|
||||
$fareSvc;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->importerSvc = app(\App\Services\ImporterService::class);
|
||||
parent::setUp();
|
||||
$this->importBaseClass = new \App\Interfaces\ImportExport();
|
||||
$this->importSvc = app(\App\Services\ImporterService::class);
|
||||
$this->fareSvc = app(\App\Services\FareService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some of the basic data needed to properly import the flights.csv file
|
||||
* @return mixed
|
||||
*/
|
||||
protected function insertFlightsScaffoldData()
|
||||
{
|
||||
$fare_svc = app(FareService::class);
|
||||
|
||||
$al = [
|
||||
'icao' => 'VMS',
|
||||
'name' => 'phpVMS Airlines',
|
||||
];
|
||||
|
||||
$airline = factory(App\Models\Airline::class)->create($al);
|
||||
$subfleet = factory(App\Models\Subfleet::class)->create(['type' => 'A32X']);
|
||||
|
||||
# Add the economy class
|
||||
$fare_economy = factory(App\Models\Fare::class)->create(['code' => 'Y', 'capacity' => 150]);
|
||||
$fare_svc->setForSubfleet($subfleet, $fare_economy);
|
||||
|
||||
# Add first class
|
||||
$fare_first = factory(App\Models\Fare::class)->create(['code' => 'F', 'capacity' => 10]);
|
||||
$fare_svc->setForSubfleet($subfleet, $fare_first);
|
||||
|
||||
return $airline;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -22,7 +56,7 @@ class ImporterTest extends TestCase
|
||||
$tests = [
|
||||
[
|
||||
'input' => 'gate',
|
||||
'expected' => 'gate'
|
||||
'expected' => ['gate']
|
||||
],
|
||||
[
|
||||
'input' => 'gate;cost index',
|
||||
@@ -61,12 +95,155 @@ class ImporterTest extends TestCase
|
||||
'price' => 1200
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'input' => 'Y; F?price=1200',
|
||||
'expected' => [
|
||||
0 => 'Y',
|
||||
'F' => [
|
||||
'price' => 1200
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'input' => 'Departure Gate=4;Arrival Gate=C61',
|
||||
'expected' => [
|
||||
'Departure Gate' => '4',
|
||||
'Arrival Gate' => 'C61',
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
foreach($tests as $test) {
|
||||
$parsed = $this->importerSvc->parseMultiColumnValues($test['input']);
|
||||
$parsed = $this->importBaseClass->parseMultiColumnValues($test['input']);
|
||||
$this->assertEquals($parsed, $test['expected']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the flight importer
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function testFlightImporter(): void
|
||||
{
|
||||
$airline = $this->insertFlightsScaffoldData();
|
||||
|
||||
$file_path = base_path('tests/data/flights.csv');
|
||||
$this->importSvc->importFlights($file_path);
|
||||
|
||||
// See if it imported
|
||||
$flight = \App\Models\Flight::where([
|
||||
'airline_id' => $airline->id,
|
||||
'flight_number' => '1972'
|
||||
])->first();
|
||||
|
||||
$this->assertNotNull($flight);
|
||||
|
||||
// Check the flight itself
|
||||
$this->assertEquals('KAUS', $flight->dpt_airport_id);
|
||||
$this->assertEquals('KJFK', $flight->arr_airport_id);
|
||||
$this->assertEquals('0810 CST', $flight->dpt_time);
|
||||
$this->assertEquals('1235 EST', $flight->arr_time);
|
||||
$this->assertEquals('350', $flight->level);
|
||||
$this->assertEquals('1477', $flight->distance);
|
||||
$this->assertEquals('207', $flight->flight_time);
|
||||
$this->assertEquals(FlightType::PASSENGER, $flight->flight_type);
|
||||
$this->assertEquals('ILEXY2 ZENZI LFK ELD J29 MEM Q29 JHW J70 STENT J70 MAGIO J70 LVZ LENDY6', $flight->route);
|
||||
$this->assertEquals('Just a flight', $flight->notes);
|
||||
$this->assertEquals(true, $flight->active);
|
||||
|
||||
// Check the custom fields entered
|
||||
$fields = \App\Models\FlightFieldValue::where([
|
||||
'flight_id' => $flight->id,
|
||||
])->get();
|
||||
|
||||
$this->assertCount(2, $fields);
|
||||
$dep_gate = $fields->where('name', 'Departure Gate')->first();
|
||||
$this->assertEquals('4', $dep_gate['value']);
|
||||
|
||||
$dep_gate = $fields->where('name', 'Arrival Gate')->first();
|
||||
$this->assertEquals('C41', $dep_gate['value']);
|
||||
|
||||
// Check the fare class
|
||||
$fares = $this->fareSvc->getForFlight($flight);
|
||||
$this->assertCount(2, $fares);
|
||||
|
||||
$first = $fares->where('code', 'Y')->first();
|
||||
$this->assertEquals(300, $first->price);
|
||||
$this->assertEquals(100, $first->cost);
|
||||
$this->assertEquals(130, $first->capacity);
|
||||
|
||||
$first = $fares->where('code', 'F')->first();
|
||||
$this->assertEquals(600, $first->price);
|
||||
$this->assertEquals(400, $first->cost);
|
||||
$this->assertEquals(10, $first->capacity);
|
||||
|
||||
// Check the subfleets
|
||||
$subfleets = $flight->subfleets;
|
||||
$this->assertCount(1, $subfleets);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function testAircraftImporter()
|
||||
{
|
||||
$subfleet = factory(App\Models\Subfleet::class)->create(['type' => 'A32X']);
|
||||
|
||||
$file_path = base_path('tests/data/aircraft.csv');
|
||||
$this->importSvc->importAircraft($file_path);
|
||||
|
||||
// See if it imported
|
||||
$aircraft = \App\Models\Aircraft::where([
|
||||
'registration' => 'N309US',
|
||||
])->first();
|
||||
|
||||
$this->assertNotNull($aircraft);
|
||||
$this->assertEquals($subfleet->id, $aircraft->id);
|
||||
$this->assertEquals('A320-211', $aircraft->name);
|
||||
$this->assertEquals('N309US', $aircraft->registration);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function testAirportImporter()
|
||||
{
|
||||
$file_path = base_path('tests/data/airports.csv');
|
||||
$this->importSvc->importAirports($file_path);
|
||||
|
||||
// See if it imported
|
||||
$airport = \App\Models\Airport::where([
|
||||
'id' => 'KAUS',
|
||||
])->first();
|
||||
|
||||
$this->assertNotNull($airport);
|
||||
$this->assertEquals('KAUS', $airport->id);
|
||||
$this->assertEquals('AUS', $airport->iata);
|
||||
$this->assertEquals('KAUS', $airport->icao);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test importing the subfleets
|
||||
* @throws \League\Csv\Exception
|
||||
*/
|
||||
public function testSubfleetImporter(): void
|
||||
{
|
||||
$airline = factory(App\Models\Airline::class)->create(['icao' => 'VMS']);
|
||||
|
||||
$file_path = base_path('tests/data/subfleets.csv');
|
||||
$this->importSvc->importSubfleets($file_path);
|
||||
|
||||
// See if it imported
|
||||
$subfleet = \App\Models\Subfleet::where([
|
||||
'type' => 'A32X',
|
||||
])->first();
|
||||
|
||||
$this->assertNotNull($subfleet);
|
||||
$this->assertEquals($airline->id, $subfleet->id);
|
||||
$this->assertEquals('A32X', $subfleet->type);
|
||||
$this->assertEquals('Airbus A320', $subfleet->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,24 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* So we can test private/protected methods
|
||||
* http://bit.ly/1mr5hMq
|
||||
* @param $object
|
||||
* @param $methodName
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function invokeMethod(&$object, $methodName, array $parameters = [])
|
||||
{
|
||||
$reflection = new \ReflectionClass(get_class($object));
|
||||
$method = $reflection->getMethod($methodName);
|
||||
$method->setAccessible(true);
|
||||
|
||||
return $method->invokeArgs($object, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the GET call to inject the user API key
|
||||
* @param string $uri
|
||||
|
||||
2
tests/data/aircraft.csv
Normal file
2
tests/data/aircraft.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
subfleet,name,registration,hex_code,status
|
||||
A32X,A320-211,N309US,,
|
||||
|
2
tests/data/airports.csv
Normal file
2
tests/data/airports.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
iata,icao,name,location,country,timezone,hub,lat,lon
|
||||
AUS,KAUS,Austin-Bergstrom,"Austin, Texas, USA", United States,America/Chicago,1,30.1945,-97.6699
|
||||
|
2
tests/data/flights.csv
Normal file
2
tests/data/flights.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
airline,flight_number,route_code,route_leg,dpt_airport,arr_airport,alt_airport,days,dpt_time,arr_time,level,distance,flight_time,flight_type,route,notes,active,subfleets,fares,fields
|
||||
VMS,1972,,,KAUS,KJFK,KLGA,,0810 CST,1235 EST,350,1477,207,P,ILEXY2 ZENZI LFK ELD J29 MEM Q29 JHW J70 STENT J70 MAGIO J70 LVZ LENDY6,"Just a flight",1,A32X,Y?price=300&cost=100&capacity=130;F?price=600&cost=400,Departure Gate=4;Arrival Gate=C41
|
||||
|
2
tests/data/subfleets.csv
Normal file
2
tests/data/subfleets.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
airline,type,name
|
||||
VMS,A32X,Airbus A320
|
||||
|
Reference in New Issue
Block a user