feat: implementar generación de PDF para tags dañados y modificaciones al actualizar datos del vehiculo
This commit is contained in:
parent
1c6cb99187
commit
525bcc0db7
@ -14,6 +14,7 @@
|
|||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Notsoweb\ApiResponse\Enums\ApiResponse;
|
use Notsoweb\ApiResponse\Enums\ApiResponse;
|
||||||
|
use Barryvdh\DomPDF\Facade\Pdf;
|
||||||
|
|
||||||
class CancellationController extends Controller
|
class CancellationController extends Controller
|
||||||
{
|
{
|
||||||
@ -239,27 +240,69 @@ public function cancelarTagNoAsignado(Request $request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cancelar el tag
|
// Cancelar el tag
|
||||||
$tag->markAsCancelled();
|
$tag->markAsDamaged();
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
|
|
||||||
return ApiResponse::OK->response([
|
try {
|
||||||
'message' => 'Tag cancelado exitosamente',
|
// Recargar el tag con sus relaciones actualizadas
|
||||||
'tag' => [
|
$tag->load(['status', 'cancellationLogs.cancellationReason', 'cancellationLogs.cancelledBy', 'module']);
|
||||||
'id' => $tag->id,
|
|
||||||
'tag_number' => $tag->tag_number,
|
// Obtener datos de cancelación del último log
|
||||||
'folio' => $tag->folio,
|
$lastCancellation = $tag->cancellationLogs()
|
||||||
'previous_status' => 'Disponible',
|
->with(['cancellationReason', 'cancelledBy'])
|
||||||
'new_status' => 'Cancelado',
|
->latest()
|
||||||
],
|
->first();
|
||||||
'cancellation' => [
|
|
||||||
'id' => $cancellationLog->id,
|
// Preparar datos para el PDF
|
||||||
'reason' => $cancellationLog->cancellationReason->name,
|
$cancellationData = [
|
||||||
'observations' => $cancellationLog->cancellation_observations,
|
'fecha' => $lastCancellation ? $lastCancellation->cancellation_at->format('d/m/Y') : now()->format('d/m/Y'),
|
||||||
'cancelled_at' => $cancellationLog->cancellation_at->toDateTimeString(),
|
'folio' => $tag->folio ?? '',
|
||||||
'cancelled_by' => Auth::user()->name,
|
'id_chip' => $request->id_chip ?? '',
|
||||||
],
|
'motivo' => $lastCancellation && $lastCancellation->cancellationReason
|
||||||
]);
|
? $lastCancellation->cancellationReason->name
|
||||||
|
: 'No especificado',
|
||||||
|
'operador' => $lastCancellation && $lastCancellation->cancelledBy
|
||||||
|
? $lastCancellation->cancelledBy->name
|
||||||
|
: 'Sistema',
|
||||||
|
'modulo' => $tag->module ? $tag->module->name : 'No especificado',
|
||||||
|
'ubicacion' => $tag->module ? $tag->module->address : 'No especificado',
|
||||||
|
];
|
||||||
|
|
||||||
|
$pdf = Pdf::loadView('pdfs.tag', [
|
||||||
|
'cancellation' => $cancellationData,
|
||||||
|
])
|
||||||
|
->setPaper('a4', 'portrait')
|
||||||
|
->setOptions([
|
||||||
|
'defaultFont' => 'sans-serif',
|
||||||
|
'isHtml5ParserEnabled' => true,
|
||||||
|
'isRemoteEnabled' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $pdf->stream('constancia_cancelada_' . ($tag->tag_number ?? $tag->folio) . '.pdf');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Si falla la generación del PDF, devolver respuesta JSON
|
||||||
|
Log::error('Error al generar PDF de tag cancelado: ' . $e->getMessage());
|
||||||
|
|
||||||
|
return ApiResponse::OK->response([
|
||||||
|
'message' => 'Tag cancelado exitosamente (Error al generar PDF)',
|
||||||
|
'tag' => [
|
||||||
|
'id' => $tag->id,
|
||||||
|
'tag_number' => $tag->tag_number,
|
||||||
|
'folio' => $tag->folio,
|
||||||
|
'previous_status' => 'Disponible',
|
||||||
|
'new_status' => 'Dañado',
|
||||||
|
],
|
||||||
|
'cancellation' => [
|
||||||
|
'id' => $cancellationLog->id,
|
||||||
|
'reason' => $cancellationLog->cancellationReason->name,
|
||||||
|
'observations' => $cancellationLog->cancellation_observations,
|
||||||
|
'cancelled_at' => $cancellationLog->cancellation_at->toDateTimeString(),
|
||||||
|
'cancelled_by' => Auth::user()->name,
|
||||||
|
],
|
||||||
|
'pdf_error' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
|
|
||||||
|
|||||||
@ -129,14 +129,14 @@ public function tagSubstitution(Request $request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verificar robo del vehículo
|
// Verificar robo del vehículo
|
||||||
/* $isStolen = $this->checkIfStolen($vehicle->niv);
|
$isStolen = $this->checkIfStolen($vehicle->niv);
|
||||||
|
|
||||||
if ($isStolen) {
|
if ($isStolen) {
|
||||||
return ApiResponse::FORBIDDEN->response([
|
return ApiResponse::FORBIDDEN->response([
|
||||||
'message' => 'El vehículo reporta robo. No se puede continuar con la sustitución.',
|
'message' => 'El vehículo reporta robo. No se puede continuar con la sustitución.',
|
||||||
'niv' => $vehicle->niv,
|
'niv' => $vehicle->niv,
|
||||||
]);
|
]);
|
||||||
} */
|
}
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
|
|
||||||
@ -179,9 +179,9 @@ public function tagSubstitution(Request $request)
|
|||||||
'performed_by' => Auth::id(),
|
'performed_by' => Auth::id(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/* // 6. Enviar a REPUVE Nacional
|
// 6. Enviar a REPUVE Nacional
|
||||||
$datosCompletos = $this->prepararDatosParaInscripcion($vehicle->niv);
|
$datosCompletos = $this->prepararDatosParaInscripcion($vehicle->niv);
|
||||||
ProcessRepuveResponse::dispatch($record->id, $datosCompletos); */
|
ProcessRepuveResponse::dispatch($record->id, $datosCompletos);
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
|
|
||||||
@ -725,19 +725,6 @@ private function detectOwnerChanges($owner, array $ownerDataEstatal)
|
|||||||
return $changedFields;
|
return $changedFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getVehicle(string $niv): array
|
|
||||||
{
|
|
||||||
$datos = $this->padronEstatalService->getVehiculoByNiv($niv);
|
|
||||||
return $this->padronEstatalService->extraerDatosVehiculo($datos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getOwner(string $niv): array
|
|
||||||
{
|
|
||||||
$datos = $this->padronEstatalService->getVehiculoByNiv($niv);
|
|
||||||
return $this->padronEstatalService->extraerDatosPropietario($datos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------------------------------------- */
|
/* --------------------------------------------------------- */
|
||||||
|
|
||||||
public function updateData(VehicleUpdateRequest $request, $id)
|
public function updateData(VehicleUpdateRequest $request, $id)
|
||||||
@ -754,6 +741,8 @@ public function updateData(VehicleUpdateRequest $request, $id)
|
|||||||
|
|
||||||
$hasVehicleChanges = false;
|
$hasVehicleChanges = false;
|
||||||
$hasOwnerChanges = false;
|
$hasOwnerChanges = false;
|
||||||
|
$hasFolioChange = false;
|
||||||
|
$oldFolio = $record->folio;
|
||||||
|
|
||||||
if ($request->has('vehicle')) {
|
if ($request->has('vehicle')) {
|
||||||
$vehicleData = $request->input('vehicle', []);
|
$vehicleData = $request->input('vehicle', []);
|
||||||
@ -791,6 +780,31 @@ public function updateData(VehicleUpdateRequest $request, $id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualizar folio si se envía
|
||||||
|
if ($request->has('folio')) {
|
||||||
|
$newFolio = $request->input('folio');
|
||||||
|
|
||||||
|
if ($newFolio && $newFolio !== $record->folio) {
|
||||||
|
// Verificar que el nuevo folio no exista
|
||||||
|
$existingRecord = Record::where('folio', $newFolio)->first();
|
||||||
|
|
||||||
|
if ($existingRecord && $existingRecord->id !== $record->id) {
|
||||||
|
DB::rollBack();
|
||||||
|
return ApiResponse::BAD_REQUEST->response([
|
||||||
|
'message' => 'El folio ya existe en el sistema y pertenece a un expediente',
|
||||||
|
'folio' => $newFolio,
|
||||||
|
'record_id' => $existingRecord->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
// Mover carpeta de archivos
|
||||||
|
$this->moveRecordFiles($record->id, $oldFolio, $newFolio);
|
||||||
|
|
||||||
|
// Actualizar folio del record
|
||||||
|
$record->update(['folio' => $newFolio]);
|
||||||
|
$hasFolioChange = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Actualizar propietario si se envían datos
|
// Actualizar propietario si se envían datos
|
||||||
if ($request->has('owner')) {
|
if ($request->has('owner')) {
|
||||||
$ownerInput = $request->input('owner', []);
|
$ownerInput = $request->input('owner', []);
|
||||||
@ -847,7 +861,7 @@ public function updateData(VehicleUpdateRequest $request, $id)
|
|||||||
$replacedFiles = [];
|
$replacedFiles = [];
|
||||||
$deletedFiles = [];
|
$deletedFiles = [];
|
||||||
|
|
||||||
// Manejar eliminación de archivos (solo de BD, conserva archivo físico)
|
// Manejar eliminación de archivos
|
||||||
if ($request->has('delete_files')) {
|
if ($request->has('delete_files')) {
|
||||||
$filesToDelete = $request->input('delete_files', []);
|
$filesToDelete = $request->input('delete_files', []);
|
||||||
|
|
||||||
@ -857,14 +871,23 @@ public function updateData(VehicleUpdateRequest $request, $id)
|
|||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($fileToDelete) {
|
if ($fileToDelete) {
|
||||||
|
$catalogName = $fileToDelete->catalogName;
|
||||||
|
|
||||||
$deletedFiles[] = [
|
$deletedFiles[] = [
|
||||||
'id' => $fileToDelete->id,
|
'id' => $fileToDelete->id,
|
||||||
'name_id' => $fileToDelete->name_id,
|
'name_id' => $fileToDelete->name_id,
|
||||||
'name' => $fileToDelete->catalogName->name ?? 'Desconocido',
|
'name' => $catalogName->name ?? 'Desconocido',
|
||||||
'path' => $fileToDelete->path,
|
'path' => $fileToDelete->path,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Eliminar archivo físico y registro de BD
|
||||||
|
Storage::disk('public')->delete($fileToDelete->path);
|
||||||
$fileToDelete->delete();
|
$fileToDelete->delete();
|
||||||
|
|
||||||
|
// Si es Evidencia Adicional, renumerar las restantes
|
||||||
|
if ($catalogName && $catalogName->name === 'EVIDENCIA ADICIONAL') {
|
||||||
|
$this->renumberEvidenciasAdicionales($record->id, $record->folio);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -873,6 +896,7 @@ public function updateData(VehicleUpdateRequest $request, $id)
|
|||||||
if ($request->hasFile('files')) {
|
if ($request->hasFile('files')) {
|
||||||
$files = $request->file('files');
|
$files = $request->file('files');
|
||||||
$nameIds = $request->input('name_id', []);
|
$nameIds = $request->input('name_id', []);
|
||||||
|
$observations = $request->input('observations', []);
|
||||||
|
|
||||||
if (!empty($nameIds)) {
|
if (!empty($nameIds)) {
|
||||||
$validIds = CatalogNameImg::whereIn('id', $nameIds)->pluck('id')->toArray();
|
$validIds = CatalogNameImg::whereIn('id', $nameIds)->pluck('id')->toArray();
|
||||||
@ -896,26 +920,47 @@ public function updateData(VehicleUpdateRequest $request, $id)
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$existingFile = File::where('record_id', $record->id)
|
// Obtener el nombre del catálogo
|
||||||
->where('name_id', $nameId)
|
$catalogName = CatalogNameImg::find($nameId);
|
||||||
->first();
|
|
||||||
|
|
||||||
if ($existingFile) {
|
if (!$catalogName) {
|
||||||
Storage::disk('public')->delete($existingFile->path);
|
DB::rollBack();
|
||||||
|
return ApiResponse::BAD_REQUEST->response([
|
||||||
$replacedFiles[] = [
|
'message' => "No se encontró el catálogo de nombre con id {$nameId}",
|
||||||
'id' => $existingFile->id,
|
]);
|
||||||
'name_id' => $nameId,
|
|
||||||
'old_path' => $existingFile->path,
|
|
||||||
];
|
|
||||||
|
|
||||||
$existingFile->delete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtener el nombre del catálogo para el nombre del archivo
|
|
||||||
$catalogName = CatalogNameImg::find($nameId);
|
|
||||||
$extension = $file->getClientOriginalExtension();
|
$extension = $file->getClientOriginalExtension();
|
||||||
$fileName = $catalogName->name . '_' . date('dmY_His') . '.' . $extension;
|
$isEvidenciaAdicional = $catalogName->name === 'EVIDENCIA ADICIONAL';
|
||||||
|
|
||||||
|
// Si NO es Evidencia Adicional, verificar si existe y reemplazar
|
||||||
|
if (!$isEvidenciaAdicional) {
|
||||||
|
$existingFile = File::where('record_id', $record->id)
|
||||||
|
->where('name_id', $nameId)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($existingFile) {
|
||||||
|
Storage::disk('public')->delete($existingFile->path);
|
||||||
|
|
||||||
|
$replacedFiles[] = [
|
||||||
|
'id' => $existingFile->id,
|
||||||
|
'name_id' => $nameId,
|
||||||
|
'old_path' => $existingFile->path,
|
||||||
|
];
|
||||||
|
|
||||||
|
$existingFile->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileName = $catalogName->name . '_' . date('dmY_His') . '.' . $extension;
|
||||||
|
} else {
|
||||||
|
// Si es Evidencia Adicional, contar cuántas ya existen y agregar número
|
||||||
|
$count = File::where('record_id', $record->id)
|
||||||
|
->where('name_id', $nameId)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
$fileName = 'Evidencia_Adicional_' . ($count + 1) . '_' . date('dmY_His') . '.' . $extension;
|
||||||
|
}
|
||||||
|
|
||||||
$path = $file->storeAs("records/{$record->folio}", $fileName, 'public');
|
$path = $file->storeAs("records/{$record->folio}", $fileName, 'public');
|
||||||
$md5 = md5_file($file->getRealPath());
|
$md5 = md5_file($file->getRealPath());
|
||||||
|
|
||||||
@ -924,20 +969,33 @@ public function updateData(VehicleUpdateRequest $request, $id)
|
|||||||
'path' => $path,
|
'path' => $path,
|
||||||
'md5' => $md5,
|
'md5' => $md5,
|
||||||
'record_id' => $record->id,
|
'record_id' => $record->id,
|
||||||
|
'observations' => $observations[$indx] ?? null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Calcular el número de Evidencia Adicional si aplica
|
||||||
|
$displayNumber = null;
|
||||||
|
if ($isEvidenciaAdicional) {
|
||||||
|
$displayNumber = File::where('record_id', $record->id)
|
||||||
|
->where('name_id', $nameId)
|
||||||
|
->where('id', '<=', $fileRecord->id)
|
||||||
|
->count();
|
||||||
|
}
|
||||||
|
|
||||||
$uploadedFiles[] = [
|
$uploadedFiles[] = [
|
||||||
'id' => $fileRecord->id,
|
'id' => $fileRecord->id,
|
||||||
'name' => $catalogName->name,
|
'name' => $catalogName->name,
|
||||||
|
'display_name' => $isEvidenciaAdicional ? "Evidencia Adicional {$displayNumber}" : $catalogName->name,
|
||||||
'path' => $fileRecord->path,
|
'path' => $fileRecord->path,
|
||||||
'url' => $fileRecord->url,
|
'url' => $fileRecord->url,
|
||||||
'replaced' => $existingFile !== null,
|
'observations' => $fileRecord->observations,
|
||||||
|
'number' => $displayNumber,
|
||||||
|
'replaced' => isset($existingFile) && $existingFile !== null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registrar el log de cambios si hubo actualizaciones
|
// Registrar el log de cambios si hubo actualizaciones
|
||||||
if ($hasVehicleChanges || $hasOwnerChanges || count($uploadedFiles) > 0 || count($deletedFiles) > 0) {
|
if ($hasVehicleChanges || $hasOwnerChanges || $hasFolioChange || count($uploadedFiles) > 0 || count($deletedFiles) > 0) {
|
||||||
VehicleTagLog::create([
|
VehicleTagLog::create([
|
||||||
'vehicle_id' => $vehicle->id,
|
'vehicle_id' => $vehicle->id,
|
||||||
'tag_id' => $tag->id,
|
'tag_id' => $tag->id,
|
||||||
@ -947,7 +1005,7 @@ public function updateData(VehicleUpdateRequest $request, $id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// datos para REPUVE Nacional usando datos actuales de la BD
|
// datos para REPUVE Nacional usando datos actuales de la BD
|
||||||
if ($hasVehicleChanges || $hasOwnerChanges || count($uploadedFiles) > 0 || count($deletedFiles) > 0) {
|
if ($hasVehicleChanges || $hasOwnerChanges || $hasFolioChange || count($uploadedFiles) > 0 || count($deletedFiles) > 0) {
|
||||||
// Recargar el vehículo y propietario con los datos actualizados
|
// Recargar el vehículo y propietario con los datos actualizados
|
||||||
$vehicle->refresh();
|
$vehicle->refresh();
|
||||||
$owner->refresh();
|
$owner->refresh();
|
||||||
@ -1000,8 +1058,16 @@ public function updateData(VehicleUpdateRequest $request, $id)
|
|||||||
$record->load(['vehicle.owner', 'vehicle.tag', 'files', 'error']);
|
$record->load(['vehicle.owner', 'vehicle.tag', 'files', 'error']);
|
||||||
|
|
||||||
$message = 'Expediente actualizado exitosamente';
|
$message = 'Expediente actualizado exitosamente';
|
||||||
if (!$hasVehicleChanges && !$hasOwnerChanges && empty($uploadedFiles) && empty($deletedFiles)) {
|
if (!$hasVehicleChanges && !$hasOwnerChanges && !$hasFolioChange && empty($uploadedFiles) && empty($deletedFiles)) {
|
||||||
$message = 'No se detectaron cambios. Los datos ya estaban actualizados.';
|
$message = 'No se detectaron cambios. Los datos ya estaban actualizados.';
|
||||||
|
} elseif ($hasFolioChange) {
|
||||||
|
$message = 'Folio actualizado exitosamente de "' . $oldFolio . '" a "' . $record->folio . '".';
|
||||||
|
if ($hasVehicleChanges || $hasOwnerChanges) {
|
||||||
|
$message .= ' Datos del vehículo/propietario actualizados.';
|
||||||
|
}
|
||||||
|
if (!empty($uploadedFiles) || !empty($deletedFiles)) {
|
||||||
|
$message .= ' Archivos modificados.';
|
||||||
|
}
|
||||||
} elseif (($hasVehicleChanges || $hasOwnerChanges) && (!empty($uploadedFiles) || !empty($deletedFiles))) {
|
} elseif (($hasVehicleChanges || $hasOwnerChanges) && (!empty($uploadedFiles) || !empty($deletedFiles))) {
|
||||||
$message = 'Datos del vehículo/propietario y archivos actualizados exitosamente.';
|
$message = 'Datos del vehículo/propietario y archivos actualizados exitosamente.';
|
||||||
} elseif (($hasVehicleChanges || $hasOwnerChanges) && empty($uploadedFiles) && empty($deletedFiles)) {
|
} elseif (($hasVehicleChanges || $hasOwnerChanges) && empty($uploadedFiles) && empty($deletedFiles)) {
|
||||||
@ -1010,6 +1076,7 @@ public function updateData(VehicleUpdateRequest $request, $id)
|
|||||||
$message = 'Archivos modificados exitosamente. No hubo cambios en los datos del vehículo/propietario.';
|
$message = 'Archivos modificados exitosamente. No hubo cambios en los datos del vehículo/propietario.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return ApiResponse::OK->response([
|
return ApiResponse::OK->response([
|
||||||
'message' => $message,
|
'message' => $message,
|
||||||
'has_error' => false,
|
'has_error' => false,
|
||||||
@ -1099,4 +1166,83 @@ public function resendToRepuve($id)
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renumerar las Evidencias Adicionales después de eliminar una
|
||||||
|
*/
|
||||||
|
private function renumberEvidenciasAdicionales(int $recordId, string $folio): void
|
||||||
|
{
|
||||||
|
$catalogName = CatalogNameImg::where('name', 'EVIDENCIA ADICIONAL')->first();
|
||||||
|
if (!$catalogName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtener todas las evidencias adicionales ordenadas por ID
|
||||||
|
$files = File::where('record_id', $recordId)
|
||||||
|
->where('name_id', $catalogName->id)
|
||||||
|
->orderBy('id')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($files as $index => $file) {
|
||||||
|
$newNumber = $index + 1;
|
||||||
|
$extension = pathinfo($file->path, PATHINFO_EXTENSION);
|
||||||
|
$oldPath = $file->path;
|
||||||
|
|
||||||
|
// Nuevo nombre de archivo con numeración actualizada
|
||||||
|
$newFileName = 'Evidencia_Adicional_' . $newNumber . '_' . date('dmY_His') . '.' . $extension;
|
||||||
|
$newPath = "records/{$folio}/" . $newFileName;
|
||||||
|
|
||||||
|
// Solo renombrar si el path es diferente
|
||||||
|
if ($oldPath !== $newPath) {
|
||||||
|
// Verificar que el archivo antiguo existe antes de intentar moverlo
|
||||||
|
if (Storage::disk('public')->exists($oldPath)) {
|
||||||
|
// Renombrar archivo físico
|
||||||
|
Storage::disk('public')->move($oldPath, $newPath);
|
||||||
|
|
||||||
|
// Actualizar registro en BD
|
||||||
|
$file->update(['path' => $newPath]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function moveRecordFiles(int $recordId, string $oldFolio, string $newFolio): void
|
||||||
|
{
|
||||||
|
$files = File::where('record_id', $recordId)->get();
|
||||||
|
|
||||||
|
$oldDirectory = "records/{$oldFolio}";
|
||||||
|
$newDirectory = "records/{$newFolio}";
|
||||||
|
|
||||||
|
// Verificar si existe la carpeta antigua
|
||||||
|
if (!Storage::disk('public')->exists($oldDirectory)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear la nueva carpeta si no existe
|
||||||
|
if (!Storage::disk('public')->exists($newDirectory)) {
|
||||||
|
Storage::disk('public')->makeDirectory($newDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mover cada archivo
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$oldPath = $file->path;
|
||||||
|
$fileName = basename($oldPath);
|
||||||
|
$newPath = "{$newDirectory}/{$fileName}";
|
||||||
|
|
||||||
|
// Verificar que el archivo existe antes de moverlo
|
||||||
|
if (Storage::disk('public')->exists($oldPath)) {
|
||||||
|
// Mover archivo físico
|
||||||
|
Storage::disk('public')->move($oldPath, $newPath);
|
||||||
|
|
||||||
|
// Actualizar registro en BD
|
||||||
|
$file->update(['path' => $newPath]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eliminar carpeta antigua si está vacía
|
||||||
|
$remainingFiles = Storage::disk('public')->files($oldDirectory);
|
||||||
|
if (empty($remainingFiles)) {
|
||||||
|
Storage::disk('public')->deleteDirectory($oldDirectory);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ public function authorize(): bool
|
|||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'folio' => 'nullable|string|max:50|unique:records,folio,' . $this->route('id'),
|
||||||
// --- DATOS DEL VEHÍCULO ---
|
// --- DATOS DEL VEHÍCULO ---
|
||||||
'vehicle.placa' => 'nullable|string|max:20',
|
'vehicle.placa' => 'nullable|string|max:20',
|
||||||
'vehicle.marca' => 'nullable|string|max:100',
|
'vehicle.marca' => 'nullable|string|max:100',
|
||||||
@ -60,6 +61,10 @@ public function rules(): array
|
|||||||
'files.*' => 'file|mimes:jpeg,png,jpg|max:2048',
|
'files.*' => 'file|mimes:jpeg,png,jpg|max:2048',
|
||||||
'name_id' => 'nullable|array',
|
'name_id' => 'nullable|array',
|
||||||
'name_id.*' => 'integer|exists:catalog_name_img,id',
|
'name_id.*' => 'integer|exists:catalog_name_img,id',
|
||||||
|
'observations' => 'nullable|array',
|
||||||
|
'observations.*' => 'nullable|string|max:500',
|
||||||
|
'delete_files' => 'nullable|array',
|
||||||
|
'delete_files.*' => 'integer|exists:files,id',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +77,10 @@ public function messages(): array
|
|||||||
'owner.cp.max' => 'El código postal debe tener máximo 5 caracteres',
|
'owner.cp.max' => 'El código postal debe tener máximo 5 caracteres',
|
||||||
'files.*.mimes' => 'Solo se permiten archivos JPG, PNG o JPEG',
|
'files.*.mimes' => 'Solo se permiten archivos JPG, PNG o JPEG',
|
||||||
'files.*.max' => 'El archivo no debe superar 2MB',
|
'files.*.max' => 'El archivo no debe superar 2MB',
|
||||||
|
'observations.*.max' => 'La observación no debe superar 120 caracteres',
|
||||||
|
'delete_files.*.exists' => 'El archivo a eliminar no existe',
|
||||||
|
'folio.unique' => 'El folio ya existe en el sistema',
|
||||||
|
'folio.max' => 'El folio no puede exceder 50 caracteres',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ class File extends Model
|
|||||||
'name_id',
|
'name_id',
|
||||||
'path',
|
'path',
|
||||||
'md5',
|
'md5',
|
||||||
|
'observations',
|
||||||
'record_id',
|
'record_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class Tag extends Model
|
|||||||
const STATUS_AVAILABLE = 'available';
|
const STATUS_AVAILABLE = 'available';
|
||||||
const STATUS_ASSIGNED = 'assigned';
|
const STATUS_ASSIGNED = 'assigned';
|
||||||
const STATUS_CANCELLED = 'cancelled';
|
const STATUS_CANCELLED = 'cancelled';
|
||||||
const STATUS_LOST = 'lost';
|
const STATUS_DAMAGED = 'damaged';
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'folio',
|
'folio',
|
||||||
@ -85,6 +85,19 @@ public function markAsCancelled(): void
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marcar tag como dañado
|
||||||
|
*/
|
||||||
|
public function markAsDamaged(): void
|
||||||
|
{
|
||||||
|
$statusDamaged = CatalogTagStatus::where('code', self::STATUS_DAMAGED)->first();
|
||||||
|
|
||||||
|
$this->update([
|
||||||
|
'status_id' => $statusDamaged->id,
|
||||||
|
'vehicle_id' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verificar si el tag está disponible
|
* Verificar si el tag está disponible
|
||||||
*/
|
*/
|
||||||
@ -109,4 +122,12 @@ public function isCancelled(): bool
|
|||||||
return $this->status->code === self::STATUS_CANCELLED;
|
return $this->status->code === self::STATUS_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verificar si el tag está dañado
|
||||||
|
*/
|
||||||
|
public function isDamaged(): bool
|
||||||
|
{
|
||||||
|
return $this->status->code === self::STATUS_DAMAGED;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('files', function (Blueprint $table) {
|
||||||
|
$table->text('observations')->nullable()->after('md5');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('files', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('observations');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Descripción
|
* Descripción
|
||||||
*
|
*
|
||||||
* @author Moisés Cortés C. <moises.cortes@notsoweb.com>
|
* @author Moisés Cortés C. <moises.cortes@notsoweb.com>
|
||||||
*
|
*
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
class CatalogNameImgSeeder extends Seeder
|
class CatalogNameImgSeeder extends Seeder
|
||||||
@ -40,6 +40,7 @@ public function run(): void
|
|||||||
'IDENTIFICACIÓN OFICIAL TRASERA',
|
'IDENTIFICACIÓN OFICIAL TRASERA',
|
||||||
'TARJETA DE CIRCULACIÓN',
|
'TARJETA DE CIRCULACIÓN',
|
||||||
'FOTO VIN',
|
'FOTO VIN',
|
||||||
|
'EVIDENCIA ADICIONAL',
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($names as $name) {
|
foreach ($names as $name) {
|
||||||
|
|||||||
@ -37,7 +37,13 @@ public function run(): void
|
|||||||
[
|
[
|
||||||
'code' => 'cancelled',
|
'code' => 'cancelled',
|
||||||
'name' => 'Cancelado',
|
'name' => 'Cancelado',
|
||||||
'description' => 'Tag cancelado (incluye perdidos, dañados o reemplazados)',
|
'description' => 'Tag cancelado',
|
||||||
|
'active' => true,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'damaged',
|
||||||
|
'name' => 'Dañado',
|
||||||
|
'description' => 'Tag dañado y no utilizable',
|
||||||
'active' => true,
|
'active' => true,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@ -126,11 +126,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr class="data-row">
|
<tr class="data-row">
|
||||||
<td class="data-label">MOTIVO:</td>
|
<td class="data-label">MOTIVO:</td>
|
||||||
<td class="data-value">{{ strtoupper($cancellation['motivo'] ?? '') }}</td>
|
<td class="data-value">{{ mb_strtoupper($cancellation['motivo'] ?? '') }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="data-row">
|
<tr class="data-row">
|
||||||
<td class="data-label">OPERADOR:</td>
|
<td class="data-label">OPERADOR:</td>
|
||||||
<td class="data-value">{{ strtoupper($cancellation['operador'] ?? '') }}</td>
|
<td class="data-value">{{ mb_strtoupper($cancellation['operador'] ?? '') }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="data-row">
|
<tr class="data-row">
|
||||||
<td class="data-label">MÓDULO:</td>
|
<td class="data-label">MÓDULO:</td>
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="es">
|
<html lang="es">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Constancia Sustituida - REPUVE Tabasco</title> <!-- CAMBIO LÍNEA 5 -->
|
<title>Constancia Sustituida - REPUVE Tabasco</title>
|
||||||
<style>
|
<style>
|
||||||
@page {
|
@page {
|
||||||
margin: 2cm 1.5cm;
|
margin: 2cm 1.5cm;
|
||||||
@ -44,13 +45,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.space-box {
|
.space-box {
|
||||||
height: 200px;
|
height: 470px;
|
||||||
|
width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
position: relative;
|
padding: 0;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 16pt;
|
font-size: 16pt;
|
||||||
text-align: center;
|
|
||||||
border-bottom: 1px solid #000;
|
border-bottom: 1px solid #000;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.space-box-text {
|
.space-box-text {
|
||||||
@ -59,6 +61,7 @@
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table {
|
.data-table {
|
||||||
@ -89,6 +92,7 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
@ -152,4 +156,5 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -42,7 +42,6 @@
|
|||||||
Route::get('expediente/{id}/pdfVerificacion', [RecordController::class, 'generatePdfVerification']);
|
Route::get('expediente/{id}/pdfVerificacion', [RecordController::class, 'generatePdfVerification']);
|
||||||
Route::get('expediente/{id}/pdfConstancia', [RecordController::class, 'generatePdfConstancia']);
|
Route::get('expediente/{id}/pdfConstancia', [RecordController::class, 'generatePdfConstancia']);
|
||||||
Route::get('expediente/{id}/pdfImagenes', [RecordController::class, 'generatePdfImages']);
|
Route::get('expediente/{id}/pdfImagenes', [RecordController::class, 'generatePdfImages']);
|
||||||
Route::get('tags/{tag}/pdfTag-cancelado', [RecordController::class, 'pdfCancelledTag']);
|
|
||||||
Route::get('tags/{id}/pdfTag-sustituido', [RecordController::class, 'pdfSubstitutedTag']);
|
Route::get('tags/{id}/pdfTag-sustituido', [RecordController::class, 'pdfSubstitutedTag']);
|
||||||
Route::get('expediente/{id}/pdfFormulario', [RecordController::class, 'generatePdfForm']);
|
Route::get('expediente/{id}/pdfFormulario', [RecordController::class, 'generatePdfForm']);
|
||||||
Route::get('RecordErrors', [RecordController::class, 'errors']);
|
Route::get('RecordErrors', [RecordController::class, 'errors']);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user