feat: enhance purchase detail handling to support cart items and improve resource structure
This commit is contained in:
@@ -19,7 +19,6 @@ class PurchaseController extends Controller
|
|||||||
{
|
{
|
||||||
return PurchaseResource::collection(
|
return PurchaseResource::collection(
|
||||||
Purchase::query()
|
Purchase::query()
|
||||||
->with(['items.variant.product', 'items.variant.definitions.productAttribute.attribute'])
|
|
||||||
->where('tenant_codigo', $tenant->codigo)
|
->where('tenant_codigo', $tenant->codigo)
|
||||||
->where('user_id', $request->user()->id)
|
->where('user_id', $request->user()->id)
|
||||||
->when($request->query('status'), function ($query, $status) {
|
->when($request->query('status'), function ($query, $status) {
|
||||||
@@ -48,7 +47,7 @@ class PurchaseController extends Controller
|
|||||||
$compra = $this->resolveScopedPurchase($tenant, $request->user()->id, $compra);
|
$compra = $this->resolveScopedPurchase($tenant, $request->user()->id, $compra);
|
||||||
|
|
||||||
return PurchaseResource::make(
|
return PurchaseResource::make(
|
||||||
$compra->loadMissing(['items.variant.product', 'items.variant.definitions.productAttribute.attribute'])
|
$compra->loadMissing($this->purchaseDetailRelations())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,4 +139,19 @@ class PurchaseController extends Controller
|
|||||||
|
|
||||||
return $purchase;
|
return $purchase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
protected function purchaseDetailRelations(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'items.variant.product',
|
||||||
|
'items.variant.definitions.productAttribute.attribute',
|
||||||
|
'items.variant.attachments',
|
||||||
|
'cart.items.variant.product',
|
||||||
|
'cart.items.variant.definitions.productAttribute.attribute',
|
||||||
|
'cart.items.variant.attachments',
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Domains\Purchase\Resources;
|
namespace App\Domains\Purchase\Resources;
|
||||||
|
|
||||||
use App\Domains\Catalog\Resources\ProductVariantDefinitionResource;
|
use App\Domains\Cart\Models\CartItem;
|
||||||
|
use App\Domains\Purchase\Models\PurchaseItem;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @mixin \App\Domains\Purchase\Models\PurchaseItem
|
* @mixin \App\Domains\Purchase\Models\PurchaseItem|\App\Domains\Cart\Models\CartItem
|
||||||
*/
|
*/
|
||||||
class PurchaseItemResource extends JsonResource
|
class PurchaseItemResource extends JsonResource
|
||||||
{
|
{
|
||||||
@@ -18,24 +19,90 @@ class PurchaseItemResource extends JsonResource
|
|||||||
{
|
{
|
||||||
$variant = $this->variant;
|
$variant = $this->variant;
|
||||||
$product = $variant?->product;
|
$product = $variant?->product;
|
||||||
|
$quantity = (int) ($this->cantidad ?? 0);
|
||||||
|
$unitPrice = $this->resolveUnitPrice();
|
||||||
|
$lineTotal = $this->resolveLineTotal($unitPrice, $quantity);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'cantidad' => $this->cantidad,
|
'quantity' => $quantity,
|
||||||
'precio_unitario' => $this->formatMoney($this->precio_unitario),
|
'unit_price' => $this->formatMoney($unitPrice),
|
||||||
'total' => $this->formatMoney($this->total),
|
'line_total' => $this->formatMoney($lineTotal),
|
||||||
'product' => $product === null ? null : [
|
'product' => $product === null ? null : [
|
||||||
'id' => $product->id,
|
'id' => $product->id,
|
||||||
'nombre' => $product->nombre,
|
'nombre' => $product->nombre,
|
||||||
'slug' => $product->slug,
|
'slug' => $product->slug,
|
||||||
|
'imagen' => $this->resolveImageUrl(),
|
||||||
],
|
],
|
||||||
'variant' => $variant === null ? null : [
|
'variant' => $variant === null ? null : [
|
||||||
'id' => $variant->id,
|
'id' => $variant->id,
|
||||||
'definitions' => ProductVariantDefinitionResource::collection($variant->definitions),
|
'attributes' => $this->resolveAttributes(),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function resolveUnitPrice(): float
|
||||||
|
{
|
||||||
|
if ($this->resource instanceof PurchaseItem) {
|
||||||
|
return (float) ($this->precio_unitario ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->resource instanceof CartItem) {
|
||||||
|
return (float) ($this->variant?->product?->precio ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resolveLineTotal(float $unitPrice, int $quantity): float
|
||||||
|
{
|
||||||
|
if ($this->resource instanceof PurchaseItem) {
|
||||||
|
return (float) ($this->total ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $unitPrice * $quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resolveImageUrl(): ?string
|
||||||
|
{
|
||||||
|
$variant = $this->variant;
|
||||||
|
|
||||||
|
if ($variant === null || ! $variant->relationLoaded('attachments')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attachment = $variant->attachments->first();
|
||||||
|
|
||||||
|
if ($attachment === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $attachment->getTemporaryUrl(1440);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, value: mixed}>
|
||||||
|
*/
|
||||||
|
protected function resolveAttributes(): array
|
||||||
|
{
|
||||||
|
$variant = $this->variant;
|
||||||
|
|
||||||
|
if ($variant === null || ! $variant->relationLoaded('definitions')) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $variant->definitions
|
||||||
|
->map(function ($definition): array {
|
||||||
|
return [
|
||||||
|
'name' => (string) ($definition->productAttribute?->attribute?->nombre ?? ''),
|
||||||
|
'value' => $definition->value,
|
||||||
|
];
|
||||||
|
})
|
||||||
|
->filter(fn (array $attribute): bool => $attribute['name'] !== '' || $attribute['value'] !== null)
|
||||||
|
->values()
|
||||||
|
->all();
|
||||||
|
}
|
||||||
|
|
||||||
protected function formatMoney(float|int|string|null $amount): ?string
|
protected function formatMoney(float|int|string|null $amount): ?string
|
||||||
{
|
{
|
||||||
if ($amount === null) {
|
if ($amount === null) {
|
||||||
|
|||||||
@@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Domains\Purchase\Resources;
|
namespace App\Domains\Purchase\Resources;
|
||||||
|
|
||||||
|
use App\Domains\Cart\Models\CartItem;
|
||||||
|
use App\Domains\Purchase\Models\PurchaseItem;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @mixin \App\Domains\Purchase\Models\Purchase
|
* @mixin \App\Domains\Purchase\Models\Purchase
|
||||||
@@ -15,20 +18,18 @@ class PurchaseResource extends JsonResource
|
|||||||
*/
|
*/
|
||||||
public function toArray(Request $request): array
|
public function toArray(Request $request): array
|
||||||
{
|
{
|
||||||
$items = $this->resource->relationLoaded('items')
|
[$items, $itemsSource] = $this->resolveItems();
|
||||||
? $this->resource->getRelation('items')
|
|
||||||
: collect();
|
|
||||||
|
|
||||||
$subtotal = $items->isNotEmpty()
|
$subtotal = $items->isNotEmpty()
|
||||||
? $items->reduce(
|
? $items->reduce(
|
||||||
fn (float $carry, $item): float => $carry + ((float) $item->precio_unitario * $item->cantidad),
|
fn (float $carry, PurchaseItem|CartItem $item): float => $carry + $this->resolveItemSubtotal($item),
|
||||||
0.0,
|
0.0,
|
||||||
)
|
)
|
||||||
: (float) ($this->total ?? 0);
|
: (float) ($this->total ?? 0);
|
||||||
|
|
||||||
$total = $items->isNotEmpty()
|
$total = $items->isNotEmpty()
|
||||||
? $items->reduce(
|
? $items->reduce(
|
||||||
fn (float $carry, $item): float => $carry + (float) $item->total,
|
fn (float $carry, PurchaseItem|CartItem $item): float => $carry + $this->resolveItemTotal($item),
|
||||||
0.0,
|
0.0,
|
||||||
)
|
)
|
||||||
: (float) ($this->total ?? 0);
|
: (float) ($this->total ?? 0);
|
||||||
@@ -38,18 +39,66 @@ class PurchaseResource extends JsonResource
|
|||||||
'cart_id' => $this->cart_id,
|
'cart_id' => $this->cart_id,
|
||||||
'tenant_codigo' => $this->tenant_codigo,
|
'tenant_codigo' => $this->tenant_codigo,
|
||||||
'user_id' => $this->user_id,
|
'user_id' => $this->user_id,
|
||||||
|
'created_at' => $this->created_at,
|
||||||
'status' => $this->status,
|
'status' => $this->status,
|
||||||
'payment_method' => $this->payment_method,
|
'payment_method' => $this->payment_method,
|
||||||
'dni' => $this->dni,
|
'dni' => $this->dni,
|
||||||
'telefono' => $this->telefono,
|
'telefono' => $this->telefono,
|
||||||
'nombre_apellido' => $this->nombre_apellido,
|
'nombre_apellido' => $this->nombre_apellido,
|
||||||
'email' => $this->email,
|
'email' => $this->email,
|
||||||
|
'items_source' => $itemsSource,
|
||||||
'items' => PurchaseItemResource::collection($items),
|
'items' => PurchaseItemResource::collection($items),
|
||||||
'subtotal' => $this->formatMoney($subtotal),
|
'subtotal' => $this->formatMoney($subtotal),
|
||||||
'total' => $this->formatMoney($total),
|
'total' => $this->formatMoney($total),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{0: Collection<int, PurchaseItem|CartItem>, 1: string|null}
|
||||||
|
*/
|
||||||
|
protected function resolveItems(): array
|
||||||
|
{
|
||||||
|
if (! $this->resource->relationLoaded('items')) {
|
||||||
|
return [collect(), null];
|
||||||
|
}
|
||||||
|
|
||||||
|
$purchaseItems = $this->resource->getRelation('items');
|
||||||
|
|
||||||
|
if ($purchaseItems->isNotEmpty()) {
|
||||||
|
return [$purchaseItems, 'purchase'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $this->resource->relationLoaded('cart')) {
|
||||||
|
return [collect(), null];
|
||||||
|
}
|
||||||
|
|
||||||
|
$cart = $this->resource->getRelation('cart');
|
||||||
|
|
||||||
|
if ($cart === null || ! $cart->relationLoaded('items')) {
|
||||||
|
return [collect(), null];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$cart->getRelation('items'), 'cart'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resolveItemSubtotal(PurchaseItem|CartItem $item): float
|
||||||
|
{
|
||||||
|
if ($item instanceof PurchaseItem) {
|
||||||
|
return (float) $item->precio_unitario * $item->cantidad;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (float) ($item->variant?->product?->precio ?? 0) * $item->cantidad;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resolveItemTotal(PurchaseItem|CartItem $item): float
|
||||||
|
{
|
||||||
|
if ($item instanceof PurchaseItem) {
|
||||||
|
return (float) ($item->total ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->resolveItemSubtotal($item);
|
||||||
|
}
|
||||||
|
|
||||||
protected function formatMoney(float|int|string|null $amount): string
|
protected function formatMoney(float|int|string|null $amount): string
|
||||||
{
|
{
|
||||||
return number_format((float) ($amount ?? 0), 2, '.', '');
|
return number_format((float) ($amount ?? 0), 2, '.', '');
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use App\Domains\Cart\Models\Cart;
|
|||||||
use App\Domains\Catalog\Models\Product;
|
use App\Domains\Catalog\Models\Product;
|
||||||
use App\Domains\Catalog\Models\ProductVariant;
|
use App\Domains\Catalog\Models\ProductVariant;
|
||||||
use App\Domains\Purchase\Models\Purchase;
|
use App\Domains\Purchase\Models\Purchase;
|
||||||
|
use App\Domains\Purchase\Services\CheckoutService;
|
||||||
use App\Domains\Tenant\Models\Tenant;
|
use App\Domains\Tenant\Models\Tenant;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
@@ -76,6 +77,7 @@ class StorePurchaseTest extends TestCase
|
|||||||
$response->assertJsonPath('data.email', 'juan.perez@example.com');
|
$response->assertJsonPath('data.email', 'juan.perez@example.com');
|
||||||
$response->assertJsonPath('data.tenant_codigo', 'sonder');
|
$response->assertJsonPath('data.tenant_codigo', 'sonder');
|
||||||
$response->assertJsonPath('data.status', Purchase::STATUS_CREATED);
|
$response->assertJsonPath('data.status', Purchase::STATUS_CREATED);
|
||||||
|
$response->assertJsonPath('data.items_source', null);
|
||||||
$response->assertJsonPath('data.items', []);
|
$response->assertJsonPath('data.items', []);
|
||||||
$response->assertJsonPath('data.subtotal', '100.00');
|
$response->assertJsonPath('data.subtotal', '100.00');
|
||||||
$response->assertJsonPath('data.total', '100.00');
|
$response->assertJsonPath('data.total', '100.00');
|
||||||
@@ -159,6 +161,150 @@ class StorePurchaseTest extends TestCase
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_purchase_detail_uses_cart_items_for_created_purchase(): void
|
||||||
|
{
|
||||||
|
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||||
|
$user = User::factory()->create([
|
||||||
|
'email' => 'buyer@example.com',
|
||||||
|
]);
|
||||||
|
$variant = $this->createVariantForTenant('sonder', 10, '50.00');
|
||||||
|
$purchase = $this->createCheckoutPurchase($user, 'sonder', $variant, 2);
|
||||||
|
|
||||||
|
$this->actingAs($user, 'sanctum')
|
||||||
|
->getJson("/api/tenants/sonder/compras/{$purchase->id}")
|
||||||
|
->assertOk()
|
||||||
|
->assertJsonPath('data.status', Purchase::STATUS_CREATED)
|
||||||
|
->assertJsonPath('data.items_source', 'cart')
|
||||||
|
->assertJsonCount(1, 'data.items')
|
||||||
|
->assertJsonPath('data.items.0.quantity', 2)
|
||||||
|
->assertJsonPath('data.items.0.unit_price', '50.00')
|
||||||
|
->assertJsonPath('data.items.0.line_total', '100.00')
|
||||||
|
->assertJsonPath('data.items.0.product.id', $variant->product->id)
|
||||||
|
->assertJsonPath('data.items.0.product.nombre', $variant->product->nombre)
|
||||||
|
->assertJsonPath('data.items.0.product.slug', $variant->product->slug)
|
||||||
|
->assertJsonPath('data.items.0.product.imagen', null)
|
||||||
|
->assertJsonPath('data.items.0.variant.id', $variant->id)
|
||||||
|
->assertJsonPath('data.items.0.variant.attributes', [])
|
||||||
|
->assertJsonPath('data.subtotal', '100.00')
|
||||||
|
->assertJsonPath('data.total', '100.00');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_purchase_detail_uses_cart_items_for_pending_payment_purchase(): void
|
||||||
|
{
|
||||||
|
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||||
|
$user = User::factory()->create([
|
||||||
|
'email' => 'buyer@example.com',
|
||||||
|
]);
|
||||||
|
$variant = $this->createVariantForTenant('sonder', 10, '50.00');
|
||||||
|
$purchase = $this->createCheckoutPurchase($user, 'sonder', $variant, 2);
|
||||||
|
|
||||||
|
$purchase->update([
|
||||||
|
'payment_method' => 'transfer',
|
||||||
|
]);
|
||||||
|
|
||||||
|
app(CheckoutService::class)->completePurchase($purchase);
|
||||||
|
|
||||||
|
$this->actingAs($user, 'sanctum')
|
||||||
|
->getJson("/api/tenants/sonder/compras/{$purchase->id}")
|
||||||
|
->assertOk()
|
||||||
|
->assertJsonPath('data.status', Purchase::STATUS_PENDING_PAYMENT)
|
||||||
|
->assertJsonPath('data.items_source', 'cart')
|
||||||
|
->assertJsonCount(1, 'data.items')
|
||||||
|
->assertJsonPath('data.items.0.quantity', 2)
|
||||||
|
->assertJsonPath('data.items.0.unit_price', '50.00')
|
||||||
|
->assertJsonPath('data.items.0.line_total', '100.00')
|
||||||
|
->assertJsonPath('data.items.0.product.imagen', null)
|
||||||
|
->assertJsonPath('data.items.0.variant.attributes', [])
|
||||||
|
->assertJsonPath('data.subtotal', '100.00')
|
||||||
|
->assertJsonPath('data.total', '100.00');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_purchase_detail_uses_purchase_items_for_paid_purchase_even_without_cart(): void
|
||||||
|
{
|
||||||
|
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||||
|
$user = User::factory()->create([
|
||||||
|
'email' => 'buyer@example.com',
|
||||||
|
]);
|
||||||
|
$variant = $this->createVariantForTenant('sonder', 10, '50.00');
|
||||||
|
$purchase = $this->createCheckoutPurchase($user, 'sonder', $variant, 2);
|
||||||
|
|
||||||
|
$purchase->update([
|
||||||
|
'payment_method' => 'transfer',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$checkoutService = app(CheckoutService::class);
|
||||||
|
$purchase = $checkoutService->completePurchase($purchase);
|
||||||
|
$checkoutService->confirmPurchase($purchase);
|
||||||
|
$purchase->refresh()->markAsPaid();
|
||||||
|
|
||||||
|
$this->assertSoftDeleted('carritos', [
|
||||||
|
'id' => $purchase->cart_id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->actingAs($user, 'sanctum')
|
||||||
|
->getJson("/api/tenants/sonder/compras/{$purchase->id}")
|
||||||
|
->assertOk()
|
||||||
|
->assertJsonPath('data.status', Purchase::STATUS_PAID)
|
||||||
|
->assertJsonPath('data.items_source', 'purchase')
|
||||||
|
->assertJsonCount(1, 'data.items')
|
||||||
|
->assertJsonPath('data.items.0.quantity', 2)
|
||||||
|
->assertJsonPath('data.items.0.unit_price', '50.00')
|
||||||
|
->assertJsonPath('data.items.0.line_total', '100.00')
|
||||||
|
->assertJsonPath('data.items.0.product.id', $variant->product->id)
|
||||||
|
->assertJsonPath('data.items.0.product.imagen', null)
|
||||||
|
->assertJsonPath('data.items.0.variant.id', $variant->id)
|
||||||
|
->assertJsonPath('data.items.0.variant.attributes', [])
|
||||||
|
->assertJsonPath('data.subtotal', '100.00')
|
||||||
|
->assertJsonPath('data.total', '100.00');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_purchase_detail_prefers_purchase_items_when_both_sources_exist(): void
|
||||||
|
{
|
||||||
|
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||||
|
$user = User::factory()->create([
|
||||||
|
'email' => 'buyer@example.com',
|
||||||
|
]);
|
||||||
|
$variant = $this->createVariantForTenant('sonder', 10, '50.00');
|
||||||
|
$purchase = $this->createCheckoutPurchase($user, 'sonder', $variant, 2);
|
||||||
|
|
||||||
|
$purchase->items()->create([
|
||||||
|
'producto_variante_id' => $variant->id,
|
||||||
|
'cantidad' => 1,
|
||||||
|
'precio_unitario' => '50.00',
|
||||||
|
'discount_total' => null,
|
||||||
|
'tax_total' => null,
|
||||||
|
'total' => '50.00',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->actingAs($user, 'sanctum')
|
||||||
|
->getJson("/api/tenants/sonder/compras/{$purchase->id}")
|
||||||
|
->assertOk()
|
||||||
|
->assertJsonPath('data.items_source', 'purchase')
|
||||||
|
->assertJsonCount(1, 'data.items')
|
||||||
|
->assertJsonPath('data.items.0.quantity', 1)
|
||||||
|
->assertJsonPath('data.items.0.line_total', '50.00')
|
||||||
|
->assertJsonPath('data.subtotal', '50.00')
|
||||||
|
->assertJsonPath('data.total', '50.00');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_purchase_index_returns_empty_items_without_loaded_relations(): void
|
||||||
|
{
|
||||||
|
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||||
|
$user = User::factory()->create([
|
||||||
|
'email' => 'buyer@example.com',
|
||||||
|
]);
|
||||||
|
$variant = $this->createVariantForTenant('sonder', 10, '50.00');
|
||||||
|
$this->createCheckoutPurchase($user, 'sonder', $variant, 2);
|
||||||
|
|
||||||
|
$this->actingAs($user, 'sanctum')
|
||||||
|
->getJson('/api/tenants/sonder/compras?status=created')
|
||||||
|
->assertOk()
|
||||||
|
->assertJsonCount(1, 'data')
|
||||||
|
->assertJsonPath('data.0.items_source', null)
|
||||||
|
->assertJsonPath('data.0.items', [])
|
||||||
|
->assertJsonPath('data.0.total', '100.00');
|
||||||
|
}
|
||||||
|
|
||||||
public function test_it_rejects_a_cart_from_another_user(): void
|
public function test_it_rejects_a_cart_from_another_user(): void
|
||||||
{
|
{
|
||||||
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
$this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||||
@@ -290,6 +436,30 @@ class StorePurchaseTest extends TestCase
|
|||||||
])->load('product');
|
])->load('product');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function createCheckoutPurchase(
|
||||||
|
User $user,
|
||||||
|
string $tenantCode,
|
||||||
|
ProductVariant $variant,
|
||||||
|
int $quantity,
|
||||||
|
): Purchase {
|
||||||
|
$tenant = Tenant::query()->where('codigo', $tenantCode)->firstOrFail();
|
||||||
|
$cart = Cart::query()->create([
|
||||||
|
'tenant_codigo' => $tenantCode,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'status' => 'active',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cart->addItem($variant->id, $quantity);
|
||||||
|
|
||||||
|
return app(CheckoutService::class)->startCheckout($tenant, $user->id, [
|
||||||
|
'cart_id' => $cart->id,
|
||||||
|
'dni' => '987654321',
|
||||||
|
'telefono' => '+54 9 341 555-4321',
|
||||||
|
'nombre_apellido' => 'Juan Perez',
|
||||||
|
'email' => 'juan.perez@example.com',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
protected function createTenant(string $codigo, string $nombre, string $dominio): Tenant
|
protected function createTenant(string $codigo, string $nombre, string $dominio): Tenant
|
||||||
{
|
{
|
||||||
$hdrKey = (string) \Illuminate\Support\Str::uuid();
|
$hdrKey = (string) \Illuminate\Support\Str::uuid();
|
||||||
|
|||||||
Reference in New Issue
Block a user