feat(purchase): add checkout expiration settings and reservation status to purchase items
- Introduced a new configuration file for purchase settings, including checkout and payment expiration times. - Added a migration to include a `reservation_status` column in the `compra_items` table, defaulting to 'active' and updating existing records based on purchase status. - Created a migration to add an `expires_at` timestamp to the `compras` table, updating it for existing records based on their status. - Scoped unique indexes in the `carritos` table to only active carts, adding virtual columns for active user and guest tokens. - Implemented a console command to expire overdue purchases and release stock reservations, scheduled to run every minute. - Added tests for Google token exchange and login functionality, ensuring proper cart handling and user authentication. - Updated purchase-related tests to reflect changes in item handling and customer data validation.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('compra_items', function (Blueprint $table): void {
|
||||
$table->string('reservation_status')
|
||||
->default('active')
|
||||
->after('total');
|
||||
});
|
||||
|
||||
DB::table('compra_items')
|
||||
->whereIn('compra_id', DB::table('compras')->where('status', 'paid')->select('id'))
|
||||
->update(['reservation_status' => 'committed']);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('compra_items', function (Blueprint $table): void {
|
||||
$table->dropColumn('reservation_status');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('compras', function (Blueprint $table): void {
|
||||
$table->timestamp('expires_at')->nullable()->index()->after('payment_method');
|
||||
});
|
||||
|
||||
DB::table('compras')
|
||||
->whereIn('status', ['created', 'pending_payment'])
|
||||
->whereNull('expires_at')
|
||||
->update([
|
||||
'expires_at' => now()->addMinutes(
|
||||
max(1, (int) config('purchase.checkout_expiration_minutes', 30)),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('compras', function (Blueprint $table): void {
|
||||
$table->dropColumn('expires_at');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// MySQL may use one of the old composite unique indexes to support the
|
||||
// tenant foreign key. Give that foreign key its own index before the
|
||||
// unique indexes are removed.
|
||||
Schema::whenTableDoesntHaveIndex(
|
||||
'carritos',
|
||||
'carritos_tenant_codigo_index',
|
||||
fn (Blueprint $table) => $table->index(
|
||||
'tenant_codigo',
|
||||
'carritos_tenant_codigo_index',
|
||||
),
|
||||
);
|
||||
|
||||
Schema::whenTableHasIndex(
|
||||
'carritos',
|
||||
'carritos_tenant_codigo_user_id_unique',
|
||||
fn (Blueprint $table) => $table->dropUnique(
|
||||
'carritos_tenant_codigo_user_id_unique',
|
||||
),
|
||||
);
|
||||
Schema::whenTableHasIndex(
|
||||
'carritos',
|
||||
'carritos_tenant_codigo_guest_token_unique',
|
||||
fn (Blueprint $table) => $table->dropUnique(
|
||||
'carritos_tenant_codigo_guest_token_unique',
|
||||
),
|
||||
);
|
||||
|
||||
Schema::whenTableDoesntHaveColumn('carritos', 'active_user_id', function (Blueprint $table): void {
|
||||
$table->unsignedBigInteger('active_user_id')
|
||||
->virtualAs("CASE WHEN status = 'active' AND deleted_at IS NULL THEN user_id ELSE NULL END");
|
||||
});
|
||||
Schema::whenTableDoesntHaveColumn('carritos', 'active_guest_token', function (Blueprint $table): void {
|
||||
$table->string('active_guest_token')
|
||||
->virtualAs("CASE WHEN status = 'active' AND deleted_at IS NULL THEN guest_token ELSE NULL END");
|
||||
});
|
||||
|
||||
Schema::whenTableDoesntHaveIndex(
|
||||
'carritos',
|
||||
'carritos_tenant_active_user_unique',
|
||||
fn (Blueprint $table) => $table->unique(
|
||||
['tenant_codigo', 'active_user_id'],
|
||||
'carritos_tenant_active_user_unique',
|
||||
),
|
||||
);
|
||||
Schema::whenTableDoesntHaveIndex(
|
||||
'carritos',
|
||||
'carritos_tenant_active_guest_unique',
|
||||
fn (Blueprint $table) => $table->unique(
|
||||
['tenant_codigo', 'active_guest_token'],
|
||||
'carritos_tenant_active_guest_unique',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::whenTableHasIndex(
|
||||
'carritos',
|
||||
'carritos_tenant_active_user_unique',
|
||||
fn (Blueprint $table) => $table->dropUnique(
|
||||
'carritos_tenant_active_user_unique',
|
||||
),
|
||||
);
|
||||
Schema::whenTableHasIndex(
|
||||
'carritos',
|
||||
'carritos_tenant_active_guest_unique',
|
||||
fn (Blueprint $table) => $table->dropUnique(
|
||||
'carritos_tenant_active_guest_unique',
|
||||
),
|
||||
);
|
||||
|
||||
Schema::whenTableHasColumn(
|
||||
'carritos',
|
||||
'active_user_id',
|
||||
fn (Blueprint $table) => $table->dropColumn('active_user_id'),
|
||||
);
|
||||
Schema::whenTableHasColumn(
|
||||
'carritos',
|
||||
'active_guest_token',
|
||||
fn (Blueprint $table) => $table->dropColumn('active_guest_token'),
|
||||
);
|
||||
|
||||
Schema::whenTableDoesntHaveIndex(
|
||||
'carritos',
|
||||
'carritos_tenant_codigo_user_id_unique',
|
||||
fn (Blueprint $table) => $table->unique(['tenant_codigo', 'user_id']),
|
||||
);
|
||||
Schema::whenTableDoesntHaveIndex(
|
||||
'carritos',
|
||||
'carritos_tenant_codigo_guest_token_unique',
|
||||
fn (Blueprint $table) => $table->unique(['tenant_codigo', 'guest_token']),
|
||||
);
|
||||
Schema::whenTableHasIndex(
|
||||
'carritos',
|
||||
'carritos_tenant_codigo_index',
|
||||
fn (Blueprint $table) => $table->dropIndex('carritos_tenant_codigo_index'),
|
||||
);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user