getSchemaBuilder(); foreach (self::TABLES as $table) { if ($schema->hasTable($table)) { throw new \RuntimeException('Dependência de interface existente exige reconciliação explícita.'); } } $scope = function (Blueprint $t) { foreach (['tenant_id', 'company_id', 'unit_id'] as $name) { $t->unsignedBigInteger($name); } $t->foreign(['tenant_id', 'company_id', 'unit_id'])->references(['tenant_id', 'company_id', 'id'])->on('units')->restrictOnDelete(); }; $schema->create('cb_ui_commands', function (Blueprint $t) use ($scope) { $t->id(); $scope($t); $t->unsignedBigInteger('actor_id'); $t->foreign(['actor_id', 'tenant_id', 'company_id'])->references(['user_id', 'tenant_id', 'company_id'])->on('company_memberships')->restrictOnDelete(); $t->uuid('command_key'); $t->string('action'); $t->string('request_hash', 64); $t->jsonb('result'); $t->timestamp('created_at'); $t->unique(['tenant_id', 'company_id', 'unit_id', 'actor_id', 'command_key']); }); $schema->create('cb_consumption_sources', function (Blueprint $t) use ($scope) { $t->id(); $scope($t); $t->foreignId('origin_id')->constrained('cb_origins'); $t->foreignId('created_by')->constrained('users'); $t->string('reference', 100); $t->bigInteger('total_minor'); $t->bigInteger('subtotal_minor'); $t->timestamp('created_at'); $t->unique(['tenant_id', 'company_id', 'unit_id', 'reference']); }); $db->unprepared("CREATE FUNCTION cb_ui_commands_immutable() RETURNS trigger LANGUAGE plpgsql AS \$\$ BEGIN RAISE EXCEPTION 'Preserve budget command receipts'; END; \$\$; CREATE TRIGGER cb_ui_commands_immutable BEFORE UPDATE OR DELETE ON cb_ui_commands FOR EACH ROW EXECUTE FUNCTION cb_ui_commands_immutable();"); } }