hire flow issue
This commit is contained in:
parent
1b4699db4c
commit
2483e2c933
@ -362,7 +362,10 @@ public function updateStatus(Request $request, $id)
|
|||||||
return redirect()->route('employer.login');
|
return redirect()->route('employer.login');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->checkJobAccess($user)) {
|
$statusLower = strtolower($request->status);
|
||||||
|
$isDirectHiringAction = in_array($statusLower, ['hired', 'hire_requested']);
|
||||||
|
|
||||||
|
if (!$isDirectHiringAction && !$this->checkJobAccess($user)) {
|
||||||
return redirect()->route('employer.subscription')
|
return redirect()->route('employer.subscription')
|
||||||
->with('error', 'Your current plan does not support the Job Apply module. Please upgrade to a Premium plan to access this feature.');
|
->with('error', 'Your current plan does not support the Job Apply module. Please upgrade to a Premium plan to access this feature.');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,10 +32,6 @@ public function run(): void
|
|||||||
SkillSeeder::class,
|
SkillSeeder::class,
|
||||||
AdminSeeder::class,
|
AdminSeeder::class,
|
||||||
NationalitySeeder::class,
|
NationalitySeeder::class,
|
||||||
WorkerSeeder::class,
|
|
||||||
EmployerProfileSeeder::class,
|
|
||||||
JobPostSeeder::class,
|
|
||||||
ConversationSeeder::class,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,39 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Database\Seeders;
|
|
||||||
|
|
||||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
|
||||||
use Illuminate\Database\Seeder;
|
|
||||||
|
|
||||||
class EmployerProfileSeeder extends Seeder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the database seeds.
|
|
||||||
*/
|
|
||||||
public function run(): void
|
|
||||||
{
|
|
||||||
// Create Employer User
|
|
||||||
$userId = \Illuminate\Support\Facades\DB::table('users')->insertGetId([
|
|
||||||
'name' => 'Employer One',
|
|
||||||
'email' => 'employer1@example.com',
|
|
||||||
'password' => \Illuminate\Support\Facades\Hash::make('password'),
|
|
||||||
'role' => 'employer',
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Create Employer Profile
|
|
||||||
\Illuminate\Support\Facades\DB::table('employer_profiles')->insert([
|
|
||||||
'user_id' => $userId,
|
|
||||||
'company_name' => 'Al Mansoor Household',
|
|
||||||
'phone' => '+971 50 123 4567',
|
|
||||||
'verification_status' => 'approved',
|
|
||||||
'emirates_id_front' => '[DELETED_FOR_PDPL_COMPLIANCE]',
|
|
||||||
'emirates_id_back' => '[DELETED_FOR_PDPL_COMPLIANCE]',
|
|
||||||
'emirates_id_number' => '784-1990-1234567-8',
|
|
||||||
'emirates_id_expiry' => '2028-12-31',
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,253 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Database\Seeders;
|
|
||||||
|
|
||||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
|
||||||
use Illuminate\Database\Seeder;
|
|
||||||
|
|
||||||
class WorkerSeeder extends Seeder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the database seeds.
|
|
||||||
*/
|
|
||||||
public function run(): void
|
|
||||||
{
|
|
||||||
$workers = [
|
|
||||||
[
|
|
||||||
'name' => 'John Doe',
|
|
||||||
'email' => 'john.doe@example.com',
|
|
||||||
'phone' => '+971 50 111 2222',
|
|
||||||
'nationality' => 'Indian',
|
|
||||||
'country' => 'United Arab Emirates',
|
|
||||||
'city' => 'Dubai',
|
|
||||||
'area' => 'Dubai Marina',
|
|
||||||
'preferred_location' => 'Dubai Marina',
|
|
||||||
'live_in_out' => 'Live-in (Stay with family)',
|
|
||||||
'language' => 'English',
|
|
||||||
'age' => 30,
|
|
||||||
'gender' => 'Male',
|
|
||||||
'salary' => 2500.00,
|
|
||||||
'availability' => 'Immediate',
|
|
||||||
'experience' => '5+ Years',
|
|
||||||
'religion' => 'Christian',
|
|
||||||
'bio' => '',
|
|
||||||
'verified' => true,
|
|
||||||
'status' => 'active',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Ali Hassan',
|
|
||||||
'email' => 'ali.hassan@example.com',
|
|
||||||
'phone' => '+971 50 333 4444',
|
|
||||||
'nationality' => 'Pakistani',
|
|
||||||
'country' => 'United Arab Emirates',
|
|
||||||
'city' => 'Dubai',
|
|
||||||
'area' => 'Al Barsha',
|
|
||||||
'preferred_location' => 'Al Barsha',
|
|
||||||
'live_in_out' => 'Live-out (External housing)',
|
|
||||||
'language' => 'English',
|
|
||||||
'age' => 28,
|
|
||||||
'gender' => 'Male',
|
|
||||||
'salary' => 2000.00,
|
|
||||||
'availability' => '1 Month Notice',
|
|
||||||
'experience' => '3 Years',
|
|
||||||
'religion' => 'Muslim',
|
|
||||||
'bio' => 'Skilled mason with experience in block work and plastering.',
|
|
||||||
'verified' => true,
|
|
||||||
'status' => 'active',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Maria Santos',
|
|
||||||
'email' => 'maria.santos@example.com',
|
|
||||||
'phone' => '+971 50 555 6666',
|
|
||||||
'nationality' => 'Filipino',
|
|
||||||
'country' => 'United Arab Emirates',
|
|
||||||
'city' => 'Yas Island',
|
|
||||||
'area' => 'Yas Island',
|
|
||||||
'preferred_location' => 'Yas Island',
|
|
||||||
'live_in_out' => 'Live-in (Stay with family)',
|
|
||||||
'language' => 'Tagalog',
|
|
||||||
'age' => 32,
|
|
||||||
'gender' => 'Female',
|
|
||||||
'salary' => 1800.00,
|
|
||||||
'availability' => 'Immediate',
|
|
||||||
'experience' => '5+ Years',
|
|
||||||
'religion' => 'Christian',
|
|
||||||
'bio' => 'Experienced nanny with 6 years working with expatriate families in Dubai. Certified in pediatric first aid.',
|
|
||||||
'verified' => true,
|
|
||||||
'status' => 'active',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Lakshmi Sharma',
|
|
||||||
'email' => 'lakshmi.sharma@example.com',
|
|
||||||
'phone' => '+971 50 777 8888',
|
|
||||||
'nationality' => 'Indian',
|
|
||||||
'country' => 'United Arab Emirates',
|
|
||||||
'city' => 'Abu Dhabi',
|
|
||||||
'area' => 'Khalifa City',
|
|
||||||
'preferred_location' => 'Khalifa City',
|
|
||||||
'live_in_out' => 'Live-out (External housing)',
|
|
||||||
'language' => 'Hindi',
|
|
||||||
'age' => 38,
|
|
||||||
'gender' => 'Female',
|
|
||||||
'salary' => 1600.00,
|
|
||||||
'availability' => '2 Weeks',
|
|
||||||
'experience' => '3-5 Years',
|
|
||||||
'religion' => 'Hindu',
|
|
||||||
'bio' => 'Patient caregiver specializing in elderly assistance, mobility support, and vegetarian cooking.',
|
|
||||||
'verified' => true,
|
|
||||||
'status' => 'active',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Siti Aminah',
|
|
||||||
'email' => 'siti.aminah@example.com',
|
|
||||||
'phone' => '+971 50 999 0000',
|
|
||||||
'nationality' => 'Indonesian',
|
|
||||||
'country' => 'United Arab Emirates',
|
|
||||||
'city' => 'Sharjah',
|
|
||||||
'area' => 'Al Nahda',
|
|
||||||
'preferred_location' => 'Al Nahda',
|
|
||||||
'live_in_out' => 'Live-in (Stay with family)',
|
|
||||||
'language' => 'Arabic',
|
|
||||||
'age' => 29,
|
|
||||||
'gender' => 'Female',
|
|
||||||
'salary' => 1400.00,
|
|
||||||
'availability' => 'Immediate',
|
|
||||||
'experience' => '3-5 Years',
|
|
||||||
'religion' => 'Muslim',
|
|
||||||
'bio' => 'Hardworking and meticulous housekeeper with excellent references from Abu Dhabi households.',
|
|
||||||
'verified' => true,
|
|
||||||
'status' => 'active',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Grace Osei',
|
|
||||||
'email' => 'grace.osei@example.com',
|
|
||||||
'phone' => '+971 50 222 3333',
|
|
||||||
'nationality' => 'Ghanaian',
|
|
||||||
'country' => 'Saudi Arabia',
|
|
||||||
'city' => 'Riyadh',
|
|
||||||
'area' => 'Al Olaya',
|
|
||||||
'preferred_location' => 'Al Olaya',
|
|
||||||
'live_in_out' => 'Live-out (External housing)',
|
|
||||||
'language' => 'English',
|
|
||||||
'age' => 26,
|
|
||||||
'gender' => 'Female',
|
|
||||||
'salary' => 1500.00,
|
|
||||||
'availability' => '1 Month',
|
|
||||||
'experience' => '1-2 Years',
|
|
||||||
'religion' => 'Christian',
|
|
||||||
'bio' => 'Energetic and educated nanny. Fluent in English, great with toddlers and assisting with homework.',
|
|
||||||
'verified' => false,
|
|
||||||
'status' => 'active',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Anoma Perera',
|
|
||||||
'email' => 'anoma.perera@example.com',
|
|
||||||
'phone' => '+971 50 444 5555',
|
|
||||||
'nationality' => 'Sri Lankan',
|
|
||||||
'country' => 'Saudi Arabia',
|
|
||||||
'city' => 'Jeddah',
|
|
||||||
'area' => 'Al Hamra',
|
|
||||||
'preferred_location' => 'Al Hamra',
|
|
||||||
'live_in_out' => 'Live-in (Stay with family)',
|
|
||||||
'language' => 'English',
|
|
||||||
'age' => 41,
|
|
||||||
'gender' => 'Female',
|
|
||||||
'salary' => 2200.00,
|
|
||||||
'availability' => 'Immediate',
|
|
||||||
'experience' => '5+ Years',
|
|
||||||
'religion' => 'Buddhist',
|
|
||||||
'bio' => 'Professional domestic cook skilled in Arabic, Continental, and Asian cuisine. Highly organized.',
|
|
||||||
'verified' => true,
|
|
||||||
'status' => 'active',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Ramesh Thapa',
|
|
||||||
'email' => 'ramesh.thapa@example.com',
|
|
||||||
'phone' => '+971 50 666 7777',
|
|
||||||
'nationality' => 'Nepalese',
|
|
||||||
'country' => 'Saudi Arabia',
|
|
||||||
'city' => 'Riyadh',
|
|
||||||
'area' => 'Al Yasmin',
|
|
||||||
'preferred_location' => 'Al Yasmin',
|
|
||||||
'live_in_out' => 'Live-out (External housing)',
|
|
||||||
'language' => 'English',
|
|
||||||
'age' => 36,
|
|
||||||
'gender' => 'Male',
|
|
||||||
'salary' => 2500.00,
|
|
||||||
'availability' => '2 Weeks',
|
|
||||||
'experience' => '5+ Years',
|
|
||||||
'religion' => 'Hindu',
|
|
||||||
'bio' => 'Valid UAE driving license with clean record. Familiar with all Dubai and Sharjah school routes.',
|
|
||||||
'verified' => true,
|
|
||||||
'status' => 'active',
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
// Dynamic Skill Resolution
|
|
||||||
$skillIds = \Illuminate\Support\Facades\DB::table('skills')->pluck('id')->toArray();
|
|
||||||
if (empty($skillIds)) {
|
|
||||||
foreach (['cooking', 'driving', 'childcare', 'cleaning', 'elderly care', 'gardening'] as $skillName) {
|
|
||||||
$skillIds[] = \Illuminate\Support\Facades\DB::table('skills')->insertGetId([
|
|
||||||
'name' => $skillName,
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$sId1 = $skillIds[0] ?? 1;
|
|
||||||
$sId2 = $skillIds[1] ?? 2;
|
|
||||||
|
|
||||||
foreach ($workers as $workerData) {
|
|
||||||
// Exclude email duplicates to avoid unique constraint violations
|
|
||||||
if (\Illuminate\Support\Facades\DB::table('workers')->where('email', $workerData['email'])->exists()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$workerId = \Illuminate\Support\Facades\DB::table('workers')->insertGetId(array_merge($workerData, [
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
]));
|
|
||||||
|
|
||||||
// Seed Documents
|
|
||||||
\Illuminate\Support\Facades\DB::table('worker_documents')->insert([
|
|
||||||
[
|
|
||||||
'worker_id' => $workerId,
|
|
||||||
'type' => 'passport',
|
|
||||||
'number' => 'P' . rand(100000, 999999),
|
|
||||||
'issue_date' => '2020-01-01',
|
|
||||||
'expiry_date' => '2030-01-01',
|
|
||||||
'ocr_accuracy' => 95.5,
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'worker_id' => $workerId,
|
|
||||||
'type' => 'visa',
|
|
||||||
'number' => 'V' . rand(100000, 999999),
|
|
||||||
'issue_date' => '2022-01-01',
|
|
||||||
'expiry_date' => '2025-01-01',
|
|
||||||
'ocr_accuracy' => 98.0,
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Seed Skills using resolved IDs
|
|
||||||
\Illuminate\Support\Facades\DB::table('worker_skills')->insert([
|
|
||||||
[
|
|
||||||
'worker_id' => $workerId,
|
|
||||||
'skill_id' => $sId1,
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'worker_id' => $workerId,
|
|
||||||
'skill_id' => $sId2,
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -336,6 +336,18 @@ export default function Show({ worker }) {
|
|||||||
<span>{t('start_direct_chat', 'Start Direct Chat')}</span>
|
<span>{t('start_direct_chat', 'Start Direct Chat')}</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
{/* Stage 4 Hire: Hire Worker Button */}
|
||||||
|
{availabilityStatus !== 'Pending Confirmation' && availabilityStatus !== 'Hired' && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleMarkHired}
|
||||||
|
className="bg-emerald-600 hover:bg-emerald-700 border border-emerald-700 text-white px-6 py-3 rounded-xl font-bold text-sm shadow-xs transition-all flex items-center justify-center space-x-2 flex-1 sm:flex-initial cursor-pointer"
|
||||||
|
>
|
||||||
|
<UserCheck className="w-4 h-4 text-white" />
|
||||||
|
<span>{t('hire_worker', 'Hire Worker')}</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Stage 4 Hire: Pending Confirmation Indicator */}
|
{/* Stage 4 Hire: Pending Confirmation Indicator */}
|
||||||
{availabilityStatus === 'Pending Confirmation' && (
|
{availabilityStatus === 'Pending Confirmation' && (
|
||||||
<div className="bg-amber-50 text-amber-700 border border-amber-200 px-6 py-3 rounded-xl font-bold text-sm flex items-center justify-center space-x-2">
|
<div className="bg-amber-50 text-amber-700 border border-amber-200 px-6 py-3 rounded-xl font-bold text-sm flex items-center justify-center space-x-2">
|
||||||
|
|||||||
@ -1077,6 +1077,62 @@ public function test_direct_hiring_sends_correct_notifications_to_worker()
|
|||||||
unlink($credentialsPath);
|
unlink($credentialsPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_basic_plan_employer_can_directly_hire_without_subscription_redirect()
|
||||||
|
{
|
||||||
|
// 1. Change employer subscription to 'basic'
|
||||||
|
$this->employer->subscription()->delete();
|
||||||
|
Subscription::create([
|
||||||
|
'user_id' => $this->employer->id,
|
||||||
|
'plan_id' => 'basic',
|
||||||
|
'amount_aed' => 0.00,
|
||||||
|
'starts_at' => now(),
|
||||||
|
'expires_at' => now()->addDays(30),
|
||||||
|
'status' => 'active',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Create a job post (representing a placeholder or existing one)
|
||||||
|
$job = JobPost::create([
|
||||||
|
'employer_id' => $this->employer->id,
|
||||||
|
'title' => 'General Helper Placeholder',
|
||||||
|
'location' => 'Dubai',
|
||||||
|
'salary' => 2000,
|
||||||
|
'job_type' => 'Full Time',
|
||||||
|
'start_date' => now()->addDays(5)->format('Y-m-d'),
|
||||||
|
'description' => 'Placeholder',
|
||||||
|
'status' => 'active',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Create a job application
|
||||||
|
$application = JobApplication::create([
|
||||||
|
'worker_id' => $this->worker->id,
|
||||||
|
'job_id' => $job->id,
|
||||||
|
'status' => 'applied'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 2. Try to update status to 'Shortlisted' - should redirect to subscription
|
||||||
|
$responseShortlist = $this->actingAs($this->employer)
|
||||||
|
->withSession(['user' => $this->employer])
|
||||||
|
->post("/employer/candidates/{$application->id}/status", [
|
||||||
|
'status' => 'Shortlisted',
|
||||||
|
'notes' => 'Try to shortlist'
|
||||||
|
]);
|
||||||
|
$responseShortlist->assertRedirect(route('employer.subscription'));
|
||||||
|
|
||||||
|
// 3. Try to update status to 'Hired' - should bypass redirect and succeed
|
||||||
|
$responseHire = $this->actingAs($this->employer)
|
||||||
|
->withSession(['user' => $this->employer])
|
||||||
|
->post("/employer/candidates/{$application->id}/status", [
|
||||||
|
'status' => 'Hired',
|
||||||
|
'notes' => 'Direct hiring worker'
|
||||||
|
]);
|
||||||
|
$responseHire->assertSessionHasNoErrors();
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('job_applications', [
|
||||||
|
'id' => $application->id,
|
||||||
|
'status' => 'hire_requested',
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user