Package system sms

This commit is contained in:
Simon Pocrnjič
2025-10-26 12:57:09 +01:00
parent 266af6595e
commit 369af34ad4
29 changed files with 2639 additions and 330 deletions
@@ -0,0 +1,37 @@
<?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::create('packages', function (Blueprint $table) {
$table->id();
$table->uuid('uuid')->unique();
$table->string('type'); // sms, email, archive, segment
$table->string('status')->default('draft'); // draft, queued, running, completed, failed, canceled
$table->string('name')->nullable();
$table->text('description')->nullable();
$table->json('meta')->nullable();
$table->unsignedInteger('total_items')->default(0);
$table->unsignedInteger('processing_count')->default(0);
$table->unsignedInteger('sent_count')->default(0);
$table->unsignedInteger('failed_count')->default(0);
$table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
$table->timestamp('finished_at')->nullable();
$table->timestamps();
$table->index(['type', 'status']);
$table->index(['created_by']);
$table->index(['finished_at']);
});
}
public function down(): void
{
Schema::dropIfExists('packages');
}
};
@@ -0,0 +1,35 @@
<?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::create('package_items', function (Blueprint $table) {
$table->id();
$table->foreignId('package_id')->constrained('packages')->cascadeOnDelete();
$table->string('status')->default('queued'); // queued, processing, sent, failed, canceled, skipped
$table->json('target_json'); // e.g., {"phone_id": 1, "number": "+386..."}
$table->json('payload_json')->nullable(); // per-item overrides and variables
$table->unsignedTinyInteger('attempts')->default(0);
$table->text('last_error')->nullable();
$table->json('result_json')->nullable();
$table->string('provider_message_id')->nullable();
$table->decimal('cost', 10, 4)->nullable();
$table->string('currency', 10)->nullable();
$table->string('idempotency_key')->nullable();
$table->timestamps();
$table->index(['package_id', 'status']);
$table->unique(['idempotency_key']);
});
}
public function down(): void
{
Schema::dropIfExists('package_items');
}
};
@@ -0,0 +1,85 @@
<?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
{
$driver = DB::getDriverName();
if ($driver === 'pgsql') {
// Create PostgreSQL enum type for phone_type if not exists
DB::statement(<<<'SQL'
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'phone_type_enum') THEN
CREATE TYPE phone_type_enum AS ENUM ('mobile', 'landline', 'voip');
END IF;
END$$;
SQL);
}
Schema::table('person_phones', function (Blueprint $table): void {
// validated flag (default false)
if (! Schema::hasColumn('person_phones', 'validated')) {
$table->boolean('validated')->default(false)->after('active');
}
});
// Add phone_type column depending on driver
$hasPhoneType = $driver === 'pgsql'
? (bool) DB::selectOne("SELECT 1 as exists FROM information_schema.columns WHERE table_name = 'person_phones' AND column_name = 'phone_type'")
: Schema::hasColumn('person_phones', 'phone_type');
if (! $hasPhoneType) {
if ($driver === 'pgsql') {
// enum-typed column for Postgres
DB::statement('ALTER TABLE person_phones ADD COLUMN phone_type phone_type_enum NULL');
} else {
// Fallback for sqlite/mysql in tests/dev: simple string column
Schema::table('person_phones', function (Blueprint $table): void {
$table->string('phone_type', 20)->nullable()->after('validated');
});
}
}
}
public function down(): void
{
$driver = DB::getDriverName();
// Drop column phone_type if exists
$hasPhoneType = $driver === 'pgsql'
? (bool) DB::selectOne("SELECT 1 as exists FROM information_schema.columns WHERE table_name = 'person_phones' AND column_name = 'phone_type'")
: Schema::hasColumn('person_phones', 'phone_type');
if ($hasPhoneType) {
if ($driver === 'pgsql') {
DB::statement('ALTER TABLE person_phones DROP COLUMN phone_type');
} else {
Schema::table('person_phones', function (Blueprint $table): void {
$table->dropColumn('phone_type');
});
}
}
Schema::table('person_phones', function (Blueprint $table): void {
if (Schema::hasColumn('person_phones', 'validated')) {
$table->dropColumn('validated');
}
});
if ($driver === 'pgsql') {
// Drop type if no longer used (best-effort)
DB::statement(<<<'SQL'
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'phone_type_enum') THEN
-- ensure no remaining dependencies
EXECUTE 'DROP TYPE phone_type_enum';
END IF;
END$$;
SQL);
}
}
};