diff --git a/app/Http/Controllers/Repuve/InscriptionController.php b/app/Http/Controllers/Repuve/InscriptionController.php index 867a5c6..7ecf4d5 100644 --- a/app/Http/Controllers/Repuve/InscriptionController.php +++ b/app/Http/Controllers/Repuve/InscriptionController.php @@ -13,9 +13,7 @@ use App\Models\Tag; use App\Models\Error; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Auth; -use Illuminate\Validation\ValidationException; class InscriptionController extends Controller { @@ -357,16 +355,12 @@ public function searchRecord(Request $request) 'required_without_all' => 'Debe proporcionar al menos uno de los siguientes: folio, placa o NIV.' ]); - if (!$request->filled('folio') && !$request->filled('placa') && !$request->filled('niv')) { - return ApiResponse::BAD_REQUEST->response([ - 'message' => 'Debe proporcionar al menos uno de los siguientes parámetros: folio, placa o niv.' - ]); - } - - $query = Record::with(['vehicle.owner', 'vehicle.tag', 'files', 'user', 'error'])->orderBy('created_at', 'desc'); + $query = Record::with(['vehicle.owner', 'vehicle.tag', 'files', 'user', 'error'])->orderBy('id', 'ASC'); if ($request->filled('folio')) { - $query->where('folio', 'LIKE', '%' . $request->input('folio') . '%'); + $query->whereHas('vehicle.tag', function ($q) use ($request) { + $q->where('folio', 'LIKE', '%' . $request->input('folio') . '%'); + }); } elseif ($request->filled('placa')) { $query->whereHas('vehicle', function ($q) use ($request) { $q->where('placa', 'LIKE', '%' . $request->input('placa') . '%'); @@ -486,116 +480,4 @@ private function getOwner(): array 'address' => 'Fracc Pomoca, Calle Armadillo MZ9 LT28', ]; } - - /** - * Listar TAGs filtrados por status - */ - public function listTags(Request $request) - { - try { - $request->validate([ - 'status' => 'required|in:available,assigned,cancelled,lost', - 'per_page' => 'nullable|integer|min:1|max:100', - ], [ - 'status.required' => 'El parámetro status es requerido', - 'status.in' => 'El status debe ser uno de: available, assigned, cancelled, lost', - ]); - - $status = $request->input('status'); - $perPage = $request->input('per_page', 20); - - // Query base - $query = Tag::where('status', $status); - - // Cargar relaciones según el status - if ($status === 'assigned') { - // Si está asignado, cargar vehículo y propietario - $query->with(['vehicle.owner', 'package']); - } else { - // Si no está asignado, solo cargar paquete - $query->with('package'); - } - - // Ordenar por más reciente - $query->orderBy('created_at', 'desc'); - - // Paginar - $tags = $query->paginate($perPage); - - if ($tags->isEmpty()) { - return ApiResponse::NOT_FOUND->response([ - 'message' => 'No se encontraron tags con el status: ' . $status, - 'tags' => [], - 'pagination' => [ - 'current_page' => 1, - 'total_pages' => 0, - 'total' => 0, - 'per_page' => $perPage, - ], - ]); - } - - return ApiResponse::OK->response([ - 'message' => 'Tags encontrados exitosamente', - 'status_filter' => $status, - 'tags' => $tags->map(function ($tag) use ($status) { - $tagData = [ - 'id' => $tag->id, - 'folio' => $tag->folio, - 'status' => $tag->status, - 'package' => $tag->package ? [ - 'id' => $tag->package->id, - 'lot' => $tag->package->lot, - 'box_number' => $tag->package->box_number, - ] : null, - 'created_at' => $tag->created_at->format('Y-m-d H:i:s'), - 'updated_at' => $tag->updated_at->format('Y-m-d H:i:s'), - ]; - - // Si el tag está asignado, agregar información del vehículo - if ($status === 'assigned' && $tag->vehicle) { - $tagData['vehicle'] = [ - 'id' => $tag->vehicle->id, - 'placa' => $tag->vehicle->placa, - 'numero_serie' => $tag->vehicle->numero_serie, - 'marca' => $tag->vehicle->marca, - 'modelo' => $tag->vehicle->modelo, - 'color' => $tag->vehicle->color, - 'owner' => $tag->vehicle->owner ? [ - 'id' => $tag->vehicle->owner->id, - 'full_name' => $tag->vehicle->owner->full_name, - 'rfc' => $tag->vehicle->owner->rfc, - ] : null, - ]; - } else { - $tagData['vehicle'] = null; - } - - return $tagData; - }), - 'pagination' => [ - 'current_page' => $tags->currentPage(), - 'total_pages' => $tags->lastPage(), - 'total' => $tags->total(), - 'per_page' => $tags->perPage(), - 'from' => $tags->firstItem(), - 'to' => $tags->lastItem(), - ], - ]); - } catch (ValidationException $e) { - return ApiResponse::BAD_REQUEST->response([ - 'message' => 'Error de validación', - 'errors' => $e->errors(), - ]); - } catch (\Exception $e) { - Log::error('Error al listar tags: ' . $e->getMessage(), [ - 'trace' => $e->getTraceAsString() - ]); - - return ApiResponse::INTERNAL_ERROR->response([ - 'message' => 'Error al listar tags', - 'error' => $e->getMessage(), - ]); - } - } } diff --git a/app/Http/Controllers/Repuve/TagsController.php b/app/Http/Controllers/Repuve/TagsController.php new file mode 100644 index 0000000..814fe5c --- /dev/null +++ b/app/Http/Controllers/Repuve/TagsController.php @@ -0,0 +1,59 @@ +input('per_page', 15); + $tags = Tag::orderBy('id', 'ASC')->paginate($perPage); + + return ApiResponse::OK->response([ + 'data' => $tags->items(), + 'pagination' => [ + 'total' => $tags->total(), + 'per_page' => $tags->perPage(), + 'current_page' => $tags->currentPage(), + 'last_page' => $tags->lastPage(), + 'from' => $tags->firstItem(), + 'to' => $tags->lastItem(), + ], + ]); + } catch (\Exception $e) { + return ApiResponse::INTERNAL_ERROR->response([ + 'message' => 'Error al obtener la lista de tags.', + 'error' => $e->getMessage(), + ]); + } + } + + 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, + ]); + } +} diff --git a/app/Http/Controllers/TagsController.php b/app/Http/Controllers/TagsController.php deleted file mode 100644 index a9fa651..0000000 --- a/app/Http/Controllers/TagsController.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * @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, - ]); - } -} diff --git a/database/factories/TagFactory.php b/database/factories/TagFactory.php index 3ce621a..fbfa09c 100644 --- a/database/factories/TagFactory.php +++ b/database/factories/TagFactory.php @@ -26,6 +26,7 @@ public function definition(): array return [ 'folio' => $this->generateFolio(), + 'tag_number' => strtoupper(fake()->bothify('TAG-########')), 'vehicle_id' => fake()->boolean(60) ? Vehicle::factory() : null, // 60% asignados 'package_id' => Package::factory(), 'status' => fake()->randomElement(array_combine($statuses, $weights)) ?? 'available', @@ -39,9 +40,9 @@ private function generateFolio(): string { $year = fake()->numberBetween(2020, 2025); $series = strtoupper(fake()->bothify('??')); - $number = fake()->unique()->numerify('####################'); + $number = fake()->unique()->numerify('##########'); - return 'TAG-' . $year . '-' . $series . '-' . $number; + return $year . '-' . $series . '-' . $number; } /** diff --git a/docker-compose.yml b/docker-compose.yml index 2b05416..1c92cc5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -66,6 +66,8 @@ services: mem_limit: 400m volumes: + nginx_data: + driver: local mysql_data: driver: local diff --git a/routes/api.php b/routes/api.php index 16ae42d..061bf33 100644 --- a/routes/api.php +++ b/routes/api.php @@ -8,7 +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; +use App\Http\Controllers\Repuve\TagsController; /** * Rutas del núcleo de la aplicación. @@ -28,8 +28,7 @@ Route::middleware('auth:api')->group(function() { // Rutas de inscripción de vehículos Route::post('inscripcion', [InscriptionController::class, 'vehicleInscription']); - Route::post('consulta', [InscriptionController::class, 'searchRecord']); - Route::post('consulta-tag', [InscriptionController::class, 'listTags']); + Route::get('consulta', [InscriptionController::class, 'searchRecord']); // Rutas de expedientes y documentos Route::get('expediente/{id}/pdf', [RecordController::class, 'generatePdf']); @@ -58,7 +57,7 @@ Route::put('/devices/{id}', [DeviceController::class, 'update']); Route::delete('/devices/{id}', [DeviceController::class, 'destroy']); - //Ruta de tags + //Ruta de paquetes Route::get('/packages', [PackageController::class, 'index']); Route::post('/packages-create', [PackageController::class, 'store']); Route::put('/packages-update/{id}', [PackageController::class, 'update']);