* Add flight_id column to pireps table * Refactor PIREPs and bids closes 406 * Formatting
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Enums\PirepSource;
|
||||
use App\Models\Enums\PirepState;
|
||||
use App\Models\Enums\PirepStatus;
|
||||
use Carbon\Carbon;
|
||||
use Faker\Generator as Faker;
|
||||
|
||||
@@ -7,10 +10,15 @@ use Faker\Generator as Faker;
|
||||
* Create a new PIREP
|
||||
*/
|
||||
$factory->define(App\Models\Pirep::class, function (Faker $faker) {
|
||||
$airline = factory(App\Models\Airline::class)->create();
|
||||
$flight = factory(App\Models\Flight::class)->create([
|
||||
'airline_id' => $airline->id,
|
||||
]);
|
||||
|
||||
return [
|
||||
'id' => $faker->unique()->numberBetween(10, 10000000),
|
||||
'airline_id' => function () {
|
||||
return factory(App\Models\Airline::class)->create()->id;
|
||||
'airline_id' => function () use ($airline) {
|
||||
return $airline->id;
|
||||
},
|
||||
'user_id' => function () {
|
||||
return factory(App\Models\User::class)->create()->id;
|
||||
@@ -18,18 +26,19 @@ $factory->define(App\Models\Pirep::class, function (Faker $faker) {
|
||||
'aircraft_id' => function () {
|
||||
return factory(App\Models\Aircraft::class)->create()->id;
|
||||
},
|
||||
'flight_number' => function (array $pirep) {
|
||||
return factory(App\Models\Flight::class)->create([
|
||||
'airline_id' => $pirep['airline_id'],
|
||||
])->flight_number;
|
||||
'flight_id' => function () use ($flight) {
|
||||
return $flight->id;
|
||||
},
|
||||
'flight_number' => function () use ($flight) {
|
||||
return $flight->flight_number;
|
||||
},
|
||||
'route_code' => null,
|
||||
'route_leg' => null,
|
||||
'dpt_airport_id' => function () {
|
||||
return factory(App\Models\Airport::class)->create()->id;
|
||||
'dpt_airport_id' => function () use ($flight) {
|
||||
return $flight->dpt_airport_id;
|
||||
},
|
||||
'arr_airport_id' => function () {
|
||||
return factory(App\Models\Airport::class)->create()->id;
|
||||
'arr_airport_id' => function () use ($flight) {
|
||||
return $flight->arr_airport_id;
|
||||
},
|
||||
'level' => $faker->numberBetween(20, 400),
|
||||
'distance' => $faker->randomFloat(2, 0, 6000),
|
||||
@@ -48,7 +57,7 @@ $factory->define(App\Models\Pirep::class, function (Faker $faker) {
|
||||
'route' => $faker->text(200),
|
||||
'notes' => $faker->text(200),
|
||||
'source' => $faker->randomElement([PirepSource::MANUAL, PirepSource::ACARS]),
|
||||
'source_name' => 'Test Factory',
|
||||
'source_name' => 'TestFactory',
|
||||
'state' => PirepState::PENDING,
|
||||
'status' => PirepStatus::SCHEDULED,
|
||||
'submitted_at' => Carbon::now('UTC')->toDateTimeString(),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Contracts\Migration;
|
||||
use App\Contracts\Model;
|
||||
use App\Models\Enums\FlightType;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
@@ -14,7 +15,7 @@ class CreateFlightTables extends Migration
|
||||
public function up()
|
||||
{
|
||||
Schema::create('flights', function (Blueprint $table) {
|
||||
$table->string('id', \App\Contracts\Model::ID_MAX_LENGTH);
|
||||
$table->string('id', Model::ID_MAX_LENGTH);
|
||||
$table->unsignedInteger('airline_id');
|
||||
$table->unsignedInteger('flight_number');
|
||||
$table->string('route_code', 5)->nullable();
|
||||
@@ -47,7 +48,7 @@ class CreateFlightTables extends Migration
|
||||
});
|
||||
|
||||
Schema::create('flight_fare', function (Blueprint $table) {
|
||||
$table->string('flight_id', \App\Contracts\Model::ID_MAX_LENGTH);
|
||||
$table->string('flight_id', Model::ID_MAX_LENGTH);
|
||||
$table->unsignedInteger('fare_id');
|
||||
$table->string('price', 10)->nullable();
|
||||
$table->string('cost', 10)->nullable();
|
||||
@@ -71,7 +72,7 @@ class CreateFlightTables extends Migration
|
||||
*/
|
||||
Schema::create('flight_field_values', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('flight_id', \App\Contracts\Model::ID_MAX_LENGTH);
|
||||
$table->string('flight_id', Model::ID_MAX_LENGTH);
|
||||
$table->string('name', 50);
|
||||
$table->string('slug', 50)->nullable();
|
||||
$table->text('value');
|
||||
@@ -83,7 +84,7 @@ class CreateFlightTables extends Migration
|
||||
Schema::create('flight_subfleet', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedInteger('subfleet_id');
|
||||
$table->string('flight_id', \App\Contracts\Model::ID_MAX_LENGTH);
|
||||
$table->string('flight_id', Model::ID_MAX_LENGTH);
|
||||
|
||||
$table->index(['subfleet_id', 'flight_id']);
|
||||
$table->index(['flight_id', 'subfleet_id']);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Contracts\Migration;
|
||||
use App\Contracts\Model;
|
||||
use App\Models\Enums\FlightType;
|
||||
use App\Models\Enums\PirepState;
|
||||
use App\Models\Enums\PirepStatus;
|
||||
@@ -16,7 +17,7 @@ class CreatePirepTables extends Migration
|
||||
public function up()
|
||||
{
|
||||
Schema::create('pireps', function (Blueprint $table) {
|
||||
$table->string('id', \App\Contracts\Model::ID_MAX_LENGTH);
|
||||
$table->string('id', Model::ID_MAX_LENGTH);
|
||||
$table->unsignedInteger('user_id');
|
||||
$table->unsignedInteger('airline_id');
|
||||
$table->unsignedInteger('aircraft_id')->nullable();
|
||||
@@ -57,7 +58,7 @@ class CreatePirepTables extends Migration
|
||||
|
||||
Schema::create('pirep_comments', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('pirep_id', \App\Contracts\Model::ID_MAX_LENGTH);
|
||||
$table->string('pirep_id', Model::ID_MAX_LENGTH);
|
||||
$table->unsignedInteger('user_id');
|
||||
$table->text('comment');
|
||||
$table->timestamps();
|
||||
@@ -65,7 +66,7 @@ class CreatePirepTables extends Migration
|
||||
|
||||
Schema::create('pirep_fares', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('pirep_id', \App\Contracts\Model::ID_MAX_LENGTH);
|
||||
$table->string('pirep_id', Model::ID_MAX_LENGTH);
|
||||
$table->unsignedInteger('fare_id');
|
||||
$table->unsignedInteger('count')->nullable()->default(0);
|
||||
|
||||
@@ -81,7 +82,7 @@ class CreatePirepTables extends Migration
|
||||
|
||||
Schema::create('pirep_field_values', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('pirep_id', \App\Contracts\Model::ID_MAX_LENGTH);
|
||||
$table->string('pirep_id', Model::ID_MAX_LENGTH);
|
||||
$table->string('name', 50);
|
||||
$table->string('slug', 50)->nullable();
|
||||
$table->string('value')->nullable();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Contracts\Migration;
|
||||
use App\Contracts\Model;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
@@ -16,7 +17,7 @@ class CreateBidsTable extends Migration
|
||||
Schema::create('bids', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->unsignedInteger('user_id');
|
||||
$table->string('flight_id', \App\Contracts\Model::ID_MAX_LENGTH);
|
||||
$table->string('flight_id', Model::ID_MAX_LENGTH);
|
||||
$table->timestamps();
|
||||
|
||||
$table->index('user_id');
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use App\Contracts\Model;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class PirepsAddFlightId extends Migration
|
||||
{
|
||||
/**
|
||||
* Add a `flight_id` column to the PIREPs table
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('pireps', function (Blueprint $table) {
|
||||
$table->string('flight_id', Model::ID_MAX_LENGTH)->nullable()->after('aircraft_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('pireps', function (Blueprint $table) {
|
||||
$table->dropColumn('flight_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
45
app/Exceptions/UserBidLimit.php
Normal file
45
app/Exceptions/UserBidLimit.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
class UserBidLimit extends HttpException
|
||||
{
|
||||
private $user;
|
||||
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
parent::__construct(
|
||||
409,
|
||||
'User '.$user->ident.' has the maximum number of bids'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the RFC 7807 error type (without the URL root)
|
||||
*/
|
||||
public function getErrorType(): string
|
||||
{
|
||||
return 'user-bid-limit';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the detailed error string
|
||||
*/
|
||||
public function getErrorDetails(): string
|
||||
{
|
||||
return $this->getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array with the error details, merged with the RFC7807 response
|
||||
*/
|
||||
public function getErrorMetadata(): array
|
||||
{
|
||||
return [
|
||||
'user_id' => $this->user->id,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@ use App\Http\Resources\Navdata as NavdataResource;
|
||||
use App\Repositories\Criteria\WhereCriteria;
|
||||
use App\Repositories\FlightRepository;
|
||||
use App\Services\FlightService;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Prettus\Repository\Criteria\RequestCriteria;
|
||||
use Prettus\Repository\Exceptions\RepositoryException;
|
||||
|
||||
@@ -44,6 +44,9 @@ class FlightController extends Controller
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/**
|
||||
* @var $user \App\Models\User
|
||||
*/
|
||||
$user = Auth::user();
|
||||
|
||||
$where = [
|
||||
@@ -52,7 +55,7 @@ class FlightController extends Controller
|
||||
];
|
||||
|
||||
if (setting('pilots.restrict_to_company')) {
|
||||
$where['airline_id'] = Auth::user()->airline_id;
|
||||
$where['airline_id'] = $user->airline_id;
|
||||
}
|
||||
if (setting('pilots.only_flights_from_current', false)) {
|
||||
$where['dpt_airport_id'] = $user->curr_airport_id;
|
||||
|
||||
@@ -20,6 +20,7 @@ use App\Http\Resources\PirepComment as PirepCommentResource;
|
||||
use App\Http\Resources\PirepFieldCollection;
|
||||
use App\Models\Acars;
|
||||
use App\Models\Enums\AcarsType;
|
||||
use App\Models\Enums\FlightType;
|
||||
use App\Models\Enums\PirepFieldSource;
|
||||
use App\Models\Enums\PirepSource;
|
||||
use App\Models\Enums\PirepState;
|
||||
@@ -93,6 +94,10 @@ class PirepController extends Controller
|
||||
$attrs['created_at'] = Carbon::createFromTimeString($attrs['created_at']);
|
||||
}
|
||||
|
||||
if (array_key_exists('updated_at', $attrs)) {
|
||||
$attrs['updated_at'] = Carbon::createFromTimeString($attrs['updated_at']);
|
||||
}
|
||||
|
||||
return $attrs;
|
||||
}
|
||||
|
||||
@@ -186,6 +191,9 @@ class PirepController extends Controller
|
||||
{
|
||||
Log::info('PIREP Prefile, user '.Auth::id(), $request->post());
|
||||
|
||||
/**
|
||||
* @var $user \App\Models\User
|
||||
*/
|
||||
$user = Auth::user();
|
||||
|
||||
$attrs = $this->parsePirep($request);
|
||||
@@ -228,7 +236,7 @@ class PirepController extends Controller
|
||||
|
||||
// Default to a scheduled passenger flight
|
||||
if (!array_key_exists('flight_type', $attrs)) {
|
||||
$attrs['flight_type'] = 'J';
|
||||
$attrs['flight_type'] = FlightType::SCHED_PAX;
|
||||
}
|
||||
|
||||
$pirep->save();
|
||||
|
||||
@@ -13,18 +13,17 @@ use App\Repositories\Criteria\WhereCriteria;
|
||||
use App\Repositories\FlightRepository;
|
||||
use App\Repositories\PirepRepository;
|
||||
use App\Repositories\UserRepository;
|
||||
use App\Services\BidService;
|
||||
use App\Services\FlightService;
|
||||
use App\Services\UserService;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Prettus\Repository\Criteria\RequestCriteria;
|
||||
use Prettus\Repository\Exceptions\RepositoryException;
|
||||
|
||||
/**
|
||||
* Class UserController
|
||||
*/
|
||||
class UserController extends Controller
|
||||
{
|
||||
private $bidSvc;
|
||||
private $flightRepo;
|
||||
private $flightSvc;
|
||||
private $pirepRepo;
|
||||
@@ -32,8 +31,7 @@ class UserController extends Controller
|
||||
private $userSvc;
|
||||
|
||||
/**
|
||||
* UserController constructor.
|
||||
*
|
||||
* @param BidService $bidSvc
|
||||
* @param FlightRepository $flightRepo
|
||||
* @param FlightService $flightSvc
|
||||
* @param PirepRepository $pirepRepo
|
||||
@@ -41,12 +39,14 @@ class UserController extends Controller
|
||||
* @param UserService $userSvc
|
||||
*/
|
||||
public function __construct(
|
||||
BidService $bidSvc,
|
||||
FlightRepository $flightRepo,
|
||||
FlightService $flightSvc,
|
||||
PirepRepository $pirepRepo,
|
||||
UserRepository $userRepo,
|
||||
UserService $userSvc
|
||||
) {
|
||||
$this->bidSvc = $bidSvc;
|
||||
$this->flightRepo = $flightRepo;
|
||||
$this->flightSvc = $flightSvc;
|
||||
$this->pirepRepo = $pirepRepo;
|
||||
@@ -61,11 +61,11 @@ class UserController extends Controller
|
||||
*/
|
||||
protected function getUserId(Request $request)
|
||||
{
|
||||
if ($request->id === null) {
|
||||
if ($request->get('id') === null) {
|
||||
return Auth::user()->id;
|
||||
}
|
||||
|
||||
return $request->id;
|
||||
return $request->get('id');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +110,7 @@ class UserController extends Controller
|
||||
if ($request->isMethod('PUT') || $request->isMethod('POST')) {
|
||||
$flight_id = $request->input('flight_id');
|
||||
$flight = $this->flightRepo->find($flight_id);
|
||||
$bid = $this->flightSvc->addBid($flight, $user);
|
||||
$bid = $this->bidSvc->addBid($flight, $user);
|
||||
|
||||
return new BidResource($bid);
|
||||
}
|
||||
@@ -124,11 +124,11 @@ class UserController extends Controller
|
||||
}
|
||||
|
||||
$flight = $this->flightRepo->find($flight_id);
|
||||
$this->flightSvc->removeBid($flight, $user);
|
||||
$this->bidSvc->removeBid($flight, $user);
|
||||
}
|
||||
|
||||
// Return the flights they currently have bids on
|
||||
$bids = Bid::where(['user_id' => $user->id])->get();
|
||||
$bids = $this->bidSvc->findBidsForUser($user);
|
||||
|
||||
return BidResource::collection($bids);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ use App\Repositories\AircraftRepository;
|
||||
use App\Repositories\AirlineRepository;
|
||||
use App\Repositories\AirportRepository;
|
||||
use App\Repositories\Criteria\WhereCriteria;
|
||||
use App\Repositories\FlightRepository;
|
||||
use App\Repositories\PirepFieldRepository;
|
||||
use App\Repositories\PirepRepository;
|
||||
use App\Services\FareService;
|
||||
@@ -35,6 +36,7 @@ class PirepController extends Controller
|
||||
private $aircraftRepo;
|
||||
private $airlineRepo;
|
||||
private $fareSvc;
|
||||
private $flightRepo;
|
||||
private $geoSvc;
|
||||
private $pirepRepo;
|
||||
private $airportRepo;
|
||||
@@ -43,12 +45,11 @@ class PirepController extends Controller
|
||||
private $userSvc;
|
||||
|
||||
/**
|
||||
* PirepController constructor.
|
||||
*
|
||||
* @param AircraftRepository $aircraftRepo
|
||||
* @param AirlineRepository $airlineRepo
|
||||
* @param AirportRepository $airportRepo
|
||||
* @param FareService $fareSvc
|
||||
* @param FlightRepository $flightRepo
|
||||
* @param GeoService $geoSvc
|
||||
* @param PirepRepository $pirepRepo
|
||||
* @param PirepFieldRepository $pirepFieldRepo
|
||||
@@ -60,6 +61,7 @@ class PirepController extends Controller
|
||||
AirlineRepository $airlineRepo,
|
||||
AirportRepository $airportRepo,
|
||||
FareService $fareSvc,
|
||||
FlightRepository $flightRepo,
|
||||
GeoService $geoSvc,
|
||||
PirepRepository $pirepRepo,
|
||||
PirepFieldRepository $pirepFieldRepo,
|
||||
@@ -73,6 +75,7 @@ class PirepController extends Controller
|
||||
$this->pirepFieldRepo = $pirepFieldRepo;
|
||||
|
||||
$this->fareSvc = $fareSvc;
|
||||
$this->flightRepo = $flightRepo;
|
||||
$this->geoSvc = $geoSvc;
|
||||
$this->pirepSvc = $pirepSvc;
|
||||
$this->userSvc = $userSvc;
|
||||
@@ -231,12 +234,24 @@ class PirepController extends Controller
|
||||
/**
|
||||
* Create a new flight report
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function create()
|
||||
public function create(Request $request)
|
||||
{
|
||||
$pirep = null;
|
||||
|
||||
// See if request has a ?flight_id, so we can pre-populate the fields from the flight
|
||||
// Makes filing easier, but we can also more easily find a bid and close it
|
||||
if ($request->has('flight_id')) {
|
||||
$flight = $this->flightRepo->find($request->get('flight_id'));
|
||||
$pirep = Pirep::fromFlight($flight);
|
||||
}
|
||||
|
||||
return view('pireps.create', [
|
||||
'aircraft' => null,
|
||||
'pirep' => $pirep,
|
||||
'read_only' => false,
|
||||
'airline_list' => $this->airlineRepo->selectBoxList(true),
|
||||
'aircraft_list' => $this->aircraftList(true),
|
||||
|
||||
@@ -4,9 +4,6 @@ namespace App\Http\Requests\Acars;
|
||||
|
||||
use App\Contracts\FormRequest;
|
||||
|
||||
/**
|
||||
* Class CommentRequest
|
||||
*/
|
||||
class CommentRequest extends FormRequest
|
||||
{
|
||||
public function rules(): array
|
||||
|
||||
@@ -4,25 +4,17 @@ namespace App\Http\Requests\Acars;
|
||||
|
||||
use App\Contracts\FormRequest;
|
||||
use App\Models\Pirep;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* Class EventRequest
|
||||
*/
|
||||
class EventRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
$pirep = Pirep::findOrFail($this->route('pirep_id'), ['user_id']);
|
||||
return $pirep->user_id === Auth::id();
|
||||
}
|
||||
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'events' => 'required|array',
|
||||
|
||||
@@ -9,10 +9,7 @@ use App\Contracts\FormRequest;
|
||||
*/
|
||||
class FieldsRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'fields' => 'required|array',
|
||||
|
||||
@@ -4,26 +4,22 @@ namespace App\Http\Requests\Acars;
|
||||
|
||||
use App\Contracts\FormRequest;
|
||||
use App\Models\Pirep;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* Class FileRequest
|
||||
*/
|
||||
class FileRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
$pirep = Pirep::findOrFail($this->route('pirep_id'), ['user_id']);
|
||||
return $pirep->user_id === Auth::id();
|
||||
}
|
||||
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'distance' => 'required|numeric',
|
||||
'flight_time' => 'required|integer',
|
||||
'fuel_used' => 'required|numeric',
|
||||
|
||||
'distance' => 'required|numeric',
|
||||
'flight_time' => 'required|integer',
|
||||
'fuel_used' => 'required|numeric',
|
||||
'block_time' => 'nullable|integer',
|
||||
'airline_id' => 'nullable|exists:airlines,id',
|
||||
'aircraft_id' => 'nullable|exists:aircraft,id',
|
||||
|
||||
@@ -4,20 +4,17 @@ namespace App\Http\Requests\Acars;
|
||||
|
||||
use App\Contracts\FormRequest;
|
||||
use App\Models\Pirep;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* Class LogRequest
|
||||
*/
|
||||
class LogRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
$pirep = Pirep::findOrFail($this->route('pirep_id'), ['user_id']);
|
||||
return $pirep->user_id === Auth::id();
|
||||
}
|
||||
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'logs' => 'required|array',
|
||||
|
||||
@@ -4,36 +4,20 @@ namespace App\Http\Requests\Acars;
|
||||
|
||||
use App\Contracts\FormRequest;
|
||||
use App\Models\Pirep;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* Class PositionRequest
|
||||
*/
|
||||
class PositionRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
* Is the user allowed to do this?
|
||||
*/
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
$pirep = Pirep::findOrFail($this->route('pirep_id'), ['user_id']);
|
||||
return $pirep->user_id === Auth::id();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
/*public function sanitize()
|
||||
{
|
||||
return [
|
||||
'positions.*.sim_time' => Acars::$sanitize['sim_time'],
|
||||
];
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'positions' => 'required|array',
|
||||
|
||||
@@ -4,32 +4,18 @@ namespace App\Http\Requests\Acars;
|
||||
|
||||
use App\Contracts\FormRequest;
|
||||
|
||||
/**
|
||||
* Class PrefileRequest
|
||||
*/
|
||||
class PrefileRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* @return array|void
|
||||
*/
|
||||
/*public function sanitize()
|
||||
{
|
||||
return Pirep::$sanitize;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'airline_id' => 'required|exists:airlines,id',
|
||||
'aircraft_id' => 'required|exists:aircraft,id',
|
||||
'flight_number' => 'required',
|
||||
'dpt_airport_id' => 'required',
|
||||
'arr_airport_id' => 'required',
|
||||
'source_name' => 'required',
|
||||
|
||||
'airline_id' => 'required|exists:airlines,id',
|
||||
'aircraft_id' => 'required|exists:aircraft,id',
|
||||
'flight_number' => 'required',
|
||||
'dpt_airport_id' => 'required',
|
||||
'arr_airport_id' => 'required',
|
||||
'flight_id' => 'nullable',
|
||||
'source_name' => 'required',
|
||||
'alt_airport_id' => 'nullable',
|
||||
'status' => 'nullable',
|
||||
'level' => 'nullable|numeric',
|
||||
|
||||
@@ -4,20 +4,17 @@ namespace App\Http\Requests\Acars;
|
||||
|
||||
use App\Contracts\FormRequest;
|
||||
use App\Models\Pirep;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* Class RouteRequest
|
||||
*/
|
||||
class RouteRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
$pirep = Pirep::findOrFail($this->route('pirep_id'), ['user_id']);
|
||||
return $pirep->user_id === Auth::id();
|
||||
}
|
||||
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'route' => 'required|array',
|
||||
|
||||
@@ -4,20 +4,17 @@ namespace App\Http\Requests\Acars;
|
||||
|
||||
use App\Contracts\FormRequest;
|
||||
use App\Models\Pirep;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* Class UpdateRequest
|
||||
*/
|
||||
class UpdateRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
$pirep = Pirep::findOrFail($this->route('pirep_id'), ['user_id']);
|
||||
return $pirep->user_id === Auth::id();
|
||||
}
|
||||
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'airline_id' => 'nullable|exists:airlines,id',
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace App\Listeners;
|
||||
|
||||
use App\Contracts\Listener;
|
||||
use App\Events\PirepAccepted;
|
||||
use App\Services\PirepService;
|
||||
use App\Services\BidService;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
/**
|
||||
@@ -12,17 +12,11 @@ use Illuminate\Contracts\Events\Dispatcher;
|
||||
*/
|
||||
class BidEvents extends Listener
|
||||
{
|
||||
private $pirepSvc;
|
||||
private $bidSvc;
|
||||
|
||||
/**
|
||||
* FinanceEvents constructor.
|
||||
*
|
||||
* @param PirepService $pirepSvc
|
||||
*/
|
||||
public function __construct(
|
||||
PirepService $pirepSvc
|
||||
) {
|
||||
$this->pirepSvc = $pirepSvc;
|
||||
public function __construct(BidService $bidSvc)
|
||||
{
|
||||
$this->bidSvc = $bidSvc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,10 +38,9 @@ class BidEvents extends Listener
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \Exception
|
||||
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
||||
*/
|
||||
public function onPirepAccept(PirepAccepted $event): void
|
||||
{
|
||||
$this->pirepSvc->removeBid($event->pirep);
|
||||
$this->bidSvc->removeBidForPirep($event->pirep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,10 @@ use Illuminate\Support\Collection;
|
||||
* @property Collection fares
|
||||
* @property Collection subfleets
|
||||
* @property int days
|
||||
* @property int distance
|
||||
* @property int flight_time
|
||||
* @property string route
|
||||
* @property int level
|
||||
* @property Airport dpt_airport
|
||||
* @property Airport arr_airport
|
||||
* @property Airport alt_airport
|
||||
|
||||
@@ -150,6 +150,28 @@ class Pirep extends Model
|
||||
PirepState::DELETED,
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new PIREP model from a given flight. Pre-populates the fields
|
||||
*
|
||||
* @param \App\Models\Flight $flight
|
||||
*
|
||||
* @return \App\Models\Pirep
|
||||
*/
|
||||
public static function fromFlight(Flight $flight)
|
||||
{
|
||||
return new self([
|
||||
'flight_id' => $flight->id,
|
||||
'airline_id' => $flight->airline_id,
|
||||
'flight_number' => $flight->flight_number,
|
||||
'route_code' => $flight->route_code,
|
||||
'route_leg' => $flight->route_leg,
|
||||
'dpt_airport_id' => $flight->dpt_airport_id,
|
||||
'arr_airport_id' => $flight->arr_airport_id,
|
||||
'route' => $flight->route,
|
||||
'level' => $flight->level,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the flight ident, e.,g JBU1900
|
||||
*
|
||||
@@ -277,10 +299,16 @@ class Pirep extends Model
|
||||
/**
|
||||
* Look up the flight, based on the PIREP flight info
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return Flight|null
|
||||
*/
|
||||
public function getFlightAttribute(): ?Flight
|
||||
/*public function getFlightAttribute(): ?Flight
|
||||
{
|
||||
if (!empty($this->flight_id)) {
|
||||
return Flight::find($this->flight_id);
|
||||
}
|
||||
|
||||
$where = [
|
||||
'airline_id' => $this->airline_id,
|
||||
'flight_number' => $this->flight_number,
|
||||
@@ -296,7 +324,7 @@ class Pirep extends Model
|
||||
}
|
||||
|
||||
return Flight::where($where)->first();
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Set the amount of fuel used
|
||||
@@ -412,6 +440,11 @@ class Pirep extends Model
|
||||
return $this->belongsTo(Airline::class, 'airline_id');
|
||||
}
|
||||
|
||||
public function flight()
|
||||
{
|
||||
return $this->belongsTo(Flight::class, 'flight_id');
|
||||
}
|
||||
|
||||
public function arr_airport()
|
||||
{
|
||||
return $this->belongsTo(Airport::class, 'arr_airport_id');
|
||||
|
||||
@@ -12,6 +12,7 @@ use Laratrust\Traits\LaratrustUserTrait;
|
||||
/**
|
||||
* @property int id
|
||||
* @property int pilot_id
|
||||
* @property int airline_id
|
||||
* @property string name
|
||||
* @property string email
|
||||
* @property string password
|
||||
|
||||
145
app/Services/BidService.php
Normal file
145
app/Services/BidService.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Contracts\Service;
|
||||
use App\Exceptions\BidExistsForFlight;
|
||||
use App\Exceptions\UserBidLimit;
|
||||
use App\Models\Bid;
|
||||
use App\Models\Flight;
|
||||
use App\Models\Pirep;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class BidService extends Service
|
||||
{
|
||||
/**
|
||||
* Find all of the bids for a given user
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function findBidsForUser(User $user)
|
||||
{
|
||||
$bids = Bid::where(['user_id' => $user->id])->get();
|
||||
return $bids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow a user to bid on a flight. Check settings and all that good stuff
|
||||
*
|
||||
* @param Flight $flight
|
||||
* @param User $user
|
||||
*
|
||||
* @throws \App\Exceptions\BidExistsForFlight
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function addBid(Flight $flight, User $user)
|
||||
{
|
||||
// Get all of the bids for this user. See if they're allowed to have multiple
|
||||
// bids
|
||||
$bid_count = Bid::where(['user_id' => $user->id])->count();
|
||||
if ($bid_count > 0 && setting('bids.allow_multiple_bids') === false) {
|
||||
throw new UserBidLimit($user);
|
||||
}
|
||||
|
||||
// Get all of the bids for this flight
|
||||
$bids = Bid::where(['flight_id' => $flight->id])->get();
|
||||
if ($bids->count() > 0) {
|
||||
// Does the flight have a bid set?
|
||||
if ($flight->has_bid === false) {
|
||||
$flight->has_bid = true;
|
||||
$flight->save();
|
||||
}
|
||||
|
||||
// Check all the bids for one of this user
|
||||
foreach ($bids as $bid) {
|
||||
if ($bid->user_id === $user->id) {
|
||||
Log::info('Bid exists, user='.$user->ident.', flight='.$flight->id);
|
||||
|
||||
return $bid;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the flight should be blocked off
|
||||
if (setting('bids.disable_flight_on_bid') === true) {
|
||||
throw new BidExistsForFlight($flight);
|
||||
}
|
||||
|
||||
if (setting('bids.allow_multiple_bids') === false) {
|
||||
throw new BidExistsForFlight($flight);
|
||||
}
|
||||
} else {
|
||||
/* @noinspection NestedPositiveIfStatementsInspection */
|
||||
if ($flight->has_bid === true) {
|
||||
Log::info('Bid exists, flight='.$flight->id.'; no entry in bids table, cleaning up');
|
||||
}
|
||||
}
|
||||
|
||||
$bid = Bid::firstOrCreate([
|
||||
'user_id' => $user->id,
|
||||
'flight_id' => $flight->id,
|
||||
]);
|
||||
|
||||
$flight->has_bid = true;
|
||||
$flight->save();
|
||||
|
||||
return $bid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a bid from a given flight
|
||||
*
|
||||
* @param Flight $flight
|
||||
* @param User $user
|
||||
*/
|
||||
public function removeBid(Flight $flight, User $user)
|
||||
{
|
||||
$bids = Bid::where([
|
||||
'flight_id' => $flight->id,
|
||||
'user_id' => $user->id,
|
||||
])->get();
|
||||
|
||||
foreach ($bids as $bid) {
|
||||
$bid->forceDelete();
|
||||
}
|
||||
|
||||
// Only flip the flag if there are no bids left for this flight
|
||||
$bid_count = Bid::where(['flight_id' => $flight->id])->count();
|
||||
if ($bid_count === 0) {
|
||||
$flight->has_bid = false;
|
||||
$flight->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the setting is enabled, remove the bid
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function removeBidForPirep(Pirep $pirep)
|
||||
{
|
||||
if (!setting('pireps.remove_bid_on_accept')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$flight = $pirep->flight;
|
||||
if (!$flight) {
|
||||
return;
|
||||
}
|
||||
|
||||
$bid = Bid::where([
|
||||
'user_id' => $pirep->user->id,
|
||||
'flight_id' => $flight->id,
|
||||
]);
|
||||
|
||||
if ($bid) {
|
||||
Log::info('Bid for user: '.$pirep->user->ident.' on flight '.$flight->ident);
|
||||
$bid->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,14 @@
|
||||
namespace App\Services;
|
||||
|
||||
use App\Contracts\Service;
|
||||
use App\Exceptions\BidExistsForFlight;
|
||||
use App\Exceptions\DuplicateFlight;
|
||||
use App\Models\Bid;
|
||||
use App\Models\Enums\Days;
|
||||
use App\Models\Flight;
|
||||
use App\Models\FlightFieldValue;
|
||||
use App\Models\User;
|
||||
use App\Repositories\FlightRepository;
|
||||
use App\Repositories\NavdataRepository;
|
||||
use App\Support\Units\Time;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class FlightService extends Service
|
||||
{
|
||||
@@ -123,24 +120,6 @@ class FlightService extends Service
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter out any flights according to different settings
|
||||
*
|
||||
* @param $user
|
||||
*
|
||||
* @return FlightRepository
|
||||
*/
|
||||
public function filterFlights($user)
|
||||
{
|
||||
$where = [];
|
||||
if (setting('pilots.only_flights_from_current', false)) {
|
||||
$where['dpt_airport_id'] = $user->curr_airport_id;
|
||||
}
|
||||
|
||||
return $this->flightRepo
|
||||
->whereOrder($where, 'flight_number', 'asc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter out subfleets to only include aircraft that a user has access to
|
||||
*
|
||||
@@ -276,91 +255,4 @@ class FlightService extends Service
|
||||
|
||||
return collect($return_points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow a user to bid on a flight. Check settings and all that good stuff
|
||||
*
|
||||
* @param Flight $flight
|
||||
* @param User $user
|
||||
*
|
||||
*@throws \App\Exceptions\BidExistsForFlight
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function addBid(Flight $flight, User $user)
|
||||
{
|
||||
// Get all of the bids for this user. See if they're allowed to have multiple
|
||||
// bids
|
||||
$bids = Bid::where('user_id', $user->id)->get();
|
||||
if ($bids->count() > 0 && setting('bids.allow_multiple_bids') === false) {
|
||||
throw new BidExistsForFlight('User "'.$user->ident.'" already has bids, skipping');
|
||||
}
|
||||
|
||||
// Get all of the bids for this flight
|
||||
$bids = Bid::where('flight_id', $flight->id)->get();
|
||||
if ($bids->count() > 0) {
|
||||
// Does the flight have a bid set?
|
||||
if ($flight->has_bid === false) {
|
||||
$flight->has_bid = true;
|
||||
$flight->save();
|
||||
}
|
||||
|
||||
// Check all the bids for one of this user
|
||||
foreach ($bids as $bid) {
|
||||
if ($bid->user_id === $user->id) {
|
||||
Log::info('Bid exists, user='.$user->ident.', flight='.$flight->id);
|
||||
return $bid;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the flight should be blocked off
|
||||
if (setting('bids.disable_flight_on_bid') === true) {
|
||||
throw new BidExistsForFlight($flight);
|
||||
}
|
||||
|
||||
if (setting('bids.allow_multiple_bids') === false) {
|
||||
throw new BidExistsForFlight($flight);
|
||||
}
|
||||
} else {
|
||||
/* @noinspection NestedPositiveIfStatementsInspection */
|
||||
if ($flight->has_bid === true) {
|
||||
Log::info('Bid exists, flight='.$flight->id.'; no entry in bids table, cleaning up');
|
||||
}
|
||||
}
|
||||
|
||||
$bid = Bid::firstOrCreate([
|
||||
'user_id' => $user->id,
|
||||
'flight_id' => $flight->id,
|
||||
]);
|
||||
|
||||
$flight->has_bid = true;
|
||||
$flight->save();
|
||||
|
||||
return $bid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a bid from a given flight
|
||||
*
|
||||
* @param Flight $flight
|
||||
* @param User $user
|
||||
*/
|
||||
public function removeBid(Flight $flight, User $user)
|
||||
{
|
||||
$bids = Bid::where([
|
||||
'flight_id' => $flight->id,
|
||||
'user_id' => $user->id,
|
||||
])->get();
|
||||
|
||||
foreach ($bids as $bid) {
|
||||
$bid->forceDelete();
|
||||
}
|
||||
|
||||
// Only flip the flag if there are no bids left for this flight
|
||||
$bids = Bid::where('flight_id', $flight->id)->get();
|
||||
if ($bids->count() === 0) {
|
||||
$flight->has_bid = false;
|
||||
$flight->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ use App\Events\PirepRejected;
|
||||
use App\Events\UserStatsChanged;
|
||||
use App\Exceptions\PirepCancelNotAllowed;
|
||||
use App\Models\Acars;
|
||||
use App\Models\Bid;
|
||||
use App\Models\Enums\AcarsType;
|
||||
use App\Models\Enums\PirepSource;
|
||||
use App\Models\Enums\PirepState;
|
||||
@@ -20,12 +19,10 @@ use App\Models\PirepFieldValue;
|
||||
use App\Models\User;
|
||||
use App\Repositories\PirepRepository;
|
||||
use Carbon\Carbon;
|
||||
use function count;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class PirepService
|
||||
*/
|
||||
class PirepService extends Service
|
||||
{
|
||||
private $geoSvc;
|
||||
@@ -33,8 +30,6 @@ class PirepService extends Service
|
||||
private $pirepRepo;
|
||||
|
||||
/**
|
||||
* PirepService constructor.
|
||||
*
|
||||
* @param GeoService $geoSvc
|
||||
* @param PirepRepository $pirepRepo
|
||||
* @param UserService $pilotSvc
|
||||
@@ -49,6 +44,60 @@ class PirepService extends Service
|
||||
$this->pirepRepo = $pirepRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PIREP with some given fields
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
* @param array PirepFieldValue[] $field_values
|
||||
*
|
||||
* @return Pirep
|
||||
*/
|
||||
public function create(Pirep $pirep, array $field_values = []): Pirep
|
||||
{
|
||||
if (empty($field_values)) {
|
||||
$field_values = [];
|
||||
}
|
||||
|
||||
// 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->status = PirepStatus::ARRIVED;
|
||||
|
||||
// Copy some fields over from Flight if we have it
|
||||
if ($pirep->flight) {
|
||||
$pirep->planned_distance = $pirep->flight->distance;
|
||||
$pirep->planned_flight_time = $pirep->flight->flight_time;
|
||||
}
|
||||
|
||||
$pirep->save();
|
||||
$pirep->refresh();
|
||||
|
||||
if (count($field_values) > 0) {
|
||||
$this->updateCustomFields($pirep->id, $field_values);
|
||||
}
|
||||
|
||||
return $pirep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find if there are duplicates to a given PIREP. Ideally, the passed
|
||||
* in PIREP hasn't been saved or gone through the create() method
|
||||
@@ -149,54 +198,6 @@ class PirepService extends Service
|
||||
return $pirep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PIREP with some given fields
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
* @param array PirepFieldValue[] $field_values
|
||||
*
|
||||
* @return Pirep
|
||||
*/
|
||||
public function create(Pirep $pirep, array $field_values = []): Pirep
|
||||
{
|
||||
if (empty($field_values)) {
|
||||
$field_values = [];
|
||||
}
|
||||
|
||||
// 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->status = PirepStatus::ARRIVED;
|
||||
|
||||
$pirep->save();
|
||||
$pirep->refresh();
|
||||
|
||||
if (\count($field_values) > 0) {
|
||||
$this->updateCustomFields($pirep->id, $field_values);
|
||||
}
|
||||
|
||||
return $pirep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit the PIREP. Figure out its default state
|
||||
*
|
||||
@@ -421,33 +422,4 @@ class PirepService extends Service
|
||||
|
||||
event(new UserStatsChanged($pilot, 'airport', $previous_airport));
|
||||
}
|
||||
|
||||
/**
|
||||
* If the setting is enabled, remove the bid
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function removeBid(Pirep $pirep)
|
||||
{
|
||||
if (!setting('pireps.remove_bid_on_accept')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$flight = $pirep->flight;
|
||||
if (!$flight) {
|
||||
return;
|
||||
}
|
||||
|
||||
$bid = Bid::where([
|
||||
'user_id' => $pirep->user->id,
|
||||
'flight_id' => $flight->id,
|
||||
]);
|
||||
|
||||
if ($bid) {
|
||||
Log::info('Bid for user: '.$pirep->user->ident.' on flight '.$flight->ident);
|
||||
$bid->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ return [
|
||||
'submitpirep' => 'Submit PIREP',
|
||||
'fileflightreport' => 'File New Report',
|
||||
'filenewpirep' => 'File New PIREP',
|
||||
'newpirep' => 'New PIREP',
|
||||
'pilotreport' => 'Pilot Report|Pilot Reports',
|
||||
'arrived' => 'Arrived',
|
||||
'source' => 'Source',
|
||||
|
||||
@@ -7,6 +7,7 @@ return [
|
||||
'submitpirep' => 'Enviar PIREP',
|
||||
'fileflightreport' => 'Archivo informe de vuelo',
|
||||
'filenewpirep' => 'Archivo nuevo PIREP',
|
||||
'newpirep' => 'Nuevo PIREP',
|
||||
'pilotreport' => 'Informe de piloto|Informes de piloto',
|
||||
'arrived' => 'Llegó',
|
||||
'source' => 'Origen',
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
return [
|
||||
'filenewpirep' => 'Inserici Nuovo PIREP',
|
||||
'newpirep' => 'Nuovo PIREP',
|
||||
'pilotreport' => 'Rapporto Pilota|Rapporti Pilota',
|
||||
'arrived' => 'Arrivato',
|
||||
'source' => 'Fonte',
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
x-id="{{ $flight->id }}"
|
||||
x-saved-class="btn-info"
|
||||
type="button"
|
||||
title="@lang('flights.addremovebid')"
|
||||
>
|
||||
title="@lang('flights.addremovebid')">
|
||||
<i class="fas fa-map-marker"></i>
|
||||
</button>
|
||||
@endif
|
||||
@@ -64,6 +63,14 @@
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 text-right">
|
||||
<a href="{{ route('frontend.pireps.create') }}?flight_id={{ $flight->id }}"
|
||||
class="btn btn-sm btn-info">
|
||||
{{ __('pireps.newpirep') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,17 +2,22 @@
|
||||
@section('title', __('pireps.fileflightreport'))
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>@lang('pireps.newflightreport')</h2>
|
||||
@include('flash::message')
|
||||
{{ Form::open(['route' => 'frontend.pireps.store']) }}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>@lang('pireps.newflightreport')</h2>
|
||||
@include('flash::message')
|
||||
@if(!empty($pirep))
|
||||
wee
|
||||
{{ Form::model($pirep, ['route' => 'frontend.pireps.store']) }}
|
||||
@else
|
||||
{{ Form::open(['route' => 'frontend.pireps.store']) }}
|
||||
@endif
|
||||
|
||||
@include('pireps.fields')
|
||||
@include('pireps.fields')
|
||||
|
||||
{{ Form::close() }}
|
||||
</div>
|
||||
{{ Form::close() }}
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@include('pireps.scripts')
|
||||
|
||||
@@ -9,323 +9,326 @@ flight reports that have been filed. You've been warned!
|
||||
|
||||
--}}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
@component('components.info')
|
||||
@lang('pireps.fieldsreadonly')
|
||||
@endcomponent
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
@component('components.info')
|
||||
@lang('pireps.fieldsreadonly')
|
||||
@endcomponent
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="form-container">
|
||||
<h6><i class="fas fa-info-circle"></i>
|
||||
@lang('pireps.flightinformations')
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
{{ Form::label('airline_id', __('common.airline')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ $pirep->airline->name }}</p>
|
||||
{{ Form::hidden('airline_id') }}
|
||||
@else
|
||||
<div class="input-group input-group form-group">
|
||||
{{ Form::select('airline_id', $airline_list, null, [
|
||||
'class' => 'custom-select select2',
|
||||
'style' => 'width: 100%',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('airline_id') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
{{ Form::label('flight_number', __('pireps.flightident')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ $pirep->ident }}
|
||||
{{ Form::hidden('flight_number') }}
|
||||
{{ Form::hidden('flight_code') }}
|
||||
{{ Form::hidden('flight_leg') }}
|
||||
</p>
|
||||
@else
|
||||
<div class="input-group input-group-sm mb3">
|
||||
{{ Form::text('flight_number', null, [
|
||||
'placeholder' => __('flights.flightnumber'),
|
||||
'class' => 'form-control',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
|
||||
{{ Form::text('route_code', null, [
|
||||
'placeholder' => __('pireps.codeoptional'),
|
||||
'class' => 'form-control',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
|
||||
{{ Form::text('route_leg', null, [
|
||||
'placeholder' => __('pireps.legoptional'),
|
||||
'class' => 'form-control',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('flight_number') }}</p>
|
||||
<p class="text-danger">{{ $errors->first('route_code') }}</p>
|
||||
<p class="text-danger">{{ $errors->first('route_leg') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
{{ Form::label('flight_type', __('flights.flighttype')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ \App\Models\Enums\FlightType::label($pirep->flight_type) }}</p>
|
||||
{{ Form::hidden('flight_type') }}
|
||||
@else
|
||||
<div class="form-group">
|
||||
{{ Form::select('flight_type',
|
||||
\App\Models\Enums\FlightType::select(), null, [
|
||||
'class' => 'custom-select select2',
|
||||
'style' => 'width: 100%',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
])
|
||||
}}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('flight_type') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
{{ Form::label('hours', __('flights.flighttime')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>
|
||||
{{ $pirep->hours.' '.trans_choice('common.hour', $pirep->hours) }}, {{ $pirep->minutes.' '.trans_choice('common.minute', $pirep->minutes) }}
|
||||
{{ Form::hidden('hours') }}
|
||||
{{ Form::hidden('minutes') }}
|
||||
</p>
|
||||
@else
|
||||
<div class="input-group input-group-sm" style="max-width: 400px;">
|
||||
{{ Form::number('hours', null, [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => trans_choice('common.hour', 2),
|
||||
'min' => '0',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
|
||||
{{ Form::number('minutes', null, [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => trans_choice('common.minute', 2),
|
||||
'min' => 0,
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('hours') }}</p>
|
||||
<p class="text-danger">{{ $errors->first('minutes') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div class="form-container">
|
||||
<h6><i class="fas fa-info-circle"></i>
|
||||
@lang('pireps.flightinformations')
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
{{ Form::label('airline_id', __('common.airline')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ $pirep->airline->name }}</p>
|
||||
{{ Form::hidden('airline_id') }}
|
||||
@else
|
||||
<div class="input-group input-group form-group">
|
||||
{{ Form::select('airline_id', $airline_list, null, [
|
||||
'class' => 'custom-select select2',
|
||||
'style' => 'width: 100%',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('airline_id') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
{{ Form::label('flight_number', __('pireps.flightident')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ $pirep->ident }}
|
||||
{{ Form::hidden('flight_number') }}
|
||||
{{ Form::hidden('flight_code') }}
|
||||
{{ Form::hidden('flight_leg') }}
|
||||
</p>
|
||||
@else
|
||||
<div class="input-group input-group-sm mb3">
|
||||
{{ Form::text('flight_number', null, [
|
||||
'placeholder' => __('flights.flightnumber'),
|
||||
'class' => 'form-control',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
|
||||
{{ Form::text('route_code', null, [
|
||||
'placeholder' => __('pireps.codeoptional'),
|
||||
'class' => 'form-control',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
|
||||
{{ Form::text('route_leg', null, [
|
||||
'placeholder' => __('pireps.legoptional'),
|
||||
'class' => 'form-control',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('flight_number') }}</p>
|
||||
<p class="text-danger">{{ $errors->first('route_code') }}</p>
|
||||
<p class="text-danger">{{ $errors->first('route_leg') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
{{ Form::label('flight_type', __('flights.flighttype')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ \App\Models\Enums\FlightType::label($pirep->flight_type) }}</p>
|
||||
{{ Form::hidden('flight_type') }}
|
||||
@else
|
||||
<div class="form-group">
|
||||
{{ Form::select('flight_type',
|
||||
\App\Models\Enums\FlightType::select(), null, [
|
||||
'class' => 'custom-select select2',
|
||||
'style' => 'width: 100%',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
])
|
||||
}}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('flight_type') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
{{ Form::label('hours', __('flights.flighttime')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>
|
||||
{{ $pirep->hours.' '.trans_choice('common.hour', $pirep->hours) }}
|
||||
, {{ $pirep->minutes.' '.trans_choice('common.minute', $pirep->minutes) }}
|
||||
{{ Form::hidden('hours') }}
|
||||
{{ Form::hidden('minutes') }}
|
||||
</p>
|
||||
@else
|
||||
<div class="input-group input-group-sm" style="max-width: 400px;">
|
||||
{{ Form::number('hours', null, [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => trans_choice('common.hour', 2),
|
||||
'min' => '0',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
|
||||
<div class="form-container">
|
||||
<h6><i class="fas fa-globe"></i>
|
||||
@lang('pireps.deparrinformations')
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
{{ Form::label('dpt_airport_id', __('airports.departure')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
{{ $pirep->dpt_airport->name }}
|
||||
(<a href="{{route('frontend.airports.show', [
|
||||
{{ Form::number('minutes', null, [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => trans_choice('common.minute', 2),
|
||||
'min' => 0,
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('hours') }}</p>
|
||||
<p class="text-danger">{{ $errors->first('minutes') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-container">
|
||||
<h6><i class="fas fa-globe"></i>
|
||||
@lang('pireps.deparrinformations')
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
{{ Form::label('dpt_airport_id', __('airports.departure')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
{{ $pirep->dpt_airport->name }}
|
||||
(<a href="{{route('frontend.airports.show', [
|
||||
'id' => $pirep->dpt_airport->icao
|
||||
])}}">{{$pirep->dpt_airport->icao}}</a>)
|
||||
{{ Form::hidden('dpt_airport_id') }}
|
||||
@else
|
||||
<div class="form-group">
|
||||
{{ Form::select('dpt_airport_id', $airport_list, null, [
|
||||
'class' => 'custom-select select2',
|
||||
'style' => 'width: 100%',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('dpt_airport_id') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
{{ Form::hidden('dpt_airport_id') }}
|
||||
@else
|
||||
<div class="form-group">
|
||||
{{ Form::select('dpt_airport_id', $airport_list, null, [
|
||||
'class' => 'custom-select select2',
|
||||
'style' => 'width: 100%',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('dpt_airport_id') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
{{ Form::label('arr_airport_id', __('airports.arrival')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
{{ $pirep->arr_airport->name }}
|
||||
(<a href="{{route('frontend.airports.show', [
|
||||
<div class="col-6">
|
||||
{{ Form::label('arr_airport_id', __('airports.arrival')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
{{ $pirep->arr_airport->name }}
|
||||
(<a href="{{route('frontend.airports.show', [
|
||||
'id' => $pirep->arr_airport->icao
|
||||
])}}">{{$pirep->arr_airport->icao}}</a>)
|
||||
{{ Form::hidden('arr_airport_id') }}
|
||||
@else
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{ Form::select('arr_airport_id', $airport_list, null, [
|
||||
'class' => 'custom-select select2',
|
||||
'style' => 'width: 100%',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('arr_airport_id') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<h6><i class="fab fa-avianex"></i>
|
||||
@lang('pireps.aircraftinformations')
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
{{ Form::label('aircraft_id', __('common.aircraft')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ $pirep->aircraft->name }}</p>
|
||||
{{ Form::hidden('aircraft_id') }}
|
||||
@else
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{-- You probably don't want to change this ID if you want the fare select to work --}}
|
||||
{{ Form::select('aircraft_id', $aircraft_list, null, [
|
||||
'id' => 'aircraft_select',
|
||||
'class' => 'custom-select select2',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('aircraft_id') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-4">
|
||||
{{ Form::label('block_fuel', __('pireps.block_fuel')) }} ({{config('phpvms.internal_units.fuel')}})
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ $pirep->block_fuel }}</p>
|
||||
@else
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{ Form::number('block_fuel', null, [
|
||||
'class' => 'form-control',
|
||||
'min' => '0',
|
||||
'step' => '0.01',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('block_fuel') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-4">
|
||||
{{ Form::label('fuel_used', __('pireps.fuel_used')) }} ({{config('phpvms.internal_units.fuel')}})
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ $pirep->fuel_used }}</p>
|
||||
@else
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{ Form::number('fuel_used', null, [
|
||||
'class' => 'form-control',
|
||||
'min' => '0',
|
||||
'step' => '0.01',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('fuel_used') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="fares_container" class="form-container">
|
||||
@include('pireps.fares')
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<h6><i class="far fa-comments"></i>
|
||||
@lang('flights.route')
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{ Form::textarea('route', null, [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => __('flights.route'),
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
<p class="text-danger">{{ $errors->first('route') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<h6><i class="far fa-comments"></i>
|
||||
{{ trans_choice('common.remark', 2) }}
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{ Form::textarea('notes', null, ['class' => 'form-control', 'placeholder' => trans_choice('common.note', 2)]) }}
|
||||
<p class="text-danger">{{ $errors->first('notes') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ Form::hidden('arr_airport_id') }}
|
||||
@else
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{ Form::select('arr_airport_id', $airport_list, null, [
|
||||
'class' => 'custom-select select2',
|
||||
'style' => 'width: 100%',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('arr_airport_id') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{--
|
||||
Write out the custom fields, and label if they're required
|
||||
--}}
|
||||
<div class="col-4">
|
||||
<div class="form-container">
|
||||
<h6><i class="fab fa-wpforms"></i>
|
||||
{{ trans_choice('common.field', 2) }}
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
@if(isset($pirep) && $pirep->fields)
|
||||
@each('pireps.custom_fields', $pirep->fields, 'field')
|
||||
@else
|
||||
@each('pireps.custom_fields', $pirep_fields, 'field')
|
||||
@endif
|
||||
</div>
|
||||
<div class="form-container">
|
||||
<h6><i class="fab fa-avianex"></i>
|
||||
@lang('pireps.aircraftinformations')
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
{{ Form::label('aircraft_id', __('common.aircraft')) }}
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ $pirep->aircraft->name }}</p>
|
||||
{{ Form::hidden('aircraft_id') }}
|
||||
@else
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{-- You probably don't want to change this ID if you want the fare select to work --}}
|
||||
{{ Form::select('aircraft_id', $aircraft_list, null, [
|
||||
'id' => 'aircraft_select',
|
||||
'class' => 'custom-select select2',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('aircraft_id') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-4">
|
||||
{{ Form::label('block_fuel', __('pireps.block_fuel')) }} ({{config('phpvms.internal_units.fuel')}})
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ $pirep->block_fuel }}</p>
|
||||
@else
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{ Form::number('block_fuel', null, [
|
||||
'class' => 'form-control',
|
||||
'min' => '0',
|
||||
'step' => '0.01',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('block_fuel') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-4">
|
||||
{{ Form::label('fuel_used', __('pireps.fuel_used')) }} ({{config('phpvms.internal_units.fuel')}})
|
||||
@if(!empty($pirep) && $pirep->read_only)
|
||||
<p>{{ $pirep->fuel_used }}</p>
|
||||
@else
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{ Form::number('fuel_used', null, [
|
||||
'class' => 'form-control',
|
||||
'min' => '0',
|
||||
'step' => '0.01',
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
</div>
|
||||
<p class="text-danger">{{ $errors->first('fuel_used') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="fares_container" class="form-container">
|
||||
@include('pireps.fares')
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<h6><i class="far fa-comments"></i>
|
||||
@lang('flights.route')
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{ Form::textarea('route', null, [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => __('flights.route'),
|
||||
'readonly' => (!empty($pirep) && $pirep->read_only),
|
||||
]) }}
|
||||
<p class="text-danger">{{ $errors->first('route') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<h6><i class="far fa-comments"></i>
|
||||
{{ trans_choice('common.remark', 2) }}
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="input-group input-group-sm form-group">
|
||||
{{ Form::textarea('notes', null, ['class' => 'form-control', 'placeholder' => trans_choice('common.note', 2)]) }}
|
||||
<p class="text-danger">{{ $errors->first('notes') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{--
|
||||
Write out the custom fields, and label if they're required
|
||||
--}}
|
||||
<div class="col-4">
|
||||
<div class="form-container">
|
||||
<h6><i class="fab fa-wpforms"></i>
|
||||
{{ trans_choice('common.field', 2) }}
|
||||
</h6>
|
||||
<div class="form-container-body">
|
||||
@if(isset($pirep) && $pirep->fields)
|
||||
@each('pireps.custom_fields', $pirep->fields, 'field')
|
||||
@else
|
||||
@each('pireps.custom_fields', $pirep_fields, 'field')
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-12">
|
||||
<div class="float-right">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="float-right">
|
||||
<div class="form-group">
|
||||
|
||||
@if(isset($pirep) && !$pirep->read_only)
|
||||
{{ Form::button(__('pireps.deletepirep'), [
|
||||
'name' => 'submit',
|
||||
'value' => 'Delete',
|
||||
'class' => 'btn btn-warning',
|
||||
'type' => 'submit'])
|
||||
}}
|
||||
@endif
|
||||
{{ Form::hidden('flight_id') }}
|
||||
|
||||
{{ Form::button(__('pireps.savepirep'), [
|
||||
'name' => 'submit',
|
||||
'value' => 'Save',
|
||||
'class' => 'btn btn-info',
|
||||
'type' => 'submit'])
|
||||
}}
|
||||
@if(isset($pirep) && !$pirep->read_only)
|
||||
{{ Form::button(__('pireps.deletepirep'), [
|
||||
'name' => 'submit',
|
||||
'value' => 'Delete',
|
||||
'class' => 'btn btn-warning',
|
||||
'type' => 'submit'])
|
||||
}}
|
||||
@endif
|
||||
|
||||
@if(!isset($pirep) || (filled($pirep) && !$pirep->read_only))
|
||||
{{ Form::button(__('pireps.submitpirep'), [
|
||||
'name' => 'submit',
|
||||
'value' => 'Submit',
|
||||
'class' => 'btn btn-success',
|
||||
'type' => 'submit'])
|
||||
}}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
{{ Form::button(__('pireps.savepirep'), [
|
||||
'name' => 'submit',
|
||||
'value' => 'Save',
|
||||
'class' => 'btn btn-info',
|
||||
'type' => 'submit'])
|
||||
}}
|
||||
|
||||
@if(!isset($pirep) || (filled($pirep) && !$pirep->read_only))
|
||||
{{ Form::button(__('pireps.submitpirep'), [
|
||||
'name' => 'submit',
|
||||
'value' => 'Submit',
|
||||
'class' => 'btn btn-success',
|
||||
'type' => 'submit'])
|
||||
}}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
212
tests/BidTest.php
Normal file
212
tests/BidTest.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Bid;
|
||||
use App\Models\Flight;
|
||||
use App\Models\User;
|
||||
use App\Repositories\SettingRepository;
|
||||
use App\Services\BidService;
|
||||
use App\Services\FlightService;
|
||||
|
||||
class BidTest extends TestCase
|
||||
{
|
||||
protected $bidSvc;
|
||||
protected $flightSvc;
|
||||
protected $settingsRepo;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->addData('base');
|
||||
|
||||
$this->bidSvc = app(BidService::class);
|
||||
$this->flightSvc = app(FlightService::class);
|
||||
$this->settingsRepo = app(SettingRepository::class);
|
||||
}
|
||||
|
||||
public function addFlight($user)
|
||||
{
|
||||
$flight = factory(App\Models\Flight::class)->create([
|
||||
'airline_id' => $user->airline_id,
|
||||
]);
|
||||
|
||||
$flight->subfleets()->syncWithoutDetaching([
|
||||
factory(App\Models\Subfleet::class)->create([
|
||||
'airline_id' => $user->airline_id,
|
||||
])->id,
|
||||
]);
|
||||
|
||||
return $flight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/remove a bid, test the API, etc
|
||||
*
|
||||
* @throws \App\Services\Exception
|
||||
*/
|
||||
public function testBids()
|
||||
{
|
||||
$this->settingsRepo->store('bids.allow_multiple_bids', true);
|
||||
$this->settingsRepo->store('bids.disable_flight_on_bid', false);
|
||||
|
||||
$user = factory(User::class)->create();
|
||||
$user2 = factory(User::class)->create();
|
||||
$headers = $this->headers($user);
|
||||
|
||||
$flight = $this->addFlight($user);
|
||||
|
||||
$bid = $this->bidSvc->addBid($flight, $user);
|
||||
$this->assertEquals($user->id, $bid->user_id);
|
||||
$this->assertEquals($flight->id, $bid->flight_id);
|
||||
$this->assertTrue($flight->has_bid);
|
||||
|
||||
// Refresh
|
||||
$flight = Flight::find($flight->id);
|
||||
$this->assertTrue($flight->has_bid);
|
||||
|
||||
// Check the table and make sure the entry is there
|
||||
$bid_retrieved = $this->bidSvc->addBid($flight, $user);
|
||||
$this->assertEquals($bid->id, $bid_retrieved->id);
|
||||
|
||||
$user->refresh();
|
||||
$bids = $user->bids;
|
||||
$this->assertEquals(1, $bids->count());
|
||||
|
||||
// Query the API and see that the user has the bids
|
||||
// And pull the flight details for the user/bids
|
||||
$req = $this->get('/api/user', $headers);
|
||||
$req->assertStatus(200);
|
||||
|
||||
$body = $req->json()['data'];
|
||||
$this->assertCount(1, $body['bids']);
|
||||
$this->assertEquals($flight->id, $body['bids'][0]['flight_id']);
|
||||
|
||||
$req = $this->get('/api/users/'.$user->id.'/bids', $headers);
|
||||
|
||||
$body = $req->json()['data'];
|
||||
$req->assertStatus(200);
|
||||
$this->assertEquals($flight->id, $body[0]['flight_id']);
|
||||
|
||||
// have a second user bid on it
|
||||
$bid_user2 = $this->bidSvc->addBid($flight, $user2);
|
||||
$this->assertNotNull($bid_user2);
|
||||
$this->assertNotEquals($bid_retrieved->id, $bid_user2->id);
|
||||
|
||||
// Now remove the flight and check API
|
||||
|
||||
$this->bidSvc->removeBid($flight, $user);
|
||||
|
||||
$flight = Flight::find($flight->id);
|
||||
|
||||
// user2 still has a bid on it
|
||||
$this->assertTrue($flight->has_bid);
|
||||
|
||||
// Remove it from 2nd user
|
||||
$this->bidSvc->removeBid($flight, $user2);
|
||||
$flight->refresh();
|
||||
$this->assertFalse($flight->has_bid);
|
||||
|
||||
$user->refresh();
|
||||
$bids = $user->bids()->get();
|
||||
$this->assertTrue($bids->isEmpty());
|
||||
|
||||
$req = $this->get('/api/user', $headers);
|
||||
$req->assertStatus(200);
|
||||
|
||||
$body = $req->json()['data'];
|
||||
$this->assertEquals($user->id, $body['id']);
|
||||
$this->assertCount(0, $body['bids']);
|
||||
|
||||
$req = $this->get('/api/users/'.$user->id.'/bids', $headers);
|
||||
$req->assertStatus(200);
|
||||
$body = $req->json()['data'];
|
||||
|
||||
$this->assertCount(0, $body);
|
||||
}
|
||||
|
||||
public function testMultipleBidsSingleFlight()
|
||||
{
|
||||
$this->settingsRepo->store('bids.disable_flight_on_bid', true);
|
||||
|
||||
$user1 = factory(User::class)->create();
|
||||
$user2 = factory(User::class)->create([
|
||||
'airline_id' => $user1->airline_id,
|
||||
]);
|
||||
|
||||
$flight = $this->addFlight($user1);
|
||||
|
||||
// Put bid on the flight to block it off
|
||||
$this->bidSvc->addBid($flight, $user1);
|
||||
|
||||
// Try adding again, should throw an exception
|
||||
$this->expectException(\App\Exceptions\BidExistsForFlight::class);
|
||||
$this->bidSvc->addBid($flight, $user2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a flight bid VIA the API
|
||||
*/
|
||||
public function testAddBidApi()
|
||||
{
|
||||
$this->user = factory(User::class)->create();
|
||||
$user2 = factory(User::class)->create();
|
||||
$flight = $this->addFlight($this->user);
|
||||
|
||||
$uri = '/api/user/bids';
|
||||
$data = ['flight_id' => $flight->id];
|
||||
|
||||
$body = $this->put($uri, $data);
|
||||
$body = $body->json('data');
|
||||
|
||||
$this->assertEquals($body['flight_id'], $flight->id);
|
||||
|
||||
// Now try to have the second user bid on it
|
||||
// Should return a 409 error
|
||||
$response = $this->put($uri, $data, [], $user2);
|
||||
$response->assertStatus(409);
|
||||
|
||||
// Try now deleting the bid from the user
|
||||
$response = $this->delete($uri, $data);
|
||||
$body = $response->json('data');
|
||||
$this->assertCount(0, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a flight and make sure all the bids are gone
|
||||
*/
|
||||
public function testDeleteFlightWithBids()
|
||||
{
|
||||
$user = factory(User::class)->create();
|
||||
$headers = $this->headers($user);
|
||||
|
||||
$flight = $this->addFlight($user);
|
||||
|
||||
$bid = $this->bidSvc->addBid($flight, $user);
|
||||
$this->assertEquals($user->id, $bid->user_id);
|
||||
$this->assertEquals($flight->id, $bid->flight_id);
|
||||
$this->assertTrue($flight->has_bid);
|
||||
|
||||
$this->flightSvc->deleteFlight($flight);
|
||||
|
||||
$empty_flight = Flight::find($flight->id);
|
||||
$this->assertNull($empty_flight);
|
||||
|
||||
// Make sure no bids exist
|
||||
$user_bids_count = Bid::where(['flight_id' => $flight->id])->count();
|
||||
$this->assertEquals(0, $user_bids_count);
|
||||
|
||||
// Query the API and see that the user has the bids
|
||||
// And pull the flight details for the user/bids
|
||||
$req = $this->get('/api/user', $headers);
|
||||
$req->assertStatus(200);
|
||||
|
||||
$body = $req->json()['data'];
|
||||
$this->assertEquals($user->id, $body['id']);
|
||||
$this->assertCount(0, $body['bids']);
|
||||
|
||||
$req = $this->get('/api/users/'.$user->id.'/bids', $headers);
|
||||
$req->assertStatus(200);
|
||||
|
||||
$body = $req->json()['data'];
|
||||
$this->assertCount(0, $body);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Bid;
|
||||
use App\Models\Enums\Days;
|
||||
use App\Models\Flight;
|
||||
use App\Models\User;
|
||||
@@ -401,177 +400,18 @@ class FlightTest extends TestCase
|
||||
$this->assertCount(1, $found);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/remove a bid, test the API, etc
|
||||
*
|
||||
* @throws \App\Services\Exception
|
||||
*/
|
||||
public function testBids()
|
||||
{
|
||||
$this->settingsRepo->store('bids.allow_multiple_bids', true);
|
||||
$this->settingsRepo->store('bids.disable_flight_on_bid', false);
|
||||
|
||||
$user = factory(User::class)->create();
|
||||
$user2 = factory(User::class)->create();
|
||||
$headers = $this->headers($user);
|
||||
|
||||
$flight = $this->addFlight($user);
|
||||
|
||||
$bid = $this->flightSvc->addBid($flight, $user);
|
||||
$this->assertEquals($user->id, $bid->user_id);
|
||||
$this->assertEquals($flight->id, $bid->flight_id);
|
||||
$this->assertTrue($flight->has_bid);
|
||||
|
||||
// Refresh
|
||||
$flight = Flight::find($flight->id);
|
||||
$this->assertTrue($flight->has_bid);
|
||||
|
||||
// Check the table and make sure the entry is there
|
||||
$bid_retrieved = $this->flightSvc->addBid($flight, $user);
|
||||
$this->assertEquals($bid->id, $bid_retrieved->id);
|
||||
|
||||
$user->refresh();
|
||||
$bids = $user->bids;
|
||||
$this->assertEquals(1, $bids->count());
|
||||
|
||||
// Query the API and see that the user has the bids
|
||||
// And pull the flight details for the user/bids
|
||||
$req = $this->get('/api/user', $headers);
|
||||
$req->assertStatus(200);
|
||||
|
||||
$body = $req->json()['data'];
|
||||
$this->assertCount(1, $body['bids']);
|
||||
$this->assertEquals($flight->id, $body['bids'][0]['flight_id']);
|
||||
|
||||
$req = $this->get('/api/users/'.$user->id.'/bids', $headers);
|
||||
|
||||
$body = $req->json()['data'];
|
||||
$req->assertStatus(200);
|
||||
$this->assertEquals($flight->id, $body[0]['flight_id']);
|
||||
|
||||
// have a second user bid on it
|
||||
$bid_user2 = $this->flightSvc->addBid($flight, $user2);
|
||||
$this->assertNotNull($bid_user2);
|
||||
$this->assertNotEquals($bid_retrieved->id, $bid_user2->id);
|
||||
|
||||
// Now remove the flight and check API
|
||||
|
||||
$this->flightSvc->removeBid($flight, $user);
|
||||
|
||||
$flight = Flight::find($flight->id);
|
||||
|
||||
// user2 still has a bid on it
|
||||
$this->assertTrue($flight->has_bid);
|
||||
|
||||
// Remove it from 2nd user
|
||||
$this->flightSvc->removeBid($flight, $user2);
|
||||
$flight->refresh();
|
||||
$this->assertFalse($flight->has_bid);
|
||||
|
||||
$user->refresh();
|
||||
$bids = $user->bids()->get();
|
||||
$this->assertTrue($bids->isEmpty());
|
||||
|
||||
$req = $this->get('/api/user', $headers);
|
||||
$req->assertStatus(200);
|
||||
|
||||
$body = $req->json()['data'];
|
||||
$this->assertEquals($user->id, $body['id']);
|
||||
$this->assertCount(0, $body['bids']);
|
||||
|
||||
$req = $this->get('/api/users/'.$user->id.'/bids', $headers);
|
||||
$req->assertStatus(200);
|
||||
$body = $req->json()['data'];
|
||||
|
||||
$this->assertCount(0, $body);
|
||||
}
|
||||
|
||||
public function testMultipleBidsSingleFlight()
|
||||
{
|
||||
$this->settingsRepo->store('bids.disable_flight_on_bid', true);
|
||||
|
||||
$user1 = factory(User::class)->create();
|
||||
$user2 = factory(User::class)->create([
|
||||
'airline_id' => $user1->airline_id,
|
||||
]);
|
||||
|
||||
$flight = $this->addFlight($user1);
|
||||
|
||||
// Put bid on the flight to block it off
|
||||
$this->flightSvc->addBid($flight, $user1);
|
||||
|
||||
// Try adding again, should throw an exception
|
||||
$this->expectException(\App\Exceptions\BidExistsForFlight::class);
|
||||
$this->flightSvc->addBid($flight, $user2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a flight bid VIA the API
|
||||
*/
|
||||
public function testAddBidApi()
|
||||
{
|
||||
$this->user = factory(User::class)->create();
|
||||
$user2 = factory(User::class)->create();
|
||||
$flight = $this->addFlight($this->user);
|
||||
|
||||
$uri = '/api/user/bids';
|
||||
$data = ['flight_id' => $flight->id];
|
||||
|
||||
$body = $this->put($uri, $data);
|
||||
$body = $body->json('data');
|
||||
|
||||
$this->assertEquals($body['flight_id'], $flight->id);
|
||||
|
||||
// Now try to have the second user bid on it
|
||||
// Should return a 409 error
|
||||
$response = $this->put($uri, $data, [], $user2);
|
||||
$response->assertStatus(409);
|
||||
|
||||
// Try now deleting the bid from the user
|
||||
$response = $this->delete($uri, $data);
|
||||
$body = $response->json('data');
|
||||
$this->assertCount(0, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a flight and make sure all the bids are gone
|
||||
*/
|
||||
public function testDeleteFlight()
|
||||
{
|
||||
$user = factory(User::class)->create();
|
||||
$headers = $this->headers($user);
|
||||
|
||||
$flight = $this->addFlight($user);
|
||||
|
||||
$bid = $this->flightSvc->addBid($flight, $user);
|
||||
$this->assertEquals($user->id, $bid->user_id);
|
||||
$this->assertEquals($flight->id, $bid->flight_id);
|
||||
$this->assertTrue($flight->has_bid);
|
||||
|
||||
$this->flightSvc->deleteFlight($flight);
|
||||
|
||||
$empty_flight = Flight::find($flight->id);
|
||||
$this->assertNull($empty_flight);
|
||||
|
||||
// Make sure no bids exist
|
||||
$user_bids = Bid::where('flight_id', $flight->id)->get();
|
||||
|
||||
//$this->assertEquals(0, $user_bid->count());
|
||||
|
||||
// Query the API and see that the user has the bids
|
||||
// And pull the flight details for the user/bids
|
||||
$req = $this->get('/api/user', $headers);
|
||||
$req->assertStatus(200);
|
||||
|
||||
$body = $req->json()['data'];
|
||||
$this->assertEquals($user->id, $body['id']);
|
||||
$this->assertCount(0, $body['bids']);
|
||||
|
||||
$req = $this->get('/api/users/'.$user->id.'/bids', $headers);
|
||||
$req->assertStatus(200);
|
||||
|
||||
$body = $req->json()['data'];
|
||||
$this->assertCount(0, $body);
|
||||
}
|
||||
|
||||
public function testAirportDistance()
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Models\Enums\PirepState;
|
||||
use App\Models\Pirep;
|
||||
use App\Models\User;
|
||||
use App\Repositories\SettingRepository;
|
||||
use App\Services\BidService;
|
||||
use App\Services\FlightService;
|
||||
use App\Services\PirepService;
|
||||
use Carbon\Carbon;
|
||||
@@ -358,6 +359,7 @@ class PIREPTest extends TestCase
|
||||
*/
|
||||
public function testPirepBidRemoved()
|
||||
{
|
||||
$bidSvc = app(BidService::class);
|
||||
$flightSvc = app(FlightService::class);
|
||||
$this->settingsRepo->store('pireps.remove_bid_on_accept', true);
|
||||
|
||||
@@ -370,11 +372,12 @@ class PIREPTest extends TestCase
|
||||
'route_leg' => null,
|
||||
]);
|
||||
|
||||
$flightSvc->addBid($flight, $user);
|
||||
$bidSvc->addBid($flight, $user);
|
||||
|
||||
$pirep = factory(App\Models\Pirep::class)->create([
|
||||
'user_id' => $user->id,
|
||||
'airline_id' => $flight->airline_id,
|
||||
'flight_id' => $flight->id,
|
||||
'flight_number' => $flight->flight_number,
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user