#406 Refactor bids (#432)

* Add flight_id column to pireps table

* Refactor PIREPs and bids closes 406

* Formatting
This commit is contained in:
Nabeel S
2019-11-05 11:44:31 -05:00
committed by GitHub
parent db087d0ccb
commit f5183babf6
35 changed files with 967 additions and 798 deletions

145
app/Services/BidService.php Normal file
View 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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}
}