argument('year'); if ($year < 2020 || $year > 2100) { $this->error("Некорректный год: {$year}"); return self::FAILURE; } $stats = $this->collectStats($year); $this->info("Данные для удаления за {$year} год:"); $this->table( ['Сущность', 'Количество'], collect($stats)->map(fn($count, $name) => [$name, $count])->toArray() ); if (!$this->option('force')) { if (!$this->confirm('Вы уверены, что хотите удалить все эти данные? Это действие необратимо!')) { $this->info('Операция отменена.'); return self::SUCCESS; } } $this->info('Начинаю удаление данных...'); DB::beginTransaction(); try { $this->clearData($year); DB::commit(); $this->info('Все данные за ' . $year . ' год успешно удалены.'); return self::SUCCESS; } catch (\Exception $e) { DB::rollBack(); $this->error('Ошибка при удалении данных: ' . $e->getMessage()); return self::FAILURE; } } private function collectStats(int $year): array { $orderIds = Order::withoutGlobalScopes()->withTrashed()->where('year', $year)->pluck('id'); $productIds = Product::withoutGlobalScopes()->withTrashed()->where('year', $year)->pluck('id'); $mafOrderIds = MafOrder::withoutGlobalScopes()->withTrashed()->where('year', $year)->pluck('id'); $productSkuIds = ProductSKU::withoutGlobalScopes()->withTrashed()->where('year', $year)->pluck('id'); $reclamationCount = Reclamation::whereIn('order_id', $orderIds)->count(); // Собираем ID файлов для удаления $fileIds = $this->collectFileIds($year, $orderIds, $productIds, $productSkuIds); return [ 'Заказы (Orders)' => $orderIds->count(), 'Заказы МАФ (MafOrders)' => $mafOrderIds->count(), 'Продукты (Products)' => $productIds->count(), 'SKU продуктов (ProductSKU)' => $productSkuIds->count(), 'Рекламации (Reclamations)' => $reclamationCount, 'Расписания (Schedules)' => Schedule::whereIn('order_id', $orderIds)->count(), 'ТТН (Ttns)' => Ttn::where('year', $year)->count(), 'Контракты (Contracts)' => Contract::where('year', $year)->count(), 'Файлы (Files)' => $fileIds->count(), ]; } private function collectFileIds(int $year, $orderIds, $productIds, $productSkuIds): \Illuminate\Support\Collection { $fileIds = collect(); // Файлы заказов (фото, документы, ведомости) $fileIds = $fileIds->merge( DB::table('order_photo')->whereIn('order_id', $orderIds)->pluck('file_id') ); $fileIds = $fileIds->merge( DB::table('order_document')->whereIn('order_id', $orderIds)->pluck('file_id') ); $fileIds = $fileIds->merge( DB::table('order_statement')->whereIn('order_id', $orderIds)->pluck('file_id') ); // Рекламации связанных заказов $reclamationIds = Reclamation::whereIn('order_id', $orderIds)->pluck('id'); $fileIds = $fileIds->merge( DB::table('reclamation_photo_before')->whereIn('reclamation_id', $reclamationIds)->pluck('file_id') ); $fileIds = $fileIds->merge( DB::table('reclamation_photo_after')->whereIn('reclamation_id', $reclamationIds)->pluck('file_id') ); $fileIds = $fileIds->merge( DB::table('reclamation_document')->whereIn('reclamation_id', $reclamationIds)->pluck('file_id') ); $fileIds = $fileIds->merge( DB::table('reclamation_act')->whereIn('reclamation_id', $reclamationIds)->pluck('file_id') ); // Сертификаты продуктов $fileIds = $fileIds->merge( Product::withoutGlobalScopes()->withTrashed() ->whereIn('id', $productIds) ->whereNotNull('certificate_id') ->pluck('certificate_id') ); // Паспорта SKU $fileIds = $fileIds->merge( ProductSKU::withoutGlobalScopes()->withTrashed() ->whereIn('id', $productSkuIds) ->whereNotNull('passport_id') ->pluck('passport_id') ); // Файлы ТТН $fileIds = $fileIds->merge( Ttn::where('year', $year)->whereNotNull('file_id')->pluck('file_id') ); return $fileIds->unique(); } private function clearData(int $year): void { $orderIds = Order::withoutGlobalScopes()->withTrashed()->where('year', $year)->pluck('id'); $productIds = Product::withoutGlobalScopes()->withTrashed()->where('year', $year)->pluck('id'); $mafOrderIds = MafOrder::withoutGlobalScopes()->withTrashed()->where('year', $year)->pluck('id'); $productSkuIds = ProductSKU::withoutGlobalScopes()->withTrashed()->where('year', $year)->pluck('id'); $reclamationIds = Reclamation::whereIn('order_id', $orderIds)->pluck('id'); // Собираем файлы до удаления связей $fileIds = $this->collectFileIds($year, $orderIds, $productIds, $productSkuIds); $this->info('Удаление рекламаций и связанных данных...'); // Детали рекламаций (cascadeOnDelete, но удаляем явно для уверенности) DB::table('reclamation_details')->whereIn('reclamation_id', $reclamationIds)->delete(); DB::table('reclamation_product_sku')->whereIn('reclamation_id', $reclamationIds)->delete(); DB::table('reclamation_photo_before')->whereIn('reclamation_id', $reclamationIds)->delete(); DB::table('reclamation_photo_after')->whereIn('reclamation_id', $reclamationIds)->delete(); DB::table('reclamation_document')->whereIn('reclamation_id', $reclamationIds)->delete(); DB::table('reclamation_act')->whereIn('reclamation_id', $reclamationIds)->delete(); Reclamation::whereIn('id', $reclamationIds)->delete(); $this->info('Удаление связей заказов с файлами...'); DB::table('order_photo')->whereIn('order_id', $orderIds)->delete(); DB::table('order_document')->whereIn('order_id', $orderIds)->delete(); DB::table('order_statement')->whereIn('order_id', $orderIds)->delete(); $this->info('Удаление расписаний...'); Schedule::whereIn('order_id', $orderIds)->delete(); $this->info('Удаление SKU продуктов...'); ProductSKU::withoutGlobalScopes()->withTrashed()->where('year', $year)->forceDelete(); $this->info('Удаление заказов...'); Order::withoutGlobalScopes()->withTrashed()->where('year', $year)->forceDelete(); $this->info('Удаление заказов МАФ...'); MafOrder::withoutGlobalScopes()->withTrashed()->where('year', $year)->forceDelete(); $this->info('Удаление продуктов...'); // Сначала обнуляем certificate_id чтобы избежать проблем с FK Product::withoutGlobalScopes()->withTrashed() ->whereIn('id', $productIds) ->update(['certificate_id' => null]); Product::withoutGlobalScopes()->withTrashed()->where('year', $year)->forceDelete(); $this->info('Удаление ТТН...'); // Обнуляем file_id перед удалением Ttn::where('year', $year)->update(['file_id' => null]); Ttn::where('year', $year)->delete(); $this->info('Удаление контрактов...'); Contract::where('year', $year)->delete(); $this->info('Удаление файлов...'); $this->deleteFiles($fileIds); } private function deleteFiles($fileIds): void { $files = File::whereIn('id', $fileIds)->get(); foreach ($files as $file) { // Удаляем физический файл if ($file->path && Storage::disk('public')->exists($file->path)) { Storage::disk('public')->delete($file->path); } } // Удаляем записи из БД File::whereIn('id', $fileIds)->delete(); } }