Add fare type for pax/cargo/mixed flights #621 (#623)

This commit is contained in:
Nabeel S 2020-03-06 15:10:03 -05:00 committed by GitHub
parent 9f3ddd5dbd
commit 632c5782de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 150 additions and 46 deletions

View File

@ -0,0 +1,34 @@
<?php
use App\Models\Enums\FareType;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class FaresAddType extends Migration
{
/**
* Add a `pilot_pay` column for a fixed amount to pay to a pilot for a flight
*/
public function up()
{
Schema::table('fares', function (Blueprint $table) {
$table->unsignedTinyInteger('type')
->default(FareType::PASSENGER)
->nullable()
->after('capacity');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('fares', function (Blueprint $table) {
$table->dropColumn('type');
});
}
}

View File

@ -6,6 +6,7 @@ use App\Contracts\Controller;
use App\Http\Controllers\Admin\Traits\Importable; use App\Http\Controllers\Admin\Traits\Importable;
use App\Http\Requests\CreateFareRequest; use App\Http\Requests\CreateFareRequest;
use App\Http\Requests\UpdateFareRequest; use App\Http\Requests\UpdateFareRequest;
use App\Models\Enums\FareType;
use App\Models\Enums\ImportExportType; use App\Models\Enums\ImportExportType;
use App\Repositories\FareRepository; use App\Repositories\FareRepository;
use App\Services\ExportService; use App\Services\ExportService;
@ -58,7 +59,9 @@ class FareController extends Controller
*/ */
public function create() public function create()
{ {
return view('admin.fares.create'); return view('admin.fares.create', [
'fare_types' => FareType::select(),
]);
} }
/** /**
@ -94,7 +97,9 @@ class FareController extends Controller
return redirect(route('admin.fares.index')); return redirect(route('admin.fares.index'));
} }
return view('admin.fares.show')->with('fare', $fare); return view('admin.fares.show', [
'fare' => $fare,
]);
} }
/** /**
@ -112,7 +117,10 @@ class FareController extends Controller
return redirect(route('admin.fares.index')); return redirect(route('admin.fares.index'));
} }
return view('admin.fares.edit')->with('fare', $fare); return view('admin.fares.edit', [
'fare' => $fare,
'fare_types' => FareType::select(),
]);
} }
/** /**

View File

@ -7,6 +7,7 @@ use App\Http\Controllers\Admin\Traits\Importable;
use App\Http\Requests\CreateSubfleetRequest; use App\Http\Requests\CreateSubfleetRequest;
use App\Http\Requests\UpdateSubfleetRequest; use App\Http\Requests\UpdateSubfleetRequest;
use App\Models\Airline; use App\Models\Airline;
use App\Models\Enums\FareType;
use App\Models\Enums\FuelType; use App\Models\Enums\FuelType;
use App\Models\Enums\ImportExportType; use App\Models\Enums\ImportExportType;
use App\Models\Expense; use App\Models\Expense;
@ -98,6 +99,7 @@ class SubfleetController extends Controller
foreach ($avail_fares as $fare) { foreach ($avail_fares as $fare) {
$retval[$fare->id] = $fare->name. $retval[$fare->id] = $fare->name.
' (price: '.$fare->price. ' (price: '.$fare->price.
', type: '.FareType::label($fare->type).
', cost: '.$fare->cost. ', cost: '.$fare->cost.
', capacity: '.$fare->capacity.')'; ', capacity: '.$fare->capacity.')';
} }
@ -162,7 +164,9 @@ class SubfleetController extends Controller
*/ */
public function show($id) public function show($id)
{ {
$subfleet = $this->subfleetRepo->findWithoutFail($id); $subfleet = $this->subfleetRepo
->with(['fares'])
->findWithoutFail($id);
if (empty($subfleet)) { if (empty($subfleet)) {
Flash::error('Subfleet not found'); Flash::error('Subfleet not found');
@ -185,7 +189,9 @@ class SubfleetController extends Controller
*/ */
public function edit($id) public function edit($id)
{ {
$subfleet = $this->subfleetRepo->findWithoutFail($id); $subfleet = $this->subfleetRepo
->with(['fares', 'ranks'])
->findWithoutFail($id);
if (empty($subfleet)) { if (empty($subfleet)) {
Flash::error('Subfleet not found'); Flash::error('Subfleet not found');

View File

@ -18,6 +18,7 @@ class Fare extends Resource
'price' => $this->price, 'price' => $this->price,
'cost' => $this->cost, 'cost' => $this->cost,
'capacity' => $this->capacity, 'capacity' => $this->capacity,
'type' => $this->type,
'notes' => $this->notes, 'notes' => $this->notes,
'active' => $this->active, 'active' => $this->active,
]; ];

View File

@ -0,0 +1,16 @@
<?php
namespace App\Models\Enums;
use App\Contracts\Enum;
class FareType extends Enum
{
public const PASSENGER = 0;
public const CARGO = 1;
public static $labels = [
self::PASSENGER => 'Passenger',
self::CARGO => 'Cargo',
];
}

View File

@ -78,4 +78,9 @@ class Expense extends Model
{ {
return $this->belongsTo(Airline::class, 'airline_id'); return $this->belongsTo(Airline::class, 'airline_id');
} }
public function ref_model()
{
return $this->morphTo();
}
} }

View File

@ -11,6 +11,7 @@ use App\Contracts\Model;
* @property int code * @property int code
* @property int capacity * @property int capacity
* @property int count Only when merged with pivot * @property int count Only when merged with pivot
* @property int type
* @property string notes * @property string notes
* @property bool active * @property bool active
*/ */
@ -32,12 +33,14 @@ class Fare extends Model
'price' => 'float', 'price' => 'float',
'cost' => 'float', 'cost' => 'float',
'capacity' => 'integer', 'capacity' => 'integer',
'type' => 'integer',
'active' => 'boolean', 'active' => 'boolean',
]; ];
public static $rules = [ public static $rules = [
'code' => 'required', 'code' => 'required',
'name' => 'required', 'name' => 'required',
'type' => 'required',
]; ];
/** /**

View File

@ -7,6 +7,7 @@ use App\Events\Expenses as ExpensesEvent;
use App\Models\Aircraft; use App\Models\Aircraft;
use App\Models\Airport; use App\Models\Airport;
use App\Models\Enums\ExpenseType; use App\Models\Enums\ExpenseType;
use App\Models\Enums\FareType;
use App\Models\Enums\PirepSource; use App\Models\Enums\PirepSource;
use App\Models\Expense; use App\Models\Expense;
use App\Models\Pirep; use App\Models\Pirep;
@ -124,13 +125,15 @@ class PirepFinanceService extends Service
Log::info('Finance: Calculate: C='.$credit->toAmount().', D='.$debit->toAmount()); Log::info('Finance: Calculate: C='.$credit->toAmount().', D='.$debit->toAmount());
$memo = FareType::label($fare->type).' fare: '.$fare->code.$fare->count
.'; price: '.$fare->price.', cost: '.$fare->cost;
$this->journalRepo->post( $this->journalRepo->post(
$pirep->airline->journal, $pirep->airline->journal,
$credit, $credit,
$debit, $debit,
$pirep, $pirep,
'Fares '.$fare->code.$fare->count $memo,
.'; price: '.$fare->price.', cost: '.$fare->cost,
null, null,
'Fares', 'Fares',
'fare' 'fare'

View File

@ -9,7 +9,7 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="form-group col-sm-6"> <div class="form-group col-sm-4">
{{ Form::label('code', 'Code:') }}&nbsp;<span class="required">*</span> {{ Form::label('code', 'Code:') }}&nbsp;<span class="required">*</span>
@component('admin.components.info') @component('admin.components.info')
How this fare class will show up on a ticket How this fare class will show up on a ticket
@ -18,7 +18,7 @@
<p class="text-danger">{{ $errors->first('code') }}</p> <p class="text-danger">{{ $errors->first('code') }}</p>
</div> </div>
<div class="form-group col-sm-6"> <div class="form-group col-sm-4">
{{ Form::label('name', 'Name:') }}&nbsp;<span class="required">*</span> {{ Form::label('name', 'Name:') }}&nbsp;<span class="required">*</span>
@component('admin.components.info') @component('admin.components.info')
The fare class name, E.g, "Economy" or "First" The fare class name, E.g, "Economy" or "First"
@ -27,10 +27,25 @@
<p class="text-danger">{{ $errors->first('name') }}</p> <p class="text-danger">{{ $errors->first('name') }}</p>
</div> </div>
<div class="form-group col-sm-4">
{{ Form::label('type', 'Fare Type:') }}&nbsp;<span class="required">*</span>
@component('admin.components.info')
If this is a passenger or cargo fare
@endcomponent
{{ Form::select('type', $fare_types, null , [
'id' => 'type',
'class' => 'form-control select2'
]) }}
<p class="text-danger">{{ $errors->first('type') }}</p>
</div>
</div>
<div class="row">
<div class="form-group col-sm-6"> <div class="form-group col-sm-6">
{{ Form::label('price', 'Price:') }} {{ Form::label('price', 'Price:') }}
@component('admin.components.info') @component('admin.components.info')
This is the price of a ticket for a passenger This is the price of a ticket or price per {{ setting('units.weight') }}
@endcomponent @endcomponent
{{ Form::text('price', null, ['class' => 'form-control', 'placeholder' => 0]) }} {{ Form::text('price', null, ['class' => 'form-control', 'placeholder' => 0]) }}
<p class="text-danger">{{ $errors->first('price') }}</p> <p class="text-danger">{{ $errors->first('price') }}</p>
@ -39,16 +54,17 @@
<div class="form-group col-sm-6"> <div class="form-group col-sm-6">
{{ Form::label('cost', 'Cost:') }} {{ Form::label('cost', 'Cost:') }}
@component('admin.components.info') @component('admin.components.info')
The operating cost The operating cost per unit (passenger or {{ setting('units.weight') }})
@endcomponent @endcomponent
{{ Form::number('cost', null, ['class' => 'form-control', 'placeholder' => 0, 'step' => '0.01']) }} {{ Form::number('cost', null, ['class' => 'form-control', 'placeholder' => 0, 'step' => '0.01']) }}
<p class="text-danger">{{ $errors->first('cost') }}</p> <p class="text-danger">{{ $errors->first('cost') }}</p>
</div> </div>
</div>
<div class="row">
<div class="form-group col-sm-6"> <div class="form-group col-sm-6">
{{ Form::label('capacity', 'Capacity:') }} {{ Form::label('capacity', 'Capacity:') }}
@component('admin.components.info') @component('admin.components.info')
The number of seats available in this class. Max seats or capacity available. This can be adjusted in the subfleet
@endcomponent @endcomponent
{{ Form::number('capacity', null, ['class' => 'form-control', 'min' => 0]) }} {{ Form::number('capacity', null, ['class' => 'form-control', 'min' => 0]) }}
<p class="text-danger">{{ $errors->first('capacity') }}</p> <p class="text-danger">{{ $errors->first('capacity') }}</p>
@ -56,10 +72,15 @@
<div class="form-group col-sm-6"> <div class="form-group col-sm-6">
{{ Form::label('notes', 'Notes:') }} {{ Form::label('notes', 'Notes:') }}
@component('admin.components.info')
Notes for this fare
@endcomponent
{{ Form::text('notes', null, ['class' => 'form-control']) }} {{ Form::text('notes', null, ['class' => 'form-control']) }}
<p class="text-danger">{{ $errors->first('notes') }}</p> <p class="text-danger">{{ $errors->first('notes') }}</p>
</div> </div>
</div>
<div class="row">
<!-- Active Field --> <!-- Active Field -->
<div class="form-group col-sm-12"> <div class="form-group col-sm-12">
{{ Form::label('active', 'Active:') }} {{ Form::label('active', 'Active:') }}
@ -68,7 +89,8 @@
{{ Form::checkbox('active', 1, null) }} {{ Form::checkbox('active', 1, null) }}
</label> </label>
</div> </div>
</div>
<div class="row">
<!-- Submit Field --> <!-- Submit Field -->
<div class="form-group col-sm-12"> <div class="form-group col-sm-12">
<div class="pull-right"> <div class="pull-right">

View File

@ -14,6 +14,7 @@
<tr> <tr>
<th>Name</th> <th>Name</th>
<th style="text-align: center;">Code</th> <th style="text-align: center;">Code</th>
<th style="text-align: center;">Type</th>
<th style="text-align: center;">Capacity (default)</th> <th style="text-align: center;">Capacity (default)</th>
<th style="text-align: center;">Price (default)</th> <th style="text-align: center;">Price (default)</th>
<th style="text-align: center;">Cost (default)</th> <th style="text-align: center;">Cost (default)</th>
@ -24,16 +25,17 @@
<tbody> <tbody>
@foreach($subfleet->fares as $atf) @foreach($subfleet->fares as $atf)
<tr> <tr>
<td class="sorting_1">{{ $atf->name }}</td> <td class="sorting_1 text-center">{{ $atf->name }}</td>
<td style="text-align: center;">{{ $atf->code }}</td> <td class="text-center">{{ $atf->code }}</td>
<td style="text-align: center;"> <td class="sorting_1 text-center">{{ \App\Models\Enums\FareType::label($atf->type) }}</td>
<td class="text-center">
<a href="#" data-pk="{{ $atf->id }}" data-name="capacity">{{ $atf->pivot->capacity }}</a> <a href="#" data-pk="{{ $atf->id }}" data-name="capacity">{{ $atf->pivot->capacity }}</a>
<span class="small background-color-grey-light">({{ $atf->capacity }})</span> <span class="small background-color-grey-light">({{ $atf->capacity }})</span>
</td> </td>
<td style="text-align: center;"> <td class="text-center">
<a href="#" data-pk="{{ $atf->id }}" data-name="price">{{ $atf->pivot->price }}</a> <a href="#" data-pk="{{ $atf->id }}" data-name="price">{{ $atf->pivot->price }}</a>
<span class="small background-color-grey-light">({{ $atf->price }})</span></td> <span class="small background-color-grey-light">({{ $atf->price }})</span></td>
<td style="text-align: center;"> <td class="text-center">
<a href="#" data-pk="{{ $atf->id }}" data-name="cost">{{ $atf->pivot->cost }}</a> <a href="#" data-pk="{{ $atf->id }}" data-name="cost">{{ $atf->pivot->cost }}</a>
<span class="small background-color-grey-light">({{ $atf->cost}})</span></td> <span class="small background-color-grey-light">({{ $atf->cost}})</span></td>
<td style="text-align: right; width:3%;"> <td style="text-align: right; width:3%;">

View File

@ -1,32 +1,36 @@
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-12">
@component('admin.components.info') <div class="row">
Subfleets are aircraft groups. The "type" is a short name. Airlines always <div class="col-sm-12">
group aircraft together by feature, so 737s with winglets might have a type of @component('admin.components.info')
"B.738-WL". You can create as many as you want, you need at least one, though. Subfleets are aircraft groups. The "type" is a short name. Airlines always
group aircraft together by feature, so 737s with winglets might have a type of
"B.738-WL". You can create as many as you want, you need at least one, though.
Read more about subfleets <a href="{{ docs_link('finances') }}" target="_new">here</a>. Read more about subfleets <a href="{{ docs_link('finances') }}" target="_new">here</a>.
@endcomponent @endcomponent
</div>
</div>
<div class="row">
<div class="form-group col-sm-4">
{{ Form::label('airline_id', 'Airline:') }}
{{ Form::select('airline_id', $airlines, null , ['class' => 'form-control select2']) }}
<p class="text-danger">{{ $errors->first('airline_id') }}</p>
</div>
<div class="form-group col-sm-4">
{{ Form::label('type', 'Type:') }}
{{ Form::text('type', null, ['class' => 'form-control']) }}
<p class="text-danger">{{ $errors->first('type') }}</p>
</div>
<div class="form-group col-sm-4">
{{ Form::label('name', 'Name:') }}
{{ Form::text('name', null, ['class' => 'form-control']) }}
<p class="text-danger">{{ $errors->first('name') }}</p>
</div>
</div>
</div> </div>
<div class="form-group col-sm-4">
{{ Form::label('airline_id', 'Airline:') }}
{{ Form::select('airline_id', $airlines, null , ['class' => 'form-control select2']) }}
<p class="text-danger">{{ $errors->first('airline_id') }}</p>
</div>
<div class="form-group col-sm-4">
{{ Form::label('type', 'Type:') }}
{{ Form::text('type', null, ['class' => 'form-control']) }}
<p class="text-danger">{{ $errors->first('type') }}</p>
</div>
<div class="form-group col-sm-4">
{{ Form::label('name', 'Name:') }}
{{ Form::text('name', null, ['class' => 'form-control']) }}
<p class="text-danger">{{ $errors->first('name') }}</p>
</div>
</div> </div>
<div class="row"> <div class="row">

View File

@ -7,7 +7,7 @@
@foreach($aircraft->subfleet->fares as $fare) @foreach($aircraft->subfleet->fares as $fare)
<div class="row"> <div class="row">
<div class="col"> <div class="col">
{{Form::label('fare_'.$fare->id, $fare->name.' ('.$fare->code.')')}} {{Form::label('fare_'.$fare->id, $fare->name.' ('. \App\Models\Enums\FareType::label($fare->type).', code '.$fare->code.')')}}
<div class="input-group form-group"> <div class="input-group form-group">
{{ Form::number('fare_'.$fare->id, null, ['class' => 'form-control', 'min' => 0]) }} {{ Form::number('fare_'.$fare->id, null, ['class' => 'form-control', 'min' => 0]) }}
</div> </div>