WIP
This commit is contained in:
parent
1d69c5ee7c
commit
3a25257dc5
@ -113,10 +113,7 @@ public function vehicleInscription(VehicleStoreRequest $request)
|
||||
]);
|
||||
|
||||
// Asignar Tag al vehículo
|
||||
$tag->update([
|
||||
'vehicle_id' => $vehicle->id,
|
||||
'folio' => $folio,
|
||||
]);
|
||||
$tag->markAsAssigned($vehicle->id, $folio);
|
||||
|
||||
// Crear registro
|
||||
$record = Record::create([
|
||||
@ -132,12 +129,15 @@ public function vehicleInscription(VehicleStoreRequest $request)
|
||||
$fileNames = $request->input('names', []);
|
||||
|
||||
foreach ($files as $index => $file) {
|
||||
$fileName = uniqid() . '_' . time() . '_' . $file->getClientOriginalName();
|
||||
$customName = $fileNames[$index] ?? "archivo_" . ($index + 1);
|
||||
$customName = str_replace(' ', '_', $customName);
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$fileName = $customName . '_' . time() . '.' . $extension;
|
||||
$path = $file->storeAs('/', $fileName, 'records');
|
||||
$md5 = md5_file($file->getRealPath());
|
||||
|
||||
$fileRecord = File::create([
|
||||
'name' => $fileNames[$index] ?? "Archivo " . ($index + 1),
|
||||
'name' => $customName,
|
||||
'path' => $path,
|
||||
'md5' => $md5,
|
||||
'record_id' => $record->id,
|
||||
@ -240,6 +240,7 @@ public function vehicleInscription(VehicleStoreRequest $request)
|
||||
'tag' => [
|
||||
'id' => $tag->id,
|
||||
'folio' => $tag->folio,
|
||||
'status' => $tag->status,
|
||||
],
|
||||
'files' => $uploadedFiles,
|
||||
'total_files' => count($uploadedFiles),
|
||||
|
||||
@ -78,7 +78,6 @@ public function generatePdfImages($id)
|
||||
$pdf->SetAutoPageBreak(false);
|
||||
$pdf->SetMargins(10, 10, 10);
|
||||
|
||||
$totalImages = $record->files->count();
|
||||
$currentImage = 0;
|
||||
|
||||
foreach ($record->files as $file) {
|
||||
@ -137,6 +136,9 @@ public function generatePdfImages($id)
|
||||
case IMAGETYPE_JPEG:
|
||||
$imageExtension = 'JPEG';
|
||||
break;
|
||||
case IMAGETYPE_JPEG:
|
||||
$imageExtension = 'JPG';
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
$imageExtension = 'PNG';
|
||||
break;
|
||||
|
||||
@ -56,4 +56,21 @@ public function show(Tag $tag)
|
||||
'tag' => $tag,
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(Tag $tag)
|
||||
{
|
||||
try{
|
||||
$tag->delete();
|
||||
return ApiResponse::OK->response([
|
||||
'message' => 'Tag eliminado correctamente.',
|
||||
]);
|
||||
|
||||
}catch(\Exception $e){
|
||||
return ApiResponse::INTERNAL_ERROR->response([
|
||||
'message' => 'Error al eliminar el tag.',
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,36 +20,36 @@ class UpdateController extends Controller
|
||||
public function vehicleUpdate(VehicleUpdateRequest $request)
|
||||
{
|
||||
try {
|
||||
$folio = $request->input('folio');
|
||||
$tagId = $request->input('tag_id');
|
||||
$recordId = $request->input('record_id');
|
||||
|
||||
// Buscar vehículo por folio y tag
|
||||
$tag = Tag::with('vehicle.owner')->findOrFail($tagId);
|
||||
$record = Record::with(['vehicle.owner', 'vehicle.tag', 'files', 'error'])->find($recordId);
|
||||
|
||||
// Validar que el tag corresponda al folio
|
||||
if ($tag->folio !== $folio) {
|
||||
// Validar que el tag
|
||||
if (!$record) {
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
'message' => 'El folio no coincide con el tag RFID proporcionado',
|
||||
'folio_request' => $folio,
|
||||
'folio_tag' => $tag->folio,
|
||||
'message' => 'No se encontró el expediente',
|
||||
'record_id' => $recordId,
|
||||
]);
|
||||
}
|
||||
|
||||
$vehicle = $tag->vehicle;
|
||||
$vehicle = $record->vehicle;
|
||||
$tag = $vehicle->tag;
|
||||
|
||||
if (!$vehicle) {
|
||||
if (!$tag) {
|
||||
return ApiResponse::NOT_FOUND->response([
|
||||
'message' => 'No se encontró un vehículo asociado al tag',
|
||||
'message' => 'El vehículo no tiene tag asociado',
|
||||
'vehicle_id' => $vehicle->placa,
|
||||
]);
|
||||
}
|
||||
|
||||
// Consultar API Repuve Nacional (verificar robo)
|
||||
$isStolen = $this->checkIfStolen($folio);
|
||||
$isStolen = $this->checkIfStolen($record->folio);
|
||||
|
||||
if ($isStolen) {
|
||||
return ApiResponse::FORBIDDEN->response([
|
||||
'folio' => $folio,
|
||||
'tag_id' => $tagId,
|
||||
'record_id' => $recordId,
|
||||
'tag_number' => $tag->tag_number,
|
||||
'stolen' => true,
|
||||
'message' => 'El vehículo reporta robo. No se puede continuar con la actualización.',
|
||||
]);
|
||||
@ -80,7 +80,7 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
|
||||
// NO actualizar 'placa' - es UNIQUE
|
||||
// NO actualizar 'numero_serie' - es UNIQUE (NIV/VIN)
|
||||
'rfc' => $vehicleData['RFC'],
|
||||
'folio' => $folio,
|
||||
// NO actualizar 'folio' => $folio,
|
||||
'vigencia' => $vehicleData['VIGENCIA'],
|
||||
'fecha_impresion' => $vehicleData['FECHA_IMPRESION'],
|
||||
'qr_hash' => $vehicleData['QR_HASH'],
|
||||
@ -107,16 +107,40 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
|
||||
'owner_id' => $owner->id,
|
||||
]);
|
||||
|
||||
$record = Record::firstOrCreate(
|
||||
['vehicle_id' => $vehicle->id],
|
||||
[
|
||||
'folio' => $folio,
|
||||
'user_id' => Auth::id(),
|
||||
]
|
||||
);
|
||||
// Procesar archivos si existen
|
||||
$uploadedFiles = [];
|
||||
if ($request->hasFile('files')) {
|
||||
$files = $request->file('files');
|
||||
$fileNames = $request->input('names', []);
|
||||
|
||||
foreach ($files as $index => $file) {
|
||||
$customName = $fileNames[$index] ?? "archivo_" . ($index + 1);
|
||||
$customName = str_replace(' ', '_', $customName);
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$fileName = $customName . '_' . time() . '.' . $extension;
|
||||
$path = $file->storeAs('/', $fileName, 'records');
|
||||
$md5 = md5_file($file->getRealPath());
|
||||
|
||||
$fileRecord = File::create([
|
||||
'name' => $customName,
|
||||
'path' => $path,
|
||||
'md5' => $md5,
|
||||
'record_id' => $record->id,
|
||||
]);
|
||||
|
||||
$uploadedFiles[] = [
|
||||
'id' => $fileRecord->id,
|
||||
'name' => $fileRecord->name,
|
||||
'path' => $fileRecord->path,
|
||||
'url' => $fileRecord->url,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Enviar datos a API Repuve Nacional
|
||||
$apiResponse = $this->sendToRepuveNacional($folio, $tagId, $vehicleData);
|
||||
$apiResponse = $this->sendToRepuveNacional($vehicle->numero_serie);
|
||||
$apiResponse["repuve_response"]["folio_ci"] = $record->folio;
|
||||
$apiResponse["repuve_response"]["identificador_ci"] = $tag->tag_number;
|
||||
|
||||
// Procesar respuesta de la API
|
||||
if (isset($apiResponse['has_error']) && $apiResponse['has_error']) {
|
||||
@ -135,7 +159,7 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
|
||||
// guarda error
|
||||
$record->update([
|
||||
'error_id' => $error->id,
|
||||
'api_response' => $apiResponse, // Guarda respuesta con error
|
||||
'api_response' => $apiResponse,
|
||||
'error_occurred_at' => now(),
|
||||
]);
|
||||
|
||||
@ -146,7 +170,7 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
|
||||
return ApiResponse::OK->response([
|
||||
'message' => 'Datos guardados con error. Corrija los datos y vuelva a enviar.',
|
||||
'has_error' => true,
|
||||
'can_retry' => true,
|
||||
'can_update' => true,
|
||||
'error' => [
|
||||
'code' => $error->code,
|
||||
'description' => $error->description,
|
||||
@ -158,6 +182,16 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
|
||||
],
|
||||
'vehicle' => $vehicleData,
|
||||
'owner' => $ownerData,
|
||||
'new_files' => $uploadedFiles,
|
||||
'total_new_files' => count($uploadedFiles),
|
||||
'existing_files' => $record->files->map(function ($file) {
|
||||
return [
|
||||
'id' => $file->id,
|
||||
'name' => $file->name,
|
||||
'path' => $file->path,
|
||||
'url' => $file->url,
|
||||
];
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -168,33 +202,6 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
|
||||
'error_occurred_at' => null,
|
||||
]);
|
||||
|
||||
// Procesar archivos si existen
|
||||
$uploadedFiles = [];
|
||||
if ($request->hasFile('files')) {
|
||||
$files = $request->file('files');
|
||||
$fileNames = $request->input('names', []);
|
||||
|
||||
foreach ($files as $index => $file) {
|
||||
$fileName = uniqid() . '_' . time() . '_' . $file->getClientOriginalName();
|
||||
$path = $file->storeAs('records', $fileName, 'public');
|
||||
$md5 = md5_file($file->getRealPath());
|
||||
|
||||
$fileRecord = File::create([
|
||||
'name' => $fileNames[$index] ?? "Archivo " . ($index + 1),
|
||||
'path' => $path,
|
||||
'md5' => $md5,
|
||||
'record_id' => $record->id,
|
||||
]);
|
||||
|
||||
$uploadedFiles[] = [
|
||||
'id' => $fileRecord->id,
|
||||
'name' => $fileRecord->name,
|
||||
'path' => $fileRecord->path,
|
||||
'url' => $fileRecord->url,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return ApiResponse::OK->response([
|
||||
@ -203,6 +210,8 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
|
||||
'record' => [
|
||||
'id' => $record->id,
|
||||
'folio' => $record->folio,
|
||||
'vehicle_id' => $vehicle->id,
|
||||
'user_id' => $record->user_id,
|
||||
'updated_at' => $record->updated_at->toDateTimeString(),
|
||||
],
|
||||
'vehicle' => [
|
||||
@ -211,6 +220,7 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
|
||||
'numero_serie' => $vehicle->numero_serie,
|
||||
'marca' => $vehicle->marca,
|
||||
'modelo' => $vehicle->modelo,
|
||||
'color' => $vehicle->color,
|
||||
],
|
||||
'owner' => [
|
||||
'id' => $owner->id,
|
||||
@ -220,11 +230,20 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
|
||||
'tag' => [
|
||||
'id' => $tag->id,
|
||||
'folio' => $tag->folio,
|
||||
'tag_number' => $tag->tag_number,
|
||||
'status' => $tag->status,
|
||||
],
|
||||
'new_files' => $uploadedFiles,
|
||||
'total_new_files' => count($uploadedFiles),
|
||||
'existing_files' => $record->files->map(function ($file) {
|
||||
return [
|
||||
'id' => $file->id,
|
||||
'name' => $file->name,
|
||||
'url' => $file->url,
|
||||
];
|
||||
}),
|
||||
'total_files' => $record->files->count() + count($uploadedFiles),
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
@ -241,55 +260,57 @@ 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
|
||||
// Por ahora simulamos con mock igual que InscriptionController
|
||||
|
||||
$hasError = (bool) rand(0, 1);
|
||||
// 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
";
|
||||
|
||||
if ($hasError) {
|
||||
// Obtener un error aleatorio de la tabla errors
|
||||
$error = Error::inRandomOrder()->first();
|
||||
|
||||
if (!$error) {
|
||||
// Si no hay errores en la tabla, retornar error genérico
|
||||
return [
|
||||
'has_error' => true,
|
||||
'error_code' => 'ERR_UNKNOWN',
|
||||
'error_message' => 'No hay errores registrados en el catálogo',
|
||||
'timestamp' => now()->toDateTimeString(),
|
||||
'folio' => $folio,
|
||||
'tag_id' => $tagId,
|
||||
'response_data' => null,
|
||||
// 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;
|
||||
}
|
||||
|
||||
return [
|
||||
'has_error' => true,
|
||||
'error_code' => $error->code,
|
||||
'error_message' => $error->description,
|
||||
'timestamp' => now()->toDateTimeString(),
|
||||
'folio' => $folio,
|
||||
'tag_id' => $tagId,
|
||||
'response_data' => 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,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -13,13 +13,21 @@ public function authorize(): bool
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'folio' => ['required', 'string', 'max:50'],
|
||||
'tag_id' => ['required', 'exists:tags,id'],
|
||||
'record_id' => ['required', 'integer', 'exists:records,id'],
|
||||
'files' => ['nullable', 'array', 'min:1'],
|
||||
'files.*' => ['file', 'mimes:jpeg,png,jpg,pdf', 'max:10240'],
|
||||
'names' => ['nullable', 'array'],
|
||||
'names.*' => ['string', 'max:255'],
|
||||
'replace_files' => ['nullable', 'boolean'],
|
||||
];
|
||||
}
|
||||
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'record_id.required' => 'El id del expediente es requerido',
|
||||
'record_id.exists' => 'El expediente no existe en el sistema',
|
||||
'files.*.mimes' => 'Solo se permiten archivos JPG, PNG o JPEG',
|
||||
'files.*.max' => 'El archivo no debe superar 3MB',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,11 +9,18 @@ class Tag extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
// Constantes de status
|
||||
const STATUS_AVAILABLE = 'available';
|
||||
const STATUS_ASSIGNED = 'assigned';
|
||||
const STATUS_CANCELLED = 'cancelled';
|
||||
const STATUS_LOST = 'lost';
|
||||
|
||||
protected $fillable = [
|
||||
'folio',
|
||||
'tag_number',
|
||||
'vehicle_id',
|
||||
'package_id',
|
||||
'status',
|
||||
];
|
||||
|
||||
public function vehicle()
|
||||
@ -35,4 +42,48 @@ public function scanHistories()
|
||||
{
|
||||
return $this->hasMany(ScanHistory::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marcar tag como asignado a un vehículo
|
||||
*/
|
||||
public function markAsAssigned(int $vehicleId, string $folio): void
|
||||
{
|
||||
$this->update([
|
||||
'vehicle_id' => $vehicleId,
|
||||
'folio' => $folio,
|
||||
'status' => self::STATUS_ASSIGNED,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar si el tag está disponible
|
||||
*/
|
||||
public function isAvailable(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_AVAILABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar si el tag está asignado
|
||||
*/
|
||||
public function isAssigned(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_ASSIGNED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar si el tag está cancelado
|
||||
*/
|
||||
public function isCancelled(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_CANCELLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar si el tag está perdido
|
||||
*/
|
||||
public function isLost(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_LOST;
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
Route::get('expediente/{id}/pdfImagenes', [RecordController::class, 'generatePdfImages']);
|
||||
|
||||
//Rutas de Actualización
|
||||
Route::put('actualizar-vehiculo', [UpdateController::class, 'vehicleUpdate']);
|
||||
Route::post('actualizar', [UpdateController::class, 'vehicleUpdate']);
|
||||
|
||||
// Rutas de cancelación de constancias
|
||||
Route::post('cancelacion/cancelar', [CancellationController::class, 'cancelarConstancia']);
|
||||
@ -58,12 +58,8 @@
|
||||
Route::put('/devices/{id}', [DeviceController::class, 'update']);
|
||||
Route::delete('/devices/{id}', [DeviceController::class, 'destroy']);
|
||||
|
||||
//Ruta de paquetes
|
||||
Route::get('/packages', [PackageController::class, 'index']);
|
||||
Route::post('/packages-create', [PackageController::class, 'store']);
|
||||
Route::put('/packages-update/{id}', [PackageController::class, 'update']);
|
||||
Route::delete('/packages/{id}', [PackageController::class, 'destroy']);
|
||||
|
||||
//Ruta de paquetes CRUD
|
||||
Route::resource('packages', PackageController::class);
|
||||
|
||||
//Ruta CRUD Tags
|
||||
Route::resource('tags', TagsController::class);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user