| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- <?php
- namespace App\Services\Import;
- use App\Models\Dictionary\Area;
- use App\Models\Dictionary\District;
- use Exception;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Log;
- use PhpOffice\PhpSpreadsheet\IOFactory;
- class ImportAreasService
- {
- private array $logs = [];
- private array $districtCache = [];
- public function __construct(
- private readonly string $filePath,
- private readonly int $userId,
- ) {}
- public function handle(): array
- {
- try {
- $this->log("Начало импорта справочника районов");
- // Загружаем кэш округов
- $this->loadDistrictCache();
- DB::beginTransaction();
- try {
- $spreadsheet = IOFactory::load($this->filePath);
- $sheet = $spreadsheet->getActiveSheet();
- $highestRow = $sheet->getHighestRow();
- $imported = 0;
- $updated = 0;
- $skipped = 0;
- for ($row = 2; $row <= $highestRow; $row++) {
- $id = trim($sheet->getCell('A' . $row)->getValue());
- $name = trim($sheet->getCell('B' . $row)->getValue());
- $districtShortname = trim($sheet->getCell('C' . $row)->getValue());
- $districtId = trim($sheet->getCell('D' . $row)->getValue());
- // Пропускаем пустые строки
- if (empty($name)) {
- $skipped++;
- continue;
- }
- // Определяем округ
- $foundDistrictId = null;
- // Сначала по ID округа
- if (!empty($districtId) && is_numeric($districtId)) {
- $foundDistrictId = (int) $districtId;
- if (!isset($this->districtCache[$foundDistrictId])) {
- $this->log("Строка {$row}: округ с ID {$districtId} не найден");
- $foundDistrictId = null;
- }
- }
- // Потом по сокращению
- if (!$foundDistrictId && !empty($districtShortname)) {
- foreach ($this->districtCache as $dId => $dShortname) {
- if (mb_strtolower($dShortname) === mb_strtolower($districtShortname)) {
- $foundDistrictId = $dId;
- break;
- }
- }
- if (!$foundDistrictId) {
- $this->log("Строка {$row}: округ '{$districtShortname}' не найден");
- }
- }
- if (!$foundDistrictId) {
- $this->log("Строка {$row}: пропущена (не найден округ)");
- $skipped++;
- continue;
- }
- $data = [
- 'name' => $name,
- 'district_id' => $foundDistrictId,
- ];
- // Если есть ID, ищем по нему
- if (!empty($id) && is_numeric($id)) {
- $area = Area::withTrashed()->find((int) $id);
- if ($area) {
- if ($area->trashed()) {
- $area->restore();
- }
- $area->update($data);
- $updated++;
- continue;
- }
- }
- // Ищем по названию и округу
- $area = Area::withTrashed()
- ->where('name', $name)
- ->where('district_id', $foundDistrictId)
- ->first();
- if ($area) {
- if ($area->trashed()) {
- $area->restore();
- }
- $area->update($data);
- $updated++;
- } else {
- Area::create($data);
- $imported++;
- }
- }
- DB::commit();
- $this->log("Импорт районов: создано {$imported}, обновлено {$updated}, пропущено {$skipped}");
- return [
- 'success' => true,
- 'imported' => $imported,
- 'updated' => $updated,
- 'skipped' => $skipped,
- 'logs' => $this->logs,
- ];
- } catch (Exception $e) {
- DB::rollBack();
- throw $e;
- }
- } catch (Exception $e) {
- $this->log("ОШИБКА: " . $e->getMessage());
- Log::error("Ошибка импорта районов: " . $e->getMessage(), [
- 'trace' => $e->getTraceAsString(),
- ]);
- return [
- 'success' => false,
- 'error' => $e->getMessage(),
- 'logs' => $this->logs,
- ];
- }
- }
- private function loadDistrictCache(): void
- {
- $this->districtCache = District::pluck('shortname', 'id')->toArray();
- }
- private function log(string $message): void
- {
- $this->logs[] = '[' . date('H:i:s') . '] ' . $message;
- Log::info($message);
- }
- public function getLogs(): array
- {
- return $this->logs;
- }
- }
|