Datenmodell Kern: Projekt, PFA, Vertrag, LV, Nachtrag, Dokument
- Mandant, Auftragnehmer, Projekt mit Suchreihenfolge, Abschnitt (PFA), Vertrag, Leistungsverzeichnis, Nachtrag (MKA nur als Bezug), Nachtragsposition, Dokument - Projektmitglieder mit Projektrolle, Freigaben für vertrauliche Dokumente - Mandant, Land und Projekt werden vom übergeordneten Datensatz übernommen; Fehlzuordnungen über Mandanten oder Projekte hinweg werden abgewiesen - Feste Morph-Map, Factories, Demodaten (Musterbahn, PFA 1–4, N14/N16/N21), Tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ca09d23a78
commit
6aac8b0a16
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Kern des Datenmodells: Mandant → Projekt → Abschnitt (PFA) → Vertrag → LVs und Nachträge.
|
||||
* Beschreibung in docs/datenmodell.md.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('mandanten', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->unique();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->foreignId('mandant_id')->nullable()->after('id')->constrained('mandanten')->restrictOnDelete();
|
||||
});
|
||||
|
||||
Schema::create('auftragnehmer', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('mandant_id')->constrained('mandanten')->restrictOnDelete();
|
||||
$table->char('land', 2);
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['mandant_id', 'land', 'name']);
|
||||
});
|
||||
|
||||
Schema::create('projekte', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('mandant_id')->constrained('mandanten')->restrictOnDelete();
|
||||
$table->char('land', 2);
|
||||
$table->string('name');
|
||||
$table->string('nummer', 100)->nullable();
|
||||
$table->string('auftraggeber');
|
||||
$table->string('vertragsgrundlage', 20)->default('vob_b');
|
||||
$table->string('abschnitt_bezeichnung', 50)->default('PFA');
|
||||
$table->string('status', 20)->default('aktiv');
|
||||
$table->boolean('suche_andere_vertraege_im_abschnitt')->default(false);
|
||||
$table->boolean('suche_andere_abschnitte')->default(true);
|
||||
$table->boolean('suche_nur_gleicher_auftragnehmer')->default(false);
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['mandant_id', 'land', 'status']);
|
||||
});
|
||||
|
||||
Schema::create('projekt_mitglieder', function (Blueprint $table) {
|
||||
$table->foreignId('projekt_id')->constrained('projekte')->cascadeOnDelete();
|
||||
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
|
||||
$table->string('rolle', 20);
|
||||
$table->timestamps();
|
||||
|
||||
$table->primary(['projekt_id', 'user_id']);
|
||||
});
|
||||
|
||||
Schema::create('abschnitte', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('mandant_id')->constrained('mandanten')->restrictOnDelete();
|
||||
$table->char('land', 2);
|
||||
$table->foreignId('projekt_id')->constrained('projekte')->restrictOnDelete();
|
||||
$table->string('bezeichnung', 100);
|
||||
$table->unsignedSmallInteger('sortierung')->default(0);
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['projekt_id', 'bezeichnung']);
|
||||
});
|
||||
|
||||
Schema::create('vertraege', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('mandant_id')->constrained('mandanten')->restrictOnDelete();
|
||||
$table->char('land', 2);
|
||||
$table->foreignId('projekt_id')->constrained('projekte')->restrictOnDelete();
|
||||
$table->foreignId('abschnitt_id')->constrained('abschnitte')->restrictOnDelete();
|
||||
$table->foreignId('auftragnehmer_id')->constrained('auftragnehmer')->restrictOnDelete();
|
||||
$table->string('bezeichnung', 150);
|
||||
$table->string('vertragsnummer', 100)->nullable();
|
||||
$table->date('vertrag_vom')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('leistungsverzeichnisse', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('mandant_id')->constrained('mandanten')->restrictOnDelete();
|
||||
$table->char('land', 2);
|
||||
$table->foreignId('projekt_id')->constrained('projekte')->restrictOnDelete();
|
||||
$table->foreignId('vertrag_id')->constrained('vertraege')->restrictOnDelete();
|
||||
$table->string('bezeichnung');
|
||||
$table->string('import_status', 20)->default('wartet');
|
||||
$table->text('import_fehler')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('nachtraege', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('mandant_id')->constrained('mandanten')->restrictOnDelete();
|
||||
$table->char('land', 2);
|
||||
$table->foreignId('projekt_id')->constrained('projekte')->restrictOnDelete();
|
||||
$table->foreignId('vertrag_id')->constrained('vertraege')->restrictOnDelete();
|
||||
$table->string('nummer', 50);
|
||||
$table->date('eingang_am');
|
||||
$table->string('betreff');
|
||||
$table->json('mka_bezug')->nullable();
|
||||
$table->string('status', 20)->default('eingegangen');
|
||||
$table->foreignId('zugewiesen_an')->nullable()->constrained('users')->nullOnDelete();
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['vertrag_id', 'nummer']);
|
||||
$table->index(['projekt_id', 'status']);
|
||||
});
|
||||
|
||||
Schema::create('nachtragspositionen', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('mandant_id')->constrained('mandanten')->restrictOnDelete();
|
||||
$table->char('land', 2);
|
||||
$table->foreignId('projekt_id')->constrained('projekte')->restrictOnDelete();
|
||||
$table->foreignId('nachtrag_id')->constrained('nachtraege')->cascadeOnDelete();
|
||||
$table->string('oz', 50);
|
||||
$table->string('kurztext', 500);
|
||||
$table->text('langtext')->nullable();
|
||||
$table->decimal('menge', 15, 3)->nullable();
|
||||
$table->string('einheit', 20)->nullable();
|
||||
$table->decimal('einheitspreis', 15, 2)->nullable();
|
||||
$table->unsignedInteger('sortierung')->default(0);
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['nachtrag_id', 'oz']);
|
||||
});
|
||||
|
||||
Schema::create('dokumente', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('mandant_id')->constrained('mandanten')->restrictOnDelete();
|
||||
$table->char('land', 2);
|
||||
$table->foreignId('projekt_id')->nullable()->constrained('projekte')->restrictOnDelete();
|
||||
$table->nullableMorphs('dokumentable');
|
||||
$table->string('kategorie', 40);
|
||||
$table->string('dateiname');
|
||||
$table->string('pfad', 500);
|
||||
$table->string('mime_type', 150);
|
||||
$table->unsignedBigInteger('groesse');
|
||||
$table->char('sha256', 64);
|
||||
$table->boolean('vertraulich')->default(false);
|
||||
$table->foreignId('hochgeladen_von')->nullable()->constrained('users')->nullOnDelete();
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['projekt_id', 'kategorie']);
|
||||
$table->index('sha256');
|
||||
});
|
||||
|
||||
Schema::create('dokument_freigaben', function (Blueprint $table) {
|
||||
$table->foreignId('dokument_id')->constrained('dokumente')->cascadeOnDelete();
|
||||
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
|
||||
$table->timestamps();
|
||||
|
||||
$table->primary(['dokument_id', 'user_id']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('dokument_freigaben');
|
||||
Schema::dropIfExists('dokumente');
|
||||
Schema::dropIfExists('nachtragspositionen');
|
||||
Schema::dropIfExists('nachtraege');
|
||||
Schema::dropIfExists('leistungsverzeichnisse');
|
||||
Schema::dropIfExists('vertraege');
|
||||
Schema::dropIfExists('abschnitte');
|
||||
Schema::dropIfExists('projekt_mitglieder');
|
||||
Schema::dropIfExists('projekte');
|
||||
Schema::dropIfExists('auftragnehmer');
|
||||
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropConstrainedForeignId('mandant_id');
|
||||
});
|
||||
|
||||
Schema::dropIfExists('mandanten');
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user