@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class FlightsAddPilotPay extends Migration
|
||||
{
|
||||
/**
|
||||
* Add a `pilot_pay` column for a fixed amount to pay to a pilot for a flight
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('flights', function (Blueprint $table) {
|
||||
$table->decimal('pilot_pay')
|
||||
->nullable()
|
||||
->after('route');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('flights', function (Blueprint $table) {
|
||||
$table->dropColumn('pilot_pay');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ use Illuminate\Support\Collection;
|
||||
* @property int level
|
||||
* @property float load_factor
|
||||
* @property float load_factor_variance
|
||||
* @property float pilot_pay
|
||||
* @property Airport dpt_airport
|
||||
* @property Airport arr_airport
|
||||
* @property Airport alt_airport
|
||||
@@ -69,6 +70,7 @@ class Flight extends Model
|
||||
'flight_type',
|
||||
'load_factor',
|
||||
'load_factor_variance',
|
||||
'pilot_pay',
|
||||
'route',
|
||||
'notes',
|
||||
'start_date',
|
||||
@@ -88,6 +90,7 @@ class Flight extends Model
|
||||
'end_date' => 'date',
|
||||
'load_factor' => 'double',
|
||||
'load_factor_variance' => 'double',
|
||||
'pilot_pay' => 'float',
|
||||
'has_bid' => 'boolean',
|
||||
'route_leg' => 'integer',
|
||||
'active' => 'boolean',
|
||||
|
||||
@@ -374,11 +374,18 @@ class PirepFinanceService extends Service
|
||||
public function payPilotForPirep(Pirep $pirep): void
|
||||
{
|
||||
$pilot_pay = $this->getPilotPay($pirep);
|
||||
$pilot_pay_rate = $this->getPilotPayRateForPirep($pirep);
|
||||
$memo = 'Pilot Payment @ '.$pilot_pay_rate;
|
||||
|
||||
Log::info('Finance: PIREP: '.$pirep->id
|
||||
.'; pilot pay: '.$pilot_pay_rate.', total: '.$pilot_pay);
|
||||
if ($pirep->flight && !empty($pirep->flight->pilot_pay)) {
|
||||
$memo = 'Pilot fixed payment for flight: '.$pirep->flight->pilot_pay;
|
||||
Log::info('Finance: PIREP: '.$pirep->id
|
||||
.'; pilot pay: fixed for flight='.$pirep->flight->pilot_pay.', total: '.$pilot_pay);
|
||||
} else {
|
||||
$pilot_pay_rate = $this->getPilotPayRateForPirep($pirep);
|
||||
$memo = 'Pilot Payment @ '.$pilot_pay_rate;
|
||||
|
||||
Log::info('Finance: PIREP: '.$pirep->id
|
||||
.'; pilot pay: '.$pilot_pay_rate.', total: '.$pilot_pay);
|
||||
}
|
||||
|
||||
$this->financeSvc->debitFromJournal(
|
||||
$pirep->airline->journal,
|
||||
@@ -530,6 +537,13 @@ class PirepFinanceService extends Service
|
||||
*/
|
||||
public function getPilotPay(Pirep $pirep)
|
||||
{
|
||||
// If there is a fixed price for this flight, return that amount
|
||||
$flight = $pirep->flight;
|
||||
if ($flight && !empty($flight->pilot_pay)) {
|
||||
return new Money(Money::convertToSubunit($flight->pilot_pay));
|
||||
}
|
||||
|
||||
// Divided by 60 to get the rate per minute
|
||||
$pilot_rate = $this->getPilotPayRateForPirep($pirep) / 60;
|
||||
$payment = round($pirep->flight_time * $pilot_rate, 2);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ class FlightImporter extends ImportExport
|
||||
'flight_type' => 'required|alpha',
|
||||
'load_factor' => 'nullable',
|
||||
'load_factor_variance' => 'nullable',
|
||||
'pilot_pay' => 'nullable',
|
||||
'route' => 'nullable',
|
||||
'notes' => 'nullable',
|
||||
'active' => 'nullable|boolean',
|
||||
|
||||
@@ -67,38 +67,14 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-4">
|
||||
{{ Form::label('dpt_airport_id', 'Departure Airport:') }} <span
|
||||
class="required">*</span>
|
||||
{{ Form::select('dpt_airport_id', $airports, null , [
|
||||
'id' => 'dpt_airport_id',
|
||||
'class' => 'form-control select2'
|
||||
]) }}
|
||||
<p class="text-danger">{{ $errors->first('dpt_airport_id') }}</p>
|
||||
{{ Form::label('pilot_pay', 'Pilot Pay:') }}
|
||||
{{ Form::text('pilot_pay', null, ['class' => 'form-control']) }}
|
||||
<p class="text-danger">{{ $errors->first('pilot_pay') }}</p>
|
||||
@component('admin.components.info')
|
||||
Fill this in to pay a pilot a fixed amount for this flight.
|
||||
@endcomponent
|
||||
</div>
|
||||
|
||||
<!-- Arr Airport Id Field -->
|
||||
<div class="form-group col-sm-4">
|
||||
{{ Form::label('arr_airport_id', 'Arrival Airport:') }} <span
|
||||
class="required">*</span>
|
||||
{{ Form::select('arr_airport_id', $airports, null , [
|
||||
'id' => 'arr_airport_id',
|
||||
'class' => 'form-control select2 select2'
|
||||
]) }}
|
||||
<p class="text-danger">{{ $errors->first('arr_airport_id') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Alt Airport Id Field -->
|
||||
<div class="form-group col-sm-4">
|
||||
{{ Form::label('alt_airport_id', 'Alt Airport:') }}
|
||||
{{ Form::select('alt_airport_id', $alt_airports, null , ['class' => 'form-control select2']) }}
|
||||
<p class="text-danger">{{ $errors->first('alt_airport_id') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{-- NEXT ROW --}}
|
||||
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-4">
|
||||
{{ Form::label('load_factor', 'Load Factor:') }}
|
||||
{{ Form::text('load_factor', null, ['class' => 'form-control']) }}
|
||||
@@ -119,6 +95,66 @@
|
||||
use the default value.
|
||||
@endcomponent
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="form-container">
|
||||
<h6><i class="fas fa-map"></i>
|
||||
Route
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-6">
|
||||
{{ Form::label('dpt_airport_id', 'Departure Airport:') }} <span
|
||||
class="required">*</span>
|
||||
{{ Form::select('dpt_airport_id', $airports, null , [
|
||||
'id' => 'dpt_airport_id',
|
||||
'class' => 'form-control select2'
|
||||
]) }}
|
||||
<p class="text-danger">{{ $errors->first('dpt_airport_id') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Arr Airport Id Field -->
|
||||
<div class="form-group col-sm-6">
|
||||
{{ Form::label('arr_airport_id', 'Arrival Airport:') }} <span
|
||||
class="required">*</span>
|
||||
{{ Form::select('arr_airport_id', $airports, null , [
|
||||
'id' => 'arr_airport_id',
|
||||
'class' => 'form-control select2 select2'
|
||||
]) }}
|
||||
<p class="text-danger">{{ $errors->first('arr_airport_id') }}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- Route Field -->
|
||||
<div class="form-group col-sm-12">
|
||||
{{ Form::label('route', 'Route:') }}
|
||||
{{ Form::textarea('route', null, [
|
||||
'class' => 'form-control input-text',
|
||||
'style' => 'padding: 10px',
|
||||
]) }}
|
||||
<p class="text-danger">{{ $errors->first('route') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- Alt Airport Id Field -->
|
||||
<div class="form-group col-sm-4">
|
||||
{{ Form::label('alt_airport_id', 'Alt Airport:') }}
|
||||
{{ Form::select('alt_airport_id', $alt_airports, null , ['class' => 'form-control select2']) }}
|
||||
<p class="text-danger">{{ $errors->first('alt_airport_id') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-4">
|
||||
{{ Form::label('level', 'Flight Level:') }}
|
||||
{{ Form::text('level', null, ['class' => 'form-control']) }}
|
||||
<p class="text-danger">{{ $errors->first('level') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-4">
|
||||
{{ Form::label('distance', 'Distance:') }} <span class="description small">in nautical miles</span>
|
||||
@@ -132,6 +168,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="form-container">
|
||||
@@ -140,7 +177,6 @@
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-4">
|
||||
{{ Form::label('start_date', 'Start Date') }}
|
||||
<span class="description small">optional</span>
|
||||
@@ -207,47 +243,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="form-container">
|
||||
<h6><i class="fas fa-map"></i>
|
||||
Route
|
||||
</h6>
|
||||
<div class="form-container-body row">
|
||||
<!-- Route Field -->
|
||||
<div class="form-group col-sm-12">
|
||||
{{ Form::textarea('route', null, [
|
||||
'class' => 'form-control input-text',
|
||||
'style' => 'padding: 10px',
|
||||
]) }}
|
||||
<p class="text-danger">{{ $errors->first('route') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-container-body row">
|
||||
<div class="form-group col-sm-4">
|
||||
{{ Form::label('level', 'Flight Level:') }}
|
||||
{{ Form::text('level', null, ['class' => 'form-control']) }}
|
||||
<p class="text-danger">{{ $errors->first('level') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="form-container">
|
||||
<h6><i class="fas fa-sticky-note"></i>
|
||||
Remarks
|
||||
</h6>
|
||||
<div class="form-container-body row">
|
||||
<div class="form-group col-sm-12">
|
||||
{{ Form::textarea('notes', null, [
|
||||
'class' => 'form-control input-text',
|
||||
'style' => 'padding: 10px',
|
||||
]) }}
|
||||
<p class="text-danger">{{ $errors->first('notes') }}</p>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-12">
|
||||
{{ Form::textarea('notes', null, [
|
||||
'class' => 'form-control input-text',
|
||||
'style' => 'padding: 10px',
|
||||
]) }}
|
||||
<p class="text-danger">{{ $errors->first('notes') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -90,6 +90,7 @@ class FinanceTest extends TestCase
|
||||
'user_id' => $user->id,
|
||||
'airline_id' => $user->airline_id,
|
||||
'aircraft_id' => $subfleet['aircraft']->random(),
|
||||
'flight_id' => $flight->id,
|
||||
'source' => PirepSource::ACARS,
|
||||
'flight_time' => 120,
|
||||
'block_fuel' => 10,
|
||||
@@ -495,6 +496,47 @@ class FinanceTest extends TestCase
|
||||
$this->assertEquals($payment->getValue(), 150);
|
||||
}
|
||||
|
||||
public function testGetPirepPilotPayWithFixedPrice()
|
||||
{
|
||||
$acars_pay_rate = 100;
|
||||
|
||||
$subfleet = $this->createSubfleetWithAircraft(2);
|
||||
$rank = $this->createRank(10, [$subfleet['subfleet']->id]);
|
||||
$this->fleetSvc->addSubfleetToRank($subfleet['subfleet'], $rank, [
|
||||
'acars_pay' => $acars_pay_rate,
|
||||
]);
|
||||
|
||||
$this->user = factory(App\Models\User::class)->create([
|
||||
'rank_id' => $rank->id,
|
||||
]);
|
||||
|
||||
$flight = factory(App\Models\Flight::class)->create([
|
||||
'airline_id' => $this->user->airline_id,
|
||||
'pilot_pay' => 1000,
|
||||
]);
|
||||
|
||||
$pirep_acars = factory(App\Models\Pirep::class)->create([
|
||||
'user_id' => $this->user->id,
|
||||
'aircraft_id' => $subfleet['aircraft']->random(),
|
||||
'source' => PirepSource::ACARS,
|
||||
'flight_id' => $flight->id,
|
||||
'flight_time' => 60,
|
||||
]);
|
||||
|
||||
$payment = $this->financeSvc->getPilotPay($pirep_acars);
|
||||
$this->assertEquals(1000, $payment->getValue());
|
||||
|
||||
$pirep_acars = factory(App\Models\Pirep::class)->create([
|
||||
'user_id' => $this->user->id,
|
||||
'aircraft_id' => $subfleet['aircraft']->random(),
|
||||
'source' => PirepSource::ACARS,
|
||||
'flight_time' => 90,
|
||||
]);
|
||||
|
||||
$payment = $this->financeSvc->getPilotPay($pirep_acars);
|
||||
$this->assertEquals($payment->getValue(), 150);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
airline,flight_number,route_code,route_leg,dpt_airport,arr_airport,alt_airport,days,dpt_time,arr_time,level,distance,flight_time,flight_type,load_factor, load_factor_variance,route,notes,active,subfleets,fares,fields
|
||||
VMS,1972,,,KAUS,KJFK,KLGA,15,0810 CST,1235 EST,350,1477,207,J,85,0, 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,100,10, 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,113,,,KJFK,KAUS,KDFW,15,0810 EST,1035 CST,350,,207,J,70,2,,"Empty distance",1,A32X,Y?price=300&cost=100&capacity=130;F?price=600&cost=400;B?,Departure Gate=C41;Arrival Gate=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,load_factor, load_factor_variance,pilot_pay,route,notes,active,subfleets,fares,fields
|
||||
VMS,1972,,,KAUS,KJFK,KLGA,15,0810 CST,1235 EST,350,1477,207,J,85,0,100, 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,100,10, ,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,113,,,KJFK,KAUS,KDFW,15,0810 EST,1035 CST,350,,207,J,70,2,,,"Empty distance",1,A32X,Y?price=300&cost=100&capacity=130;F?price=600&cost=400;B?,Departure Gate=C41;Arrival Gate=2
|
||||
|
||||
|
@@ -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,load_factor, load_factor_variance,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?,
|
||||
airline,flight_number,route_code,route_leg,dpt_airport,arr_airport,alt_airport,days,dpt_time,arr_time,level,distance,flight_time,flight_type,load_factor, load_factor_variance,pilot_pay,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?,
|
||||
|
||||
|
Reference in New Issue
Block a user