Y ahora, ¿qué?

Me encuentro dando los últimos retoques a la v3 del SOSNext, un programa de gestión de incidencias que ha crecido tanto que vamos a tener que cambiarle el nombre, porque el módulo de incidencias es ya sólo una pequeña parte del total.

En fin, que estos últimos tres meses le he hecho la cirugía mayor al programa, pasándolo de VB2010 Express a VS2012 (la versión Express ya no daba más), haciéndolo más modular (aumentando la complejidad un montón, de paso), adaptando algunos controles bajados de internet, cambiando algunas cosas de la BDD, metiéndolo todo en Team Foundation Server (Express) para coordinarme con un compañero… Un jaleo enorme.

Y ahora, cuando estoy dando los últimos retoques, un usercontrol que no ha sufrido modificaciones (ni una), que no lo he tocado ni abierto ni cambiado de proyecto o espacio de nombres, que ha pasado desapercibido y no ha recibido ni una mirada de atención, ese cabronazo, digo, ha decidido:

1) Cambiar el alto de las etiquetas y cajas de texto, cortando las letras tipo p, q…

2) Un ListBox con funciones de búsqueda de cadenas (que funciona bien en el resto de controles donde se usa) decide, de paso, funcionar como un ListBox normal (sólo primera letra).

Creo que le he contagiado la gripe, porque otra explicación no se me ocurre.

Compañías telefónicas

—Oiga, me mudo y quiero cambiar la línea a mi nuevo domicilio.

—Sin problema. Son tropecientos leuros.

—Disculpe, pero eso es lo que pagué por el alta. No quiero un alta nueva, sólo un cambio de domicilio.

—Da igual, son tropecientos leuros. Lo pone en el contrato: si no sabe bailar la jota aragonesa a la pata coja y haciendo el pino, son tropecientos leuros.

—Perdone, pero en mi contrato no pone nada de eso.

—Es que se aplica a los contratos yuxtapuestos.

—Pero es que el mío es pluscuamperfecto.

—Da igual, son tropocientos leuros.

—Quiero poner una reclamación.

—Da igual, son tropecientos leuros.

—Váyase a paseo y dé de baja la línea, que me voy a la competencia.

—Pero, hombre. No sea así, con lo bien que lo tratamos. Mire, le diré lo que vamos a hacer: le haremos el cambio de domicilio gratis, sin cobrarle nada. Para que vea que le apreciamos.

Hola, si lo hacemos mal os las apañáis vosotros

Tengo un amigo que trabaja en un distribuidor de cierta compañía de telefonía. Oírle hablar de los programas informáticos que usan para hacer su trabajo me demuestra que no sólo es el trato al cliente lo que falla en las empresas de telefonía y que la externalización a bajo coste de los servicios incluye algunas áreas que debieran ser básicas para el funcionamiento de la empresa. La última que me ha contado va de un problema para dar de alta un servicio a un cliente. Un problema que, tras pruebas varias y la intervención del soporte técnico que, como distribuidor, tiene a su disposición, tiene todas y cada una de las papeletas de ser un bug del programa. Así que se abre una incidencia a los responsables del susodicho programa.

Que empiezan a marear la perdiz. Lo suficiente como para que la promoción caduque y se retire dicha opción del programa. Dado lo que sé del programa, me imagino una subcontrata con becarios y picacódigos con poca experiencia, mal pagados y echando horas a manta, con una motivación por los suelos y una productividad e interés por hacer bien su trabajo en consonancia (modificada a la baja por la falta de respeto que puedan recibir de sus jefes). Ante la queja del usuario y para dos días que faltan del tema, que le den a él y a su cliente. Y luego, todos, así te las apañes con tu cliente, que no es problema nuestro.

Ya la versión 2… cómo pasa el tiempo

La semana pasada cerré el diseño de la versión 2.0 (nombre clave «La Cigala») de nuestro gestor de incidencias, ahora ampliado también a gestor de proyectos. Dos meses de trabajo para una versión preliminar a la que aún tengo que echarle mucho trabajo. Pero ya casi está. Ahora tengo que preparar un par de programitas auxiliares para importar datos a cascoporro desde unos Excel que se usan ahora y a quienes mi criaturita va a jubilar.

Da gusto ver el trabajo de uno en funcionamiento y que los usuarios lo acepten y usen.

No debería haber pasado

—¡Permiso para ir a Donde-sale-el-sol y caparle, señor!

—Ya lo haré yo el lunes.

Los viernes son terroríficos. Siempre pasa algo. Que además de viernes sea el día en que sensei empieza vacaciones es tentar al diablo, así que senpai y yo estábamos con la mosca detrás de la oreja y esperando… Esperando…

A media mañana, el caos: los usuarios avisan de que no pueden entrar en SAP. Donde-sale-el-sol ha desaparecido del mapa. Y bien desaparecido: no responde ni por MPLS ni por ADSL. ¡Ni siquiera por teléfono! ¡Un meteorito ha arrasado la fábrica! ¡Nos invaden los extraterrestres!

La cara de sensei, al móvil, mientras le van dando partes, es todo un poema. Un lumbreras de mantenimiento, sin avisar, se ha puesto a hacer pruebas con las líneas eléctricas. Como resultado, ha tumbado la luz en la fábrica.

—No lo entiendo. No debería haber pasado.

Y la línea de los SAIs. Y con ella, los routers, los switches, el MPLS, la centralita… y todos y cada uno de los servidores.

—Pero si no debería haber pasado nada.

Y mientras intentábamos arrancar todo y lo chequeábamos, yo iba haciendo mentalmente la lista de cosas que necesitaba para un fin de semana de trabajo no planeado, por si las moscas. E incluía una escopeta.

Aghhhh, quiero morir

En algún momento, pareció buena idea. Desdoblar incidencias para cubrir también peticiones de servicio. Se trataba sólo de añadir un campo a tres tablas y luego gestionarlo en tres formularios.

Ya, claro.

Pero había cuatro vistas de esas tablas. Y luego procedimientos almacenados sobre esas vistas y esas tablas. Que eran llamados por los tableadapters de cinco datasets tipados, que los usaban para trabajar con esas vistas y esas tablas. Una docena de tableadapters, más o menos. Muchos métodos llamados (por fortuna) desde unos pocos sitios bien controlados.

Un horror de día.

Datasets tipados, amor y odio

Llevo varios meses con un proyecto que empezó siendo algo pequeño (sustituir una aplicación Access de gestión de incidencias por un desarrollo en .NET, por temas de falta de licencias de Access para todos los usuarios) y ha ido creciendo hasta el punto que mataría por tener una semana para documentar con calma todo lo que llevo hecho. Este crecimiento, aunque lo tenía en mente (no tanto, claro) cuando diseñé la aplicación, me hace dudar de ciertas decisiones que tomé en su día, como el uso de datasets tipados.

Supongo que la idea de usar datasets tipados con VB2010 teniendo Entity Framework puede parecer rara o anacrónica, pero llevo usando datasets desde 2005 y tirar de ellos me ahorraba un tiempo de aprendizaje que no tenía. Ahora, con 17 datasets tipados (y creciendo) no sé hasta qué punto fue buena idea.

Entendámonos, me gustan porque el asistente es cómodo y puedo personalizarlos rápida y fácilmente. Se han convertido en poderosas (y pesadas, me temo) entidades que se mueven entre la aplicación tanto con los datos como con las órdenes de qué hacer con ellos.

El problema viene cuando tengo que reconfigurar alguno, porque se ha añadido algún campo a la base de datos o, como está pasando estos días, ha habido que hacer cirugía mayor y donde antes tiraban de una tabla ahora lo hacen de una vista. Esa forma de machacarse la configuración de los campos existentes, esos problemas con el AllowDBNull y con los NullValue…

A veces odio los datasets tipados.

Calc es para los pobres

Este año he sido especialmente parco en entradas en este blog. Lo tengo casi abandonado, con entradas a medio redactar, distintos temas por probar para cambiar el que tiene… Ha sido un año lleno de historias y de material que publicar, no ha faltado el trabajo: una migración a SAP B1, nuevos equipos, programación a saco, anécdotas varias… Un año completo y divertido en el curro. También muy cansado, que me dejaba sin ganas de tocar otro ordenador al llegar a casa. Intentaré estos pocos días que tengo de vacaciones contar algunas y que no parezca Quemando Cromo un blog abandonado.

El título de la entrada de hoy es una frase lapidaria de mi jefe de departamento cuyo origen hay que buscarlo en un problema de licencias que nos encontramos a principios de año: los puestos de trabajo crecían y faltaban licencias de Microsoft Office (el 2000 teníamos). Teníamos entonces una gran dependencia de Outlook, Excel y Access, pero el precio de las licencias de Office resultaba prohibitivo para todos los puestos que teníamos, así que estudiamos alternativas.

Outlook fue sustituido sin más problemas por Thunderbird + Lightning. Necesitábamos un cliente de correo con calendario y tareas y el pájaro de trueno cumplió con creces. Con Access el problema desapareció por sí solo: había muchos aplicativos en Access que atacaban la base de datos del ERP. Pero este iba a ser sustituido por SAP B1, así que muerto el perro…

El tercer problema era Excel. Probamos tanto OpenOffice.org como LibreOffice como Lotus Symphony. Elegimos finalmente LibreOffice confiando en su futuro frente a OpenOffice.org y tras tener graves problemas de estabilidad con Lotus Symphony. Migramos con ilusión intentando contagiar nuestro entusiasmo para cortar las quejas tontas (tal opción se llama distinta, los botones no son iguales, el desplegable de colores es peor porque es distinto…).

Después de varios desesperantes meses, hubo que claudicar, re-evaluar y adquirir cierto número de licencias para algunos puestos claves. Simplemente, Calc no está a la altura. Tuvimos unos meses de horror, plagados de archivos corruptos al guardar y de pérdida de información (hiperenlaces y vínculos externos). A la hora de buscar cómo migrar ciertos libros de Excel complejos a Calc nos topamos con la falta de documentación, falta de movimiento en los foros oficiales… Cuando llegamos a las tablas dinámicas y las conexiones a SQL Server, tiramos la toalla. Salía más caro intentar usar Calc (tiempo perdido en varios departamentos, falta de información en el momento clave o inconsistencia de la misma) que volver a Excel.

A fin de cuentas, Excel es Dios.

PD: como yo no ocupo un puesto clave, uso Calc. Total, para lo que sé y necesito hacer me basta. Voy más lento de lo que podría ir con Excel 2007-2010 (falta de herramientas, están más ocultas), pero para una vez al mes que lo uso me vale.

Cualquiercosa x 1 = Cualquiercosa

Necesitamos un campo que siempre valga uno.

—¿Uno? ¿Por qué?

—Porque cualquier cosa multiplicada por uno es cualquier cosa. Y necesitamos pedir cualquiercosa al usuario y la única forma es ligarlo a un campo de una tabla. Con un campo que siempre valga uno podemos meterlo en un select que nos devuelva cualquiercosa * campo_que_vale_1 y meterlo en la variable con la que necesitamos trabajar.

Momento de silencio pensativo. Los engranajes mentales zumban.

—OITM. Uno de los Salesfactor. Por defecto, valen uno y sólo usamos el primero de ellos.

Viernes, 13 horas. Avanzando en una consulta puñetera en SAP B1.

El infierno de los códigos de barras

Con motivo del día de Satán, también conocido como nuestro arranque con SAP B1, hemos tenido un fin de semana horroroso de preparativos que se alargó un día más de lo previsto, como colofón a una semana horrorosa y preludio a otra igual de terrible. Una de las cosas que más guerra nos ha dado la impresión de etiquetas de códigos de barra que antes las hacíamos con un programa y ahora teníamos pensado emplear informes de Crystal Reports. No había manera de conseguir imprimir un EAN14 válido. El problema añadido es que en Internet no encontrábamos mucha ayuda.

Al final, la solución vino de un foro del venerable Visual FoxPro, solución que resumo aquí como aviso para navegantes:

El EAN/DUN14 es un churro de números. Información sobre cómo componer un número válido es fácil de encontrar: que debe tener un número par de cifras, cómo se calcula el dígito de control, la norma para su composición… Pero averiguar cómo imprimir eso en un código de barras es harina de otro costal.

Para el código de barras se usa una codificación Interleaved 2 of 5, que representa dos números como un grupo de cinco líneas y espacios. Aquí viene nuestro problema, porque con una fuente de texto sola no hacemos nada: cada carácter de nuestro código de barras se corresponde con dos números de nuestro DUN14. O sea, nuestro código de barras tendrá la mitad de caracteres que nuestro DUN14. Esto nos obliga a usar un algoritmo que nos convierta nuestro chorro de números en esa cadena. Esta cadena, con un tipo de letra Interleaved 2 of 5, será nuestro código de barras.

Y aquí es donde se nos presenta el problema, porque el algoritmo depende de la fuente empleada (o al revés, vamos). De nada nos vale una fuente I2o5 si no tenemos el algoritmo. ¿Por qué? Porque los casos que he visto funcionan del siguiente modo:

Vamos recorriendo nuestro DUN14, cogiendo cada par de números. Al número que representan (por ejemplo, 58) se le suma un valor dado (digamos 52). Se obtiene el carácter correspondiente a ese código numérico (110) y ése, en nuestra fuente I2o5, se corresponderá con las cinco barras-espacios que necesitamos. Como se ve, si nuestra fuente no es la correspondiente a nuestro algoritmo, el carácter representado no tiene por qué coincidir (y no lo hará) con el buscado.

Al final, debemos tener una cadena de caracteres formada por un carácter de apertura, la cadena tratada y un carácter de fin, que nuestro lector será capaz de entender.

En el artículo que menciono antes encontramos código para generar una representación de nuestro DUN14 para una fuente I2o5 y, además, nos da la fuente. El código, pese a los nombres de las variables, es muy simple: la mayor parte de la función se dedica en calcular el dígito de control y en asegurarse que la longitud sea correcta. Si ya tenemos nuestro código válido, todo se reduce a lo siguiente:

1) Tomamos cada par de números de nuestro código (para 14 cifras tendremos, pues, 7 pares).

2) Si el número de dos cifras que componen es menor de 50, le sumamos 48. Si es mayor, 142.

3) Sacamos el carácter correspondiente a ese código.

4) Formamos una nueva cadena de caracteres con los que hemos obtenido, en orden.

5) Como cabecera le añadimos el carácter 40 y como cierre, el 41 (los paréntesis)

6) Aplicamos la fuente I2o5 que acompaña al ejemplo y listo.

La primera aplicación de esto la hice a mano, en Excel, para un código dado y la alegría de ver cómo el lector entendía el puñetero código después de tan horroroso y desesperante fin de semana es difícil de explicar.