149 lines
5.7 KiB
PHP
149 lines
5.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Web;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Services\SchoolYears\SchoolYearClosureService;
|
|
use App\Services\SchoolYears\SchoolYearResolver;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Validation\ValidationException;
|
|
use Illuminate\View\View;
|
|
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
|
|
|
|
class SchoolYearAdminPageController extends Controller
|
|
{
|
|
public function __construct(
|
|
private SchoolYearClosureService $service,
|
|
private SchoolYearResolver $resolver
|
|
) {}
|
|
|
|
public function show(Request $request): View
|
|
{
|
|
$years = $this->service->list();
|
|
$selectedId = (int) ($request->query('year') ?? 0);
|
|
$activeYear = collect($years)->firstWhere('is_current', true);
|
|
|
|
$defaultNext = $activeYear
|
|
? ($this->resolver->suggestNextName((string) $activeYear['name']) ?? '')
|
|
: '';
|
|
[$defaultStart, $defaultEnd] = $defaultNext !== ''
|
|
? $this->resolver->inferDatesFromName($defaultNext)
|
|
: ['', ''];
|
|
|
|
return view('admin.school-years', [
|
|
'pageConfig' => [
|
|
'jwt' => JWTAuth::fromUser($request->user()),
|
|
'selected_year_id' => $selectedId,
|
|
'docs_url' => url('/docs'),
|
|
'default_draft' => [
|
|
'name' => $defaultNext,
|
|
'start_date' => $defaultStart,
|
|
'end_date' => $defaultEnd,
|
|
],
|
|
'api' => [
|
|
'index' => url('/api/v1/school-years'),
|
|
'store' => url('/api/v1/school-years'),
|
|
'update' => url('/api/v1/school-years/__ID__'),
|
|
'summary' => url('/api/v1/school-years/__ID__/summary'),
|
|
'validate_close' => url('/api/v1/school-years/__ID__/validate-close'),
|
|
'preview_close' => url('/api/v1/school-years/__ID__/preview-close'),
|
|
'close' => url('/api/v1/school-years/__ID__/close'),
|
|
'reopen' => url('/api/v1/school-years/__ID__/reopen'),
|
|
'parent_balances' => url('/api/v1/school-years/__ID__/parent-balances'),
|
|
'promotion_preview' => url('/api/v1/school-years/__ID__/promotion-preview'),
|
|
],
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function store(Request $request): RedirectResponse
|
|
{
|
|
$payload = $request->validate([
|
|
'name' => ['required', 'string', 'max:50'],
|
|
'start_date' => ['required', 'date'],
|
|
'end_date' => ['required', 'date', 'after:start_date'],
|
|
]);
|
|
|
|
try {
|
|
$year = $this->service->createYear($payload, optional($request->user())->id);
|
|
} catch (ValidationException $e) {
|
|
throw $e;
|
|
}
|
|
|
|
return redirect()
|
|
->route('admin.school-years', ['year' => $year['id']])
|
|
->with('status', sprintf('Draft school year %s created.', $year['name']));
|
|
}
|
|
|
|
public function update(Request $request, int $schoolYear): RedirectResponse
|
|
{
|
|
$payload = $request->validate([
|
|
'name' => ['required', 'string', 'max:50'],
|
|
'start_date' => ['required', 'date'],
|
|
'end_date' => ['required', 'date', 'after:start_date'],
|
|
]);
|
|
|
|
$updated = $this->service->updateYear($schoolYear, $payload, optional($request->user())->id);
|
|
|
|
return redirect()
|
|
->route('admin.school-years', ['year' => $updated['id']])
|
|
->with('status', sprintf('School year %s updated.', $updated['name']));
|
|
}
|
|
|
|
public function validateClose(Request $request, int $schoolYear): JsonResponse
|
|
{
|
|
return response()->json([
|
|
'ok' => true,
|
|
'validation' => $this->service->validateClose($schoolYear, $this->validatedClosePayload($request)),
|
|
]);
|
|
}
|
|
|
|
public function previewClose(Request $request, int $schoolYear): JsonResponse
|
|
{
|
|
return response()->json([
|
|
'ok' => true,
|
|
'data' => $this->service->previewClose($schoolYear, $this->validatedClosePayload($request)),
|
|
]);
|
|
}
|
|
|
|
public function close(Request $request, int $schoolYear): RedirectResponse
|
|
{
|
|
$payload = $this->validatedClosePayload($request);
|
|
$payload['confirmation'] = (string) $request->validate([
|
|
'confirmation' => ['required', 'string', 'max:80'],
|
|
])['confirmation'];
|
|
|
|
$result = $this->service->close($schoolYear, $payload, optional($request->user())->id);
|
|
|
|
return redirect()
|
|
->route('admin.school-years', ['year' => $result['new_school_year']['id']])
|
|
->with('status', sprintf(
|
|
'Closed %s and opened %s.',
|
|
$result['closed_school_year']['name'],
|
|
$result['new_school_year']['name']
|
|
));
|
|
}
|
|
|
|
public function reopen(Request $request, int $schoolYear): RedirectResponse
|
|
{
|
|
$year = $this->service->reopen($schoolYear, optional($request->user())->id);
|
|
|
|
return redirect()
|
|
->route('admin.school-years', ['year' => $year['id']])
|
|
->with('status', sprintf('School year %s is now active.', $year['name']));
|
|
}
|
|
|
|
private function validatedClosePayload(Request $request): array
|
|
{
|
|
return $request->validate([
|
|
'new_school_year' => ['required', 'array'],
|
|
'new_school_year.name' => ['required', 'string', 'max:50'],
|
|
'new_school_year.start_date' => ['required', 'date'],
|
|
'new_school_year.end_date' => ['required', 'date', 'after:new_school_year.start_date'],
|
|
'transfer_unpaid_balances' => ['nullable', 'boolean'],
|
|
]);
|
|
}
|
|
}
|