id(); $table->foreignId('tenant_id')->constrained()->restrictOnDelete(); $table->foreignId('created_by')->constrained('users')->restrictOnDelete(); $table->uuid('operation_key'); $table->string('creation_hash', 64); $table->string('name', 200); $table->string('reference', 120); $table->string('reference_key', 120); $table->text('profile_summary'); $table->boolean('active')->default(true); $table->unsignedInteger('version')->default(1); $table->timestamps(); $table->unique(['tenant_id', 'reference_key']); $table->unique(['tenant_id', 'operation_key']); $table->unique(['tenant_id', 'id']); }); Schema::table('people_applications', function (Blueprint $table) { $table->unsignedBigInteger('person_id')->nullable(); $table->json('person_snapshot')->nullable(); $table->foreign(['tenant_id', 'person_id'])->references(['tenant_id', 'id'])->on('people_registry')->restrictOnDelete(); $table->unique(['people_process_id', 'person_id']); }); if (DB::getDriverName() === 'pgsql') { DB::unprepared("CREATE FUNCTION sgc_guard_people_registry() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF TG_OP = 'DELETE' THEN RAISE EXCEPTION 'Preservar cadastro de pessoas'; END IF; IF NEW.version <> OLD.version + 1 OR ROW(NEW.tenant_id,NEW.created_by,NEW.operation_key,NEW.creation_hash) IS DISTINCT FROM ROW(OLD.tenant_id,OLD.created_by,OLD.operation_key,OLD.creation_hash) THEN RAISE EXCEPTION 'Preservar origem e versao do cadastro'; END IF; RETURN NEW; END $$; CREATE TRIGGER guard_people_registry BEFORE UPDATE OR DELETE ON people_registry FOR EACH ROW EXECUTE FUNCTION sgc_guard_people_registry();"); } elseif (DB::getDriverName() === 'sqlite') { DB::unprepared("CREATE TRIGGER guard_people_registry_delete BEFORE DELETE ON people_registry BEGIN SELECT RAISE(ABORT, 'Preservar cadastro'); END; CREATE TRIGGER guard_people_registry_update BEFORE UPDATE ON people_registry WHEN NEW.version != OLD.version+1 OR NEW.tenant_id IS NOT OLD.tenant_id OR NEW.created_by IS NOT OLD.created_by OR NEW.operation_key IS NOT OLD.operation_key OR NEW.creation_hash IS NOT OLD.creation_hash BEGIN SELECT RAISE(ABORT, 'Preservar origem e versao'); END;"); // SQLite rebuilds a table to add composite foreign keys: restore its evidence guards. foreach (['UPDATE', 'DELETE'] as $operation) { DB::unprepared("DROP TRIGGER IF EXISTS preserve_people_applications_{$operation}; CREATE TRIGGER preserve_people_applications_{$operation} BEFORE {$operation} ON people_applications BEGIN SELECT RAISE(ABORT, 'Preservar evidencias'); END;"); } } } public function down(): void { throw new LogicException('Preservar cadastro, candidaturas e versões históricas.'); } };