diff --git a/.github/scripts/env.test b/.github/scripts/env.test index 331fcd922..4da361afb 100644 --- a/.github/scripts/env.test +++ b/.github/scripts/env.test @@ -16,7 +16,7 @@ DB_HOST="127.0.0.1" DB_PORT="3306" DB_DATABASE="phpvms" DB_USERNAME="root" -DB_PASSWORD= +DB_PASSWORD="root" CACHE_DRIVER="file" CACHE_PREFIX= diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 55987919b..bb7104fd0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,6 +17,7 @@ jobs: env: extensions: intl, pcov, mbstring key: cache-v1 + MYSQL_ROOT_PASSWORD: root steps: - name: Checkout uses: actions/checkout@v3 @@ -60,16 +61,31 @@ jobs: - name: Shutdown Ubuntu MySQL run: sudo service mysql stop - - name: Install MariaDB - uses: getong/mariadb-action@v1.1 +# - name: Install MariaDB +# uses: getong/mariadb-action@v1.1 +# with: +# character set server: 'utf8' +# collation server: 'utf8_general_ci' +# mysql database: 'phpvms' +# mysql root password: '' +# mysql user: '' +# mysql password: '' + + - name: Install MySQL + uses: mirromutth/mysql-action@v1.1 with: - character set server: 'utf8' - collation server: 'utf8_general_ci' + mysql version: '8.0' mysql database: 'phpvms' - mysql root password: '' + mysql root password: $MYSQL_ROOT_PASSWORD mysql user: '' mysql password: '' + - name: Wait for MySQL + run: | + while ! mysqladmin ping -h127.0.0.1 --silent; do + sleep 1 + done + - name: Configure Environment run: | php --version diff --git a/app/Http/Resources/Subfleet.php b/app/Http/Resources/Subfleet.php index 263dae98c..deb106784 100644 --- a/app/Http/Resources/Subfleet.php +++ b/app/Http/Resources/Subfleet.php @@ -4,6 +4,9 @@ use App\Contracts\Resource; +/** + * @mixin \App\Models\Subfleet + */ class Subfleet extends Resource { public function toArray($request) diff --git a/app/Models/Aircraft.php b/app/Models/Aircraft.php index 3b5346cfe..5193d479a 100644 --- a/app/Models/Aircraft.php +++ b/app/Models/Aircraft.php @@ -40,6 +40,7 @@ * @property int state * @property Carbon landing_time * @property float fuel_onboard + * @property Bid bid */ class Aircraft extends Model { diff --git a/app/Models/Bid.php b/app/Models/Bid.php index 2bf437271..94c1d9f71 100644 --- a/app/Models/Bid.php +++ b/app/Models/Bid.php @@ -7,14 +7,15 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; /** - * @property int user_id - * @property string flight_id - * @property int aircraft_id - * @property Carbon created_at - * @property Carbon updated_at - * @property Aircraft aircraft - * @property Flight flight - * @property User user + * @property int user_id + * @property string flight_id + * @property int aircraft_id + * @property Carbon created_at + * @property Carbon updated_at + * @property Aircraft aircraft + * @property Flight flight + * @property User user + * @property mixed flights */ class Bid extends Model { diff --git a/app/Models/Subfleet.php b/app/Models/Subfleet.php index ca65a7aac..9ce121def 100644 --- a/app/Models/Subfleet.php +++ b/app/Models/Subfleet.php @@ -16,19 +16,20 @@ use Kyslik\ColumnSortable\Sortable; /** - * @property int id - * @property string type - * @property string simbrief_type - * @property string name - * @property int airline_id - * @property int hub_id - * @property string ground_handling_multiplier - * @property Fare[] fares - * @property float cost_block_hour - * @property float cost_delay_minute - * @property Airline airline - * @property Airport home - * @property int fuel_type + * @property int id + * @property string type + * @property string simbrief_type + * @property string name + * @property int airline_id + * @property int hub_id + * @property string ground_handling_multiplier + * @property Fare[] fares + * @property float cost_block_hour + * @property float cost_delay_minute + * @property Airline airline + * @property Airport home + * @property int fuel_type + * @property Aircraft[] $aircraft */ class Subfleet extends Model { @@ -97,7 +98,10 @@ public function type(): Attribute */ public function aircraft(): HasMany { - return $this->hasMany(Aircraft::class, 'subfleet_id')->where('status', AircraftStatus::ACTIVE); + return $this->hasMany(Aircraft::class, 'subfleet_id')->where( + 'status', + AircraftStatus::ACTIVE + ); } public function airline(): BelongsTo @@ -111,9 +115,9 @@ public function home(): HasOne } /** - * @deprecated use home() - * * @return HasOne + * + * @deprecated use home() */ public function hub(): HasOne { @@ -122,7 +126,11 @@ public function hub(): HasOne public function fares(): BelongsToMany { - return $this->belongsToMany(Fare::class, 'subfleet_fare')->withPivot('price', 'cost', 'capacity'); + return $this->belongsToMany(Fare::class, 'subfleet_fare')->withPivot( + 'price', + 'cost', + 'capacity' + ); } public function flights(): BelongsToMany @@ -133,11 +141,16 @@ public function flights(): BelongsToMany public function ranks(): BelongsToMany { return $this->belongsToMany(Rank::class, 'subfleet_rank') - ->withPivot('acars_pay', 'manual_pay'); + ->withPivot('acars_pay', 'manual_pay'); } public function typeratings(): BelongsToMany { - return $this->belongsToMany(Typerating::class, 'typerating_subfleet', 'subfleet_id', 'typerating_id'); + return $this->belongsToMany( + Typerating::class, + 'typerating_subfleet', + 'subfleet_id', + 'typerating_id' + ); } } diff --git a/app/Models/User.php b/app/Models/User.php index 779661722..d2f5da5ef 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -59,6 +59,7 @@ * @property Airport home_airport * @property Airport current_airport * @property Airport location + * @property Bid[] bids * * @mixin \Illuminate\Database\Eloquent\Builder * @mixin \Illuminate\Notifications\Notifiable diff --git a/app/Services/BidService.php b/app/Services/BidService.php index 0f47d20bd..a80ae40d7 100644 --- a/app/Services/BidService.php +++ b/app/Services/BidService.php @@ -35,6 +35,7 @@ public function getBid(User $user, $bid_id): ?Bid { $with = [ 'aircraft', + 'aircraft.subfleet', 'flight', 'flight.fares', 'flight.simbrief' => function ($query) use ($user) { @@ -56,7 +57,12 @@ public function getBid(User $user, $bid_id): ?Bid // Reconcile the aircraft for this bid // TODO: Only do this if there isn't a Simbrief attached? - $bid->flight = $this->flightSvc->filterSubfleets($user, $bid->flight); + if (!empty($bid->aircraft)) { + $bid->flight->subfleets = $this->flightSvc->getSubfleetsForBid($bid); + } else { + $bid->flight = $this->flightSvc->filterSubfleets($user, $bid->flight, $bid); + } + $bid->flight = $this->fareSvc->getReconciledFaresForFlight($bid->flight); return $bid; @@ -89,10 +95,13 @@ public function findBidsForUser(User $user): Collection|array|null $bids = Bid::with($with)->where(['user_id' => $user->id])->get(); foreach ($bids as $bid) { - // if (empty($bid->flight->simbrief)) { - $bid->flight = $this->flightSvc->filterSubfleets($user, $bid->flight); + if (!empty($bid->aircraft)) { + $bid->flight->subfleets = $this->flightSvc->getSubfleetsForBid($bid); + } else { + $bid->flight = $this->flightSvc->filterSubfleets($user, $bid->flight, $bid); + } + $bid->flight = $this->fareSvc->getReconciledFaresForFlight($bid->flight); - // } } return $bids; diff --git a/app/Services/FlightService.php b/app/Services/FlightService.php index 6a6200893..c7d62f6c9 100644 --- a/app/Services/FlightService.php +++ b/app/Services/FlightService.php @@ -4,12 +4,14 @@ use App\Contracts\Service; use App\Exceptions\DuplicateFlight; +use App\Models\Aircraft; use App\Models\Bid; use App\Models\Enums\Days; use App\Models\Enums\PirepState; use App\Models\Enums\PirepStatus; use App\Models\Flight; use App\Models\FlightFieldValue; +use App\Models\Subfleet; use App\Models\User; use App\Repositories\FlightRepository; use App\Repositories\NavdataRepository; @@ -121,6 +123,26 @@ protected function transformFlightFields($fields) return $fields; } + /** + * Return the proper subfleets for the given bid + * + * @param Bid $bid + * + * @return mixed + */ + public function getSubfleetsForBid(Bid $bid) + { + $sf = Subfleet::with([ + 'fares', + 'aircraft' => function ($query) use ($bid) { + $query->where('id', $bid->aircraft_id); + }]) + ->where('id', $bid->aircraft->subfleet_id) + ->get(); + + return $sf; + } + /** * Filter out subfleets to only include aircraft that a user has access to * @@ -156,6 +178,8 @@ public function filterSubfleets(User $user, Flight $flight) if ($allowed_subfleets->contains($subfleet->id)) { return true; } + + return false; }); } @@ -179,7 +203,9 @@ function ($aircraft, $i) use ($user, $flight, $aircraft_at_dpt_airport, $aircraf return true; } - ); + )->sortBy(function (Aircraft $ac, int $_) { + return !empty($ac->bid); + }); } } diff --git a/tests/BidTest.php b/tests/BidTest.php index 04e9cd03b..5dadab197 100644 --- a/tests/BidTest.php +++ b/tests/BidTest.php @@ -4,7 +4,6 @@ use App\Exceptions\BidExistsForAircraft; use App\Exceptions\BidExistsForFlight; -use App\Models\Aircraft; use App\Models\Bid; use App\Models\Fare; use App\Models\Flight; @@ -64,6 +63,7 @@ public function testBids() $this->settingsRepo->store('bids.allow_multiple_bids', true); $this->settingsRepo->store('bids.disable_flight_on_bid', false); + /** @var Subfleet $subfleet */ $subfleet = $this->createSubfleetWithAircraft(2); $rank = $this->createRank(2, [$subfleet['subfleet']->id]); @@ -87,11 +87,13 @@ public function testBids() /** @var Flight $flight */ $flight = $this->addFlight($user, $subfleet['subfleet']->id); - $bid = $this->bidSvc->addBid($flight, $user); + $bid = $this->bidSvc->addBid($flight, $user, $subfleet['aircraft'][0]); $this->assertEquals($user->id, $bid->user_id); $this->assertEquals($flight->id, $bid->flight_id); $this->assertTrue($flight->has_bid); + $flight = $bid->flight; + // Refresh $flight = Flight::find($flight->id); $this->assertTrue($flight->has_bid); @@ -263,25 +265,32 @@ public function testDeleteFlightWithBids() */ public function testBidWithAircraft() { + $this->settingsRepo->store('pireps.restrict_aircraft_to_rank', false); + $this->settingsRepo->store('pireps.only_aircraft_at_dpt_airport', false); $this->settingsRepo->store('bids.allow_multiple_bids', true); $this->settingsRepo->store('bids.block_aircraft', true); $user = User::factory()->create(); $headers = $this->headers($user); - $subfleet = $this->createSubfleetWithAircraft(1); + $subfleet_unused = $this->createSubfleetWithAircraft(10); + $subfleet = $this->createSubfleetWithAircraft(10); $aircraft = $subfleet['aircraft']->first(); $flight = $this->addFlight($user, $subfleet['subfleet']->id); + $flight->subfleets()->syncWithoutDetaching([$subfleet_unused['subfleet']->id]); $bid = $this->bidSvc->addBid($flight, $user, $aircraft); + $bid_flight = $bid->flight; + $this->assertEquals(1, $bid_flight->subfleets[0]->aircraft->count()); + $this->assertEquals($user->id, $bid->user_id); $this->assertEquals($flight->id, $bid->flight_id); $this->assertEquals($aircraft->id, $bid->aircraft_id); $this->assertTrue($flight->has_bid); // Expect aircraft to have a bid - $this->assertEquals($aircraft->bid->count(), 1); + $this->assertEquals(1, $aircraft->bid->count()); // Now add another bid on another flight with the same aircraft, should throw an exception $flight2 = $this->addFlight($user, $subfleet['subfleet']->id);