66 lines
2.6 KiB
PHP
66 lines
2.6 KiB
PHP
<?php
|
|
|
|
use Illuminate\Database\Migrations\Migration;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
/**
|
|
* What a customer actually bought, frozen at the moment they bought it.
|
|
*
|
|
* The plan catalogue in config/provisioning.php describes what we sell TODAY.
|
|
* A customer who signed up last year bought last year's terms, and raising a
|
|
* price must never reach back into their contract. So every condition that
|
|
* matters commercially is copied here at signup and never touched again:
|
|
* price, quotas, seats, the hardware behind the plan.
|
|
*
|
|
* `term` decides the rhythm: a monthly subscription can be changed at the end
|
|
* of the month, a yearly one at the end of the year. Upgrades are the exception
|
|
* — they take effect immediately and are charged pro rata.
|
|
*/
|
|
return new class extends Migration
|
|
{
|
|
public function up(): void
|
|
{
|
|
Schema::create('subscriptions', function (Blueprint $table) {
|
|
$table->id();
|
|
$table->uuid()->unique();
|
|
$table->foreignId('customer_id')->constrained()->cascadeOnDelete();
|
|
$table->foreignId('instance_id')->nullable()->constrained()->nullOnDelete();
|
|
|
|
$table->string('plan');
|
|
$table->string('term')->default('monthly'); // monthly|yearly
|
|
|
|
// ── Snapshot: the conditions this customer is owed ──────────────
|
|
$table->unsignedInteger('price_cents'); // net, per term
|
|
$table->string('currency', 3)->default('EUR');
|
|
$table->unsignedBigInteger('quota_gb');
|
|
$table->unsignedBigInteger('traffic_gb');
|
|
$table->unsignedInteger('seats');
|
|
$table->unsignedInteger('ram_mb');
|
|
$table->unsignedInteger('cores');
|
|
$table->unsignedBigInteger('disk_gb');
|
|
$table->string('performance')->nullable();
|
|
|
|
$table->timestamp('started_at');
|
|
$table->timestamp('current_period_start');
|
|
$table->timestamp('current_period_end');
|
|
|
|
// A downgrade is scheduled, never immediate: it lands when the term
|
|
// the customer already paid for runs out.
|
|
$table->string('pending_plan')->nullable();
|
|
$table->timestamp('pending_effective_at')->nullable();
|
|
|
|
$table->string('status')->default('active'); // active|cancelled
|
|
$table->timestamp('cancelled_at')->nullable();
|
|
$table->timestamps();
|
|
|
|
$table->index(['customer_id', 'status']);
|
|
});
|
|
}
|
|
|
|
public function down(): void
|
|
{
|
|
Schema::dropIfExists('subscriptions');
|
|
}
|
|
};
|