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(), ]); } }