- Added buttons for assigning diagnosis and starting diagnosis based on job card status in the job card view. - Implemented a modal for assigning technicians for diagnosis, including form validation and technician selection. - Updated routes to include a test route for job cards. - Created a new Blade view for testing inspection inputs. - Developed comprehensive feature tests for the estimate module, including creation, viewing, editing, and validation of estimates. - Added tests for estimate model relationships and statistics calculations. - Introduced a basic feature test for job cards index.
186 lines
5.3 KiB
PHP
186 lines
5.3 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
|
|
|
class JobCard extends Model
|
|
{
|
|
use HasFactory;
|
|
|
|
protected $fillable = [
|
|
'job_card_number',
|
|
'branch_code',
|
|
'customer_id',
|
|
'vehicle_id',
|
|
'arrival_datetime',
|
|
'expected_completion_date',
|
|
'mileage_in',
|
|
'mileage_out',
|
|
'fuel_level_in',
|
|
'fuel_level_out',
|
|
'status',
|
|
'priority',
|
|
'service_advisor_id',
|
|
'assigned_technician_id',
|
|
'assignment_notes',
|
|
'assigned_at',
|
|
'diagnosis_started_at',
|
|
'diagnosis_completed_at',
|
|
'notes',
|
|
'customer_reported_issues',
|
|
'vehicle_condition_notes',
|
|
'keys_location',
|
|
'personal_items_removed',
|
|
'photos_taken',
|
|
'completion_datetime',
|
|
'delivery_method',
|
|
'customer_satisfaction_rating',
|
|
'delivered_by_id',
|
|
'delivery_notes',
|
|
'archived_at',
|
|
'incoming_inspection_data',
|
|
'outgoing_inspection_data',
|
|
'quality_alerts',
|
|
];
|
|
|
|
// Enhanced status constants following the 11-step workflow
|
|
public const STATUS_RECEIVED = 'received';
|
|
|
|
public const STATUS_INSPECTED = 'inspected';
|
|
|
|
public const STATUS_ASSIGNED_FOR_DIAGNOSIS = 'assigned_for_diagnosis';
|
|
|
|
public const STATUS_IN_DIAGNOSIS = 'in_diagnosis';
|
|
|
|
public const STATUS_ESTIMATE_SENT = 'estimate_sent';
|
|
|
|
public const STATUS_APPROVED = 'approved';
|
|
|
|
public const STATUS_PARTS_PROCUREMENT = 'parts_procurement';
|
|
|
|
public const STATUS_IN_PROGRESS = 'in_progress';
|
|
|
|
public const STATUS_QUALITY_REVIEW_REQUIRED = 'quality_review_required';
|
|
|
|
public const STATUS_COMPLETED = 'completed';
|
|
|
|
public const STATUS_DELIVERED = 'delivered';
|
|
|
|
public static function getStatusOptions(): array
|
|
{
|
|
return [
|
|
self::STATUS_RECEIVED => 'Vehicle Received',
|
|
self::STATUS_INSPECTED => 'Initial Inspection Complete',
|
|
self::STATUS_ASSIGNED_FOR_DIAGNOSIS => 'Assigned for Diagnosis',
|
|
self::STATUS_IN_DIAGNOSIS => 'Diagnosis In Progress',
|
|
self::STATUS_ESTIMATE_SENT => 'Estimate Sent to Customer',
|
|
self::STATUS_APPROVED => 'Estimate Approved',
|
|
self::STATUS_PARTS_PROCUREMENT => 'Parts Procurement',
|
|
self::STATUS_IN_PROGRESS => 'Work in Progress',
|
|
self::STATUS_QUALITY_REVIEW_REQUIRED => 'Quality Review Required',
|
|
self::STATUS_COMPLETED => 'Work Completed',
|
|
self::STATUS_DELIVERED => 'Vehicle Delivered',
|
|
];
|
|
}
|
|
|
|
protected $casts = [
|
|
'arrival_datetime' => 'datetime',
|
|
'expected_completion_date' => 'datetime',
|
|
'completion_datetime' => 'datetime',
|
|
'assigned_at' => 'datetime',
|
|
'diagnosis_started_at' => 'datetime',
|
|
'diagnosis_completed_at' => 'datetime',
|
|
'archived_at' => 'datetime',
|
|
'personal_items_removed' => 'boolean',
|
|
'photos_taken' => 'boolean',
|
|
'incoming_inspection_data' => 'array',
|
|
'outgoing_inspection_data' => 'array',
|
|
];
|
|
|
|
protected static function boot()
|
|
{
|
|
parent::boot();
|
|
|
|
static::creating(function ($jobCard) {
|
|
if (empty($jobCard->job_card_number)) {
|
|
$branchCode = $jobCard->branch_code ?? config('app.default_branch_code', 'ACC');
|
|
$nextNumber = static::where('branch_code', $branchCode)
|
|
->whereYear('created_at', now()->year)
|
|
->count() + 1;
|
|
|
|
$jobCard->job_card_number = $branchCode.'/'.str_pad($nextNumber, 5, '0', STR_PAD_LEFT);
|
|
}
|
|
});
|
|
}
|
|
|
|
public function customer(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Customer::class);
|
|
}
|
|
|
|
public function vehicle(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Vehicle::class);
|
|
}
|
|
|
|
public function serviceAdvisor(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'service_advisor_id');
|
|
}
|
|
|
|
public function assignedTechnician(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'assigned_technician_id');
|
|
}
|
|
|
|
public function branch(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Branch::class, 'branch_code', 'code');
|
|
}
|
|
|
|
public function incomingInspection(): HasOne
|
|
{
|
|
return $this->hasOne(VehicleInspection::class)->incoming();
|
|
}
|
|
|
|
public function outgoingInspection(): HasOne
|
|
{
|
|
return $this->hasOne(VehicleInspection::class)->outgoing();
|
|
}
|
|
|
|
public function diagnosis(): HasOne
|
|
{
|
|
return $this->hasOne(Diagnosis::class);
|
|
}
|
|
|
|
public function workOrders(): HasMany
|
|
{
|
|
return $this->hasMany(WorkOrder::class);
|
|
}
|
|
|
|
public function timesheets(): HasMany
|
|
{
|
|
return $this->hasMany(Timesheet::class);
|
|
}
|
|
|
|
public function estimates(): HasMany
|
|
{
|
|
return $this->hasMany(Estimate::class);
|
|
}
|
|
|
|
public function scopeByBranch($query, $branchCode)
|
|
{
|
|
return $query->where('branch_code', $branchCode);
|
|
}
|
|
|
|
public function scopeByStatus($query, $status)
|
|
{
|
|
return $query->where('status', $status);
|
|
}
|
|
}
|