query('school_year') ?? $this->context->getSchoolYear()); $sem = (string) ($request->query('semester') ?? $this->context->getSemester()); $status = $request->query('status') ?: null; $q = trim((string) ($request->query('q') ?? '')) ?: null; $per = (int) ($request->query('per_page') ?? 50); [$rows, $meta] = $this->listService->listForTerm($year, $sem, $status, $q, $per); return response()->json([ 'ok' => true, 'school_year' => $year, 'semester' => $sem, 'rows' => ExtraChargeResource::collection($rows), 'pager' => $meta, ]); } public function options(Request $request): JsonResponse { $q = trim((string) ($request->query('q') ?? '')); $parentOptions = $this->parents->searchParents($q); return response()->json([ 'ok' => true, 'schoolYear' => $this->context->getSchoolYear(), 'semester' => $this->context->getSemester(), 'schoolYears' => $this->meta->getSchoolYears($this->context->getSchoolYear()), 'parents' => ExtraChargeParentOptionResource::collection($parentOptions), ]); } public function parentOptions(Request $request): JsonResponse { $q = trim((string) ($request->query('q') ?? '')); $parentOptions = $this->parents->searchParents($q); return response()->json([ 'results' => ExtraChargeParentOptionResource::collection($parentOptions), ]); } public function invoicesForParent(Request $request): JsonResponse { $parentId = (int) ($request->query('parent_id') ?? 0); $schoolYear = (string) ($request->query('school_year') ?? $this->context->getSchoolYear()); $rows = $this->invoices->listInvoicesForParent($parentId, $schoolYear); return response()->json([ 'results' => ExtraChargeInvoiceOptionResource::collection($rows), ]); } public function store(StoreExtraChargeRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $payload['created_by'] = $userId; $result = $this->chargeService->createCharge($payload); return response()->json($result, $result['ok'] ? 201 : 422); } public function update(UpdateExtraChargeRequest $request, int $id): JsonResponse { $charge = AdditionalCharge::query()->find($id); if (!$charge) { return response()->json(['ok' => false, 'error' => 'Charge not found'], 404); } $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $payload['updated_by'] = $userId; $ok = $this->chargeService->updateCharge($charge, $payload); return response()->json([ 'ok' => $ok, 'id' => $id, ], $ok ? 200 : 422); } public function void(int $id): JsonResponse { $charge = AdditionalCharge::query()->find($id); if (!$charge) { return response()->json(['ok' => false, 'error' => 'Charge not found'], 404); } $ok = $this->chargeService->voidCharge($charge); return response()->json([ 'ok' => $ok, ], $ok ? 200 : 422); } public function reverse(int $id): JsonResponse { $charge = AdditionalCharge::query()->find($id); if (!$charge) { return response()->json(['ok' => false, 'error' => 'Charge not found'], 404); } $ok = $this->chargeService->reverseCharge($charge); return response()->json([ 'ok' => $ok, ], $ok ? 200 : 422); } /** * @return int|JsonResponse */ private function authenticatedUserIdOrUnauthorized(): int|JsonResponse { $userId = (int) (auth()->id() ?? 0); if ($userId <= 0) { return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401); } return $userId; } }