feat(menu): enhance Menu and TenantMenu models with parent-child relationships and static content support

This commit is contained in:
2026-07-23 15:54:16 -03:00
parent 018f3f6c13
commit aed818da6e
5 changed files with 170 additions and 9 deletions

View File

@@ -4,14 +4,16 @@ namespace App\Domains\Menu\Controllers;
use App\Domains\Menu\Models\Menu;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
class MenuController extends Controller
{
public function index(): JsonResponse
{
$menues = Menu::all();
return response()->json($menues);
}
@@ -19,10 +21,19 @@ class MenuController extends Controller
{
$validated = $request->validate([
'code' => 'required|string|unique:menues,code',
'parent_menu_code' => [
'nullable',
'string',
Rule::exists('menues', 'code'),
'different:code',
],
'content_type' => ['sometimes', Rule::in(['static', 'dynamic'])],
'static_content_schema' => 'nullable|array',
'route' => 'required|string',
]);
$menu = Menu::create($validated);
return response()->json($menu, 201);
}
@@ -34,17 +45,27 @@ class MenuController extends Controller
public function update(Request $request, Menu $menu): JsonResponse
{
$validated = $request->validate([
'code' => 'sometimes|required|string|unique:menues,code,' . $menu->id,
'code' => 'sometimes|required|string|unique:menues,code,'.$menu->id,
'parent_menu_code' => [
'nullable',
'string',
Rule::exists('menues', 'code'),
Rule::notIn([$menu->code]),
],
'content_type' => ['sometimes', Rule::in(['static', 'dynamic'])],
'static_content_schema' => 'nullable|array',
'route' => 'sometimes|required|string',
]);
$menu->update($validated);
return response()->json($menu);
}
public function destroy(Menu $menu): JsonResponse
{
$menu->delete();
return response()->json(null, 204);
}
}

View File

@@ -5,7 +5,9 @@ namespace App\Domains\Menu\Models;
use App\Domains\Tenant\Models\Tenant;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Menu extends Model
{
@@ -15,18 +17,41 @@ class Menu extends Model
protected $fillable = [
'code',
'parent_menu_code',
'content_type',
'static_content_schema',
'route',
];
protected function casts(): array
{
return [
'static_content_schema' => 'array',
];
}
public function parent(): BelongsTo
{
return $this->belongsTo(self::class, 'parent_menu_code', 'code');
}
public function children(): HasMany
{
return $this->hasMany(self::class, 'parent_menu_code', 'code');
}
public function tenants(): BelongsToMany
{
return $this->belongsToMany(
Tenant::class,
'tenant_menues',
'tenants_menues',
'menu_code',
'tenant_codigo',
'tenant_code',
'code',
'codigo'
)->withTimestamps();
)
->using(TenantMenu::class)
->withPivot('static_content')
->withTimestamps();
}
}

View File

@@ -2,9 +2,36 @@
namespace App\Domains\Menu\Models;
use App\Domains\Tenant\Models\Tenant;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\Pivot;
class TenantMenu extends Pivot
{
protected $table = 'tenant_menues';
protected $table = 'tenants_menues';
public $incrementing = true;
protected $fillable = [
'tenant_code',
'menu_code',
'static_content',
];
protected function casts(): array
{
return [
'static_content' => 'array',
];
}
public function tenant(): BelongsTo
{
return $this->belongsTo(Tenant::class, 'tenant_code', 'codigo');
}
public function menu(): BelongsTo
{
return $this->belongsTo(Menu::class, 'menu_code', 'code');
}
}

View File

@@ -5,6 +5,7 @@ namespace App\Domains\Tenant\Models;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Menu\Models\Menu;
use App\Domains\Menu\Models\TenantMenu;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
@@ -116,11 +117,14 @@ class Tenant extends Model
{
return $this->belongsToMany(
Menu::class,
'tenant_menues',
'tenant_codigo',
'tenants_menues',
'tenant_code',
'menu_code',
'codigo',
'code'
)->withTimestamps();
)
->using(TenantMenu::class)
->withPivot('static_content')
->withTimestamps();
}
}

View File

@@ -0,0 +1,84 @@
<?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('tenant_menues', function (Blueprint $table) {
$table->dropForeign(['tenant_codigo']);
$table->dropForeign(['menu_code']);
});
Schema::rename('tenant_menues', 'tenants_menues');
Schema::table('tenants_menues', function (Blueprint $table) {
$table->renameColumn('tenant_codigo', 'tenant_code');
$table->json('static_content')->nullable();
});
Schema::table('menues', function (Blueprint $table) {
$table->string('parent_menu_code')->nullable()->after('code');
$table->enum('content_type', ['static', 'dynamic'])
->default('dynamic')
->after('parent_menu_code');
$table->json('static_content_schema')->nullable()->after('content_type');
});
Schema::table('menues', function (Blueprint $table) {
$table->foreign('parent_menu_code')
->references('code')
->on('menues')
->nullOnDelete();
});
Schema::table('tenants_menues', function (Blueprint $table) {
$table->foreign('tenant_code')
->references('codigo')
->on('tenants')
->cascadeOnDelete();
$table->foreign('menu_code')
->references('code')
->on('menues')
->cascadeOnDelete();
});
}
public function down(): void
{
Schema::table('tenants_menues', function (Blueprint $table) {
$table->dropForeign(['tenant_code']);
$table->dropForeign(['menu_code']);
});
Schema::table('menues', function (Blueprint $table) {
$table->dropForeign(['parent_menu_code']);
$table->dropColumn([
'parent_menu_code',
'content_type',
'static_content_schema',
]);
});
Schema::table('tenants_menues', function (Blueprint $table) {
$table->dropColumn('static_content');
$table->renameColumn('tenant_code', 'tenant_codigo');
});
Schema::rename('tenants_menues', 'tenant_menues');
Schema::table('tenant_menues', function (Blueprint $table) {
$table->foreign('tenant_codigo')
->references('codigo')
->on('tenants')
->cascadeOnDelete();
$table->foreign('menu_code')
->references('code')
->on('menues')
->cascadeOnDelete();
});
}
};