From 7e79bf714afcb7cfb975e09654d7b49b67f3e1ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Tue, 26 May 2026 11:28:57 +0300 Subject: [PATCH] feat(project-bulk): distinguish supplier_snapshot_locked from has_deals in bulkDelete --- app/app/Services/Project/ProjectService.php | 11 +++++++++-- .../Unit/Services/Project/PausedAtWriteSideTest.php | 9 +++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/app/Services/Project/ProjectService.php b/app/app/Services/Project/ProjectService.php index f06ba237..5a657ea5 100644 --- a/app/app/Services/Project/ProjectService.php +++ b/app/app/Services/Project/ProjectService.php @@ -312,8 +312,15 @@ class ProjectService try { $this->delete($model); $deleted++; - } catch (HttpResponseException) { - $skipped[] = ['id' => $p->id, 'reason' => 'has_deals']; + } catch (HttpResponseException $e) { + // Spec: docs/superpowers/plans/2026-05-26-supplier-snapshot-guard.md (Task 12). + // Разделяем причину: guard поставщика (нужно подождать) vs has-deals. + $body = json_decode((string) $e->getResponse()->getContent(), true); + $message = (string) ($body['errors']['project'][0] ?? ''); + $reason = str_contains($message, 'Мы уже начали сбор лидов') + ? 'supplier_snapshot_locked' + : 'has_deals'; + $skipped[] = ['id' => $p->id, 'reason' => $reason]; } } diff --git a/app/tests/Unit/Services/Project/PausedAtWriteSideTest.php b/app/tests/Unit/Services/Project/PausedAtWriteSideTest.php index c1034603..a729c359 100644 --- a/app/tests/Unit/Services/Project/PausedAtWriteSideTest.php +++ b/app/tests/Unit/Services/Project/PausedAtWriteSideTest.php @@ -43,6 +43,15 @@ class PausedAtWriteSideTest extends TestCase $this->assertStringContainsString('is_active', $body); } + public function test_bulk_delete_distinguishes_supplier_snapshot_lock_from_has_deals(): void + { + $body = $this->methodBody(ProjectService::class, 'bulkDelete'); + + $this->assertStringContainsString('supplier_snapshot_locked', $body, + 'bulkDelete должен помечать пропущенные проекты reason="supplier_snapshot_locked" при guard-блоке'); + $this->assertStringContainsString('has_deals', $body); + } + private function methodBody(string $class, string $method): string { $rm = new ReflectionMethod($class, $method);