Преглед изворни кода

feat: adiciona comentarios em ticket

ebagabee пре 3 недеља
родитељ
комит
668dbc530d

+ 33 - 0
app/Http/Controllers/SupportReplyController.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Services\SupportReplyService;
+use App\Http\Requests\SupportReplyRequest;
+use App\Http\Resources\SupportReplyResource;
+use Illuminate\Http\JsonResponse;
+
+class SupportReplyController extends Controller
+{
+    public function __construct(
+        protected SupportReplyService $service,
+    ) {}
+
+    public function index(int $ticketId): JsonResponse
+    {
+        $replies = $this->service->getByTicket($ticketId);
+        return $this->successResponse(payload: SupportReplyResource::collection($replies));
+    }
+
+    public function store(SupportReplyRequest $request, int $ticketId): JsonResponse
+    {
+        $reply = $this->service->create($ticketId, auth()->id(), $request->validated()['reply']);
+        return $this->successResponse(payload: new SupportReplyResource($reply), message: __('messages.created'), code: 201);
+    }
+
+    public function destroy(int $ticketId, int $id): JsonResponse
+    {
+        $this->service->delete($ticketId, $id);
+        return $this->successResponse(message: __('messages.deleted'), code: 204);
+    }
+}

+ 3 - 3
app/Http/Controllers/SupportTicketController.php

@@ -22,8 +22,9 @@ public function index(): JsonResponse
     public function store(SupportTicketRequest $request): JsonResponse
     public function store(SupportTicketRequest $request): JsonResponse
     {
     {
         $data = $request->validated();
         $data = $request->validated();
-        $data['applicant_user_id'] = auth()->id();
+        $data['applicant_user_id']   = auth()->id();
         $data['responsable_user_id'] = auth()->id();
         $data['responsable_user_id'] = auth()->id();
+        $data['status']              = 'in_progress';
 
 
         $item = $this->service->create($data);
         $item = $this->service->create($data);
         return $this->successResponse(payload: new SupportTicketResource($item), message: __('messages.created'), code: 201);
         return $this->successResponse(payload: new SupportTicketResource($item), message: __('messages.created'), code: 201);
@@ -37,8 +38,7 @@ public function show(int $id): JsonResponse
 
 
     public function update(SupportTicketRequest $request, int $id): JsonResponse
     public function update(SupportTicketRequest $request, int $id): JsonResponse
     {
     {
-        $data = $request->validated();
-        $item = $this->service->update($id, $data);
+        $item = $this->service->update($id, $request->validated());
         return $this->successResponse(payload: new SupportTicketResource($item), message: __('messages.updated'));
         return $this->successResponse(payload: new SupportTicketResource($item), message: __('messages.updated'));
     }
     }
 
 

+ 20 - 0
app/Http/Requests/SupportReplyRequest.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class SupportReplyRequest extends FormRequest
+{
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    public function rules(): array
+    {
+        return [
+            'reply' => 'required|string',
+        ];
+    }
+}

+ 7 - 4
app/Http/Requests/SupportTicketRequest.php

@@ -8,13 +8,16 @@ class SupportTicketRequest extends FormRequest
 {
 {
     public function rules(): array
     public function rules(): array
     {
     {
+        $isUpdate = $this->isMethod('PUT') || $this->isMethod('PATCH');
+
         return [
         return [
-            'title'       => 'required|string|max:255',
-            'description' => 'nullable|string',
-            'severity'    => 'required|string|in:alta,normal,baixa',
-            'scope'       => 'required|string|in:all,internal,specific',
+            'title'       => ($isUpdate ? 'sometimes' : 'required') . '|string|max:255',
+            'severity'    => ($isUpdate ? 'sometimes' : 'required') . '|string|in:alta,normal,baixa',
+            'scope'       => ($isUpdate ? 'sometimes' : 'required') . '|string|in:all,internal,specific',
             'unit_id'     => 'nullable|integer|exists:units,id',
             'unit_id'     => 'nullable|integer|exists:units,id',
             'sector'      => 'nullable|string|max:255',
             'sector'      => 'nullable|string|max:255',
+            'description' => 'nullable|string',
+            'status'      => 'sometimes|string|in:in_progress,resolved,unresolved',
         ];
         ];
     }
     }
 }
 }

+ 21 - 0
app/Http/Resources/SupportReplyResource.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Carbon\Carbon;
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class SupportReplyResource extends JsonResource
+{
+    public function toArray(Request $request): array
+    {
+        return [
+            'id'         => $this->id,
+            'ticket_id'  => $this->ticket_id,
+            'reply'      => $this->reply,
+            'user_name'  => $this->user?->name,
+            'created_at' => Carbon::parse($this->created_at)->format('d/m/Y H:i'),
+        ];
+    }
+}

+ 12 - 12
app/Http/Resources/SupportTicketResource.php

@@ -13,18 +13,18 @@ class SupportTicketResource extends JsonResource
     public function toArray(Request $request): array
     public function toArray(Request $request): array
     {
     {
         return [
         return [
-            'id'                   => $this->id,
-            'title'                => $this->title,
-            'description'          => $this->description,
-            'severity'             => $this->severity,
-            'scope'                => $this->scope,
-            'unit_id'              => $this->unit_id,
-            'sector'               => $this->sector,
-            'support_status_id'    => $this->support_status_id,
-            'applicant_user_id'    => $this->applicant_user_id,
-            'responsable_user_id'  => $this->responsable_user_id,
-            'created_at'           => Carbon::parse($this->created_at)->format('d/m/Y H:i'),
-            'updated_at'           => Carbon::parse($this->updated_at)->format('d/m/Y H:i'),
+            'id'                  => $this->id,
+            'title'               => $this->title,
+            'description'         => $this->description,
+            'severity'            => $this->severity,
+            'scope'               => $this->scope,
+            'unit_id'             => $this->unit_id,
+            'sector'              => $this->sector,
+            'status'              => $this->status,
+            'applicant_user_id'   => $this->applicant_user_id,
+            'responsable_user_id' => $this->responsable_user_id,
+            'created_at'          => Carbon::parse($this->created_at)->format('d/m/Y H:i'),
+            'updated_at'          => Carbon::parse($this->updated_at)->format('d/m/Y H:i'),
         ];
         ];
     }
     }
 
 

+ 31 - 0
app/Models/SupportReply.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+
+class SupportReply extends Model
+{
+    use HasFactory, SoftDeletes;
+
+    protected $table = 'support_replies';
+
+    protected $guarded = ['id'];
+
+    protected $casts = [
+        'created_at' => 'datetime',
+        'updated_at' => 'datetime',
+    ];
+
+    public function ticket()
+    {
+        return $this->belongsTo(SupportTicket::class, 'ticket_id');
+    }
+
+    public function user()
+    {
+        return $this->belongsTo(User::class, 'user_id');
+    }
+}

+ 34 - 0
app/Services/SupportReplyService.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\SupportReply;
+use Illuminate\Database\Eloquent\Collection;
+
+class SupportReplyService
+{
+    public function getByTicket(int $ticketId): Collection
+    {
+        return SupportReply::with('user')
+            ->where('ticket_id', $ticketId)
+            ->orderBy('created_at', 'asc')
+            ->get();
+    }
+
+    public function create(int $ticketId, int $userId, string $reply): SupportReply
+    {
+        $model = SupportReply::create([
+            'ticket_id' => $ticketId,
+            'user_id'   => $userId,
+            'reply'     => $reply,
+        ]);
+
+        return $model->load('user');
+    }
+
+    public function delete(int $ticketId, int $id): bool
+    {
+        $model = SupportReply::where('ticket_id', $ticketId)->findOrFail($id);
+        return $model->delete();
+    }
+}

+ 27 - 0
database/migrations/2026_05_18_170854_modify_support_tickets_replace_status.php

@@ -0,0 +1,27 @@
+<?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('support_tickets', function (Blueprint $table) {
+            $table->dropForeign(['support_status_id']);
+            $table->dropColumn('support_status_id');
+
+            $table->string('status')->default('in_progress')->after('description');
+        });
+    }
+
+    public function down(): void
+    {
+        Schema::table('support_tickets', function (Blueprint $table) {
+            $table->dropColumn('status');
+
+            $table->foreignId('support_status_id')->nullable()->constrained('support_statuses');
+        });
+    }
+};

+ 28 - 0
database/migrations/2026_05_18_173440_create_support_replies_table.php

@@ -0,0 +1,28 @@
+<?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('support_replies', function (Blueprint $table) {
+            $table->id();
+            $table->foreignId('ticket_id')->constrained('support_tickets')->cascadeOnDelete();
+            $table->foreignId('user_id')->constrained('users');
+            $table->text('reply');
+            $table->timestamps();
+            $table->softDeletes();
+
+            $table->index('ticket_id');
+            $table->index('user_id');
+        });
+    }
+
+    public function down(): void
+    {
+        Schema::dropIfExists('support_replies');
+    }
+};

+ 10 - 0
routes/authRoutes/support_reply.php

@@ -0,0 +1,10 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+use App\Http\Controllers\SupportReplyController;
+
+Route::controller(SupportReplyController::class)->prefix('support-ticket/{ticketId}/replies')->group(function () {
+    Route::get('/', 'index')->middleware('permission:support-ticket,view');
+    Route::post('/', 'store')->middleware('permission:support-ticket,add');
+    Route::delete('/{id}', 'destroy')->middleware('permission:support-ticket,delete');
+});