where('election_id', $electionId) // Ensure we keep all voter columns when adding computed selects ->select('voter.*') // Computed: whether voter has any vote record for this election ->selectSub(function ($sq) use ($electionId) { $sq->from('result') ->selectRaw('COUNT(*)') ->whereColumn('result.voter_id', 'voter.id') ->where('result.election_id', $electionId); }, 'votes_count'); // Computed: payout timestamps (paperless coupon replacement state) $q->selectSub(function ($sq) use ($electionId) { $sq->from('allowance_payouts') ->selectRaw('MAX(paid_at)') ->whereColumn('allowance_payouts.voter_id', 'voter.id') ->where('allowance_payouts.election_id', $electionId) ->where('allowance_payouts.method', 'cash') ->where('allowance_payouts.status', 'paid'); }, 'cash_paid_at'); $q->selectSub(function ($sq) use ($electionId) { $sq->from('allowance_payouts') ->selectRaw('MAX(id)') ->whereColumn('allowance_payouts.voter_id', 'voter.id') ->where('allowance_payouts.election_id', $electionId) ->where('allowance_payouts.method', 'cash') ->where('allowance_payouts.status', 'paid'); }, 'cash_payout_id'); $q->selectSub(function ($sq) use ($electionId) { $sq->from('allowance_payouts') ->selectRaw('MAX(paid_at)') ->whereColumn('allowance_payouts.voter_id', 'voter.id') ->where('allowance_payouts.election_id', $electionId) ->where('allowance_payouts.method', 'bank') ->where('allowance_payouts.status', 'paid'); }, 'bank_paid_at'); $q->selectSub(function ($sq) use ($electionId) { $sq->from('allowance_payouts') ->selectRaw('MAX(id)') ->whereColumn('allowance_payouts.voter_id', 'voter.id') ->where('allowance_payouts.election_id', $electionId) ->where('allowance_payouts.method', 'bank') ->where('allowance_payouts.status', 'paid'); }, 'bank_payout_id'); // Optional search filters $noAnggota = request('no_anggota'); if ($noAnggota !== null && $noAnggota !== '') { $q->where('no_anggota', 'like', '%' . $noAnggota . '%'); } $noKp = request('no_kp'); if ($noKp !== null && $noKp !== '') { $q->where('no_kp', 'like', '%' . $noKp . '%'); } $name = request('name'); if ($name !== null && $name !== '') { $q->where('name', 'like', '%' . $name . '%'); } // Optional attendance filter: 1 = Fizikal, 2 = Maya $kehadiran = request('kehadiran'); if ($kehadiran !== null && $kehadiran !== '') { if ($kehadiran === 'unset') { $q->where(function ($qq) { $qq->whereNull('kehadiran')->orWhere('kehadiran', 0); }); } else { $k = (int) $kehadiran; if (in_array($k, [1, 2], true)) { $q->where('kehadiran', $k); } } } // Fizikal registration queue: pending = fizikal but not admin-verified yet $fizikalReg = request('fizikal_reg'); if ($fizikalReg !== null && $fizikalReg !== '') { if ($fizikalReg === 'pending') { $q->where('kehadiran', 1)->whereNull('fizikal_registration_verified_at'); } elseif ($fizikalReg === 'verified') { $q->where('kehadiran', 1)->whereNotNull('fizikal_registration_verified_at'); } } return $q->paginate(50); } }