*/ use HasFactory; protected $fillable = [ 'order_number', 'customer_id', 'vehicle_id', 'assigned_technician_id', 'customer_complaint', 'recommended_services', 'priority', 'status', 'labor_cost', 'parts_cost', 'tax_amount', 'discount_amount', 'total_amount', 'scheduled_date', 'started_at', 'completed_at', 'estimated_hours', 'actual_hours', 'internal_notes', 'customer_notes', ]; protected $casts = [ 'scheduled_date' => 'datetime', 'started_at' => 'datetime', 'completed_at' => 'datetime', 'labor_cost' => 'decimal:2', 'parts_cost' => 'decimal:2', 'tax_amount' => 'decimal:2', 'discount_amount' => 'decimal:2', 'total_amount' => 'decimal:2', ]; protected static function boot() { parent::boot(); static::creating(function ($serviceOrder) { if (empty($serviceOrder->order_number)) { $serviceOrder->order_number = 'SO-' . str_pad( static::count() + 1, 6, '0', STR_PAD_LEFT ); } }); } public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } public function vehicle(): BelongsTo { return $this->belongsTo(Vehicle::class); } public function assignedTechnician(): BelongsTo { return $this->belongsTo(Technician::class, 'assigned_technician_id'); } public function serviceItems(): HasMany { return $this->hasMany(ServiceItem::class); } public function parts(): BelongsToMany { return $this->belongsToMany(Part::class, 'service_order_parts') ->withPivot(['quantity_used', 'unit_cost', 'unit_price', 'total_cost', 'total_price', 'status', 'notes']) ->withTimestamps(); } public function inspections(): HasMany { return $this->hasMany(VehicleInspection::class); } public function appointments(): HasMany { return $this->hasMany(Appointment::class); } public function calculateTotals(): void { $this->labor_cost = $this->serviceItems->sum('labor_cost'); $this->parts_cost = $this->parts->sum('pivot.total_price'); $subtotal = $this->labor_cost + $this->parts_cost - $this->discount_amount; $this->tax_amount = $subtotal * 0.08; // 8% tax rate - should be configurable $this->total_amount = $subtotal + $this->tax_amount; $this->save(); } }