Update Tag Model, add TagController and routes, fix InscriptionControlle

This commit is contained in:
Edgar Méndez Mendoza 2025-10-27 09:25:30 -06:00
parent e97d124967
commit 843d3404e9
6 changed files with 130 additions and 36 deletions

View File

@ -28,35 +28,35 @@ public function vehicleInscription(VehicleStoreRequest $request)
{
try {
$folio = $request->input('folio');
$tagId = $request->input('tag_id');
$tagNumber = $request->input('tag_number');
$vin = $request->input('vin');
// Buscar Tag y validar que NO tenga vehículo asignado
$tag = Tag::findOrFail($tagId);
$tag = Tag::where('folio', $folio)->where('tag_number', $tagNumber)->first();
if (!$tag) {
return ApiResponse::NOT_FOUND->response([
'message' => 'No se encontró el tag con el folio y tag_number proporcionados.',
'folio' => $folio,
'tag_number' => $tagNumber,
]);
}
if ($tag->vehicle_id) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'El tag ya está asignado a un vehículo. Use actualizar en su lugar.',
'tag_id' => $tagId,
'tag_number' => $tagNumber,
'vehicle_id' => $tag->vehicle_id,
]);
}
// Validar que el folio del tag coincida
if ($tag->folio !== $folio) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'El folio no coincide con el tag RFID proporcionado',
'folio_request' => $folio,
'folio_tag' => $tag->folio,
]);
}
// Verificar robo (API Repuve Nacional)
$isStolen = $this->checkIfStolen($folio);
if ($isStolen) {
return ApiResponse::FORBIDDEN->response([
'folio' => $folio,
'tag_id' => $tagId,
'tag_number' => $tagNumber,
'stolen' => true,
'message' => 'El vehículo reporta robo. No se puede continuar con la inscripción.',
]);
@ -85,7 +85,7 @@ public function vehicleInscription(VehicleStoreRequest $request)
$vehicle = Vehicle::create([
'anio_placa' => $vehicleData['ANIO_PLACA'],
'placa' => $vehicleData['PLACA'],
'numero_serie' => $vehicleData['NO_SERIE'],
'numero_serie' => $vin,
'rfc' => $vehicleData['RFC'],
'folio' => $folio,
'vigencia' => $vehicleData['VIGENCIA'],
@ -155,7 +155,10 @@ public function vehicleInscription(VehicleStoreRequest $request)
}
// Enviar a API Repuve Nacional
$apiResponse = $this->sendToRepuveNacional($folio, $tagId, $vehicleData);
$apiResponse = $this->sendToRepuveNacional($vin);
$apiResponse["repuve_response"]["folio_ci"] = $folio;
$apiResponse["repuve_response"]["identificador_ci"] = $tagNumber;
// Procesar respuesta
if (isset($apiResponse['has_error']) && $apiResponse['has_error']) {
@ -260,13 +263,13 @@ private function checkIfStolen(string $folio): bool
return (bool) rand(0, 1);
}
private function sendToRepuveNacional(string $folio, int $tagId, array $vehicleData): array
private function sendToRepuveNacional(string $vin): array
{
// Enviar datos a API Repuve Nacional
// Aquí se haría la llamada real a la API de Repuve Nacional
// Por ahora simulamos respuestas aleatorias usando la tabla errors
$hasError = (bool) rand(0, 1);
/* $hasError = (bool) rand(0, 1);
if ($hasError) {
// Obtener un error aleatorio de la tabla errors
@ -279,8 +282,7 @@ private function sendToRepuveNacional(string $folio, int $tagId, array $vehicleD
'error_code' => 'ERR_UNKNOWN',
'error_message' => 'No hay errores registrados en el catálogo',
'timestamp' => now()->toDateTimeString(),
'folio' => $folio,
'tag_id' => $tagId,
'vin' => $vin,
'response_data' => null,
];
}
@ -290,25 +292,57 @@ private function sendToRepuveNacional(string $folio, int $tagId, array $vehicleD
'error_code' => $error->code,
'error_message' => $error->description,
'timestamp' => now()->toDateTimeString(),
'folio' => $folio,
'tag_id' => $tagId,
'vin' => $vin,
'response_data' => null,
];
} */
// Respuesta exitosa mockup REPUVE
$mockResponse = "OK:SIN INFORMACION|OTROS|SIN INFORMACION|10/07/2023|CENTRO|$vin|WSA548B|HR16777934V|2023|BLANCO|ADVANCE|TABASCO|NISSAN|MARCH|PARTICULAR|AUTOMOVIL|ACTIVO|null||null|0|null|0|10337954|E2003412012BB0C130FAD04D|Sin observaciones
";
// Parsear la cadena a JSON
// Parsear la cadena a JSON usando los campos oficiales
$fields = [
'marca',
'submarca',
'tipo_vehiculo',
'fecha_expedicion',
'oficina',
'niv',
'placa',
'motor',
'modelo',
'color',
'version',
'entidad',
'marca_padron',
'submarca_padron',
'tipo_uso_padron',
'tipo_vehiculo_padron',
'estatus_registro',
'aduana',
'nombre_aduana',
'patente',
'pedimento',
'fecha_pedimento',
'clave_importador',
'folio_ci',
'identificador_ci',
'observaciones'
];
$values = explode('|', str_replace('OK:', '', $mockResponse));
$jsonResponse = [];
foreach ($fields as $i => $field) {
$jsonResponse[$field] = $values[$i] ?? null;
}
// Respuesta exitosa
return [
'has_error' => false,
'error_code' => null,
'error_message' => null,
'timestamp' => now()->toDateTimeString(),
'folio' => $folio,
'tag_id' => $tagId,
'response_data' => [
'status' => 'success',
'repuve_id' => 'REPUVE-' . strtoupper(uniqid()),
'validated' => true,
],
'vin' => $vin,
'repuve_response' => $jsonResponse,
];
}
@ -548,7 +582,6 @@ public function listTags(Request $request)
'to' => $tags->lastItem(),
],
]);
} catch (ValidationException $e) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'Error de validación',
@ -565,5 +598,4 @@ public function listTags(Request $request)
]);
}
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace App\Http\Controllers;
/**
* @copyright (c) 2025 Notsoweb Software (https://notsoweb.com) - All Rights Reserved
*/
use Illuminate\Http\Request;
use App\Models\Tag;
use Notsoweb\ApiResponse\Enums\ApiResponse;
/**
* Descripción
*
* @author Moisés Cortés C. <moises.cortes@notsoweb.com>
*
* @version 1.0.0
*/
class TagsController extends Controller
{
public function index()
{
$tags = Tag::all();
return ApiResponse::OK->response([
'data' => $tags,
]);
}
public function store(Request $request)
{
$validated = $request->validate([
'folio' => 'required|string|max:255',
'package_id' => 'required|integer|exists:packages,id',
'tag_number' => 'required|string|max:255',
]);
$tag = Tag::create($validated);
return ApiResponse::CREATED->response([
'tag' => $tag,
]);
}
public function show(Tag $tag)
{
return ApiResponse::OK->response([
'tag' => $tag,
]);
}
}

View File

@ -14,7 +14,8 @@ public function rules(): array
{
return [
'folio' => ['required', 'string', 'max:50'],
'tag_id' => ['required', 'exists:tags,id'],
'tag_number' => ['required', 'string', 'exists:tags,tag_number'],
'vin' => ['required', 'string', 'max:30'],
'files' => ['nullable', 'array', 'min:1'],
'files.*' => ['file', 'mimes:jpeg,png,jpg,pdf', 'max:10240'],
'names' => ['nullable', 'array'],
@ -27,8 +28,10 @@ public function messages(): array
return [
'folio.required' => 'El folio es requerido',
'folio.string' => 'El folio debe ser una cadena de texto',
'tag_id.required' => 'El tag_id es requerido',
'tag_id.exists' => 'El tag_id no existe en el sistema',
'tag_number.required' => 'El tag_number es requerido',
'tag_number.exists' => 'El tag_number no existe en el sistema',
'vin.required' => 'El VIN es requerido',
'vin.string' => 'El VIN debe ser una cadena de texto',
'files.array' => 'Los archivos deben ser un array',
'files.*.file' => 'Cada elemento debe ser un archivo válido',
'files.*.mimes' => 'Los archivos deben ser de tipo: jpeg, png, jpg, pdf',

View File

@ -11,6 +11,7 @@ class Tag extends Model
protected $fillable = [
'folio',
'tag_number',
'vehicle_id',
'package_id',
];

View File

@ -14,6 +14,7 @@ public function up(): void
Schema::create('tags', function (Blueprint $table) {
$table->id();
$table->string('folio')->unique();
$table->string('tag_number')->unique()->nullable();
$table->foreignId('vehicle_id')->nullable()->unique()->constrained('vehicle')->nullOnDelete();
$table->foreignId('package_id')->nullable()->constrained('packages')->nullOnDelete();
$table->enum('status', ['available', 'assigned', 'cancelled', 'lost'])->default('available');

View File

@ -8,6 +8,7 @@
use App\Http\Controllers\Admin\RoleController;
use App\Http\Controllers\Repuve\DeviceController;
use App\Http\Controllers\Repuve\PackageController;
use App\Http\Controllers\TagsController;
/**
* Rutas del núcleo de la aplicación.
@ -63,6 +64,10 @@
Route::put('/packages-update/{id}', [PackageController::class, 'update']);
Route::delete('/packages/{id}', [PackageController::class, 'destroy']);
//Ruta CRUD Tags
Route::resource('tags', TagsController::class);
});
/** Rutas públicas */