From c025ec4b696ab1faf4d1a0f2e5214ae8f97cb607 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, 12 May 2026 14:52:23 +0300 Subject: [PATCH] feat(projects-bulk): update_days handler with bitmask OR/AND-NOT Co-Authored-By: Claude Sonnet 4.6 --- app/app/Services/Project/ProjectService.php | 9 ++++++++- app/phpstan-baseline.neon | 12 ++++++------ .../Feature/Api/ProjectBulkActionsTest.php | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/app/app/Services/Project/ProjectService.php b/app/app/Services/Project/ProjectService.php index 9249ea7e..74beff5f 100644 --- a/app/app/Services/Project/ProjectService.php +++ b/app/app/Services/Project/ProjectService.php @@ -101,7 +101,14 @@ class ProjectService private function bulkUpdateDays($query, array $payload): array { - return ['updated' => 0, 'skipped' => [], 'warnings' => []]; + $add = (int) ($payload['add'] ?? 0); + $remove = (int) ($payload['remove'] ?? 0); + + $updated = $query->update([ + 'delivery_days_mask' => \DB::raw("(delivery_days_mask | {$add}) & ~{$remove} & 127"), + ]); + + return ['updated' => $updated, 'skipped' => [], 'warnings' => []]; } private function bulkUpdateLimit($query, array $payload): array diff --git a/app/phpstan-baseline.neon b/app/phpstan-baseline.neon index 6b805c62..a9356d2c 100644 --- a/app/phpstan-baseline.neon +++ b/app/phpstan-baseline.neon @@ -246,6 +246,12 @@ parameters: count: 13 path: tests/Feature/AdminTenantsIndexTest.php + - + message: '#^Call to an undefined method Pest\\PendingCalls\\TestCall\:\:actingAs\(\)\.$#' + identifier: method.notFound + count: 7 + path: tests/Feature/Api/ProjectBulkActionsTest.php + - message: '#^Access to an undefined property Pest\\PendingCalls\\TestCall\:\:\$tenant\.$#' identifier: property.notFound @@ -1253,9 +1259,3 @@ parameters: identifier: argument.type count: 3 path: tests/Unit/Supplier/SupplierQuotaAllocatorTest.php - - - - message: '#^Call to an undefined method Pest\\PendingCalls\\TestCall\:\:actingAs\(\)\.$#' - identifier: method.notFound - count: 6 - path: tests/Feature/Api/ProjectBulkActionsTest.php diff --git a/app/tests/Feature/Api/ProjectBulkActionsTest.php b/app/tests/Feature/Api/ProjectBulkActionsTest.php index 12fbc3e3..74179dfe 100644 --- a/app/tests/Feature/Api/ProjectBulkActionsTest.php +++ b/app/tests/Feature/Api/ProjectBulkActionsTest.php @@ -88,3 +88,21 @@ it('applies update_regions add and remove correctly', function () { expect($p1->fresh()->region_mask)->toBe((3 | 16) & ~1); // = 18 expect($p2->fresh()->region_mask)->toBe((5 | 16) & ~1); // = 20 }); + +it('applies update_days add and remove correctly', function () { + $tenant = Tenant::factory()->create(); + $user = User::factory()->for($tenant)->create(); + $p = Project::factory()->for($tenant)->create(['delivery_days_mask' => 31]); // Пн-Пт + + $this->actingAs($user) + ->postJson('/api/projects/bulk', [ + 'action' => 'update_days', + 'ids' => [$p->id], + 'add' => 96, // 32+64 = Сб+Вс + 'remove' => 1, // Пн + ]) + ->assertOk() + ->assertJson(['updated' => 1, 'skipped' => [], 'warnings' => []]); + + expect($p->fresh()->delivery_days_mask)->toBe((31 | 96) & ~1); // = 126 +});