Pārlūkot izejas kodu

✨ feat(category): adicionar módulo de categorias com CRUD e suporte a tipo

Fase: dev | Origin: melhoria-interna
Gustavo Zanatta 1 nedēļu atpakaļ
vecāks
revīzija
d9d4399159

+ 51 - 0
app/Http/Controllers/CategoryController.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Http\Requests\CategoryRequest;
+use App\Http\Resources\CategoryResource;
+use App\Services\CategoryService;
+use Illuminate\Http\JsonResponse;
+
+class CategoryController extends Controller
+{
+    public function __construct(protected CategoryService $service) {}
+
+    public function index(): JsonResponse
+    {
+        $type  = request()->query('type');
+        $items = $this->service->getAll($type);
+        return $this->successResponse(payload: CategoryResource::collection($items));
+    }
+
+    public function store(CategoryRequest $request): JsonResponse
+    {
+        $item = $this->service->create($request->validated());
+        return $this->successResponse(
+            payload: new CategoryResource($item),
+            message: __('messages.created'),
+            code: 201,
+        );
+    }
+
+    public function show(int $id): JsonResponse
+    {
+        $item = $this->service->findById($id);
+        return $this->successResponse(payload: new CategoryResource($item));
+    }
+
+    public function update(CategoryRequest $request, int $id): JsonResponse
+    {
+        $item = $this->service->update($id, $request->validated());
+        return $this->successResponse(
+            payload: new CategoryResource($item),
+            message: __('messages.updated'),
+        );
+    }
+
+    public function destroy(int $id): JsonResponse
+    {
+        $this->service->delete($id);
+        return $this->successResponse(message: __('messages.deleted'), code: 204);
+    }
+}

+ 23 - 0
app/Http/Requests/CategoryRequest.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class CategoryRequest extends FormRequest
+{
+    public function rules(): array
+    {
+        $rules = [
+            'name'   => 'sometimes|string|max:255',
+            'type'   => 'sometimes|nullable|string|in:partner,service,order',
+            'active' => 'sometimes|boolean',
+        ];
+
+        if ($this->isMethod('post')) {
+            $rules['name'] = 'required|string|max:255';
+        }
+
+        return $rules;
+    }
+}

+ 22 - 0
app/Http/Resources/CategoryResource.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Carbon\Carbon;
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class CategoryResource extends JsonResource
+{
+    public function toArray(Request $request): array
+    {
+        return [
+            'id'         => $this->id,
+            'name'       => $this->name,
+            'type'       => $this->type,
+            'active'     => $this->active,
+            'created_at' => Carbon::parse($this->created_at)->format('Y-m-d H:i:s'),
+            'updated_at' => Carbon::parse($this->updated_at)->format('Y-m-d H:i:s'),
+        ];
+    }
+}

+ 36 - 0
app/Models/Category.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\HasMany;
+use Illuminate\Database\Eloquent\SoftDeletes;
+
+class Category extends Model
+{
+    use SoftDeletes;
+
+    protected $guarded = ['id'];
+
+    protected function casts(): array
+    {
+        return [
+            'active' => 'boolean',
+        ];
+    }
+
+    public function partnerAgreements(): HasMany
+    {
+        return $this->hasMany(PartnerAgreement::class);
+    }
+
+    public function partnerAgreementServices(): HasMany
+    {
+        return $this->hasMany(PartnerAgreementService::class);
+    }
+
+    public function storeItems(): HasMany
+    {
+        return $this->hasMany(StoreItem::class);
+    }
+}

+ 49 - 0
app/Services/CategoryService.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\Category;
+use Illuminate\Database\Eloquent\Collection;
+
+class CategoryService
+{
+    public function getAll(?string $type = null): Collection
+    {
+        return Category::when($type, fn($q) => $q->where('type', $type))
+            ->orderBy('name')
+            ->get();
+    }
+
+    public function findById(int $id): ?Category
+    {
+        return Category::find($id);
+    }
+
+    public function create(array $data): Category
+    {
+        return Category::create($data);
+    }
+
+    public function update(int $id, array $data): ?Category
+    {
+        $model = $this->findById($id);
+
+        if (!$model) {
+            return null;
+        }
+
+        $model->update($data);
+        return $model->fresh();
+    }
+
+    public function delete(int $id): bool
+    {
+        $model = $this->findById($id);
+
+        if (!$model) {
+            return false;
+        }
+
+        return $model->delete();
+    }
+}

+ 26 - 0
database/migrations/2025_01_01_000004_create_categories_table.php

@@ -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('categories', function (Blueprint $table) {
+            $table->id();
+            $table->string('name');
+            $table->boolean('active')->default(true);
+            $table->timestamps();
+            $table->softDeletes();
+
+            $table->index('active');
+        });
+    }
+
+    public function down(): void
+    {
+        Schema::dropIfExists('categories');
+    }
+};

+ 22 - 0
database/migrations/2026_04_20_134056_add_type_to_categories_table.php

@@ -0,0 +1,22 @@
+<?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('categories', function (Blueprint $table) {
+            $table->string('type')->nullable()->index()->after('name');
+        });
+    }
+
+    public function down(): void
+    {
+        Schema::table('categories', function (Blueprint $table) {
+            $table->dropColumn('type');
+        });
+    }
+};

+ 16 - 0
routes/authRoutes/category.php

@@ -0,0 +1,16 @@
+<?php
+
+use App\Http\Controllers\CategoryController;
+use Illuminate\Support\Facades\Route;
+
+Route::controller(CategoryController::class)->prefix('category')->group(function () {
+    Route::get('/', 'index')->middleware('permission:categoria,view');
+
+    Route::post('/', 'store')->middleware('permission:categoria,add');
+
+    Route::get('/{id}', 'show')->middleware('permission:categoria,view');
+
+    Route::put('/{id}', 'update')->middleware('permission:categoria,edit');
+
+    Route::delete('/{id}', 'destroy')->middleware('permission:categoria,delete');
+});