122 خطوط
5.2 KiB
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, 'دسترسی غیرمجاز');
|
|
}
|
|
}
|