Summary
DB_StatServices::PirepStats($airline_id, $aircraft_id) reports VA-wide PAX and Cargo totals on every airline-detail / aircraft-detail page, instead of the figures for the selected airline/aircraft. All other stats (flights, time, distance, fuel, landing rate) are correctly scoped — only Total/Avg Passengers and Total/Avg Freight are wrong.
It's most obvious on a small operator: on our install a business-jet airline (6 accepted PIREPs, ~31 pax / ~993 kg total) showed 439,756 passengers and 33,932,376 kg freight — the totals of the whole VA.
Root cause
In Services/DB_StatServices.php, PirepStats():
$allpireps = Pirep::where('state', '!=', PirepState::ACCEPTED)->when(isset($airline_id), ...airline_id...)
->when(isset($aircraft_id), ...aircraft_id...)->pluck('id')->toArray();
$pax_amount = PirepFare::where('type', FareType::PASSENGER)->whereNotIn('pirep_id', $allpireps)->sum('count');
// + pax_avg, cgo_amount, cgo_avg
$allpireps is the list of non-accepted PIREPs of this airline only. Using it as a whereNotIn blacklist therefore excludes just that handful of rows and still sums the fares of every other airline's accepted PIREPs. The scoping intent (airline/aircraft) is lost entirely for PAX/CGO.
Suggested fix
Switch from a blacklist to a whitelist of the in-scope accepted PIREPs and use whereIn:
$scoped_pireps = Pirep::where('state', PirepState::ACCEPTED)
->when(isset($airline_id), fn ($q) => $q->where('airline_id', $airline_id))
->when(isset($aircraft_id), fn ($q) => $q->where('aircraft_id', $aircraft_id))
->pluck('id')->toArray();
if (count($scoped_pireps) > 0) {
$pax_amount = PirepFare::where('type', FareType::PASSENGER)->whereIn('pirep_id', $scoped_pireps)->sum('count');
$pax_avg = PirepFare::where('type', FareType::PASSENGER)->whereIn('pirep_id', $scoped_pireps)->avg('count');
$cgo_amount = PirepFare::where('type', FareType::CARGO)->whereIn('pirep_id', $scoped_pireps)->sum('count');
$cgo_avg = PirepFare::where('type', FareType::CARGO)->whereIn('pirep_id', $scoped_pireps)->avg('count');
} else {
$pax_amount = 0;
$cgo_amount = 0;
}
The original < 65500 guard was a workaround for large whereNotIn lists; with a whitelist of accepted PIREPs it's no longer needed (a > 0 guard is enough to skip the work and avoid an empty IN ()).
Note: the global statistics page (PirepStats() with no args) keeps returning VA-wide totals, which is correct — when both $airline_id and $aircraft_id are null the whitelist is simply "all accepted PIREPs". ApiPirepStats() is global by design and unaffected.
Verified on phpVMS 7.x with DisposableBasic v3.7.4. Happy to open a PR if useful.
Summary
DB_StatServices::PirepStats($airline_id, $aircraft_id)reports VA-wide PAX and Cargo totals on every airline-detail / aircraft-detail page, instead of the figures for the selected airline/aircraft. All other stats (flights, time, distance, fuel, landing rate) are correctly scoped — onlyTotal/Avg PassengersandTotal/Avg Freightare wrong.It's most obvious on a small operator: on our install a business-jet airline (6 accepted PIREPs, ~31 pax / ~993 kg total) showed 439,756 passengers and 33,932,376 kg freight — the totals of the whole VA.
Root cause
In
Services/DB_StatServices.php,PirepStats():$allpirepsis the list of non-accepted PIREPs of this airline only. Using it as awhereNotInblacklist therefore excludes just that handful of rows and still sums the fares of every other airline's accepted PIREPs. The scoping intent (airline/aircraft) is lost entirely for PAX/CGO.Suggested fix
Switch from a blacklist to a whitelist of the in-scope accepted PIREPs and use
whereIn:The original
< 65500guard was a workaround for largewhereNotInlists; with a whitelist of accepted PIREPs it's no longer needed (a> 0guard is enough to skip the work and avoid an emptyIN ()).Note: the global statistics page (
PirepStats()with no args) keeps returning VA-wide totals, which is correct — when both$airline_idand$aircraft_idare null the whitelist is simply "all accepted PIREPs".ApiPirepStats()is global by design and unaffected.Verified on phpVMS 7.x with DisposableBasic v3.7.4. Happy to open a PR if useful.