$data */ public function update(StaffAssignment $assignment, User $actor, array $data): StaffAssignment { return DB::transaction(function () use ($assignment, $actor, $data): StaffAssignment { $assignment->loadMissing(['election', 'position']); $election = $assignment->election; if (! $election instanceof Election) { throw ValidationException::withMessages([ 'election_id' => 'Pilihanraya tugasan tidak sah.', ]); } $this->postCloseNoteService->requireIfClosed($election, $data['note'] ?? null); /** @var Position $position */ $position = Position::query()->findOrFail($data['position_id']); /** @var PusatMengundi $pusat */ $pusat = PusatMengundi::query()->findOrFail($data['pusat_mengundi_id']); if ((int) $pusat->election_id !== (int) $election->id) { throw ValidationException::withMessages([ 'pusat_mengundi_id' => 'Pusat Mengundi tidak berada dalam pilihanraya yang sama.', ]); } $before = [ 'position_id' => $assignment->position_id, 'pusat_mengundi_id' => $assignment->pusat_mengundi_id, 'saluran_mengundi_id' => $assignment->saluran_mengundi_id, 'reports_to_assignment_id' => $assignment->reports_to_assignment_id, 'status' => $assignment->status, ]; $reportsToAssignmentId = $data['reports_to_assignment_id'] ?? null; $saluranMengundiId = $data['saluran_mengundi_id'] ?? null; if ($saluranMengundiId) { /** @var SaluranMengundi $saluran */ $saluran = SaluranMengundi::query()->findOrFail($saluranMengundiId); if ((int) $saluran->pusat_mengundi_id !== (int) $pusat->id) { throw ValidationException::withMessages([ 'saluran_mengundi_id' => 'Saluran Mengundi tidak berada di bawah Pusat Mengundi yang dipilih.', ]); } } if ($reportsToAssignmentId) { /** @var StaffAssignment $ktmAssignment */ $ktmAssignment = StaffAssignment::query() ->with('position') ->whereKey($reportsToAssignmentId) ->where('election_id', $election->id) ->where('pusat_mengundi_id', $pusat->id) ->where('status', 'active') ->firstOrFail(); $ktmPosition = $ktmAssignment->position; if (! $ktmPosition instanceof Position || $ktmPosition->code !== 'KTM') { throw ValidationException::withMessages([ 'reports_to_assignment_id' => 'Ketua rujukan mestilah tugasan KTM aktif.', ]); } if ((int) $ktmAssignment->id === (int) $assignment->id) { throw ValidationException::withMessages([ 'reports_to_assignment_id' => 'KTM tidak boleh melapor kepada tugasan sendiri.', ]); } $saluranMengundiId = $ktmAssignment->saluran_mengundi_id; } $assignment->forceFill([ 'position_id' => $position->id, 'pusat_mengundi_id' => $pusat->id, 'saluran_mengundi_id' => $saluranMengundiId, 'reports_to_assignment_id' => $reportsToAssignmentId, 'status' => $data['status'], 'assigned_by_user_id' => $actor->id, 'assigned_at' => now(), 'source' => 'admin_update', ])->save(); $assignment->histories()->create([ 'from_position_id' => $before['position_id'], 'to_position_id' => $position->id, 'from_pusat_mengundi_id' => $before['pusat_mengundi_id'], 'to_pusat_mengundi_id' => $pusat->id, 'from_saluran_mengundi_id' => $before['saluran_mengundi_id'], 'to_saluran_mengundi_id' => $saluranMengundiId, 'from_reports_to_assignment_id' => $before['reports_to_assignment_id'], 'to_reports_to_assignment_id' => $reportsToAssignmentId, 'changed_by_user_id' => $actor->id, 'note' => $data['note'] ?? 'Assignment updated by Admin.', ]); $application = $assignment->application; if ($application instanceof Application) { $application->forceFill([ 'pusat_mengundi_id' => $pusat->id, 'approved_position_id' => $position->id, 'selected_ktm_assignment_id' => $reportsToAssignmentId, 'status' => $data['status'] === 'active' ? 'assigned' : $application->status, ])->save(); } $this->operationalAccountService->provisionForAssignment($assignment, $position); $this->postCloseNoteService->recordIfClosed($election, $assignment, $actor, $data['note'] ?? null, 'admin_assignment_edit_after_close'); activity('admin_management') ->performedOn($assignment) ->causedBy($actor) ->withProperties([ 'before' => $before, 'after' => [ 'position_id' => $assignment->position_id, 'pusat_mengundi_id' => $assignment->pusat_mengundi_id, 'saluran_mengundi_id' => $assignment->saluran_mengundi_id, 'reports_to_assignment_id' => $assignment->reports_to_assignment_id, 'status' => $assignment->status, ], ]) ->log('staff_assignment_updated_by_admin'); return $assignment; }); } }