copy()->subDays(self::RETENTION_DAYS); return [ 'retention_days' => self::RETENTION_DAYS, 'cutoff' => $cutoff->toDateTimeString(), 'price_sync_logs' => $this->prunePriceSyncLogs($cutoff), 'logs' => $this->pruneGenericLogs($cutoff), 'pargar_sync_logs' => $this->pruneSuccessfulRows( PargarSyncLog::query(), 'pargar_sync_logs', PargarSyncService::STATUS_SUCCESS, $cutoff ), 'zarin' => $this->pruneSuccessfulRows( Zarin::query(), 'zarin', ZarinSyncService::STATUS_SUCCESS, $cutoff ), 'tahesab' => $this->pruneSuccessfulRows( Tahesab::query(), 'tahesab', TahesabSyncService::STATUS_SUCCESS, $cutoff ), ]; } /** @return array{deleted: int, items_deleted: int} */ private function prunePriceSyncLogs(Carbon $cutoff): array { if (! Schema::hasTable('price_sync_logs')) { return ['deleted' => 0, 'items_deleted' => 0]; } $deleted = 0; $itemsDeleted = 0; $hasItems = Schema::hasTable('price_sync_log_items'); PriceSyncLog::query() ->where('created_at', '<', $cutoff) ->orderBy('id') ->select(['id']) ->chunkById(self::CHUNK, function ($rows) use (&$deleted, &$itemsDeleted, $hasItems) { $ids = $rows->pluck('id')->all(); if ($ids === []) { return; } if ($hasItems) { $itemsDeleted += (int) PriceSyncLogItem::query()->whereIn('log_id', $ids)->delete(); } $deleted += (int) PriceSyncLog::query()->whereIn('id', $ids)->delete(); }); return ['deleted' => $deleted, 'items_deleted' => $itemsDeleted]; } /** @return array{deleted: int} */ private function pruneGenericLogs(Carbon $cutoff): array { if (! Schema::hasTable('logs')) { return ['deleted' => 0]; } $deleted = 0; Log::query() ->where('created_at', '<', $cutoff) ->orderBy('id') ->select(['id']) ->chunkById(self::CHUNK, function ($rows) use (&$deleted) { $ids = $rows->pluck('id')->all(); if ($ids === []) { return; } $deleted += (int) Log::query()->whereIn('id', $ids)->delete(); }); return ['deleted' => $deleted]; } /** * فقط ردیف‌های موفق حسابداری — pending/failed برای retry می‌مانند. * * @return array{deleted: int, skipped: bool} */ private function pruneSuccessfulRows(Builder $query, string $table, string $successStatus, Carbon $cutoff): array { if (! Schema::hasTable($table) || ! Schema::hasColumn($table, 'sync_status')) { return ['deleted' => 0, 'skipped' => true]; } if (! Schema::hasColumn($table, 'created_at')) { return ['deleted' => 0, 'skipped' => true]; } $deleted = 0; (clone $query) ->where('sync_status', $successStatus) ->where('created_at', '<', $cutoff) ->orderBy('id') ->select(['id']) ->chunkById(self::CHUNK, function ($rows) use (&$deleted, $query) { $ids = $rows->pluck('id')->all(); if ($ids === []) { return; } $deleted += (int) (clone $query)->whereIn('id', $ids)->delete(); }); return ['deleted' => $deleted, 'skipped' => false]; } }