Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 61 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 1 |
| CleanupNuvemshopE2ECommand | |
0.00% |
0 / 61 |
|
0.00% |
0 / 3 |
506 | |
0.00% |
0 / 1 |
| handle | |
0.00% |
0 / 38 |
|
0.00% |
0 / 1 |
210 | |||
| deleteCouponDirectly | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
| cleanupLocal | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
30 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace App\Console\Commands; |
| 4 | |
| 5 | use App\Enums\CouponStatus; |
| 6 | use App\Models\Influencer; |
| 7 | use App\Models\InfluencerCoupon; |
| 8 | use App\Models\Order; |
| 9 | use App\Models\StoreIntegration; |
| 10 | use App\Models\User; |
| 11 | use App\Services\Nuvemshop\NuvemshopProductService; |
| 12 | use App\Services\Nuvemshop\NuvemshopWebhookRegistrationService; |
| 13 | use Illuminate\Console\Command; |
| 14 | use Illuminate\Support\Facades\File; |
| 15 | use Illuminate\Support\Facades\Http; |
| 16 | use Throwable; |
| 17 | |
| 18 | class CleanupNuvemshopE2ECommand extends Command |
| 19 | { |
| 20 | protected $signature = 'orvox:test:nuvemshop-cleanup |
| 21 | {--manifest=storage/app/orvox-nuvemshop-e2e-manifest.json : Caminho do manifest gerado no E2E} |
| 22 | {--keep-local : Não apaga dados locais, apenas Nuvemshop}'; |
| 23 | |
| 24 | protected $description = 'Remove produto/cupom/webhooks criados para teste E2E da Nuvemshop e limpa dados locais de teste.'; |
| 25 | |
| 26 | public function handle(NuvemshopProductService $productService, NuvemshopWebhookRegistrationService $webhookService): int |
| 27 | { |
| 28 | $manifestPath = base_path((string) $this->option('manifest')); |
| 29 | |
| 30 | if (! File::exists($manifestPath)) { |
| 31 | $this->error('Manifest não encontrado: '.$manifestPath); |
| 32 | return self::FAILURE; |
| 33 | } |
| 34 | |
| 35 | $manifest = json_decode(File::get($manifestPath), true) ?: []; |
| 36 | $integration = StoreIntegration::find(data_get($manifest, 'integration_id')); |
| 37 | |
| 38 | if (! $integration) { |
| 39 | $this->error('Integração não encontrada no manifest.'); |
| 40 | return self::FAILURE; |
| 41 | } |
| 42 | |
| 43 | $errors = []; |
| 44 | |
| 45 | if ($productId = data_get($manifest, 'nuvemshop.product_id')) { |
| 46 | try { |
| 47 | $productService->deleteProduct($integration, $productId); |
| 48 | $this->info('Produto removido da Nuvemshop: '.$productId); |
| 49 | } catch (Throwable $exception) { |
| 50 | $errors[] = 'Produto '.$productId.': '.$exception->getMessage(); |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | foreach ((array) data_get($manifest, 'nuvemshop.webhooks', []) as $event => $webhook) { |
| 55 | $webhookId = data_get($webhook, 'id'); |
| 56 | if (! $webhookId) { |
| 57 | continue; |
| 58 | } |
| 59 | |
| 60 | try { |
| 61 | $webhookService->delete($integration, $webhookId); |
| 62 | $this->info('Webhook removido da Nuvemshop: '.$event.' #'.$webhookId); |
| 63 | } catch (Throwable $exception) { |
| 64 | $errors[] = 'Webhook '.$webhookId.': '.$exception->getMessage(); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | if ($couponId = data_get($manifest, 'nuvemshop.coupon_id')) { |
| 69 | try { |
| 70 | $this->deleteCouponDirectly($integration, $couponId); |
| 71 | $this->info('Cupom removido da Nuvemshop: '.$couponId); |
| 72 | } catch (Throwable $exception) { |
| 73 | $errors[] = 'Cupom '.$couponId.': '.$exception->getMessage(); |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | if (! $this->option('keep-local')) { |
| 78 | $this->cleanupLocal($manifest); |
| 79 | } |
| 80 | |
| 81 | if ($errors) { |
| 82 | $this->warn('Cleanup finalizado com avisos:'); |
| 83 | foreach ($errors as $error) { |
| 84 | $this->warn('- '.$error); |
| 85 | } |
| 86 | return self::FAILURE; |
| 87 | } |
| 88 | |
| 89 | File::delete($manifestPath); |
| 90 | $this->info('Cleanup E2E finalizado.'); |
| 91 | |
| 92 | return self::SUCCESS; |
| 93 | } |
| 94 | |
| 95 | private function deleteCouponDirectly(StoreIntegration $integration, string|int $couponId): void |
| 96 | { |
| 97 | $base = rtrim((string) config('services.nuvemshop.api_base_url', 'https://api.tiendanube.com/v1'), '/'); |
| 98 | |
| 99 | $response = Http::acceptJson() |
| 100 | ->asJson() |
| 101 | ->withToken($integration->access_token) |
| 102 | ->withHeaders(['User-Agent' => config('services.nuvemshop.user_agent', 'Orvox Influencers Test Suite')]) |
| 103 | ->delete($base.'/'.$integration->external_store_id.'/coupons/'.$couponId); |
| 104 | |
| 105 | if ($response->failed() && $response->status() !== 404) { |
| 106 | throw new \RuntimeException($response->body()); |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | private function cleanupLocal(array $manifest): void |
| 111 | { |
| 112 | if ($orderId = data_get($manifest, 'local.simulated_order_id')) { |
| 113 | Order::whereKey($orderId)->delete(); |
| 114 | $this->info('Pedido simulado local removido: '.$orderId); |
| 115 | } |
| 116 | |
| 117 | if ($couponId = data_get($manifest, 'local.coupon_id')) { |
| 118 | InfluencerCoupon::whereKey($couponId)->update([ |
| 119 | 'status' => CouponStatus::Inactive->value, |
| 120 | 'ended_at' => now(), |
| 121 | ]); |
| 122 | $this->info('Cupom local inativado: '.$couponId); |
| 123 | } |
| 124 | |
| 125 | if ($influencerId = data_get($manifest, 'local.influencer_id')) { |
| 126 | Influencer::whereKey($influencerId)->delete(); |
| 127 | $this->info('Influencer local removido: '.$influencerId); |
| 128 | } |
| 129 | |
| 130 | if ($userId = data_get($manifest, 'local.user_id')) { |
| 131 | User::whereKey($userId)->delete(); |
| 132 | $this->info('Usuário local removido: '.$userId); |
| 133 | } |
| 134 | } |
| 135 | } |