latestForEnrollment($enrollmentId); if ($calculation === null || ($calculation['status'] ?? '') === 'superseded') { $calculation = service('withdrawalFinancial')->preview($enrollmentId, $this->userId()); } elseif ($this->hasStaleInstructionalWeeksBlocker($calculation)) { $calculation = service('withdrawalFinancial')->preview($enrollmentId, $this->userId()); } return view('withdrawals/review', [ 'calculation' => $this->withPostingGateBlockers($calculation), ]); } catch (Throwable $e) { return redirect()->back()->with('error', $e->getMessage()); } } public function recalculate(int $enrollmentId) { try { $calculation = service('withdrawalFinancial')->preview($enrollmentId, $this->userId(), [ 'enrollment_date' => (string) $this->request->getPost('enrollment_date'), 'withdrawal_request_date' => (string) $this->request->getPost('withdrawal_request_date'), 'override_reason' => (string) $this->request->getPost('override_reason'), 'legacy_invoice_confirmed' => (string) $this->request->getPost('legacy_invoice_confirmed') === '1', ]); return redirect()->to('/administrator/withdrawals/' . $enrollmentId . '/review') ->with('success', 'Calculation preview version ' . (int) $calculation['version'] . ' saved.'); } catch (Throwable $e) { return redirect()->back()->withInput()->with('error', $e->getMessage()); } } public function confirm(int $calculationId) { try { $calculation = service('withdrawalFinancial')->post($calculationId, $this->userId()); return redirect()->to('/administrator/withdrawal-calculations/' . $calculationId) ->with('success', ((int) ($calculation['new_refund_request_cents'] ?? 0)) > 0 ? 'Withdrawal posted and the refund request was created.' : 'Withdrawal posted. No refund is due; the invoice balance was recalculated.'); } catch (Throwable $e) { return redirect()->back()->with('error', $e->getMessage()); } } public function calculation(int $calculationId) { try { $calculation = service('withdrawalFinancial')->details($calculationId); if ($this->hasStaleInstructionalWeeksBlocker($calculation)) { $calculation = service('withdrawalFinancial')->preview((int) $calculation['enrollment_id'], $this->userId()); return redirect()->to('/administrator/withdrawal-calculations/' . (int) $calculation['id']) ->with('success', 'Calculation preview refreshed with the configured total instructional weeks.'); } return view('withdrawals/calculation', [ 'calculation' => $calculation, ]); } catch (Throwable $e) { return redirect()->back()->with('error', $e->getMessage()); } } public function invoiceSummary(int $invoiceId) { try { return view('withdrawals/invoice_summary', [ 'calculations' => service('withdrawalFinancial')->calculationsForInvoice($invoiceId), 'invoiceId' => $invoiceId, ]); } catch (Throwable $e) { return redirect()->back()->with('error', $e->getMessage()); } } private function hasStaleInstructionalWeeksBlocker(array $calculation): bool { if (($calculation['status'] ?? '') !== 'requires_review' || ! empty($calculation['posted_at'])) { return false; } $blockers = array_map('strval', (array) ($calculation['blockers'] ?? [])); return in_array('Set a positive total_instructional_weeks value for this school year.', $blockers, true) || in_array('Set a positive total_instructional_weeks value in configuration.', $blockers, true); } /** @return array */ private function withPostingGateBlockers(array $calculation): array { $blockers = array_values(array_filter(array_map('strval', (array) ($calculation['blockers'] ?? [])))); foreach (service('withdrawalFinancial')->postingGateBlockers($calculation) as $blocker) { if (! in_array($blocker, $blockers, true)) { $blockers[] = $blocker; } } $calculation['blockers'] = $blockers; if (isset($calculation['explanation']) && is_array($calculation['explanation'])) { $calculation['explanation']['blockers'] = $blockers; } return $calculation; } private function userId(): ?int { $id = session()->get('user_id'); return $id === null || $id === '' ? null : (int) $id; } }