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

122 خطوط
5.2 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Company;
use App\Services\ActivityLogger;
use App\Services\DuplicateService;
use App\Support\AccessControl;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CompanyController extends Controller
{
public function __construct(private DuplicateService $duplicates) {}
public function index(Request $request): JsonResponse
{
$query = Company::with('owner:id,name')->withCount(['contacts', 'leads', 'deals']);
$this->scope($query);
if ($request->search) {
$search = $request->search;
$query->where(fn($q) => $q->where('name', 'like', "%{$search}%")->orWhere('website', 'like', "%{$search}%")->orWhere('city', 'like', "%{$search}%"));
}
if ($request->status) $query->where('status', $request->status);
if ($request->owner_id) $query->where('owner_id', $request->owner_id);
return response()->json($query->latest()->paginate(min((int) $request->get('per_page', 15), 100)));
}
public function store(Request $request): JsonResponse
{
$validated = $this->validated($request);
$suggestions = $this->duplicates->companySuggestions($validated);
if ($request->boolean('block_duplicates') && $suggestions) {
return response()->json(['message' => 'شرکت مشابهی در سیستم وجود دارد.', 'duplicates' => $suggestions], 422);
}
$company = Company::create($this->prepare($validated) + ['created_by' => auth()->id()]);
ActivityLogger::log('company_created', "Company {$company->name} created", $company);
$payload = $company->load('owner:id,name')->toArray();
if ($suggestions) $payload['duplicate_suggestions'] = $suggestions;
return response()->json($payload, 201);
}
public function show(Company $company): JsonResponse
{
$this->authorizeAccess($company);
return response()->json($company->load([
'owner:id,name', 'contacts.phones', 'leads.pipelineStage', 'deals.product', 'notes.user:id,name', 'attachments.uploader:id,name',
]));
}
public function update(Request $request, Company $company): JsonResponse
{
$this->authorizeAccess($company);
$validated = $this->validated($request, true);
$company->update($this->prepare($validated));
ActivityLogger::log('company_updated', "Company {$company->name} updated", $company);
return response()->json($company->fresh('owner:id,name'));
}
public function destroy(Company $company): JsonResponse
{
$this->authorizeAccess($company, true);
$company->delete();
ActivityLogger::log('company_deleted', "Company {$company->id} deleted");
return response()->json(['message' => 'شرکت حذف شد']);
}
public function merge(Request $request, Company $company): JsonResponse
{
abort_unless(auth()->user()?->hasRole('admin') || auth()->user()?->can('merge_duplicates'), 403, 'شما مجوز ادغام رکوردهای تکراری را ندارید.');
$validated = $request->validate(['target_id' => 'required|exists:companies,id|different:' . $company->id]);
$target = Company::findOrFail($validated['target_id']);
return response()->json($this->duplicates->mergeCompanies($company, $target, auth()->id()));
}
private function validated(Request $request, bool $partial = false): array
{
$sometimes = $partial ? 'sometimes|' : '';
return $request->validate([
'name' => $sometimes . 'required|string|max:255',
'company_type' => 'nullable|string|max:80',
'industry' => 'nullable|string|max:120',
'city' => 'nullable|string|max:120',
'address' => 'nullable|string',
'website' => 'nullable|string|max:255',
'description' => 'nullable|string',
'status' => 'nullable|string|max:40',
'owner_id' => 'nullable|exists:users,id',
]);
}
private function prepare(array $data): array
{
if (array_key_exists('name', $data)) $data['normalized_name'] = DuplicateService::normalizeName($data['name']);
if (array_key_exists('website', $data)) $data['normalized_website'] = DuplicateService::normalizeWebsite($data['website']);
return $data;
}
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->where(function ($q) use ($user) {
$q->where('owner_id', $user->id)->orWhereIn('owner_id', AccessControl::teamMemberIds($user));
});
}
}
private function authorizeAccess(Company $company, bool $manage = false): void
{
$user = auth()->user();
abort_unless($user && ($user->hasRole('admin') || (!$manage && $company->owner_id === $user->id) || (!$manage && $user->hasRole('supervisor') && in_array($company->owner_id, AccessControl::teamMemberIds($user), true))), 403, 'دسترسی غیرمجاز');
}
}