fix: mejorar validaciones y extraer datos adicionales en el proceso de cancelación de tags

This commit is contained in:
Juan Felipe Zapata Moreno 2025-12-17 23:19:53 -06:00
parent 89989c6fe4
commit 1c6cb99187
3 changed files with 134 additions and 94 deletions

View File

@ -71,7 +71,7 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
if ($isSubstitution) {
$newTag = Tag::where('folio', $request->new_folio)->first();
if(!$newTag){
if (!$newTag) {
DB::rollBack();
return ApiResponse::NOT_FOUND->response([
'message' => 'El nuevo tag proporcionado no existe.',
@ -79,7 +79,7 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
]);
}
if(!$newTag->isAvailable()) {
if (!$newTag->isAvailable()) {
DB::rollBack();
return ApiResponse::BAD_REQUEST->response([
'message' => 'El nuevo tag no está disponible para asignación',
@ -88,29 +88,26 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
]);
}
if(!$newTag->tag_number){
if (!$newTag->tag_number) {
$existingTag = Tag::where('tag_number', $request->new_tag_number)->first();
if($existingTag && $existingTag->id !== $newTag->id){
if ($existingTag && $existingTag->id !== $newTag->id) {
DB::rollBack();
return ApiResponse::BAD_REQUEST->response([
'message' => 'El nuevo tag_number ya está asignado a otro folio.',
'new_tag_number' => $request->new_tag_number,
'folio_existente' => $existingTag->folio,
]);
}
$newTag->tag_number = $request->new_tag_number;
$newTag->save();
}elseif($newTag->tag_number !== $request->new_tag_number){
DB::rollBack();
return ApiResponse::BAD_REQUEST->response([
'message' => 'El nuevo tag ya tiene un tag_number diferente asignado.',
'assigned_tag_number' => $newTag->tag_number,
'provided_tag_number' => $request->new_tag_number,
]);
} elseif ($newTag->tag_number !== $request->new_tag_number) {
DB::rollBack();
return ApiResponse::BAD_REQUEST->response([
'message' => 'El nuevo tag ya tiene un tag_number diferente asignado.',
'assigned_tag_number' => $newTag->tag_number,
'provided_tag_number' => $request->new_tag_number,
]);
}
// Usar el folio del request
@ -179,80 +176,97 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
}
public function cancelarTagNoAsignado(Request $request)
{
try {
$request->validate([
'folio' => 'required|string|exists:tags,folio',
'cancellation_reason_id' => 'required|exists:catalog_cancellation_reasons,id',
'cancellation_observations' => 'nullable|string',
]);
{
try {
$request->validate([
'folio' => 'required|string|exists:tags,folio',
'cancellation_reason_id' => 'required|exists:catalog_cancellation_reasons,id',
'cancellation_observations' => 'nullable|string',
'id_chip' => 'nullable|string|max:255',
'module_id' => 'nullable|exists:modules,id',
]);
DB::beginTransaction();
DB::beginTransaction();
$tag = Tag::where('folio', $request->folio)->first();
$tag = Tag::where('folio', $request->folio)->first();
if (!$tag) {
if (!$tag) {
DB::rollBack();
return ApiResponse::NOT_FOUND->response([
'message' => 'No se encontró el tag con el folio proporcionado.',
'folio' => $request->folio,
]);
}
// Validar que el tag NO esté asignado
if ($tag->isAssigned()) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'Este tag está asignado a un vehículo. Usa el endpoint de cancelación de constancia.',
'tag_status' => $tag->status->name,
]);
}
// Validar que no esté ya cancelado
if ($tag->isCancelled()) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'El tag ya está cancelado.',
]);
}
$additionalInfo = [];
if ($request->filled('id_chip')) {
$additionalInfo[] = "ID CHIP: {$request->id_chip}";
}
$observations = $request->cancellation_observations;
if (!empty($additionalInfo)) {
$observations = ($observations ? $observations . ' | ' : '') . implode(' | ', $additionalInfo);
}
$cancellationLog = TagCancellationLog::create([
'tag_id' => $tag->id,
'cancellation_reason_id' => $request->cancellation_reason_id,
'cancellation_observations' => $observations,
'cancellation_at' => now(),
'cancelled_by' => Auth::id(),
]);
// Actualizar el módulo del tag si se proporciona
if ($request->filled('module_id')) {
$tag->module_id = $request->module_id;
$tag->save();
}
// Cancelar el tag
$tag->markAsCancelled();
DB::commit();
return ApiResponse::OK->response([
'message' => 'Tag cancelado exitosamente',
'tag' => [
'id' => $tag->id,
'tag_number' => $tag->tag_number,
'folio' => $tag->folio,
'previous_status' => 'Disponible',
'new_status' => 'Cancelado',
],
'cancellation' => [
'id' => $cancellationLog->id,
'reason' => $cancellationLog->cancellationReason->name,
'observations' => $cancellationLog->cancellation_observations,
'cancelled_at' => $cancellationLog->cancellation_at->toDateTimeString(),
'cancelled_by' => Auth::user()->name,
],
]);
} catch (\Exception $e) {
DB::rollBack();
return ApiResponse::NOT_FOUND->response([
'message' => 'No se encontró el tag con el folio proporcionado.',
'folio' => $request->folio,
]);
}
// Validar que el tag NO esté asignado
if ($tag->isAssigned()) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'Este tag está asignado a un vehículo. Usa el endpoint de cancelación de constancia.',
'tag_status' => $tag->status->name,
'message' => 'Error al cancelar el tag',
'error' => $e->getMessage(),
]);
}
// Validar que no esté ya cancelado
if ($tag->isCancelled()) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'El tag ya está cancelado.',
]);
}
// Crear log de cancelación ANTES de cancelar el tag
$cancellationLog = TagCancellationLog::create([
'tag_id' => $tag->id,
'cancellation_reason_id' => $request->cancellation_reason_id,
'cancellation_observations' => $request->cancellation_observations,
'cancellation_at' => now(),
'cancelled_by' => Auth::id(),
]);
// Cancelar el tag
$tag->markAsCancelled();
DB::commit();
return ApiResponse::OK->response([
'message' => 'Tag cancelado exitosamente',
'tag' => [
'id' => $tag->id,
'tag_number' => $tag->tag_number,
'folio' => $tag->folio,
'previous_status' => 'Disponible',
'new_status' => 'Cancelado',
],
'cancellation' => [
'id' => $cancellationLog->id,
'reason' => $cancellationLog->cancellationReason->name,
'observations' => $cancellationLog->cancellation_observations,
'cancelled_at' => $cancellationLog->cancellation_at->toDateTimeString(),
'cancelled_by' => Auth::user()->name,
],
]);
} catch (\Exception $e) {
DB::rollBack();
return ApiResponse::BAD_REQUEST->response([
'message' => 'Error al cancelar el tag',
'error' => $e->getMessage(),
]);
}
}
}

View File

@ -373,11 +373,18 @@ private function cancellationData(Tag $tag)
->first();
if ($tagCancellationLog) {
$data['fecha'] = $tagCancellationLog->cancellation_at->format('d/m/Y');
$data['motivo'] = $tagCancellationLog->cancellationReason->name ?? 'No especificado';
$data['operador'] = $tagCancellationLog->cancelledBy->name ?? 'Sistema';
// Cargar módulo del cual el usuario es responsable
if ($tagCancellationLog->cancelledBy) {
// Extraer datos adicionales de las observaciones
$this->extractAdditionalDataFromObservations($tagCancellationLog->cancellation_observations, $data);
// Cargar módulo del tag si existe, sino cargar módulo del usuario
if ($tag->module_id && $tag->module) {
$data['modulo'] = $tag->module->name;
$data['ubicacion'] = $tag->module->address;
} elseif ($tagCancellationLog->cancelledBy) {
$user = $tagCancellationLog->cancelledBy;
$this->loadUserModule($user, $data);
}
@ -412,6 +419,31 @@ private function cancellationData(Tag $tag)
return $data;
}
/**
* Extraer datos adicionales de las observaciones de cancelación
*/
private function extractAdditionalDataFromObservations($observations, &$data)
{
if (empty($observations)) {
return;
}
// Extraer ID CHIP
if (preg_match('/ID CHIP:\s*([^|]+)/', $observations, $matches)) {
$data['id_chip'] = trim($matches[1]);
}
// Extraer PLACA
if (preg_match('/PLACA:\s*([^|]+)/', $observations, $matches)) {
$data['placa'] = trim($matches[1]);
}
// Extraer VIN
if (preg_match('/VIN:\s*([^|]+)/', $observations, $matches)) {
$data['niv'] = trim($matches[1]);
}
}
private function substitutionData(Tag $tag)
{
$data = [

View File

@ -44,13 +44,14 @@
}
.space-box {
height: 200px;
height: 470px;
width: 100%;
margin: 0;
position: relative;
padding: 0;
font-weight: bold;
font-size: 16pt;
text-align: center;
border-bottom: 1px solid #000;
position: relative;
}
.space-box-text {
@ -59,6 +60,7 @@
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
text-align: center;
}
.data-table {
@ -122,14 +124,6 @@
<td class="data-label">ID CHIP:</td>
<td class="data-value">{{ $cancellation['id_chip'] ?? '' }}</td>
</tr>
<tr class="data-row">
<td class="data-label">PLACAS:</td>
<td class="data-value">{{ $cancellation['placa'] ?? '' }}</td>
</tr>
<tr class="data-row">
<td class="data-label">VIN:</td>
<td class="data-value">{{ $cancellation['niv'] ?? '' }}</td>
</tr>
<tr class="data-row">
<td class="data-label">MOTIVO:</td>
<td class="data-value">{{ strtoupper($cancellation['motivo'] ?? '') }}</td>