diff --git a/app/Domains/Catalog/Controllers/BrandController.php b/app/Domains/Catalog/Controllers/BrandController.php index 30b3584..1529e0a 100644 --- a/app/Domains/Catalog/Controllers/BrandController.php +++ b/app/Domains/Catalog/Controllers/BrandController.php @@ -19,10 +19,7 @@ class BrandController extends Controller public function store(StoreBrandRequest $request): JsonResponse { - $validated = $request->validated(); - $props = $validated['props'] ?? []; - - $brand = Brand::createWithProps($validated, $props); + $brand = Brand::query()->create($request->validated()); return BrandResource::make($brand)->response()->setStatusCode(201); } @@ -34,10 +31,7 @@ class BrandController extends Controller public function update(UpdateBrandRequest $request, Brand $marca): BrandResource { - $validated = $request->validated(); - $props = $validated['props'] ?? []; - - $marca = $marca->updateWithProps($validated, $props); + $marca->update($request->validated()); return BrandResource::make($marca); } diff --git a/app/Domains/Catalog/Controllers/CategoryController.php b/app/Domains/Catalog/Controllers/CategoryController.php index 71b9bd3..c870e64 100644 --- a/app/Domains/Catalog/Controllers/CategoryController.php +++ b/app/Domains/Catalog/Controllers/CategoryController.php @@ -21,10 +21,7 @@ class CategoryController extends Controller public function store(StoreCategoryRequest $request): JsonResponse { - $validated = $request->validated(); - $props = $validated['props'] ?? []; - - $category = Category::createWithProps($validated, $props); + $category = Category::query()->create($request->validated()); return CategoryResource::make($category->load(['parent', 'subCategories', 'tenant'])) ->response() @@ -38,10 +35,7 @@ class CategoryController extends Controller public function update(UpdateCategoryRequest $request, Category $categoria): CategoryResource { - $validated = $request->validated(); - $props = $validated['props'] ?? []; - - $categoria = $categoria->updateWithProps($validated, $props); + $categoria->update($request->validated()); return CategoryResource::make($categoria->load(['parent', 'subCategories', 'tenant'])); } diff --git a/app/Domains/Catalog/Controllers/ProductController.php b/app/Domains/Catalog/Controllers/ProductController.php index a14a4fb..6236d3c 100644 --- a/app/Domains/Catalog/Controllers/ProductController.php +++ b/app/Domains/Catalog/Controllers/ProductController.php @@ -19,10 +19,7 @@ class ProductController extends Controller public function store(StoreProductRequest $request): JsonResponse { - $validated = $request->validated(); - $props = $validated['props'] ?? []; - - $product = Product::createWithProps($validated, $props); + $product = Product::query()->create($request->validated()); return ProductResource::make($product)->response()->setStatusCode(201); } @@ -34,10 +31,7 @@ class ProductController extends Controller public function update(UpdateProductRequest $request, Product $producto): ProductResource { - $validated = $request->validated(); - $props = $validated['props'] ?? []; - - $producto = $producto->updateWithProps($validated, $props); + $producto->update($request->validated()); return ProductResource::make($producto); } diff --git a/app/Domains/Catalog/Models/Brand.php b/app/Domains/Catalog/Models/Brand.php index ffb4688..6b28721 100644 --- a/app/Domains/Catalog/Models/Brand.php +++ b/app/Domains/Catalog/Models/Brand.php @@ -2,7 +2,6 @@ namespace App\Domains\Catalog\Models; -use App\Domains\Prop\Concerns\Propable; use App\Domains\Tenant\Models\Tenant; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -17,7 +16,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; class Brand extends Model { use HasFactory; - use Propable; protected $table = 'brands'; diff --git a/app/Domains/Catalog/Models/Category.php b/app/Domains/Catalog/Models/Category.php index 1803f6c..5c95de1 100644 --- a/app/Domains/Catalog/Models/Category.php +++ b/app/Domains/Catalog/Models/Category.php @@ -2,7 +2,6 @@ namespace App\Domains\Catalog\Models; -use App\Domains\Prop\Concerns\Propable; use App\Domains\Tenant\Models\Tenant; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -18,7 +17,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; class Category extends Model { use HasFactory; - use Propable; protected $table = 'categorias'; diff --git a/app/Domains/Catalog/Models/Product.php b/app/Domains/Catalog/Models/Product.php index d9e5482..8063d72 100644 --- a/app/Domains/Catalog/Models/Product.php +++ b/app/Domains/Catalog/Models/Product.php @@ -2,7 +2,6 @@ namespace App\Domains\Catalog\Models; -use App\Domains\Prop\Concerns\Propable; use App\Domains\Tenant\Models\Tenant; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -21,7 +20,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; class Product extends Model { use HasFactory; - use Propable; protected $table = 'productos'; diff --git a/app/Domains/Catalog/Requests/StoreBrandRequest.php b/app/Domains/Catalog/Requests/StoreBrandRequest.php index cb151c7..3f87c5b 100644 --- a/app/Domains/Catalog/Requests/StoreBrandRequest.php +++ b/app/Domains/Catalog/Requests/StoreBrandRequest.php @@ -2,8 +2,6 @@ namespace App\Domains\Catalog\Requests; -use App\Domains\Catalog\Models\Brand; -use App\Domains\Prop\Support\PropRules; use Illuminate\Foundation\Http\FormRequest; class StoreBrandRequest extends FormRequest @@ -22,7 +20,6 @@ class StoreBrandRequest extends FormRequest 'tenant_codigo' => ['required', 'string', 'exists:tenants,codigo'], 'nombre' => ['required', 'string', 'max:255'], 'descripcion' => ['nullable', 'string'], - ...PropRules::sync(Brand::class), ]; } } diff --git a/app/Domains/Catalog/Requests/StoreCategoryRequest.php b/app/Domains/Catalog/Requests/StoreCategoryRequest.php index 08e75ee..77c4b97 100644 --- a/app/Domains/Catalog/Requests/StoreCategoryRequest.php +++ b/app/Domains/Catalog/Requests/StoreCategoryRequest.php @@ -2,8 +2,6 @@ namespace App\Domains\Catalog\Requests; -use App\Domains\Catalog\Models\Category; -use App\Domains\Prop\Support\PropRules; use Illuminate\Foundation\Http\FormRequest; class StoreCategoryRequest extends FormRequest @@ -22,7 +20,6 @@ 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(Category::class), ]; } } diff --git a/app/Domains/Catalog/Requests/StoreProductRequest.php b/app/Domains/Catalog/Requests/StoreProductRequest.php index 781f75e..72ec014 100644 --- a/app/Domains/Catalog/Requests/StoreProductRequest.php +++ b/app/Domains/Catalog/Requests/StoreProductRequest.php @@ -2,8 +2,6 @@ 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; @@ -26,7 +24,6 @@ class StoreProductRequest extends FormRequest 'nombre' => ['required', 'string', 'max:255'], 'descripcion' => ['nullable', 'string'], 'precio' => ['required', 'numeric', 'min:0'], - ...PropRules::sync(Product::class), ]; } } diff --git a/app/Domains/Catalog/Requests/UpdateBrandRequest.php b/app/Domains/Catalog/Requests/UpdateBrandRequest.php index 525c6ac..63b1c4f 100644 --- a/app/Domains/Catalog/Requests/UpdateBrandRequest.php +++ b/app/Domains/Catalog/Requests/UpdateBrandRequest.php @@ -2,8 +2,6 @@ namespace App\Domains\Catalog\Requests; -use App\Domains\Catalog\Models\Brand; -use App\Domains\Prop\Support\PropRules; use Illuminate\Foundation\Http\FormRequest; class UpdateBrandRequest extends FormRequest @@ -22,7 +20,6 @@ class UpdateBrandRequest extends FormRequest 'tenant_codigo' => ['required', 'string', 'exists:tenants,codigo'], 'nombre' => ['required', 'string', 'max:255'], 'descripcion' => ['nullable', 'string'], - ...PropRules::sync(Brand::class), ]; } } diff --git a/app/Domains/Catalog/Requests/UpdateCategoryRequest.php b/app/Domains/Catalog/Requests/UpdateCategoryRequest.php index e27f92e..5db12fb 100644 --- a/app/Domains/Catalog/Requests/UpdateCategoryRequest.php +++ b/app/Domains/Catalog/Requests/UpdateCategoryRequest.php @@ -3,7 +3,6 @@ namespace App\Domains\Catalog\Requests; use App\Domains\Catalog\Models\Category; -use App\Domains\Prop\Support\PropRules; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Rule; @@ -31,7 +30,6 @@ class UpdateCategoryRequest extends FormRequest Rule::notIn([$category?->id]), ], 'nombre' => ['required', 'string', 'max:255'], - ...PropRules::sync(Category::class), ]; } } diff --git a/app/Domains/Catalog/Requests/UpdateProductRequest.php b/app/Domains/Catalog/Requests/UpdateProductRequest.php index ef516e0..ed25e51 100644 --- a/app/Domains/Catalog/Requests/UpdateProductRequest.php +++ b/app/Domains/Catalog/Requests/UpdateProductRequest.php @@ -3,7 +3,6 @@ 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; @@ -34,7 +33,6 @@ class UpdateProductRequest extends FormRequest 'nombre' => ['required', 'string', 'max:255'], 'descripcion' => ['nullable', 'string'], 'precio' => ['required', 'numeric', 'min:0'], - ...PropRules::sync(Product::class), ]; } } diff --git a/app/Domains/Prop/Concerns/Propable.php b/app/Domains/Prop/Concerns/Propable.php deleted file mode 100644 index f6af543..0000000 --- a/app/Domains/Prop/Concerns/Propable.php +++ /dev/null @@ -1,138 +0,0 @@ - $attributes - * @param array $props - * @return static - */ - public static function createWithProps(array $attributes, array $props = []): static - { - /** @var static $model */ - $model = DB::transaction(function () use ($attributes, $props): Model { - /** @var static $createdModel */ - $createdModel = static::query()->create($attributes); - $createdModel->syncPropValues($props); - - return $createdModel; - }); - - return $model; - } - - /** - * @param array $attributes - */ - public static function createProp(array $attributes): Prop - { - return Prop::query()->create([ - ...$attributes, - 'propable_type' => static::class, - ]); - } - - /** - * @return Builder - */ - public function props(): Builder - { - return Prop::query()->forModel(static::class); - } - - /** - * @return HasMany - */ - public function propValues(): HasMany - { - return $this->hasMany(ModelPropValue::class, 'valuable_id') - ->whereHas('prop', fn (Builder $query) => $query->forModel(static::class)); - } - - public function getPropValue(Prop|string $prop): ?ModelPropValue - { - $resolvedProp = $this->resolveProp($prop); - - return $this->propValues() - ->where('prop_id', $resolvedProp->getKey()) - ->first(); - } - - public function setPropValue(Prop|string $prop, mixed $value): ModelPropValue - { - $this->ensurePropValuesCanBeManaged(); - - $resolvedProp = $this->resolveProp($prop); - - return $this->propValues()->updateOrCreate( - ['prop_id' => $resolvedProp->getKey()], - ['value' => $value], - ); - } - - /** - * @param array $props - */ - public function syncPropValues(array $props): void - { - foreach ($props as $codigo => $value) { - $this->setPropValue($codigo, $value); - } - } - - /** - * @param array $attributes - * @param array $props - */ - public function updateWithProps(array $attributes, array $props = []): static - { - DB::transaction(function () use ($attributes, $props): void { - $this->update($attributes); - $this->syncPropValues($props); - }); - - return $this; - } - - public function deletePropValue(Prop|string $prop): bool - { - $resolvedProp = $this->resolveProp($prop); - - return $this->propValues() - ->where('prop_id', $resolvedProp->getKey()) - ->delete() > 0; - } - - protected function ensurePropValuesCanBeManaged(): void - { - if (! $this->exists) { - throw new LogicException('Cannot manage prop values for an unsaved model.'); - } - } - - protected function resolveProp(Prop|string $prop): Prop - { - if ($prop instanceof Prop) { - if ($prop->propable_type !== static::class) { - throw new LogicException('The given prop does not belong to this model type.'); - } - - return $prop; - } - - return Prop::query() - ->forModel(static::class) - ->where('codigo', $prop) - ->firstOrFail(); - } -} diff --git a/app/Domains/Prop/Controllers/PropController.php b/app/Domains/Prop/Controllers/PropController.php deleted file mode 100644 index 1225e72..0000000 --- a/app/Domains/Prop/Controllers/PropController.php +++ /dev/null @@ -1,70 +0,0 @@ -forModel($modelClass)->latest()->get() - )->response(); - } - - public function store(StorePropRequest $request, string $propableType): JsonResponse - { - $modelClass = PropableModels::resolveOrFail($propableType); - - /** @var Prop $prop */ - $prop = $modelClass::createProp($request->validated()); - - return PropResource::make($prop)->response()->setStatusCode(201); - } - - public function show(string $propableType, Prop $prop): PropResource - { - $modelClass = PropableModels::resolveOrFail($propableType); - $prop = $this->resolveScopedProp($prop, $modelClass); - - return PropResource::make($prop); - } - - public function update(UpdatePropRequest $request, string $propableType, Prop $prop): PropResource - { - $modelClass = PropableModels::resolveOrFail($propableType); - $prop = $this->resolveScopedProp($prop, $modelClass); - $prop->update($request->validated()); - - return PropResource::make($prop); - } - - public function destroy(string $propableType, Prop $prop): Response - { - $modelClass = PropableModels::resolveOrFail($propableType); - $prop = $this->resolveScopedProp($prop, $modelClass); - $prop->delete(); - - return response()->noContent(); - } - - protected function resolveScopedProp(Prop $prop, string $modelClass): Prop - { - if ($prop->propable_type !== $modelClass) { - throw new NotFoundHttpException('Prop not found for the given model type.'); - } - - return $prop; - } -} diff --git a/app/Domains/Prop/Models/ModelPropValue.php b/app/Domains/Prop/Models/ModelPropValue.php deleted file mode 100644 index ea57800..0000000 --- a/app/Domains/Prop/Models/ModelPropValue.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ - public function prop(): BelongsTo - { - return $this->belongsTo(Prop::class, 'prop_id'); - } -} diff --git a/app/Domains/Prop/Models/Prop.php b/app/Domains/Prop/Models/Prop.php deleted file mode 100644 index 9b2e6c3..0000000 --- a/app/Domains/Prop/Models/Prop.php +++ /dev/null @@ -1,57 +0,0 @@ - - */ - protected function casts(): array - { - return [ - 'is_required' => 'boolean', - 'data_type' => PropDataType::class, - ]; - } - - /** - * @param Builder $query - */ - public function scopeForModel(Builder $query, Model|string $model): void - { - $query->where('propable_type', is_string($model) ? $model : $model::class); - } - - /** - * @return HasMany - */ - public function options(): HasMany - { - return $this->hasMany(PropOption::class); - } - - /** - * @return HasMany - */ - public function modelValues(): HasMany - { - return $this->hasMany(ModelPropValue::class, 'prop_id'); - } -} diff --git a/app/Domains/Prop/Models/PropOption.php b/app/Domains/Prop/Models/PropOption.php deleted file mode 100644 index 32416de..0000000 --- a/app/Domains/Prop/Models/PropOption.php +++ /dev/null @@ -1,27 +0,0 @@ - - */ - public function prop(): BelongsTo - { - return $this->belongsTo(Prop::class); - } -} diff --git a/app/Domains/Prop/Requests/StorePropRequest.php b/app/Domains/Prop/Requests/StorePropRequest.php deleted file mode 100644 index 181b2b8..0000000 --- a/app/Domains/Prop/Requests/StorePropRequest.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ - public function rules(): array - { - return [ - 'codigo' => ['required', 'string', 'max:255', Rule::unique('props', 'codigo')], - 'nombre' => ['required', 'string', 'max:255'], - 'is_required' => ['sometimes', 'boolean'], - 'data_type' => ['required', Rule::enum(PropDataType::class)], - ]; - } -} diff --git a/app/Domains/Prop/Requests/UpdatePropRequest.php b/app/Domains/Prop/Requests/UpdatePropRequest.php deleted file mode 100644 index 9fc5c90..0000000 --- a/app/Domains/Prop/Requests/UpdatePropRequest.php +++ /dev/null @@ -1,32 +0,0 @@ - - */ - public function rules(): array - { - /** @var Prop|null $prop */ - $prop = $this->route('prop'); - - return [ - 'codigo' => ['required', 'string', 'max:255', Rule::unique('props', 'codigo')->ignore($prop?->id)], - 'nombre' => ['required', 'string', 'max:255'], - 'is_required' => ['sometimes', 'boolean'], - 'data_type' => ['required', Rule::enum(PropDataType::class)], - ]; - } -} diff --git a/app/Domains/Prop/Resources/PropResource.php b/app/Domains/Prop/Resources/PropResource.php deleted file mode 100644 index 79b421d..0000000 --- a/app/Domains/Prop/Resources/PropResource.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ - public function toArray(Request $request): array - { - return [ - 'id' => $this->id, - 'propable_type' => PropableModels::aliasFor($this->propable_type) ?? $this->propable_type, - 'codigo' => $this->codigo, - 'nombre' => $this->nombre, - 'is_required' => $this->is_required, - 'data_type' => $this->data_type?->value, - 'created_at' => $this->created_at, - 'updated_at' => $this->updated_at, - ]; - } -} diff --git a/app/Domains/Prop/Resources/PropValueResource.php b/app/Domains/Prop/Resources/PropValueResource.php deleted file mode 100644 index 1a5b16a..0000000 --- a/app/Domains/Prop/Resources/PropValueResource.php +++ /dev/null @@ -1,50 +0,0 @@ - $propValues - * @return array - */ - public static function collapsed(iterable $propValues): array - { - return collect($propValues) - ->mapWithKeys(fn (ModelPropValue $propValue) => [ - $propValue->prop->codigo => $propValue->value, - ]) - ->all(); - } - - /** - * @return array - */ - public static function collapsedFromPropable(object $model): array - { - if (! in_array(Propable::class, class_uses_recursive($model), true)) { - throw new InvalidArgumentException('The given model must use the Propable trait.'); - } - - return static::collapsed( - $model->propValues()->with('prop')->get(), - ); - } - - /** - * @return array - */ - public function toArray(Request $request): array - { - return [$this->prop->codigo => $this->value]; - } -} diff --git a/app/Domains/Prop/Support/PropDataType.php b/app/Domains/Prop/Support/PropDataType.php deleted file mode 100644 index 4de2f95..0000000 --- a/app/Domains/Prop/Support/PropDataType.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ - public static function values(): array - { - return array_map( - static fn (self $type): string => $type->value, - self::cases(), - ); - } -} diff --git a/app/Domains/Prop/Support/PropRules.php b/app/Domains/Prop/Support/PropRules.php deleted file mode 100644 index f3c2d9d..0000000 --- a/app/Domains/Prop/Support/PropRules.php +++ /dev/null @@ -1,60 +0,0 @@ - - */ - public static function sync(string $modelClass): array - { - return [ - '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), - )); - } -} diff --git a/app/Domains/Prop/Support/PropableModels.php b/app/Domains/Prop/Support/PropableModels.php deleted file mode 100644 index e55c89e..0000000 --- a/app/Domains/Prop/Support/PropableModels.php +++ /dev/null @@ -1,47 +0,0 @@ -> - */ - public static function map(): array - { - return [ - 'brand' => Brand::class, - 'category' => Category::class, - 'product' => Product::class, - 'tenant' => Tenant::class, - ]; - } - - /** - * @return class-string - */ - public static function resolveOrFail(string $alias): string - { - $modelClass = Arr::get(static::map(), $alias); - - if (! is_string($modelClass) || ! is_subclass_of($modelClass, Model::class) || ! in_array(Propable::class, class_uses_recursive($modelClass), true)) { - throw new NotFoundHttpException('Propable model not found.'); - } - - return $modelClass; - } - - public static function aliasFor(string $modelClass): ?string - { - return array_search($modelClass, static::map(), true) ?: null; - } -} diff --git a/app/Domains/Prop/routes/api.php b/app/Domains/Prop/routes/api.php deleted file mode 100644 index dfbce5b..0000000 --- a/app/Domains/Prop/routes/api.php +++ /dev/null @@ -1,10 +0,0 @@ -parameters([ - 'prop-models' => 'propableType', - 'props' => 'prop', - ]); diff --git a/app/Domains/Tenant/Controllers/TenantController.php b/app/Domains/Tenant/Controllers/TenantController.php index abe38db..7774207 100644 --- a/app/Domains/Tenant/Controllers/TenantController.php +++ b/app/Domains/Tenant/Controllers/TenantController.php @@ -19,10 +19,7 @@ class TenantController extends Controller public function store(StoreTenantRequest $request): JsonResponse { - $validated = $request->validated(); - $props = $validated['props'] ?? []; - - $tenant = Tenant::createWithProps($validated, $props); + $tenant = Tenant::query()->create($request->validated()); return TenantResource::make($tenant)->response()->setStatusCode(201); } @@ -34,10 +31,7 @@ class TenantController extends Controller public function update(UpdateTenantRequest $request, Tenant $tenant): TenantResource { - $validated = $request->validated(); - $props = $validated['props'] ?? []; - - $tenant = $tenant->updateWithProps($validated, $props); + $tenant->update($request->validated()); return TenantResource::make($tenant); } diff --git a/app/Domains/Tenant/Controllers/TenantPropController.php b/app/Domains/Tenant/Controllers/TenantPropController.php deleted file mode 100644 index 94f3c34..0000000 --- a/app/Domains/Tenant/Controllers/TenantPropController.php +++ /dev/null @@ -1,61 +0,0 @@ -props()->latest()->get() - )->response(); - } - - public function store(StoreTenantPropRequest $request): JsonResponse - { - /** @var Prop $prop */ - $prop = Tenant::createProp($request->validated()); - - return PropResource::make($prop)->response()->setStatusCode(201); - } - - public function show(Prop $tenantProp): PropResource - { - return PropResource::make($this->resolveScopedProp($tenantProp)); - } - - public function update(UpdateTenantPropRequest $request, Prop $tenantProp): PropResource - { - $tenantProp = $this->resolveScopedProp($tenantProp); - $tenantProp->update($request->validated()); - - return PropResource::make($tenantProp); - } - - public function destroy(Prop $tenantProp): Response - { - $tenantProp = $this->resolveScopedProp($tenantProp); - $tenantProp->delete(); - - return response()->noContent(); - } - - protected function resolveScopedProp(Prop $prop): Prop - { - if ($prop->propable_type !== Tenant::class) { - throw new NotFoundHttpException('Tenant prop not found.'); - } - - return $prop; - } -} diff --git a/app/Domains/Tenant/Models/Tenant.php b/app/Domains/Tenant/Models/Tenant.php index 48937e2..c06e0ec 100644 --- a/app/Domains/Tenant/Models/Tenant.php +++ b/app/Domains/Tenant/Models/Tenant.php @@ -2,7 +2,6 @@ namespace App\Domains\Tenant\Models; -use App\Domains\Prop\Concerns\Propable; use App\Domains\Catalog\Models\Product; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -17,7 +16,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; class Tenant extends Model { use HasFactory; - use Propable; /** * @return HasMany diff --git a/app/Domains/Tenant/Requests/StoreTenantPropRequest.php b/app/Domains/Tenant/Requests/StoreTenantPropRequest.php deleted file mode 100644 index 1b0b74a..0000000 --- a/app/Domains/Tenant/Requests/StoreTenantPropRequest.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ - public function rules(): array - { - return [ - 'codigo' => ['required', 'string', 'max:255', Rule::unique('props', 'codigo')], - 'nombre' => ['required', 'string', 'max:255'], - 'is_required' => ['sometimes', 'boolean'], - 'data_type' => ['required', Rule::enum(PropDataType::class)], - ]; - } -} diff --git a/app/Domains/Tenant/Requests/StoreTenantRequest.php b/app/Domains/Tenant/Requests/StoreTenantRequest.php index 59ab351..5557f81 100644 --- a/app/Domains/Tenant/Requests/StoreTenantRequest.php +++ b/app/Domains/Tenant/Requests/StoreTenantRequest.php @@ -2,8 +2,6 @@ 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; @@ -51,7 +49,6 @@ class StoreTenantRequest extends FormRequest 'max:255', Rule::unique('tenants', 'dominio'), ], - ...PropRules::sync(Tenant::class), ]; } } diff --git a/app/Domains/Tenant/Requests/UpdateTenantPropRequest.php b/app/Domains/Tenant/Requests/UpdateTenantPropRequest.php deleted file mode 100644 index b5388f8..0000000 --- a/app/Domains/Tenant/Requests/UpdateTenantPropRequest.php +++ /dev/null @@ -1,32 +0,0 @@ - - */ - public function rules(): array - { - /** @var Prop|null $tenantProp */ - $tenantProp = $this->route('tenantProp'); - - return [ - 'codigo' => ['required', 'string', 'max:255', Rule::unique('props', 'codigo')->ignore($tenantProp?->id)], - 'nombre' => ['required', 'string', 'max:255'], - 'is_required' => ['sometimes', 'boolean'], - 'data_type' => ['required', Rule::enum(PropDataType::class)], - ]; - } -} diff --git a/app/Domains/Tenant/Requests/UpdateTenantRequest.php b/app/Domains/Tenant/Requests/UpdateTenantRequest.php index 94e5a2e..365b98c 100644 --- a/app/Domains/Tenant/Requests/UpdateTenantRequest.php +++ b/app/Domains/Tenant/Requests/UpdateTenantRequest.php @@ -2,7 +2,6 @@ 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; @@ -59,7 +58,6 @@ class UpdateTenantRequest extends FormRequest 'max:255', Rule::unique('tenants', 'dominio')->ignore($tenant?->id), ], - ...PropRules::sync(Tenant::class), ]; } } diff --git a/app/Domains/Tenant/Resources/TenantResource.php b/app/Domains/Tenant/Resources/TenantResource.php index 623d9a9..91a027a 100644 --- a/app/Domains/Tenant/Resources/TenantResource.php +++ b/app/Domains/Tenant/Resources/TenantResource.php @@ -2,7 +2,6 @@ namespace App\Domains\Tenant\Resources; -use App\Domains\Prop\Resources\PropValueResource; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; @@ -21,7 +20,6 @@ class TenantResource extends JsonResource 'codigo' => $this->codigo, 'nombre' => $this->nombre, 'dominio' => $this->dominio, - 'props' => PropValueResource::collapsedFromPropable($this->resource) ]; } } diff --git a/app/Domains/Tenant/routes/api.php b/app/Domains/Tenant/routes/api.php index 70623bf..69464a8 100644 --- a/app/Domains/Tenant/routes/api.php +++ b/app/Domains/Tenant/routes/api.php @@ -2,12 +2,9 @@ use App\Domains\Tenant\Controllers\BootstrapTenantController; use App\Domains\Tenant\Controllers\TenantController; -use App\Domains\Tenant\Controllers\TenantPropController; use Illuminate\Support\Facades\Route; Route::get('tenants/bootstrap/{dominio}', BootstrapTenantController::class) ->where('dominio', '.*'); Route::apiResource('tenants', TenantController::class); -Route::apiResource('tenant-props', TenantPropController::class) - ->parameters(['tenant-props' => 'tenantProp']); diff --git a/database/migrations/2026_06_22_120100_create_props_table.php b/database/migrations/2026_06_22_120100_create_props_table.php deleted file mode 100644 index 87aec31..0000000 --- a/database/migrations/2026_06_22_120100_create_props_table.php +++ /dev/null @@ -1,34 +0,0 @@ -id(); - $table->string('propable_type'); - $table->string('codigo')->unique(); - $table->string('nombre'); - $table->boolean('is_required')->default(false); - $table->string('data_type'); - $table->timestamps(); - - $table->index('propable_type'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('props'); - } -}; diff --git a/database/migrations/2026_06_22_120200_create_prop_options_table.php b/database/migrations/2026_06_22_120200_create_prop_options_table.php deleted file mode 100644 index 77c37d8..0000000 --- a/database/migrations/2026_06_22_120200_create_prop_options_table.php +++ /dev/null @@ -1,33 +0,0 @@ -id(); - $table->foreignId('prop_id')->constrained('props')->cascadeOnUpdate()->cascadeOnDelete(); - $table->string('value'); - $table->string('label'); - $table->unsignedInteger('sort_order')->default(0); - $table->timestamps(); - - $table->unique(['prop_id', 'value']); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('prop_options'); - } -}; diff --git a/database/migrations/2026_06_22_120300_create_model_prop_values_table.php b/database/migrations/2026_06_22_120300_create_model_prop_values_table.php deleted file mode 100644 index 0e3f8ba..0000000 --- a/database/migrations/2026_06_22_120300_create_model_prop_values_table.php +++ /dev/null @@ -1,33 +0,0 @@ -id(); - $table->unsignedBigInteger('valuable_id'); - $table->foreignId('prop_id')->constrained('props')->cascadeOnUpdate()->cascadeOnDelete(); - $table->text('value')->nullable(); - $table->timestamps(); - - $table->unique(['prop_id', 'valuable_id']); - $table->index('valuable_id'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('model_prop_values'); - } -}; diff --git a/database/migrations/2026_06_22_130000_convert_prop_data_types_to_enum.php b/database/migrations/2026_06_22_130000_convert_prop_data_types_to_enum.php deleted file mode 100644 index edee49e..0000000 --- a/database/migrations/2026_06_22_130000_convert_prop_data_types_to_enum.php +++ /dev/null @@ -1,106 +0,0 @@ -string('data_type')->nullable()->after('is_required'); - }); - - if (Schema::hasTable('props_data_types')) { - $typeMap = DB::table('props_data_types') - ->pluck('code', 'id') - ->map(static fn (mixed $code): string => in_array($code, PropDataType::values(), true) ? (string) $code : PropDataType::String->value) - ->all(); - - DB::table('props') - ->select(['id', 'data_type_id']) - ->orderBy('id') - ->get() - ->each(function (object $prop) use ($typeMap): void { - DB::table('props') - ->where('id', $prop->id) - ->update([ - 'data_type' => $typeMap[$prop->data_type_id] ?? PropDataType::String->value, - ]); - }); - } else { - DB::table('props')->update([ - 'data_type' => PropDataType::String->value, - ]); - } - - Schema::table('props', function (Blueprint $table) { - $table->dropForeign(['data_type_id']); - $table->dropColumn('data_type_id'); - }); - - Schema::table('props', function (Blueprint $table) { - $table->string('data_type')->nullable(false)->change(); - }); - } - - if (Schema::hasTable('props_data_types')) { - Schema::drop('props_data_types'); - } - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - if (! Schema::hasTable('props_data_types')) { - Schema::create('props_data_types', function (Blueprint $table) { - $table->id(); - $table->string('name'); - $table->string('code')->unique(); - $table->timestamps(); - }); - - DB::table('props_data_types')->insert([ - [ - 'id' => 1, - 'name' => 'String', - 'code' => PropDataType::String->value, - 'created_at' => now(), - 'updated_at' => now(), - ], - ]); - } - - if (Schema::hasTable('props') && Schema::hasColumn('props', 'data_type') && ! Schema::hasColumn('props', 'data_type_id')) { - Schema::table('props', function (Blueprint $table) { - $table->foreignId('data_type_id')->nullable()->after('is_required')->constrained('props_data_types')->cascadeOnUpdate()->restrictOnDelete(); - }); - - $stringTypeId = DB::table('props_data_types') - ->where('code', PropDataType::String->value) - ->value('id'); - - DB::table('props')->update([ - 'data_type_id' => $stringTypeId, - ]); - - Schema::table('props', function (Blueprint $table) { - $table->foreignId('data_type_id')->nullable(false)->change(); - $table->dropColumn('data_type'); - }); - } - } -}; diff --git a/routes/api.php b/routes/api.php index 3cc32f0..0f64bbf 100644 --- a/routes/api.php +++ b/routes/api.php @@ -8,5 +8,4 @@ Route::get('/user', function (Request $request) { })->middleware('auth:sanctum'); require __DIR__.'/../app/Domains/Catalog/routes/api.php'; -require __DIR__.'/../app/Domains/Prop/routes/api.php'; require __DIR__.'/../app/Domains/Tenant/routes/api.php'; diff --git a/tests/Feature/Prop/PropControllerTest.php b/tests/Feature/Prop/PropControllerTest.php deleted file mode 100644 index 50f1928..0000000 --- a/tests/Feature/Prop/PropControllerTest.php +++ /dev/null @@ -1,45 +0,0 @@ -postJson('/api/prop-models/tenant/props', [ - 'codigo' => 'color_primario', - 'nombre' => 'Color primario', - 'is_required' => false, - 'data_type' => 'string', - ]); - - $response - ->assertCreated() - ->assertJsonPath('propable_type', 'tenant') - ->assertJsonPath('data_type', 'string'); - - $this->assertDatabaseHas('props', [ - 'codigo' => 'color_primario', - 'data_type' => 'string', - ]); - } - - public function test_it_rejects_unknown_enum_data_type(): void - { - $response = $this->postJson('/api/prop-models/tenant/props', [ - 'codigo' => 'color_primario', - 'nombre' => 'Color primario', - 'is_required' => false, - 'data_type' => 'unsupported-type', - ]); - - $response - ->assertUnprocessable() - ->assertJsonValidationErrors(['data_type']); - } -} diff --git a/tests/Feature/Tenant/BootstrapTenantControllerTest.php b/tests/Feature/Tenant/BootstrapTenantControllerTest.php index 4c749dc..16e549b 100644 --- a/tests/Feature/Tenant/BootstrapTenantControllerTest.php +++ b/tests/Feature/Tenant/BootstrapTenantControllerTest.php @@ -10,7 +10,7 @@ class BootstrapTenantControllerTest extends TestCase { use RefreshDatabase; - public function test_it_bootstraps_a_tenant_by_domain_and_includes_props(): void + public function test_it_bootstraps_a_tenant_by_domain(): void { $tenant = Tenant::create([ 'codigo' => 'acme', @@ -18,22 +18,12 @@ class BootstrapTenantControllerTest extends TestCase 'dominio' => 'acme.com', ]); - Tenant::createProp([ - 'codigo' => 'primary_color', - 'nombre' => 'Primary Color', - 'is_required' => false, - 'data_type' => 'string', - ]); - - $tenant->setPropValue('primary_color', 'blue'); - $response = $this->getJson('/api/tenants/bootstrap/acme.com'); $response ->assertOk() ->assertJsonPath('codigo', 'acme') - ->assertJsonPath('dominio', 'acme.com') - ->assertJsonPath('props.primary_color', 'blue'); + ->assertJsonPath('dominio', 'acme.com'); } public function test_it_bootstraps_a_tenant_from_a_full_url(): void