Refactor request validation to use model-specific prop synchronization and add migrations for categories and brands

This commit is contained in:
2026-06-24 11:02:35 -03:00
parent 8d840d94a0
commit e4139d48aa
12 changed files with 136 additions and 11 deletions

View File

@@ -2,6 +2,7 @@
namespace App\Domains\Catalog\Requests;
use App\Domains\Catalog\Models\Brand;
use App\Domains\Prop\Support\PropRules;
use Illuminate\Foundation\Http\FormRequest;
@@ -21,7 +22,7 @@ class StoreBrandRequest extends FormRequest
'tenant_codigo' => ['required', 'string', 'exists:tenants,codigo'],
'nombre' => ['required', 'string', 'max:255'],
'descripcion' => ['nullable', 'string'],
...PropRules::sync(),
...PropRules::sync(Brand::class),
];
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Domains\Catalog\Requests;
use App\Domains\Catalog\Models\Category;
use App\Domains\Prop\Support\PropRules;
use Illuminate\Foundation\Http\FormRequest;
@@ -21,7 +22,7 @@ class StoreCategoryRequest extends FormRequest
'tenant_code' => ['required_with:categoria_id', 'string', 'exists:tenants,codigo'],
'categoria_id' => ['nullable', 'integer', 'exists:categorias,id'],
'nombre' => ['required', 'string', 'max:255'],
...PropRules::sync(),
...PropRules::sync(Category::class),
];
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Domains\Catalog\Requests;
use App\Domains\Catalog\Models\Product;
use App\Domains\Prop\Support\PropRules;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
@@ -25,7 +26,7 @@ class StoreProductRequest extends FormRequest
'nombre' => ['required', 'string', 'max:255'],
'descripcion' => ['nullable', 'string'],
'precio' => ['required', 'numeric', 'min:0'],
...PropRules::sync(),
...PropRules::sync(Product::class),
];
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Domains\Catalog\Requests;
use App\Domains\Catalog\Models\Brand;
use App\Domains\Prop\Support\PropRules;
use Illuminate\Foundation\Http\FormRequest;
@@ -21,7 +22,7 @@ class UpdateBrandRequest extends FormRequest
'tenant_codigo' => ['required', 'string', 'exists:tenants,codigo'],
'nombre' => ['required', 'string', 'max:255'],
'descripcion' => ['nullable', 'string'],
...PropRules::sync(),
...PropRules::sync(Brand::class),
];
}
}

View File

@@ -31,7 +31,7 @@ class UpdateCategoryRequest extends FormRequest
Rule::notIn([$category?->id]),
],
'nombre' => ['required', 'string', 'max:255'],
...PropRules::sync(),
...PropRules::sync(Category::class),
];
}
}

View File

@@ -34,7 +34,7 @@ class UpdateProductRequest extends FormRequest
'nombre' => ['required', 'string', 'max:255'],
'descripcion' => ['nullable', 'string'],
'precio' => ['required', 'numeric', 'min:0'],
...PropRules::sync(),
...PropRules::sync(Product::class),
];
}
}

View File

@@ -2,16 +2,59 @@
namespace App\Domains\Prop\Support;
use App\Domains\Prop\Models\Prop;
use Closure;
use Illuminate\Database\Eloquent\Model;
class PropRules
{
/**
* @return array<string, mixed>
*/
public static function sync(): array
public static function sync(string $modelClass): array
{
return [
'props' => ['sometimes', 'array'],
'props' => [
'sometimes',
'array',
static function (string $attribute, mixed $value, Closure $fail) use ($modelClass): void {
static::validatePropsForModel($attribute, $value, $fail, $modelClass);
},
],
'props.*' => ['nullable'],
];
}
protected static function validatePropsForModel(string $attribute, mixed $value, Closure $fail, string $modelClass): void
{
if (! is_array($value) || $value === []) {
return;
}
if (! is_subclass_of($modelClass, Model::class)) {
$fail("The {$attribute} field references an invalid propable model.");
return;
}
$propCodes = array_map('strval', array_keys($value));
$existingPropCodes = Prop::query()
->forModel($modelClass)
->whereIn('codigo', $propCodes)
->pluck('codigo')
->all();
$missingPropCodes = array_values(array_diff($propCodes, $existingPropCodes));
if ($missingPropCodes === []) {
return;
}
$fail(sprintf(
'The selected %s are invalid for %s: %s.',
$attribute,
class_basename($modelClass),
implode(', ', $missingPropCodes),
));
}
}

View File

@@ -21,7 +21,6 @@ class TenantController extends Controller
{
$validated = $request->validated();
$props = $validated['props'] ?? [];
unset($validated['props']);
$tenant = Tenant::createWithProps($validated, $props);

View File

@@ -3,6 +3,7 @@
namespace App\Domains\Tenant\Requests;
use App\Domains\Prop\Support\PropRules;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Support\TenantDomainNormalizer;
use Closure;
use Illuminate\Foundation\Http\FormRequest;
@@ -50,7 +51,7 @@ class StoreTenantRequest extends FormRequest
'max:255',
Rule::unique('tenants', 'dominio'),
],
...PropRules::sync(),
...PropRules::sync(Tenant::class),
];
}
}

View File

@@ -59,7 +59,7 @@ class UpdateTenantRequest extends FormRequest
'max:255',
Rule::unique('tenants', 'dominio')->ignore($tenant?->id),
],
...PropRules::sync(),
...PropRules::sync(Tenant::class),
];
}
}