diff --git a/Modules/Institution/App/Http/Controllers/AttestationController.php b/Modules/Institution/App/Http/Controllers/AttestationController.php index 5ce40c9f..0b941414 100644 --- a/Modules/Institution/App/Http/Controllers/AttestationController.php +++ b/Modules/Institution/App/Http/Controllers/AttestationController.php @@ -4,6 +4,7 @@ use App\Events\AttestationDraftUpdated; use App\Events\AttestationIssued; +use App\Facades\InstitutionFacade; use App\Http\Controllers\Controller; use App\Models\Attestation; use App\Models\AttestationPdf; @@ -11,6 +12,7 @@ use App\Models\Country; use App\Models\FedCap; use App\Models\User; +use App\Services\Institution\InstitutionAttestationsDetails; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\App; @@ -45,8 +47,7 @@ public function index() // This is going to be all attes. under this inst. and are using the same fed cap as this. $user = User::find(Auth::user()->id); $institution = $user->institution; -// $fedCap = FedCap::active()->first(); - + // $fedCap = FedCap::active()->first(); $cap = Cap::where('fed_cap_guid', Cache::get('global_fed_caps')['default'])->active() // $cap = Cap::where('fed_cap_guid', $fedCap->guid)->active() @@ -54,11 +55,48 @@ public function index() ->where('institution_guid', $institution->guid) ->first(); + if (is_null($cap)) { + return redirect(route('institution.dashboard'))->withErrors(['error' => "Error: No institution cap found for this institution, attestations can't be retrieved."]); + } + $user = User::find(Auth::user()->id); $attestations = $this->paginateAtte($user->institution); - return Inertia::render('Institution::Attestations', ['error' => null, 'results' => $attestations, + // Display a warning message to users if the institution has reached a cap. + $warning_message = ''; + + // Get the inst cap and check if we have hit the cap for issued attestations + // This is going to be all attes. under this inst. and are using the same fed cap as this. + $issued_attestations = Attestation::where('status', 'Issued') + ->where('institution_guid', $cap->institution_guid) + ->where('fed_cap_guid', $cap->fed_cap_guid) + ->count(); + + // If the attestation is linked to a reserved graduate program + // Get the total for reserved graduate issued attestations + $issued_res_grad_attestations = Attestation::where('status', 'Issued') + ->where('institution_guid', $cap->institution_guid) + ->where('fed_cap_guid', $cap->fed_cap_guid) + ->whereHas('program', function ($query) { + $query->where('program_graduate', true); + }) + ->count(); + + $instituion_attestations_details = InstitutionFacade::getInstitutionAttestInfo($issued_attestations, $issued_res_grad_attestations, $cap); + + // If we hit or acceded the reserved graduate inst cap limit for issued attestations + if ($instituion_attestations_details['undergradRemaining'] === 0) { + $warning_message = "Your institution has reached the limit for undergraduate attestations. You can't issue a new attestation linked to an undergraduate program or it will be automatically converted as a Draft."; + } + elseif ($instituion_attestations_details['issued']>= $cap->total_attestations) { + $warning_message = "Your institution has reached the maximum attestations cap. You can't issue a new attestation or it will be automatically converted as a Draft."; + } + + return Inertia::render('Institution::Attestations', [ + 'error' => null, + 'warning' => $warning_message, + 'results' => $attestations, 'institution' => $user->institution, 'programs' => $user->institution->activePrograms, 'countries' => $this->countries, 'instCaps' => $user->institution->activeInstCaps, @@ -87,7 +125,6 @@ public function store(AttestationStoreRequest $request): RedirectResponse|\Illum $attestation = Attestation::create($request->validated()); $this->authorize('download', $attestation); event(new AttestationIssued($attestation->cap, $attestation, $request->status)); - } else { $error = "There's already an attestation for the same user."; } @@ -121,12 +158,11 @@ public function update(AttestationEditRequest $request): RedirectResponse|\Illum ->whereNot('status', 'Cancelled Draft') ->first(); - if(is_null($check1)){ + if (is_null($check1)) { $error = 'This attestation cannot be edited. Only draft attestations can be edited.'; - } - elseif(!is_null($check2)){ + } elseif (! is_null($check2)) { $error = "There's already an attestation for the exact same user."; - }else{ + } else { $cap = Cap::where('guid', $request->cap_guid)->first(); Attestation::where('id', $request->id)->update($request->validated()); @@ -211,15 +247,23 @@ public function capStat(Request $request) ->where('program_guid', null) ->first(); - if(!is_null($instCap)) { + if (! is_null($instCap)) { $issuedInstAttestations = Attestation::where('status', 'Issued') ->where('institution_guid', $instCap->institution_guid) ->where('fed_cap_guid', $instCap->fed_cap_guid) ->count(); + + $issuedResGradInstAttestations = Attestation::where('status', 'Issued') + ->where('institution_guid', $instCap->institution_guid) + ->where('fed_cap_guid', $instCap->fed_cap_guid) + ->whereHas('program', function ($query) { + $query->where('program_graduate', true); + }) + ->count(); } - return Response::json(['status' => true, 'body' => ['instCap' => $instCap, 'issued' => $issuedInstAttestations ?? 0]]); - } + return Response::json(['status' => true, 'body' => ['instCap' => $instCap, 'issued' => $issuedInstAttestations ?? 0, 'resGradIssued' => $issuedResGradInstAttestations ?? 0]]); + } public function duplicateStudent(Request $request) { @@ -232,7 +276,7 @@ public function duplicateStudent(Request $request) ->where('program_guid', null) ->first(); - if(!is_null($instCap)) { + if (! is_null($instCap)) { $issuedInstAttestations = Attestation::where('institution_guid', $instCap->institution_guid) ->where('fed_cap_guid', $instCap->fed_cap_guid) ->where('student_number', $request->input('student_number')) @@ -245,11 +289,10 @@ public function duplicateStudent(Request $request) private function paginateAtte($institution) { -// $attestations = Attestation::where('institution_guid', $institution->guid)->with('program'); + // $attestations = Attestation::where('institution_guid', $institution->guid)->with('program'); $attestations = Attestation::where('institution_guid', $institution->guid) ->where('fed_cap_guid', Cache::get('global_fed_caps')['default']) - ->whereNot('status', 'Cancelled Draft') - ->with('program'); + ->whereNot('status', 'Cancelled Draft'); if (request()->filter_term !== null && request()->filter_type !== null) { $attestations = match (request()->filter_type) { @@ -269,6 +312,18 @@ private function paginateAtte($institution) $attestations = $attestations->orderBy('created_at', 'desc'); } - return $attestations->with('institution.activeCaps', 'institution.programs')->paginate(25)->onEachSide(1)->appends(request()->query()); + if (request()->filter_program) { + $attestations->whereHas('program', function ($query) { + $query->where('program_graduate', request()->filter_program === 'graduate'); + }); + } + + return $attestations->with([ + 'institution.activeCaps', + 'institution.programs', + 'program' => function ($query) { + $query->select('guid', 'program_name', 'program_graduate'); + }, + ])->paginate(25)->onEachSide(1)->appends(request()->query()); } } diff --git a/Modules/Institution/App/Http/Controllers/InstitutionController.php b/Modules/Institution/App/Http/Controllers/InstitutionController.php index fbfaf1c6..44812efd 100644 --- a/Modules/Institution/App/Http/Controllers/InstitutionController.php +++ b/Modules/Institution/App/Http/Controllers/InstitutionController.php @@ -3,6 +3,7 @@ namespace Modules\Institution\App\Http\Controllers; use App\Events\StaffRoleChanged; +use App\Facades\InstitutionFacade; use App\Http\Controllers\Controller; use App\Http\Requests\InstitutionStaffEditRequest; use App\Models\Attestation; @@ -22,6 +23,7 @@ class InstitutionController extends Controller public function index() { $issuedInstAttestations = 0; + $issuedResGradInstAttestations = 0; $user = User::find(Auth::user()->id); $institution = $user->institution; @@ -32,17 +34,34 @@ public function index() ->first(); $capTotal = 0; + if (! is_null($instCap)) { $capTotal = $instCap->total_attestations; $issuedInstAttestations = Attestation::where('status', 'Issued') ->where('institution_guid', $institution->guid) ->where('fed_cap_guid', $instCap->fed_cap_guid) ->count(); + + // Total for Grad3. attestations + $issuedResGradInstAttestations = Attestation::where('status', 'Issued') + ->where('institution_guid', $institution->guid) + ->where('fed_cap_guid', $instCap->fed_cap_guid) + ->whereHas('program', function ($query) { + $query->where('program_graduate', true); + }) + ->count(); + + $instituionAttestationsDetails = InstitutionFacade::getInstitutionAttestInfo($issuedInstAttestations, $issuedResGradInstAttestations, $instCap); } - return Inertia::render('Institution::Dashboard', ['results' => $institution, + return Inertia::render('Institution::Dashboard', [ + 'results' => $institution, 'capTotal' => $capTotal, - 'issued' => $issuedInstAttestations]); + 'issued' => $issuedInstAttestations, + 'issuedUndegrad' => $instituionAttestationsDetails['issuedUndegrad'] ?? 0, + 'undergradRemaining' => $instituionAttestationsDetails['undergradRemaining'] ?? 0, + 'issuedResGrad' => $issuedResGradInstAttestations, + ]); } /** @@ -66,9 +85,11 @@ public function caps() $institution->activeInstCaps->makeHidden(['comment']); $institution->activeProgramCaps->makeHidden(['comment']); - return Inertia::render('Institution::Caps', ['results' => $institution, + return Inertia::render('Institution::Caps', [ + 'results' => $institution, 'instCaps' => $institution->activeInstCaps, - 'programCaps' => $institution->activeProgramCaps]); + 'programCaps' => $institution->activeProgramCaps, + ]); } /** @@ -81,7 +102,10 @@ public function staffList(Request $request): \Inertia\Response $user = User::find(Auth::user()->id); $institution = $user->institution->staff()->with('user.roles')->get(); - return Inertia::render('Institution::Staff', ['status' => true, 'results' => $institution]); + return Inertia::render('Institution::Staff', [ + 'status' => true, + 'results' => $institution, + ]); } /** @@ -89,11 +113,15 @@ public function staffList(Request $request): \Inertia\Response */ public function staffUpdate(InstitutionStaffEditRequest $request): \Inertia\Response { - InstitutionStaff::where('id', $request->id)->update($request->validated()); + InstitutionStaff::where('id', $request->id) + ->update($request->validated()); $user = User::find(Auth::user()->id); $institution = $user->institution->staff; - return Inertia::render('Institution::Staff', ['status' => true, 'results' => $institution]); + return Inertia::render('Institution::Staff', [ + 'status' => true, + 'results' => $institution, + ]); } /** @@ -106,13 +134,27 @@ public function staffUpdateRole(Request $request): \Inertia\Response $newRole = Role::where('name', Role::Institution_USER)->first(); } - $rolesToCheck = [Role::Ministry_ADMIN, Role::SUPER_ADMIN, Role::Institution_ADMIN, Role::Institution_USER]; - if (Auth::user()->roles()->pluck('name')->intersect($rolesToCheck)->isNotEmpty() && Auth::user()->disabled === false) { - $staff = InstitutionStaff::where('id', $request->input('id'))->first(); + $rolesToCheck = [ + Role::Ministry_ADMIN, + Role::SUPER_ADMIN, + Role::Institution_ADMIN, + Role::Institution_USER, + ]; + if (Auth::user() + ->roles() + ->pluck('name') + ->intersect($rolesToCheck) + ->isNotEmpty() && Auth::user()->disabled === false) { + $staff = InstitutionStaff::where('id', $request->input('id')) + ->first(); if (! is_null($staff)) { //reset roles - $roles = Role::whereIn('name', [Role::Institution_ADMIN, Role::Institution_USER, Role::Institution_GUEST])->get(); + $roles = Role::whereIn('name', [ + Role::Institution_ADMIN, + Role::Institution_USER, + Role::Institution_GUEST, + ])->get(); foreach ($roles as $role) { $staff->user->roles()->detach($role); } @@ -125,6 +167,9 @@ public function staffUpdateRole(Request $request): \Inertia\Response $user = User::find(Auth::user()->id); $institution = $user->institution->staff; - return Inertia::render('Institution::Staff', ['status' => true, 'results' => $institution]); + return Inertia::render('Institution::Staff', [ + 'status' => true, + 'results' => $institution, + ]); } } diff --git a/Modules/Institution/App/Http/Requests/AttestationEditRequest.php b/Modules/Institution/App/Http/Requests/AttestationEditRequest.php index dec40dd1..d0695766 100644 --- a/Modules/Institution/App/Http/Requests/AttestationEditRequest.php +++ b/Modules/Institution/App/Http/Requests/AttestationEditRequest.php @@ -39,6 +39,7 @@ public function rules(): array 'last_name' => 'required', 'id_number' => 'nullable', 'student_number' => 'nullable', + 'student_confirmation' => 'boolean', 'dob' => 'required|date_format:Y-m-d', 'email' => 'required|email', 'address1' => 'required', @@ -90,6 +91,7 @@ protected function prepareForValidation() 'last_touch_by_user_guid' => $this->user()->guid, 'id_number' => Str::upper($this->id_number), 'student_number' => Str::upper($this->student_number), + 'student_confirmation' => $this->toBoolean($this->student_confirmation), 'first_name' => Str::title($this->first_name), 'last_name' => Str::title($this->last_name), 'email' => Str::lower($this->email), diff --git a/Modules/Institution/App/Http/Requests/AttestationStoreRequest.php b/Modules/Institution/App/Http/Requests/AttestationStoreRequest.php index db23b05f..b79c380e 100644 --- a/Modules/Institution/App/Http/Requests/AttestationStoreRequest.php +++ b/Modules/Institution/App/Http/Requests/AttestationStoreRequest.php @@ -41,6 +41,7 @@ public function rules() 'last_name' => 'required', 'id_number' => 'nullable', 'student_number' => 'nullable', + 'student_confirmation' => 'boolean', 'dob' => 'required|date_format:Y-m-d', 'email' => 'required|email', 'address1' => 'required', @@ -97,6 +98,7 @@ protected function prepareForValidation() 'last_touch_by_user_guid' => $this->user()->guid, 'id_number' => Str::upper($this->id_number), 'student_number' => Str::upper($this->student_number), + 'student_confirmation' => $this->toBoolean($this->student_confirmation), 'first_name' => Str::title($this->first_name), 'last_name' => Str::title($this->last_name), 'email' => Str::lower($this->email), diff --git a/Modules/Institution/resources/assets/js/Components/AttestationCreate.vue b/Modules/Institution/resources/assets/js/Components/AttestationCreate.vue index b4878895..c761ad63 100644 --- a/Modules/Institution/resources/assets/js/Components/AttestationCreate.vue +++ b/Modules/Institution/resources/assets/js/Components/AttestationCreate.vue @@ -6,7 +6,7 @@