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

88 خطوط
3.8 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Deal;
use App\Services\ActivityLogger;
use App\Support\AccessControl;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DealController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = Deal::with('company:id,name', 'lead:id,company,first_name,last_name', 'contact:id,name', 'product:id,name', 'owner:id,name');
$this->scope($query);
foreach (['status', 'sales_stage', 'company_id', 'lead_id', 'owner_id', 'product_id'] as $filter) {
if ($request->filled($filter)) $query->where($filter, $request->get($filter));
}
if ($request->search) $query->where('title', 'like', "%{$request->search}%");
return response()->json($query->latest()->paginate(min((int) $request->get('per_page', 15), 100)));
}
public function store(Request $request): JsonResponse
{
$deal = Deal::create($this->validated($request) + ['created_by' => auth()->id()]);
ActivityLogger::log('deal_created', "Deal {$deal->title} created", $deal);
return response()->json($deal->load('company', 'contact', 'product', 'owner'), 201);
}
public function show(Deal $deal): JsonResponse
{
$this->authorizeAccess($deal);
return response()->json($deal->load('company', 'lead', 'contact.phones', 'product.salesScript.sections', 'owner:id,name', 'timelineNotes.user:id,name', 'attachments.uploader:id,name'));
}
public function update(Request $request, Deal $deal): JsonResponse
{
$this->authorizeAccess($deal);
$deal->update($this->validated($request, true));
ActivityLogger::log('deal_updated', "Deal {$deal->title} updated", $deal);
return response()->json($deal->fresh('company', 'contact', 'product', 'owner'));
}
public function destroy(Deal $deal): JsonResponse
{
$this->authorizeAccess($deal, true);
$deal->delete();
ActivityLogger::log('deal_deleted', "Deal {$deal->id} deleted");
return response()->json(['message' => 'فرصت فروش حذف شد']);
}
private function validated(Request $request, bool $partial = false): array
{
$sometimes = $partial ? 'sometimes|' : '';
return $request->validate([
'title' => $sometimes . 'required|string|max:255',
'company_id' => 'nullable|exists:companies,id',
'lead_id' => 'nullable|exists:leads,id',
'contact_id' => 'nullable|exists:contacts,id',
'product_id' => 'nullable|exists:products,id',
'estimated_value' => 'nullable|numeric|min:0',
'win_probability' => 'nullable|integer|min:0|max:100',
'sales_stage' => 'nullable|string|max:80',
'expected_close_date' => 'nullable|date',
'owner_id' => 'nullable|exists:users,id',
'status' => 'nullable|string|max:40',
'won_lost_reason' => 'nullable|string|max:255',
'notes' => 'nullable|string',
]);
}
private function scope($query): void
{
$user = auth()->user();
if ($user?->hasRole('admin')) return;
if ($user?->hasRole('agent')) $query->where('owner_id', $user->id);
if ($user?->hasRole('supervisor')) $query->whereIn('owner_id', array_merge([$user->id], AccessControl::teamMemberIds($user)));
}
private function authorizeAccess(Deal $deal, bool $manage = false): void
{
$user = auth()->user();
abort_unless($user && ($user->hasRole('admin') || (!$manage && $deal->owner_id === $user->id) || (!$manage && $user->hasRole('supervisor') && in_array($deal->owner_id, AccessControl::teamMemberIds($user), true))), 403, 'دسترسی غیرمجاز');
}
}