diff --git a/app/Services/ExportService.php b/app/Services/ExportService.php index bfe5d9bc..10c6e35f 100644 --- a/app/Services/ExportService.php +++ b/app/Services/ExportService.php @@ -53,7 +53,7 @@ class ExportService extends Service $writer = $this->openCsv($path); // Write out the header first - $writer->insertOne($exporter->getColumns()); + $writer->insertOne(array_keys($exporter->getColumns())); // Write the rest of the rows foreach ($collection as $row) { diff --git a/app/Services/ImportExport/AircraftExporter.php b/app/Services/ImportExport/AircraftExporter.php index a7ba16a2..f0eddad3 100644 --- a/app/Services/ImportExport/AircraftExporter.php +++ b/app/Services/ImportExport/AircraftExporter.php @@ -21,7 +21,7 @@ class AircraftExporter extends ImportExport */ public function __construct() { - self::$columns = AircraftImporter::$columns; + self::$columns = array_keys(AircraftImporter::$columns); } /** diff --git a/app/Services/ImportExport/AircraftImporter.php b/app/Services/ImportExport/AircraftImporter.php index 1b5bc837..7f1d3e74 100644 --- a/app/Services/ImportExport/AircraftImporter.php +++ b/app/Services/ImportExport/AircraftImporter.php @@ -22,11 +22,11 @@ class AircraftImporter extends ImportExport * Should match the database fields, for the most part */ public static $columns = [ - 'subfleet', - 'name', - 'registration', - 'hex_code', - 'status', + 'subfleet' => 'required', + 'name' => 'required', + 'registration' => 'required', + 'hex_code' => 'nullable', + 'status' => 'nullable', ]; /** diff --git a/app/Services/ImportExport/AirportExporter.php b/app/Services/ImportExport/AirportExporter.php index 527d7d3d..16c185e7 100644 --- a/app/Services/ImportExport/AirportExporter.php +++ b/app/Services/ImportExport/AirportExporter.php @@ -19,7 +19,7 @@ class AirportExporter extends ImportExport */ public function __construct() { - self::$columns = AirportImporter::$columns; + self::$columns = array_keys(AirportImporter::$columns); } /** diff --git a/app/Services/ImportExport/AirportImporter.php b/app/Services/ImportExport/AirportImporter.php index 605e9707..d0ad25a4 100644 --- a/app/Services/ImportExport/AirportImporter.php +++ b/app/Services/ImportExport/AirportImporter.php @@ -18,15 +18,15 @@ class AirportImporter extends ImportExport * Should match the database fields, for the most part */ public static $columns = [ - 'icao', - 'iata', - 'name', - 'location', - 'country', - 'timezone', - 'hub', - 'lat', - 'lon', + 'icao' => 'required', + 'iata' => 'required', + 'name' => 'required', + 'location' => 'nullable', + 'country' => 'nullable', + 'timezone' => 'nullable', + 'hub' => 'nullable|boolean', + 'lat' => 'required|numeric', + 'lon' => 'required|numeric', ]; /** diff --git a/app/Services/ImportExport/ExpenseExporter.php b/app/Services/ImportExport/ExpenseExporter.php index b25ae4f9..44dde720 100644 --- a/app/Services/ImportExport/ExpenseExporter.php +++ b/app/Services/ImportExport/ExpenseExporter.php @@ -22,7 +22,7 @@ class ExpenseExporter extends ImportExport */ public function __construct() { - self::$columns = ExpenseImporter::$columns; + self::$columns = array_keys(ExpenseImporter::$columns); } /** diff --git a/app/Services/ImportExport/ExpenseImporter.php b/app/Services/ImportExport/ExpenseImporter.php index 2bf17eab..f483c589 100644 --- a/app/Services/ImportExport/ExpenseImporter.php +++ b/app/Services/ImportExport/ExpenseImporter.php @@ -23,15 +23,15 @@ class ExpenseImporter extends ImportExport * Should match the database fields, for the most part */ public static $columns = [ - 'airline', - 'name', - 'amount', - 'type', - 'charge_to_user', - 'multiplier', - 'active', - 'ref_class', - 'ref_class_id', + 'airline' => 'nullable', + 'name' => 'required', + 'amount' => 'required|numeric', + 'type' => 'required', + 'charge_to_user' => 'nullable|boolean', + 'multiplier' => 'nullable|numeric', + 'active' => 'nullable|boolean', + 'ref_class' => 'nullable', + 'ref_class_id' => 'nullable', ]; /** diff --git a/app/Services/ImportExport/FareExporter.php b/app/Services/ImportExport/FareExporter.php index b3bef9f9..903c459d 100644 --- a/app/Services/ImportExport/FareExporter.php +++ b/app/Services/ImportExport/FareExporter.php @@ -19,7 +19,7 @@ class FareExporter extends ImportExport */ public function __construct() { - self::$columns = FareImporter::$columns; + self::$columns = array_keys(FareImporter::$columns); } /** diff --git a/app/Services/ImportExport/FareImporter.php b/app/Services/ImportExport/FareImporter.php index d57767c6..843a58b5 100644 --- a/app/Services/ImportExport/FareImporter.php +++ b/app/Services/ImportExport/FareImporter.php @@ -18,13 +18,13 @@ class FareImporter extends ImportExport * Should match the database fields, for the most part */ public static $columns = [ - 'code', - 'name', - 'price', - 'cost', - 'capacity', - 'notes', - 'active', + 'code' => 'required', + 'name' => 'required', + 'price' => 'nullable|numeric', + 'cost' => 'nullable|numeric', + 'capacity' => 'required|integer', + 'notes' => 'nullable', + 'active' => 'nullable|boolean', ]; /** diff --git a/app/Services/ImportExport/FlightExporter.php b/app/Services/ImportExport/FlightExporter.php index 55bce02f..68f2aac7 100644 --- a/app/Services/ImportExport/FlightExporter.php +++ b/app/Services/ImportExport/FlightExporter.php @@ -21,7 +21,7 @@ class FlightExporter extends ImportExport */ public function __construct() { - self::$columns = FlightImporter::$columns; + self::$columns = array_keys(FlightImporter::$columns); } /** diff --git a/app/Services/ImportExport/FlightImporter.php b/app/Services/ImportExport/FlightImporter.php index f5c26562..d3f2e882 100644 --- a/app/Services/ImportExport/FlightImporter.php +++ b/app/Services/ImportExport/FlightImporter.php @@ -27,26 +27,26 @@ class FlightImporter extends ImportExport * Should match the database fields, for the most part */ public static $columns = [ - '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', + 'airline' => 'required', + 'flight_number' => 'required', + 'route_code' => 'nullable', + 'route_leg' => 'nullable', + 'dpt_airport' => 'required', + 'arr_airport' => 'required', + 'alt_airport' => 'nullable', + 'days' => 'nullable', + 'dpt_time' => 'nullable', + 'arr_time' => 'nullable', + 'level' => 'nullable|integer', + 'distance' => 'required|numeric', + 'flight_time' => 'required|integer', + 'flight_type' => 'required|alpha', + 'route' => 'nullable', + 'notes' => 'nullable', + 'active' => 'nullable|boolean', + 'subfleets' => 'nullable', + 'fares' => 'nullable', + 'fields' => 'nullable', ]; /** diff --git a/app/Services/ImportExport/SubfleetExporter.php b/app/Services/ImportExport/SubfleetExporter.php index 6b9725c8..70562667 100644 --- a/app/Services/ImportExport/SubfleetExporter.php +++ b/app/Services/ImportExport/SubfleetExporter.php @@ -21,7 +21,7 @@ class SubfleetExporter extends ImportExport */ public function __construct() { - self::$columns = SubfleetImporter::$columns; + self::$columns = array_keys(SubfleetImporter::$columns); } /** diff --git a/app/Services/ImportExport/SubfleetImporter.php b/app/Services/ImportExport/SubfleetImporter.php index 0f242ef6..0d817f71 100644 --- a/app/Services/ImportExport/SubfleetImporter.php +++ b/app/Services/ImportExport/SubfleetImporter.php @@ -20,10 +20,10 @@ class SubfleetImporter extends ImportExport * Should match the database fields, for the most part */ public static $columns = [ - 'airline', - 'type', - 'name', - 'fares', + 'airline' => 'required', + 'type' => 'required', + 'name' => 'required', + 'fares' => 'nullable', ]; private $fareSvc; diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php index 1f32fc09..ccd61e15 100644 --- a/app/Services/ImportService.php +++ b/app/Services/ImportService.php @@ -83,7 +83,7 @@ class ImportService extends Service { $reader = $this->openCsv($file_path); - $cols = $importer->getColumns(); + $cols = array_keys($importer->getColumns()); $first_header = $cols[0]; $first = true; @@ -111,6 +111,14 @@ class ImportService extends Service return trim($val); })->toArray(); + # Try to validate + $validator = Validator::make($row, $importer->getColumns()); + if($validator->fails()) { + $errors = 'Error in row '.$offset.','.implode(';', $validator->errors()->all()); + $importer->errorLog($errors); + continue; + } + $importer->import($row, $offset); } diff --git a/tests/ImporterTest.php b/tests/ImporterTest.php index 61690f21..c9d6300c 100644 --- a/tests/ImporterTest.php +++ b/tests/ImporterTest.php @@ -277,6 +277,18 @@ class ImporterTest extends TestCase $this->importSvc->importAirports($file_path); } + /** + * Try importing the aicraft in the airports. Should fail because of + * empty/invalid rows + */ + public function testEmptyCols(): void + { + $file_path = base_path('tests/data/expenses_empty_rows.csv'); + $status = $this->importSvc->importExpenses($file_path); + $this->assertCount(8, $status['success']); + $this->assertCount(0, $status['errors']); + } + /** * Test the importing of expenses * @throws \Illuminate\Validation\ValidationException @@ -291,7 +303,10 @@ class ImporterTest extends TestCase ]); $file_path = base_path('tests/data/expenses.csv'); - $this->importSvc->importExpenses($file_path); + $status = $this->importSvc->importExpenses($file_path); + + $this->assertCount(8, $status['success']); + $this->assertCount(0, $status['errors']); $expenses = \App\Models\Expense::all(); @@ -320,7 +335,10 @@ class ImporterTest extends TestCase public function testFareImporter(): void { $file_path = base_path('tests/data/fares.csv'); - $this->importSvc->importFares($file_path); + $status = $this->importSvc->importFares($file_path); + + $this->assertCount(3, $status['success']); + $this->assertCount(0, $status['errors']); $fares = \App\Models\Fare::all(); @@ -358,7 +376,10 @@ class ImporterTest extends TestCase [$airline, $subfleet] = $this->insertFlightsScaffoldData(); $file_path = base_path('tests/data/flights.csv'); - $this->importSvc->importFlights($file_path); + $status = $this->importSvc->importFlights($file_path); + + $this->assertCount(1, $status['success']); + $this->assertCount(1, $status['errors']); // See if it imported $flight = \App\Models\Flight::where([ @@ -425,7 +446,10 @@ class ImporterTest extends TestCase $subfleet = factory(App\Models\Subfleet::class)->create(['type' => 'A32X']); $file_path = base_path('tests/data/aircraft.csv'); - $this->importSvc->importAircraft($file_path); + $status = $this->importSvc->importAircraft($file_path); + + $this->assertCount(1, $status['success']); + $this->assertCount(1, $status['errors']); // See if it imported $aircraft = \App\Models\Aircraft::where([ @@ -444,7 +468,10 @@ class ImporterTest extends TestCase public function testAirportImporter(): void { $file_path = base_path('tests/data/airports.csv'); - $this->importSvc->importAirports($file_path); + $status = $this->importSvc->importAirports($file_path); + + $this->assertCount(1, $status['success']); + $this->assertCount(1, $status['errors']); // See if it imported $airport = \App\Models\Airport::where([ @@ -468,7 +495,10 @@ class ImporterTest extends TestCase $airline = factory(App\Models\Airline::class)->create(['icao' => 'VMS']); $file_path = base_path('tests/data/subfleets.csv'); - $this->importSvc->importSubfleets($file_path); + $status = $this->importSvc->importSubfleets($file_path); + + $this->assertCount(1, $status['success']); + $this->assertCount(1, $status['errors']); // See if it imported $subfleet = \App\Models\Subfleet::where([ diff --git a/tests/data/aircraft.csv b/tests/data/aircraft.csv index 3c758c1f..d9583705 100644 --- a/tests/data/aircraft.csv +++ b/tests/data/aircraft.csv @@ -1,2 +1,3 @@ subfleet,name,registration,hex_code,status A32X,A320-211,N309US,, +74X,747 400, ,, diff --git a/tests/data/aircraft_empty_cols.csv b/tests/data/aircraft_empty_cols.csv new file mode 100644 index 00000000..645052ce --- /dev/null +++ b/tests/data/aircraft_empty_cols.csv @@ -0,0 +1,3 @@ +subfleet,name,registration,hex_code,status +A32X,A320-211,N309US,, + , B744-GE, N304,, diff --git a/tests/data/airports.csv b/tests/data/airports.csv index 6482b8d2..9032b21f 100644 --- a/tests/data/airports.csv +++ b/tests/data/airports.csv @@ -1,2 +1,3 @@ icao,iata,name,location,country,timezone,hub,lat,lon KAUS,AUS,Austin-Bergstrom,"Austin, Texas, USA", United States,America/Chicago,1,30.1945,-97.6699 +KJFK,JFK,Kennery,"Queens, New York, USA", United States,America/New_York,0,30.1945,abcd diff --git a/tests/data/expenses_empty_rows.csv b/tests/data/expenses_empty_rows.csv new file mode 100644 index 00000000..7138106d --- /dev/null +++ b/tests/data/expenses_empty_rows.csv @@ -0,0 +1,11 @@ +airline,name,amount,type,charge_to_user,multiplier,active,ref_class,ref_class_id +,"Per-Flight (no muliplier)",100,F,0,0,1,, +,"Per-Flight (multiplier)",100,F,0,1,1,, +VMS,"Per-Flight (multiplier, on airline)",200,F,0,1,1,, +,"A daily fee",800,D,0,0,1,, +,"A monthly fee",5000,M,0,0,1,, +,Catering,1000,F,0,0,1,Subfleet,744-3X-RB211 +,"Catering Staff",1000,D,0,0,1,Subfleet,744-3X-RB211 +,Maintenance,1000,D,0,0,1,App\Models\Aircraft,001Z + + diff --git a/tests/data/flights.csv b/tests/data/flights.csv index 5ccaea93..640dcf7a 100644 --- a/tests/data/flights.csv +++ b/tests/data/flights.csv @@ -1,2 +1,3 @@ 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,15,0810 CST,1235 EST,350,1477,207,J,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;B?,Departure Gate=4;Arrival Gate=C41 +" ",1972,,,KAUS,KJFK,KLGA,15,0810 CST,1235 EST,350,1477,207,J,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;B?,Departure Gate=4;Arrival Gate=C41 diff --git a/tests/data/subfleets.csv b/tests/data/subfleets.csv index bec4efb7..0711662a 100644 --- a/tests/data/subfleets.csv +++ b/tests/data/subfleets.csv @@ -1,2 +1,3 @@ airline,type,name,fares VMS,A32X,Airbus A320,Y;B?capacity=100&price=500% +VMS, ,Boeing 747-400,Y;B?capacity=100&price=500%