sackey e839d40a99
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
Initial commit
2025-07-30 17:15:50 +00:00

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');
}
}