CRM/backend/app/Http/Controllers/Api/AssignmentController.php

148 خطوط
5.2 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Lead;
use App\Models\User;
use App\Services\ActivityLogger;
use App\Services\AssignmentService;
use App\Support\AccessControl;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class AssignmentController extends Controller
{
public function __construct(private AssignmentService $assignmentService) {}
public function assign(Request $request): JsonResponse
{
$validated = $request->validate([
'lead_id' => 'required|exists:leads,id',
'agent_id' => 'required|exists:users,id',
]);
$lead = Lead::findOrFail($validated['lead_id']);
$agent = User::findOrFail($validated['agent_id']);
if (!$this->canAssignToAgent($lead, $agent)) {
return response()->json(['message' => 'دسترسی غیرمجاز'], 403);
}
$lead = $this->assignmentService->assignToAgent(
$validated['lead_id'],
$validated['agent_id'],
auth()->id()
);
ActivityLogger::log('lead_owner_changed', "Lead {$lead->id} assigned to user {$agent->id}", $lead);
return response()->json($lead->load('assignedAgent'));
}
public function bulkAssign(Request $request): JsonResponse
{
$validated = $request->validate([
'lead_ids' => 'required|array|min:1',
'lead_ids.*' => 'exists:leads,id',
'agent_id' => 'required|exists:users,id',
]);
$agent = User::findOrFail($validated['agent_id']);
$leads = Lead::whereIn('id', $validated['lead_ids'])->get();
if ($leads->count() !== count(array_unique($validated['lead_ids'])) || $leads->contains(fn(Lead $lead) => !$this->canAssignToAgent($lead, $agent))) {
return response()->json(['message' => 'دسترسی غیرمجاز'], 403);
}
$leads = $this->assignmentService->bulkAssign(
$validated['lead_ids'],
$validated['agent_id'],
auth()->id()
);
ActivityLogger::log('lead_bulk_owner_changed', count($leads) . " leads assigned to user {$agent->id}");
return response()->json(['assigned' => count($leads)]);
}
public function roundRobin(Request $request): JsonResponse
{
$validated = $request->validate([
'lead_ids' => 'required|array|min:1',
'lead_ids.*' => 'exists:leads,id',
'agent_ids' => 'required|array|min:1',
'agent_ids.*' => 'exists:users,id',
]);
$agents = User::whereIn('id', $validated['agent_ids'])->get()->keyBy('id');
$leads = Lead::whereIn('id', $validated['lead_ids'])->get();
if (
$agents->count() !== count(array_unique($validated['agent_ids']))
|| $leads->count() !== count(array_unique($validated['lead_ids']))
|| $leads->contains(fn(Lead $lead) => Gate::denies('assign', $lead))
|| $agents->contains(fn(User $agent) => !$this->agentIsAssignable($agent))
) {
return response()->json(['message' => 'دسترسی غیرمجاز'], 403);
}
$leads = $this->assignmentService->roundRobin(
$validated['lead_ids'],
$validated['agent_ids'],
auth()->id()
);
ActivityLogger::log('lead_round_robin_owner_changed', count($leads) . ' leads assigned by round robin');
return response()->json(['assigned' => count($leads)]);
}
public function reassign(Request $request): JsonResponse
{
$validated = $request->validate([
'lead_id' => 'required|exists:leads,id',
'agent_id' => 'required|exists:users,id',
]);
$lead = Lead::findOrFail($validated['lead_id']);
$agent = User::findOrFail($validated['agent_id']);
if (!$this->canAssignToAgent($lead, $agent)) {
return response()->json(['message' => 'دسترسی غیرمجاز'], 403);
}
$lead = $this->assignmentService->assignToAgent(
$validated['lead_id'],
$validated['agent_id'],
auth()->id()
);
ActivityLogger::log('lead_owner_changed', "Lead {$lead->id} reassigned to user {$agent->id}", $lead);
return response()->json($lead->load('assignedAgent'));
}
public function returnToPool(int $leadId): JsonResponse
{
$leadModel = Lead::findOrFail($leadId);
Gate::authorize('assign', $leadModel);
$lead = $this->assignmentService->returnToPool($leadId);
return response()->json($lead);
}
private function canAssignToAgent(Lead $lead, User $agent): bool
{
return Gate::allows('assign', $lead) && $this->agentIsAssignable($agent);
}
private function agentIsAssignable(User $agent): bool
{
$user = auth()->user();
if (!$agent->hasRole('agent') || !$agent->is_active) {
return false;
}
if ($user?->hasRole('admin')) {
return true;
}
if ($user?->hasRole('supervisor')) {
return (bool) array_intersect(AccessControl::teamIds($user), $agent->teams()->pluck('teams.id')->all());
}
return false;
}
}