Files
alrahma_sunday_school_api/app/Http/Controllers/Api/Finance/InvoiceController.php
T
2026-06-09 01:25:14 -04:00

167 lines
5.6 KiB
PHP

<?php
namespace App\Http\Controllers\Api\Finance;
use App\Http\Controllers\Api\Core\BaseApiController;
use App\Http\Requests\Invoices\InvoiceManagementRequest;
use App\Http\Requests\Invoices\InvoiceParentRequest;
use App\Http\Requests\Invoices\InvoiceStatusRequest;
use App\Http\Resources\Invoices\InvoiceManagementParentResource;
use App\Http\Resources\Invoices\InvoiceResource;
use App\Models\Invoice;
use App\Services\Invoices\InvoiceGenerationService;
use App\Services\Invoices\InvoiceManagementService;
use App\Services\Invoices\InvoicePaymentService;
use App\Services\Invoices\InvoicePdfService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\StreamedResponse;
class InvoiceController extends BaseApiController
{
public function __construct(
private InvoiceManagementService $management,
private InvoiceGenerationService $generation,
private InvoicePaymentService $paymentService,
private InvoicePdfService $pdfService
) {
parent::__construct();
}
public function management(InvoiceManagementRequest $request): JsonResponse
{
$schoolYear = $request->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']);
}
private function authenticatedUserIdOrUnauthorized(): int|JsonResponse
{
$userId = (int) (auth()->id() ?? 0);
if ($userId <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401);
}
return $userId;
}
}