refactor(checkout): materialize purchase items on confirmation
This commit is contained in:
@@ -30,7 +30,7 @@ class StorePurchaseTest extends TestCase
|
||||
Queue::fake();
|
||||
}
|
||||
|
||||
public function test_it_creates_an_independent_purchase_snapshot_from_cart(): void
|
||||
public function test_it_starts_checkout_from_cart_without_materializing_purchase_items(): void
|
||||
{
|
||||
$tenant = $this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||
$tenant->update([
|
||||
@@ -90,7 +90,7 @@ class StorePurchaseTest extends TestCase
|
||||
$response->assertJsonPath('data.email', null);
|
||||
$response->assertJsonPath('data.tenant_codigo', 'sonder');
|
||||
$response->assertJsonPath('data.status', Purchase::STATUS_CREATED);
|
||||
$response->assertJsonPath('data.items_source', 'purchase');
|
||||
$response->assertJsonPath('data.items_source', 'cart');
|
||||
$response->assertJsonCount(1, 'data.items');
|
||||
$response->assertJsonPath('data.subtotal', '100.00');
|
||||
$response->assertJsonPath('data.total', '100.00');
|
||||
@@ -109,12 +109,12 @@ class StorePurchaseTest extends TestCase
|
||||
'status' => Purchase::STATUS_CREATED,
|
||||
'total' => 100,
|
||||
]);
|
||||
$this->assertDatabaseHas('compra_items', [
|
||||
'compra_id' => $purchaseId,
|
||||
'source_catalog_item_id' => $catalogItem->id,
|
||||
'source_variant_id' => $variant->id,
|
||||
'cantidad' => 2,
|
||||
'reservation_status' => 'active',
|
||||
$this->assertDatabaseMissing('compra_items', ['compra_id' => $purchaseId]);
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
'inventory_id' => $inventory->id,
|
||||
'purchase_id' => $purchaseId,
|
||||
'quantity' => 2,
|
||||
'status' => 'active',
|
||||
]);
|
||||
$this->assertDatabaseHas('carritos', [
|
||||
'id' => $cartId,
|
||||
@@ -133,9 +133,22 @@ class StorePurchaseTest extends TestCase
|
||||
'real_stock' => 10,
|
||||
'reserved_stock' => 2,
|
||||
]);
|
||||
|
||||
$catalogItem->update([
|
||||
'nombre' => 'Updated Product',
|
||||
'precio' => '75.00',
|
||||
]);
|
||||
|
||||
$this->actingAs($user, 'sanctum')
|
||||
->getJson("/api/tenants/sonder/compras/{$purchaseId}")
|
||||
->assertOk()
|
||||
->assertJsonPath('data.items_source', 'cart')
|
||||
->assertJsonPath('data.items.0.item_details.nombre', 'Updated Product')
|
||||
->assertJsonPath('data.items.0.unit_price', '75.00')
|
||||
->assertJsonPath('data.total', '150.00');
|
||||
}
|
||||
|
||||
public function test_it_creates_a_direct_purchase_without_creating_or_changing_a_cart(): void
|
||||
public function test_it_creates_a_direct_purchase_with_a_technical_checkout_cart(): void
|
||||
{
|
||||
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||
$user = User::factory()->create();
|
||||
@@ -152,18 +165,23 @@ class StorePurchaseTest extends TestCase
|
||||
],
|
||||
])
|
||||
->assertCreated()
|
||||
->assertJsonPath('data.cart_id', null)
|
||||
->assertJsonPath('data.items_source', 'purchase')
|
||||
->assertJsonPath('data.items_source', 'cart')
|
||||
->assertJsonPath('data.items.0.quantity', 3)
|
||||
->assertJsonPath('data.total', '150.00');
|
||||
|
||||
$this->assertDatabaseCount('carritos', 0);
|
||||
$this->assertDatabaseHas('compra_items', [
|
||||
$this->assertDatabaseHas('carritos', [
|
||||
'id' => $response->json('data.cart_id'),
|
||||
'status' => 'checkout',
|
||||
'origin' => Cart::ORIGIN_DIRECT_CHECKOUT,
|
||||
]);
|
||||
$this->assertDatabaseMissing('compra_items', [
|
||||
'compra_id' => $response->json('data.id'),
|
||||
'source_catalog_item_id' => $variant->catalog_item_id,
|
||||
'source_variant_id' => $variant->id,
|
||||
'cantidad' => 3,
|
||||
'reservation_status' => 'active',
|
||||
]);
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
'inventory_id' => $variant->inventory_id,
|
||||
'purchase_id' => $response->json('data.id'),
|
||||
'quantity' => 3,
|
||||
'status' => 'active',
|
||||
]);
|
||||
$this->assertDatabaseHas('inventories', [
|
||||
'id' => $variant->inventory_id,
|
||||
@@ -176,9 +194,9 @@ class StorePurchaseTest extends TestCase
|
||||
->assertOk()
|
||||
->assertJsonPath('data.status', Purchase::STATUS_CANCELLED);
|
||||
|
||||
$this->assertDatabaseHas('compra_items', [
|
||||
'compra_id' => $response->json('data.id'),
|
||||
'reservation_status' => 'released',
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
'purchase_id' => $response->json('data.id'),
|
||||
'status' => 'released',
|
||||
]);
|
||||
$this->assertDatabaseHas('inventories', [
|
||||
'id' => $variant->inventory_id,
|
||||
@@ -215,7 +233,7 @@ class StorePurchaseTest extends TestCase
|
||||
],
|
||||
])
|
||||
->assertCreated()
|
||||
->assertJsonPath('data.cart_id', null)
|
||||
->assertJsonPath('data.items_source', 'cart')
|
||||
->assertJsonCount(2, 'data.items')
|
||||
->assertJsonPath('data.items.0.source_variant_id', $firstVariant->id)
|
||||
->assertJsonPath('data.items.1.source_variant_id', $secondVariant->id)
|
||||
@@ -223,18 +241,22 @@ class StorePurchaseTest extends TestCase
|
||||
|
||||
$purchaseId = $response->json('data.id');
|
||||
|
||||
$this->assertDatabaseCount('carritos', 0);
|
||||
$this->assertDatabaseHas('compra_items', [
|
||||
'compra_id' => $purchaseId,
|
||||
'source_variant_id' => $firstVariant->id,
|
||||
'cantidad' => 1,
|
||||
'reservation_status' => 'active',
|
||||
$this->assertDatabaseHas('carritos', [
|
||||
'id' => $response->json('data.cart_id'),
|
||||
'origin' => Cart::ORIGIN_DIRECT_CHECKOUT,
|
||||
]);
|
||||
$this->assertDatabaseHas('compra_items', [
|
||||
'compra_id' => $purchaseId,
|
||||
'source_variant_id' => $secondVariant->id,
|
||||
'cantidad' => 1,
|
||||
'reservation_status' => 'active',
|
||||
$this->assertDatabaseMissing('compra_items', ['compra_id' => $purchaseId]);
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
'inventory_id' => $firstVariant->inventory_id,
|
||||
'purchase_id' => $purchaseId,
|
||||
'quantity' => 1,
|
||||
'status' => 'active',
|
||||
]);
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
'inventory_id' => $secondVariant->inventory_id,
|
||||
'purchase_id' => $purchaseId,
|
||||
'quantity' => 1,
|
||||
'status' => 'active',
|
||||
]);
|
||||
$this->assertDatabaseHas('inventories', [
|
||||
'id' => $firstVariant->inventory_id,
|
||||
@@ -462,7 +484,7 @@ class StorePurchaseTest extends TestCase
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_it_creates_purchase_items_before_checkout_and_updates_customer_data(): void
|
||||
public function test_it_keeps_cart_items_during_checkout_and_updates_customer_data(): void
|
||||
{
|
||||
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||
$user = User::factory()->create();
|
||||
@@ -479,7 +501,7 @@ class StorePurchaseTest extends TestCase
|
||||
],
|
||||
])
|
||||
->assertCreated()
|
||||
->assertJsonPath('data.items_source', 'purchase')
|
||||
->assertJsonPath('data.items_source', 'cart')
|
||||
->assertJsonCount(1, 'data.items')
|
||||
->assertJsonPath('data.items.0.quantity', 2)
|
||||
->assertJsonPath('data.dni', null)
|
||||
@@ -543,7 +565,7 @@ class StorePurchaseTest extends TestCase
|
||||
$user = User::factory()->create();
|
||||
$variant = $this->createVariantForTenant('sonder', 10, '50.00');
|
||||
$purchase = $this->createCheckoutPurchase($user, 'sonder', $variant, 2);
|
||||
$itemId = $purchase->items->firstOrFail()->id;
|
||||
$itemId = $purchase->cart->items->firstOrFail()->id;
|
||||
|
||||
$this->actingAs($user, 'sanctum')
|
||||
->patchJson("/api/tenants/sonder/compras/{$purchase->id}/items/{$itemId}", [
|
||||
@@ -587,7 +609,7 @@ class StorePurchaseTest extends TestCase
|
||||
$variant = $this->createVariantForTenant('sonder', 10, '50.00');
|
||||
$variant->catalogItem->update(['max_units_per_user' => 3]);
|
||||
$purchase = $this->createCheckoutPurchase($user, 'sonder', $variant, 2);
|
||||
$itemId = $purchase->items->firstOrFail()->id;
|
||||
$itemId = $purchase->cart->items->firstOrFail()->id;
|
||||
|
||||
$this->actingAs($user, 'sanctum')
|
||||
->patchJson("/api/tenants/sonder/compras/{$purchase->id}/items/{$itemId}", [
|
||||
@@ -596,7 +618,7 @@ class StorePurchaseTest extends TestCase
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors('quantity');
|
||||
|
||||
$this->assertDatabaseHas('compra_items', [
|
||||
$this->assertDatabaseHas('carrito_items', [
|
||||
'id' => $itemId,
|
||||
'cantidad' => 2,
|
||||
]);
|
||||
@@ -797,9 +819,11 @@ class StorePurchaseTest extends TestCase
|
||||
'id' => $purchase->id,
|
||||
'status' => Purchase::STATUS_EXPIRED,
|
||||
]);
|
||||
$this->assertDatabaseHas('compra_items', [
|
||||
'compra_id' => $purchase->id,
|
||||
'reservation_status' => 'released',
|
||||
$this->assertDatabaseMissing('compra_items', ['compra_id' => $purchase->id]);
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
'purchase_id' => null,
|
||||
'quantity' => 3,
|
||||
'status' => 'active',
|
||||
]);
|
||||
$this->assertDatabaseHas('inventories', [
|
||||
'id' => $variant->inventory_id,
|
||||
@@ -819,7 +843,7 @@ class StorePurchaseTest extends TestCase
|
||||
->assertSuccessful();
|
||||
}
|
||||
|
||||
public function test_purchase_detail_uses_purchase_items_for_created_purchase(): void
|
||||
public function test_purchase_detail_uses_cart_items_for_created_purchase(): void
|
||||
{
|
||||
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||
$user = User::factory()->create([
|
||||
@@ -832,7 +856,7 @@ class StorePurchaseTest extends TestCase
|
||||
->getJson("/api/tenants/sonder/compras/{$purchase->id}")
|
||||
->assertOk()
|
||||
->assertJsonPath('data.status', Purchase::STATUS_CREATED)
|
||||
->assertJsonPath('data.items_source', 'purchase')
|
||||
->assertJsonPath('data.items_source', 'cart')
|
||||
->assertJsonCount(1, 'data.items')
|
||||
->assertJsonPath('data.items.0.quantity', 2)
|
||||
->assertJsonPath('data.items.0.unit_price', '50.00')
|
||||
@@ -863,7 +887,7 @@ class StorePurchaseTest extends TestCase
|
||||
'type' => AttachmentType::Image,
|
||||
'mime_type' => 'image/png',
|
||||
]);
|
||||
$purchase->items()->firstOrFail()->update(['image_attachment_id' => $image->id]);
|
||||
$variant->catalogItem->attachments()->attach($image->id, ['orden' => 0]);
|
||||
|
||||
$this->actingAs($user, 'sanctum')
|
||||
->getJson("/api/tenants/sonder/compras/{$purchase->id}")
|
||||
@@ -871,7 +895,7 @@ class StorePurchaseTest extends TestCase
|
||||
->assertJsonPath('data.items.0.item_details.imagen', null);
|
||||
}
|
||||
|
||||
public function test_purchase_detail_uses_purchase_items_for_pending_payment_purchase(): void
|
||||
public function test_purchase_detail_uses_cart_items_for_pending_payment_purchase(): void
|
||||
{
|
||||
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||
$user = User::factory()->create([
|
||||
@@ -890,7 +914,7 @@ class StorePurchaseTest extends TestCase
|
||||
->getJson("/api/tenants/sonder/compras/{$purchase->id}")
|
||||
->assertOk()
|
||||
->assertJsonPath('data.status', Purchase::STATUS_PENDING_PAYMENT)
|
||||
->assertJsonPath('data.items_source', 'purchase')
|
||||
->assertJsonPath('data.items_source', 'cart')
|
||||
->assertJsonCount(1, 'data.items')
|
||||
->assertJsonPath('data.items.0.quantity', 2)
|
||||
->assertJsonPath('data.items.0.unit_price', '50.00')
|
||||
@@ -925,6 +949,12 @@ class StorePurchaseTest extends TestCase
|
||||
'reserved_stock' => 0,
|
||||
'sold_units' => 2,
|
||||
]);
|
||||
$this->assertDatabaseHas('stock_reservations', [
|
||||
'purchase_id' => $purchase->id,
|
||||
'inventory_id' => $variant->inventory_id,
|
||||
'quantity' => 2,
|
||||
'status' => 'committed',
|
||||
]);
|
||||
|
||||
$this->assertSoftDeleted('carritos', [
|
||||
'id' => $purchase->cart_id,
|
||||
@@ -956,7 +986,9 @@ class StorePurchaseTest extends TestCase
|
||||
$variant = $this->createVariantForTenant('sonder', 10, '50.00');
|
||||
$purchase = $this->createCheckoutPurchase($user, 'sonder', $variant, 2);
|
||||
|
||||
$purchase->update(['cart_id' => null]);
|
||||
$purchase->update(['payment_method' => 'transfer']);
|
||||
app(CheckoutService::class)->confirmPurchase($purchase);
|
||||
$purchase->refresh()->update(['cart_id' => null]);
|
||||
|
||||
$this->actingAs($user, 'sanctum')
|
||||
->getJson("/api/tenants/sonder/compras/{$purchase->id}")
|
||||
|
||||
Reference in New Issue
Block a user