24/04/2013

ADSL Pepephone. Paso 3: Solución al problema del "número administrativo"

Después del abrupto final de mi primer intento de portabilidad de mi ADSL a +Pepephone, gracias a +Fander Awensome he encontrado la solución al problema, o al menos eso parece. El caso es que Orange (como al parecer Jazztel y Ono) no facilita (porque no quiere) a Pepephone el número administrativo identificativo de la línea que suministra el servicio de ADSL de manera que los usuarios, como es mi caso, que no tenemos una dirección totalmente estándar (calle, número, piso, puerta, etc.) y que al parecer somos muchos, nos quedamos a la espera de que el técnico de Telefónica sea capaz de localizar nuestra línea para realizar el cambio de suministrador. Ésto no sería ningún problema si esa línea estuviera asociada a un número de teléfono, ya que con ésta referencia se ve que pueden realizar la localización del dichoso cable, pero como el ADSL de Pepephone se suministra sin servicio de teléfono nuestra línea queda en el limbo. El caso es que ahí se acaba el camino para un 30% de usuarios solicitantes. Yo estaba en esas, y mirando ofertas de ADSL de otras compañías, cuando un comentario de +Fander Awensome en el blog me advierte de que llame al servicio de atención al cliente de Orange, que a él le pasaba igual con Jazztel y con llamar le facilitaron el número administrativo al momento. Un poco escéptico (no por Fander sino por Orange) así lo he hecho, he llamado a Orange y sorprendentemente en cinco minutos he obtenido el número administrativo que identifica mi línea, que ahora tendré que hacer llegar a Pepephone para tratar de formalizar la portabilidad (Nota para interesados: según me adelantó +Fander Awensome, y yo he confirmado después, el famoso número administrativo debe tener 14 dígitos, coincidiendo los 2 primeros con el comienzo del código postal correspondiente al domicilio al que da servicio la línea). 

Lo realmente chocante del tema es por qué +Pepephone  no nos advierte de ésta solución tan sencilla a los interesados en realizar la portabilidad y lo que aún me tiene más descolocado ha sido la atención al cliente de Orange. Nada de comerciales tratando de retenerme, nada de ir pasándome de un técnico a otro para marearme. Y eso que les he dicho claramente para qué quería el número administrativo. De todas formas no creo que tarden en llamarme para ofrecerme alguna promoción con permanencia.

En cualquier caso todo parece indicar que aún hay posibilidad de probar el ADSL de Pepephone así que allá vamos.


El proceso completo:
Paso 3: Solución al problema del número administrativo
Paso 4 y Final: Configuración del router

15/04/2013

AÑADIR BIBLIOTECAS EN NETBEANS


Las bibliotecas son uno de los recursos más importantes a la hora de ahorrar trabajo durante el desarrollo de aplicaciones. Es completamente habitual echar mano de éste tipo de elementos para evitarnos en lo posible escribir código o para automatizar ciertos procesos. Como se nos dice en clase: si la rueda ya existe usémosla en lugar de perder tiempo volviendo a inventarla.
Las bibliotecas pueden ser de código libre o bien de pago. Existen verdaderas comunidades de open source de las que pueden obtenerse multitud de bibliotecas y al mismo tiempo existen empresas que ofrecen bibliotecas que pueden obtenerse bajo pago como un producto más del mercado.
En nuestro caso  vamos a instalar la biblioteca libre Commons BeanUtils (que estamos utilizamos en nuestros proyectos con persistencia de datos en ficheros xml para la automatización de una serie de asignaciones de enlaces entre una interfaz gráfica y el xml pero a través además de una entidad).
Lo primero que debemos hacer será elegir una carpeta en nuestro ordenador destinada a almacenar todas las bibliotecas que vayamos a instalar para su uso con NetBeans. Una vez tengamos clara la ubicación descargamos la biblioteca de la web de Commons BeanUtils (http://commons.apache.org/proper/commons-beanutils/download_beanutils.cgi) y la descomprimimos en la carpeta que hemos decidido destinar a las bibliotecas. Una vez hecho esto abrimos NetBeans y acudimos al menú Tools/Ant Libraries:


 Nos aparece la siguiente ventana, en la que seleccionamos New Library:


Se abre otra ventana en la que damos nombre a la nueva librería que vamos a crear, en nuestro caso le daremos como nombre Commons BeanUtils, aunque podríamos poner cualquier otro, damos OK:


Hemos vuelto a la ventana de gestión de bibliotecas y debe aparecernos la biblioteca recién creada en el listado de la izquierda. La seleccionamos y procedemos a indicarle a NetBeans dónde se encuentran los archivos correspondientes a dicha biblioteca para poder hacer uso de ella. En concreto deberemos ir completando cada una de las tres partes, representadas por las pestañas Classpath (para el .jar principal de la biblioteca), Sources (para el .jar de las fuentes) y Javadoc (para la documentación de la biblioteca). Con la primera pestaña Classpath seleccionada presionamos Add JAR/Folder...:


Buscamos el .jar de la biblioteca en la carpeta descomprimida y se lo asignamos:


Repetimos la operación para las otras dos pestañas (Sources y Javadoc):





Finalmente presionamos OK y ya tendremos creada y referenciada (y por tanto lista para su uso) la nueva biblioteca.



Nota: Para éste ejemplo de instalación de una biblioteca esto ya no es necesario pero de cara al uso de Commons BeanUtils se ha comprobado en la documentación de Apache Commons que es necesaria la instalación también de la librería Commons-Logging (http://commons.apache.org/proper/commons-logging/download_logging.cgi) así que procederemos del mismo modo con la descarga, la descompresión, la creación de la nueva librería y el enlazado (especificación de la ruta) para cada una de las tres partes (classpath, sources y javadoc).

13/04/2013

EL OBJETO “VISTA” EN UNA BASE DE DATOS


Apartado de "Vistas" tratado en la asignatura de Base de Datos del Ciclo Superior de Diseño de Aplicaciones Web impartido en el IES Camp de Morvedre.

INTRODUCCIÓN


El esquema de una Base de Datos está formado por diversos objetos, entre los que, a nivel primario, encontramos las tablas, las secuencias (al menos en Oracle) y también las vistas.
Las vistas son objetos que no almacenan datos y que son definiciones basadas en una consulta, es decir, las vistas proporcionarán una visión, modelada mediante una consulta, de un subconjunto de componentes de una o varias tablas.
Para poder trabajar con vistas lo primero que debemos tener en cuenta es si nuestro usuario tiene los privilegios necesarios. Si no es así lo primero que deberemos hacer es otorgarnos dichos privilegios. En nuestro caso estamos trabajando en una base de datos creada con Oracle y realizamos las tareas de gestión a través del usuario scott. Por tanto para dotar a scott de privilegios para trabajar con vistas dentro de la base de datos deberemos entrar como usuarios administradores, con la cuenta system, y generar dichos privilegios. Desde un programa gestor como puede ser SQLPlus (que se instala junto con Oracle) entraremos como usuario system, al cual le dimos contraseña durante la instalación de Oracle y por tanto la conocemos o bien si ya estábamos en SQLPlus cambiaremos de usuario mediante CONNECT SYSTEM/Gladiador12 (Gladiador12 es la contraseña que se le dio en su día a system). System es, junto con sys, uno de los dos usuarios administradores que se generan automáticamente con Oracle. Este tipo de usuarios, por su nivel jerárquico, únicamente deben utilizarse para tareas de gestión administrativa de la base de datos (como pueda ser en este caso la concesión de privilegios), tratando en la medida de lo posible de evitar su uso para el resto de tareas. Bien, desde SQLPlus y ya como usuario system identificado tecleamos la siguiente sentencia:

GRANT CREATE VIEW TO SCOTT;




Si vamos a continuar usando SQLPlus cambiamos de usuario con la instrucción:

CONNECT SCOTT/TIGRE;(Tigre es la contraseña que tiene scott en nuestro sistema).

En nuestro caso vamos a usar SQLDeveloper (también se instala junto con Oracle) que es un gestor mucho más amigable (por la interfaz gráfica de usuario) que SQLPlus (que solo dispone de modo consola). Por tanto salimos de SQLPlus y lanzamos SQLDeveloper.

Ahora necesitamos un esquema relacional para poder realizar ejemplos básicos con las vistas. Para ello partiremos de las siguientes tablas e inserts:


CREATE TABLE clientes(
dni CHAR(10),
nombre VARCHAR(20) NOT NULL,
constraint pk_clientes PRIMARY KEY (dni)
);

CREATE TABLE cuotas (
num_periodo CHAR(1) NOT NULL,
potencia CHAR(1) NOT NULL,
precio NUMBER NOT NULL,
constraint pk_cuotas PRIMARY KEY (num_periodo,potencia),
constraint c_cuotas_opcionPotencia CHECK (potencia IN ('0','1','2','3'))
);

CREATE TABLE contadores(
id_contador CHAR(2),
dni_titular CHAR(10),
potencia_contratada CHAR(1),
dir_suministro VARCHAR(20) NOT NULL,
dir_facturacion VARCHAR(20) NOT NULL,
constraint pk_contadores PRIMARY KEY (id_contador),
constraint fk_contadores_dniTitular FOREIGN KEY (dni_titular) REFERENCES clientes (dni)
);

CREATE TABLE facturas(
num_periodo CHAR(1) NOT NULL,
contador CHAR(2),
num_factura CHAR(10),
lectura NUMBER NOT NULL,
pagado CHAR(1),
fecha_lectura DATE,
constraint pk_facturas PRIMARY KEY (num_periodo,contador),
constraint c_facturas_RangoPago CHECK (pagado IN (null,'s','S','n','N'))
);  

Y los inserts:
INSERT INTO clientes VALUES ('11','Pepe');
INSERT INTO clientes VALUES ('22','Luis');
INSERT INTO clientes VALUES ('33','Rosa');

INSERT INTO cuotas VALUES ('1','0','0,15');
INSERT INTO cuotas VALUES ('1','1','20');
INSERT INTO cuotas VALUES ('1','2','25');
INSERT INTO cuotas VALUES ('1','3','30');
INSERT INTO cuotas VALUES ('2','0','0,17');
INSERT INTO cuotas VALUES ('2','1','21');
INSERT INTO cuotas VALUES ('2','2','26');
INSERT INTO cuotas VALUES ('2','3','30');
INSERT INTO cuotas VALUES ('3','0','0,17');
INSERT INTO cuotas VALUES ('3','1','21');
INSERT INTO cuotas VALUES ('3','2','26');
INSERT INTO cuotas VALUES ('3','3','30');

INSERT INTO contadores VALUES ('A1','11','1','c/Mayor','c/Mayor');
INSERT INTO contadores VALUES ('A2','11','2','Poligono Industrial','c/ Mayor');
INSERT INTO contadores VALUES ('A3','22','2','c/tintorerias','c/Barcelona');

INSERT INTO facturas VALUES ('0','A1','---','0',null,null);
INSERT INTO facturas VALUES ('0','A2','---','0',null,null);
INSERT INTO facturas VALUES ('0','A3','---','0',null,null);
INSERT INTO facturas VALUES ('1','A1','2013-001','200','n','28/02/13');
INSERT INTO facturas VALUES ('1','A2','2013-002','350','n','28/02/13');
INSERT INTO facturas VALUES ('1','A3','2013-003','275','n','28/02/13');
INSERT INTO facturas VALUES ('2','A1','2013-004','500','n','30/04/13');
INSERT INTO facturas VALUES ('2','A2','2013-005','565','n','30/04/13');
INSERT INTO facturas VALUES ('2','A3','2013-006','700','n','30/04/13');
INSERT INTO facturas VALUES ('3','A1','2013-007','835','n','30/06/13');
INSERT INTO facturas VALUES ('3','A2','2013-008','865','n','30/06/13');
INSERT INTO facturas VALUES ('3','A3','2013-009','900','n','30/06/13');

commit;



CREACIÓN, VISUALIZACIÓN Y BORRADO DE VISTAS


Una vez obtenidos los privilegios necesarios vamos a crear una primera vista mediante la instrucción:  

CREATE VIEW vista_de_prueba AS SELECT dni,nombre FROM clientes;

Si desplegamos el elemento Vistas vemos que efectivamente aparece la vista que acabamos de crear.






Si ahora comprobamos la consulta que acabamos de usar:

SELECT dni,nombre FROM clientes;

Obtenemos:



Ahora visualizamos la vista:

SELECT * FROM vista_de_prueba;










Y comprobamos cómo el resultado es el mismo. A través de la vista creada estamos viendo una parte de la tabla clientes, concretamente las columnas dni y nombre, y solo esas columnas, no la tabla entera.
Podemos borrar la vista con el comando:

DROP VIEW vista_de_prueba;



CONSULTA COMBINADA CON UNA VISTA Y UNA TABLA


Las vistas, como objetos que son, permiten ser relacionadas con otros objetos como son las tablas. Vamos a ver la lista de clientes de nuestro esquema, para lo que recurrimos de paso a la vista recientemente creada:

 SELECT * FROM vista_de_prueba;

Y vamos a hacer una consulta para ver qué clientes tienen dado de alta un contador:

SELECT nombre FROM contadores,clientes where clientes.dni=contadores.dni_titular;













Por tanto, de los tres clientes que veíamos anteriormente que existen, hay uno que no es titular actualmente de un contador.
Ahora, igual que hemos hecho con la consulta, podemos cruzar la vista vista_de_prueba con la tabla contadores:

SELECT nombre FROM vista_de_prueba,contadores WHERE vista_de_prueba.dni= contadores.dni_titular;

Obteniendo el mismo resultado:













Por tanto las vistas funcionan como un objeto semejante a una tabla, permitiendo realizar combinaciones. Como ya hemos mencionado al principio las vistas nos dan una visión sesgada de la tabla o tablas que subyacen tras la consulta. Nuevamente insistir en que las vistas no almacenan datos y que tras ellas lo que ocurre es que se procesa una consulta que da como resultado una visión parcial de una o varias tablas.



REALIZACIÓN DE INSERTS A TRAVÉS DE UNA VISTA


Cuando la vista se basa sólo en la consulta sobre una tabla es posible realizar inserts en esa tabla a través de la vista. No obstante si la vista combina varias tablas la inserción de datos a través de ella no se contempla.
Los datos insertados deben, eso sí, cumplir con las restricciones de la tabla de destino. Vamos a realizar un insert en la tabla clientes a través de la vista vista_de_prueba:

INSERT INTO vista_de_prueba VALUES ('112','Miguelin');

Ahora comprobamos:

SELECT * FROM clientes;












Vemos como efectivamente hemos introducido una nueva fila en la tabla clientes a través de la vista.




USO DE UNA VISTA COMO RESTRICCIÓN


Podemos definir restricciones para los inserts que se realicen a través de una vista. Vamos a crear una nueva vista y le vamos a aplicar una restricción. Vamos a hacer que los nuevos clientes a insertar deban llamarse ‘Samuel’ para ser “aceptados” en la tabla:

CREATE VIEW vista_restriccion AS SELECT dni,nombre FROM clientes
WHERE nombre='Samuel' WITH CHECK OPTION;

Como no hay clientes llamados ‘Samuel’ esta vista está vacía, pero si ahora intentamos realizar este insert:

INSERT INTO vista_restriccion VALUES ('113','Roberto');

Salta la restricción:














El with check option es un comando que hace que la cláusula where actúe como filtro no solo de salida sino también de entrada.
Si tratamos ahora de realizar el siguiente insert vemos como no tenemos ningún problema:

INSERT INTO vista_restriccion VALUES ('113','Samuel');

Comprobamos la tabla clientes y vemos como efectivamente ahí está el nuevo dato:

SELECT * FROM clientes;
















Si lo que quisiéramos fuera modificar una vista ya creada recurriremos al comando:

CREATE OR REPLACE VIEW nombre_de_la_vista AS SELECT....etc.,etc...

Recapitulando nuevamente: las vistas proporcionan un subconjunto de datos de una o varias tablas moldeado en combinación de columnas/filas a nuestro gusto mediante una consulta con select.
Existen además del with check option otros comandos de interés para las vistas como es el caso de with read only, mediante el cual restringimos la introducción de de datos a través de la vista a la que se le aplica permitiendo únicamente el acceso en modo lectura.




VISTA QUE COMBINA VARIAS TABLAS


Si tenemos una consulta como ésta:

SELECT nombre, id_contador as contador, contadores.dir_facturacion,
actual.fecha_lectura,
(actual.lectura- anterior.lectura) as consumo,
((actual.lectura-anterior.lectura)*cuotas.precio) as importe_variable
FROM clientes, contadores, facturas anterior, facturas actual, cuotas
where clientes.dni= contadores.dni_titular
and contadores.id_contador= actual.contador
and anterior.contador=actual.contador
and anterior.num_periodo+1=actual.num_periodo
and actual.num_periodo=2
and cuotas.num_periodo= actual.num_periodo
and cuotas.potencia=0
order by actual.num_periodo, actual.contador;

que nos devuelve los recibos de todos los clientes para el perido 2: 




podríamos "encapsular" dicha consulta a través de una vista de manera que fuéramos creando vistas para cada uno de los periodos de facturación. Vamos a crear una vista mediante la consulta del periodo 2 de la facturación del modelo tipo Iberdrola aportado al principio del post. Creamos la vista, copiamos la consulta y le quitamos la cláusula que indica el periodo para añadírsela al final en modo "and" (ya que ya tenemos
en uso el Where con "clientes.dni=contadores.dni_titular").

CREATE VIEW v_recibos_periodo_2 AS
SELECT nombre, id_contador as contador, contadores.dir_facturacion,
actual.fecha_lectura,
(actual.lectura- anterior.lectura) as consumo,
((actual.lectura-anterior.lectura)*cuotas.precio) as importe_variable
FROM clientes, contadores, facturas anterior, facturas actual, cuotas
where clientes.dni= contadores.dni_titular
and contadores.id_contador= actual.contador
and anterior.contador=actual.contador
and anterior.num_periodo+1=actual.num_periodo
and cuotas.num_periodo=actual.num_periodo
and cuotas.potencia=0 
and actual.num_periodo=2;


Ahora, con una sola línea de código obtendremos el mismo resultado que con toda la consulta anterior:

select * from v_recibos_periodo_2;

Igualmente podríamos crear una nueva tabla en lugar de una vista, pero es una tabla que no tiene restricciones, no se actualiza con la actualización de las tablas origen y ocupa espacio aunque una select contra una tabla es mucho más eficiente que una select contra una vista (que tiene que elaborar todo ese lote de datos. Éste tipo de recursos se usan en caso de querer exportar los datos de una organización a otra o de un gestor a otro (de un sistema a otro, de un servidor a otro). Ejemplo Iberdrola subcontratando la impresión, ensobrado y envío por correo de las facturas de sus millones de clientes.

CREATE TABLE t_recibos_periodo_2 AS
SELECT nombre, id_contador as contador, contadores.dir_facturacion,
actual.fecha_lectura,
(actual.lectura- anterior.lectura) as consumo,
((actual.lectura-anterior.lectura)*cuotas.precio) as importe_variable
FROM clientes, contadores, facturas anterior, facturas actual, cuotas
where clientes.dni= contadores.dni_titular
and contadores.id_contador= actual.contador
and anterior.contador=actual.contador
and anterior.num_periodo+1=actual.num_periodo
and cuotas.num_periodo=actual.num_periodo
and cuotas.potencia=0 
and actual.num_periodo=2;

Para ver el resultado:

SELECT * from t_recibos_periodo_2;





USO PRINCIPAL DE LAS VISTAS


Las vistas pueden tener múltiples usos pero esencialmente el ámbito de utilidad es el de la seguridad, es decir, el de la restricción de los accesos de cada usuario de la base de datos al resto de “parcelas” que la conforman. Si pensamos, por ejemplo, en el ámbito de un ayuntamiento, en el que se instala una base de datos para la gestión del municipio y en la que existen distintas parcelas dirigidas por distintos usuarios (padrón, tráfico, rústica, urbana, etc.) aparece la problemática de que debe restringirse el acceso de cada usuario al resto de parcelas pero a la vez debe evitarse la redundancia de datos y la descentralización. Es decir, no debe permitirse que el usuario que se encarga de la gestión de la parte de las fincas rústicas pueda entrar en tráfico y realizar cambios en las tablas de esa parcela (imaginemos a Pepe Pérez entrando desde rústica y quitándole una multa de tráfico a su primo Paquito). Pero al mismo tiempo cada parcela debe tener acceso a ciertos datos que el resto de parcelas poseen para evitar la redundancia de éstos y la mala eficiencia de una base de datos descentralizada a la hora por ejemplo de las actualizaciones de datos (Pepe Pérez, de rústica, sí deberá poder tener acceso al listado de habitantes censados en el municipio que figura en las tablas del usuario que gestiona padrón, por ejemplo. O cuando se realice el nuevo censo esos datos actualizados deben entrara en el menor número de tablas posibles y que éstas estén compartidas por todos los usuarios).
Es aquí donde entran en juego las vistas. Mediante ellas se establecen una serie de filtros y una serie de restricciones de unas partes a otras para permitir el control en los accesos de cada usuario a cada tabla (o solo al conjunto de datos de interés de una o unas tablas determinadas) ya sea además restringiendo la inserción de nuevos datos o funcionando en modo sólo lectura con el with read only si además se quiere bloquear la adición de inserts

05/04/2013

Solución para problema de encendido del LG Nexus 4

Como casi usuario de un Nexus 4 (el desastre de su distribución me empujó, como a tantos otros, a decidirme por otro teléfono mientras perdía la paciencia ante la falta de noticias y de seriedad de Google/LG) me ha parecido interesante hacerme eco de este problema con el encendido del terminal  (y su correspondiente solución) que vi el otro día a través de Twitter vía @stephaniefalla:












No tengo ni idea de si es un problema extendido o es un caso aislado, ni si la solución tiene algo de base científica pero por si a alguien puede servirle aquí queda plasmado.

04/04/2013

ADSL Pepephone. Paso 2: Problema con Orange y el "número administrativo"

Tras solcicitar la portabilidad al ADSL Pepephone desde mi actual proveedor (Orange) escribo estas líneas como final abrupto y prematuro de lo que comenzó siendo el relato de un "viaje" a una nueva visión del servicio de ADSL en España, sin número de teléfono asociado y sin falsos regalos de routers, etc. A la vez se trataba de un experimento para comprobar si un usuario sin conocimientos previos de configuración o administración de redes podía adaptarse a la propuesta de Pepephone (aportación y configuración del router por cuenta del cliente), hasta dónde llegaba el asesoramiento técnico que Pepephone facilitaba para este tipo de clientes y por tanto si esta oferta de ADSL era recomendable para cualquier usuario o solo para los considerados como "avanzados" y ver si una compañía pequeña y admirable como Pepephone podía seguir manteniendo su calidad en el servicio también con algo tan problemático como es el ADSL.

Escribo esta entrada asombrado aún, y con cabreo en fase creciente, por el email que acabo de recibir de Pepephone y que muestro a continuación. Resumiendo: Quería pasarme al ADSL de Pepephone, pero Orange me tiene "secuestrado".

Pues sí, puede parecer mentira pero es así, existen casos en los que aunque como cliente, y por cobertura, tengas derecho a recibir el servicio ADSL de Pepephone es tu compañía actual la que no piensa dejarte "escapar" aprovechando una especie de vacío legal que les otorga a ellos la última palabra. Si Orange no facilita a Pepephone ese "número administrativo", que Telefónica a su vez no encuentra (qué país!), y que es necesario para dar de alta un servicio sin número de teléfono asociado, no hay nada que hacer. Y claro, Orange no es Pepephone y no van a querer encontrarlo. Me extrañaba muchísimo no haber recibido aún contraofertas desde Orange, ahora entiendo el motivo.

Así que con todo mi pesar he de renunciar al ADSL de Pepephone, al menos por el momento, pero no así a quedarme en Orange, compañía que lo único que ha generado en este humilde cliente es una sensación de rechazo con la que, lejos de retenerme, como es su intención con esta treta, ha conseguido ponerme al borde de dejarlos sí o sí por otra compañía. Comienzo a mirar ofertas de ADSL hoy mismo y Orange parte la última de la fila y con el goal average en contra, aunque el resto de compañías son también para verlas.

Orange me tiene secuestrado en el grupo de compañías "grandes" y no me deja escapar.


El proceso completo:
Paso 2: Problema con Orange y el número administrativo