estimate = $estimate->load([ 'jobCard.customer', 'jobCard.vehicle', 'jobCard.branch', 'customer', // For standalone estimates 'vehicle', // For standalone estimates 'diagnosis', 'preparedBy', 'lineItems', 'workOrders', ]); } public function approveEstimate() { if (! auth()->user()->can('approve', $this->estimate)) { session()->flash('error', 'You do not have permission to approve this estimate.'); return; } try { $this->estimate->update([ 'customer_approval_status' => 'approved', 'customer_approved_at' => now(), 'customer_approval_method' => 'staff_portal', 'status' => 'approved', ]); // Update job card status to approved (if job card exists) if ($this->estimate->jobCard) { $this->estimate->jobCard->update([ 'status' => 'approved', ]); } // Notify relevant parties $customer = $this->estimate->customer ?? $this->estimate->jobCard?->customer; if ($customer) { $customer->notify( new EstimateNotification($this->estimate, 'approved') ); } Log::info('Estimate approved', [ 'estimate_id' => $this->estimate->id, 'approved_by' => auth()->id(), ]); session()->flash('success', 'Estimate approved successfully.'); // Refresh estimate data $this->estimate->refresh(); $this->dispatch('$refresh'); } catch (\Exception $e) { Log::error('Failed to approve estimate', [ 'estimate_id' => $this->estimate->id, 'error' => $e->getMessage(), ]); session()->flash('error', 'Failed to approve estimate. Please try again.'); } } public function rejectEstimate() { if (! auth()->user()->can('reject', $this->estimate)) { session()->flash('error', 'You do not have permission to reject this estimate.'); return; } try { $this->estimate->update([ 'customer_approval_status' => 'rejected', 'customer_approved_at' => now(), 'customer_approval_method' => 'staff_portal', 'status' => 'rejected', ]); // Notify relevant parties $customer = $this->estimate->customer ?? $this->estimate->jobCard?->customer; if ($customer) { $customer->notify( new EstimateNotification($this->estimate, 'rejected') ); } Log::info('Estimate rejected', [ 'estimate_id' => $this->estimate->id, 'rejected_by' => auth()->id(), ]); session()->flash('success', 'Estimate rejected.'); // Refresh estimate data $this->estimate->refresh(); $this->dispatch('$refresh'); } catch (\Exception $e) { Log::error('Failed to reject estimate', [ 'estimate_id' => $this->estimate->id, 'error' => $e->getMessage(), ]); session()->flash('error', 'Failed to reject estimate. Please try again.'); } } public function sendToCustomer() { try { $this->estimate->update([ 'status' => 'sent', 'sent_to_customer_at' => now(), 'sent_by_id' => auth()->id(), ]); // Send notification to customer $customer = $this->estimate->customer ?? $this->estimate->jobCard?->customer; if ($customer) { $customer->notify( new EstimateNotification($this->estimate, 'sent') ); } // Update job card status (if job card exists) if ($this->estimate->jobCard) { $this->estimate->jobCard->update([ 'status' => 'estimate_sent', ]); } Log::info('Estimate sent to customer', [ 'estimate_id' => $this->estimate->id, 'customer_id' => $this->estimate->customer_id ?? $this->estimate->jobCard?->customer?->id, 'sent_by' => auth()->id(), ]); session()->flash('success', 'Estimate sent to customer successfully.'); // Refresh estimate data $this->estimate->refresh(); $this->dispatch('$refresh'); } catch (\Exception $e) { Log::error('Failed to send estimate to customer', [ 'estimate_id' => $this->estimate->id, 'error' => $e->getMessage(), ]); session()->flash('error', 'Failed to send estimate to customer. Please try again.'); } } public function duplicateEstimate() { try { // Create a new estimate based on current one $newEstimate = $this->estimate->replicate(); $newEstimate->estimate_number = 'EST-'.str_pad(Estimate::max('id') + 1, 6, '0', STR_PAD_LEFT); $newEstimate->status = 'draft'; $newEstimate->customer_approval_status = 'pending'; $newEstimate->sent_to_customer_at = null; $newEstimate->customer_viewed_at = null; $newEstimate->customer_approved_at = null; $newEstimate->prepared_by_id = auth()->id(); $newEstimate->save(); // Duplicate line items foreach ($this->estimate->lineItems as $lineItem) { $newLineItem = $lineItem->replicate(); $newLineItem->estimate_id = $newEstimate->id; $newLineItem->save(); } Log::info('Estimate duplicated', [ 'original_estimate_id' => $this->estimate->id, 'new_estimate_id' => $newEstimate->id, 'duplicated_by' => auth()->id(), ]); session()->flash('success', 'Estimate has been duplicated successfully.'); return redirect()->route('estimates.edit', $newEstimate); } catch (\Exception $e) { Log::error('Failed to duplicate estimate', [ 'estimate_id' => $this->estimate->id, 'error' => $e->getMessage(), ]); session()->flash('error', 'Failed to duplicate estimate. Please try again.'); } } public function downloadPDF() { try { // Generate PDF using DomPDF $pdf = Pdf::loadView('estimates.pdf', [ 'estimate' => $this->estimate, ]); // Log the download Log::info('Estimate PDF downloaded', [ 'estimate_id' => $this->estimate->id, 'downloaded_by' => auth()->id(), ]); return response()->streamDownload(function () use ($pdf) { echo $pdf->output(); }, "estimate-{$this->estimate->estimate_number}.pdf"); } catch (\Exception $e) { Log::error('Failed to generate estimate PDF', [ 'estimate_id' => $this->estimate->id, 'error' => $e->getMessage(), ]); session()->flash('error', 'Failed to generate PDF. Please try again.'); } } public function toggleItemDetails() { $this->showItemDetails = ! $this->showItemDetails; } public function refreshEstimate() { $this->estimate->refresh(); session()->flash('success', 'Estimate data refreshed.'); $this->dispatch('$refresh'); } public function createWorkOrder() { if ($this->estimate->customer_approval_status !== 'approved') { session()->flash('error', 'Estimate must be approved before creating a work order.'); return; } return redirect()->route('work-orders.create', ['estimate' => $this->estimate->id]); } #[Layout('components.layouts.app')] public function render() { return view('livewire.estimates.show'); } }