physiotherapy-clinic/app/Http/Controllers/Api/InvoiceController.php

135 lines
4.3 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\InvoiceResource;
use App\Models\Invoice;
use App\Models\Payment;
use App\Services\LedgerService;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
class InvoiceController extends Controller
{
public function index(Request $request)
{
$query = Invoice::with(['patient', 'currency']);
if ($request->has('patient_id')) {
$query->where('patient_id', $request->patient_id);
}
if ($request->has('status')) {
$query->where('status', $request->status);
}
if ($request->has('date_from')) {
$query->whereDate('invoice_date', '>=', $request->date_from);
}
if ($request->has('date_to')) {
$query->whereDate('invoice_date', '<=', $request->date_to);
}
$invoices = $query->orderByDesc('invoice_date')->paginate($request->per_page ?? 20);
return InvoiceResource::collection($invoices);
}
public function store(Request $request)
{
$data = $request->validate([
'patient_id' => 'required|exists:patients,id',
'invoice_date' => 'required|date',
'due_date' => 'required|date|after_or_equal:invoice_date',
'subtotal' => 'required|numeric|min:0',
'tax_amount' => 'nullable|numeric|min:0',
'discount_amount' => 'nullable|numeric|min:0',
'currency_id' => 'required|exists:currencies,id',
'notes' => 'nullable|string',
]);
$data['created_by'] = auth()->id();
// Calculate total
$data['total_amount'] = $data['subtotal']
+ ($data['tax_amount'] ?? 0)
- ($data['discount_amount'] ?? 0);
$data['paid_amount'] = 0;
// Generate invoice number
$lastId = Invoice::max('id') ?? 0;
$data['invoice_number'] = 'INV-' . date('Y') . '-' . str_pad($lastId + 1, 6, '0', STR_PAD_LEFT);
$invoice = Invoice::create($data);
return new InvoiceResource($invoice);
}
public function show(Invoice $invoice)
{
return new InvoiceResource($invoice);
}
public function update(Request $request, Invoice $invoice)
{
if (in_array($invoice->status, ['paid', 'cancelled'])) {
return response()->json(['message' => 'Cannot update paid or cancelled invoice'], 422);
}
$data = $request->validate([
'invoice_date' => 'sometimes|date',
'due_date' => 'sometimes|date',
'subtotal' => 'sometimes|numeric|min:0',
'tax_amount' => 'nullable|numeric|min:0',
'discount_amount' => 'nullable|numeric|min:0',
'notes' => 'nullable|string',
'status' => ['sometimes', Rule::in(['draft', 'sent', 'paid', 'partial', 'overdue', 'cancelled'])],
]);
if (isset($data['subtotal'])) {
$data['total_amount'] = $data['subtotal']
+ ($data['tax_amount'] ?? $invoice->tax_amount)
- ($data['discount_amount'] ?? $invoice->discount_amount);
}
$invoice->update($data);
return new InvoiceResource($invoice);
}
public function destroy(Invoice $invoice)
{
if ($invoice->payments()->exists()) {
return response()->json(['message' => 'Cannot delete invoice with payments'], 422);
}
$invoice->delete();
return response()->json(['message' => 'Invoice deleted successfully']);
}
public function summary(Request $request)
{
$query = Invoice::query();
if ($request->has('date_from')) {
$query->whereDate('invoice_date', '>=', $request->date_from);
}
if ($request->has('date_to')) {
$query->whereDate('invoice_date', '<=', $request->date_to);
}
return response()->json([
'total_invoices' => $query->count(),
'total_amount' => $query->sum('total_amount'),
'total_paid' => $query->sum('paid_amount'),
'total_outstanding' => $query->sum('balance'),
'by_status' => $query->selectRaw('status, count(*) as count, sum(total_amount) as amount')
->groupBy('status')
->get(),
]);
}
}