feat(checkout): track current cart purchase
This commit is contained in:
@@ -17,6 +17,7 @@ use App\Domains\Tenant\Models\Tenant;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Tests\TestCase;
|
||||
|
||||
class StorePurchaseTest extends TestCase
|
||||
@@ -128,6 +129,7 @@ class StorePurchaseTest extends TestCase
|
||||
'user_id' => $user->id,
|
||||
'status' => 'active',
|
||||
'origin' => Cart::ORIGIN_USER,
|
||||
'current_purchase_id' => $purchaseId,
|
||||
'deleted_at' => null,
|
||||
]);
|
||||
$this->assertDatabaseHas('carrito_items', [
|
||||
@@ -150,12 +152,31 @@ class StorePurchaseTest extends TestCase
|
||||
->assertJsonCount(1, 'data.items')
|
||||
->assertJsonPath('data.items.0.cantidad', 2);
|
||||
|
||||
$this->actingAs($user, 'sanctum')
|
||||
$replacementResponse = $this->actingAs($user, 'sanctum')
|
||||
->postJson('/api/tenants/sonder/compras/start-checkout', [
|
||||
'cart_id' => $cartId,
|
||||
])
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors('cart_id');
|
||||
->assertCreated();
|
||||
$replacementPurchaseId = $replacementResponse->json('data.id');
|
||||
|
||||
$this->assertDatabaseHas('compras', [
|
||||
'id' => $purchaseId,
|
||||
'status' => Purchase::STATUS_SUPERSEDED,
|
||||
]);
|
||||
$this->assertDatabaseHas('carritos', [
|
||||
'id' => $cartId,
|
||||
'current_purchase_id' => $replacementPurchaseId,
|
||||
]);
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
'inventory_id' => $inventory->id,
|
||||
'purchase_id' => $replacementPurchaseId,
|
||||
'quantity' => 2,
|
||||
'status' => 'active',
|
||||
]);
|
||||
$this->assertDatabaseHas('inventories', [
|
||||
'id' => $inventory->id,
|
||||
'reserved_stock' => 2,
|
||||
]);
|
||||
|
||||
$catalogItem->update([
|
||||
'nombre' => 'Updated Product',
|
||||
@@ -196,6 +217,7 @@ class StorePurchaseTest extends TestCase
|
||||
'id' => $response->json('data.cart_id'),
|
||||
'status' => 'checkout',
|
||||
'origin' => Cart::ORIGIN_DIRECT_CHECKOUT,
|
||||
'current_purchase_id' => $response->json('data.id'),
|
||||
]);
|
||||
$this->assertDatabaseHas('compra_items', [
|
||||
'compra_id' => $response->json('data.id'),
|
||||
@@ -455,6 +477,7 @@ class StorePurchaseTest extends TestCase
|
||||
'id' => $purchase->cart_id,
|
||||
'status' => 'active',
|
||||
'origin' => Cart::ORIGIN_USER,
|
||||
'current_purchase_id' => $purchase->id,
|
||||
'deleted_at' => null,
|
||||
]);
|
||||
$this->assertDatabaseCount('carrito_items', 1);
|
||||
@@ -469,6 +492,7 @@ class StorePurchaseTest extends TestCase
|
||||
'id' => $activeCart->id,
|
||||
'user_id' => $user->id,
|
||||
'status' => 'active',
|
||||
'current_purchase_id' => null,
|
||||
'deleted_at' => null,
|
||||
]);
|
||||
$this->assertDatabaseHas('inventories', [
|
||||
@@ -484,6 +508,60 @@ class StorePurchaseTest extends TestCase
|
||||
$this->assertSame(1, $activeCart->items()->count());
|
||||
}
|
||||
|
||||
public function test_it_reassigns_a_terminal_purchase_reservation_and_rejects_a_late_confirmation(): void
|
||||
{
|
||||
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||
$user = User::factory()->create();
|
||||
$variant = $this->createVariantForTenant('sonder', 10, '50.00');
|
||||
$previousPurchase = $this->createCheckoutPurchase($user, 'sonder', $variant, 2);
|
||||
$cart = $previousPurchase->cart;
|
||||
|
||||
$previousPurchase->update([
|
||||
'status' => Purchase::STATUS_PENDING_PAYMENT,
|
||||
'payment_method' => 'transfer',
|
||||
'expires_at' => now()->addMinutes(30),
|
||||
]);
|
||||
|
||||
$currentPurchase = app(CheckoutService::class)->startCheckout(
|
||||
$previousPurchase->tenant,
|
||||
$user->id,
|
||||
['cart_id' => $cart->id],
|
||||
);
|
||||
|
||||
$this->assertDatabaseHas('compras', [
|
||||
'id' => $previousPurchase->id,
|
||||
'status' => Purchase::STATUS_SUPERSEDED,
|
||||
'expires_at' => null,
|
||||
]);
|
||||
$this->assertDatabaseHas('carritos', [
|
||||
'id' => $cart->id,
|
||||
'current_purchase_id' => $currentPurchase->id,
|
||||
]);
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
'purchase_id' => $currentPurchase->id,
|
||||
'quantity' => 2,
|
||||
'status' => 'active',
|
||||
]);
|
||||
|
||||
try {
|
||||
app(CheckoutService::class)->confirmPaidPurchase($previousPurchase->fresh());
|
||||
$this->fail('A superseded purchase was allowed to commit the current reservation.');
|
||||
} catch (ValidationException $exception) {
|
||||
$this->assertArrayHasKey('purchase', $exception->errors());
|
||||
}
|
||||
|
||||
$this->assertDatabaseHas('inventories', [
|
||||
'id' => $variant->inventory_id,
|
||||
'reserved_stock' => 2,
|
||||
'sold_units' => 0,
|
||||
]);
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
'purchase_id' => $currentPurchase->id,
|
||||
'quantity' => 2,
|
||||
'status' => 'active',
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_it_expires_the_purchase_without_mutating_the_active_cart(): void
|
||||
{
|
||||
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||
@@ -511,6 +589,7 @@ class StorePurchaseTest extends TestCase
|
||||
'id' => $activeCart->id,
|
||||
'user_id' => $user->id,
|
||||
'status' => 'active',
|
||||
'current_purchase_id' => null,
|
||||
'deleted_at' => null,
|
||||
]);
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
|
||||
Reference in New Issue
Block a user