diff --git a/app/Database/factories/PirepFactory.php b/app/Database/factories/PirepFactory.php index 133d3f21..a3f28d63 100644 --- a/app/Database/factories/PirepFactory.php +++ b/app/Database/factories/PirepFactory.php @@ -39,13 +39,18 @@ $factory->define(App\Models\Pirep::class, function (Faker $faker) { 'zfw' => $faker->randomFloat(2), 'block_fuel' => $faker->randomFloat(2, 0, 30000), 'fuel_used' => $faker->randomFloat(2, 0, 30000), + 'block_on_time' => Carbon::now('UTC'), + 'block_off_time' => function (array $pirep) { + return $pirep['block_on_time']->subMinutes($pirep['flight_time']); + }, 'route' => $faker->text(200), 'notes' => $faker->text(200), 'source' => $faker->randomElement([PirepSource::MANUAL, PirepSource::ACARS]), 'source_name' => 'Test Factory', 'state' => PirepState::PENDING, 'status' => PirepStatus::SCHEDULED, - 'created_at' => Carbon::now()->toDateTimeString(), + 'submitted_at' => Carbon::now('UTC')->toDateTimeString(), + 'created_at' => Carbon::now('UTC')->toDateTimeString(), 'updated_at' => function (array $pirep) { return $pirep['created_at']; }, diff --git a/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php b/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php index 4fa8562a..51a26898 100644 --- a/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php +++ b/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php @@ -39,9 +39,10 @@ class CreatePirepTables extends Migration $table->text('route')->nullable(); $table->text('notes')->nullable(); $table->unsignedTinyInteger('source')->nullable()->default(0); - $table->string('source_name', 25)->nullable(); + $table->string('source_name', 50)->nullable(); $table->tinyInteger('state')->default(PirepState::PENDING); $table->char('status', 3)->default(PirepStatus::SCHEDULED); + $table->dateTime('submitted_at')->nullable(); $table->dateTime('block_off_time')->nullable(); $table->dateTime('block_on_time')->nullable(); $table->timestamps(); diff --git a/app/Database/seeds/sample.yml b/app/Database/seeds/sample.yml index 79032bdc..9a6db118 100644 --- a/app/Database/seeds/sample.yml +++ b/app/Database/seeds/sample.yml @@ -386,6 +386,8 @@ pireps: aircraft_id: 1 dpt_airport_id: KAUS arr_airport_id: KJFK + block_off_time: 2018-04-04T12:42:36+00:00 + block_on_time: 2018-04-04T16:42:36+00:00 flight_time: 180 # 6 hours state: 1 # accepted status: 0 @@ -393,8 +395,9 @@ pireps: flight_type: J route: KAUS SID TNV J87 IAH J2 LCH J22 MEI J239 ATL J52 AJFEB J14 BYJAC Q60 JAXSN J14 COLIN J61 HUBBS J55 SIE STAR KJFK notes: just a pilot report - created_at: NOW - updated_at: NOW + submitted_at: 2018-04-04T16:50:36+00:00 + created_at: 2018-04-04T16:50:36+00:00 + updated_at: 2018-04-04T17:00:36+00:00 - id: pirepid_2 user_id: 1 airline_id: 1 @@ -409,6 +412,7 @@ pireps: notes: just a pilot report source: 1 # pending source_name: sample + submitted_at: NOW created_at: NOW updated_at: NOW - id: pirepid_3 @@ -424,6 +428,7 @@ pireps: flight_type: J route: PLMMR2 SPA Q22 BEARI FAK PHLBO3 notes: just a pilot report + submitted_at: NOW created_at: NOW updated_at: NOW diff --git a/app/Http/Controllers/Api/PirepController.php b/app/Http/Controllers/Api/PirepController.php index 1886c20b..d610ff19 100644 --- a/app/Http/Controllers/Api/PirepController.php +++ b/app/Http/Controllers/Api/PirepController.php @@ -35,6 +35,7 @@ use App\Services\GeoService; use App\Services\PirepService; use App\Services\UserService; use Auth; +use Carbon\Carbon; use Illuminate\Http\Request; use Log; @@ -237,7 +238,7 @@ class PirepController extends Controller Log::info('PIREP Update, user '.Auth::id(), $request->post()); $user = Auth::user(); - $pirep = $this->pirepRepo->find($id); + $pirep = Pirep::find($id); $this->checkCancelled($pirep); $attrs = $request->post(); @@ -277,7 +278,7 @@ class PirepController extends Controller $user = Auth::user(); # Check if the status is cancelled... - $pirep = $this->pirepRepo->find($id); + $pirep = Pirep::find($id); $this->checkCancelled($pirep); $attrs = $request->post(); @@ -294,9 +295,11 @@ class PirepController extends Controller $attrs['state'] = PirepState::PENDING; $attrs['status'] = PirepStatus::ARRIVED; + $attrs['submitted_at'] = Carbon::now('UTC'); + + $pirep = $this->pirepRepo->update($attrs, $id); try { - $pirep = $this->pirepRepo->update($attrs, $id); $pirep = $this->pirepSvc->create($pirep); $this->updateFields($pirep, $request); $this->updateFares($pirep, $request); @@ -343,7 +346,7 @@ class PirepController extends Controller */ public function acars_geojson($id, Request $request) { - $pirep = $this->pirepRepo->find($id); + $pirep = Pirep::find($id); $geodata = $this->geoSvc->getFeatureFromAcars($pirep); return response(\json_encode($geodata), 200, [ @@ -378,7 +381,7 @@ class PirepController extends Controller public function acars_store($id, PositionRequest $request) { # Check if the status is cancelled... - $pirep = $this->pirepRepo->find($id); + $pirep = Pirep::find($id); $this->checkCancelled($pirep); Log::debug( @@ -420,7 +423,7 @@ class PirepController extends Controller public function acars_logs($id, LogRequest $request) { # Check if the status is cancelled... - $pirep = $this->pirepRepo->find($id); + $pirep = Pirep::find($id); $this->checkCancelled($pirep); Log::debug('Posting ACARS log, PIREP: '.$id, $request->post()); @@ -451,7 +454,7 @@ class PirepController extends Controller public function acars_events($id, EventRequest $request) { # Check if the status is cancelled... - $pirep = $this->pirepRepo->find($id); + $pirep = Pirep::find($id); $this->checkCancelled($pirep); Log::debug('Posting ACARS event, PIREP: '.$id, $request->post()); @@ -479,8 +482,7 @@ class PirepController extends Controller */ public function comments_get($id, Request $request) { - $pirep = $this->pirepRepo->find($id); - + $pirep = Pirep::find($id); return PirepCommentResource::collection($pirep->comments); } @@ -493,7 +495,7 @@ class PirepController extends Controller */ public function comments_post($id, CommentRequest $request) { - $pirep = $this->pirepRepo->find($id); + $pirep = Pirep::find($id); $this->checkCancelled($pirep); Log::debug('Posting comment, PIREP: '.$id, $request->post()); @@ -516,9 +518,8 @@ class PirepController extends Controller */ public function finances_get($id, Request $request) { - $pirep = $this->pirepRepo->find($id); + $pirep = Pirep::find($id); $transactions = $this->journalRepo->getAllForObject($pirep); - return JournalTransactionResource::collection($transactions); } @@ -533,12 +534,12 @@ class PirepController extends Controller */ public function finances_recalculate($id, Request $request) { - $pirep = $this->pirepRepo->find($id); + $pirep = Pirep::find($id); $this->financeSvc->processFinancesForPirep($pirep); $pirep->refresh(); - $transactions = $this->journalRepo->getAllForObject($pirep); + $transactions = $this->journalRepo->getAllForObject($pirep); return JournalTransactionResource::collection($transactions['transactions']); } @@ -549,8 +550,7 @@ class PirepController extends Controller */ public function route_get($id, Request $request) { - $this->pirepRepo->find($id); - + $pirep = Pirep::find($id); return AcarsRouteResource::collection(Acars::where([ 'pirep_id' => $id, 'type' => AcarsType::ROUTE @@ -568,7 +568,7 @@ class PirepController extends Controller public function route_post($id, RouteRequest $request) { # Check if the status is cancelled... - $pirep = $this->pirepRepo->find($id); + $pirep = Pirep::find($id); $this->checkCancelled($pirep); Log::info('Posting ROUTE, PIREP: '.$id, $request->post()); @@ -596,7 +596,7 @@ class PirepController extends Controller */ public function route_delete($id, Request $request) { - $this->pirepRepo->find($id); + $pirep = Pirep::find($id); Acars::where([ 'pirep_id' => $id, diff --git a/app/Http/Controllers/Frontend/PirepController.php b/app/Http/Controllers/Frontend/PirepController.php index d58319e2..fb740f2d 100644 --- a/app/Http/Controllers/Frontend/PirepController.php +++ b/app/Http/Controllers/Frontend/PirepController.php @@ -21,6 +21,7 @@ use App\Services\GeoService; use App\Services\PirepService; use App\Services\UserService; use App\Support\Units\Time; +use Carbon\Carbon; use Flash; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -283,6 +284,9 @@ class PirepController extends Controller $minutes = (int) $request->input('minutes', 0); $pirep->flight_time = Utils::hoursToMinutes($hours) + $minutes; + // Put the time that this is currently submitted + $attrs['submitted_at'] = Carbon::now('UTC'); + $pirep = $this->pirepSvc->create($pirep); $this->saveCustomFields($pirep, $request); $this->saveFares($pirep, $request); diff --git a/app/Http/Requests/Acars/FileRequest.php b/app/Http/Requests/Acars/FileRequest.php index 96675db2..d835d264 100644 --- a/app/Http/Requests/Acars/FileRequest.php +++ b/app/Http/Requests/Acars/FileRequest.php @@ -41,7 +41,7 @@ class FileRequest extends FormRequest 'block_fuel' => 'nullable|numeric', 'route' => 'nullable', 'notes' => 'nullable', - 'source_name' => 'nullable|max:25', + 'source_name' => 'nullable', 'landing_rate' => 'nullable|numeric', 'flight_type' => 'nullable|integer', 'block_off_time' => 'nullable|date', diff --git a/app/Http/Requests/Acars/PrefileRequest.php b/app/Http/Requests/Acars/PrefileRequest.php index aded7443..c968d582 100644 --- a/app/Http/Requests/Acars/PrefileRequest.php +++ b/app/Http/Requests/Acars/PrefileRequest.php @@ -23,7 +23,7 @@ class PrefileRequest extends FormRequest 'flight_number' => 'required', 'dpt_airport_id' => 'required', 'arr_airport_id' => 'required', - 'source_name' => 'required|max:25', + 'source_name' => 'required', 'level' => 'nullable|numeric', 'route_code' => 'nullable', diff --git a/app/Http/Requests/Acars/UpdateRequest.php b/app/Http/Requests/Acars/UpdateRequest.php index 12f2ddb6..53bfc61c 100644 --- a/app/Http/Requests/Acars/UpdateRequest.php +++ b/app/Http/Requests/Acars/UpdateRequest.php @@ -31,7 +31,7 @@ class UpdateRequest extends FormRequest 'route_leg' => 'nullable', 'distance' => 'nullable|numeric', 'planned_distance' => 'nullable|numeric', - 'block_time' => 'nullable|integer', + 'block_time' => 'nullable|integer', 'flight_time' => 'nullable|integer', 'planned_flight_time' => 'nullable|integer', 'level' => 'nullable|numeric', @@ -47,6 +47,7 @@ class UpdateRequest extends FormRequest 'block_on_time' => 'nullable|date', 'created_at' => 'nullable|date', 'status' => 'nullable', + 'source_name' => 'nullable', # See if the fare objects are included and formatted properly 'fares' => 'nullable|array', diff --git a/app/Models/Pirep.php b/app/Models/Pirep.php index 06ac3656..9f10837b 100644 --- a/app/Models/Pirep.php +++ b/app/Models/Pirep.php @@ -8,6 +8,7 @@ use App\Models\Enums\PirepState; use App\Models\Traits\HashIdTrait; use App\Support\Units\Distance; use App\Support\Units\Fuel; +use Carbon\Carbon; use Illuminate\Support\Collection; use PhpUnitsOfMeasure\Exception\NonNumericValue; use PhpUnitsOfMeasure\Exception\NonStringUnitName; @@ -27,11 +28,16 @@ use PhpUnitsOfMeasure\Exception\NonStringUnitName; * @property string arr_airport_id * @property Airport dpt_airport * @property string dpt_airport_id + * @property Carbon block_off_time + * @property Carbon block_on_time * @property integer block_time * @property integer flight_time In minutes * @property User user * @property Flight|null flight * @property Collection fields + * @property Carbon submitted_at + * @property Carbon created_at + * @property Carbon updated_at * @package App\Models */ class Pirep extends Model @@ -73,6 +79,7 @@ class Pirep extends Model 'status', 'block_off_time', 'block_on_time', + 'submitted_at', 'created_at', 'updated_at', ]; @@ -95,6 +102,7 @@ class Pirep extends Model 'state' => 'integer', 'block_off_time' => 'datetime', 'block_on_time' => 'datetime', + 'submitted_at' => 'datetime', ]; public static $rules = [ diff --git a/app/Models/PirepComment.php b/app/Models/PirepComment.php index ba1e61f3..224bfd54 100644 --- a/app/Models/PirepComment.php +++ b/app/Models/PirepComment.php @@ -7,6 +7,8 @@ use App\Interfaces\Model; /** * Class PirepEvent * + * @property string pirep_id + * @property int user_id * @package App\Models */ class PirepComment extends Model diff --git a/app/Services/PirepService.php b/app/Services/PirepService.php index c6f04406..1f0e2c17 100644 --- a/app/Services/PirepService.php +++ b/app/Services/PirepService.php @@ -185,6 +185,28 @@ class PirepService extends Service } } + # Check the block times. If a block on (arrival) time isn't + # specified, then use the time that it was submitted. It won't + # be the most accurate, but that might be OK + if(!$pirep->block_on_time) { + if($pirep->submitted_at) { + $pirep->block_on_time = $pirep->submitted_at; + } else { + $pirep->block_on_time = Carbon::now('UTC'); + } + } + + # If the depart time isn't set, then try to calculate it by + # subtracting the flight time from the block_on (arrival) time + if(!$pirep->block_off_time && $pirep->flight_time > 0) { + $pirep->block_off_time = $pirep->block_on_time->subMinutes($pirep->flight_time); + } + + # Check that there's a submit time + if (!$pirep->submitted_at) { + $pirep->submitted_at = Carbon::now('UTC'); + } + $pirep->save(); $pirep->refresh(); diff --git a/tests/AcarsTest.php b/tests/AcarsTest.php index 1bf310ec..00df1dbb 100644 --- a/tests/AcarsTest.php +++ b/tests/AcarsTest.php @@ -288,7 +288,7 @@ class AcarsTest extends TestCase 'planned_distance' => 400, 'planned_flight_time' => 120, 'route' => 'POINTA POINTB', - 'source_name' => 'UnitTest', + 'source_name' => 'AcarsTest::testAcarsUpdates', 'fields' => [ 'custom_field' => 'custom_value', ], @@ -410,6 +410,62 @@ class AcarsTest extends TestCase $this->assertCount(1, $comments); } + /** + * Post a PIREP into a PREFILE state and post ACARS + */ + public function testFilePirepApi(): void + { + $subfleet = $this->createSubfleetWithAircraft(2); + $rank = $this->createRank(10, [$subfleet['subfleet']->id]); + + $this->user = factory(App\Models\User::class)->create([ + 'rank_id' => $rank->id, + ]); + + $airport = factory(App\Models\Airport::class)->create(); + $airline = factory(App\Models\Airline::class)->create(); + $aircraft = $subfleet['aircraft']->random(); + + $uri = '/api/pireps/prefile'; + $pirep = [ + 'airline_id' => $airline->id, + 'aircraft_id' => $aircraft->id, + 'dpt_airport_id' => $airport->icao, + 'arr_airport_id' => $airport->icao, + 'flight_number' => '6000', + 'level' => 38000, + 'source_name' => 'AcarsTest::testFilePirepApi', + ]; + + $response = $this->post($uri, $pirep); + $response->assertStatus(201); + + # Get the PIREP ID + $body = $response->json(); + $pirep_id = $body['data']['id']; + + # File the PIREP now + $uri = '/api/pireps/'.$pirep_id.'/file'; + + $response = $this->post($uri, [ + 'flight_time' => 130, + 'fuel_used' => 8000.19, + 'distance' => 400, + ]); + + $response->assertStatus(200); + + # Check the block_off_time and block_on_time being set + $body = $this->get('/api/pireps/'.$pirep_id)->json('data'); + $this->assertNotNull($body['block_off_time']); + $this->assertNotNull($body['block_on_time']); + + # make sure the time matches up + $block_on = new Carbon($body['block_on_time'], 'UTC'); + $block_off = new Carbon($body['block_off_time'], 'UTC'); + $this->assertEquals($block_on->subMinutes($body['flight_time']), $block_off); + } + /** * Test aircraft is allowed */