141 lines
6.1 KiB
PHP
141 lines
6.1 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Inertia\Inertia;
|
|
|
|
class WorkerVerificationController extends Controller
|
|
{
|
|
/**
|
|
* Display a listing of worker identity verifications.
|
|
*/
|
|
public function index(Request $request)
|
|
{
|
|
$status = $request->input('status', 'all');
|
|
|
|
$query = \App\Models\Worker::with('documents');
|
|
|
|
if ($status === 'approved') {
|
|
$query->where('verified', true);
|
|
} elseif ($status === 'pending') {
|
|
$query->where('verified', false);
|
|
}
|
|
|
|
$paginator = $query->paginate(20);
|
|
|
|
$paginator->getCollection()->transform(function($worker) {
|
|
$passportDoc = $worker->documents->where('type', 'passport')->first();
|
|
$visaDoc = $worker->documents->where('type', 'visa')->first();
|
|
$doc = $passportDoc ?: ($visaDoc ?: $worker->documents->first());
|
|
|
|
return [
|
|
'id' => $worker->id,
|
|
'worker_name' => $worker->name,
|
|
'nationality' => $worker->nationality,
|
|
'passport_number' => $passportDoc ? $passportDoc->number : ($doc ? $doc->number : 'N/A'),
|
|
'processed_at' => $worker->updated_at ? $worker->updated_at->format('Y-m-d H:i') : 'N/A',
|
|
'status' => $worker->verified ? 'approved' : 'flagged',
|
|
'confidence' => $doc && $doc->ocr_accuracy ? intval($doc->ocr_accuracy) : 95,
|
|
'verification_method' => $doc && $doc->ocr_accuracy ? 'Auto-OCR' : 'Manual',
|
|
'document_type' => $doc ? ucfirst($doc->type) : 'Passport',
|
|
'warnings' => $worker->verified ? [] : ($doc ? [] : ['No documents uploaded']),
|
|
'document_images' => $worker->documents->map(function($d) {
|
|
return $d->file_path ?: 'https://images.unsplash.com/photo-1544717305-2782549b5136?q=80&w=600&auto=format&fit=crop';
|
|
})->toArray(),
|
|
'ocr_data' => [
|
|
'Name' => $worker->name,
|
|
'DOB' => $worker->age ? date('Y-m-d', strtotime('-' . $worker->age . ' years')) : 'N/A',
|
|
'Nationality' => $worker->nationality,
|
|
'Passport No.' => $passportDoc ? $passportDoc->number : 'N/A',
|
|
'Expiry' => $passportDoc && $passportDoc->expiry_date ? (is_string($passportDoc->expiry_date) ? date('Y-m-d', strtotime($passportDoc->expiry_date)) : $passportDoc->expiry_date->format('Y-m-d')) : 'N/A',
|
|
]
|
|
];
|
|
});
|
|
|
|
$history = \Illuminate\Support\Facades\DB::table('audit_logs')
|
|
->where('category', 'verification')
|
|
->orWhere('action', 'like', '%verification%')
|
|
->orWhere('action', 'like', '%verify%')
|
|
->orderBy('created_at', 'desc')
|
|
->take(5)
|
|
->get()
|
|
->map(function ($log) {
|
|
return [
|
|
'time' => date('Y-m-d H:i', strtotime($log->created_at)),
|
|
'text' => $log->action,
|
|
'ip' => $log->ip_address ?: 'Auto-System',
|
|
];
|
|
})->toArray();
|
|
|
|
return Inertia::render('Admin/Workers/Verifications', [
|
|
'verifications' => $paginator,
|
|
'status' => $status,
|
|
'summary' => [
|
|
'auto_approve_rate' => \App\Models\Worker::count() > 0 ? round((\App\Models\Worker::where('verified', true)->count() / \App\Models\Worker::count()) * 100, 1) : 0.0,
|
|
'average_match_score' => round(\App\Models\WorkerDocument::avg('ocr_accuracy') ?: 95.0, 1),
|
|
'flagged_count' => \App\Models\Worker::where('verified', false)->count(),
|
|
],
|
|
'history' => $history,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Process verification approval or rejection.
|
|
*/
|
|
public function verify(Request $request, $worker)
|
|
{
|
|
$validated = $request->validate([
|
|
'action' => 'required|in:approve,reject',
|
|
'rejection_reason' => 'required_if:action,reject|nullable|string',
|
|
'ocr_overrides' => 'nullable|array',
|
|
]);
|
|
|
|
$workerModel = \App\Models\Worker::findOrFail($worker);
|
|
|
|
if ($validated['action'] === 'approve') {
|
|
$workerModel->verified = true;
|
|
|
|
if (!empty($validated['ocr_overrides'])) {
|
|
$overrides = $validated['ocr_overrides'];
|
|
if (isset($overrides['Name'])) {
|
|
$workerModel->name = $overrides['Name'];
|
|
}
|
|
if (isset($overrides['Nationality'])) {
|
|
$workerModel->nationality = $overrides['Nationality'];
|
|
}
|
|
if (isset($overrides['Passport No.'])) {
|
|
$passportDoc = $workerModel->documents()->where('type', 'passport')->first();
|
|
if ($passportDoc) {
|
|
$passportDoc->number = $overrides['Passport No.'];
|
|
if (isset($overrides['Expiry'])) {
|
|
$passportDoc->expiry_date = $overrides['Expiry'];
|
|
}
|
|
$passportDoc->save();
|
|
}
|
|
}
|
|
}
|
|
$workerModel->save();
|
|
$statusMsg = 'approved';
|
|
} else {
|
|
$workerModel->verified = false;
|
|
$workerModel->save();
|
|
$statusMsg = 'rejected';
|
|
}
|
|
|
|
// Insert into audit logs
|
|
\Illuminate\Support\Facades\DB::table('audit_logs')->insert([
|
|
'category' => 'verification',
|
|
'user' => auth()->user() ? auth()->user()->email : 'Admin',
|
|
'action' => "Admin manually " . ($validated['action'] === 'approve' ? 'approved' : 'rejected') . " verification for worker #{$workerModel->id} ({$workerModel->name})",
|
|
'ip_address' => $request->ip(),
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
return back()->with('success', "Worker verification #{$worker} has been {$statusMsg} successfully.");
|
|
}
|
|
}
|