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

165 خطوط
6.4 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\ImportBatch;
use App\Models\Setting;
use App\Services\ActivityLogger;
use App\Services\ImportService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
class ImportController extends Controller
{
public function __construct(private ImportService $importService) {}
public function upload(Request $request): JsonResponse
{
Gate::authorize('import', ImportBatch::class);
$allowedTypes = Setting::where('key', 'import_allowed_file_types')->value('value') ?: 'xlsx,xls,csv';
$maxMb = max(1, (int) (Setting::where('key', 'import_max_file_size_mb')->value('value') ?: 10));
$request->validate([
'file' => 'required|file|mimes:'.$allowedTypes.'|max:'.($maxMb * 1024),
], [
'file.mimes' => 'نوع فایل import مجاز نیست.',
'file.max' => "حجم فایل import نباید بیشتر از {$maxMb} مگابایت باشد.",
]);
$file = $request->file('file');
$path = $file->store('imports');
$batch = ImportBatch::create([
'user_id' => auth()->id(),
'filename' => $file->getClientOriginalName(),
'status' => 'pending',
'can_rollback' => Setting::where('key', 'import_rollback_allowed')->value('value') !== 'false',
]);
try {
$fullPath = Storage::path($path);
$preview = $this->importService->preview($fullPath);
// Store rows for later processing
$rows = Excel::toArray([], $fullPath)[0] ?? [];
$dataRows = array_slice($rows, 1);
foreach ($dataRows as $index => $row) {
$batch->rows()->create([
'original_data' => $row,
'status' => 'pending',
]);
}
$batch->update(['total_rows' => count($dataRows)]);
ActivityLogger::log('lead_import_uploaded', "Import batch {$batch->id} uploaded", $batch);
return response()->json([
'batch_id' => $batch->id,
'filename' => $file->getClientOriginalName(),
'headers' => $preview['headers'],
'total_rows' => $preview['total_rows'],
'preview' => $preview['preview'],
]);
} catch (\Exception $e) {
$batch->update(['status' => 'failed', 'errors' => $e->getMessage()]);
return response()->json(['message' => $e->getMessage()], 422);
}
}
public function confirm(Request $request): JsonResponse
{
$user = auth()->user();
Gate::authorize('import', ImportBatch::class);
$validated = $request->validate([
'batch_id' => 'required|exists:import_batches,id',
'column_mapping' => 'required|array',
'column_mapping.company' => 'required|integer',
'column_mapping.first_name' => 'nullable|integer',
'column_mapping.last_name' => 'nullable|integer',
'column_mapping.phone' => 'required|integer',
'column_mapping.phone_secondary' => 'nullable|integer',
'column_mapping.email' => 'nullable|integer',
'column_mapping.city' => 'nullable|integer',
'column_mapping.province' => 'nullable|integer',
'column_mapping.source' => 'nullable|integer',
'column_mapping.product_interest' => 'nullable|integer',
'column_mapping.priority' => 'nullable|integer',
'column_mapping.lead_score' => 'nullable|integer',
'column_mapping.interest_level' => 'nullable|integer',
'column_mapping.notes' => 'nullable|integer',
'column_mapping.tags' => 'nullable|integer',
'campaign_id' => 'nullable|exists:campaigns,id',
'agent_ids' => 'nullable|array',
'agent_ids.*' => 'exists:users,id',
]);
$agentIds = $validated['agent_ids'] ?? null;
if ($user?->hasRole('agent')) {
$agentIds = [$user->id];
}
$pendingBatch = ImportBatch::findOrFail($validated['batch_id']);
Gate::authorize('view', $pendingBatch);
$batch = $this->importService->confirm(
$validated['batch_id'],
$validated['column_mapping'],
$validated['campaign_id'] ?? null,
$agentIds,
auth()->id()
);
ActivityLogger::log('lead_import_confirmed', "Import batch {$batch->id} confirmed", $batch);
return response()->json($batch->load('rows'));
}
public function rollback(int $batchId): JsonResponse
{
$batch = ImportBatch::findOrFail($batchId);
Gate::authorize('rollback', $batch);
$this->importService->rollback($batchId);
ActivityLogger::log('lead_import_rolled_back', "Import batch {$batchId} rolled back", $batch);
return response()->json(['message' => 'بازگشت import انجام شد']);
}
public function index(): JsonResponse
{
Gate::authorize('viewAny', ImportBatch::class);
return response()->json(
ImportBatch::with('user:id,name')
->orderBy('created_at', 'desc')
->paginate(15)
);
}
public function template()
{
Gate::authorize('import', ImportBatch::class);
$spreadsheet = new Spreadsheet;
$sheet = $spreadsheet->getActiveSheet();
$sheet->fromArray([
['company', 'phone', 'phone_secondary', 'first_name', 'last_name', 'email', 'city', 'province', 'source', 'product_interest', 'priority', 'lead_score', 'interest_level', 'notes', 'tags'],
['Acme Industrial', '02112345678', '09121234567', 'Ali', 'Karimi', 'ali@example.com', 'Tehran', 'Tehran', 'Website', 'CRM', '5', '70', 'warm', 'Initial import note', 'b2b,website'],
['Pars Co', '02187654321', '', 'Sara', 'Ahmadi', 'sara@example.com', 'Shiraz', 'Fars', 'Exhibition', 'Support', '3', '40', 'cold', '', 'exhibition'],
]);
$path = storage_path('app/import-template-b2b.xlsx');
(new Xlsx($spreadsheet))->save($path);
return response()->download($path, 'sample-leads-b2b.xlsx')->deleteFileAfterSend(true);
}
}