feat: Add event association to purchases; implement event relationship in models, update migration, and enhance tests
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace App\Domains\Event\Models;
|
||||
|
||||
use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Purchase\Models\Purchase;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
@@ -38,4 +39,10 @@ class Event extends Model
|
||||
{
|
||||
return $this->hasMany(CatalogItem::class);
|
||||
}
|
||||
|
||||
/** @return HasMany<Purchase, $this> */
|
||||
public function purchases(): HasMany
|
||||
{
|
||||
return $this->hasMany(Purchase::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Domains\Purchase\Models;
|
||||
|
||||
use App\Domains\Auth\Models\User;
|
||||
use App\Domains\Cart\Models\Cart;
|
||||
use App\Domains\Event\Models\Event;
|
||||
use App\Domains\Logging\Models\Concerns\LogsValueChanges;
|
||||
use App\Domains\Purchase\Events\PurchasePaid;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
@@ -19,6 +20,7 @@ use Illuminate\Support\Facades\DB;
|
||||
#[Fillable([
|
||||
'cart_id',
|
||||
'tenant_codigo',
|
||||
'event_id',
|
||||
'user_id',
|
||||
'status',
|
||||
'payment_method',
|
||||
@@ -70,6 +72,7 @@ class Purchase extends Model
|
||||
{
|
||||
return [
|
||||
'cart_id' => 'integer',
|
||||
'event_id' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'expires_at' => 'datetime',
|
||||
'total' => 'decimal:2',
|
||||
@@ -84,6 +87,12 @@ class Purchase extends Model
|
||||
return $this->belongsTo(Tenant::class, 'tenant_codigo', 'codigo');
|
||||
}
|
||||
|
||||
/** @return BelongsTo<Event, $this> */
|
||||
public function event(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Event::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
|
||||
@@ -42,6 +42,7 @@ class PurchaseResource extends JsonResource
|
||||
'id' => $this->id,
|
||||
'cart_id' => $this->cart_id,
|
||||
'tenant_codigo' => $this->tenant_codigo,
|
||||
'event_id' => $this->event_id,
|
||||
'user_id' => $this->user_id,
|
||||
'created_at' => $this->created_at,
|
||||
'status' => $this->status,
|
||||
|
||||
@@ -26,6 +26,11 @@ class CheckoutService
|
||||
public function startCheckout(Tenant $tenant, int $userId, array $purchaseData): Purchase
|
||||
{
|
||||
return DB::transaction(function () use ($tenant, $userId, $purchaseData): Purchase {
|
||||
/** @var Tenant $tenant */
|
||||
$tenant = Tenant::query()
|
||||
->lockForUpdate()
|
||||
->findOrFail($tenant->getKey());
|
||||
|
||||
$directItem = $purchaseData['direct_item'] ?? null;
|
||||
$cartId = isset($purchaseData['cart_id']) ? (int) $purchaseData['cart_id'] : null;
|
||||
unset($purchaseData['direct_item'], $purchaseData['cart_id']);
|
||||
@@ -615,6 +620,7 @@ class CheckoutService
|
||||
...$purchaseData,
|
||||
'cart_id' => $cartId,
|
||||
'tenant_codigo' => $tenant->codigo,
|
||||
'event_id' => $tenant->active_event_id,
|
||||
'user_id' => $userId,
|
||||
'status' => Purchase::STATUS_CREATED,
|
||||
'payment_method' => null,
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('compras', function (Blueprint $table): void {
|
||||
$table->foreignId('event_id')
|
||||
->nullable()
|
||||
->after('tenant_codigo')
|
||||
->constrained('events')
|
||||
->nullOnDelete();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('compras', function (Blueprint $table): void {
|
||||
$table->dropConstrainedForeignId('event_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -11,6 +11,7 @@ use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Catalog\Models\Category;
|
||||
use App\Domains\Catalog\Models\Inventory;
|
||||
use App\Domains\Catalog\Models\Variant;
|
||||
use App\Domains\Event\Models\Event;
|
||||
use App\Domains\Purchase\Models\Purchase;
|
||||
use App\Domains\Purchase\Services\CheckoutService;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
@@ -33,6 +34,12 @@ class StorePurchaseTest extends TestCase
|
||||
public function test_it_creates_an_independent_purchase_snapshot_from_cart(): void
|
||||
{
|
||||
$tenant = $this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||
$event = Event::query()->create([
|
||||
'tenant_code' => $tenant->codigo,
|
||||
'name' => 'Sonder Fest',
|
||||
'address' => 'Test address',
|
||||
]);
|
||||
$tenant->update(['active_event_id' => $event->id]);
|
||||
$user = User::factory()->create([
|
||||
'email' => 'buyer@example.com',
|
||||
]);
|
||||
@@ -85,6 +92,7 @@ class StorePurchaseTest extends TestCase
|
||||
$response->assertJsonPath('data.nombre_apellido', null);
|
||||
$response->assertJsonPath('data.email', null);
|
||||
$response->assertJsonPath('data.tenant_codigo', 'sonder');
|
||||
$response->assertJsonPath('data.event_id', $event->id);
|
||||
$response->assertJsonPath('data.status', Purchase::STATUS_CREATED);
|
||||
$response->assertJsonPath('data.items_source', 'purchase');
|
||||
$response->assertJsonCount(1, 'data.items');
|
||||
@@ -97,6 +105,7 @@ class StorePurchaseTest extends TestCase
|
||||
'id' => $purchaseId,
|
||||
'cart_id' => $cartId,
|
||||
'tenant_codigo' => 'sonder',
|
||||
'event_id' => $event->id,
|
||||
'user_id' => $user->id,
|
||||
'dni' => null,
|
||||
'telefono' => null,
|
||||
|
||||
25
tests/Unit/Forms/SaleFormServiceTest.php
Normal file
25
tests/Unit/Forms/SaleFormServiceTest.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Forms;
|
||||
|
||||
use App\Domains\Forms\Services\SaleFormService;
|
||||
use App\Domains\Purchase\Models\Purchase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SaleFormServiceTest extends TestCase
|
||||
{
|
||||
public function test_it_returns_every_purchase_status_as_a_form_option(): void
|
||||
{
|
||||
$form = (new SaleFormService)->get();
|
||||
|
||||
$this->assertSame(Purchase::statuses(), array_column($form['statuses'], 'code'));
|
||||
$this->assertSame([
|
||||
'Creada',
|
||||
'Esperando pago',
|
||||
'Confirmada',
|
||||
'Cancelada',
|
||||
'Rechazada',
|
||||
'Vencida',
|
||||
], array_column($form['statuses'], 'name'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user