21-11-2025
This commit is contained in:
parent
fa2ebd457d
commit
07959c0ba2
113 changed files with 4730 additions and 898 deletions
|
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
$teams = config('permission.teams');
|
||||
$tableNames = config('permission.table_names');
|
||||
$columnNames = config('permission.column_names');
|
||||
$pivotRole = $columnNames['role_pivot_key'] ?? 'role_id';
|
||||
$pivotPermission = $columnNames['permission_pivot_key'] ?? 'permission_id';
|
||||
|
||||
throw_if(empty($tableNames), new Exception('Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.'));
|
||||
throw_if($teams && empty($columnNames['team_foreign_key'] ?? null), new Exception('Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.'));
|
||||
|
||||
Schema::create($tableNames['permissions'], static function (Blueprint $table) {
|
||||
// $table->engine('InnoDB');
|
||||
$table->bigIncrements('id'); // permission id
|
||||
$table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format)
|
||||
$table->string('guard_name'); // For MyISAM use string('guard_name', 25);
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['name', 'guard_name']);
|
||||
});
|
||||
|
||||
Schema::create($tableNames['roles'], static function (Blueprint $table) use ($teams, $columnNames) {
|
||||
// $table->engine('InnoDB');
|
||||
$table->bigIncrements('id'); // role id
|
||||
if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
|
||||
$table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();
|
||||
$table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
|
||||
}
|
||||
$table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format)
|
||||
$table->string('guard_name'); // For MyISAM use string('guard_name', 25);
|
||||
$table->timestamps();
|
||||
if ($teams || config('permission.testing')) {
|
||||
$table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
|
||||
} else {
|
||||
$table->unique(['name', 'guard_name']);
|
||||
}
|
||||
});
|
||||
|
||||
Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) {
|
||||
$table->unsignedBigInteger($pivotPermission);
|
||||
|
||||
$table->string('model_type');
|
||||
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
|
||||
|
||||
$table->foreign($pivotPermission)
|
||||
->references('id') // permission id
|
||||
->on($tableNames['permissions'])
|
||||
->onDelete('cascade');
|
||||
if ($teams) {
|
||||
$table->unsignedBigInteger($columnNames['team_foreign_key']);
|
||||
$table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
|
||||
|
||||
$table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_permissions_permission_model_type_primary');
|
||||
} else {
|
||||
$table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_permissions_permission_model_type_primary');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {
|
||||
$table->unsignedBigInteger($pivotRole);
|
||||
|
||||
$table->string('model_type');
|
||||
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
|
||||
|
||||
$table->foreign($pivotRole)
|
||||
->references('id') // role id
|
||||
->on($tableNames['roles'])
|
||||
->onDelete('cascade');
|
||||
if ($teams) {
|
||||
$table->unsignedBigInteger($columnNames['team_foreign_key']);
|
||||
$table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
|
||||
|
||||
$table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_roles_role_model_type_primary');
|
||||
} else {
|
||||
$table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_roles_role_model_type_primary');
|
||||
}
|
||||
});
|
||||
|
||||
Schema::create($tableNames['role_has_permissions'], static function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) {
|
||||
$table->unsignedBigInteger($pivotPermission);
|
||||
$table->unsignedBigInteger($pivotRole);
|
||||
|
||||
$table->foreign($pivotPermission)
|
||||
->references('id') // permission id
|
||||
->on($tableNames['permissions'])
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->foreign($pivotRole)
|
||||
->references('id') // role id
|
||||
->on($tableNames['roles'])
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary');
|
||||
});
|
||||
|
||||
app('cache')
|
||||
->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
|
||||
->forget(config('permission.cache.key'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
$tableNames = config('permission.table_names');
|
||||
|
||||
if (empty($tableNames)) {
|
||||
throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
|
||||
}
|
||||
|
||||
Schema::drop($tableNames['role_has_permissions']);
|
||||
Schema::drop($tableNames['model_has_roles']);
|
||||
Schema::drop($tableNames['model_has_permissions']);
|
||||
Schema::drop($tableNames['roles']);
|
||||
Schema::drop($tableNames['permissions']);
|
||||
}
|
||||
};
|
||||
26
database/migrations/2025_11_06_115527_create_hubs_table.php
Normal file
26
database/migrations/2025_11_06_115527_create_hubs_table.php
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('hubs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name'); // z.B. "OWL" oder "Rhein-Main"
|
||||
$table->string('slug')->unique(); // Für saubere URLs, z.B. "owl"
|
||||
$table->string('keyvisual_url')->nullable(); // Keyvisual-Bild des Hubs
|
||||
$table->string('emblem_url')->nullable(); // Wappen-URL des Hubs
|
||||
$table->boolean('is_active')->default(false);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('hubs');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('hub_locations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
// Beziehung zum Hub
|
||||
$table->foreignId('hub_id')->constrained()->onDelete('cascade');
|
||||
|
||||
$table->string('city_name')->nullable(); // z.B. "Bielefeld"
|
||||
$table->string('zip_code'); // z.B. "33602"
|
||||
|
||||
// Index für schnelle PLZ-Suche
|
||||
$table->index('zip_code');
|
||||
|
||||
// Verhindert doppelte PLZ-Einträge pro Hub
|
||||
$table->unique(['hub_id', 'zip_code']);
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('hub_locations');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('partners', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('company_name');
|
||||
$table->string('slug')->unique();
|
||||
|
||||
// Partner-Typ (gemäß Wissensbasis)
|
||||
$table->string('type'); // 'Retailer', 'Manufacturer', 'Estate-Agent'
|
||||
|
||||
// Hub-Zugehörigkeit (kann NULL sein für "globale" Hersteller)
|
||||
$table->foreignId('hub_id')->nullable()->constrained()->onDelete('set null');
|
||||
|
||||
$table->text('description')->nullable();
|
||||
$table->string('logo_url')->nullable();
|
||||
$table->boolean('is_active')->default(false);
|
||||
|
||||
// Spezifische Felder für 'Retailer' (Händler)
|
||||
$table->integer('delivery_radius_km')->nullable();
|
||||
$table->integer('assembly_radius_km')->nullable();
|
||||
|
||||
// Flexible Provisions-Engine (pro Partner)
|
||||
// Speichert den Wert in Cents, um Rundungsfehler zu vermeiden
|
||||
$table->integer('provision_fixed_amount')->nullable();
|
||||
// Speichert als 10.5 für 10.5%
|
||||
$table->decimal('provision_rate_percentage', 5, 2)->nullable();
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('partners');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('roles', function (Blueprint $table) {
|
||||
$table->string('color', 50)->default('zinc')->after('guard_name');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('roles', function (Blueprint $table) {
|
||||
$table->dropColumn('color');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
// Verknüpft einen User mit einer Partner-Firma
|
||||
// 'after' ist optional, aber gut für die DB-Lesbarkeit
|
||||
$table->foreignId('partner_id')
|
||||
->nullable()
|
||||
->after('id')
|
||||
->constrained('partners')
|
||||
->onDelete('set null'); // Wenn Partner gelöscht wird, bleibt User bestehen
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
// Entferne Foreign Key zuerst
|
||||
try {
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropForeign(['partner_id']);
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
// Foreign Key existiert nicht oder hat anderen Namen - weitermachen
|
||||
}
|
||||
|
||||
// Entferne Spalte
|
||||
if (Schema::hasColumn('users', 'partner_id')) {
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('partner_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('attributes', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name'); // z.B. "Farbe", "Größe", "Material"
|
||||
$table->string('slug')->unique();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('attributes');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('attribute_values', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('attribute_id')->constrained('attributes')->onDelete('cascade');
|
||||
$table->string('value'); // z.B. "Anthrazit", "3-Sitzer", "Eiche"
|
||||
$table->string('slug')->unique();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('attribute_values');
|
||||
}
|
||||
};
|
||||
35
database/migrations/2025_11_06_153100_create_media_table.php
Normal file
35
database/migrations/2025_11_06_153100_create_media_table.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('media', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('model_type'); // "App\Models\Product" ODER "App\Models\ProductVariant"
|
||||
$table->unsignedBigInteger('model_id');
|
||||
$table->string('file_path');
|
||||
$table->string('type')->default('image'); // 'image', 'video', 'pdf', '3d_model'
|
||||
$table->string('alt_text')->nullable();
|
||||
$table->integer('order_column')->default(0);
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['model_type', 'model_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('media');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
// database/migrations/xxxx_create_brands_table.php
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('brands', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('slug')->unique();
|
||||
$table->string('logo_url')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('brands');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
// database/migrations/xxxx_create_collections_table.php
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('collections', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('slug')->unique();
|
||||
$table->text('description')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('collections');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
// database/migrations/xxxx_create_categories_table.php
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
// Für Baumstruktur (z.B. "Sofas" gehört zu "Wohnzimmer")
|
||||
$table->foreignId('parent_id')
|
||||
->nullable()
|
||||
->constrained('categories')
|
||||
->onDelete('set null');
|
||||
|
||||
$table->string('name');
|
||||
$table->string('slug')->unique();
|
||||
$table->text('description')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('categories');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('tax_rates', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name'); // z.B. "Regelsatz", "Ermäßigt"
|
||||
$table->decimal('rate_percentage', 5, 2); // z.B. 19.00, 7.00
|
||||
$table->boolean('is_default')->default(false);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('tax_rates');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('shipping_classes', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name'); // z.B. "Paketversand", "Spedition (2-Mann)"
|
||||
$table->text('description')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('shipping_classes');
|
||||
}
|
||||
};
|
||||
28
database/migrations/2025_11_06_153520_create_tags_table.php
Normal file
28
database/migrations/2025_11_06_153520_create_tags_table.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('tags', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('slug')->unique();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('tags');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
// database/migrations/xxxx_create_products_table.php
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('products', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('partner_id')->constrained('partners')->onDelete('cascade');
|
||||
|
||||
// NEU: Verknüpfung zu Marke/Hersteller
|
||||
$table->foreignId('brand_id')->nullable()->constrained('brands')->onDelete('set null');
|
||||
// NEU: Verknüpfung zu Kollektion/Serie
|
||||
$table->foreignId('collection_id')->nullable()->constrained('collections')->onDelete('set null');
|
||||
|
||||
$table->string('name'); // z.B. "3-Sitzer Sofa 'Stockholm'"
|
||||
$table->string('slug')->unique();
|
||||
$table->string('status')->default('draft'); // draft, active, archived
|
||||
|
||||
$table->text('description_short')->nullable();
|
||||
$table->text('description_long')->nullable();
|
||||
$table->text('care_instructions')->nullable();
|
||||
|
||||
// Basis-Maße (können von Varianten überschrieben werden, wenn nötig)
|
||||
$table->integer('width_cm')->nullable();
|
||||
$table->integer('height_cm')->nullable();
|
||||
$table->integer('depth_cm')->nullable();
|
||||
|
||||
// PERFEKTER ANWENDUNGSFALL FÜR JSON:
|
||||
// Spezifische Maße, nach denen nie gefiltert wird.
|
||||
$table->json('dimensions_specific')->nullable();
|
||||
// Bsp: {"seat_height_cm": 45, "seat_depth_cm": 60}
|
||||
|
||||
// Logistik-Basis
|
||||
$table->string('assembly_status')->nullable(); // z.B. 'flat_pack', 'partially_assembled', 'fully_assembled'
|
||||
|
||||
// SEO
|
||||
$table->string('meta_title')->nullable();
|
||||
$table->text('meta_description')->nullable();
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('products');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
// database/migrations/xxxx_create_product_variants_table.php
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('product_variants', function (Blueprint $table) {
|
||||
$table->id();
|
||||
// Jede Variante gehört zu einem "Parent"-Produkt
|
||||
$table->foreignId('product_id')->constrained('products')->onDelete('cascade');
|
||||
|
||||
$table->string('name_suffix')->nullable(); // z.B. "Anthrazit / 3-Sitzer"
|
||||
$table->boolean('is_master_variant')->default(false); // Die "Standard"-Variante
|
||||
|
||||
// Eindeutige IDs
|
||||
$table->string('sku')->unique(); // Interne SKU
|
||||
$table->string('han_mpn')->nullable()->index(); // Hersteller-Nr.
|
||||
$table->string('ean_gtin')->nullable()->index(); // Barcode
|
||||
|
||||
// Preis-Logik (in Cents)
|
||||
$table->integer('selling_price'); // VK
|
||||
$table->integer('msrp')->nullable(); // UVP (Streichpreis)
|
||||
$table->integer('purchase_price')->nullable(); // EK
|
||||
$table->foreignId('tax_rate_id')->constrained('tax_rates');
|
||||
|
||||
// Lager-Logik
|
||||
$table->integer('stock_quantity')->default(0);
|
||||
$table->integer('stock_min_threshold')->nullable(); // Meldebestand
|
||||
$table->string('availability_status')->nullable(); // z.B. 'in_stock', 'out_of_stock'
|
||||
$table->string('delivery_time_text')->nullable(); // z.B. "6-8 Wochen" (ersetzt altes Feld)
|
||||
|
||||
// WICHTIG: Re-Integration des Mietmodells aus dem Initial-Briefing
|
||||
$table->boolean('is_rentable')->default(false);
|
||||
$table->json('rental_duration_options')->nullable(); // [6, 12, 24]
|
||||
$table->string('rental_rate_formula')->nullable();
|
||||
$table->decimal('residual_value_percentage', 5, 2)->nullable();
|
||||
|
||||
// Variante-spezifische Maße & Gewicht (falls abweichend vom Parent)
|
||||
$table->integer('variant_weight_g')->nullable();
|
||||
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('product_variants');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// ... create_product_variant_attributes_table.php
|
||||
Schema::create('product_variant_attributes', function (Blueprint $table) {
|
||||
// Composite Primary Key
|
||||
$table->foreignId('product_variant_id')->constrained('product_variants')->onDelete('cascade');
|
||||
$table->foreignId('attribute_value_id')->constrained('attribute_values')->onDelete('cascade');
|
||||
$table->primary(['product_variant_id', 'attribute_value_id'], 'variant_attribute_primary');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('product_variant_attributes');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('partner_invitations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('company_name');
|
||||
$table->enum('partner_type', ['Retailer', 'Manufacturer', 'Estate-Agent', 'Customer'])->default('Retailer');
|
||||
$table->string('email');
|
||||
$table->string('token', 64)->unique();
|
||||
$table->enum('status', ['pending', 'accepted', 'expired', 'cancelled'])->default('pending');
|
||||
$table->timestamp('expires_at');
|
||||
$table->foreignId('invited_by')->constrained('users')->onDelete('cascade');
|
||||
$table->foreignId('partner_id')->nullable()->constrained('partners')->onDelete('set null');
|
||||
$table->timestamp('accepted_at')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['token', 'status']);
|
||||
$table->index(['email', 'status']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// Foreign Keys werden automatisch mit der Tabelle gelöscht
|
||||
Schema::dropIfExists('partner_invitations');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('category_product', function (Blueprint $table) {
|
||||
$table->foreignId('category_id')->constrained()->onDelete('cascade');
|
||||
$table->foreignId('product_id')->constrained()->onDelete('cascade');
|
||||
|
||||
// Primärschlüssel aus beiden IDs
|
||||
$table->primary(['category_id', 'product_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('category_product');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('product_tag', function (Blueprint $table) {
|
||||
$table->foreignId('product_id')->constrained()->onDelete('cascade');
|
||||
$table->foreignId('tag_id')->constrained()->onDelete('cascade');
|
||||
|
||||
// Primärschlüssel aus beiden IDs
|
||||
$table->primary(['product_id', 'tag_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('product_tag');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('related_products', function (Blueprint $table) {
|
||||
// Das "Basis"-Produkt
|
||||
$table->foreignId('product_id')->constrained('products')->onDelete('cascade');
|
||||
|
||||
// Das "verknüpfte" Produkt
|
||||
$table->foreignId('related_product_id')->constrained('products')->onDelete('cascade');
|
||||
|
||||
$table->primary(['product_id', 'related_product_id']);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('related_products');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('product_logistics', function (Blueprint $table) {
|
||||
$table->id();
|
||||
// 1-zu-1 Beziehung zur Variante
|
||||
$table->foreignId('product_variant_id')->constrained('product_variants')->onDelete('cascade');
|
||||
|
||||
$table->foreignId('shipping_class_id')->nullable()->constrained('shipping_classes');
|
||||
|
||||
// Verpackungsmaße
|
||||
$table->integer('package_width_cm')->nullable();
|
||||
$table->integer('package_height_cm')->nullable();
|
||||
$table->integer('package_depth_cm')->nullable();
|
||||
$table->integer('package_weight_g')->nullable(); // Bruttogewicht
|
||||
$table->integer('package_count')->default(1); // Anzahl Packstücke
|
||||
|
||||
$table->string('location_bin')->nullable(); // Lagerort
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('product_logistics');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('roles', function (Blueprint $table) {
|
||||
$table->string('display_name')->nullable()->after('name');
|
||||
$table->string('icon')->nullable()->after('display_name');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('roles', function (Blueprint $table) {
|
||||
$table->dropColumn(['display_name', 'icon']);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('partner_invitations', function (Blueprint $table) {
|
||||
$table->string('contact_first_name')->nullable()->after('company_name');
|
||||
$table->string('contact_last_name')->nullable()->after('contact_first_name');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('partner_invitations', function (Blueprint $table) {
|
||||
$table->dropColumn(['contact_first_name', 'contact_last_name']);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('roles', function (Blueprint $table) {
|
||||
$table->boolean('can_be_invited')->default(false)->after('icon');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('roles', function (Blueprint $table) {
|
||||
$table->dropColumn('can_be_invited');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Füge zuerst role_id als nullable hinzu (falls nicht existiert)
|
||||
if (!Schema::hasColumn('partner_invitations', 'role_id')) {
|
||||
Schema::table('partner_invitations', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('role_id')->nullable()->after('contact_last_name');
|
||||
});
|
||||
}
|
||||
|
||||
// Migriere bestehende Daten: partner_type -> role_id
|
||||
if (Schema::hasColumn('partner_invitations', 'partner_type')) {
|
||||
DB::table('partner_invitations')->get()->each(function ($invitation) {
|
||||
$roleName = $invitation->partner_type;
|
||||
$role = DB::table('roles')->where('name', $roleName)->first();
|
||||
|
||||
if ($role) {
|
||||
DB::table('partner_invitations')
|
||||
->where('id', $invitation->id)
|
||||
->update(['role_id' => $role->id]);
|
||||
}
|
||||
});
|
||||
|
||||
// Jetzt partner_type entfernen und role_id als required machen
|
||||
Schema::table('partner_invitations', function (Blueprint $table) {
|
||||
$table->dropColumn('partner_type');
|
||||
});
|
||||
}
|
||||
|
||||
// Mache role_id required und füge Foreign Key hinzu
|
||||
try {
|
||||
Schema::table('partner_invitations', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('role_id')->nullable(false)->change();
|
||||
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
// Foreign Key existiert bereits, nur die Spalte ändern
|
||||
Schema::table('partner_invitations', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('role_id')->nullable(false)->change();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// Füge partner_type wieder hinzu (als nullable, da wir Daten migrieren)
|
||||
if (!Schema::hasColumn('partner_invitations', 'partner_type')) {
|
||||
Schema::table('partner_invitations', function (Blueprint $table) {
|
||||
$table->enum('partner_type', ['Retailer', 'Manufacturer', 'Estate-Agent', 'Customer'])->nullable()->after('email');
|
||||
});
|
||||
}
|
||||
|
||||
// Migriere Daten zurück: role_id -> partner_type
|
||||
if (Schema::hasColumn('partner_invitations', 'role_id')) {
|
||||
DB::table('partner_invitations')->get()->each(function ($invitation) {
|
||||
if ($invitation->role_id) {
|
||||
$role = DB::table('roles')->where('id', $invitation->role_id)->first();
|
||||
if ($role) {
|
||||
DB::table('partner_invitations')
|
||||
->where('id', $invitation->id)
|
||||
->update(['partner_type' => $role->name]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Entferne role_id Foreign Key und Spalte
|
||||
try {
|
||||
Schema::table('partner_invitations', function (Blueprint $table) {
|
||||
$table->dropForeign(['role_id']);
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
// Foreign Key existiert nicht oder hat anderen Namen - weitermachen
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('partner_invitations', 'role_id')) {
|
||||
Schema::table('partner_invitations', function (Blueprint $table) {
|
||||
$table->dropColumn('role_id');
|
||||
});
|
||||
}
|
||||
|
||||
// Mache partner_type wieder required mit default
|
||||
Schema::table('partner_invitations', function (Blueprint $table) {
|
||||
$table->enum('partner_type', ['Retailer', 'Manufacturer', 'Estate-Agent', 'Customer'])->default('Retailer')->change();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('partners', function (Blueprint $table) {
|
||||
$table->boolean('setup_completed')->default(false)->after('is_active');
|
||||
$table->timestamp('setup_completed_at')->nullable()->after('setup_completed');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('partners', function (Blueprint $table) {
|
||||
$table->dropColumn(['setup_completed', 'setup_completed_at']);
|
||||
});
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue