diff --git a/app/Domains/Sale/Services/AdminAppSaleService.php b/app/Domains/Sale/Services/AdminAppSaleService.php index 95fec11..e771f8b 100644 --- a/app/Domains/Sale/Services/AdminAppSaleService.php +++ b/app/Domains/Sale/Services/AdminAppSaleService.php @@ -151,7 +151,8 @@ class AdminAppSaleService $filters['status'] ?? null, fn (Builder $query, string $status): Builder => $query->where('status', $status) ) - ->withSum('items as quantity', 'cantidad') + ->select('compras.*') + ->selectRaw($this->quantityExpression()) ->withCount('tickets') ->orderBy($sortColumns[$sortBy], $sortDirection) ->when($sortBy !== 'id', fn (Builder $query): Builder => $query->orderByDesc('id')); @@ -177,8 +178,26 @@ class AdminAppSaleService protected function saleForResponse(Purchase $sale): Purchase { - return $sale->refresh() - ->loadSum('items as quantity', 'cantidad') - ->loadCount('tickets'); + /** @var Purchase */ + return Purchase::query() + ->select('compras.*') + ->selectRaw($this->quantityExpression()) + ->withCount('tickets') + ->findOrFail($sale->getKey()); + } + + protected function quantityExpression(): string + { + return <<<'SQL' + COALESCE( + (SELECT SUM(compra_items.cantidad) + FROM compra_items + WHERE compra_items.compra_id = compras.id), + (SELECT SUM(carrito_items.cantidad) + FROM carrito_items + WHERE carrito_items.cart_id = compras.cart_id), + 0 + ) AS quantity + SQL; } } diff --git a/tests/Feature/Sale/AdminAppSaleControllerTest.php b/tests/Feature/Sale/AdminAppSaleControllerTest.php index 5235e38..e232999 100644 --- a/tests/Feature/Sale/AdminAppSaleControllerTest.php +++ b/tests/Feature/Sale/AdminAppSaleControllerTest.php @@ -110,6 +110,54 @@ class AdminAppSaleControllerTest extends TestCase ->assertJsonPath('data.items.0.total', '25000.00'); } + public function test_sales_list_uses_cart_quantity_until_purchase_items_exist(): void + { + $tenant = $this->createTenant('acme'); + Sanctum::actingAs($this->createAdminAppUser($tenant)); + + $catalogItem = CatalogItem::query()->create([ + 'tenant_code' => $tenant->codigo, + 'slug' => 'entrada-general', + 'nombre' => 'Entrada general', + 'descripcion' => 'Acceso general', + 'precio' => '12500.00', + ]); + $cart = Cart::query()->create([ + 'tenant_codigo' => $tenant->codigo, + 'status' => 'checkout', + ]); + CartItem::query()->create([ + 'cart_id' => $cart->id, + 'catalog_item_id' => $catalogItem->id, + 'cantidad' => 3, + ]); + $purchase = Purchase::query()->create([ + 'cart_id' => $cart->id, + 'tenant_codigo' => $tenant->codigo, + 'status' => Purchase::STATUS_PENDING_PAYMENT, + 'total' => '37500.00', + ]); + + $this->getJson('/api/v1/adminapp/tenant/sales') + ->assertOk() + ->assertJsonPath('data.0.id', $purchase->id) + ->assertJsonPath('data.0.quantity', 3); + + PurchaseItem::query()->create([ + 'compra_id' => $purchase->id, + 'source_catalog_item_id' => $catalogItem->id, + 'nombre' => 'Entrada general', + 'item_nombre' => 'Entrada general', + 'cantidad' => 2, + 'precio_unitario' => '12500.00', + 'total' => '25000.00', + ]); + + $this->getJson('/api/v1/adminapp/tenant/sales') + ->assertOk() + ->assertJsonPath('data.0.quantity', 2); + } + public function test_an_adminapp_user_cannot_read_a_sale_from_another_tenant(): void { $tenant = $this->createTenant('acme'); @@ -241,6 +289,18 @@ class AdminAppSaleControllerTest extends TestCase 'user_id' => $admin->id, 'status' => 'converted', ]); + $catalogItem = CatalogItem::query()->create([ + 'tenant_code' => $tenant->codigo, + 'slug' => 'entrada-general', + 'nombre' => 'Entrada general', + 'descripcion' => 'Acceso general', + 'precio' => '10000.00', + ]); + CartItem::query()->create([ + 'cart_id' => $cart->id, + 'catalog_item_id' => $catalogItem->id, + 'cantidad' => 2, + ]); $cart->delete(); $purchase = Purchase::query()->create([ 'cart_id' => $cart->id, @@ -251,7 +311,8 @@ class AdminAppSaleControllerTest extends TestCase $this->postJson("/api/v1/adminapp/tenant/sales/{$purchase->id}/cancel") ->assertOk() - ->assertJsonPath('data.status', Purchase::STATUS_CANCELLED); + ->assertJsonPath('data.status', Purchase::STATUS_CANCELLED) + ->assertJsonPath('data.quantity', 2); $this->assertSame(Purchase::STATUS_CANCELLED, $purchase->fresh()->status); $this->assertSoftDeleted('carritos', ['id' => $cart->id]);