latest()->paginate(15); return view('invoices.index', compact('invoices')); } public function create(): View { $clients = Client::where('status', 'active')->orderBy('name')->get(); $statuses = InvoiceStatus::cases(); $invoiceSettings = InvoiceSettings::instance(); return view('invoices.create', compact('clients', 'statuses', 'invoiceSettings')); } public function store(Request $request): RedirectResponse { $validated = $request->validate([ 'client_id' => 'nullable|exists:clients,id', 'title' => 'required|string|max:255', 'description' => 'nullable|string', 'tax_rate' => 'required|numeric|min:0|max:100', 'currency' => 'required|string|max:10', 'issue_date' => 'required|date', 'due_date' => 'required|date|after_or_equal:issue_date', 'notes' => 'nullable|string', 'bank_name' => 'nullable|string|max:100', 'bank_account' => 'nullable|string|max:50', 'bank_holder' => 'nullable|string|max:100', 'branch_name' => 'nullable|string|max:100', 'items' => 'required|array|min:1', 'items.*.description' => 'required|string', 'items.*.quantity' => 'required|integer|min:1', 'items.*.unit_price' => 'required|numeric|min:0', 'items.*.is_taxable' => 'nullable|boolean', ]); $items = $validated['items']; unset($validated['items']); $validated['status'] = InvoiceStatus::Draft->value; $invoice = $this->invoiceService->create($validated, $items); return redirect()->route('invoices.show', $invoice) ->with('success', '🧾 Invoice created!'); } public function show(Invoice $invoice): View { $invoice->load('client', 'items'); $invoiceSettings = InvoiceSettings::instance(); return view('invoices.show', compact('invoice', 'invoiceSettings')); } public function edit(Invoice $invoice): View { $clients = Client::where('status', 'active')->orderBy('name')->get(); $statuses = InvoiceStatus::cases(); $invoiceSettings = InvoiceSettings::instance(); $invoice->load('client', 'items'); return view('invoices.edit', compact('invoice', 'clients', 'statuses', 'invoiceSettings')); } public function update(Request $request, Invoice $invoice): RedirectResponse { $validated = $request->validate([ 'client_id' => 'nullable|exists:clients,id', 'title' => 'required|string|max:255', 'description' => 'nullable|string', 'tax_rate' => 'required|numeric|min:0|max:100', 'status' => 'required|in:draft,sent,paid,overdue,cancelled', 'issue_date' => 'required|date', 'due_date' => 'required|date', 'paid_date' => 'nullable|date', 'notes' => 'nullable|string', 'bank_name' => 'nullable|string|max:100', 'bank_account' => 'nullable|string|max:50', 'bank_holder' => 'nullable|string|max:100', 'branch_name' => 'nullable|string|max:100', 'items' => 'required|array|min:1', 'items.*.description' => 'required|string', 'items.*.quantity' => 'required|integer|min:1', 'items.*.unit_price' => 'required|numeric|min:0', 'items.*.is_taxable' => 'nullable|boolean', ]); $items = $validated['items']; unset($validated['items']); $this->invoiceService->update($invoice, $validated, $items); return redirect()->route('invoices.show', $invoice) ->with('success', '🧾 Invoice updated!'); } public function destroy(Invoice $invoice): RedirectResponse { $invoice->delete(); return redirect()->route('invoices.index')->with('success', 'Invoice deleted.'); } public function pdf(Invoice $invoice): Response { return $this->invoiceService->generatePdf($invoice); } }