feat: Agregar validaciones de longitud para 'niv' y 'placa' en el formulario PDF, array de tags

This commit is contained in:
Juan Felipe Zapata Moreno 2025-11-28 17:01:54 -06:00
parent 2d060f9909
commit d8ec98cd7c
8 changed files with 181 additions and 3 deletions

View File

@ -252,7 +252,7 @@ private function prepareExcelData($logs)
$newTag->folio ?? 'N/A',
$newTag->tag_number ?? 'N/A',
$log->created_at->format('d/m/Y'),
$log->cancellation_observations ?? 'CONSTANCIA DAÑADA',
$log->cancellation_observations ?? 'CONSTANCIA SUSTITUIDA',
];
$no++;

View File

@ -187,9 +187,9 @@ public function generatePdfForm(Request $request)
'marca' => 'required|string',
'linea' => 'required|string',
'modelo' => 'required|string',
'niv' => 'required|string',
'niv' => 'required|string|max:17',
'numero_motor' => 'required|string',
'placa' => 'required|string',
'placa' => 'required|string|max:7',
'folio' => 'required|string',
'telefono' => 'nullable|string',
]);

View File

@ -3,8 +3,11 @@
namespace App\Http\Controllers\Repuve;
use App\Http\Controllers\Controller;
use App\Models\CatalogTagStatus;
use Illuminate\Http\Request;
use App\Models\Tag;
use Exception;
use Illuminate\Support\Facades\DB;
use Notsoweb\ApiResponse\Enums\ApiResponse;
class TagsController extends Controller
@ -73,4 +76,139 @@ public function destroy(Tag $tag)
]);
}
}
/* -------------------------------------------------------------------------- */
public function tagStore(Request $request)
{
try {
$request->validate([
'package_id' => 'required|integer|exists:packages,id',
'tags' => 'required|array',
'tags.*.folio' => 'required|string|max:8',
'tags.*.tag_number' => 'required|string|max:32',
]);
DB::beginTransaction();
$statusAvailable = CatalogTagStatus::where('name', Tag::STATUS_AVAILABLE)->first();
if (!$statusAvailable) {
return ApiResponse::NOT_FOUND->response([
'message' => 'El tag no tiene estado disponible.',
]);
}
$createdTags = [];
$errors = [];
foreach ($request->tags as $index => $tagData) {
try {
$tag = Tag::create([
'folio' => $tagData['folio'],
'tag_number' => $tagData['tag_number'],
'package_id' => $request->package_id,
'status_id' => $statusAvailable->id,
'vehicle_id' => null,
'module_id' => null,
]);
$createdTags[] = $tag;
} catch (Exception $e) {
$errors[] = [
'index' => $index,
'folio' => $tagData['folio'],
'tag_number' => $tagData['tag_number'],
'error' => $e->getMessage(),
];
}
}
if (!empty($errors)) {
DB::rollback();
return ApiResponse::BAD_REQUEST->response([
'message' => 'Error al importar tags.',
'errors' => $errors,
'exitosos' => $createdTags,
'fallidos' => count($errors),
]);
}
DB::commit();
return ApiResponse::CREATED->response([
'message' => 'Tags importados correctamente.',
'tags' => $createdTags,
'total' => count($createdTags),
'package_id' => $request->package_id,
]);
} catch (Exception $e) {
DB::rollback();
return ApiResponse::INTERNAL_ERROR->response([
'message' => 'Error al importar tags.',
'error' => $e->getMessage(),
]);
}
}
public function assignToModule(Request $request)
{
try {
$request->validate([
'module_id' => 'required|exists:modules,id',
'tag_ids' => 'required_without_all:package_id,from_tag_number,to_tag_number|array|min:1',
'tag_ids.*' => 'exists:tags,id',
'package_id' => 'required_with:from_tag_number,to_tag_number|exists:packages,id',
'from_tag_number' => 'required_with:package_id|string',
'to_tag_number' => 'required_with:package_id|string',
]);
DB::beginTransaction();
// Determinar qué tags asignar
if ($request->has('tag_ids')) {
// Asignación por IDs específicos
$tags = Tag::with('status')->whereIn('id', $request->tag_ids)->get();
} else {
// Asignación por rango
$tags = Tag::where('package_id', $request->package_id)
->where('tag_number', '>=', $request->from_tag_number)
->where('tag_number', '<=', $request->to_tag_number)
->get();
}
if ($tags->isEmpty()) {
return ApiResponse::NOT_FOUND->response([
'message' => 'No se encontraron tags con los criterios especificados.',
]);
}
// Validar que no estén asignados a vehículos
$unavailableTags = $tags->filter(fn($tag) => $tag->vehicle_id !== null);
if ($unavailableTags->isNotEmpty()) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'Algunos tags ya están asignados a vehículos.',
'unavailable_tags' => $unavailableTags->pluck('tag_number')->toArray(),
]);
}
// Asignar módulo
$tagIds = $tags->pluck('id')->toArray();
Tag::whereIn('id', $tagIds)->update(['module_id' => $request->module_id]);
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(),
]);
} catch (Exception $e) {
DB::rollback();
return ApiResponse::INTERNAL_ERROR->response([
'message' => 'Error al asignar tags al módulo.',
'error' => $e->getMessage(),
]);
}
}
}

View File

@ -35,6 +35,10 @@ public function municipality()
return $this->belongsTo(Municipality::class);
}
public function tags(){
return $this->hasMany(Tag::class, 'module_id');
}
public function devices()
{
return $this->belongsTo(Device::class, 'device_module')

View File

@ -38,6 +38,10 @@ public function status()
return $this->belongsTo(CatalogTagStatus::class, 'status_id');
}
public function module(){
return $this->belongsTo(Module::class, 'module_id');
}
public function vehicleTagLogs()
{
return $this->hasMany(VehicleTagLog::class);

View File

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('tags', function (Blueprint $table) {
$table->unsignedBigInteger('module_id')->nullable()->after('package_id');
$table->foreign('module_id')->references('id')->on('modules')->onDelete('set null');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('tags', function (Blueprint $table) {
$table->dropForeign(['module_id']);
$table->dropColumn('module_id');
});
}
};

View File

View File

@ -70,6 +70,8 @@
//Ruta Tags
Route::resource('tags', TagsController::class);
Route::post('tags/import', [TagsController::class, 'tagStore']);
Route::post('tags/assign-to-module', [TagsController::class, 'assignToModule']);
//Rutas de nombres de archivos en catálogo
Route::resource('catalog-name-imgs', CatalogNameImgController::class);