id(); $table->foreignId('stabile_id')->constrained('stabili')->cascadeOnDelete(); $table->unsignedSmallInteger('anno_gestione'); $table->string('tipo_gestione', 32); $table->string('descrizione'); $table->string('stato', 32)->default('bozza'); $table->decimal('importo_totale', 12, 2)->default(0); $table->date('data_creazione')->nullable(); $table->date('data_approvazione')->nullable(); $table->foreignId('approvato_da_user_id')->nullable()->constrained('users')->nullOnDelete(); $table->text('note')->nullable(); $table->unsignedInteger('versione')->default(1); $table->timestamps(); $table->softDeletes(); $table->index(['stabile_id', 'anno_gestione']); $table->index(['stato', 'tipo_gestione']); }); } if (! Schema::hasTable('voci_preventivo')) { Schema::create('voci_preventivo', function (Blueprint $table) { $table->id(); $table->foreignId('preventivo_id')->constrained('preventivi')->cascadeOnDelete(); $table->string('codice', 20); $table->string('descrizione'); $table->decimal('importo_preventivato', 12, 2)->default(0); $table->decimal('importo_effettivo', 12, 2)->nullable(); $table->unsignedBigInteger('tabella_millesimale_id')->nullable(); $table->unsignedBigInteger('voce_spesa_id')->nullable(); $table->boolean('ricorrente')->default(false); $table->string('frequenza', 32)->nullable(); $table->date('data_scadenza_prevista')->nullable(); $table->unsignedInteger('ordinamento')->default(0); $table->text('note')->nullable(); $table->timestamps(); $table->index(['preventivo_id', 'ordinamento']); $table->index(['tabella_millesimale_id']); $table->index(['voce_spesa_id']); }); } if (! Schema::hasTable('ripartizioni_preventivo')) { Schema::create('ripartizioni_preventivo', function (Blueprint $table) { $table->id(); $table->foreignId('voce_preventivo_id')->constrained('voci_preventivo')->cascadeOnDelete(); // Nota: non forziamo FK perché nel legacy può non essere 'id' $table->unsignedBigInteger('unita_immobiliare_id'); $table->decimal('quota_calcolata', 12, 2)->nullable(); $table->decimal('quota_modificata', 12, 2)->nullable(); $table->decimal('quota_finale', 12, 2)->nullable(); $table->unsignedInteger('versione')->default(1); $table->foreignId('modificato_da_user_id')->nullable()->constrained('users')->nullOnDelete(); $table->text('motivo_modifica')->nullable(); $table->timestamp('data_modifica')->nullable(); $table->timestamps(); $table->unique(['voce_preventivo_id', 'unita_immobiliare_id'], 'uq_rip_prev_voce_unita'); }); } if (! Schema::hasTable('log_modifiche_preventivo')) { Schema::create('log_modifiche_preventivo', function (Blueprint $table) { $table->id(); $table->string('entita', 32); $table->unsignedBigInteger('entita_id'); $table->unsignedInteger('versione_precedente')->default(0); $table->unsignedInteger('versione_nuova')->default(0); $table->foreignId('utente_id')->nullable()->constrained('users')->nullOnDelete(); $table->string('tipo_operazione', 32)->nullable(); $table->text('motivo')->nullable(); $table->json('dati_precedenti')->nullable(); $table->json('dati_nuovi')->nullable(); $table->json('diff')->nullable(); $table->timestamps(); $table->index(['entita', 'entita_id']); }); } } public function down(): void { Schema::dropIfExists('log_modifiche_preventivo'); Schema::dropIfExists('ripartizioni_preventivo'); Schema::dropIfExists('voci_preventivo'); Schema::dropIfExists('preventivi'); } };