id(); $table->foreignId('user_id')->nullable()->constrained()->cascadeOnDelete(); $table->string('type'); // violation_recorded, sp_generated, threshold_reached $table->string('title'); $table->text('body')->nullable(); $table->json('data')->nullable(); $table->string('icon')->nullable(); $table->string('color')->nullable(); $table->string('action_url')->nullable(); $table->boolean('is_read')->default(false); $table->timestamp('read_at')->nullable(); $table->foreignId('violation_id')->nullable()->constrained()->nullOnDelete(); $table->foreignId('sp_letter_id')->nullable()->constrained('sp_letters')->nullOnDelete(); $table->timestamps(); $table->index(['user_id', 'is_read']); $table->index('created_at'); }); } public function down(): void { Schema::dropIfExists('notifications'); } };