From e8bcaa20261c0007ba6e805d33752130537d6322 Mon Sep 17 00:00:00 2001 From: ncoronel Date: Fri, 21 Aug 2026 16:15:59 -0300 Subject: [PATCH] feat(sales): handle in-review purchases as pending --- .../Sale/Services/AdminAppSaleService.php | 9 ++- .../Sale/AdminAppSaleControllerTest.php | 62 +++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/app/Domains/Sale/Services/AdminAppSaleService.php b/app/Domains/Sale/Services/AdminAppSaleService.php index 36afe58..e4e073d 100644 --- a/app/Domains/Sale/Services/AdminAppSaleService.php +++ b/app/Domains/Sale/Services/AdminAppSaleService.php @@ -79,7 +79,7 @@ class AdminAppSaleService $sale = $this->findForTenant($tenant, $saleId); return $this->saleForResponse( - $this->checkoutService->cancelPurchase($sale) + $this->checkoutService->cancelPurchaseFromAdmin($sale) ); } @@ -144,7 +144,12 @@ class AdminAppSaleService ) ->when( $filters['status'] ?? null, - fn (Builder $query, string $status): Builder => $query->where('status', $status) + fn (Builder $query, string $status): Builder => $status === Purchase::STATUS_PENDING_PAYMENT + ? $query->whereIn('status', [ + Purchase::STATUS_PENDING_PAYMENT, + Purchase::STATUS_IN_REVIEW, + ]) + : $query->where('status', $status) ) ->select('compras.*') ->selectRaw( diff --git a/tests/Feature/Sale/AdminAppSaleControllerTest.php b/tests/Feature/Sale/AdminAppSaleControllerTest.php index 4d1e99a..5d0d971 100644 --- a/tests/Feature/Sale/AdminAppSaleControllerTest.php +++ b/tests/Feature/Sale/AdminAppSaleControllerTest.php @@ -142,6 +142,31 @@ class AdminAppSaleControllerTest extends TestCase $this->getJson('/api/v1/adminapp/tenant/sales/1')->assertUnauthorized(); } + public function test_pending_payment_filter_also_returns_purchases_in_review(): void + { + $tenant = $this->createTenant('acme'); + Sanctum::actingAs($this->createAdminAppUser($tenant)); + + $pendingPurchase = Purchase::query()->create([ + 'tenant_codigo' => $tenant->codigo, + 'status' => Purchase::STATUS_PENDING_PAYMENT, + ]); + $reviewPurchase = Purchase::query()->create([ + 'tenant_codigo' => $tenant->codigo, + 'status' => Purchase::STATUS_IN_REVIEW, + ]); + Purchase::query()->create([ + 'tenant_codigo' => $tenant->codigo, + 'status' => Purchase::STATUS_PAID, + ]); + + $this->getJson('/api/v1/adminapp/tenant/sales?status=pending_payment&sort_by=id&sort_direction=asc') + ->assertOk() + ->assertJsonCount(2, 'data') + ->assertJsonPath('data.0.id', $pendingPurchase->id) + ->assertJsonPath('data.1.id', $reviewPurchase->id); + } + public function test_an_adminapp_user_can_read_a_sale_detail_from_its_tenant(): void { $tenant = $this->createTenant('acme'); @@ -464,6 +489,43 @@ class AdminAppSaleControllerTest extends TestCase ->assertJsonPath('data.items.0.quantity', 2); } + public function test_adminapp_can_cancel_a_purchase_in_review(): void + { + $tenant = $this->createTenant('acme'); + $admin = $this->createAdminAppUser($tenant); + Sanctum::actingAs($admin); + $inventory = Inventory::query()->create(['real_stock' => 10]); + $catalogItem = CatalogItem::query()->create([ + 'tenant_code' => $tenant->codigo, + 'slug' => 'review-item', + 'nombre' => 'Review item', + 'precio' => '10000.00', + ]); + $variant = Variant::query()->create([ + 'catalog_item_id' => $catalogItem->id, + 'inventory_id' => $inventory->id, + ]); + $purchase = app(CheckoutService::class)->startCheckout($tenant, $admin->id, [ + 'direct_items' => [[ + 'catalog_item_id' => $catalogItem->id, + 'variant_id' => $variant->id, + 'cantidad' => 2, + ]], + ]); + $purchase->update(['status' => Purchase::STATUS_IN_REVIEW]); + $sourceCartId = $purchase->cart_id; + + $this->postJson("/api/v1/adminapp/tenant/sales/{$purchase->id}/cancel") + ->assertOk() + ->assertJsonPath('data.status', Purchase::STATUS_CANCELLED); + + $this->assertSoftDeleted('carritos', ['id' => $sourceCartId]); + $this->assertDatabaseHas('stock_reservations', [ + 'purchase_id' => $purchase->id, + 'status' => 'released', + ]); + } + public function test_an_adminapp_user_cannot_change_a_sale_from_another_tenant(): void { $tenant = $this->createTenant('acme');