¿Engaña Openbravo a sus clientes?

Entiendo que una compañía de software libre venda servicios a sus clientes como pueden ser soporte del producto o actualizaciones automáticas, siempre y cuando no sucedan cosas como esta, al fin y al cabo es el modelo natural del software libre, vender servicios. Lo que ya no termino de entender es que compañías como Openbravo intenten vender cosas sin sentido como son la posibilidad de instalar su producto utilizando más de un servidor o el hecho de conectarse x usuarios concurrentes a la máquina. Si además tenemos en cuenta que toda la pila de herramientas necesarias para ejecutar Openbravo son libres, y por tanto no hay ningún impedimento técnico ni legal en el que basarse para poner estas limitaciones, terminas sacando ciertas conclusiones.

Preguntando a Josep Mitjà si lo que querían decir es que iban a capar artificialmente el producto para cobrar más no tuvo ningún pudor en contestar que si.

Lo que nos vienen a decir es algo así que si quieres comprar un coche te cobramos a tanto, pero si lo vas a utilizar por autopista entonces es ese tanto más un plus. Si quieres comprar un autobús en el que pueden ir 50 personas es tanto pero sólo podrás llevar a 1 persona, por cada persona de más que quieras llevar tienes que pagar también un plus. ¿Tiene algún sentido esto?, yo creo que no.

Supongo que se excusarán en que no es lo mismo dar soporte para un usuario que para 10, en este caso el autobús vuelve a ser un buen ejemplo, necesita un mantenimiento y da igual si va 1 persona o van 50 porque el mantenimiento será el mismo. En Openbravo sucede algo parecido, un error en el sistema afecta igual si hay una persona o 10 porque el límite de usuarios lo pone el hardware y la red, no Openbravo. Con el hecho que el servidor de base de datos esté en un servidor y tomcat en otro volvemos a estar en las mismas, el mantenimiento de la aplicación es idéntico en los dos casos. Puede que el mantenimiento de servidores, red, sistemas en general no lo sea pero es que esa tarea de mantenimiento y soporte no es la que se paga con Openbravo Profesional sino que se tendrá que contratar a parte.

Me han propuesto trabajar en algún proyecto de implantación con Openbravo Profesional y justamente este es el motivo por el que los voy rechazando, no puedo ser cómplice de este engaño.

Cheli

Como configurar el conector jk para Openbravo en Debian Gnu/Linux

Jk es un conector entre apache y tomcat que permite que las peticiones estáticas las responda directamente apache y las peticiones que necesiten ser procesadas se redirijan al contenedor tomcat, así conseguimos optimizar el rendimiento al lograr que cada servicio realice la tarea que mejor sabe hacer.

Configurar este conector en Debian Gnu/linux para una instalación estándar de Openbravo es muy sencillo. Después de instalar y configurar apache y la pila de herramientas que necesita Openbravo, también necesitaremos instalar el conector (libapache2-mod-jk). Todas estas instalaciones se pueden realizar directamente desde apt.

Ahora lo único que tendremos que hacer es descargar estos dos archivos jk.conf y workers.properties y copiarlos a /etc/apache2/mods-available/jk.conf y /etc/libapache2-mod-jk/workers.properties respectivamente. Además deberemos crear un enlace simbólico en mods-enabled.

ln -s /etc/apache2/mods-available/jk.conf /etc/apache2/mods-enabled/jk.conf

Por último deberemos añadir esta linea al archivo /etc/apache2/sites-enabled/000-default

……
Deny from all
Allow from 127.0.0.0/255.0.0.0 ::1/128
</Directory>
jkMount /openbravo* ajp13_worker
</VirtualHost>

Y eso es todo.

Cheli

¿Por qué el sistema de módulos y plantillas no aporta ventajas al desarrollo de Openbravo ERP?

Para poder entender que ha cambiado o mejor dicho, que no ha cambiado al desarrollar sobre Openbravo ERP después de la introducción del sistema de módulos y plantillas en la versión 2.50 tendremos que hacer un poco de historia de lo que teníamos antes.

En versiones anteriores a la 2.50 la recomendación de openbravo a la hora de introducir un desarrollo propio era meterlo en un directorio que existía por defecto en el árbol de código llamado srcClient. ¿En qué consistía esta metodología? es muy fácil de explicar, si querías introducir un nuevo archivo de código lo que debías de hacer era replicar el árbol de directorios donde se iba a ubicar dicho archivo en src/ pero sobre srcClient, pongamos un ejemplo.

Si yo necesitaba como desarrollador añadir un nuevo informe (un archivo jrxml de jasper) que iba a estar ubicado en src/org/openbravo/erpReports lo que tenía que hacer es lo siguiente:

  1. Replicar el árbol de directorios donde va a quedar ubicado el archivo pero en srcClient.
    mkdir srcClient/org
    mkdir srcClient/org/openbravo
    mkdir srcClient/org/openbravo/erpReports
  2. Copiar el archivo a esa ubicación
    mv archivo.jrxml srcClient/org/openbravo/erpReports

Ahora al compilar el codigo lo que hacía la tarea ant correspondiente era copiar todo lo que encontraba en srcClient y lo volcaba en src sobreescribiendo los archivos originales si se diera el caso para posteriormente empezar la compilación. Con esto lo que conseguíamos es tener nuestros desarrollos separados del resto de código, única y exclusivamente, pero no nos servía para nada más. Yo como siempre utilizo un sistema de control de versiones no le veía ninguna ventaja a este método ya que en el histórico de mi scv tenía qué archivos había tocado y qué había hecho con ellos por lo que los cambios siempre se hacen directamente en la rama src. Mi opinión es que si utilizas un scv el método de srcClient es completamente inútil.

A este método hay que sumarle una serie de inconvenientes adicionales. Por ejemplo, si queríamos modificar un archivo ya existente en openbravo (core) tenías que hacer una copia sobre srcClient y modificarlo ahí. Si ahora en algún momento se aplicaba un cambio al core que involucrara a ese archivo el primer problema es que el archivo que encontraba el actualizador era una copia del tuyo (srcClient) pero en src (recordemos que al compilar se machaca la versión src con la de srcClient) con lo que ya teníamos los primeros problemas de conflicto de código. Lo que te tocababa hacer si utilizabas srcClient es:

  1. recuperar la version original del archivo sin tus cambios y colocarla en su lugar en src.
  2. Aplicar la actualización de openbravo para ese archivo con lo que no se produciría ningún conflicto.
  3. Y por último integrar (hacer merge) de los cambios de ese archivo en tu versión en srcClient para que funcionara.

La otra opción sería la misma que si no utilizaras srcClient, o lo que es lo mismo la que he estado utilizando yo que consiste en:

  1. Aplicar la actualización de openbravo para ese archivo con lo que si ese archivo es consecuencia de un archivo en srcClient (insito en que machaca sobre src) o de una modificación directa en src, cabe la posibilidad de que exista un conflicto.
  2. Resolver el conflicto.
  3. En caso de que ese archivo fuera consecuencia de uno en srcClient tendríamos que actualizarlo en este árbol (srcClient).

¿Cómo funciona el sistema de módulos?, en esencia es muy parecido a srcClient. Cuando vas a crear un módulo debes crear un directorio al estilo srcClient para recrear los archivos, sean del core o no, y su posición en el árbol de código en el directorio de soporte para el módulo (llamémoslo moduleClient, esto es una convención que me acabo de inventar por si alguien no se había dado cuenta). Lo que sucede ahora es que cuando se actualiza el core lo que hace openbravo es desacoplar todos los módulos (limpiar todo el código moduleClient de todos los módulos), dejándo el código original de la versión de core instalada y sobre esa aplicar la actualización al siguiente (hacen merge) así se aseguran que el actualizador de OB ahora ya no va a tener virtualmente coflicto alguno. Pero el problema lo volvemos a tener en el momento de volver a acoplar los módulos (volver a meter el código moduleClient) igual que lo teníamos con srcClient de ahí que diga que virtualmente no hay conflictos ya que realmente hay exactamente los mismos conflictos que en cualquier otra versión anterior.

Como dije en un comentario a Pepe, ahora OB puede afirmar con rigor frases propagandísticas del tipo «Hemos solventado los problemas de actualizaciones, ahora ya no vamos a tener ningún conflicto y actualizar el core es tan sencillo como dar un click». Pero si uno tiene dos dedos de frente y sabe como funciona openbravo sabría que la magia no existe y pensaría lo que suelo pensar yo en estos casos ¡estos se piensan que soy imbécil!.

Aquí no se queda la historia, ni siquiera los que toman las decisiones de diseño en OB saben como van a mantener la compatibilidad de módulos en versiones posteriores. Cuando le vieron las orejas al lobo pensaron, bueno vamos a intentar mantener lo más estable posible las partes del core que son subsceptibles de desarrollo por parte de terceros y a esto lo vamos a llamar API, que en cierta manera lo es, pero hacer eso como toda compatibilidad hacia atrás y sobretodo con un desarrollo tan poco estable como el que lleva OB es imposible.

Al final pasan cosas como por ejemplo si mi código moduleClient contiene una modificación en el core y por alguna razón como puede ser corregir un bug en el core OB necesita cambiar algo de esa supuesta API (crear o eliminar campos, modificar la interfaz de un método de una clase, etc) que pueda afectar a los desarrollos de terceros lo que hacen es publicarlo en una página de wiki para que lo tengas en cuenta. En menos de dos meses ya llevan 19 cambios en esa API.

Hablando incluso con algunos desarrolladores proponen alguna solución de compromiso pero que no dejan de ser chapucillas poco elegantes, a mi a veces me ha tocado hacer alguna de estas. Sigamos con los ejemplos, imaginemos que en mi código moduleClient tengo un archivo del core y en la siguiente versión del core se modifica, pues una de las propuestas es que dejes tu antiguo archivo del core que tienes en tu moduleClient sin las nuevas modificaciones. Esto tiene un peligro que es que si el desarrollo que provocó el cambio en ese archivo también afecta a otros archivos y tu mantienes la versión anterior puede que no compile o que funcionalmente casque. No te queda más remedio que o bien integrar el cambio en tu archivo del core que tienes en tu moduleClient o revisar si realmente se va a romper la aplicación.

Otro ejemplo que me llegó hace poco en una propuesta de un desarrollador de OB era, -bueno cuando tengas que hacer una modificación en una ventana del core duplícala de forma que las mejoras que se apliquen a esa ventana se harán sin conflictos en la ventana origina que dejarás oculta y tu seguirás con tu versión de ventana sin aplicar ningún cambio ni mejora-. Esta en cierta manera me alarmó ya que si se pretende vender el soporte de actualizaciones automáticas y de forma transparente en network pero para evitar problemas lo que haces es rodear el sistema para que no se apliquen en la versión del cliente pues no sirve de nada.

Por último comentar que respecto a una consideración que me hacía Pepe en la que indicaba que el sistema de módulos permite organizar mejor los desarrollos vuelvo a no coincidir. Los desarrolladores para este fin lo que hacen es utilizar un sistema de control de versiones que aporta muchísimas más ventajas en organización y reutilización de código que el hecho de poder paquetizarlo.

Un ejemplo sería que podemos ir al detalle que queramos en las modificaciones. Si queremos aplicar una modificación que hemos desarrollado para un cliente pero para ello hay que aplicar un módulo entero a lo mejor puede implicar que al margen de esa modificación se vayan a aplicar otras que no deseamos, o alrevés, requerir de varios módulos para una única modificación. Para esto tenemos el sistema de control de versiones, sus ramas, etiquetas y demás mecanismos.

El hecho de generar un diff y aplicar con patch es inmediato en el momento que has superado la curva de aprendizaje de este tipo de herramientas. Y ahora con los sistemas descentralizados tienes aún más ventajas como poder hacer push contra la rama local de los desarrolladores que te interesen, etc etc.

Espero haber sido claro y haber podido explicar porque considero que los módulos y plantillas no aportan nada o muy poco al desarrollo en Openbravo ERP pero por otra parte si aportan mucho a la hora de generar entregables.

Un saludo.

Pagos parciales en Openbravo ERP

He desarrollado una nueva funcionalidad que permite agilizar los pagos parciales de una factura en Openbravo ERP. Primero explicaré la problemática que tiene la forma de trabajar de Openbravo y porqué se ha pensado en esta solución.

Cuando en Openbravo creamos una factura a esta se le asocian una serie de efectos que inicialmente estarán en estado «–» (pendiente), el condicionante es que una vez procesada una factura (completada en terminología de Openbravo) el total de los efectos debe ser igual al total de la factura. Como consecuencia de este requisito lo que hace Openbravo es que al completar una factura automáticamente te crea los efectos en base a las condiciones para ese cliente según su ficha en datos maestros. El problema que tiene esta solución es que estamos vaticinando como y cuando vamos a cobrar según la forma y condiciones de pago del cliente pero eso a veces no corresponde con lo que finalmente va a suceder.

Vamos a poner un ejemplo muy sencillo en el que la forma de pago es «giro bancario» y nos van a pagar a 60 días. Resulta que el cliente nos hace un pago parcial a los 20 días en efectivo, ¿cómo reflejamos esto en Openbravo?. De entrada tenemos un problema porque si hemos completado la factura se nos debe haber creado un efecto por el total de la factura con vencimiento a 60 días y este será el que actualmente tendremos en cartera de efectos.

Para este tipo de conflictos Openbravo nos provee de una herramienta que se llama «Liquidación» y que nos permite transformar unos efectos en otros. Esta herramienta tiene como entrada de 1 a n efectos ya existentes que son los que se van a cancelar y como salida de 1 a n efectos nuevos que son los que se van a generar, cómo es lógico la condición es que la suma de los efectos cancelados coincida con la suma de los efectos generados.

Por tanto la forma de solucionar el problema que tenemos es:

  1. crear una liquidación en la que cancelamos el efecto de la factua a 60 días y genermos dos nuevos, uno con las mismas condiciones del original pero por cantidad del total de la factura – el efectivo adelantado y el otro con condiciones de pago en efectivo por valor de la cantidad adelantada.
  2. Este último efecto es el que cobraremos por banco, caja o lo que corresponda dejando pendiente el segundo efecto generado.

En este caso particular en el que sólo se va a hacer un pago parcial existe otra solución que consiste en:

  1. Reactivar la factura (desprocesarla) con lo que los efectos que se generaron al completarla desaparecerán.
  2. Ahora en la pestaña de efectos de la factura añadimos un nuevo efecto que correponde al pago parcial en efectivo.
  3. Volvemos a completar la factura, esto provoca que Openbravo vuelva a generar los efectos según las condiciones del cliente, pero esta vez por la cantidad pendiente ya que tiene en cuenta el efecto que acabamos de introducir.
  4. Cobramos el efecto por banco, caja o lo que corresponda lo que implica que la factura queda definitivamente bloqueada y no se podrá reactivar.

En resumen, la segunda solución es la más ágil y cómoda pero tiene el inconveniente que sólo se puede hacer un pago parcial. La primera solución es el estandar en Openbravo, cuando queremos manipular efectos debemos hacerlo mediante una liquidación, pero tiene el inconveniente de que el hecho de tener que pasar por el proceso de crear y procesar una liquidación es lento (es el usuario el que debe introducir los datos de los efectos a generar, sus condiciones, cantidades… además de tener que hacer el cálculo para que el total de efectos generados y cancelados cuadren).

Al final hablando con un cliente se encontró una solución, primero veamos su especificación funcional:

  1. Creamos y completamos una factura, esto como ya hemos comentado nos genera sus efectos.
  2. Cuando el cliente nos hace un pago parcial que cobraremos por banco o caja vamos a «Extracto bancario» o a «Diario de caja» y creamos un nuevo registro.
  3. Añadimos el efecto de la factura como linea con lo que en el caso de caja el campo «Importe» de la linea se rellena con el total del efecto y en el caso de banco sucede lo propio con el campo «Imp.declarado».
  4. Si nos fijamos estos campos son editables así que una vez aplicado el parche podremos modificar dicha cantidad y en su lugar poner un valor entre 0 y el total del efecto.
  5. Procesamos el «Extracto bancario» o el «Diario de caja»

Nota 1: En cualquiera de los dos casos, banco o caja, al guardar la linea con el nuevo importe el efecto de dicha linea automáticamente será substituido por uno nuevo que refleje esa cantidad, por lo tanto si volvemos a modificar la cantidad y ponemos un valor entre 0 y el nuevo importe se volverá a repetir el procedimiento.

Nota 2: En este punto la única forma de volver atrás es desprocesando la entrada de caja o banco, eliminando la linea y por último desprocesar y eliminar la liquidación que se ha generado de forma automática por debajo.

Como se decía al principio el propósito de este desarrollo es agilizar los pagos parciales evitando tener que hacer una liquidación de forma manual. El atajo consiste simplemente en que en el momento de cobrar indicas una nueva cantidad y es el sistema el que hace la liquidación de forma automática por debajo dejando todo listo para que sólo tengas que procesar el banco o caja.

Ahora veamos como aplicar el cambio. Lo primero que debemos hacer es descargarnos el parche:

partialpayments.tar.bz2

partialpayments.tar.bz2.md5

Después de copiar estos dos archivos al raiz del código fuente de nuestra instalación de Openbravo ERP debemos comprobar que se han bajado correctamente:

md5sum -c partialpayments.tar.bz2.md5

Si todo esta bien ya podemos descomprimir y desempaquetar el parche:

tar xvfj partialpayments.tar.bz2

Y por último debemos actualizar nuestra base de datos:

ant update.database

Ya sólo queda decir que este parche está bajo licencia gpl versión 3.

 

Nota: Se ha elminado el archivo ya que sólo es compatible con versiones antiguas de la 2.40.

 

Cheli