Add days of week to flights table; add to import/export for flights

This commit is contained in:
Nabeel Shahzad
2018-03-22 21:21:35 -05:00
parent 8b53ca2fdc
commit 7105e82922
17 changed files with 310 additions and 21 deletions
+2
View File
@@ -26,6 +26,8 @@ $factory->define(App\Models\Flight::class, function (Faker $faker) use ($airline
}, },
'distance' => $faker->numberBetween(0, 3000), 'distance' => $faker->numberBetween(0, 3000),
'route' => null, 'route' => null,
'days' => 0,
'level' => 0,
'dpt_time' => $faker->time(), 'dpt_time' => $faker->time(),
'arr_time' => $faker->time(), 'arr_time' => $faker->time(),
'flight_time' => $faker->numberBetween(60, 360), 'flight_time' => $faker->numberBetween(60, 360),
@@ -24,6 +24,7 @@ class CreateFlightTables extends Migration
$table->string('alt_airport_id', 5)->nullable(); $table->string('alt_airport_id', 5)->nullable();
$table->string('dpt_time', 10)->nullable(); $table->string('dpt_time', 10)->nullable();
$table->string('arr_time', 10)->nullable(); $table->string('arr_time', 10)->nullable();
$table->unsignedTinyInteger('days')->nullable();
$table->unsignedInteger('level')->nullable()->default(0); $table->unsignedInteger('level')->nullable()->default(0);
$table->unsignedDecimal('distance')->nullable()->default(0.0); $table->unsignedDecimal('distance')->nullable()->default(0.0);
$table->unsignedInteger('flight_time')->nullable(); $table->unsignedInteger('flight_time')->nullable();
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin;
use App\Http\Requests\CreateFlightRequest; use App\Http\Requests\CreateFlightRequest;
use App\Http\Requests\UpdateFlightRequest; use App\Http\Requests\UpdateFlightRequest;
use App\Interfaces\Controller; use App\Interfaces\Controller;
use App\Models\Enums\Days;
use App\Models\Enums\FlightType; use App\Models\Enums\FlightType;
use App\Models\Flight; use App\Models\Flight;
use App\Models\FlightField; use App\Models\FlightField;
@@ -143,6 +144,7 @@ class FlightController extends Controller
{ {
return view('admin.flights.create', [ return view('admin.flights.create', [
'flight' => null, 'flight' => null,
'days' => [],
'flight_fields' => $this->flightFieldRepo->all(), 'flight_fields' => $this->flightFieldRepo->all(),
'airlines' => $this->airlineRepo->selectBoxList(), 'airlines' => $this->airlineRepo->selectBoxList(),
'airports' => $this->airportRepo->selectBoxList(true, false), 'airports' => $this->airportRepo->selectBoxList(true, false),
@@ -179,6 +181,7 @@ class FlightController extends Controller
return redirect()->back()->withInput($request->all()); return redirect()->back()->withInput($request->all());
} }
$input['days'] = Days::getDaysMask($input['days']);
$input['active'] = get_truth_state($input['active']); $input['active'] = get_truth_state($input['active']);
$time = new Time($input['minutes'], $input['hours']); $time = new Time($input['minutes'], $input['hours']);
@@ -232,6 +235,7 @@ class FlightController extends Controller
return view('admin.flights.edit', [ return view('admin.flights.edit', [
'flight' => $flight, 'flight' => $flight,
'days' => $flight->days,
'flight_fields' => $this->flightFieldRepo->all(), 'flight_fields' => $this->flightFieldRepo->all(),
'airlines' => $this->airlineRepo->selectBoxList(), 'airlines' => $this->airlineRepo->selectBoxList(),
'airports' => $this->airportRepo->selectBoxList(), 'airports' => $this->airportRepo->selectBoxList(),
@@ -279,6 +283,8 @@ class FlightController extends Controller
return redirect()->back()->withInput($request->all()); return redirect()->back()->withInput($request->all());
} }
$input['days'] = Days::getDaysMask($input['days']);
$input['flight_time'] = Time::init( $input['flight_time'] = Time::init(
$input['minutes'], $input['minutes'],
$input['hours'])->getMinutes(); $input['hours'])->getMinutes();
+7 -7
View File
@@ -67,12 +67,7 @@ abstract class Enum
*/ */
public static function getFromCode($code) public static function getFromCode($code)
{ {
$code = strtoupper($code); return array_search($code, static::$codes, true);
if(!array_key_exists($code, static::$codes)) {
return null;
}
return static::$codes[$code];
} }
/** /**
@@ -82,7 +77,12 @@ abstract class Enum
*/ */
public static function convertToCode($value) public static function convertToCode($value)
{ {
return array_search($value, static::$codes, true); $value = (int) $value;
if (!array_key_exists($value, static::$codes)) {
return null;
}
return static::$codes[$value];
} }
/** /**
+5 -5
View File
@@ -25,10 +25,10 @@ class AircraftStatus extends Enum
]; ];
public static $codes = [ public static $codes = [
'S' => AircraftStatus::STORED, AircraftStatus::STORED => 'S',
'A' => AircraftStatus::ACTIVE, AircraftStatus::ACTIVE => 'A' ,
'R' => AircraftStatus::RETIRED, AircraftStatus::RETIRED => 'R',
'C' => AircraftStatus::SCRAPPED, AircraftStatus::SCRAPPED => 'C',
'W' => AircraftStatus::WRITTEN_OFF, AircraftStatus::WRITTEN_OFF => 'W',
]; ];
} }
+38 -1
View File
@@ -6,6 +6,7 @@ use App\Interfaces\Enum;
/** /**
* Class Days * Class Days
* Start on Monday - ISO8601
* @package App\Models\Enums * @package App\Models\Enums
*/ */
class Days extends Enum class Days extends Enum
@@ -18,7 +19,7 @@ class Days extends Enum
public const SATURDAY = 1 << 5; public const SATURDAY = 1 << 5;
public const SUNDAY = 1 << 6; public const SUNDAY = 1 << 6;
protected static $labels = [ public static $labels = [
Days::MONDAY => 'system.days.mon', Days::MONDAY => 'system.days.mon',
Days::TUESDAY => 'system.days.tues', Days::TUESDAY => 'system.days.tues',
Days::WEDNESDAY => 'system.days.wed', Days::WEDNESDAY => 'system.days.wed',
@@ -27,4 +28,40 @@ class Days extends Enum
Days::SATURDAY => 'system.days.sat', Days::SATURDAY => 'system.days.sat',
Days::SUNDAY => 'system.days.sun', Days::SUNDAY => 'system.days.sun',
]; ];
public static $codes = [
'M' => Days::MONDAY,
'T' => Days::TUESDAY,
'W' => Days::WEDNESDAY,
'Th' => Days::THURSDAY,
'F' => Days::FRIDAY,
'S' => Days::SATURDAY,
'Su' => Days::SUNDAY,
];
/**
* Create the masked value for the days of week
* @param array $days
* @return int|mixed
*/
public static function getDaysMask(array $days)
{
$mask = 0;
foreach($days as $day) {
$mask |= $day;
}
return $mask;
}
/**
* See if the given mask has a day
* @param $mask
* @param $day
* @return bool
*/
public static function in($mask, $day): bool
{
return ($mask & $day) === $day;
}
} }
+3 -3
View File
@@ -21,8 +21,8 @@ class ExpenseType extends Enum
]; ];
protected static $codes = [ protected static $codes = [
'F' => ExpenseType::FLIGHT, ExpenseType::FLIGHT => 'F',
'D' => ExpenseType::DAILY, ExpenseType::DAILY =>'D',
'M' => ExpenseType::MONTHLY, ExpenseType::MONTHLY => 'M',
]; ];
} }
+3 -3
View File
@@ -21,8 +21,8 @@ class FlightType extends Enum
]; ];
protected static $codes = [ protected static $codes = [
'P' => FlightType::PASSENGER, FlightType::PASSENGER => 'P',
'C' => FlightType::CARGO, FlightType::CARGO => 'C',
'H' => FlightType::CHARTER, FlightType::CHARTER => 'H',
]; ];
} }
+1 -1
View File
@@ -14,7 +14,7 @@ class FuelType extends Enum
public const JET_A = 1; public const JET_A = 1;
public const MOGAS = 2; public const MOGAS = 2;
protected static $labels = [ public static $labels = [
FuelType::LOW_LEAD => '100LL', FuelType::LOW_LEAD => '100LL',
FuelType::JET_A => 'JET A', FuelType::JET_A => 'JET A',
FuelType::MOGAS => 'MOGAS', FuelType::MOGAS => 'MOGAS',
+29
View File
@@ -3,6 +3,7 @@
namespace App\Models; namespace App\Models;
use App\Interfaces\Model; use App\Interfaces\Model;
use App\Models\Enums\Days;
use App\Models\Traits\HashIdTrait; use App\Models\Traits\HashIdTrait;
use App\Support\Units\Distance; use App\Support\Units\Distance;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@@ -18,6 +19,7 @@ use PhpUnitsOfMeasure\Exception\NonStringUnitName;
* @property Collection field_values * @property Collection field_values
* @property Collection fares * @property Collection fares
* @property Collection subfleets * @property Collection subfleets
* @property integer days
*/ */
class Flight extends Model class Flight extends Model
{ {
@@ -40,6 +42,7 @@ class Flight extends Model
'alt_airport_id', 'alt_airport_id',
'dpt_time', 'dpt_time',
'arr_time', 'arr_time',
'days',
'level', 'level',
'distance', 'distance',
'flight_time', 'flight_time',
@@ -52,6 +55,7 @@ class Flight extends Model
protected $casts = [ protected $casts = [
'flight_number' => 'integer', 'flight_number' => 'integer',
'days' => 'integer',
'level' => 'integer', 'level' => 'integer',
'distance' => 'float', 'distance' => 'float',
'flight_time' => 'integer', 'flight_time' => 'integer',
@@ -70,6 +74,22 @@ class Flight extends Model
'level' => 'nullable', 'level' => 'nullable',
]; ];
/**
* Return all of the flights on any given day(s) of the week
* Search using bitmasks
* @param Days[] $days List of the enumerated values
* @return Flight
*/
public static function findByDays(array $days)
{
$flights = Flight::where('active', true);
foreach($days as $day) {
$flights = $flights->where('days', '&', $day);
}
return $flights;
}
/** /**
* Get the flight ident, e.,g JBU1900 * Get the flight ident, e.,g JBU1900
*/ */
@@ -125,6 +145,15 @@ class Flight extends Model
} }
} }
/**
* @param $day
* @return bool
*/
public function on_day($day): bool
{
return ($this->days & $day) === $day;
}
/** /**
* Return a custom field value * Return a custom field value
* @param $field_name * @param $field_name
@@ -3,6 +3,7 @@
namespace App\Services\ImportExport; namespace App\Services\ImportExport;
use App\Interfaces\ImportExport; use App\Interfaces\ImportExport;
use App\Models\Enums\Days;
use App\Models\Enums\FlightType; use App\Models\Enums\FlightType;
use App\Models\Flight; use App\Models\Flight;
@@ -39,6 +40,7 @@ class FlightExporter extends ImportExport
$ret['airline'] = $ret['airline']->icao; $ret['airline'] = $ret['airline']->icao;
$ret['distance'] = $ret['distance']->toNumber(); $ret['distance'] = $ret['distance']->toNumber();
$ret['days'] = $this->getDays($flight);
$ret['flight_type'] = FlightType::convertToCode($ret['flight_type']); $ret['flight_type'] = FlightType::convertToCode($ret['flight_type']);
$ret['fares'] = $this->getFares($flight); $ret['fares'] = $this->getFares($flight);
@@ -48,6 +50,46 @@ class FlightExporter extends ImportExport
return $ret; return $ret;
} }
/**
* Return the days string
* @param Flight $flight
* @return string
*/
protected function getDays(Flight &$flight)
{
$days_str = '';
if($flight->on_day(Days::MONDAY)) {
$days_str .= '1';
}
if ($flight->on_day(Days::TUESDAY)) {
$days_str .= '2';
}
if ($flight->on_day(Days::WEDNESDAY)) {
$days_str .= '3';
}
if ($flight->on_day(Days::THURSDAY)) {
$days_str .= '4';
}
if ($flight->on_day(Days::FRIDAY)) {
$days_str .= '5';
}
if ($flight->on_day(Days::SATURDAY)) {
$days_str .= '6';
}
if ($flight->on_day(Days::SUNDAY)) {
$days_str .= '7';
}
return $days_str;
}
/** /**
* Return any custom fares that have been made to this flight * Return any custom fares that have been made to this flight
* @param Flight $flight * @param Flight $flight
@@ -4,6 +4,7 @@ namespace App\Services\ImportExport;
use App\Interfaces\ImportExport; use App\Interfaces\ImportExport;
use App\Models\Airport; use App\Models\Airport;
use App\Models\Enums\Days;
use App\Models\Enums\FlightType; use App\Models\Enums\FlightType;
use App\Models\Fare; use App\Models\Fare;
use App\Models\Flight; use App\Models\Flight;
@@ -83,6 +84,7 @@ class FlightImporter extends ImportExport
], $row); ], $row);
// Airport atttributes // Airport atttributes
$flight->setAttribute('days', $this->setDays($row['days']));
$flight->setAttribute('dpt_airport_id', $row['dpt_airport']); $flight->setAttribute('dpt_airport_id', $row['dpt_airport']);
$flight->setAttribute('arr_airport_id', $row['arr_airport']); $flight->setAttribute('arr_airport_id', $row['arr_airport']);
if ($row['alt_airport']) { if ($row['alt_airport']) {
@@ -116,6 +118,49 @@ class FlightImporter extends ImportExport
return true; return true;
} }
/**
* Return the mask of the days
* @param $day_str
* @return int|mixed
*/
protected function setDays($day_str)
{
if(!$day_str) {
return 0;
}
$days = [];
if(strpos($day_str, '1') !== false) {
$days[] = Days::MONDAY;
}
if (strpos($day_str, '2') !== false) {
$days[] = Days::TUESDAY;
}
if (strpos($day_str, '3') !== false) {
$days[] = Days::WEDNESDAY;
}
if (strpos($day_str, '4') !== false) {
$days[] = Days::THURSDAY;
}
if (strpos($day_str, '5') !== false) {
$days[] = Days::FRIDAY;
}
if (strpos($day_str, '6') !== false) {
$days[] = Days::SATURDAY;
}
if (strpos($day_str, '7') !== false) {
$days[] = Days::SUNDAY;
}
return Days::getDaysMask($days);
}
/** /**
* Process the airport * Process the airport
* @param $airport * @param $airport
+13
View File
@@ -1,5 +1,18 @@
<?php <?php
if (!function_exists('in_mask')) {
/**
* Return true/false if a value exists in a mask
* @param $mask
* @param $value
* @return bool
*/
function in_mask($mask, $value)
{
return ($mask & $value) === $value;
}
}
if (!function_exists('get_truth_state')) { if (!function_exists('get_truth_state')) {
/** /**
* Check if the passed state matches any of the states that * Check if the passed state matches any of the states that
@@ -28,6 +28,74 @@
</div> </div>
</div> </div>
<div class="row">
<div class="form-group col-md-12" style="text-align: center;">
<span style="margin-right: 20px;">
{{ Form::label('days[]', 'Monday') }}
{{ Form::checkbox(
'days[]',
\App\Models\Enums\Days::MONDAY,
in_mask($days, \App\Models\Enums\Days::MONDAY),
['class' => 'form-control icheck']
) }}
</span>
<span style="margin-right: 20px;">
{{ Form::label('days[]', 'Tuesday') }}
{{ Form::checkbox(
'days[]',
\App\Models\Enums\Days::TUESDAY,
in_mask($days, \App\Models\Enums\Days::TUESDAY),
['class' => 'form-control icheck']
) }}
</span>
<span style="margin-right: 20px;">
{{ Form::label('days[]', 'Wednesday') }}
{{ Form::checkbox(
'days[]',
\App\Models\Enums\Days::WEDNESDAY,
in_mask($days, \App\Models\Enums\Days::WEDNESDAY),
['class' => 'form-control icheck']
) }}
</span>
<span style="margin-right: 20px;">
{{ Form::label('days[]', 'Thursday') }}
{{ Form::checkbox(
'days[]',
\App\Models\Enums\Days::THURSDAY,
in_mask($days, \App\Models\Enums\Days::THURSDAY),
['class' => 'form-control icheck']
) }}
</span>
<span style="margin-right: 20px;">
{{ Form::label('days[]', 'Friday') }}
{{ Form::checkbox(
'days[]',
\App\Models\Enums\Days::FRIDAY,
in_mask($days, \App\Models\Enums\Days::FRIDAY),
['class' => 'form-control icheck']
) }}
</span>
<span style="margin-right: 20px;">
{{ Form::label('days[]', 'Saturday') }}
{{ Form::checkbox(
'days[]',
\App\Models\Enums\Days::SATURDAY,
in_mask($days, \App\Models\Enums\Days::SATURDAY),
['class' => 'form-control icheck']
) }}
</span>
<span>
{{ Form::label('days[]', 'Sunday') }}
{{ Form::checkbox(
'days[]',
\App\Models\Enums\Days::SUNDAY,
in_mask($days, \App\Models\Enums\Days::SUNDAY),
['class' => 'form-control icheck']
) }}
</span>
</div>
</div>
<div class="row"> <div class="row">
<div class="form-group col-sm-3"> <div class="form-group col-sm-3">
+36
View File
@@ -1,5 +1,6 @@
<?php <?php
use App\Models\Enums\Days;
use App\Models\Flight; use App\Models\Flight;
use App\Models\User; use App\Models\User;
use App\Models\Bid; use App\Models\Bid;
@@ -118,6 +119,41 @@ class FlightTest extends TestCase
$res->assertJsonCount(5, 'data'); $res->assertJsonCount(5, 'data');
} }
/**
* Test the bitmasks that they work for setting the day of week and
* then retrieving by searching on those
*/
public function testFindDaysOfWeek(): void
{
$this->user = factory(App\Models\User::class)->create();
factory(App\Models\Flight::class, 20)->create([
'airline_id' => $this->user->airline_id
]);
$saved_flight = factory(App\Models\Flight::class)->create([
'airline_id' => $this->user->airline_id,
'days' => Days::getDaysMask([
Days::SUNDAY,
Days::THURSDAY
])
]);
$flight = Flight::findByDays([Days::SUNDAY])->first();
$this->assertTrue($flight->on_day(Days::SUNDAY));
$this->assertTrue($flight->on_day(Days::THURSDAY));
$this->assertFalse($flight->on_day(Days::MONDAY));
$this->assertEquals($saved_flight->id, $flight->id);
$flight = Flight::findByDays([Days::SUNDAY, Days::THURSDAY])->first();
$this->assertEquals($saved_flight->id, $flight->id);
$flight = Flight::findByDays([Days::WEDNESDAY, Days::THURSDAY])->first();
$this->assertNull($flight);
}
/**
*
*/
public function testFlightSearchApi() public function testFlightSearchApi()
{ {
$this->user = factory(App\Models\User::class)->create(); $this->user = factory(App\Models\User::class)->create();
+10
View File
@@ -230,6 +230,10 @@ class ImporterTest extends TestCase
$flight = factory(App\Models\Flight::class)->create([ $flight = factory(App\Models\Flight::class)->create([
'airline_id' => $airline->id, 'airline_id' => $airline->id,
'days' => \App\Models\Enums\Days::getDaysMask([
\App\Models\Enums\Days::TUESDAY,
\App\Models\Enums\Days::SUNDAY,
]),
]); ]);
$flight->subfleets()->syncWithoutDetaching([$subfleet->id, $subfleet2->id]); $flight->subfleets()->syncWithoutDetaching([$subfleet->id, $subfleet2->id]);
@@ -256,6 +260,7 @@ class ImporterTest extends TestCase
$exporter = new \App\Services\ImportExport\FlightExporter(); $exporter = new \App\Services\ImportExport\FlightExporter();
$exported = $exporter->export($flight); $exported = $exporter->export($flight);
$this->assertEquals('27', $exported['days']);
$this->assertEquals('VMS', $exported['airline']); $this->assertEquals('VMS', $exported['airline']);
$this->assertEquals('A32X;B74X', $exported['subfleets']); $this->assertEquals('A32X;B74X', $exported['subfleets']);
$this->assertEquals('Y?capacity=100;F', $exported['fares']); $this->assertEquals('Y?capacity=100;F', $exported['fares']);
@@ -376,6 +381,11 @@ class ImporterTest extends TestCase
$this->assertEquals('Just a flight', $flight->notes); $this->assertEquals('Just a flight', $flight->notes);
$this->assertEquals(true, $flight->active); $this->assertEquals(true, $flight->active);
# Test that the days were set properly
$this->assertTrue($flight->on_day(\App\Models\Enums\Days::MONDAY));
$this->assertTrue($flight->on_day(\App\Models\Enums\Days::FRIDAY));
$this->assertFalse($flight->on_day(\App\Models\Enums\Days::TUESDAY));
// Check the custom fields entered // Check the custom fields entered
$fields = \App\Models\FlightFieldValue::where([ $fields = \App\Models\FlightFieldValue::where([
'flight_id' => $flight->id, 'flight_id' => $flight->id,
+1 -1
View File
@@ -1,2 +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 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;B?,Departure Gate=4;Arrival Gate=C41 VMS,1972,,,KAUS,KJFK,KLGA,15,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;B?,Departure Gate=4;Arrival Gate=C41
1 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
2 VMS 1972 KAUS KJFK KLGA 15 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;B? Departure Gate=4;Arrival Gate=C41