estimate = $estimate; $this->authorize('create', Invoice::class); // Pre-fill form with estimate data $this->subject = $estimate->subject; $this->description = $estimate->description; $this->branch_id = $estimate->branch_id; $this->invoice_date = now()->format('Y-m-d'); $this->due_date = now()->addDays(30)->format('Y-m-d'); $this->tax_rate = $estimate->tax_rate; // Load estimate line items $this->lineItems = $estimate->estimateLineItems->map(function ($item) { return [ 'type' => $item->type, 'service_item_id' => $item->service_item_id, 'part_id' => $item->part_id, 'description' => $item->description, 'quantity' => $item->quantity, 'unit_price' => $item->unit_price, 'total' => $item->total, ]; })->toArray(); $this->loadFormData(); } public function loadFormData() { $this->branches = Branch::all(); $this->serviceItems = ServiceItem::all(); $this->parts = Part::all(); } public function addLineItem() { $this->lineItems[] = [ 'type' => 'service', 'service_item_id' => '', 'part_id' => '', 'description' => '', 'quantity' => 1, 'unit_price' => 0, 'total' => 0, ]; } public function removeLineItem($index) { unset($this->lineItems[$index]); $this->lineItems = array_values($this->lineItems); } public function updatedLineItems($value, $key) { $keyParts = explode('.', $key); $index = $keyParts[0]; $field = $keyParts[1]; if ($field === 'type') { // Reset related fields when type changes $this->lineItems[$index]['service_item_id'] = ''; $this->lineItems[$index]['part_id'] = ''; $this->lineItems[$index]['description'] = ''; $this->lineItems[$index]['unit_price'] = 0; } if ($field === 'service_item_id' && $this->lineItems[$index]['type'] === 'service') { $serviceItem = ServiceItem::find($value); if ($serviceItem) { $this->lineItems[$index]['description'] = $serviceItem->name; $this->lineItems[$index]['unit_price'] = $serviceItem->price; } } if ($field === 'part_id' && $this->lineItems[$index]['type'] === 'part') { $part = Part::find($value); if ($part) { $this->lineItems[$index]['description'] = $part->name; $this->lineItems[$index]['unit_price'] = $part->sell_price; } } // Recalculate total for this line item if (in_array($field, ['quantity', 'unit_price'])) { $quantity = (float) $this->lineItems[$index]['quantity']; $unitPrice = (float) $this->lineItems[$index]['unit_price']; $this->lineItems[$index]['total'] = $quantity * $unitPrice; } } public function getSubtotalProperty() { return collect($this->lineItems)->sum('total'); } public function getTaxAmountProperty() { return $this->subtotal * ($this->tax_rate / 100); } public function getTotalProperty() { return $this->subtotal + $this->taxAmount; } public function save() { $this->validate(); $invoice = Invoice::create([ 'job_card_id' => $this->estimate->job_card_id, 'estimate_id' => $this->estimate->id, 'customer_id' => $this->estimate->customer_id, 'branch_id' => $this->branch_id, 'created_by' => auth()->id(), 'invoice_number' => Invoice::generateInvoiceNumber($this->branch_id), 'subject' => $this->subject, 'description' => $this->description, 'invoice_date' => $this->invoice_date, 'due_date' => $this->due_date, 'subtotal' => $this->subtotal, 'tax_rate' => $this->tax_rate, 'tax_amount' => $this->taxAmount, 'total_amount' => $this->total, 'status' => 'draft', ]); // Create line items foreach ($this->lineItems as $item) { $invoice->invoiceLineItems()->create([ 'type' => $item['type'], 'service_item_id' => $item['service_item_id'] ?: null, 'part_id' => $item['part_id'] ?: null, 'description' => $item['description'], 'quantity' => $item['quantity'], 'unit_price' => $item['unit_price'], 'total' => $item['total'], ]); } session()->flash('success', 'Invoice created successfully from estimate.'); return redirect()->route('invoices.show', $invoice); } public function render() { return view('livewire.invoices.create-from-estimate') ->layout('layouts.app'); } }