miércoles, 28 de enero de 2015

Mostrar código fuente en Blogger

Para formatear el código fuente de una entrada se puede utilizar SyntaxHighlighter. El resultado es muy bueno, pero el rendimiento es bastante pobre. Otra forma para conseguir código con formato para tu blog, es usar google-code-prettify. Se instala muy fácilmente siguiendo esto pasos:
  • Entrar en el blog 
  • Ir a Diseño->Edición HTML
  • Buscar el cierre del head, </head> y justo arriba pegar el siguiente código:
  • <script src="
    https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js">
    </script>
  • También puede descargarse el módulo completo desde aquí y usar esto:
    <link href="prettify.css" type="text/css" rel="stylesheet" />
    <script type="text/javascript" src="prettify.js"></script>
  • Guardar los cambios

Así, cuando se escriba una entrada nueva, en la edición HTML, debe encerrarse el código con estos tags:

<pre class="prettyprint">
  código fuente aquí
</pre>

Más información sobre el google-code-prettify puede encontrarse pulsando aquí.

martes, 1 de julio de 2014

SEPA (Zona Única de Pagos en Euros). Estándar de intercambio bancario

SEPA (Single Euro Payments Area) es un nuevo estándar para la comunicación con las entidades financieras, incluyendo lo relativo a domiciliaciones bancarias, transferencias y pagos, entre países de la Unión Europea.

La entrada en vigor de SEPA supone que se dejan de utilizar los cuadernos bancarios (CB 19, etc) actuales para las comunicaciones con el banco, para pasar a utilizar la nueva definición basada en el intercambio de ficheros XML. Me ha tocado trabajar duramente en nuestra aplicación para tenerlo todo listo y a tiempo, convirtiéndonos en una de las primeras empresas en utilizar el estándar, hasta tal punto de establecer un periodo de pruebas y colaboración con entidades bancarias para implantar la nueva normativa. He aprovechado para, al mismo tiempo, realizar toda la conversión de cuentas del formato tradicional CCC al nuevo IBAN/BIC, todo un reto que había de realizarse sin que nadie notara nada.

Una de las cosas que se deben tener en cuenta para implantar la normativa SEPA es que se debe disponer de un sistema de control de los documentos firmados por el cliente en los cuales autoriza a la empresa a que le realice cargos en su cuenta, ya que dichos documentos deben ser comunicados a la entidad bancaria en cada comunicación. Toda esta información y todo lo relativo a la normativa puede consultarse desde su página oficial.

jueves, 2 de enero de 2014

EIAC: Hacia un nuevo estandar

EIAC son las siglas de Estándar de Intercambio de Información entre Entidades Aseguradoras y Mediadores. Actualmente me encuentro trabajando en una empresa del mundo del seguro, y además contamos en ella con uno de los principales impulsores y creadores de este proyecto. En este sector es complicado trabajar con distintas compañías, dado que cada una funciona de una forma diferente al no haber un estándar común, lo que hace que cada aseguradora tome sus propias decisiones en cuanto a las comunicaciones con sus corredores. Unas funcionan con ficheros excel, otras con ficheros planos, otras sólo a través de su web (aquí entran en juego otros problemas, con distintos navegadores y versiones de Java, que hacen que unas web funcionen y otras no, lo que obliga a tener distintos navegadores con distintas configuraciones, pero eso es otro tema). Se hace muy difícil mantener un software de comunicación con las distintas compañías ya que no existe nada común.


Con la intención de resolver estos problemas nace la idea de crear este estándar, que impulsamos con fuerza desde nuestra empresa. Para realizar el estándar contamos con la colaboración de Tirea, en cuyas oficinas de Madrid se llevan a cabo reuniones entre corredores, aseguradoras y empresas de software del sector para llegar a los acuerdos necesarios para sacar adelante un estándar.

La idea es disponer de una forma única de solicitar y recibir información, utilizando el intercambio de ficheros XML, del estilo al que se utilizan en otras áreas como las interconexiones bancarias (con el formato SEPA que ya se ha comentado en este blog). Además, vamos un paso más allá y no queremos quedarnos sólo con el estándar, sino que se quiere poner en marcha una zona común de intercambio (cloud, plataforma en la nube como se llama ahora) que vele por que se cumplen todos los requisitos y esquemas del estándar en el intercambio de información.

Por estos días, estoy encargado, además de colaborar en la definición del estándar, en ir implantando el mismo en nuestro software de gestión.

Prácticamente todas las aseguradas, corredores, y empresas de software del sector se encuentran al día respecto a la definición de este estándar que ya se está convirtiendo en una realidad. La información relativa al proyecto es abierta y pública, y puede encontrarse pulsando aquí.

lunes, 9 de julio de 2012

Clúster de alto rendimiento y cabina de discos iSCSI

La cabina de discos SAS de que disponemos para almacenar la información se nos ha quedado pequeña. Aprovechamos la compra de una nueva cabina de discos, en esta ocasión iSCSI, para adquirir además nuevos servidores para la creación de un nuevo clúster de alto rendimiento y comenzar a trabajar con virtualización. La cabina adquirida es la de la imagen siguiente.


Hemos adquirido también varios switches para poder optimizar el montaje de la cabina de discos. Con todo esto renovamos por completo nuestro CPD, y dedicamos los actuales servidores a otros servicios.

Lo primero que hacemos es montar el clúster de alto rendimiento. Básicamente esto consiste en instalar, en nuestro caso, dos servidores interconectados entre sí y que configuran y gestionan de forma común una serie de servicios (utilizan para ello una partición común de la cabina denominada Quorum), de forma que si uno cae automáticamente el otro toma el control de los servicios que el caído controlaba. Es posible repartir los servicios entre los servidores para distribuir la carga de trabajo, y únicamente en caso de fallo de uno de los servidores, el resto se reparten los servicios para que en ningún momento los usuarios se queden sin trabajar.

La forma en que hemos montado el cluster y la cabina es la siguiente. Cada nuevo servidor dispone de 6 conexiones de red. Utilizamos una de cada uno de ellos para interconectar los servidores directamente. El objetivo de esta conexión es hacer una especie de ping de un servidor a otro para detectar cuando uno cae, y así poder tomar el control de los servicios por parte de otro servidor. Dos conexiones más se utilizan para el tráfico iSCSI de la nueva cabina de discos. El tráfico iSCSI debe ir separado de los paquetes de red habituales para evitar problemas (es posible utilizar un switch para ambos servicios configurandóle una VLAN, que es como crear por software switches separados dentro del mismo aparato). Estas dos conexiones iSCSI se conectan cada una a un switch (que a su vez se conectan a la cabina de discos), para evitar así posibles problemas por la rotura o fallo de uno de ellos (todo este hardware lleva además dos tomas de corriente, conectadas a SAIS diferentes). Las 3 conexiones restantes se reparten entre otros dos switches de red, que une los servidores con otro armario de switches que conectan a los clientes de la red. Esas 3 conexiones se unen utilizando el software Broadcom Advanced Control Suite 3, lo que resulta en una conexión a 3000 Mb en cada uno de los servidores.

El resultado de todo esto es un cluster de alto rendimiento con duplicidad de todo tipo (conexiones eléctricas, switches y servidores). La cabina la montamos en RAID 1+0, mediante la que cada dos discos se utiliza la capacidad de uno, y el otro es un espejo exacto del primero, de forma que la misma información está almacenada en dos discos. Esta configuración permite mayor seguridad pero menor espacio de almacenamiento. Es muy importante en casos como este pensar muy bien y decidir como se quiere montar la infraestructura de la red, dado que una vez montado se hace más complicado poder cambiar la configuración.

jueves, 16 de febrero de 2012

Gestor documental

Una de las caracterisicas que debe tener nuestro software de gestion es disponer de un pequeño gestor documental. Cada documento debe estar correctamente identificado, incluso con su nombre tipificado. De esta forma es muy fácil controlar en ciertos procesos si existe cierta documentación antes de poder continuar realizando ciertas tareas (imaginar por ejemplo, dar acceso a la web de eCliente a un cliente el cual no nos ha firmado el contrato de uso de la misma, o hacerle un cargo en la cuenta del banco sin un documento firmado donde nos de el consentimiento), así como generar comunicaciones automáticas que incluyan cierta documentación, mostrar documentos online, identificar a que pertenece un documento únicamente por su nombre de fichero, y otras muchas ventajas que se pueden obtener al gestionar de esta forma los documentos.

Para solucionarlo, simplemente hemos creado una tabla en la base de datos en la que se indica una descripción del documento, el formato que este debe tener como nombre de fichero (utilizando caracteres comodín que luego son reemplazados desde el software), y la carpeta dentro de la estructura que tenemos definida para cada registro en la que debe ser almacenado. Además, hemos creado un campo para indicar si es posible crear diferentes versiones del documento (se añaden versiones según se van introduciendo documentos) o no (se sobreescribe si se introduce de nuevo).

Estructura de la tabla

Además de esto se ha incluido un visor de documentos en el software, en el que se da la posibilidad de escanear o de adjuntar un documento. Al hacerlo, el software pregunta que es lo que se está introduciendo en el sistema, y el usuario, basado en la descripción, lo selecciona. El documento seleccionado es, de acuerdo a la elección del usuario, ubicado y nombrado de acuerdo a como se especifica en la tabla.

La nomenclatura que hemos acordado consiste en grupos de 3 letras que identifican a que pertenece y donde se almacena el documento. Por ejemplo, un documento con la forma siguiente:

CON-#COD_DOC#-DOC-FTR-#COD_USU#-V#VERSION#

Se definiría como un documento relativo a un contrato(CON), a continuación se indicaría el código del mismo (#COD_DOC#), que se almacena en la carpeta Documentacion (DOC) de la estructura a la que pertence (contratos), y que representa una factura (FTR). Al final se indican el usuario que lo introduce (#COD_USU#) y la versión del documento (#VERSION#), de forma que la inicial es la 01 y si se van añadiendo más se van incrementando de forma correlativa.

Adjuntar documento


Existen múltiples y potentes alternativas para realizar un gestor documental, algunas de las cuales hemos estudiado, como Alfresco, OpenKM, etc, pero dadas nuestras necesidados hemos optado por esta sencilla solución. Esto nos ha permitido además realizar distintas tareas posteriores como realizar envíos periódicos de información a los cliente, lo cual resulta muy sencillo porque se sabe en cada caso como se llama cada documento y donde se encuentra almacenado.

martes, 11 de enero de 2011

Service Broker. Qué es y utilización en un sistema de alertas.

En nuestro software de gestión se deben llevar a cabo una importante cantidad de procesos en tiempo real. Además, existen distintos usuarios trabajando sobre las mismas parrillas de datos, y cuando un usuario cambia algo, todos los demás deben verlo instantáneamente. Hasta ahora, para solucionar esto utilizábamos Socket Broadcast, de forma que cuando un registro era modificado, enviábamos un mensaje codificado por la red (utilizando un puerto), que era escuchado por los demás y hacía un refresco de su pantalla. La utilización de sockets nos ha dado algunos problemas, relativos a cortafuegos o antivirus por ejemplo, ya que detectan que se abre un puerto no esperado. Además, si por algún motivo nos salimos del programa incorrectamente, al volver a entrar nos sale un mensaje diciendo que no se puede abrir ese puerto porque ya está abierto.

ServiceBroker se introduce a partir de SQL 2005, y nos permite solucionar este tipo de problemas. No voy a entrar en todos los detalles sobre esta tecnología, lo que hace y cómo funciona, para eso puede consultarse más información en la web de Microsoft. Para nuestro caso, lo interesante es que nos permite monitorizar registros, de forma que cuando haya un cambio en cualquier campo del mismo, se nos envíe una notificación. Tiene la ventaja de notificarnos siempre que haya un cambio, aunque este no se realice desde nuestro software. Pongámonos pués manos a la obra.

Lo primero que debemos hacer es activar Service Broker en nuestra base de datos. Para ello, debemos ejecutar sobre ella el siguiente comando:
ALTER DATABASE [Database Name] SET NEW_BROKER
ALTER DATABASE [Database Name] SET ENABLE_BROKER;
Otros comandos interesantes pueden ser, desactivar ServiceBroker:
ALTER DATABASE [Database Name] SET DISABLE_BROKER;
O comprobar si está activado:
SELECT is_broker_enabled FROM sys.databases WHERE name = 'Database name';
Si en alguna ocasión el comando, debido a los permisos de la base de datos, no se ejecuta correctamente, deberemos precederlo de lo siguiente:
ALTER AUTHORIZATION ON DATABASE::[Database name] TO [sa];
Con esto ya tenemos la base de datos preparada para notificar estos cambios. Ahora nos vamos a nuestro software. Desde .NET, podemos detectar los cambios producidos a través del objeto SqlDependency.

Nos vamos a nuestra capa de datos (trabajamos en 3 capas), y añadimos lo siguiente (existen otras formas de hacerlo, pero esta es la que nosotros utilizamos):
Private Structure sDependency
  Dim Tabla As String
  Dim ClavePrimaria As String
  Dim Registro As String
  Dim SeparadorClavePrimaria As String
End Structure
Dim rDependency As sDependency
Public Event RegistroModificado(ByVal cTabla As String, ByVal cRegistro As String)
Public Event TablaModificada(ByVal cTabla As String)
Public Event SQLModificada(ByVal cTabla As String)
Lo que vamos a hacer aquí es crear una estructura genérica para indicar que es lo que queremos monitorizar y crearemos un evento de notificación de cambios para envíar a quien use esta capa de datos. En este caso vamos a crear 3, para poder monitorizar un registro en concreto, un registro que cumpla las condiciones de una sentencia SQL, o un cambio en cualquier lugar de una tabla. Esto nos dará mucho juego, ya que podremos monitorizar y estar informados de los cambios en los que más nos interese. Para ello, definimos a continuación las rutinas para activar la monitorización y los eventos que se dispararán.
' Para un registro
Public Sub ActivarNotificacionCambiosRegistro(ByVal cTabla As String, ByVal cClavePrimaria As String, ByVal cRegistro As String, Optional ByVal cSeparadorClavePrimaria As String = "'")
  Try
    rDependency.Tabla = cTabla
    rDependency.ClavePrimaria = cClavePrimaria
    rDependency.Registro = cRegistro
    rDependency.SeparadorClavePrimaria = cSeparadorClavePrimaria

    Dim cmd As New SqlClient.SqlCommand
    cmd.CommandText = "SELECT " + cClavePrimaria + " FROM dbo." + cTabla + " WHERE " + cClavePrimaria + "=" + cSeparadorClavePrimaria + cRegistro + cSeparadorClavePrimaria
    cmd.Connection = oCon
    Dim dependency As New SqlClient.SqlDependency(cmd)
    dependency.AddCommandDependency(cmd)
    AddHandler dependency.OnChange, AddressOf OnDependencyChangeRegistro
    cmd.ExecuteNonQuery()

  Catch ex As Exception
    Throw New Exception(ex.Message)
  End Try
 End Sub

Private Sub OnDependencyChangeRegistro(ByVal sender As Object, ByVal e As SqlClient.SqlNotificationEventArgs)
  RaiseEvent RegistroModificado(rDependency.Tabla, rDependency.Registro)
End Sub

' Para cualquier registro de una tabla
Public Sub ActivarNotificacionCambiosTabla(ByVal cTabla As String, Optional ByVal cClavePrimaria As String = "")
  Try
    rDependency.Tabla = cTabla
    If cClavePrimaria = "" Then
      rDependency.ClavePrimaria = Me.ClavePrimaria(cTabla)
    Else
      rDependency.ClavePrimaria = cClavePrimaria
    End If
    rDependency.Registro = ""
    rDependency.SeparadorClavePrimaria = ""

    Dim cmd As New SqlClient.SqlCommand
    cmd.CommandText = "SELECT " + rDependency.ClavePrimaria + " FROM dbo." + cTabla
    cmd.Connection = oCon
    Dim dependency As New SqlClient.SqlDependency(cmd)
    AddHandler dependency.OnChange, AddressOf OnDependencyChangeTabla
     cmd.ExecuteNonQuery()

  Catch ex As Exception
    Throw New Exception(ex.Message)
  End Try
End Sub

Private Sub OnDependencyChangeTabla(ByVal sender As Object, ByVal e As SqlClient.SqlNotificationEventArgs)
  RaiseEvent TablaModificada(rDependency.Tabla)
End Sub


' Para un registro cualquiera de los que entren en una sentencia SQL
Public Sub ActivarNotificacionCambiosSQL(ByVal cSQL As String)
  Try
    rDependency.Tabla = cSQL
    rDependency.ClavePrimaria = ""
    rDependency.Registro = ""
    rDependency.SeparadorClavePrimaria = ""

    Dim cmd As New SqlClient.SqlCommand
    cmd.CommandText = cSQL
    cmd.Connection = oCon
    Dim dependency As New SqlClient.SqlDependency(cmd)
    AddHandler dependency.OnChange, AddressOf OnDependencyChangeSQL
    cmd.ExecuteNonQuery()

  Catch ex As Exception
    Throw New Exception(ex.Message)
  End Try
End Sub

Private Sub OnDependencyChangeSQL(ByVal sender As Object, ByVal e As SqlClient.SqlNotificationEventArgs)
  RaiseEvent SQLModificada(rDependency.Tabla)
  Call ActivarNotificacionCambiosSQL(rDependency.Tabla)
End Sub
Y con esto, ya tenemos lista nuestra capa de datos genérica con soporte para ServiceBroker. Leyendo un poco el código, necesita poca explicación. Para ver como se utiliza, vamos a hacerlo con un caso real que hemos implementado. En nuestro sistema, nos han pedido crear una serie de alertas que se disparan cuando suceden ciertos eventos. En esos casos, hay que notificar inmediatamente a uno o varios usuarios para que tomen ciertas decisiones. Para conseguir esto, lo primero que hacemos es definir una tabla para almacenar las alertas.


Con la estructura definida para esta tabla, podemos crear alertas relativas a ciertos registros, y con el campo acción podremos realizar diferentes acciones al pulsar sobre la alerta (esto lo hacemos en otro formulario, un visor de alertas). Desde abrir un registro para consultarlo o modificarlo, hasta realizar ciertas acciones de forma automática, pasando por tomar decisiones (alertas de decisión) que impliquen realizar ciertas modificaciones, o por la generación automática de informes programados desde un servicio.

Una vez definida, y con la utilización de ServiceBroker, sólo tendremos que, en los supuestos en los que los eventos deseados se producen, escribir en la tabla de alertas. En el software tenemos un formulario siempre abierto y visible (trabajamos con 2 pantallas) en el que se muestran las alertas pendientes que tiene el usuario logado. Utilizando ServiceBroker, ese formulario se actualizará en tiempo real, y el código es tan sencillo como el que se muestra a continuación.
  Dim WithEvents oCon As New VB3.Conexion

  Private Sub FrmAlertas_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Try
      Call CargarAlertas()

      Dim SQL_Monitorizacion As String
      SQL_Monitorizacion = "SELECT id FROM dbo.[Alertas.Alertas] WHERE cod_usuario='" + Constantes.Login.Codigo + "' AND fecha_lectura=''"
      oCon.ActivarNotificacionCambiosSQL(SQL_Monitorizacion)

    Catch ex As Exception
      oForm.ControlErrores(ex, Me.Name, "FrmAlertas_Load")
    End Try
  End Sub


  Private Sub SQLCambia(ByVal cSQL As String) Handles oCon.SQLModificada
    Dim oMetodoOriginal As MethodInvoker
    oMetodoOriginal = New MethodInvoker(AddressOf CargarAlertas)
    Me.Invoke(oMetodoOriginal)
  End Sub


  Public Sub CargarAlertas()
    Try
      Dim dt As New Data.DataTable, SQL As String

      SQL = "SELECT * FROM [Alertas.vAlertas] WHERE cod_usuario='" + Constantes.Login.Codigo + "' AND fecha_lectura=''"
      dt = oCon.GetDataTable(SQL)

      dg.AutoGenerateColumns = False
      dg.DataSource = dt

      dt.Dispose()

    Catch ex As Exception
      oForm.ControlErrores(ex, Me.Name, "CargarAlertas")
    End Try
  End Sub
Este sistema es muy versátil, muy fácil de utilizar, y nos puede servir para monitorizar agendas, parrillas de datos, para disparar ciertos servicios cuando se produzca algún cambio, ... El límite lo pone nuestra imaginación. Espero que este post os haya sido de utilidad. Hasta la próxima.

miércoles, 6 de octubre de 2010

eCliente

Uno de los proyectos que debemos acometer en estos tiempos es la creación de una web de eCliente para la consulta de nuestros datos por parte de los clientes.

Inicialmente se acometió el desarrollo utilizando ASP.NET y una base de datos SQL Server online con la que sincronizábamos los datos deseados desde nuestra aplicación local. Un servicio subía todas las noches los datos que queríamos hacer públicos a la base de datos de Internet, que era la que utilizaba la aplicación web.

Con el paso del tiempo hicimos una mejora sustancial de la web, montando un servidor web y construyendo un webservice (.NET) en nuestras instalaciones. Este webservice conectaba con nuestra base de datos y devolvía los resultados, tanto en formato XML como JSON. Esto permitió modificar la web y hacerla mucho más simple. Ahora la web no accedía a datos, sino que hacía llamadas al webservice, teniendo la información en tiempo real. De paso nos ahorramos unos euros de SQL en el servidor Web y procesos de sincronización de información.


 

Copyright @ 2015 Tosblama