Procházet zdrojové kódy

feat: adiciona midia de students

ebagabee před 1 měsícem
rodič
revize
aaf5b76289

+ 40 - 0
app/Http/Controllers/StudentMediaController.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Services\StudentMediaService;
+use App\Http\Requests\StudentMediaRequest;
+use App\Http\Resources\StudentMediaResource;
+use Illuminate\Http\JsonResponse;
+use Illuminate\Http\Request;
+
+class StudentMediaController extends Controller
+{
+    public function __construct(
+        protected StudentMediaService $service,
+    ) {}
+
+    public function index(Request $request): JsonResponse
+    {
+        $items = $this->service->getAll($request->only(['student_id', 'student_contract_id']));
+        return $this->successResponse(payload: StudentMediaResource::collection($items));
+    }
+
+    public function store(StudentMediaRequest $request): JsonResponse
+    {
+        $item = $this->service->create($request->validated());
+        return $this->successResponse(payload: new StudentMediaResource($item), message: __('messages.created'), code: 201);
+    }
+
+    public function update(StudentMediaRequest $request, int $id): JsonResponse
+    {
+        $item = $this->service->update($id, $request->validated());
+        return $this->successResponse(payload: new StudentMediaResource($item), message: __('messages.updated'));
+    }
+
+    public function destroy(int $id): JsonResponse
+    {
+        $this->service->delete($id);
+        return $this->successResponse(message: __('messages.deleted'), code: 204);
+    }
+}

+ 19 - 0
app/Http/Requests/StudentMediaRequest.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class StudentMediaRequest extends FormRequest
+{
+    public function rules(): array
+    {
+        return [
+            'name'       => 'nullable|string|max:255',
+            'student_id' => 'required|integer|exists:students,id',
+            'file'       => $this->isMethod('POST')
+                ? 'required|file|mimes:jpeg,png,gif,pdf,mp4,mov,avi|max:20480'
+                : 'sometimes|file|mimes:jpeg,png,gif,pdf,mp4,mov,avi|max:20480',
+        ];
+    }
+}

+ 2 - 0
app/Http/Resources/StudentContractResource.php

@@ -41,6 +41,8 @@ public function toArray(Request $request): array
             'status'                  => $this->status,
             'package_name'            => $this->whenLoaded('classPackageUnit', fn () => $this->classPackageUnit?->name),
             'student_name'            => $this->whenLoaded('student', fn () => $this->student->name),
+            'student_document'        => $this->whenLoaded('student', fn () => $this->student->document_number),
+            'student_birth_date'      => $this->whenLoaded('student', fn () => $this->student->birth_date?->format('d/m/Y')),
             'student_phone'           => $this->whenLoaded('student', fn () => $this->student->phone),
             'student_city'            => $this->whenLoaded('student', fn () => $this->student->city?->name),
             'student_state_code'      => $this->whenLoaded('student', fn () => $this->student->state?->code),

+ 25 - 0
app/Http/Resources/StudentMediaResource.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Carbon\Carbon;
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\JsonResource;
+use Illuminate\Support\Facades\Storage;
+
+class StudentMediaResource extends JsonResource
+{
+    public function toArray(Request $request): array
+    {
+        return [
+            'id'                   => $this->id,
+            'name'                 => $this->name,
+            'student_id'           => $this->student_id,
+            'student_contract_id'  => $this->student_contract_id,
+            'file_url'             => $this->url ? Storage::url($this->url) : null,
+            'file_type'            => $this->file_type,
+            'type'                 => $this->type,
+            'created_at'           => Carbon::parse($this->created_at)->format('d/m/Y H:i'),
+        ];
+    }
+}

+ 7 - 0
app/Models/StudentContract.php

@@ -6,6 +6,8 @@
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\SoftDeletes;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\HasMany;
+
 
 /**
  * @property int $id
@@ -85,4 +87,9 @@ public function classPackageUnit(): BelongsTo
     {
         return $this->belongsTo(ClassPackageUnit::class);
     }
+
+    public function medias(): HasMany
+    {
+        return $this->hasMany(StudentMedia::class);
+    }
 }

+ 32 - 0
app/Models/StudentMedia.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+
+class StudentMedia extends Model
+{
+    use SoftDeletes;
+
+    protected $table = 'student_medias';
+
+    protected $guarded = ['id'];
+
+    protected $casts = [
+        'created_at' => 'datetime',
+        'updated_at' => 'datetime',
+        'deleted_at' => 'datetime',
+    ];
+
+    public function student(): BelongsTo
+    {
+        return $this->belongsTo(Student::class);
+    }
+
+    public function studentContract(): BelongsTo
+    {
+        return $this->belongsTo(StudentContract::class);
+    }
+}

+ 12 - 8
app/Services/StudentContractService.php

@@ -3,6 +3,7 @@
 namespace App\Services;
 
 use App\Models\StudentContract;
+use App\Models\StudentMedia;
 use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Support\Facades\Storage;
 
@@ -19,7 +20,7 @@ public function getAll(int $unitId, ?int $studentId = null): Collection
 
     public function findById(int $id): ?StudentContract
     {
-        return StudentContract::find($id);
+        return StudentContract::with(['student', 'classPackageUnit'])->find($id);
     }
 
     public function create(array $data): StudentContract
@@ -57,16 +58,19 @@ public function attachFile(int $id, $file): ?StudentContract
             return null;
         }
 
-        if ($model->file_url) {
-            Storage::delete($model->file_url);
-        }
-
         /** @var \Illuminate\Http\UploadedFile $file */
-        $model->update([
-            'file_url'  => $file->store('student-contracts'),
-            'file_type' => $file->getMimeType(),
+        $path = $file->store('student-media');
+
+        StudentMedia::create([
+            'student_id'          => $model->student_id,
+            'student_contract_id' => $model->id,
+            'url'                 => $path,
+            'file_type'           => $file->getMimeType(),
+            'type'                => 'contract',
         ]);
 
+        $model->update(['file_url' => Storage::url($path), 'file_type' => $file->getMimeType()]);
+
         return $model->fresh();
     }
 

+ 92 - 0
app/Services/StudentMediaService.php

@@ -0,0 +1,92 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\StudentMedia;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Support\Facades\Storage;
+
+class StudentMediaService
+{
+    public function getAll(array $filters = []): Collection
+    {
+        $query = StudentMedia::orderBy('created_at', 'desc');
+
+        if (!empty($filters['student_id'])) {
+            $query->where('student_id', $filters['student_id']);
+        }
+
+        if (!empty($filters['student_contract_id'])) {
+            $query->where('student_contract_id', $filters['student_contract_id']);
+        }
+
+        return $query->get();
+    }
+
+    public function create(array $data): StudentMedia
+    {
+        /** @var \Illuminate\Http\UploadedFile $file */
+        $file = $data['file'];
+        $path = $file->store('student-media');
+
+        return StudentMedia::create([
+            'student_id' => $data['student_id'],
+            'name'       => $data['name'] ?? null,
+            'url'        => $path,
+            'file_type'  => $file->getMimeType(),
+            'type'       => 'media',
+        ]);
+    }
+
+    public function createFromContract(int $studentId, int $contractId, $file): StudentMedia
+    {
+        /** @var \Illuminate\Http\UploadedFile $file */
+        $path = $file->store('student-media');
+
+        return StudentMedia::create([
+            'student_id'          => $studentId,
+            'student_contract_id' => $contractId,
+            'url'                 => $path,
+            'file_type'           => $file->getMimeType(),
+            'type'                => 'contract',
+        ]);
+    }
+
+    public function findById(int $id): ?StudentMedia
+    {
+        return StudentMedia::find($id);
+    }
+
+    public function update(int $id, array $data): ?StudentMedia
+    {
+        $model = $this->findById($id);
+
+        if (!$model) {
+            return null;
+        }
+
+        if (isset($data['file'])) {
+            Storage::delete($model->url);
+            /** @var \Illuminate\Http\UploadedFile $file */
+            $file              = $data['file'];
+            $data['url']       = $file->store('student-media');
+            $data['file_type'] = $file->getMimeType();
+            unset($data['file']);
+        }
+
+        $model->update($data);
+        return $model->fresh();
+    }
+
+    public function delete(int $id): bool
+    {
+        $model = $this->findById($id);
+
+        if (!$model) {
+            return false;
+        }
+
+        Storage::delete($model->url);
+        return $model->delete();
+    }
+}

+ 28 - 0
database/migrations/2026_05_13_000001_create_student_medias_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('student_medias', function (Blueprint $table) {
+            $table->id();
+            $table->foreignId('student_id')->constrained('students')->cascadeOnDelete();
+            $table->foreignId('student_contract_id')->nullable()->constrained('student_contracts')->cascadeOnDelete();
+            $table->string('name')->nullable();
+            $table->string('url');
+            $table->string('file_type')->nullable();
+            $table->string('type')->default('media'); // 'media' | 'contract'
+            $table->timestamps();
+            $table->softDeletes();
+        });
+    }
+
+    public function down(): void
+    {
+        Schema::dropIfExists('student_medias');
+    }
+};

+ 14 - 0
routes/authRoutes/student_media.php

@@ -0,0 +1,14 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+use App\Http\Controllers\StudentMediaController;
+
+Route::controller(StudentMediaController::class)->prefix('student-media')->group(function () {
+    Route::get('/', 'index');
+
+    Route::post('/', 'store');
+
+    Route::put('/{id}', 'update');
+
+    Route::delete('/{id}', 'destroy');
+});