perf(secretary,billing): kill N+1 in secretary + claims lists (M8, M9)
M8: DoctorSecretary::toArray() lazy-loaded secretary/doctor/clinic per row; fetch-join them in findByDoctorScope/findByClinic (shared listWithRelations()). M9: enrichClaims() lazy-loaded each claim's items collection and called insuranceRepo->find() per claim. Fetch-join items in findByTenant (Paginator, fetchJoinCollection) and batch-fetch insurance names once. Regressions (query count constant vs row count): SecretaryListNPlusOneTest, ClaimsListNPlusOneTest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -63,9 +63,18 @@ class BillingController extends BaseController
|
||||
$sessionDates = $this->sessionRepo->datesForIds($uniqueSessionIds);
|
||||
$patientInfo = $this->sessionRepo->patientInfoForIds($uniqueSessionIds);
|
||||
|
||||
return array_map(function (Claim $claim) use ($itemDetails, $sessionDates, $patientInfo) {
|
||||
// Batch-fetch insurance names instead of one find() per claim (N+1).
|
||||
$insuranceIds = array_values(array_unique(array_map(fn(Claim $c) => $c->getInsuranceId(), $claims)));
|
||||
$insuranceNames = [];
|
||||
if ($insuranceIds !== []) {
|
||||
foreach ($this->insuranceRepo->findBy(['id' => $insuranceIds]) as $ins) {
|
||||
$insuranceNames[$ins->getId()] = $ins->getName();
|
||||
}
|
||||
}
|
||||
|
||||
return array_map(function (Claim $claim) use ($itemDetails, $sessionDates, $patientInfo, $insuranceNames) {
|
||||
$data = $claim->toArray();
|
||||
$data['insurance_name'] = $this->insuranceRepo->find($claim->getInsuranceId())?->getName();
|
||||
$data['insurance_name'] = $insuranceNames[$claim->getInsuranceId()] ?? null;
|
||||
|
||||
$patientName = null;
|
||||
$patientMobile = null;
|
||||
|
||||
Reference in New Issue
Block a user