Correciones a RepuveService, Tags y Module
This commit is contained in:
parent
d8ec98cd7c
commit
75889becaf
@ -21,7 +21,12 @@ class ModuleController extends Controller
|
||||
public function index(Request $request)
|
||||
{
|
||||
try {
|
||||
$modules = Module::with(['responsible:id,name,email', 'municipality:id,code,name'])->withCount(['packages']);
|
||||
$modules = Module::with([
|
||||
'responsible:id,name,email',
|
||||
'municipality:id,code,name',
|
||||
'users:id,name,paternal,maternal,email,module_id',
|
||||
'users.roles:id,name,description'
|
||||
])->withCount(['packages']);
|
||||
|
||||
// Filtro por nombre
|
||||
if ($request->filled('name')) {
|
||||
@ -101,7 +106,12 @@ public function store(ModuleStoreRequest $request)
|
||||
public function show($id)
|
||||
{
|
||||
try {
|
||||
$modules = Module::with(['responsible:id,name,email', 'municipality:id,code,name'])->withCount(['packages'])->find($id);
|
||||
$modules = Module::with([
|
||||
'responsible:id,name,email',
|
||||
'municipality:id,code,name',
|
||||
'users:id,name,paternal,maternal,email,module_id',
|
||||
'users.roles:id,name,description'
|
||||
])->withCount(['packages'])->find($id);
|
||||
|
||||
return ApiResponse::OK->response([
|
||||
'module' => $modules,
|
||||
|
||||
@ -4,18 +4,26 @@
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\CatalogTagStatus;
|
||||
use App\Models\Module;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Tag;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Notsoweb\ApiResponse\Enums\ApiResponse;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class TagsController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
try {
|
||||
$tags = Tag::with('vehicle:id,placa,niv', 'package:id,lot,box_number', 'status:id,name')->orderBy('id', 'ASC');
|
||||
$tags = Tag::with([
|
||||
'vehicle:id,placa,niv',
|
||||
'package:id,lot,box_number',
|
||||
'status:id,code,name',
|
||||
'module:id,name'
|
||||
])->orderBy('id', 'ASC');
|
||||
|
||||
if ($request->has('status')) {
|
||||
$tags->whereHas('status', function ($q) use ($request) {
|
||||
@ -29,6 +37,10 @@ public function index(Request $request)
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->has('module_id')) {
|
||||
$tags->where('module_id', $request->module_id);
|
||||
}
|
||||
|
||||
return ApiResponse::OK->response([
|
||||
'tag' => $tags->paginate(config('app.pagination')),
|
||||
]);
|
||||
@ -91,7 +103,7 @@ public function tagStore(Request $request)
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
$statusAvailable = CatalogTagStatus::where('name', Tag::STATUS_AVAILABLE)->first();
|
||||
$statusAvailable = CatalogTagStatus::where('code', Tag::STATUS_AVAILABLE)->first();
|
||||
|
||||
if (!$statusAvailable) {
|
||||
return ApiResponse::NOT_FOUND->response([
|
||||
@ -99,6 +111,13 @@ public function tagStore(Request $request)
|
||||
]);
|
||||
}
|
||||
|
||||
if ($tag->module_id === null) {
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
'message' => 'El tag no está asignado a ningún módulo. Debe asignarse primero a un módulo antes de poder usarse.',
|
||||
'tag_number' => $tagNumber,
|
||||
]);
|
||||
}
|
||||
|
||||
$createdTags = [];
|
||||
$errors = [];
|
||||
|
||||
@ -197,12 +216,13 @@ public function assignToModule(Request $request)
|
||||
|
||||
DB::commit();
|
||||
|
||||
return ApiResponse::OK->response([
|
||||
'message' => 'Tags asignados al módulo correctamente.',
|
||||
'count' => count($tagIds),
|
||||
'module_id' => $request->module_id,
|
||||
'tags_assigned' => $tags->pluck('tag_number')->toArray(),
|
||||
]);
|
||||
// Generar PDF de Vale de Entrega
|
||||
$module = Module::with('users')->findOrFail($request->module_id);
|
||||
$tagsAssigned = Tag::whereIn('id', $tagIds)->orderBy('folio')->get();
|
||||
|
||||
$pdf = $this->generateValeEntregaPdf($module, $tagsAssigned);
|
||||
|
||||
return $pdf->download('vale-entrega-modulo-' . $module->id . '-' . date('YmdHis') . '.pdf');
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
return ApiResponse::INTERNAL_ERROR->response([
|
||||
@ -211,4 +231,28 @@ public function assignToModule(Request $request)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generar PDF de Vale de Entrega
|
||||
*/
|
||||
private function generateValeEntregaPdf(Module $module, $tags)
|
||||
{
|
||||
// Cargar responsables del módulo con sus roles
|
||||
$responsables = $module->users()->with('roles')->get();
|
||||
|
||||
// Preparar datos para el PDF
|
||||
$data = [
|
||||
'module' => $module,
|
||||
'responsables' => $responsables,
|
||||
'tags' => $tags,
|
||||
'total_tags' => $tags->count(),
|
||||
'fecha' => Carbon::now()->locale('es')->isoFormat('D [de] MMMM [de] YYYY'),
|
||||
];
|
||||
|
||||
//PDF
|
||||
$pdf = Pdf::loadView('pdfs.delivery', $data);
|
||||
$pdf->setPaper('letter', 'portrait');
|
||||
|
||||
return $pdf;
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,4 +68,9 @@ public function responsible()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'responsible_id');
|
||||
}
|
||||
|
||||
public function users()
|
||||
{
|
||||
return $this->hasMany(User::class, 'module_id');
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Services;
|
||||
|
||||
use Exception;
|
||||
use App\Models\Error;
|
||||
|
||||
class RepuveService
|
||||
{
|
||||
@ -72,10 +73,11 @@ private function parseVehicleResponse(string $soapResponse, string $niv)
|
||||
preg_match('/<return>(.*?)<\/return>/s', $soapResponse, $matches);
|
||||
|
||||
if (!isset($matches[1])) {
|
||||
$errorFromDb = Error::where('code', '108')->first();
|
||||
return [
|
||||
'has_error' => true,
|
||||
'error_code' => '108',
|
||||
'error_message' => 'El resultado que devuelve el Web service es de un formato distinto al esperado',
|
||||
'error_message' => $errorFromDb ? $errorFromDb->description : 'El resultado que devuelve el Web service es de un formato distinto al esperado',
|
||||
'timestamp' => now()->toDateTimeString(),
|
||||
'niv' => $niv,
|
||||
'repuve_response' => null,
|
||||
@ -84,21 +86,21 @@ private function parseVehicleResponse(string $soapResponse, string $niv)
|
||||
|
||||
$contenido = trim($matches[1]);
|
||||
|
||||
// Verificar si hay error
|
||||
// Verificar si hay error de REPUVE Nacional
|
||||
if (str_starts_with($contenido, 'ERROR:')) {
|
||||
$errorMessage = str_replace('ERROR:', '', $contenido);
|
||||
|
||||
// Intentar extraer código de error del mensaje (formato: "ERROR:461|Mensaje")
|
||||
$errorCode = '-1'; // Por defecto: Error Interno
|
||||
$errorCode = '-1';
|
||||
if (preg_match('/^(\d+)\|/', $errorMessage, $codeMatch)) {
|
||||
$errorCode = $codeMatch[1];
|
||||
$errorMessage = substr($errorMessage, strlen($errorCode) + 1);
|
||||
}
|
||||
|
||||
// Mensaje directo de REPUVE Nacional
|
||||
return [
|
||||
'has_error' => true,
|
||||
'error_code' => $errorCode,
|
||||
'error_message' => trim($errorMessage),
|
||||
'error_message' => trim($errorMessage), // Mensaje directo de REPUVE
|
||||
'timestamp' => now()->toDateTimeString(),
|
||||
'niv' => $niv,
|
||||
'repuve_response' => null,
|
||||
@ -154,10 +156,11 @@ private function parseVehicleResponse(string $soapResponse, string $niv)
|
||||
];
|
||||
}
|
||||
|
||||
$errorFromDb = Error::where('code', '108')->first();
|
||||
return [
|
||||
'has_error' => true,
|
||||
'error_code' => '108',
|
||||
'error_message' => 'El resultado que devuelve el Web service es de un formato distinto al esperado',
|
||||
'error_message' => $errorFromDb ? $errorFromDb->description : 'El resultado que devuelve el Web service es de un formato distinto al esperado',
|
||||
'timestamp' => now()->toDateTimeString(),
|
||||
'niv' => $niv,
|
||||
'repuve_response' => null,
|
||||
@ -275,10 +278,11 @@ public function inscribirVehiculo(array $datos)
|
||||
]);
|
||||
|
||||
if ($curlError) {
|
||||
$errorFromDb = Error::where('code', '103')->first();
|
||||
return [
|
||||
'has_error' => true,
|
||||
'error_code' => '103',
|
||||
'error_message' => "Error de conexión al Web Service desde el cliente: {$curlError}",
|
||||
'error_message' => $errorFromDb ? $errorFromDb->description : "Error de conexión al Web Service: {$curlError}",
|
||||
'timestamp' => now()->toDateTimeString(),
|
||||
'http_code' => $httpCode,
|
||||
'raw_response' => $response,
|
||||
@ -286,10 +290,11 @@ public function inscribirVehiculo(array $datos)
|
||||
}
|
||||
|
||||
if ($httpCode !== 200) {
|
||||
$errorFromDb = Error::where('code', '-1')->first();
|
||||
return [
|
||||
'has_error' => true,
|
||||
'error_code' => '-1',
|
||||
'error_message' => "Error interno del web service. Código HTTP {$httpCode}",
|
||||
'error_message' => $errorFromDb ? $errorFromDb->description : "Error interno del web service. Código HTTP {$httpCode}",
|
||||
'timestamp' => now()->toDateTimeString(),
|
||||
'http_code' => $httpCode,
|
||||
'raw_response' => $response,
|
||||
@ -308,10 +313,11 @@ private function parsearRespuestaInscripcion(string $soapResponse)
|
||||
preg_match('/<return>(.*?)<\/return>/s', $soapResponse, $matches);
|
||||
|
||||
if (!isset($matches[1])) {
|
||||
$errorFromDb = Error::where('code', '108')->first();
|
||||
return [
|
||||
'has_error' => true,
|
||||
'error_code' => '108',
|
||||
'error_message' => 'El resultado que devuelve el Web service es de un formato distinto al esperado',
|
||||
'error_message' => $errorFromDb ? $errorFromDb->description : 'El resultado que devuelve el Web service es de un formato distinto al esperado',
|
||||
'timestamp' => now()->toDateTimeString(),
|
||||
'raw_response' => $soapResponse,
|
||||
'repuve_response' => null,
|
||||
@ -329,10 +335,11 @@ private function parsearRespuestaInscripcion(string $soapResponse)
|
||||
$errorMessage = substr($errorMessage, strlen($errorCode) + 1);
|
||||
}
|
||||
|
||||
// Mensaje directo de REPUVE Nacional
|
||||
return [
|
||||
'has_error' => true,
|
||||
'error_code' => $errorCode,
|
||||
'error_message' => trim($errorMessage),
|
||||
'error_message' => trim($errorMessage), // Mensaje directo de REPUVE
|
||||
'timestamp' => now()->toDateTimeString(),
|
||||
'raw_response' => $soapResponse,
|
||||
'repuve_response' => null,
|
||||
@ -352,10 +359,11 @@ private function parsearRespuestaInscripcion(string $soapResponse)
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$errorFromDb = Error::where('code', '108')->first();
|
||||
return [
|
||||
'has_error' => true,
|
||||
'error_code' => '108',
|
||||
'error_message' => 'El resultado que devuelve el Web service es de un formato distinto al esperado',
|
||||
'error_message' => $errorFromDb ? $errorFromDb->description : 'El resultado que devuelve el Web service es de un formato distinto al esperado',
|
||||
'timestamp' => now()->toDateTimeString(),
|
||||
'raw_response' => $soapResponse,
|
||||
'repuve_response' => null,
|
||||
|
||||
282
resources/views/pdfs/delivery.blade.php
Normal file
282
resources/views/pdfs/delivery.blade.php
Normal file
@ -0,0 +1,282 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Vale de Entrega de Constancias</title>
|
||||
<style>
|
||||
/* CONFIGURACIÓN DE PÁGINA */
|
||||
@page {
|
||||
margin: 1.2cm 1.5cm;
|
||||
size: letter;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 10pt;
|
||||
line-height: 1.3;
|
||||
color: #000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* HEADER */
|
||||
.header {
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.header-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 25%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.header-center {
|
||||
width: 40%;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 35%;
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
.logo {
|
||||
max-height: 50px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 9pt;
|
||||
font-weight: bold;
|
||||
line-height: 1.2;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* CUERPO DEL DOCUMENTO */
|
||||
.date-location {
|
||||
text-align: right;
|
||||
font-size: 9pt;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 12pt;
|
||||
margin: 10px 0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: justify;
|
||||
margin-bottom: 12px;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
/* LISTA DE TAGS */
|
||||
.tag-list {
|
||||
margin: 10px 0;
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
.tag-columns {
|
||||
column-count: 3;
|
||||
column-gap: 15px;
|
||||
}
|
||||
|
||||
.tag-item {
|
||||
margin: 2px 0;
|
||||
break-inside: avoid;
|
||||
}
|
||||
|
||||
/* --- ZONA DE FIRMAS (CSS IMPORTANTE AQUÍ) --- */
|
||||
.firmas-container {
|
||||
margin-top: 40px; /* Más espacio antes de empezar las firmas */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.firma-titulo {
|
||||
font-weight: bold;
|
||||
font-size: 10pt;
|
||||
margin-bottom: 15px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Contenedor para centrar la firma única de Entrega */
|
||||
.firma-entrega-wrapper {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
/* Contenedor general de Reciben */
|
||||
.reciben-wrapper {
|
||||
width: 100%;
|
||||
text-align: center; /* Esto centra las firmas horizontalmente */
|
||||
font-size: 0; /* Truco para eliminar espacios fantasmas entre inline-blocks */
|
||||
}
|
||||
|
||||
/* CAJA INDIVIDUAL DE FIRMA (RECIBEN) */
|
||||
.firma-reciben-item {
|
||||
width: 44%; /* Menos del 50% para que quepan 2 */
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-left: 2%;
|
||||
margin-right: 2%;
|
||||
margin-bottom: 60px; /* <--- ESTO ARREGLA QUE ESTÉN PEGADOS VERTICALMENTE */
|
||||
font-size: 10pt; /* Restauramos tamaño de letra */
|
||||
}
|
||||
|
||||
/* CAJA INDIVIDUAL DE ENTREGA */
|
||||
.firma-entrega-box {
|
||||
display: inline-block;
|
||||
width: 50%; /* Ancho controlado para que no ocupe toda la hoja */
|
||||
}
|
||||
|
||||
.firma-linea {
|
||||
border-top: 1px solid #000;
|
||||
padding-top: 5px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.firma-nombre {
|
||||
font-weight: bold;
|
||||
font-size: 9pt;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.firma-cargo {
|
||||
font-size: 8pt;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
/* FOOTER */
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 7pt;
|
||||
text-align: center;
|
||||
border-top: 1px solid #ccc;
|
||||
padding-top: 5px;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<table class="header-table">
|
||||
<tr>
|
||||
<td class="header-left">
|
||||
<?php
|
||||
$imagePath = resource_path('images/logo-seguridad.png');
|
||||
$imageData = base64_encode(file_get_contents($imagePath));
|
||||
$imageSrc = 'data:image/png;base64,' . $imageData;
|
||||
?>
|
||||
<img src="{{ $imageSrc }}" alt="Logo Seguridad" class="logo">
|
||||
</td>
|
||||
<td class="header-center">
|
||||
<p class="header-title">
|
||||
<strong>SEGURIDAD</strong><br>
|
||||
SECRETARIA DE SEGURIDAD<br>
|
||||
Y PROTECCIÓN CIUDADANA
|
||||
</p>
|
||||
</td>
|
||||
<td class="header-right">
|
||||
<p class="header-title">
|
||||
Dirección General de la Policía Estatal de Caminos<br>
|
||||
Dirección de Servicios al Público<br>
|
||||
Departamento del Registro Público Vehicular
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="date-location">
|
||||
Villahermosa, Tabasco a {{ $fecha }}
|
||||
</div>
|
||||
|
||||
<div class="title">
|
||||
VALE DE ENTREGA
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
Se realiza la entrega de <strong>{{ $total_tags }}</strong>
|
||||
constancias de inscripción de segunda generación (moradas) para la realización de trámites del Registro
|
||||
Público Vehicular, las cuales se enumeran por folios, a continuación.
|
||||
</div>
|
||||
|
||||
<div class="tag-list">
|
||||
<div class="tag-columns">
|
||||
@foreach($tags as $index => $tag)
|
||||
<div class="tag-item">
|
||||
{{ $index + 1 }}. {{ $tag->folio }}
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="firmas-container">
|
||||
|
||||
<div>
|
||||
<div class="firma-titulo">ENTREGA</div>
|
||||
<div class="firma-entrega-wrapper">
|
||||
<div class="firma-entrega-box">
|
||||
<div class="firma-linea">
|
||||
<p class="firma-nombre">LIC. MARY ISABEL RAMON MADRIGAL</p>
|
||||
<p class="firma-cargo">JEFA DEL DEPARTAMENTO REPUVE</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="firma-titulo">RECIBEN</div>
|
||||
<div class="reciben-wrapper">
|
||||
@foreach($responsables as $responsable)
|
||||
<div class="firma-reciben-item">
|
||||
<div class="firma-linea">
|
||||
<p class="firma-nombre">
|
||||
{{ strtoupper($responsable->full_name) }}
|
||||
</p>
|
||||
<p class="firma-cargo">
|
||||
{{ strtoupper($responsable->roles->first()->description ?? 'RESPONSABLE') }} MÓDULO {{ $module->id }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
Av. Adolfo Ruiz Cortines, S/N, Colonia Casa Blanca, C.P. 86060, Villahermosa, Tabasco, México<br>
|
||||
Tel: 9933156230 | www.ssptabasco.gob.mx
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -72,6 +72,7 @@
|
||||
Route::resource('tags', TagsController::class);
|
||||
Route::post('tags/import', [TagsController::class, 'tagStore']);
|
||||
Route::post('tags/assign-to-module', [TagsController::class, 'assignToModule']);
|
||||
Route::get('tags/pdf-vale-entrega', [TagsController::class, 'generateValeEntregaPdf']);
|
||||
|
||||
//Rutas de nombres de archivos en catálogo
|
||||
Route::resource('catalog-name-imgs', CatalogNameImgController::class);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user