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

View File

@ -26,6 +26,8 @@ $factory->define(App\Models\Flight::class, function (Faker $faker) use ($airline
},
'distance' => $faker->numberBetween(0, 3000),
'route' => null,
'days' => 0,
'level' => 0,
'dpt_time' => $faker->time(),
'arr_time' => $faker->time(),
'flight_time' => $faker->numberBetween(60, 360),

View File

@ -24,6 +24,7 @@ class CreateFlightTables extends Migration
$table->string('alt_airport_id', 5)->nullable();
$table->string('dpt_time', 10)->nullable();
$table->string('arr_time', 10)->nullable();
$table->unsignedTinyInteger('days')->nullable();
$table->unsignedInteger('level')->nullable()->default(0);
$table->unsignedDecimal('distance')->nullable()->default(0.0);
$table->unsignedInteger('flight_time')->nullable();

View File

@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin;
use App\Http\Requests\CreateFlightRequest;
use App\Http\Requests\UpdateFlightRequest;
use App\Interfaces\Controller;
use App\Models\Enums\Days;
use App\Models\Enums\FlightType;
use App\Models\Flight;
use App\Models\FlightField;
@ -143,6 +144,7 @@ class FlightController extends Controller
{
return view('admin.flights.create', [
'flight' => null,
'days' => [],
'flight_fields' => $this->flightFieldRepo->all(),
'airlines' => $this->airlineRepo->selectBoxList(),
'airports' => $this->airportRepo->selectBoxList(true, false),
@ -179,6 +181,7 @@ class FlightController extends Controller
return redirect()->back()->withInput($request->all());
}
$input['days'] = Days::getDaysMask($input['days']);
$input['active'] = get_truth_state($input['active']);
$time = new Time($input['minutes'], $input['hours']);
@ -232,6 +235,7 @@ class FlightController extends Controller
return view('admin.flights.edit', [
'flight' => $flight,
'days' => $flight->days,
'flight_fields' => $this->flightFieldRepo->all(),
'airlines' => $this->airlineRepo->selectBoxList(),
'airports' => $this->airportRepo->selectBoxList(),
@ -279,6 +283,8 @@ class FlightController extends Controller
return redirect()->back()->withInput($request->all());
}
$input['days'] = Days::getDaysMask($input['days']);
$input['flight_time'] = Time::init(
$input['minutes'],
$input['hours'])->getMinutes();

View File

@ -67,12 +67,7 @@ abstract class Enum
*/
public static function getFromCode($code)
{
$code = strtoupper($code);
if(!array_key_exists($code, static::$codes)) {
return null;
}
return static::$codes[$code];
return array_search($code, static::$codes, true);
}
/**
@ -82,7 +77,12 @@ abstract class Enum
*/
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];
}
/**

View File

@ -25,10 +25,10 @@ class AircraftStatus extends Enum
];
public static $codes = [
'S' => AircraftStatus::STORED,
'A' => AircraftStatus::ACTIVE,
'R' => AircraftStatus::RETIRED,
'C' => AircraftStatus::SCRAPPED,
'W' => AircraftStatus::WRITTEN_OFF,
AircraftStatus::STORED => 'S',
AircraftStatus::ACTIVE => 'A' ,
AircraftStatus::RETIRED => 'R',
AircraftStatus::SCRAPPED => 'C',
AircraftStatus::WRITTEN_OFF => 'W',
];
}

View File

@ -6,6 +6,7 @@ use App\Interfaces\Enum;
/**
* Class Days
* Start on Monday - ISO8601
* @package App\Models\Enums
*/
class Days extends Enum
@ -18,7 +19,7 @@ class Days extends Enum
public const SATURDAY = 1 << 5;
public const SUNDAY = 1 << 6;
protected static $labels = [
public static $labels = [
Days::MONDAY => 'system.days.mon',
Days::TUESDAY => 'system.days.tues',
Days::WEDNESDAY => 'system.days.wed',
@ -27,4 +28,40 @@ class Days extends Enum
Days::SATURDAY => 'system.days.sat',
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;
}
}

View File

@ -21,8 +21,8 @@ class ExpenseType extends Enum
];
protected static $codes = [
'F' => ExpenseType::FLIGHT,
'D' => ExpenseType::DAILY,
'M' => ExpenseType::MONTHLY,
ExpenseType::FLIGHT => 'F',
ExpenseType::DAILY =>'D',
ExpenseType::MONTHLY => 'M',
];
}

View File

@ -21,8 +21,8 @@ class FlightType extends Enum
];
protected static $codes = [
'P' => FlightType::PASSENGER,
'C' => FlightType::CARGO,
'H' => FlightType::CHARTER,
FlightType::PASSENGER => 'P',
FlightType::CARGO => 'C',
FlightType::CHARTER => 'H',
];
}

View File

@ -14,7 +14,7 @@ class FuelType extends Enum
public const JET_A = 1;
public const MOGAS = 2;
protected static $labels = [
public static $labels = [
FuelType::LOW_LEAD => '100LL',
FuelType::JET_A => 'JET A',
FuelType::MOGAS => 'MOGAS',

View File

@ -3,6 +3,7 @@
namespace App\Models;
use App\Interfaces\Model;
use App\Models\Enums\Days;
use App\Models\Traits\HashIdTrait;
use App\Support\Units\Distance;
use Illuminate\Support\Collection;
@ -18,6 +19,7 @@ use PhpUnitsOfMeasure\Exception\NonStringUnitName;
* @property Collection field_values
* @property Collection fares
* @property Collection subfleets
* @property integer days
*/
class Flight extends Model
{
@ -40,6 +42,7 @@ class Flight extends Model
'alt_airport_id',
'dpt_time',
'arr_time',
'days',
'level',
'distance',
'flight_time',
@ -52,6 +55,7 @@ class Flight extends Model
protected $casts = [
'flight_number' => 'integer',
'days' => 'integer',
'level' => 'integer',
'distance' => 'float',
'flight_time' => 'integer',
@ -70,6 +74,22 @@ class Flight extends Model
'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
*/
@ -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
* @param $field_name

View File

@ -3,6 +3,7 @@
namespace App\Services\ImportExport;
use App\Interfaces\ImportExport;
use App\Models\Enums\Days;
use App\Models\Enums\FlightType;
use App\Models\Flight;
@ -39,6 +40,7 @@ class FlightExporter extends ImportExport
$ret['airline'] = $ret['airline']->icao;
$ret['distance'] = $ret['distance']->toNumber();
$ret['days'] = $this->getDays($flight);
$ret['flight_type'] = FlightType::convertToCode($ret['flight_type']);
$ret['fares'] = $this->getFares($flight);
@ -48,6 +50,46 @@ class FlightExporter extends ImportExport
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
* @param Flight $flight

View File

@ -4,6 +4,7 @@ namespace App\Services\ImportExport;
use App\Interfaces\ImportExport;
use App\Models\Airport;
use App\Models\Enums\Days;
use App\Models\Enums\FlightType;
use App\Models\Fare;
use App\Models\Flight;
@ -83,6 +84,7 @@ class FlightImporter extends ImportExport
], $row);
// Airport atttributes
$flight->setAttribute('days', $this->setDays($row['days']));
$flight->setAttribute('dpt_airport_id', $row['dpt_airport']);
$flight->setAttribute('arr_airport_id', $row['arr_airport']);
if ($row['alt_airport']) {
@ -116,6 +118,49 @@ class FlightImporter extends ImportExport
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
* @param $airport

View File

@ -1,5 +1,18 @@
<?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')) {
/**
* Check if the passed state matches any of the states that

View File

@ -28,6 +28,74 @@
</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="form-group col-sm-3">

View File

@ -1,5 +1,6 @@
<?php
use App\Models\Enums\Days;
use App\Models\Flight;
use App\Models\User;
use App\Models\Bid;
@ -118,6 +119,41 @@ class FlightTest extends TestCase
$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()
{
$this->user = factory(App\Models\User::class)->create();

View File

@ -230,6 +230,10 @@ class ImporterTest extends TestCase
$flight = factory(App\Models\Flight::class)->create([
'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]);
@ -256,6 +260,7 @@ class ImporterTest extends TestCase
$exporter = new \App\Services\ImportExport\FlightExporter();
$exported = $exporter->export($flight);
$this->assertEquals('27', $exported['days']);
$this->assertEquals('VMS', $exported['airline']);
$this->assertEquals('A32X;B74X', $exported['subfleets']);
$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(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
$fields = \App\Models\FlightFieldValue::where([
'flight_id' => $flight->id,

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
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