Browse Source

feat: adiciona sociedade para unidade

ebagabee 2 weeks ago
parent
commit
bd2519a884

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

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

+ 44 - 0
app/Http/Requests/UnitPartnerRequest.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class UnitPartnerRequest extends FormRequest
+{
+    public function rules(): array
+    {
+        $isCreate = $this->isMethod('POST');
+
+        $rules = [
+            'unit_id'          => 'sometimes|required|integer|exists:units,id',
+            'name'             => 'sometimes|required|string|max:255',
+            'social_name'      => 'sometimes|nullable|string|max:255',
+            'role'             => 'sometimes|nullable|string|max:100',
+            'cpf'              => 'sometimes|required|string|max:20',
+            'rg'               => 'sometimes|nullable|string|max:30',
+            'birth_date'       => 'sometimes|nullable|date',
+            'participation'    => 'sometimes|nullable|numeric|min:0|max:100',
+            'email'            => 'sometimes|nullable|email|max:255',
+            'secondary_email'  => 'sometimes|nullable|email|max:255',
+            'phone_number'     => 'sometimes|nullable|string|max:20',
+            'cell_number'      => 'sometimes|nullable|string|max:20',
+            'postal_code'      => 'sometimes|nullable|string|max:9',
+            'street'           => 'sometimes|nullable|string|max:255',
+            'address_number'   => 'sometimes|nullable|string|max:20',
+            'neighborhood'     => 'sometimes|nullable|string|max:255',
+            'complement'       => 'sometimes|nullable|string|max:255',
+            'city_id'          => 'sometimes|nullable|integer|exists:cities,id',
+            'state_id'         => 'sometimes|nullable|integer|exists:states,id',
+            'avatar'           => 'sometimes|nullable|image|max:2048',
+        ];
+
+        if ($isCreate) {
+            $rules['unit_id'] = 'required|integer|exists:units,id';
+            $rules['name']    = 'required|string|max:255';
+            $rules['cpf']     = 'required|string|max:20';
+        }
+
+        return $rules;
+    }
+}

+ 64 - 0
app/Http/Resources/UnitPartnerResource.php

@@ -0,0 +1,64 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Carbon\Carbon;
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\JsonResource;
+use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
+use Illuminate\Support\Facades\Storage;
+use App\Models\UnitPartner;
+
+class UnitPartnerResource extends JsonResource
+{
+    public function toArray(Request $request): array
+    {
+        return [
+            'id'               => $this->id,
+            'unit_id'          => $this->unit_id,
+            'name'             => $this->name,
+            'social_name'      => $this->social_name,
+            'role'             => $this->role,
+            'cpf'              => $this->cpf,
+            'rg'               => $this->rg,
+            'birth_date'       => $this->birth_date?->format('Y-m-d'),
+            'participation'    => $this->participation,
+            'email'            => $this->email,
+            'secondary_email'  => $this->secondary_email,
+            'phone_number'     => $this->phone_number,
+            'cell_number'      => $this->cell_number,
+            'postal_code'      => $this->postal_code,
+            'street'           => $this->street,
+            'address_number'   => $this->address_number,
+            'neighborhood'     => $this->neighborhood,
+            'complement'       => $this->complement,
+            'city_id'          => $this->city_id,
+            'state_id'         => $this->state_id,
+            'avatar_url'       => $this->avatar_url
+                ? Storage::disk('public')->url($this->avatar_url)
+                : null,
+            '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'),
+
+            'city' => $this->whenLoaded('city', fn() => [
+                'id'   => $this->city->id,
+                'name' => $this->city->name,
+            ]),
+
+            'state' => $this->whenLoaded('state', fn() => [
+                'id'   => $this->state->id,
+                'name' => $this->state->name,
+                'code' => $this->state->code,
+            ]),
+        ];
+    }
+
+    /**
+     * @param \Illuminate\Database\Eloquent\Collection<UnitPartner> $resource
+     * @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection<UnitPartnerResource>
+     */
+    public static function collection($resource): AnonymousResourceCollection
+    {
+        return parent::collection($resource);
+    }
+}

+ 6 - 0
app/Models/Unit.php

@@ -5,6 +5,7 @@
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\HasMany;
 use Illuminate\Database\Eloquent\SoftDeletes;
 
 /**
@@ -55,4 +56,9 @@ public function state(): BelongsTo
     {
         return $this->belongsTo(State::class, 'state_id');
     }
+
+    public function partners(): HasMany
+    {
+        return $this->hasMany(UnitPartner::class, 'unit_id');
+    }
 }

+ 69 - 0
app/Models/UnitPartner.php

@@ -0,0 +1,69 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\SoftDeletes;
+
+/**
+ * @property int $id
+ * @property int $unit_id
+ * @property string $name
+ * @property string|null $social_name
+ * @property string|null $role
+ * @property string $cpf
+ * @property string|null $rg
+ * @property \Carbon\Carbon|null $birth_date
+ * @property float|null $participation
+ * @property string|null $email
+ * @property string|null $secondary_email
+ * @property string|null $phone_number
+ * @property string|null $cell_number
+ * @property string|null $postal_code
+ * @property string|null $street
+ * @property string|null $address_number
+ * @property string|null $neighborhood
+ * @property string|null $complement
+ * @property int|null $city_id
+ * @property int|null $state_id
+ * @property string|null $avatar_url
+ * @property \Carbon\Carbon $created_at
+ * @property \Carbon\Carbon $updated_at
+ * @property \Carbon\Carbon|null $deleted_at
+ * @property-read \App\Models\Unit $unit
+ * @property-read \App\Models\City|null $city
+ * @property-read \App\Models\State|null $state
+ */
+class UnitPartner extends Model
+{
+    use HasFactory, SoftDeletes;
+
+    protected $table = 'unit_partners';
+
+    protected $guarded = ['id'];
+
+    protected $casts = [
+        'birth_date'  => 'date',
+        'participation' => 'decimal:2',
+        'created_at'  => 'datetime',
+        'updated_at'  => 'datetime',
+        'deleted_at'  => 'datetime',
+    ];
+
+    public function unit(): BelongsTo
+    {
+        return $this->belongsTo(Unit::class, 'unit_id');
+    }
+
+    public function city(): BelongsTo
+    {
+        return $this->belongsTo(City::class, 'city_id');
+    }
+
+    public function state(): BelongsTo
+    {
+        return $this->belongsTo(State::class, 'state_id');
+    }
+}

+ 87 - 0
app/Services/UnitPartnerService.php

@@ -0,0 +1,87 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\UnitPartner;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Http\UploadedFile;
+use Illuminate\Support\Facades\Storage;
+
+class UnitPartnerService
+{
+    public function getAll(): Collection
+    {
+        return UnitPartner::with(['city', 'state'])
+            ->orderBy('name')
+            ->get();
+    }
+
+    public function getByUnitId(int $unitId): Collection
+    {
+        return UnitPartner::with(['city', 'state'])
+            ->where('unit_id', $unitId)
+            ->orderBy('name')
+            ->get();
+    }
+
+    public function findById(int $id): ?UnitPartner
+    {
+        return UnitPartner::with(['city', 'state'])->find($id);
+    }
+
+    public function create(array $data): UnitPartner
+    {
+        $data = $this->handleAvatar($data);
+        return UnitPartner::create($data);
+    }
+
+    public function update(int $id, array $data): ?UnitPartner
+    {
+        $model = $this->findById($id);
+
+        if (!$model) {
+            return null;
+        }
+
+        $data = $this->handleAvatar($data, $model->avatar_url);
+        $model->update($data);
+        return $model->fresh(['city', 'state']);
+    }
+
+    public function delete(int $id): bool
+    {
+        $model = $this->findById($id);
+
+        if (!$model) {
+            return false;
+        }
+
+        if ($model->avatar_url) {
+            Storage::disk('public')->delete($model->avatar_url);
+        }
+
+        return $model->delete();
+    }
+
+    private function handleAvatar(array $data, ?string $oldAvatarPath = null): array
+    {
+        if (!isset($data['avatar'])) {
+            return $data;
+        }
+
+        if ($data['avatar'] instanceof UploadedFile) {
+            if ($oldAvatarPath) {
+                Storage::disk('public')->delete($oldAvatarPath);
+            }
+            $data['avatar_url'] = $data['avatar']->store('unit-partners/avatars', 'public');
+        } elseif (is_null($data['avatar'])) {
+            if ($oldAvatarPath) {
+                Storage::disk('public')->delete($oldAvatarPath);
+            }
+            $data['avatar_url'] = null;
+        }
+
+        unset($data['avatar']);
+        return $data;
+    }
+}

+ 46 - 0
database/migrations/2026_04_14_121806_create_unit_partners_table.php

@@ -0,0 +1,46 @@
+<?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('unit_partners', function (Blueprint $table) {
+            $table->id();
+            $table->foreignId('unit_id')->constrained('units')->cascadeOnDelete();
+            $table->string('name');
+            $table->string('social_name')->nullable();
+            $table->string('role')->nullable();
+            $table->string('cpf', 20);
+            $table->string('rg', 30)->nullable();
+            $table->date('birth_date')->nullable();
+            $table->decimal('participation', 5, 2)->nullable();
+            $table->string('email')->nullable();
+            $table->string('secondary_email')->nullable();
+            $table->string('phone_number', 20)->nullable();
+            $table->string('cell_number', 20)->nullable();
+            $table->string('postal_code', 9)->nullable();
+            $table->string('street')->nullable();
+            $table->string('address_number', 20)->nullable();
+            $table->string('neighborhood')->nullable();
+            $table->string('complement')->nullable();
+            $table->unsignedBigInteger('city_id')->nullable();
+            $table->unsignedBigInteger('state_id')->nullable();
+            $table->string('avatar_url')->nullable();
+            $table->timestamps();
+            $table->softDeletes();
+
+            $table->index('unit_id');
+            $table->foreign('city_id')->references('id')->on('cities')->nullOnDelete();
+            $table->foreign('state_id')->references('id')->on('states')->nullOnDelete();
+        });
+    }
+
+    public function down(): void
+    {
+        Schema::dropIfExists('unit_partners');
+    }
+};

+ 16 - 0
routes/authRoutes/unit_partner.php

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