It seems like the issue you're encountering is related to how Eloquent is eager loading the payments relationship after the initial query has been executed. When you're using defaultSort('-payments.payment_date'), it's sorting the initial query correctly, but the subsequent eager loading of the payments relationship for each Dues model is not considering the sort order.
The first() method on the payments() relationship is likely causing the issue because it retrieves the first Payment record it finds for the Dues model, which may not be the one with the latest payment_date if the records are not sorted.
To ensure that you always get the latest payment, you can define a separate relationship in your Dues model that always fetches the latest payment. Here's how you can do it:
class Dues extends Model
{
// ... existing code ...
public function latestPayment()
{
return $this->hasOne(Payment::class)->latest('payment_date');
}
}
Then, in your TreasuryReportResource, you can use this latestPayment relationship to get the correct payment date:
public function toArray($request)
{
return [
'member_number' => $this->user->member_number,
'first_name' => $this->user->first_preferred_name,
'last_name' => $this->user->last_name,
'amount' => number_format($this->total, 2),
'payment_date' => $this->latestPayment->payment_date, // Use the latestPayment relationship
'mode' => $this->latestPayment->mode
];
}
Make sure to include the latestPayment relationship in your query:
QueryBuilder::for(Dues::class)
->allowedIncludes(['payments', 'user', 'latestPayment']) // Include the latestPayment relationship
// ... rest of the query ...
This should ensure that the payment_date you're getting in the resource is always the latest one, and it should not be affected by the sorting of the initial query.
If you still want to sort the Dues based on the latest payment_date, you might need to adjust your query to use a subquery for sorting. Here's an example of how you could do that:
QueryBuilder::for(Dues::class)
->select('dues.*')
->joinSub(
Payment::select('dues_id', DB::raw('MAX(payment_date) as latest_payment_date'))
->groupBy('dues_id'),
'latest_payments',
'dues.id',
'=',
'latest_payments.dues_id'
)
->orderBy('latest_payments.latest_payment_date', 'desc') // Sort by the latest payment date
// ... rest of the query ...
This subquery joins the Dues with a derived table that contains the latest payment_date for each dues_id, allowing you to sort the results based on this date. Adjust the query as needed to fit your exact requirements.