245 lines
7.4 KiB
PHP
245 lines
7.4 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\ServiceOrders;
|
|
|
|
use App\Models\ServiceOrder;
|
|
use App\Models\Customer;
|
|
use App\Models\Vehicle;
|
|
use App\Models\Technician;
|
|
use App\Models\Part;
|
|
use Livewire\Component;
|
|
use Livewire\Attributes\Validate;
|
|
|
|
class Edit extends Component
|
|
{
|
|
public ServiceOrder $serviceOrder;
|
|
|
|
#[Validate('required')]
|
|
public $customer_id;
|
|
|
|
#[Validate('required')]
|
|
public $vehicle_id;
|
|
|
|
#[Validate('required')]
|
|
public $technician_id;
|
|
|
|
#[Validate('required|string|max:255')]
|
|
public $customer_complaint;
|
|
|
|
#[Validate('nullable|string')]
|
|
public $diagnosis;
|
|
|
|
#[Validate('nullable|string')]
|
|
public $customer_notes;
|
|
|
|
#[Validate('nullable|numeric|min:0')]
|
|
public $discount_amount = 0;
|
|
|
|
#[Validate('required|string')]
|
|
public $status;
|
|
|
|
public $serviceItems = [];
|
|
public $selectedParts = [];
|
|
public $customers = [];
|
|
public $vehicles = [];
|
|
public $technicians = [];
|
|
public $availableParts = [];
|
|
|
|
public function mount(ServiceOrder $serviceOrder)
|
|
{
|
|
$this->serviceOrder = $serviceOrder;
|
|
$this->customer_id = $serviceOrder->customer_id;
|
|
$this->vehicle_id = $serviceOrder->vehicle_id;
|
|
$this->technician_id = $serviceOrder->technician_id;
|
|
$this->customer_complaint = $serviceOrder->customer_complaint;
|
|
$this->diagnosis = $serviceOrder->diagnosis;
|
|
$this->customer_notes = $serviceOrder->customer_notes;
|
|
$this->discount_amount = $serviceOrder->discount_amount;
|
|
$this->status = $serviceOrder->status;
|
|
|
|
// Load existing service items
|
|
$this->serviceItems = $serviceOrder->serviceItems->map(function ($item) {
|
|
return [
|
|
'id' => $item->id,
|
|
'service_name' => $item->service_name,
|
|
'description' => $item->description,
|
|
'labor_rate' => $item->labor_rate,
|
|
'estimated_hours' => $item->estimated_hours,
|
|
'labor_cost' => $item->labor_cost,
|
|
];
|
|
})->toArray();
|
|
|
|
// Load existing parts
|
|
$this->selectedParts = $serviceOrder->parts->map(function ($part) {
|
|
return [
|
|
'part_id' => $part->id,
|
|
'quantity_used' => $part->pivot->quantity_used,
|
|
'unit_price' => $part->pivot->unit_price,
|
|
'total_price' => $part->pivot->total_price,
|
|
];
|
|
})->toArray();
|
|
|
|
$this->loadData();
|
|
}
|
|
|
|
public function loadData()
|
|
{
|
|
$this->customers = Customer::orderBy('first_name')->get();
|
|
$this->vehicles = $this->customer_id ?
|
|
Vehicle::where('customer_id', $this->customer_id)->get() :
|
|
collect();
|
|
$this->technicians = Technician::where('status', 'active')->orderBy('first_name')->get();
|
|
$this->availableParts = Part::where('quantity_on_hand', '>', 0)->orderBy('name')->get();
|
|
}
|
|
|
|
public function updatedCustomerId()
|
|
{
|
|
$this->vehicle_id = null;
|
|
$this->vehicles = $this->customer_id ?
|
|
Vehicle::where('customer_id', $this->customer_id)->get() :
|
|
collect();
|
|
}
|
|
|
|
public function addServiceItem()
|
|
{
|
|
$this->serviceItems[] = [
|
|
'id' => null,
|
|
'service_name' => '',
|
|
'description' => '',
|
|
'labor_rate' => 75.00,
|
|
'estimated_hours' => 1,
|
|
'labor_cost' => 75.00,
|
|
];
|
|
}
|
|
|
|
public function removeServiceItem($index)
|
|
{
|
|
unset($this->serviceItems[$index]);
|
|
$this->serviceItems = array_values($this->serviceItems);
|
|
}
|
|
|
|
public function updateServiceItemCost($index)
|
|
{
|
|
if (isset($this->serviceItems[$index])) {
|
|
$item = &$this->serviceItems[$index];
|
|
$item['labor_cost'] = $item['labor_rate'] * $item['estimated_hours'];
|
|
}
|
|
}
|
|
|
|
public function addPart()
|
|
{
|
|
$this->selectedParts[] = [
|
|
'part_id' => '',
|
|
'quantity_used' => 1,
|
|
'unit_price' => 0,
|
|
'total_price' => 0,
|
|
];
|
|
}
|
|
|
|
public function removePart($index)
|
|
{
|
|
unset($this->selectedParts[$index]);
|
|
$this->selectedParts = array_values($this->selectedParts);
|
|
}
|
|
|
|
public function updatePartPrice($index)
|
|
{
|
|
if (isset($this->selectedParts[$index])) {
|
|
$part = &$this->selectedParts[$index];
|
|
if ($part['part_id']) {
|
|
$partModel = Part::find($part['part_id']);
|
|
if ($partModel) {
|
|
$part['unit_price'] = $partModel->cost_price * 1.3; // 30% markup
|
|
}
|
|
}
|
|
$part['total_price'] = $part['quantity_used'] * $part['unit_price'];
|
|
}
|
|
}
|
|
|
|
public function updatePartTotal($index)
|
|
{
|
|
if (isset($this->selectedParts[$index])) {
|
|
$part = &$this->selectedParts[$index];
|
|
$part['total_price'] = $part['quantity_used'] * $part['unit_price'];
|
|
}
|
|
}
|
|
|
|
public function getTotalLaborCost()
|
|
{
|
|
return collect($this->serviceItems)->sum('labor_cost');
|
|
}
|
|
|
|
public function getTotalPartsCost()
|
|
{
|
|
return collect($this->selectedParts)->sum('total_price');
|
|
}
|
|
|
|
public function getSubtotal()
|
|
{
|
|
return $this->getTotalLaborCost() + $this->getTotalPartsCost() - $this->discount_amount;
|
|
}
|
|
|
|
public function getTaxAmount()
|
|
{
|
|
return $this->getSubtotal() * 0.08; // 8% tax
|
|
}
|
|
|
|
public function getGrandTotal()
|
|
{
|
|
return $this->getSubtotal() + $this->getTaxAmount();
|
|
}
|
|
|
|
public function update()
|
|
{
|
|
$this->validate();
|
|
|
|
// Update the service order
|
|
$this->serviceOrder->update([
|
|
'customer_id' => $this->customer_id,
|
|
'vehicle_id' => $this->vehicle_id,
|
|
'technician_id' => $this->technician_id,
|
|
'customer_complaint' => $this->customer_complaint,
|
|
'diagnosis' => $this->diagnosis,
|
|
'customer_notes' => $this->customer_notes,
|
|
'discount_amount' => $this->discount_amount,
|
|
'status' => $this->status,
|
|
'labor_cost' => $this->getTotalLaborCost(),
|
|
'parts_cost' => $this->getTotalPartsCost(),
|
|
'tax_amount' => $this->getTaxAmount(),
|
|
'total_amount' => $this->getGrandTotal(),
|
|
]);
|
|
|
|
// Update service items
|
|
$this->serviceOrder->serviceItems()->delete();
|
|
foreach ($this->serviceItems as $item) {
|
|
$this->serviceOrder->serviceItems()->create([
|
|
'service_name' => $item['service_name'],
|
|
'description' => $item['description'],
|
|
'labor_rate' => $item['labor_rate'],
|
|
'estimated_hours' => $item['estimated_hours'],
|
|
'labor_cost' => $item['labor_cost'],
|
|
]);
|
|
}
|
|
|
|
// Update parts
|
|
$this->serviceOrder->parts()->detach();
|
|
foreach ($this->selectedParts as $part) {
|
|
if ($part['part_id']) {
|
|
$this->serviceOrder->parts()->attach($part['part_id'], [
|
|
'quantity_used' => $part['quantity_used'],
|
|
'unit_price' => $part['unit_price'],
|
|
'total_price' => $part['total_price'],
|
|
]);
|
|
}
|
|
}
|
|
|
|
session()->flash('success', 'Service order updated successfully!');
|
|
return redirect()->route('service-orders.show', $this->serviceOrder);
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.service-orders.edit');
|
|
}
|
|
}
|