validated()['school_year'] ?? null; $schoolYear = $schoolYear ?: $request->input('schoolYear'); $schoolYear = $schoolYear ?: $request->input('year'); $data = $this->management->getManagementData($schoolYear); return response()->json([ 'ok' => true, 'schoolYear' => $data['schoolYear'], 'schoolYears' => $data['schoolYears'], 'invoices' => InvoiceManagementParentResource::collection($data['invoices']), ]); } public function generate(Request $request): JsonResponse { $data = array_merge($request->query->all(), $request->all(), $request->json()->all()); $validator = Validator::make($data, [ 'parent_id' => ['required', 'integer', 'exists:users,id'], 'school_year' => ['nullable', 'string', 'max:20'], ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $payload = $validator->validated(); $result = $this->generation->generateInvoice((int) $payload['parent_id'], $payload['school_year'] ?? null); if (empty($result['ok'])) { return response()->json(['ok' => false, 'message' => $result['message'] ?? 'Unable to generate invoice.'], 422); } return response()->json([ 'ok' => true, 'updated' => $result['updated'] ?? false, 'updated_ids' => $result['updated_ids'] ?? [], 'insert_id' => $result['insert_id'] ?? null, ]); } public function byParent(InvoiceParentRequest $request, int $parentId): JsonResponse { $schoolYear = $request->validated()['school_year'] ?? null; $invoices = Invoice::getInvoicesByParentId($parentId, $schoolYear); return response()->json([ 'ok' => true, 'invoices' => InvoiceResource::collection($invoices), ]); } public function parentPayment(InvoiceParentRequest $request): JsonResponse { $parentId = $this->authenticatedUserIdOrUnauthorized(); if ($parentId instanceof JsonResponse) { return $parentId; } $schoolYear = $request->validated()['school_year'] ?? null; $data = $this->paymentService->getParentInvoiceSummary($parentId, $schoolYear); return response()->json([ 'ok' => true, 'invoices' => InvoiceResource::collection($data['invoices']), 'schoolYears' => $data['schoolYears'], 'selectedYear' => $data['selectedYear'], 'currentSchoolYear' => $data['currentSchoolYear'], 'dueDate' => $data['dueDate'], ]); } public function updateStatus(InvoiceStatusRequest $request, int $invoiceId): JsonResponse { $status = $request->validated()['status']; $updated = Invoice::updateInvoiceStatus($invoiceId, $status); if (!$updated) { return response()->json(['ok' => false, 'message' => 'Invoice not found.'], 404); } return response()->json(['ok' => true, 'status' => $status]); } public function unpaid(): JsonResponse { $rows = Invoice::getUnpaidInvoices(); return response()->json([ 'ok' => true, 'invoices' => InvoiceResource::collection($rows), ]); } public function preview(int $invoiceId): JsonResponse { $data = $this->pdfService->previewData($invoiceId); if (isset($data['error'])) { return response()->json([ 'ok' => false, 'message' => $data['error'], ], 404); } return response()->json([ 'ok' => true, ...$data, ]); } public function pdf(int $invoiceId): StreamedResponse { $pdfBytes = $this->pdfService->buildPdf($invoiceId); return response()->streamDownload(function () use ($pdfBytes) { echo $pdfBytes; }, 'invoice_' . $invoiceId . '.pdf', ['Content-Type' => 'application/pdf']); } /** * @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; } }