request->getGet('school_year'); $model = new FinancialAidRequestModel(); $builder = $model->orderBy('created_at', 'DESC'); if (is_string($schoolYear) && trim($schoolYear) !== '') { $builder->where('school_year', trim($schoolYear)); } $requests = $builder->findAll(); $parentIds = array_values(array_unique(array_filter(array_map('intval', array_column($requests, 'parent_id'))))); $parents = []; if ($parentIds !== []) { foreach ((new UserModel())->select('id, firstname, lastname, email')->whereIn('id', $parentIds)->findAll() as $parent) { $parents[(int) $parent['id']] = $parent; } } return view('administrator/financial_aid_queue', [ 'requests' => $requests, 'parents' => $parents, 'schoolYear' => is_string($schoolYear) ? trim($schoolYear) : '', ]); } public function show(int $id) { $request = (new FinancialAidRequestModel())->find($id); if ($request === null) { return redirect()->to('/administrator/financial-aid')->with('error', 'Financial aid request was not found.'); } $parent = (new UserModel())->find((int) $request['parent_id']); $studentIds = json_decode((string) ($request['student_ids_json'] ?? '[]'), true); $studentIds = is_array($studentIds) ? array_map('intval', $studentIds) : []; $students = $studentIds !== [] ? (new StudentModel())->whereIn('id', $studentIds)->findAll() : []; $schoolYear = (string) ($request['school_year'] ?? ''); $invoiceBalance = $this->invoiceBalanceForParent((int) ($request['parent_id'] ?? 0), $schoolYear); $householdSize = max(1, (int) ($request['household_size'] ?? 1)); $householdIncome = (float) ($request['household_income'] ?? 0); $requestedAmount = (float) ($request['requested_amount'] ?? 0); $estimateModel = new FinancialAidEstimateModel(); $estimatedAid = $estimateModel->estimatedAid($invoiceBalance, $householdSize, $householdIncome); $finalRebate = $estimateModel->finalRebate($invoiceBalance, $householdSize, $householdIncome, $requestedAmount); return view('administrator/financial_aid_review', [ 'requestRow' => $request, 'parent' => $parent, 'students' => $students, 'schoolYear' => $schoolYear, 'invoiceBalance' => $invoiceBalance, 'estimatedAid' => $estimatedAid, 'finalRebate' => $finalRebate, ]); } public function estimate(int $id) { $request = (new FinancialAidRequestModel())->find($id); if ($request === null) { return $this->response->setStatusCode(404)->setJSON(['error' => 'Financial aid request was not found.']); } $householdIncomeRaw = trim((string) $this->request->getPost('household_income')); $householdSizeRaw = (int) $this->request->getPost('household_size'); $schoolYear = (string) ($request['school_year'] ?? ''); $invoiceBalance = $this->invoiceBalanceForParent((int) ($request['parent_id'] ?? 0), $schoolYear); if ($householdIncomeRaw === '' || ! is_numeric($householdIncomeRaw) || (float) $householdIncomeRaw < 0) { return $this->response->setStatusCode(422)->setJSON(['error' => 'Enter a valid household income.']); } if ($householdSizeRaw < 1) { return $this->response->setStatusCode(422)->setJSON(['error' => 'Household size must be at least 1.']); } try { $estimateModel = new FinancialAidEstimateModel(); $householdIncome = round((float) $householdIncomeRaw, 2); $estimatedAid = $estimateModel->estimatedAid($invoiceBalance, $householdSizeRaw, $householdIncome); $finalRebate = $estimateModel->finalRebate( $invoiceBalance, $householdSizeRaw, $householdIncome, (float) ($request['requested_amount'] ?? 0) ); return $this->response->setJSON([ 'invoice_balance' => $invoiceBalance, 'estimated_aid' => $estimatedAid, 'final_rebate' => $finalRebate, 'csrf_token' => csrf_token(), 'csrf_hash' => csrf_hash(), ]); } catch (InvalidArgumentException $e) { return $this->response->setStatusCode(422)->setJSON(['error' => $e->getMessage()]); } } public function approve(int $id) { try { $model = new FinancialAidRequestModel(); $request = $model->find($id); if ($request === null) { return redirect()->to('/administrator/financial-aid')->with('error', 'Financial aid request was not found.'); } if (! in_array((string) ($request['status'] ?? ''), ['submitted', 'under_review'], true)) { return redirect()->back()->with('error', 'Only open requests can be approved.'); } $amount = $this->approvalAmount($request); $note = trim((string) $this->request->getPost('admin_note')); service('financialAid')->applyApprovedAmount($request, $amount, (int) session()->get('user_id'), $note); return redirect()->to('/administrator/financial-aid')->with('success', 'Financial aid was approved and applied to the invoice.'); } catch (Throwable $e) { return redirect()->back()->withInput()->with('error', $e->getMessage()); } } public function deny(int $id) { $model = new FinancialAidRequestModel(); $request = $model->find($id); if ($request === null) { return redirect()->to('/administrator/financial-aid')->with('error', 'Financial aid request was not found.'); } if (! in_array((string) ($request['status'] ?? ''), ['submitted', 'under_review'], true)) { return redirect()->back()->with('error', 'Only open requests can be denied.'); } $note = trim((string) $this->request->getPost('admin_note')); if ($note === '') { return redirect()->back()->with('error', 'A denial note is required.'); } $model->update($id, [ 'status' => 'denied', 'admin_note' => $note, 'reviewed_by' => (int) session()->get('user_id'), 'reviewed_at' => date('Y-m-d H:i:s'), ]); return redirect()->to('/administrator/financial-aid')->with('success', 'Financial aid request was denied.'); } private function approvalAmount(array $request): float { $postedAmount = trim((string) $this->request->getPost('admin_amount')); if ($postedAmount !== '') { return (float) $postedAmount; } return (float) ($request['requested_amount'] ?? 0); } private function invoiceBalanceForParent(int $parentId, string $schoolYear): float { if ($parentId <= 0 || $schoolYear === '') { return 0.0; } $invoice = (new InvoiceModel()) ->where('parent_id', $parentId) ->where('school_year', $schoolYear) ->orderBy('id', 'DESC') ->first(); if ($invoice === null) { return 0.0; } return round((float) ($invoice['balance'] ?? 0), 2); } }