| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- <?php
- namespace App\Services\Import;
- use App\Models\SparePart;
- use App\Models\SparePartOrder;
- use Exception;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Log;
- use PhpOffice\PhpSpreadsheet\IOFactory;
- class ImportSparePartOrdersService
- {
- private array $logs = [];
- private array $sparePartCache = [];
- public function __construct(
- private readonly string $filePath,
- private readonly int $userId,
- ) {}
- public function handle(): array
- {
- try {
- $this->log("Начало импорта заказов запчастей");
- // Загружаем кэш запчастей по артикулу
- $this->loadSparePartCache();
- DB::beginTransaction();
- try {
- $spreadsheet = IOFactory::load($this->filePath);
- $sheet = $spreadsheet->getActiveSheet();
- $highestRow = $sheet->getHighestRow();
- $imported = 0;
- $skipped = 0;
- $errors = 0;
- // Начинаем со 2-й строки (пропускаем заголовок)
- // Колонки: A=Артикул, B=кол-во, C=С документами?, D=Номер заказа, E=Статус
- for ($row = 2; $row <= $highestRow; $row++) {
- $article = trim($sheet->getCell('A' . $row)->getValue());
- $quantity = (int) $sheet->getCell('B' . $row)->getValue();
- $withDocsRaw = trim($sheet->getCell('C' . $row)->getValue());
- $orderNumber = trim($sheet->getCell('D' . $row)->getValue());
- $statusRaw = trim($sheet->getCell('E' . $row)->getValue());
- // Пропускаем пустые строки
- if (empty($article)) {
- $skipped++;
- continue;
- }
- // Проверяем наличие запчасти в каталоге
- if (!isset($this->sparePartCache[$article])) {
- $this->log("Строка {$row}: запчасть с артикулом '{$article}' не найдена в каталоге", 'ERROR');
- $errors++;
- continue;
- }
- $sparePartId = $this->sparePartCache[$article];
- // Парсим "С документами?"
- $withDocuments = $this->parseWithDocuments($withDocsRaw);
- // Парсим статус
- $status = $this->parseStatus($statusRaw);
- if ($status === null) {
- $this->log("Строка {$row}: неизвестный статус '{$statusRaw}'", 'ERROR');
- $errors++;
- continue;
- }
- // Создаём заказ запчасти
- SparePartOrder::create([
- 'spare_part_id' => $sparePartId,
- 'order_number' => $orderNumber ?: null,
- 'status' => $status,
- 'ordered_quantity' => $quantity,
- 'available_qty' => $quantity,
- 'with_documents' => $withDocuments,
- 'user_id' => $this->userId,
- ]);
- $imported++;
- }
- DB::commit();
- $this->log("=== РЕЗЮМЕ ИМПОРТА ===");
- $this->log("Импортировано: {$imported}");
- $this->log("Пропущено (пустые строки): {$skipped}");
- $this->log("Ошибок: {$errors}");
- return [
- 'success' => $errors === 0,
- 'imported' => $imported,
- 'skipped' => $skipped,
- 'errors' => $errors,
- 'logs' => $this->logs,
- ];
- } catch (Exception $e) {
- DB::rollBack();
- throw $e;
- }
- } catch (Exception $e) {
- $this->log("КРИТИЧЕСКАЯ ОШИБКА: " . $e->getMessage(), 'ERROR');
- Log::error("Ошибка импорта заказов запчастей: " . $e->getMessage(), [
- 'trace' => $e->getTraceAsString(),
- ]);
- return [
- 'success' => false,
- 'error' => $e->getMessage(),
- 'logs' => $this->logs,
- ];
- }
- }
- private function loadSparePartCache(): void
- {
- $this->sparePartCache = SparePart::pluck('id', 'article')->toArray();
- $this->log("Загружено " . count($this->sparePartCache) . " запчастей в кэш");
- }
- private function parseWithDocuments(string $value): bool
- {
- $value = mb_strtolower(trim($value));
- return in_array($value, ['да', 'yes', '1', 'true']);
- }
- private function parseStatus(string $value): ?string
- {
- $value = mb_strtolower(trim($value));
- $statusMap = [
- 'на складе' => SparePartOrder::STATUS_IN_STOCK,
- 'in_stock' => SparePartOrder::STATUS_IN_STOCK,
- 'in stock' => SparePartOrder::STATUS_IN_STOCK,
- 'заказано' => SparePartOrder::STATUS_ORDERED,
- 'ordered' => SparePartOrder::STATUS_ORDERED,
- 'отгружено' => SparePartOrder::STATUS_SHIPPED,
- 'shipped' => SparePartOrder::STATUS_SHIPPED,
- ];
- return $statusMap[$value] ?? null;
- }
- private function log(string $message, string $level = 'INFO'): void
- {
- $this->logs[] = '[' . date('H:i:s') . '] ' . $level . ': ' . $message;
- Log::info($message);
- }
- public function getLogs(): array
- {
- return $this->logs;
- }
- }
|