first
This commit is contained in:
57
app/Http/Controllers/Admin/AttendanceController.php
Normal file
57
app/Http/Controllers/Admin/AttendanceController.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Concerns\SortsQuery;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\PusatMengundi;
|
||||
use App\Models\StaffAssignment;
|
||||
use App\Services\Attendance\AttendanceExportService;
|
||||
use App\Services\Attendance\AttendanceSummaryService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\View\View;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
class AttendanceController extends Controller
|
||||
{
|
||||
use SortsQuery;
|
||||
|
||||
public function index(AttendanceSummaryService $summaryService): View
|
||||
{
|
||||
return view('admin.attendance.index', [
|
||||
'pusats' => $this->sortedQuery(
|
||||
PusatMengundi::query()->with(['election.settings']),
|
||||
['code', 'name'],
|
||||
'name'
|
||||
)->paginate(15)->withQueryString(),
|
||||
'summaryService' => $summaryService,
|
||||
]);
|
||||
}
|
||||
|
||||
public function show(PusatMengundi $pusatMengundi, AttendanceSummaryService $summaryService): View
|
||||
{
|
||||
$assignments = StaffAssignment::query()
|
||||
->with(['application', 'user', 'position', 'saluranMengundi', 'attendance.recordedBy'])
|
||||
->where('pusat_mengundi_id', $pusatMengundi->id)
|
||||
->where('status', 'active')
|
||||
->orderBy('position_id')
|
||||
->orderBy('saluran_mengundi_id')
|
||||
->get();
|
||||
|
||||
return view('admin.attendance.show', [
|
||||
'pusat' => $pusatMengundi->load('election.settings'),
|
||||
'assignments' => $assignments,
|
||||
'summary' => $summaryService->totalsForPusat($pusatMengundi),
|
||||
'roleSummaries' => $summaryService->roleTotalsForPusat($pusatMengundi),
|
||||
]);
|
||||
}
|
||||
|
||||
public function export(PusatMengundi $pusatMengundi, Request $request, AttendanceExportService $exportService): StreamedResponse
|
||||
{
|
||||
$exportLog = $exportService->exportPusat($request->user(), $pusatMengundi);
|
||||
|
||||
return Storage::disk($exportLog->disk ?? 'local')
|
||||
->download($exportLog->path, $exportLog->file_name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Management;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Application;
|
||||
use App\Models\JkmRepresentative;
|
||||
use App\Models\KkmRepresentative;
|
||||
use App\Models\PoliceEscort;
|
||||
use App\Models\StaffAssignment;
|
||||
use App\Models\WheelchairAllocation;
|
||||
use App\Services\Admin\Management\WheelchairManagementService;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AdminManagementController extends Controller
|
||||
{
|
||||
public function index(WheelchairManagementService $wheelchairService): View
|
||||
{
|
||||
$allocations = WheelchairAllocation::query()->with('transactions')->get();
|
||||
|
||||
return view('admin.management.index', [
|
||||
'counts' => [
|
||||
'applications' => Application::query()->count(),
|
||||
'assigned' => Application::query()->where('status', 'assigned')->count(),
|
||||
'staffAssignments' => StaffAssignment::query()->where('status', 'active')->count(),
|
||||
'representatives' => PoliceEscort::query()->count() + KkmRepresentative::query()->count() + JkmRepresentative::query()->count(),
|
||||
'missingDocuments' => Application::query()
|
||||
->whereDoesntHave('documents', fn ($query) => $query->where('document_type', 'ic_document'))
|
||||
->orWhereDoesntHave('documents', fn ($query) => $query->where('document_type', 'bank_statement'))
|
||||
->count(),
|
||||
'incompleteBank' => Application::query()
|
||||
->where(fn ($query) => $query->whereNull('bank_name')->orWhereNull('bank_account_number'))
|
||||
->count(),
|
||||
'wheelchairAllocated' => $allocations->sum('allocated_quantity'),
|
||||
'wheelchairOutstanding' => $allocations->sum(fn (WheelchairAllocation $allocation): int => $wheelchairService->outstandingQuantity($allocation)),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Management;
|
||||
|
||||
use App\Http\Concerns\SortsQuery;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Management\AssignApplicationRequest;
|
||||
use App\Http\Requests\Admin\Management\StoreManualApplicationRequest;
|
||||
use App\Http\Requests\Admin\Management\UpdateManagedApplicationRequest;
|
||||
use App\Models\Application;
|
||||
use App\Models\Election;
|
||||
use App\Models\Position;
|
||||
use App\Models\PusatMengundi;
|
||||
use App\Models\SaluranMengundi;
|
||||
use App\Models\StaffAssignment;
|
||||
use App\Services\Admin\Management\AdminApplicationManagementService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class ManagedApplicationController extends Controller
|
||||
{
|
||||
use SortsQuery;
|
||||
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$query = Application::query()
|
||||
->with(['election', 'pusatMengundi', 'requestedPosition', 'approvedPosition', 'selectedKtmAssignment.user'])
|
||||
->when($request->filled('status'), fn ($q) => $q->where('status', $request->string('status')))
|
||||
->when($request->filled('pusat_mengundi_id'), fn ($q) => $q->where('pusat_mengundi_id', $request->integer('pusat_mengundi_id')))
|
||||
->when($request->filled('position_id'), function ($q) use ($request): void {
|
||||
$q->where(function ($nested) use ($request): void {
|
||||
$nested->where('requested_position_id', $request->integer('position_id'))
|
||||
->orWhere('approved_position_id', $request->integer('position_id'));
|
||||
});
|
||||
})
|
||||
->when($request->filled('q'), function ($q) use ($request): void {
|
||||
$term = '%'.$request->string('q')->toString().'%';
|
||||
$q->where(fn ($nested) => $nested
|
||||
->where('name', 'like', $term)
|
||||
->orWhere('ic_number', 'like', $term)
|
||||
->orWhere('email', 'like', $term));
|
||||
});
|
||||
|
||||
$applications = $this->sortedQuery($query, ['name', 'status', 'created_at'], 'created_at', 'desc')
|
||||
->paginate(15)
|
||||
->withQueryString();
|
||||
|
||||
return view('admin.management.applications.index', [
|
||||
'applications' => $applications,
|
||||
'positions' => Position::query()->orderBy('sort_order')->orderBy('name')->get(),
|
||||
'pusats' => PusatMengundi::query()->orderBy('name')->get(),
|
||||
'filters' => $request->only(['status', 'pusat_mengundi_id', 'position_id', 'q']),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(): View
|
||||
{
|
||||
return view('admin.management.applications.create', $this->formData([
|
||||
'application' => new Application,
|
||||
]));
|
||||
}
|
||||
|
||||
public function store(StoreManualApplicationRequest $request, AdminApplicationManagementService $service): RedirectResponse
|
||||
{
|
||||
$application = $service->create($request->user(), $request->validated());
|
||||
|
||||
return redirect()->route('admin.management.applications.edit', $application->public_uuid)
|
||||
->with('status', 'Permohonan manual telah disimpan.');
|
||||
}
|
||||
|
||||
public function edit(Application $application): View
|
||||
{
|
||||
return view('admin.management.applications.edit', $this->formData([
|
||||
'application' => $application->load(['election.settings', 'pusatMengundi', 'requestedPosition', 'approvedPosition', 'documents', 'staffAssignments.position', 'staffAssignments.saluranMengundi', 'statusHistories']),
|
||||
]));
|
||||
}
|
||||
|
||||
public function update(UpdateManagedApplicationRequest $request, Application $application, AdminApplicationManagementService $service): RedirectResponse
|
||||
{
|
||||
$service->update($application, $request->user(), $request->validated());
|
||||
|
||||
return redirect()->route('admin.management.applications.edit', $application->public_uuid)
|
||||
->with('status', 'Permohonan telah dikemas kini.');
|
||||
}
|
||||
|
||||
public function assign(AssignApplicationRequest $request, Application $application, AdminApplicationManagementService $service): RedirectResponse
|
||||
{
|
||||
$service->assign($application, $request->user(), $request->validated());
|
||||
|
||||
return redirect()->route('admin.management.applications.edit', $application->public_uuid)
|
||||
->with('status', 'Tugasan staf telah dikemas kini.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $extra
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function formData(array $extra = []): array
|
||||
{
|
||||
$ktmPosition = Position::query()->where('code', 'KTM')->first();
|
||||
|
||||
return [
|
||||
...$extra,
|
||||
'elections' => Election::query()->with('settings')->orderByDesc('id')->get(),
|
||||
'pusats' => PusatMengundi::query()->with('election')->orderBy('name')->get(),
|
||||
'salurans' => SaluranMengundi::query()->with('pusatMengundi')->orderBy('number')->get(),
|
||||
'positions' => Position::query()->where('is_assignable', true)->orderBy('sort_order')->orderBy('name')->get(),
|
||||
'ktmAssignments' => $ktmPosition
|
||||
? StaffAssignment::query()
|
||||
->with(['user', 'pusatMengundi', 'saluranMengundi'])
|
||||
->where('position_id', $ktmPosition->id)
|
||||
->where('status', 'active')
|
||||
->whereNotNull('saluran_mengundi_id')
|
||||
->orderByDesc('id')
|
||||
->get()
|
||||
: collect(),
|
||||
];
|
||||
}
|
||||
}
|
||||
107
app/Http/Controllers/Admin/Management/PennempatanController.php
Normal file
107
app/Http/Controllers/Admin/Management/PennempatanController.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Management;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Position;
|
||||
use App\Models\PusatMengundi;
|
||||
use App\Models\SaluranMengundi;
|
||||
use App\Models\StaffAssignment;
|
||||
use App\Services\Admin\Management\PennempatanService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PennempatanController extends Controller
|
||||
{
|
||||
public function show(PusatMengundi $pusatMengundi, PennempatanService $service): View
|
||||
{
|
||||
$pusatMengundi->load(['dun', 'election', 'saluranMengundis']);
|
||||
|
||||
$ppmPosition = Position::query()->where('code', 'PPM')->first();
|
||||
$ppmAssignment = $ppmPosition
|
||||
? StaffAssignment::query()
|
||||
->with('application')
|
||||
->where('pusat_mengundi_id', $pusatMengundi->id)
|
||||
->where('position_id', $ppmPosition->id)
|
||||
->where('status', 'active')
|
||||
->whereNull('saluran_mengundi_id')
|
||||
->first()
|
||||
: null;
|
||||
|
||||
return view('admin.management.penempatan.show', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'ppm' => $ppmAssignment,
|
||||
'sections' => $service->detailForPusat($pusatMengundi),
|
||||
]);
|
||||
}
|
||||
|
||||
public function lepas(Request $request, PusatMengundi $pusatMengundi, StaffAssignment $assignment): RedirectResponse
|
||||
{
|
||||
abort_unless($assignment->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
|
||||
$assignment->update([
|
||||
'status' => 'inactive',
|
||||
'assigned_by_user_id' => $request->user()->id,
|
||||
]);
|
||||
|
||||
activity('admin_management')
|
||||
->performedOn($assignment)
|
||||
->causedBy($request->user())
|
||||
->log('assignment_removed_by_admin');
|
||||
|
||||
return redirect()->route('admin.management.penempatan.show', $pusatMengundi)
|
||||
->with('status', 'Petugas telah dilepaskan dari tugasan.');
|
||||
}
|
||||
|
||||
public function pindahForm(PusatMengundi $pusatMengundi, StaffAssignment $assignment): View
|
||||
{
|
||||
abort_unless($assignment->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
|
||||
return view('admin.management.penempatan.pindah', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'assignment' => $assignment->load(['application', 'position', 'saluranMengundi']),
|
||||
'pusats' => PusatMengundi::query()->with('election')->orderBy('code')->get(),
|
||||
'salurans' => SaluranMengundi::query()
|
||||
->where('pusat_mengundi_id', $pusatMengundi->id)
|
||||
->orderBy('number')
|
||||
->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function pindah(Request $request, PusatMengundi $pusatMengundi, StaffAssignment $assignment): RedirectResponse
|
||||
{
|
||||
abort_unless($assignment->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
|
||||
$data = $request->validate([
|
||||
'pusat_mengundi_id' => ['required', 'exists:pusat_mengundis,id'],
|
||||
'saluran_mengundi_id' => ['nullable', 'exists:saluran_mengundis,id'],
|
||||
]);
|
||||
|
||||
$newPusat = PusatMengundi::query()->findOrFail($data['pusat_mengundi_id']);
|
||||
|
||||
$assignment->update([
|
||||
'pusat_mengundi_id' => $newPusat->id,
|
||||
'saluran_mengundi_id' => $data['saluran_mengundi_id'] ?? null,
|
||||
'assigned_by_user_id' => $request->user()->id,
|
||||
'assigned_at' => now(),
|
||||
]);
|
||||
|
||||
// Update linked application's pusat too
|
||||
if ($assignment->application) {
|
||||
$assignment->application->forceFill(['pusat_mengundi_id' => $newPusat->id])->save();
|
||||
}
|
||||
|
||||
activity('admin_management')
|
||||
->performedOn($assignment)
|
||||
->causedBy($request->user())
|
||||
->withProperties([
|
||||
'from_pusat_id' => $pusatMengundi->id,
|
||||
'to_pusat_id' => $newPusat->id,
|
||||
])
|
||||
->log('assignment_transferred_by_admin');
|
||||
|
||||
return redirect()->route('admin.management.penempatan.show', $newPusat)
|
||||
->with('status', 'Petugas telah dipindahkan ke '.$newPusat->name.'.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Management;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Management\DeleteRepresentativeRequest;
|
||||
use App\Http\Requests\Admin\Management\StoreRepresentativeRequest;
|
||||
use App\Models\Election;
|
||||
use App\Models\JkmRepresentative;
|
||||
use App\Models\KkmRepresentative;
|
||||
use App\Models\PoliceEscort;
|
||||
use App\Models\PusatMengundi;
|
||||
use App\Models\SaluranMengundi;
|
||||
use App\Services\Admin\Management\AdminRepresentativeService;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class RepresentativeController extends Controller
|
||||
{
|
||||
public function index(): View
|
||||
{
|
||||
return view('admin.management.representatives.index', [
|
||||
'policeEscorts' => PoliceEscort::query()->with(['election', 'pusatMengundi', 'saluranMengundi'])->orderBy('name')->paginate(10, ['*'], 'police_page'),
|
||||
'kkmRepresentatives' => KkmRepresentative::query()->with(['election', 'pusatMengundi'])->orderBy('name')->paginate(10, ['*'], 'kkm_page'),
|
||||
'jkmRepresentatives' => JkmRepresentative::query()->with(['election', 'pusatMengundi'])->orderBy('name')->paginate(10, ['*'], 'jkm_page'),
|
||||
'elections' => Election::query()->orderByDesc('id')->get(),
|
||||
'pusats' => PusatMengundi::query()->orderBy('name')->get(),
|
||||
'salurans' => SaluranMengundi::query()->with('pusatMengundi')->orderBy('number')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(StoreRepresentativeRequest $request, AdminRepresentativeService $service): RedirectResponse
|
||||
{
|
||||
$service->store($request->user(), $request->validated());
|
||||
|
||||
return redirect()->route('admin.management.representatives.index')
|
||||
->with('status', 'Wakil agensi telah disimpan.');
|
||||
}
|
||||
|
||||
public function destroy(DeleteRepresentativeRequest $request, string $type, int $id, AdminRepresentativeService $service): RedirectResponse
|
||||
{
|
||||
$service->delete($this->resolveRepresentative($type, $id), $request->user(), $request->validated('note'));
|
||||
|
||||
return redirect()->route('admin.management.representatives.index')
|
||||
->with('status', 'Wakil agensi telah dipadam.');
|
||||
}
|
||||
|
||||
private function resolveRepresentative(string $type, int $id): Model
|
||||
{
|
||||
return match ($type) {
|
||||
'police' => PoliceEscort::query()->findOrFail($id),
|
||||
'kkm' => KkmRepresentative::query()->findOrFail($id),
|
||||
'jkm' => JkmRepresentative::query()->findOrFail($id),
|
||||
default => abort(404),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Management;
|
||||
|
||||
use App\Http\Concerns\SortsQuery;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Management\UpdateStaffAssignmentRequest;
|
||||
use App\Models\Position;
|
||||
use App\Models\PusatMengundi;
|
||||
use App\Models\SaluranMengundi;
|
||||
use App\Models\StaffAssignment;
|
||||
use App\Services\Admin\Management\AdminAssignmentManagementService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class StaffAssignmentController extends Controller
|
||||
{
|
||||
use SortsQuery;
|
||||
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$query = StaffAssignment::query()
|
||||
->with(['application', 'user', 'position', 'pusatMengundi', 'saluranMengundi', 'reportsTo.user'])
|
||||
->when($request->filled('pusat_mengundi_id'), fn ($q) => $q->where('pusat_mengundi_id', $request->integer('pusat_mengundi_id')))
|
||||
->when($request->filled('position_id'), fn ($q) => $q->where('position_id', $request->integer('position_id')))
|
||||
->when($request->filled('status'), fn ($q) => $q->where('status', $request->string('status')));
|
||||
|
||||
return view('admin.management.assignments.index', [
|
||||
'assignments' => $this->sortedQuery($query, ['status', 'assigned_at'], 'id', 'desc')
|
||||
->paginate(15)
|
||||
->withQueryString(),
|
||||
'positions' => Position::query()->orderBy('sort_order')->orderBy('name')->get(),
|
||||
'pusats' => PusatMengundi::query()->orderBy('name')->get(),
|
||||
'filters' => $request->only(['pusat_mengundi_id', 'position_id', 'status']),
|
||||
]);
|
||||
}
|
||||
|
||||
public function edit(StaffAssignment $assignment): View
|
||||
{
|
||||
$ktmPosition = Position::query()->where('code', 'KTM')->first();
|
||||
|
||||
return view('admin.management.assignments.edit', [
|
||||
'assignment' => $assignment->load(['application', 'user', 'election.settings', 'position', 'pusatMengundi', 'saluranMengundi', 'reportsTo.user', 'histories']),
|
||||
'positions' => Position::query()->where('is_assignable', true)->orderBy('sort_order')->orderBy('name')->get(),
|
||||
'pusats' => PusatMengundi::query()->with('election')->orderBy('name')->get(),
|
||||
'salurans' => SaluranMengundi::query()->with('pusatMengundi')->orderBy('number')->get(),
|
||||
'ktmAssignments' => $ktmPosition
|
||||
? StaffAssignment::query()
|
||||
->with(['user', 'pusatMengundi', 'saluranMengundi'])
|
||||
->where('position_id', $ktmPosition->id)
|
||||
->where('status', 'active')
|
||||
->where('id', '!=', $assignment->id)
|
||||
->whereNotNull('saluran_mengundi_id')
|
||||
->orderByDesc('id')
|
||||
->get()
|
||||
: collect(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpdateStaffAssignmentRequest $request, StaffAssignment $assignment, AdminAssignmentManagementService $service): RedirectResponse
|
||||
{
|
||||
$service->update($assignment, $request->user(), $request->validated());
|
||||
|
||||
return redirect()->route('admin.management.assignments.edit', $assignment)
|
||||
->with('status', 'Tugasan staf telah dikemas kini.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Management;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Management\StoreReturnTransactionRequest;
|
||||
use App\Http\Requests\Admin\Management\StoreTakenTransactionRequest;
|
||||
use App\Http\Requests\Admin\Management\UpsertWheelchairAllocationRequest;
|
||||
use App\Models\Election;
|
||||
use App\Models\PusatMengundi;
|
||||
use App\Models\WheelchairAllocation;
|
||||
use App\Services\Admin\Management\WheelchairManagementService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class WheelchairController extends Controller
|
||||
{
|
||||
public function index(WheelchairManagementService $service): View
|
||||
{
|
||||
$allocations = WheelchairAllocation::query()
|
||||
->with(['election', 'pusatMengundi', 'transactions'])
|
||||
->latest()
|
||||
->paginate(15);
|
||||
|
||||
return view('admin.management.wheelchairs.index', [
|
||||
'allocations' => $allocations,
|
||||
'elections' => Election::query()->orderByDesc('id')->get(),
|
||||
'pusats' => PusatMengundi::query()->orderBy('name')->get(),
|
||||
'service' => $service,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(UpsertWheelchairAllocationRequest $request, WheelchairManagementService $service): RedirectResponse
|
||||
{
|
||||
$allocation = $service->upsertAllocation($request->user(), $request->validated());
|
||||
|
||||
return redirect()->route('admin.management.wheelchairs.show', $allocation)
|
||||
->with('status', 'Peruntukan kerusi roda telah disimpan.');
|
||||
}
|
||||
|
||||
public function show(WheelchairAllocation $allocation, WheelchairManagementService $service): View
|
||||
{
|
||||
return view('admin.management.wheelchairs.show', [
|
||||
'allocation' => $allocation->load(['election', 'pusatMengundi', 'transactions.recordedBy']),
|
||||
'elections' => Election::query()->orderByDesc('id')->get(),
|
||||
'pusats' => PusatMengundi::query()->orderBy('name')->get(),
|
||||
'service' => $service,
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpsertWheelchairAllocationRequest $request, WheelchairAllocation $allocation, WheelchairManagementService $service): RedirectResponse
|
||||
{
|
||||
$data = [
|
||||
...$request->validated(),
|
||||
'election_id' => $allocation->election_id,
|
||||
'pusat_mengundi_id' => $allocation->pusat_mengundi_id,
|
||||
];
|
||||
|
||||
$service->upsertAllocation($request->user(), $data);
|
||||
|
||||
return redirect()->route('admin.management.wheelchairs.show', $allocation)
|
||||
->with('status', 'Peruntukan kerusi roda telah dikemas kini.');
|
||||
}
|
||||
|
||||
public function recordTaken(StoreTakenTransactionRequest $request, WheelchairAllocation $allocation, WheelchairManagementService $service): RedirectResponse
|
||||
{
|
||||
$service->recordTransaction($allocation, $request->user(), [
|
||||
'transaction_type' => 'taken',
|
||||
...$request->validated(),
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.management.wheelchairs.show', $allocation)
|
||||
->with('status', 'Rekod ambil kerusi roda telah disimpan.');
|
||||
}
|
||||
|
||||
public function recordReturn(StoreReturnTransactionRequest $request, WheelchairAllocation $allocation, WheelchairManagementService $service): RedirectResponse
|
||||
{
|
||||
$service->recordTransaction($allocation, $request->user(), [
|
||||
'transaction_type' => 'returned',
|
||||
...$request->validated(),
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.management.wheelchairs.show', $allocation)
|
||||
->with('status', 'Rekod pulang kerusi roda telah disimpan.');
|
||||
}
|
||||
}
|
||||
34
app/Http/Controllers/Admin/Setup/AdminSetupController.php
Normal file
34
app/Http/Controllers/Admin/Setup/AdminSetupController.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Setup;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Dun;
|
||||
use App\Models\Election;
|
||||
use App\Models\Position;
|
||||
use App\Models\PositionQuota;
|
||||
use App\Models\PusatMengundi;
|
||||
use App\Models\SaluranMengundi;
|
||||
use App\Models\StaffAssignment;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AdminSetupController extends Controller
|
||||
{
|
||||
public function index(): View
|
||||
{
|
||||
return view('admin.setup.index', [
|
||||
'counts' => [
|
||||
'elections' => Election::query()->count(),
|
||||
'duns' => Dun::query()->count(),
|
||||
'pusat' => PusatMengundi::query()->count(),
|
||||
'saluran' => SaluranMengundi::query()->count(),
|
||||
'positions' => Position::query()->count(),
|
||||
'quotas' => PositionQuota::query()->count(),
|
||||
'ppmAssignments' => StaffAssignment::query()
|
||||
->whereHas('position', fn ($query) => $query->where('code', 'PPM'))
|
||||
->where('status', 'active')
|
||||
->count(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Setup;
|
||||
|
||||
use App\Http\Concerns\SortsQuery;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Setup\UpsertBahagianPilihanrayaRequest;
|
||||
use App\Models\BahagianPilihanraya;
|
||||
use App\Models\Election;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class BahagianPilihanrayaController extends Controller
|
||||
{
|
||||
use SortsQuery;
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
return view('admin.setup.bahagian.index', [
|
||||
'bahagians' => $this->sortedQuery(
|
||||
BahagianPilihanraya::query()->with('election'),
|
||||
['code', 'name'],
|
||||
'code'
|
||||
)->paginate(15)->withQueryString(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(): View
|
||||
{
|
||||
return view('admin.setup.bahagian.create', [
|
||||
'bahagian' => new BahagianPilihanraya,
|
||||
'elections' => Election::query()->orderBy('name')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(UpsertBahagianPilihanrayaRequest $request): RedirectResponse
|
||||
{
|
||||
BahagianPilihanraya::query()->create($request->validated());
|
||||
|
||||
return redirect()->route('admin.setup.bahagian.index')
|
||||
->with('status', 'Bahagian Pilihanraya telah disimpan.');
|
||||
}
|
||||
|
||||
public function edit(BahagianPilihanraya $bahagianPilihanraya): View
|
||||
{
|
||||
return view('admin.setup.bahagian.edit', [
|
||||
'bahagian' => $bahagianPilihanraya,
|
||||
'elections' => Election::query()->orderBy('name')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpsertBahagianPilihanrayaRequest $request, BahagianPilihanraya $bahagianPilihanraya): RedirectResponse
|
||||
{
|
||||
$bahagianPilihanraya->update($request->validated());
|
||||
|
||||
return redirect()->route('admin.setup.bahagian.index')
|
||||
->with('status', 'Bahagian Pilihanraya telah dikemas kini.');
|
||||
}
|
||||
|
||||
public function destroy(BahagianPilihanraya $bahagianPilihanraya): RedirectResponse
|
||||
{
|
||||
$bahagianPilihanraya->forceDelete();
|
||||
|
||||
return redirect()->route('admin.setup.bahagian.index')
|
||||
->with('status', 'Bahagian Pilihanraya telah dipadam.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Setup;
|
||||
|
||||
use App\Http\Concerns\SortsQuery;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Setup\UpsertDaerahMengundiRequest;
|
||||
use App\Models\BahagianPilihanraya;
|
||||
use App\Models\DaerahMengundi;
|
||||
use App\Models\Election;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class DaerahMengundiController extends Controller
|
||||
{
|
||||
use SortsQuery;
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
return view('admin.setup.daerah.index', [
|
||||
'daerahs' => $this->sortedQuery(
|
||||
DaerahMengundi::query()->with(['election', 'bahagianPilihanraya']),
|
||||
['code', 'name'],
|
||||
'code'
|
||||
)->paginate(15)->withQueryString(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(): View
|
||||
{
|
||||
return view('admin.setup.daerah.create', [
|
||||
'daerah' => new DaerahMengundi,
|
||||
'elections' => Election::query()->orderBy('name')->get(),
|
||||
'bahagians' => BahagianPilihanraya::query()->orderBy('name')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(UpsertDaerahMengundiRequest $request): RedirectResponse
|
||||
{
|
||||
DaerahMengundi::query()->create($request->validated());
|
||||
|
||||
return redirect()->route('admin.setup.daerah.index')
|
||||
->with('status', 'Daerah Mengundi telah disimpan.');
|
||||
}
|
||||
|
||||
public function edit(DaerahMengundi $daerahMengundi): View
|
||||
{
|
||||
return view('admin.setup.daerah.edit', [
|
||||
'daerah' => $daerahMengundi,
|
||||
'elections' => Election::query()->orderBy('name')->get(),
|
||||
'bahagians' => BahagianPilihanraya::query()->orderBy('name')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpsertDaerahMengundiRequest $request, DaerahMengundi $daerahMengundi): RedirectResponse
|
||||
{
|
||||
$daerahMengundi->update($request->validated());
|
||||
|
||||
return redirect()->route('admin.setup.daerah.index')
|
||||
->with('status', 'Daerah Mengundi telah dikemas kini.');
|
||||
}
|
||||
|
||||
public function destroy(DaerahMengundi $daerahMengundi): RedirectResponse
|
||||
{
|
||||
$daerahMengundi->forceDelete();
|
||||
|
||||
return redirect()->route('admin.setup.daerah.index')
|
||||
->with('status', 'Daerah Mengundi telah dipadam.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Setup;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Setup\UpsertElectionSettingsRequest;
|
||||
use App\Models\Election;
|
||||
use App\Services\Admin\ElectionSettingsService;
|
||||
use App\Services\RegistrationPeriodService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class ElectionSettingsController extends Controller
|
||||
{
|
||||
public function edit(Election $election, RegistrationPeriodService $registrationPeriodService): View
|
||||
{
|
||||
return view('admin.setup.settings.edit', [
|
||||
'election' => $election->load('settings'),
|
||||
'isRegistrationOpen' => $election->settings
|
||||
? $registrationPeriodService->isOpen($election)
|
||||
: false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(
|
||||
UpsertElectionSettingsRequest $request,
|
||||
Election $election,
|
||||
ElectionSettingsService $service,
|
||||
): RedirectResponse {
|
||||
abort_if($election->settings !== null, 409);
|
||||
|
||||
$service->create($election, $request->validated(), $request->user());
|
||||
|
||||
return redirect()->route('admin.setup.settings.edit', $election)
|
||||
->with('status', 'Tetapan pilihanraya telah dicipta.');
|
||||
}
|
||||
|
||||
public function update(
|
||||
UpsertElectionSettingsRequest $request,
|
||||
Election $election,
|
||||
ElectionSettingsService $service,
|
||||
): RedirectResponse {
|
||||
abort_unless($election->settings !== null, 404);
|
||||
|
||||
$service->update($election, $request->validated(), $request->user());
|
||||
|
||||
return redirect()->route('admin.setup.settings.edit', $election)
|
||||
->with('status', 'Tetapan pilihanraya telah dikemas kini.');
|
||||
}
|
||||
}
|
||||
81
app/Http/Controllers/Admin/Setup/PositionController.php
Normal file
81
app/Http/Controllers/Admin/Setup/PositionController.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Setup;
|
||||
|
||||
use App\Http\Concerns\SortsQuery;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Setup\UpsertPositionRequest;
|
||||
use App\Models\Position;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PositionController extends Controller
|
||||
{
|
||||
use SortsQuery;
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
return view('admin.setup.positions.index', [
|
||||
'positions' => $this->sortedQuery(
|
||||
Position::query(),
|
||||
['code', 'name', 'scope', 'sort_order'],
|
||||
'sort_order'
|
||||
)->paginate(20)->withQueryString(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(): View
|
||||
{
|
||||
return view('admin.setup.positions.create', [
|
||||
'position' => new Position,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(UpsertPositionRequest $request): RedirectResponse
|
||||
{
|
||||
Position::query()->create($this->payload($request));
|
||||
|
||||
return redirect()->route('admin.setup.positions.index')
|
||||
->with('status', 'Jawatan telah disimpan.');
|
||||
}
|
||||
|
||||
public function edit(Position $position): View
|
||||
{
|
||||
return view('admin.setup.positions.edit', [
|
||||
'position' => $position,
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpsertPositionRequest $request, Position $position): RedirectResponse
|
||||
{
|
||||
$position->update($this->payload($request));
|
||||
|
||||
return redirect()->route('admin.setup.positions.index')
|
||||
->with('status', 'Jawatan telah dikemas kini.');
|
||||
}
|
||||
|
||||
public function destroy(Position $position): RedirectResponse
|
||||
{
|
||||
$position->forceDelete();
|
||||
|
||||
return redirect()->route('admin.setup.positions.index')
|
||||
->with('status', 'Jawatan telah dipadam.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function payload(UpsertPositionRequest $request): array
|
||||
{
|
||||
return [
|
||||
...$request->safe()->except([
|
||||
'is_public_applyable',
|
||||
'is_assignable',
|
||||
'allows_dual_role',
|
||||
]),
|
||||
'is_public_applyable' => $request->boolean('is_public_applyable'),
|
||||
'is_assignable' => $request->boolean('is_assignable'),
|
||||
'allows_dual_role' => $request->boolean('allows_dual_role'),
|
||||
];
|
||||
}
|
||||
}
|
||||
100
app/Http/Controllers/Admin/Setup/PositionQuotaController.php
Normal file
100
app/Http/Controllers/Admin/Setup/PositionQuotaController.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Setup;
|
||||
|
||||
use App\Http\Concerns\SortsQuery;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Setup\UpsertPositionQuotaRequest;
|
||||
use App\Models\Position;
|
||||
use App\Models\PositionQuota;
|
||||
use App\Models\PusatMengundi;
|
||||
use App\Models\SaluranMengundi;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PositionQuotaController extends Controller
|
||||
{
|
||||
use SortsQuery;
|
||||
|
||||
public function index(PusatMengundi $pusatMengundi, SaluranMengundi $saluranMengundi): View
|
||||
{
|
||||
abort_unless($saluranMengundi->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
|
||||
return view('admin.setup.quotas.index', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'saluran' => $saluranMengundi,
|
||||
'quotas' => $this->sortedQuery(
|
||||
PositionQuota::query()
|
||||
->with(['position'])
|
||||
->where('saluran_mengundi_id', $saluranMengundi->id),
|
||||
['quota'],
|
||||
'id'
|
||||
)->paginate(25)->withQueryString(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(PusatMengundi $pusatMengundi, SaluranMengundi $saluranMengundi): View
|
||||
{
|
||||
abort_unless($saluranMengundi->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
|
||||
return view('admin.setup.quotas.create', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'saluran' => $saluranMengundi,
|
||||
'quota' => new PositionQuota,
|
||||
'positions' => Position::query()->orderBy('sort_order')->orderBy('code')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(UpsertPositionQuotaRequest $request, PusatMengundi $pusatMengundi, SaluranMengundi $saluranMengundi): RedirectResponse
|
||||
{
|
||||
abort_unless($saluranMengundi->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
|
||||
PositionQuota::query()->updateOrCreate(
|
||||
[
|
||||
'election_id' => $saluranMengundi->election_id,
|
||||
'pusat_mengundi_id' => $pusatMengundi->id,
|
||||
'saluran_mengundi_id' => $saluranMengundi->id,
|
||||
'position_id' => $request->validated('position_id'),
|
||||
],
|
||||
['quota' => $request->validated('quota')],
|
||||
);
|
||||
|
||||
return redirect()->route('admin.setup.pusat.saluran.kuota.index', [$pusatMengundi, $saluranMengundi])
|
||||
->with('status', 'Kekosongan jawatan telah disimpan.');
|
||||
}
|
||||
|
||||
public function edit(PusatMengundi $pusatMengundi, SaluranMengundi $saluranMengundi, PositionQuota $quota): View
|
||||
{
|
||||
abort_unless($saluranMengundi->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
abort_unless($quota->saluran_mengundi_id === $saluranMengundi->id, 404);
|
||||
|
||||
return view('admin.setup.quotas.edit', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'saluran' => $saluranMengundi,
|
||||
'quota' => $quota->load('position'),
|
||||
'positions' => Position::query()->orderBy('sort_order')->orderBy('code')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpsertPositionQuotaRequest $request, PusatMengundi $pusatMengundi, SaluranMengundi $saluranMengundi, PositionQuota $quota): RedirectResponse
|
||||
{
|
||||
abort_unless($saluranMengundi->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
abort_unless($quota->saluran_mengundi_id === $saluranMengundi->id, 404);
|
||||
|
||||
$quota->update(['quota' => $request->validated('quota')]);
|
||||
|
||||
return redirect()->route('admin.setup.pusat.saluran.kuota.index', [$pusatMengundi, $saluranMengundi])
|
||||
->with('status', 'Kekosongan jawatan telah dikemas kini.');
|
||||
}
|
||||
|
||||
public function destroy(PusatMengundi $pusatMengundi, SaluranMengundi $saluranMengundi, PositionQuota $quota): RedirectResponse
|
||||
{
|
||||
abort_unless($saluranMengundi->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
abort_unless($quota->saluran_mengundi_id === $saluranMengundi->id, 404);
|
||||
|
||||
$quota->forceDelete();
|
||||
|
||||
return redirect()->route('admin.setup.pusat.saluran.kuota.index', [$pusatMengundi, $saluranMengundi])
|
||||
->with('status', 'Kekosongan jawatan telah dipadam.');
|
||||
}
|
||||
}
|
||||
50
app/Http/Controllers/Admin/Setup/PusatImportController.php
Normal file
50
app/Http/Controllers/Admin/Setup/PusatImportController.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Setup;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Setup\ImportPusatRequest;
|
||||
use App\Models\Dun;
|
||||
use App\Models\Election;
|
||||
use App\Services\Admin\PusatImportService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PusatImportController extends Controller
|
||||
{
|
||||
public function create(): View
|
||||
{
|
||||
return view('admin.setup.import.create', [
|
||||
'elections' => Election::query()->orderByDesc('id')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(ImportPusatRequest $request, PusatImportService $importService): RedirectResponse
|
||||
{
|
||||
/** @var Election $election */
|
||||
$election = Election::query()->findOrFail($request->validated('election_id'));
|
||||
|
||||
$dunCode = strtoupper(trim((string) $request->validated('dun_code')));
|
||||
$dunName = trim((string) $request->validated('dun_name'));
|
||||
|
||||
$dun = Dun::query()->updateOrCreate(
|
||||
['election_id' => $election->id, 'code' => $dunCode],
|
||||
['name' => $dunName],
|
||||
);
|
||||
|
||||
$result = $importService->import($election, $dun, $request->file('file'));
|
||||
|
||||
$message = "Import selesai: {$result['imported']} Pusat Mengundi, {$result['salurans']} Saluran dicipta untuk DUN {$dunCode} - {$dunName}.";
|
||||
|
||||
if (! empty($result['errors'])) {
|
||||
$message .= ' '.count($result['errors']).' baris gagal.';
|
||||
|
||||
return redirect()->route('admin.setup.import.create')
|
||||
->with('status', $message)
|
||||
->with('import_errors', $result['errors']);
|
||||
}
|
||||
|
||||
return redirect()->route('admin.setup.pusat.index')
|
||||
->with('status', $message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Setup;
|
||||
|
||||
use App\Http\Concerns\SortsQuery;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Setup\UpsertPositionQuotaRequest;
|
||||
use App\Models\Position;
|
||||
use App\Models\PositionQuota;
|
||||
use App\Models\PusatMengundi;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PusatLevelQuotaController extends Controller
|
||||
{
|
||||
use SortsQuery;
|
||||
|
||||
public function index(PusatMengundi $pusatMengundi): View
|
||||
{
|
||||
return view('admin.setup.quotas.pusat-index', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'quotas' => $this->sortedQuery(
|
||||
PositionQuota::query()
|
||||
->with(['position'])
|
||||
->where('pusat_mengundi_id', $pusatMengundi->id)
|
||||
->whereNull('saluran_mengundi_id'),
|
||||
['quota'],
|
||||
'id'
|
||||
)->paginate(25)->withQueryString(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(PusatMengundi $pusatMengundi): View
|
||||
{
|
||||
return view('admin.setup.quotas.pusat-create', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'quota' => new PositionQuota,
|
||||
'positions' => Position::query()->orderBy('sort_order')->orderBy('code')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(UpsertPositionQuotaRequest $request, PusatMengundi $pusatMengundi): RedirectResponse
|
||||
{
|
||||
PositionQuota::query()->updateOrCreate(
|
||||
[
|
||||
'election_id' => $pusatMengundi->election_id,
|
||||
'pusat_mengundi_id' => $pusatMengundi->id,
|
||||
'saluran_mengundi_id' => null,
|
||||
'position_id' => $request->validated('position_id'),
|
||||
],
|
||||
['quota' => $request->validated('quota')],
|
||||
);
|
||||
|
||||
return redirect()->route('admin.setup.pusat.kuota.index', $pusatMengundi)
|
||||
->with('status', 'Kuota peringkat pusat telah disimpan.');
|
||||
}
|
||||
|
||||
public function edit(PusatMengundi $pusatMengundi, PositionQuota $quota): View
|
||||
{
|
||||
abort_unless($quota->pusat_mengundi_id === $pusatMengundi->id && $quota->saluran_mengundi_id === null, 404);
|
||||
|
||||
return view('admin.setup.quotas.pusat-edit', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'quota' => $quota->load('position'),
|
||||
'positions' => Position::query()->orderBy('sort_order')->orderBy('code')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpsertPositionQuotaRequest $request, PusatMengundi $pusatMengundi, PositionQuota $quota): RedirectResponse
|
||||
{
|
||||
abort_unless($quota->pusat_mengundi_id === $pusatMengundi->id && $quota->saluran_mengundi_id === null, 404);
|
||||
|
||||
$quota->update(['quota' => $request->validated('quota')]);
|
||||
|
||||
return redirect()->route('admin.setup.pusat.kuota.index', $pusatMengundi)
|
||||
->with('status', 'Kuota peringkat pusat telah dikemas kini.');
|
||||
}
|
||||
|
||||
public function destroy(PusatMengundi $pusatMengundi, PositionQuota $quota): RedirectResponse
|
||||
{
|
||||
abort_unless($quota->pusat_mengundi_id === $pusatMengundi->id && $quota->saluran_mengundi_id === null, 404);
|
||||
|
||||
$quota->forceDelete();
|
||||
|
||||
return redirect()->route('admin.setup.pusat.kuota.index', $pusatMengundi)
|
||||
->with('status', 'Kuota peringkat pusat telah dipadam.');
|
||||
}
|
||||
}
|
||||
156
app/Http/Controllers/Admin/Setup/PusatMengundiController.php
Normal file
156
app/Http/Controllers/Admin/Setup/PusatMengundiController.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Setup;
|
||||
|
||||
use App\Http\Concerns\SortsQuery;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Setup\AssignPpmRequest;
|
||||
use App\Http\Requests\Admin\Setup\UpsertPusatMengundiRequest;
|
||||
use App\Models\Dun;
|
||||
use App\Models\Election;
|
||||
use App\Models\Position;
|
||||
use App\Models\PusatMengundi;
|
||||
use App\Models\User;
|
||||
use App\Services\Admin\PpmAssignmentService;
|
||||
use App\Services\Admin\PusatOperationalSetupService;
|
||||
use App\Services\Admin\PusatQrCodeService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PusatMengundiController extends Controller
|
||||
{
|
||||
use SortsQuery;
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
return view('admin.setup.pusat.index', [
|
||||
'pusats' => $this->sortedQuery(
|
||||
PusatMengundi::query()->with(['election', 'dun', 'saluranMengundis']),
|
||||
['code', 'name'],
|
||||
'code'
|
||||
)->paginate(15)->withQueryString(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(): View
|
||||
{
|
||||
return view('admin.setup.pusat.create', [
|
||||
'pusat' => new PusatMengundi,
|
||||
'elections' => Election::query()->orderBy('name')->get(),
|
||||
'duns' => Dun::query()->orderBy('name')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(
|
||||
UpsertPusatMengundiRequest $request,
|
||||
PusatQrCodeService $qrCodeService,
|
||||
PusatOperationalSetupService $operationalSetupService,
|
||||
): RedirectResponse {
|
||||
$pusat = DB::transaction(function () use ($request, $operationalSetupService): PusatMengundi {
|
||||
$pusat = PusatMengundi::query()->create([
|
||||
...$request->safe()->only([
|
||||
'election_id',
|
||||
'dun_id',
|
||||
'code',
|
||||
'name',
|
||||
'address',
|
||||
]),
|
||||
'public_uuid' => (string) Str::uuid(),
|
||||
]);
|
||||
|
||||
$operationalSetupService->configure($pusat, $request->validated());
|
||||
|
||||
return $pusat;
|
||||
});
|
||||
|
||||
$qrCodeService->generate($pusat);
|
||||
|
||||
return redirect()->route('admin.setup.pusat.index')
|
||||
->with('status', 'Pusat Mengundi telah disimpan dan QR telah dijana.');
|
||||
}
|
||||
|
||||
public function show(PusatMengundi $pusatMengundi): View
|
||||
{
|
||||
$ppmPosition = Position::query()->where('code', 'PPM')->first();
|
||||
|
||||
return view('admin.setup.pusat.show', [
|
||||
'pusat' => $pusatMengundi->load([
|
||||
'election',
|
||||
'dun',
|
||||
'saluranMengundis',
|
||||
'positionQuotas.position',
|
||||
]),
|
||||
'ppmAssignment' => $ppmPosition
|
||||
? $pusatMengundi->staffAssignments()
|
||||
->with('user')
|
||||
->where('position_id', $ppmPosition->id)
|
||||
->where('status', 'active')
|
||||
->whereNull('saluran_mengundi_id')
|
||||
->first()
|
||||
: null,
|
||||
'users' => User::query()->orderBy('name')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function edit(PusatMengundi $pusatMengundi): View
|
||||
{
|
||||
return view('admin.setup.pusat.edit', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'elections' => Election::query()->orderBy('name')->get(),
|
||||
'duns' => Dun::query()->orderBy('name')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpsertPusatMengundiRequest $request, PusatMengundi $pusatMengundi): RedirectResponse
|
||||
{
|
||||
$pusatMengundi->update($request->safe()->only([
|
||||
'election_id',
|
||||
'dun_id',
|
||||
'code',
|
||||
'name',
|
||||
'address',
|
||||
]));
|
||||
|
||||
return redirect()->route('admin.setup.pusat.show', $pusatMengundi)
|
||||
->with('status', 'Pusat Mengundi telah dikemas kini.');
|
||||
}
|
||||
|
||||
public function destroy(PusatMengundi $pusatMengundi): RedirectResponse
|
||||
{
|
||||
$pusatMengundi->forceDelete();
|
||||
|
||||
return redirect()->route('admin.setup.pusat.index')
|
||||
->with('status', 'Pusat Mengundi telah dipadam.');
|
||||
}
|
||||
|
||||
public function generateQr(PusatMengundi $pusatMengundi, PusatQrCodeService $qrCodeService): RedirectResponse
|
||||
{
|
||||
$qrCodeService->generate($pusatMengundi);
|
||||
|
||||
return redirect()->route('admin.setup.pusat.show', $pusatMengundi)
|
||||
->with('status', 'QR pendaftaran telah dijana semula.');
|
||||
}
|
||||
|
||||
public function qrSvg(PusatMengundi $pusatMengundi): Response
|
||||
{
|
||||
abort_unless($pusatMengundi->qr_code_path && Storage::disk('local')->exists($pusatMengundi->qr_code_path), 404);
|
||||
|
||||
return response(Storage::disk('local')->get($pusatMengundi->qr_code_path), 200, [
|
||||
'Content-Type' => 'image/svg+xml',
|
||||
]);
|
||||
}
|
||||
|
||||
public function assignPpm(AssignPpmRequest $request, PusatMengundi $pusatMengundi, PpmAssignmentService $assignmentService): RedirectResponse
|
||||
{
|
||||
$user = User::query()->findOrFail($request->validated('user_id'));
|
||||
|
||||
$assignmentService->assign($pusatMengundi, $user);
|
||||
|
||||
return redirect()->route('admin.setup.pusat.show', $pusatMengundi)
|
||||
->with('status', 'PPM telah ditetapkan.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Setup;
|
||||
|
||||
use App\Http\Concerns\SortsQuery;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\Setup\UpsertSaluranMengundiRequest;
|
||||
use App\Models\PusatMengundi;
|
||||
use App\Models\SaluranMengundi;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class SaluranMengundiController extends Controller
|
||||
{
|
||||
use SortsQuery;
|
||||
|
||||
public function index(PusatMengundi $pusatMengundi): View
|
||||
{
|
||||
return view('admin.setup.saluran.index', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'salurans' => $this->sortedQuery(
|
||||
SaluranMengundi::query()->where('pusat_mengundi_id', $pusatMengundi->id),
|
||||
['number', 'voter_count'],
|
||||
'number'
|
||||
)->paginate(20)->withQueryString(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(PusatMengundi $pusatMengundi): View
|
||||
{
|
||||
return view('admin.setup.saluran.create', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'saluran' => new SaluranMengundi,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(UpsertSaluranMengundiRequest $request, PusatMengundi $pusatMengundi): RedirectResponse
|
||||
{
|
||||
$pusatMengundi->saluranMengundis()->create([
|
||||
'election_id' => $pusatMengundi->election_id,
|
||||
'number' => $request->validated('number'),
|
||||
'voter_count' => $request->validated('voter_count'),
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.setup.pusat.saluran.index', $pusatMengundi)
|
||||
->with('status', 'Saluran Mengundi telah disimpan.');
|
||||
}
|
||||
|
||||
public function edit(PusatMengundi $pusatMengundi, SaluranMengundi $saluranMengundi): View
|
||||
{
|
||||
abort_unless($saluranMengundi->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
|
||||
return view('admin.setup.saluran.edit', [
|
||||
'pusat' => $pusatMengundi,
|
||||
'saluran' => $saluranMengundi,
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpsertSaluranMengundiRequest $request, PusatMengundi $pusatMengundi, SaluranMengundi $saluranMengundi): RedirectResponse
|
||||
{
|
||||
abort_unless($saluranMengundi->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
|
||||
$saluranMengundi->update([
|
||||
'number' => $request->validated('number'),
|
||||
'voter_count' => $request->validated('voter_count'),
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.setup.pusat.saluran.index', $pusatMengundi)
|
||||
->with('status', 'Saluran Mengundi telah dikemas kini.');
|
||||
}
|
||||
|
||||
public function destroy(PusatMengundi $pusatMengundi, SaluranMengundi $saluranMengundi): RedirectResponse
|
||||
{
|
||||
abort_unless($saluranMengundi->pusat_mengundi_id === $pusatMengundi->id, 404);
|
||||
|
||||
$saluranMengundi->forceDelete();
|
||||
|
||||
return redirect()->route('admin.setup.pusat.saluran.index', $pusatMengundi)
|
||||
->with('status', 'Saluran Mengundi telah dipadam.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user