withCount(['packages']); // Filtro por nombre if ($request->filled('name')) { $query->where('name', 'like', '%' . $request->input('name') . '%'); } if ($request->filled('municipality')) { $query->whereHas('municipality', function ($q) use ($request) { $q->where('name', 'like', '%' . $request->input('municipality') . '%'); }); } // Cargar relaciones para contar $query->withCount(['packages']); // Ordenar $sortOrder = $request->input('sort_order', 'ASC'); $query->orderBy('id', $sortOrder); // Paginación $perPage = $request->input('per_page', 20); $modules = $query->paginate($perPage); return ApiResponse::OK->response([ 'modules' => $modules->map(function ($module) { return [ 'id' => $module->id, 'name' => $module->name, 'responsible' => $module->responsible ? [ 'id' => $module->responsible->id, 'name' => $module->responsible->full_name, 'email' => $module->responsible->email, ] : null, 'municipality' => $module->municipality ? [ 'id' => $module->municipality->id, 'code' => $module->municipality->code, 'name' => $module->municipality->name, ] : null, 'address' => $module->address, 'colony' => $module->colony, 'cp' => $module->cp, 'longitude' => $module->longitude, 'latitude' => $module->latitude, 'status' => $module->status, 'status_text' => $module->status ? 'Activo' : 'Inactivo', 'packages_count' => $module->packages_count ?? 0, 'created_at' => $module->created_at->format('Y-m-d H:i:s'), 'updated_at' => $module->updated_at->format('Y-m-d H:i:s'), ]; }), 'pagination' => [ 'current_page' => $modules->currentPage(), 'total_pages' => $modules->lastPage(), 'per_page' => $modules->perPage(), 'total' => $modules->total(), 'from' => $modules->firstItem(), 'to' => $modules->lastItem(), ], ]); } catch (\Exception $e) { return ApiResponse::INTERNAL_ERROR->response([ 'message' => 'Error al listar módulos', 'error' => $e->getMessage(), ]); } } /** * Crear un nuevo módulo */ public function store(ModuleStoreRequest $request) { try { DB::beginTransaction(); // Crear el módulo $module = Module::create([ 'name' => $request->input('name'), 'responsible_id' => $request->input('responsible_id'), 'municipality_id' => $request->input('municipality_id'), 'address' => $request->input('address'), 'colony' => $request->input('colony'), 'cp' => $request->input('cp'), 'longitude' => $request->input('longitude'), 'latitude' => $request->input('latitude'), 'status' => $request->input('status', true), // Por defecto activo ]); DB::commit(); $module->load('municipality'); return ApiResponse::CREATED->response([ 'message' => 'Módulo creado exitosamente', 'module' => [ 'name' => $module->name, 'responsible_id' => $module->responsible_id, 'municipality' => $module->municipality ? [ 'id' => $module->municipality->id, 'code' => $module->municipality->code, 'name' => $module->municipality->name, ] : null, 'address' => $module->address, 'colony' => $module->colony, 'cp' => $module->cp, 'longitude' => $module->longitude, 'latitude' => $module->latitude, 'status' => $module->status ? 'Activo' : 'Inactivo', 'created_at' => $module->created_at->format('Y-m-d H:i:s'), ], ]); } catch (\Exception $e) { DB::rollBack(); return ApiResponse::INTERNAL_ERROR->response([ 'message' => 'Error al crear módulo', 'error' => $e->getMessage(), ]); } } /** * Actualizar un módulo existente */ public function update(ModuleUpdateRequest $request, int $id) { try { $module = Module::findOrFail($id); DB::beginTransaction(); // Actualizar solo los campos que vienen en el request $module->update($request->validated()); DB::commit(); // Cargar la relación actualizada $module->load('municipality'); return ApiResponse::OK->response([ 'message' => 'Módulo actualizado exitosamente', 'module' => [ 'name' => $module->name, 'responsible_id' => $module->responsible_id, 'municipality' => $module->municipality ? [ 'id' => $module->municipality->id, 'code' => $module->municipality->code, 'name' => $module->municipality->name, ] : null, 'address' => $module->address, 'colony' => $module->colony, 'cp' => $module->cp, 'longitude' => $module->longitude, 'latitude' => $module->latitude, 'status' => $module->status ? 'Activo' : 'Inactivo', 'updated_at' => $module->updated_at->format('Y-m-d H:i:s'), ], ]); } catch (ModelNotFoundException $e) { return ApiResponse::NOT_FOUND->response([ 'message' => 'Módulo no encontrado', ]); } catch (\Exception $e) { DB::rollBack(); return ApiResponse::INTERNAL_ERROR->response([ 'message' => 'Error al actualizar módulo', 'error' => $e->getMessage(), ]); } } /** * Cambiar solo el status de un módulo */ public function toggleStatus(int $id) { try { $module = Module::findOrFail($id); DB::beginTransaction(); // Cambiar el status al valor opuesto $module->update([ 'status' => !$module->status, ]); DB::commit(); return ApiResponse::OK->response([ 'message' => $module->status ? 'Módulo activado exitosamente' : 'Módulo desactivado exitosamente', 'module' => [ 'id' => $module->id, 'name' => $module->name, 'status' => $module->status, 'status_text' => $module->status ? 'Activo' : 'Inactivo', 'updated_at' => $module->updated_at->format('Y-m-d H:i:s'), ], ]); } catch (ModelNotFoundException $e) { return ApiResponse::NOT_FOUND->response([ 'message' => 'Módulo no encontrado', ]); } catch (\Exception $e) { DB::rollBack(); Log::error('Error al cambiar status del módulo: ' . $e->getMessage(), [ 'module_id' => $id, 'trace' => $e->getTraceAsString() ]); return ApiResponse::INTERNAL_ERROR->response([ 'message' => 'Error al cambiar status del módulo', 'error' => $e->getMessage(), ]); } } }