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

89 خطوط
3.5 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Lead;
use App\Models\SlaBreach;
use App\Models\SlaRule;
use App\Services\ActivityLogger;
use App\Services\LeadScoringService;
use App\Services\SlaMonitorService;
use App\Support\AccessControl;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class IntelligenceController extends Controller
{
public function __construct(private LeadScoringService $scoring, private SlaMonitorService $slaMonitor) {}
public function scoreLead(Request $request, Lead $lead): JsonResponse
{
abort_unless($request->user()->can('score_leads') && AccessControl::canAccessLead($request->user(), $lead), 403);
return response()->json($this->scoring->score($lead));
}
public function bulkScore(Request $request): JsonResponse
{
abort_unless($request->user()->can('score_leads'), 403);
$ids = $request->validate(['ids' => 'required|array|min:1|max:100', 'ids.*' => 'integer|exists:leads,id'])['ids'];
$query = Lead::whereKey($ids);
AccessControl::scopeLeads($query, $request->user());
$scored = $query->get()->map(fn (Lead $lead) => $this->scoring->score($lead));
return response()->json(['count' => $scored->count(), 'data' => $scored]);
}
public function slaRules(Request $request): JsonResponse
{
abort_unless($request->user()->can('view_sla'), 403);
return response()->json(SlaRule::where('event', '!=', 'stale_deal')->latest()->get());
}
public function storeSlaRule(Request $request): JsonResponse
{
abort_unless($request->user()->can('manage_sla'), 403);
$data = $request->validate([
'name' => 'required|string|max:120', 'event' => 'required|in:first_contact,follow_up',
'warning_minutes' => 'required|integer|min:1|max:525600', 'breach_minutes' => 'required|integer|gt:warning_minutes|max:525600',
'scope' => 'nullable|array|max:10', 'is_active' => 'boolean',
]);
return response()->json(SlaRule::create($data + ['created_by' => $request->user()->id]), 201);
}
public function breaches(Request $request): JsonResponse
{
abort_unless($request->user()->can('view_sla'), 403);
$query = SlaBreach::with('rule:id,name,event', 'assignee:id,name', 'breachable');
if ($request->user()->hasRole('agent')) {
$query->where('assigned_to', $request->user()->id);
} elseif ($request->user()->hasRole('supervisor')) {
$query->whereIn('assigned_to', AccessControl::teamMemberIds($request->user()));
}
if ($request->filled('status')) {
$query->where('status', $request->string('status'));
}
return response()->json($query->latest()->paginate(min((int) $request->get('per_page', 20), 100)));
}
public function detect(Request $request): JsonResponse
{
abort_unless($request->user()->can('manage_sla'), 403);
return response()->json(['created' => $this->slaMonitor->run()]);
}
public function resolve(Request $request, SlaBreach $slaBreach): JsonResponse
{
abort_unless($request->user()->can('manage_sla') || $slaBreach->assigned_to === $request->user()->id, 403);
$slaBreach->update(['status' => 'resolved', 'resolved_at' => now()]);
ActivityLogger::log('sla_breach_resolved', "SLA breach {$slaBreach->id} resolved", $slaBreach);
return response()->json($slaBreach->fresh(['rule', 'assignee:id,name']));
}
}