From cde27c0d34156cc96362d92626e8a26d3aae5534 Mon Sep 17 00:00:00 2001 From: ncoronel Date: Mon, 22 Jun 2026 12:45:23 -0300 Subject: [PATCH] Add PropController, StorePropRequest, UpdatePropRequest, PropResource, and PropableModels; define API routes for props management --- .../Prop/Controllers/PropController.php | 70 +++++++++++++++++++ .../Prop/Requests/StorePropRequest.php | 27 +++++++ .../Prop/Requests/UpdatePropRequest.php | 31 ++++++++ app/Domains/Prop/Resources/PropResource.php | 29 ++++++++ app/Domains/Prop/Support/PropableModels.php | 42 +++++++++++ app/Domains/Prop/routes/api.php | 10 +++ routes/api.php | 1 + 7 files changed, 210 insertions(+) create mode 100644 app/Domains/Prop/Controllers/PropController.php create mode 100644 app/Domains/Prop/Requests/StorePropRequest.php create mode 100644 app/Domains/Prop/Requests/UpdatePropRequest.php create mode 100644 app/Domains/Prop/Resources/PropResource.php create mode 100644 app/Domains/Prop/Support/PropableModels.php create mode 100644 app/Domains/Prop/routes/api.php diff --git a/app/Domains/Prop/Controllers/PropController.php b/app/Domains/Prop/Controllers/PropController.php new file mode 100644 index 0000000..1225e72 --- /dev/null +++ b/app/Domains/Prop/Controllers/PropController.php @@ -0,0 +1,70 @@ +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/Requests/StorePropRequest.php b/app/Domains/Prop/Requests/StorePropRequest.php new file mode 100644 index 0000000..cf5157a --- /dev/null +++ b/app/Domains/Prop/Requests/StorePropRequest.php @@ -0,0 +1,27 @@ + + */ + 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_id' => ['required', 'integer', 'exists:props_data_types,id'], + ]; + } +} diff --git a/app/Domains/Prop/Requests/UpdatePropRequest.php b/app/Domains/Prop/Requests/UpdatePropRequest.php new file mode 100644 index 0000000..ebe07ae --- /dev/null +++ b/app/Domains/Prop/Requests/UpdatePropRequest.php @@ -0,0 +1,31 @@ + + */ + 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_id' => ['required', 'integer', 'exists:props_data_types,id'], + ]; + } +} diff --git a/app/Domains/Prop/Resources/PropResource.php b/app/Domains/Prop/Resources/PropResource.php new file mode 100644 index 0000000..4b17ec9 --- /dev/null +++ b/app/Domains/Prop/Resources/PropResource.php @@ -0,0 +1,29 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'propable_type' => $this->propable_type, + 'codigo' => $this->codigo, + 'nombre' => $this->nombre, + 'is_required' => $this->is_required, + 'data_type_id' => $this->data_type_id, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + ]; + } +} diff --git a/app/Domains/Prop/Support/PropableModels.php b/app/Domains/Prop/Support/PropableModels.php new file mode 100644 index 0000000..de3d7ea --- /dev/null +++ b/app/Domains/Prop/Support/PropableModels.php @@ -0,0 +1,42 @@ +> + */ + 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; + } +} diff --git a/app/Domains/Prop/routes/api.php b/app/Domains/Prop/routes/api.php new file mode 100644 index 0000000..dfbce5b --- /dev/null +++ b/app/Domains/Prop/routes/api.php @@ -0,0 +1,10 @@ +parameters([ + 'prop-models' => 'propableType', + 'props' => 'prop', + ]); diff --git a/routes/api.php b/routes/api.php index c133d57..fe96379 100644 --- a/routes/api.php +++ b/routes/api.php @@ -8,4 +8,5 @@ Route::get('/user', function (Request $request) { })->middleware('auth:sanctum'); require __DIR__.'/../app/Domains/Product/routes/api.php'; +require __DIR__.'/../app/Domains/Prop/routes/api.php'; require __DIR__.'/../app/Domains/Tenant/routes/api.php';