From 908ba8aaf11da2970b7d114f769cb6c0b658adbc Mon Sep 17 00:00:00 2001 From: Juan Felipe Zapata Moreno Date: Sat, 20 Dec 2025 11:39:13 -0600 Subject: [PATCH] =?UTF-8?q?feat:=20agregar=20manejo=20de=20archivos=20dupl?= =?UTF-8?q?icados=20en=20la=20actualizaci=C3=B3n=20de=20datos=20del=20veh?= =?UTF-8?q?=C3=ADculo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Repuve/UpdateController.php | 146 +++++++++++++++--- 1 file changed, 124 insertions(+), 22 deletions(-) diff --git a/app/Http/Controllers/Repuve/UpdateController.php b/app/Http/Controllers/Repuve/UpdateController.php index baa043b..e405198 100644 --- a/app/Http/Controllers/Repuve/UpdateController.php +++ b/app/Http/Controllers/Repuve/UpdateController.php @@ -860,6 +860,7 @@ public function updateData(VehicleUpdateRequest $request, $id) $uploadedFiles = []; $replacedFiles = []; $deletedFiles = []; + $skippedFiles = []; // Manejar eliminación de archivos if ($request->has('delete_files')) { @@ -898,14 +899,30 @@ public function updateData(VehicleUpdateRequest $request, $id) $nameIds = $request->input('name_id', []); $observations = $request->input('observations', []); + // Normalizar arrays + if (!is_array($nameIds)) { + $nameIds = [$nameIds]; + } + if (!is_array($observations)) { + $observations = [$observations]; + } + if (!is_array($files)) { + $files = [$files]; + } + if (!empty($nameIds)) { - $validIds = CatalogNameImg::whereIn('id', $nameIds)->pluck('id')->toArray(); - if (count($validIds) !== count($nameIds)) { + // Obtener IDs únicos para validar + $uniqueNameIds = array_unique($nameIds); + $validIds = CatalogNameImg::whereIn('id', $uniqueNameIds)->pluck('id')->toArray(); + + // Verificar que todos los IDs únicos existan en el catálogo + if (count($validIds) !== count($uniqueNameIds)) { + $invalidIds = array_diff($uniqueNameIds, $validIds); DB::rollBack(); return ApiResponse::BAD_REQUEST->response([ 'message' => 'Algunos ids del catálogo de nombres no son válidos', - 'provided_id' => $nameIds, - 'valid_id' => $validIds, + 'provided_ids' => $nameIds, + 'invalid_ids' => array_values($invalidIds), ]); } } @@ -913,10 +930,10 @@ public function updateData(VehicleUpdateRequest $request, $id) foreach ($files as $indx => $file) { $nameId = $nameIds[$indx] ?? null; - if ($nameId === null) { + if ($nameId === null || $nameId === '') { DB::rollBack(); return ApiResponse::BAD_REQUEST->response([ - 'message' => "Falta el nombre para el archivo, busca en el catálogo de nombres", + 'message' => "Falta el nombre para el archivo en el índice {$indx}", ]); } @@ -933,24 +950,96 @@ public function updateData(VehicleUpdateRequest $request, $id) $extension = $file->getClientOriginalExtension(); $isEvidenciaAdicional = $catalogName->name === 'EVIDENCIA ADICIONAL'; - // Si NO es Evidencia Adicional, verificar si existe y reemplazar + // Calcular MD5 antes de guardar para verificar duplicados + $md5 = md5_file($file->getRealPath()); + + // Verificar si el archivo ya existe por MD5 en este expediente + $existingByMd5 = File::where('record_id', $record->id) + ->where('md5', $md5) + ->first(); + + if ($existingByMd5) { + // Archivo duplicado detectado, registrar y omitir + $skippedFiles[] = [ + 'index' => $indx, + 'catalog_name' => $catalogName->name, + 'md5' => $md5, + 'reason' => 'Archivo duplicado ya existe en el expediente', + 'existing_file_id' => $existingByMd5->id, + 'existing_file_path' => $existingByMd5->path, + ]; + continue; // Salta al siguiente archivo sin guardarlo + } + + // Verificar si existe archivo para reemplazar + $existingFile = null; + if (!$isEvidenciaAdicional) { + // Para archivos estándar (FACTURA, INE, etc.), buscar por name_id $existingFile = File::where('record_id', $record->id) ->where('name_id', $nameId) ->first(); + } else { + // Para EVIDENCIA ADICIONAL con observación, buscar por name_id + observations + $observation = $observations[$indx] ?? null; - if ($existingFile) { - Storage::disk('public')->delete($existingFile->path); - - $replacedFiles[] = [ - 'id' => $existingFile->id, - 'name_id' => $nameId, - 'old_path' => $existingFile->path, - ]; - - $existingFile->delete(); + if (!empty($observation)) { + $existingFile = File::where('record_id', $record->id) + ->where('name_id', $nameId) + ->where('observations', $observation) + ->first(); } + // Si no tiene observación o no se encuentra, se creará nuevo archivo + } + // Si existe archivo, reemplazarlo + if ($existingFile) { + $oldPath = $existingFile->path; + $oldMd5 = $existingFile->md5; + + // Eliminar archivo físico viejo + Storage::disk('public')->delete($oldPath); + + // Mantener el mismo nombre de archivo pero actualizar extensión si cambió + $pathInfo = pathinfo($oldPath); + $fileName = $pathInfo['filename'] . '.' . $extension; + $directory = $pathInfo['dirname']; + + // Guardar nuevo archivo con el mismo nombre + $path = $file->storeAs($directory, $fileName, 'public'); + + // Actualizar registro existente + $existingFile->update([ + 'path' => $path, + 'md5' => $md5, + 'observations' => $observations[$indx] ?? $existingFile->observations, + ]); + + $replacedFiles[] = [ + 'file_id' => $existingFile->id, + 'name' => $catalogName->name, + 'old_path' => $oldPath, + 'new_path' => $path, + 'old_md5' => $oldMd5, + 'new_md5' => $md5, + 'replaced_by' => 'observation_match', + ]; + + // Agregar a uploadedFiles también para mantener compatibilidad + $uploadedFiles[] = [ + 'file_id' => $existingFile->id, + 'name' => $catalogName->name, + 'path' => $path, + 'md5' => $md5, + 'observations' => $existingFile->observations, + 'action' => 'replaced', + ]; + + continue; // Siguiente archivo + } + + // Si no existe, crear nuevo archivo + if (!$isEvidenciaAdicional) { $fileName = $catalogName->name . '_' . date('dmY_His') . '.' . $extension; } else { // Si es Evidencia Adicional, contar cuántas ya existen y agregar número @@ -962,7 +1051,6 @@ public function updateData(VehicleUpdateRequest $request, $id) } $path = $file->storeAs("records/{$record->folio}", $fileName, 'public'); - $md5 = md5_file($file->getRealPath()); $fileRecord = File::create([ 'name_id' => $nameId, @@ -1060,6 +1148,9 @@ public function updateData(VehicleUpdateRequest $request, $id) $message = 'Expediente actualizado exitosamente'; if (!$hasVehicleChanges && !$hasOwnerChanges && !$hasFolioChange && empty($uploadedFiles) && empty($deletedFiles)) { $message = 'No se detectaron cambios. Los datos ya estaban actualizados.'; + if (!empty($skippedFiles)) { + $message .= ' Se omitieron ' . count($skippedFiles) . ' archivo(s) duplicado(s).'; + } } elseif ($hasFolioChange) { $message = 'Folio actualizado exitosamente de "' . $oldFolio . '" a "' . $record->folio . '".'; if ($hasVehicleChanges || $hasOwnerChanges) { @@ -1068,12 +1159,24 @@ public function updateData(VehicleUpdateRequest $request, $id) if (!empty($uploadedFiles) || !empty($deletedFiles)) { $message .= ' Archivos modificados.'; } + if (!empty($skippedFiles)) { + $message .= ' Se omitieron ' . count($skippedFiles) . ' archivo(s) duplicado(s).'; + } } elseif (($hasVehicleChanges || $hasOwnerChanges) && (!empty($uploadedFiles) || !empty($deletedFiles))) { $message = 'Datos del vehículo/propietario y archivos actualizados exitosamente.'; + if (!empty($skippedFiles)) { + $message .= ' Se omitieron ' . count($skippedFiles) . ' archivo(s) duplicado(s).'; + } } elseif (($hasVehicleChanges || $hasOwnerChanges) && empty($uploadedFiles) && empty($deletedFiles)) { $message = 'Datos del vehículo/propietario actualizados exitosamente. No se modificaron archivos.'; + if (!empty($skippedFiles)) { + $message .= ' Se omitieron ' . count($skippedFiles) . ' archivo(s) duplicado(s).'; + } } elseif (!$hasVehicleChanges && !$hasOwnerChanges && (!empty($uploadedFiles) || !empty($deletedFiles))) { $message = 'Archivos modificados exitosamente. No hubo cambios en los datos del vehículo/propietario.'; + if (!empty($skippedFiles)) { + $message .= ' Se omitieron ' . count($skippedFiles) . ' archivo(s) duplicado(s).'; + } } @@ -1085,12 +1188,10 @@ public function updateData(VehicleUpdateRequest $request, $id) 'owner_updated' => $hasOwnerChanges, 'files_uploaded' => count($uploadedFiles) > 0, 'files_deleted' => count($deletedFiles) > 0, + 'files_skipped' => count($skippedFiles) > 0, + 'files_replaced' => count($replacedFiles) > 0, ], 'record' => $record, - 'uploaded_files' => $uploadedFiles, - 'deleted_files' => $deletedFiles, - 'replaced_count' => count($replacedFiles), - 'total_files' => File::where('record_id', $record->id)->count(), ]); } catch (Exception $e) { DB::rollBack(); @@ -1245,4 +1346,5 @@ private function moveRecordFiles(int $recordId, string $oldFolio, string $newFol Storage::disk('public')->deleteDirectory($oldDirectory); } } + }