- Implemented the customer portal workflow progress component with detailed service progress tracking, including current status, workflow steps, and contact information. - Developed a management workflow analytics dashboard featuring key performance indicators, charts for revenue by branch, labor utilization, and recent quality issues. - Created tests for admin-only middleware to ensure proper access control for admin routes. - Added tests for customer portal view rendering and workflow integration, ensuring the workflow service operates correctly through various stages. - Introduced a .gitignore file for the debugbar storage directory to prevent unnecessary files from being tracked.
255 lines
9.6 KiB
PHP
255 lines
9.6 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\JobCards;
|
|
|
|
use Livewire\Component;
|
|
use App\Models\JobCard;
|
|
use App\Models\Customer;
|
|
use App\Models\Vehicle;
|
|
use App\Models\User;
|
|
use App\Models\Branch;
|
|
use App\Services\WorkflowService;
|
|
use Illuminate\Validation\Rule;
|
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
|
|
|
class Create extends Component
|
|
{
|
|
use AuthorizesRequests;
|
|
public $customer_id = '';
|
|
public $vehicle_id = '';
|
|
public $service_advisor_id = '';
|
|
public $branch_code = '';
|
|
public $arrival_datetime = '';
|
|
public $expected_completion_date = '';
|
|
public $mileage_in = '';
|
|
public $fuel_level_in = '';
|
|
public $customer_reported_issues = '';
|
|
public $vehicle_condition_notes = '';
|
|
public $keys_location = '';
|
|
public $personal_items_removed = false;
|
|
public $photos_taken = false;
|
|
public $priority = 'medium';
|
|
public $notes = '';
|
|
|
|
// Inspection fields
|
|
public $perform_inspection = true;
|
|
public $inspector_id = '';
|
|
public $overall_condition = '';
|
|
public $inspection_notes = '';
|
|
public $inspection_checklist = [
|
|
'exterior_damage' => '',
|
|
'interior_condition' => '',
|
|
'tire_condition' => '',
|
|
'fluid_levels' => '',
|
|
'lights_working' => '',
|
|
];
|
|
|
|
public $customers = [];
|
|
public $vehicles = [];
|
|
public $serviceAdvisors = [];
|
|
public $inspectors = [];
|
|
public $branches = [];
|
|
|
|
protected function rules()
|
|
{
|
|
return [
|
|
'customer_id' => 'required|exists:customers,id',
|
|
'vehicle_id' => 'required|exists:vehicles,id',
|
|
'service_advisor_id' => 'required|exists:users,id',
|
|
'branch_code' => 'required|string|max:10',
|
|
'arrival_datetime' => 'required|date',
|
|
'expected_completion_date' => 'nullable|date|after:arrival_datetime',
|
|
'mileage_in' => 'required|integer|min:0|max:999999',
|
|
'fuel_level_in' => 'nullable|string|max:20',
|
|
'customer_reported_issues' => 'required|string|max:2000',
|
|
'vehicle_condition_notes' => 'nullable|string|max:1000',
|
|
'keys_location' => 'nullable|string|max:255',
|
|
'personal_items_removed' => 'boolean',
|
|
'photos_taken' => 'boolean',
|
|
'priority' => 'required|in:low,medium,high,urgent',
|
|
'notes' => 'nullable|string|max:2000',
|
|
// Inspection fields
|
|
'perform_inspection' => 'boolean',
|
|
'inspector_id' => $this->perform_inspection ? 'required|exists:users,id' : 'nullable',
|
|
'overall_condition' => $this->perform_inspection ? 'required|in:excellent,good,fair,poor' : 'nullable',
|
|
'inspection_notes' => 'nullable|string|max:1000',
|
|
'inspection_checklist.exterior_damage' => $this->perform_inspection ? 'required|in:excellent,good,fair,poor' : 'nullable',
|
|
'inspection_checklist.interior_condition' => $this->perform_inspection ? 'required|in:excellent,good,fair,poor' : 'nullable',
|
|
'inspection_checklist.tire_condition' => $this->perform_inspection ? 'required|in:excellent,good,fair,poor' : 'nullable',
|
|
'inspection_checklist.fluid_levels' => $this->perform_inspection ? 'required|in:excellent,good,fair,poor' : 'nullable',
|
|
'inspection_checklist.lights_working' => $this->perform_inspection ? 'required|in:excellent,good,fair,poor' : 'nullable',
|
|
];
|
|
}
|
|
|
|
public function mount()
|
|
{
|
|
$this->loadData();
|
|
|
|
// Set default values
|
|
$this->arrival_datetime = now()->format('Y-m-d\TH:i');
|
|
$this->expected_completion_date = now()->addDays(2)->format('Y-m-d');
|
|
$this->mileage_in = 0; // Set default mileage
|
|
$this->fuel_level_in = '1/2';
|
|
$this->keys_location = 'Reception Desk';
|
|
$this->branch_code = auth()->user()->branch_code ?? 'MAIN';
|
|
|
|
// Initialize inspection checklist with empty values
|
|
$this->inspection_checklist = [
|
|
'exterior_damage' => '',
|
|
'interior_condition' => '',
|
|
'tire_condition' => '',
|
|
'fluid_levels' => '',
|
|
'lights_working' => '',
|
|
];
|
|
}
|
|
|
|
public function loadData()
|
|
{
|
|
$user = auth()->user();
|
|
|
|
$this->customers = Customer::orderBy('first_name')->get();
|
|
|
|
// Load active branches
|
|
$this->branches = Branch::active()->orderBy('name')->get();
|
|
|
|
// Filter service advisors based on user's permissions and branch
|
|
$this->serviceAdvisors = User::whereIn('role', ['service_advisor', 'service_supervisor'])
|
|
->where('status', 'active')
|
|
->when(!$user->hasPermission('job-cards.view-all'), function ($query) use ($user) {
|
|
return $query->where('branch_code', $user->branch_code);
|
|
})
|
|
->orderBy('name')
|
|
->get();
|
|
|
|
$this->inspectors = User::whereIn('role', ['service_supervisor', 'quality_inspector'])
|
|
->where('status', 'active')
|
|
->when(!$user->hasPermission('job-cards.view-all'), function ($query) use ($user) {
|
|
return $query->where('branch_code', $user->branch_code);
|
|
})
|
|
->orderBy('name')
|
|
->get();
|
|
}
|
|
|
|
public function updatedCustomerId()
|
|
{
|
|
if ($this->customer_id) {
|
|
$this->vehicles = Vehicle::where('customer_id', $this->customer_id)
|
|
->orderBy('year', 'desc')
|
|
->orderBy('make')
|
|
->orderBy('model')
|
|
->get();
|
|
} else {
|
|
$this->vehicles = [];
|
|
$this->vehicle_id = '';
|
|
}
|
|
}
|
|
|
|
public function initializeInspectionChecklist()
|
|
{
|
|
$this->inspection_checklist = [
|
|
'exterior_damage' => false,
|
|
'interior_condition' => false,
|
|
'tire_condition' => false,
|
|
'fluid_levels' => false,
|
|
'lights_working' => false,
|
|
'battery_condition' => false,
|
|
'belts_hoses' => false,
|
|
'air_filter' => false,
|
|
'brake_condition' => false,
|
|
'suspension' => false,
|
|
];
|
|
}
|
|
|
|
protected function cleanFormData()
|
|
{
|
|
// Convert empty strings to null for optional fields
|
|
if ($this->expected_completion_date === '') {
|
|
$this->expected_completion_date = null;
|
|
}
|
|
|
|
if ($this->vehicle_condition_notes === '') {
|
|
$this->vehicle_condition_notes = null;
|
|
}
|
|
|
|
if ($this->notes === '') {
|
|
$this->notes = null;
|
|
}
|
|
|
|
if ($this->inspection_notes === '') {
|
|
$this->inspection_notes = null;
|
|
}
|
|
}
|
|
|
|
public function save()
|
|
{
|
|
try {
|
|
// Check if user still has permission to create job cards
|
|
$this->authorize('create', JobCard::class);
|
|
|
|
// Clean form data (convert empty strings to null)
|
|
$this->cleanFormData();
|
|
|
|
// Add debug log
|
|
\Log::info('JobCard Create: Starting validation', ['user_id' => auth()->id()]);
|
|
|
|
$this->validate();
|
|
|
|
\Log::info('JobCard Create: Validation passed');
|
|
|
|
$workflowService = app(WorkflowService::class);
|
|
|
|
$data = [
|
|
'customer_id' => $this->customer_id,
|
|
'vehicle_id' => $this->vehicle_id,
|
|
'service_advisor_id' => $this->service_advisor_id,
|
|
'branch_code' => $this->branch_code,
|
|
'arrival_datetime' => $this->arrival_datetime,
|
|
'expected_completion_date' => $this->expected_completion_date,
|
|
'mileage_in' => $this->mileage_in,
|
|
'fuel_level_in' => $this->fuel_level_in,
|
|
'customer_reported_issues' => $this->customer_reported_issues,
|
|
'vehicle_condition_notes' => $this->vehicle_condition_notes,
|
|
'keys_location' => $this->keys_location,
|
|
'personal_items_removed' => $this->personal_items_removed,
|
|
'photos_taken' => $this->photos_taken,
|
|
'priority' => $this->priority,
|
|
'notes' => $this->notes,
|
|
];
|
|
|
|
if ($this->perform_inspection) {
|
|
$data['inspector_id'] = $this->inspector_id;
|
|
$data['inspection_checklist'] = $this->inspection_checklist;
|
|
$data['overall_condition'] = $this->overall_condition;
|
|
$data['inspection_notes'] = $this->inspection_notes;
|
|
}
|
|
|
|
\Log::info('JobCard Create: Creating job card with data', $data);
|
|
|
|
$jobCard = $workflowService->createJobCard($data);
|
|
|
|
\Log::info('JobCard Create: Job card created successfully', ['job_card_id' => $jobCard->id]);
|
|
|
|
session()->flash('success', 'Job card created successfully! Job Card #: ' . $jobCard->job_card_number);
|
|
|
|
return redirect()->route('job-cards.show', $jobCard);
|
|
|
|
} catch (\Illuminate\Validation\ValidationException $e) {
|
|
\Log::error('JobCard Create: Validation failed', ['errors' => $e->errors()]);
|
|
session()->flash('error', 'Please check the form for errors and try again.');
|
|
throw $e;
|
|
} catch (\Exception $e) {
|
|
\Log::error('JobCard Create: Exception occurred', [
|
|
'message' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString()
|
|
]);
|
|
session()->flash('error', 'Failed to create job card: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.job-cards.create')
|
|
->layout('components.layouts.app', ['title' => 'Create Job Card']);
|
|
}
|
|
}
|