$roleCodes * @return array> */ public function optionsForRoles(PusatMengundi $pusatMengundi, array $roleCodes = ['KP', 'KPDP'], ?int $ignoreApplicationId = null): array { $options = []; foreach ($roleCodes as $roleCode) { $options[$roleCode] = $this->availableKtmAssignments($pusatMengundi, $roleCode, $ignoreApplicationId) ->map(function (StaffAssignment $assignment) use ($roleCode, $ignoreApplicationId): array { $user = $assignment->user; $saluranMengundi = $assignment->saluranMengundi; return [ 'id' => $assignment->id, 'label' => trim( ($user instanceof User ? $user->name : 'KTM tanpa nama') .' - Saluran ' .($saluranMengundi instanceof SaluranMengundi ? $saluranMengundi->number : '-'), ), 'remaining' => $this->remainingVacancy($assignment, $roleCode, $ignoreApplicationId), ]; }) ->values() ->all(); } return $options; } public function hasVacancyForAssignment(int $assignmentId, PusatMengundi $pusatMengundi, string $roleCode, ?int $ignoreApplicationId = null): bool { $ktmPosition = Position::query()->where('code', 'KTM')->first(); if ($ktmPosition === null) { return false; } $assignment = StaffAssignment::query() ->with(['saluranMengundi', 'user']) ->where('id', $assignmentId) ->where('election_id', $pusatMengundi->election_id) ->where('pusat_mengundi_id', $pusatMengundi->id) ->where('position_id', $ktmPosition->id) ->where('status', 'active') ->whereNotNull('saluran_mengundi_id') ->first(); return $assignment instanceof StaffAssignment && $this->remainingVacancy($assignment, $roleCode, $ignoreApplicationId) > 0; } public function remainingForAssignment(StaffAssignment $assignment, string $roleCode, ?int $ignoreApplicationId = null): int { return $this->remainingVacancy($assignment, $roleCode, $ignoreApplicationId); } /** * @return Collection */ private function availableKtmAssignments(PusatMengundi $pusatMengundi, string $roleCode, ?int $ignoreApplicationId = null): Collection { return $this->ktmAssignments($pusatMengundi) ->filter(fn (StaffAssignment $assignment): bool => $this->remainingVacancy($assignment, $roleCode, $ignoreApplicationId) > 0) ->values(); } /** * @return EloquentCollection */ private function ktmAssignments(PusatMengundi $pusatMengundi): EloquentCollection { $ktmPosition = Position::query()->where('code', 'KTM')->first(); if ($ktmPosition === null) { return new EloquentCollection; } return StaffAssignment::query() ->with(['saluranMengundi', 'user']) ->where('election_id', $pusatMengundi->election_id) ->where('pusat_mengundi_id', $pusatMengundi->id) ->where('position_id', $ktmPosition->id) ->where('status', 'active') ->whereNotNull('saluran_mengundi_id') ->whereNotNull('user_id') ->orderBy('saluran_mengundi_id') ->get(); } private function remainingVacancy(StaffAssignment $ktmAssignment, string $roleCode, ?int $ignoreApplicationId = null): int { $position = Position::query()->where('code', $roleCode)->first(); if ($position === null || $ktmAssignment->saluran_mengundi_id === null) { return 0; } $quota = PositionQuota::query() ->where('election_id', $ktmAssignment->election_id) ->where('pusat_mengundi_id', $ktmAssignment->pusat_mengundi_id) ->where('saluran_mengundi_id', $ktmAssignment->saluran_mengundi_id) ->where('position_id', $position->id) ->value('quota'); if ($quota === null) { return 0; } $assignedCount = StaffAssignment::query() ->where('reports_to_assignment_id', $ktmAssignment->id) ->where('position_id', $position->id) ->where('status', 'active') ->count(); $reservedQuery = Application::query() ->where('selected_ktm_assignment_id', $ktmAssignment->id) ->where('requested_position_id', $position->id) ->whereIn('status', self::RESERVED_APPLICATION_STATUSES); if ($ignoreApplicationId !== null) { $reservedQuery->where('id', '!=', $ignoreApplicationId); } $reservedCount = $reservedQuery->count(); return max(0, (int) $quota - $assignedCount - $reservedCount); } }