¡Hola a todos! Pasó mucho tiempo desde que publiqué mi última entrada… el motivo fue que, por suerte, anduve con muchísimo trabajo. Ahora soy freelance a tiempo completo y decidí volver a darme tiempo para continuar con este blog.

En la entrada de hoy, voy a explicar un tema que suele ser complicado empezar debido a la falta de documentación: crear un User Control para Genexus. Como ejemplo de creación, haremos un menú desplegable. Comencemos.

Preparando el entorno.

Lo primero que tenemos que hacer es prepararnos para crear el User Control. Para esto tenemos dos alternativas: usar el UserControlEditor que viene instalado por defecto junto con Genexus; o usar el plug-in GeneXus Usercontrol Generator para el editor Atom. Vamos a optar por la segunda opción.

Descargamos e instalamos Atom en nuestro equipo. Lo pueden descargar desde su página oficial: https://atom.io/.

Luego de instalado, ejecutamos Atom y nos dirjimos a File -> Settings -> Install. Ahí buscamos el package genexus-usercontrol-generator. Nos aparecerá el plug-in creado por GenexusLab. Le damos en Install y esperamos.

Una vez finalizada la instalación, podremos ver que se nos agregó un nuevo package en el menú Packages.

Analizando la solución

Antes de crear nuestro User Control, tenemos que entender el problema y la solución. El problema que tenemos es que necesitamos un menú drop-down para nuestra aplicación web Genexus. Este menú debe permitir desplegar hasta 3 niveles (Item menú Nivel 1 -> Sub item nivel 2-> Sub item nivel 3). Como no tenemos la intención de crear algo desde 0, vamos a buscar algo en la web y adaptarlo a nuestra aplicación.

No fue difícil encontrar este menú que se ajusta bastante bien a nuestro problema: https://codepen.io/philhoyt/pen/ujHzd. Lo interesante de esta solución es que solo utiliza CSS. Solo le haremos una pequeña modificación: Agregar la siguiente línea dentro de #primary_nav_wrap ul:

z-index: 999

Esta línea hará que el menú desplegable quede por encima del resto.

En cuanto a la estructura de datos que necesitamos para nuestro menú, deberá soportar una descripción y un link. Además deberá soportar los 3 niveles que mencionamos anteriormente. Podríamos tener la siguiente estructura de ejemplo:

Estructura menú

Para esto, crearemos un SDT de la siguiente manera:

SDT Menú

Como necesitamos que este SDT exista en la KB cuando usemos el UC, vamos a crear un XPZ y anexarlo a nuestro controlador para que se importe de manera automática. Por ahora nos limitamos a hacer el export, luego veremos cómo agregarlo al controlador. Nombramos al XPZ como SDTDropDownMenu.xpz.

Export

Creando el User Control

Lo primero que debemos hacer es abrir Atom, ir a Packages -> Genexus -> Create User Control. Como nombre elegimos DropDownMenu, ponemos una descripción, como Type seleccionamos Common, tildamos la plataforma Web y en path elegimos dónde queremos que se guarden nuestros archivos. Luego presionamos Enter y esperamos unos segundos.

Estructura

Nos creará la siguiente estructura de archivos:

Estructura de archivos

Nos interesan los archivos que se encuentran dentro de la carpeta src que son los que editaremos y luego usaremos para instalar el controlador en Genexus.

Hasta aquí ya tenemos un UC creado que lo único que hace (si lo instaláramos) es mostrar un «Hola Mundo!» simple. Vamos a editarlo para que nos muestre el menú en lugar de eso.

Personalizando el User Control

Primero editaremos el archivo DropDownMenu.control. Aquí se encuentran las configuraciones generales del UC, entre las que podemos destacar el nombre, el número de versión, los archivos asociados, los eventos, métodos y acciones. En nuestro ejemplo, solo necesitamos agregar los archivos necesarios para que nuestro UC funcione. Estos archivos son el SDTDropDownMenu.xpz y CSS del menú que vamos a implementar (lo nombraremos DropDownMenu.css).

Copiamos el archivo SDTDropDownMenu.xpz y el archivo DropDownMenu.css en el directorio raíz (src).

Ahora agregamos la siguiente linea en el archivo DropDownMenu.control (debe estar dentro de la etiqueta ControlDefinition, por ejemplo luego de la etiqueta DesignRender):

<GxResources>SDTDropDownMenu.xpz</GxResources>

Esta línea hará que cuando arrastremos el UC en nuestro web panel se cree el SDT que definimos anteriormente.

Luego localizamos la etiqueta <ReferencedFiles /> y la reemplazamos por:

  <ReferencedFiles>

    <File>DropDownMenu.css</File>

  </ReferencedFiles>

Con esto logramos que se importe el CSS que descargamos del menú.

Nos toca editar el archivo DropDownMenuProperties.xml. En este archivo, como su nombre lo indica, se definen las propiedades que soportará el UC. En nuestro caso, solo necesitamos pasarle el SDT que creamos anteriormente, por lo que tendremos una sola propiedad. Dentro de la etiqueta <Children> pondremos lo siguiente:

<Prop>

  <Id>Menu</Id>

  <Name>Menu</Name>

  <Type>Custom</Type>

  <CustomType> Artech.GeneXus.Common.CustomTypes.ControlAttVarReference, Artech.GeneXus.Common </CustomType>

  <Metadata>

    <Value name="FlagSetValueMethod">SetMenu</Value>

    <Value name="FlagGetValueMethod">GetMenu</Value>

    <Value name="FlagDataTypeFilter">SDTDropDownMenu</Value>

  </Metadata>

</Prop>

Con esto estamos diciendo que el controlador tendrá una propiedad llamada Menu que es de un tipo Custom (definido por el usuario), usará los métodos SetMenuGetMenu (luego veremos) para manipular sus datos, y el tipo de datos será SDTDropDownMenu.

Ahora debemos modificar el archivo DropDownMenuProperties.js que es un JavaScript que hace toda la «magia». Por defecto vemos que nos crea un método show y un método destroy. Estos se ejecutan justamente cuando se muestra el UC o se destruye. Nos interesa en este caso solo el show. Dentro de este método hay un llamada al setHTML, que pone una etiqueta <h1> con la frase «Hello world!«. Lo que nosotros debemos hacer en este punto es, en lugar de poner esa etiqueta, poner toda la estructura HTML que muestra el menú. Además tenemos que crear los métodos SetMenuGetMenu que definimos anteriormente.

No voy a entrar en detalles de cómo está construida la parte que forma el HTML porque se entiende con ver el código. Solo diré que en la variable html se guarda todo el menú en formato HTML con sus links y descripciones y luego se muestran con setHTML.

Respecto a las funciones SetMenuGetMenu, también se entiende claramente lo que hacen. Simplemente SetMenu pasa el SDT a la variable de JavaScript y GetMenu obtiene su valor.

Aquí dejo el código:

function DropDownMenu($)
{
 this.show = function()
 {
   var html = '';
   html += '<nav id="primary_nav_wrap">';
   html += '  <ul>';
   for (var i = 0; i < this.Menu.ItemsNivel1.length; i++)
   { 
     html += '<li><a href="' + this.Menu.ItemsNivel1[i].Link + '">' + this.Menu.ItemsNivel1[i].Descripcion + '</a>';
     html += '<ul>';
     for (var j = 0; j < this.Menu.ItemsNivel1[i].ItemsNivel2.length; j++)
     {
       html += '<li><a href="' + this.Menu.ItemsNivel1[i].ItemsNivel2[j].Link + '">' + this.Menu.ItemsNivel1[i].ItemsNivel2[j].Descripcion + '</a>'; html += '<ul>';
       for (var k = 0; k < this.Menu.ItemsNivel1[i].ItemsNivel2[j].ItemsNivel3.length; k++)
       {
         html += '<li><a href="' + this.Menu.ItemsNivel1[i].ItemsNivel2[j].ItemsNivel3[k].Link + '">' + this.Menu.ItemsNivel1[i].ItemsNivel2[j].ItemsNivel3[k].Descripcion + '</a></li>';
       }
      html += '</ul>';
      html += '</li>';
     }
     html += '</ul>';
     html += '</li>';
   } 
   html += '    </ul>';
   html += '</nav>';
   this.setHtml(html);
 }
 this.destroy = function() 
 {
   // Add your cleanup code here. This method will be called when the control is destroyed. 
 }
 
 this.GetMenu = function() 
 {
  return this.Menu; 
 }

 this.SetMenu = function(data)
 {
   this.Menu = data; 
 }
}

Con esto ya es suficiente para que funcione nuestro controlador. También podríamos editar el archivo DropDownMenuRender.xsl para cambiar el icono por ejemplo (helloworld.gif), pero no es necesario.

Instalando el User Control

Nuestro User Control final se encuentra dentro de la carpeta src que terminó con la siguiente estructura:

Estructura

Lo que nos queda hacer es copiar todos los archivos de src en una nueva carpeta que se llame DropDownMenu. Luego procedemos a instalarlo como se hace con cualquier User Control.

Se cierra Genexus, se copia la carpeta DropDownMenu dentro de la carpeta UserControls donde está instalado Genexus, se corre el comando Genexus.exe /install y se vuleve a abrir Genexus.

Probando nuestro User Control

Para probarlo vamos a meterlo en la MasterPage ya que se trata de un menú. Vamos al Web Form de nuestra MasterPage, buscamos en la Toolbox en la sección Miscellaneous y veremos que está DropDownMenu:

Toolbox

Lo arrastramos a la parte del Web Panel que deseemos que aparezca. Dentro de las propiedades, vemos que nos aparece una que se llama Menu. Es la que definimos que contendrá el SDT. Al momento de arrastrar el UC al Web Panel, se creó en nuestra KB el SDT que definimos anteriormente. Entonces debemos declarar una variable que sea de este tipo y la ponemos en la propiedad Menu.

Propiedades

También podemos hacerlo por código con:

DropDownMenu1.Menu = &SDTDropDownMenu

Ahora lo que debemos hacer es inicializar el SDT con los valores del menú. Para ello lo podemos hacer con un Data Provider, con un Procedure, o directamente en el Event (queda a gusto y placer del programador). En este caso muestro una carga sencilla con un Data Provider que luego es llamado en el Event Start:

Data Provider

Ahora con una simple llamada en el Event Start a este Data Provider ya tendremos nuestro menú listo:

&SDTDropDownMenu = DPDropDownMenu.Udp()

Nuestro resultado final:

Resultado

Claramente se puede mejorar mucho la parte estética y dependerá de la aplicación en donde vamos a usar este menú. Para ello solo será necesario tocar el archivo CSS que nos descargamos anteriormente.

Pueden bajar el código en este enlace: User control Drop Down Menu

Espero que les sea de utilidad.

¡Saludos!

Hola a todos. Antes que nada, mil disculpas por la terrible demora de esta entrada, no me pude dar tiempo para escribirla completamente. Ahora, aprovechando el feriado de carnaval y que el calor que hace no te deja salir ni a la puerta, por fin la completo.

A modo de resumen de lo que tenemos hasta ahora: Ya definimos las entidades básicas de nuestro sistema: Localidad, Marca, Unidad, Categoría y Artículo. Para cada una hicimos su correspondiente ABM. Utilizamos Bootstrap para darle una mejor apariencia a nuestra aplicación. Implementamos una seguridad básica con Devise. Gracias a typeahead.js logramos mejorar el modo de selección de Marca para la entidad Artículo. Todo está subido en un ambiente de producción en Heroku (http://shopgm.herokuapp.com/).

Ahora vamos a proceder a trabajar con la entidad Venta. Esta es la más compleja de las entidades que tenemos hasta ahora, pues es una entidad «anidada» (cada Venta contiene uno o varios Detalles de Venta que, a su vez, están asociados a un Artículo). Tenemos que brindar al usuario final una forma de ingreso de artículos que sea lo más rápida posible, ya que de otra manera se retrasarían las ventas en el local y esto podría hacer que ciertos clientes se vayan sin comprar. Teniendo esto en cuenta, empecemos.

Continúa leyendo

¡Hola! Hoy les presento la quinta parte de la serie de entradas para la creación de un Sistema de Gestión de Negocios con Ruby on Rails 5.

 

Nuevamente me toca pedir disculpas por la demora en la entrega, lo que pasa es que al estar cerca de fin de año hay muchas cosas que ocupan mi tiempo y lamentablemente no pude dedicarme tanto como me gustaría a mi blog.

En la entrada de hoy, vamos a crear el modelo, la vista y el controlador para Artículos. Es un formulario un tanto distinto a los que vimos hasta ahora porque está relacionado con otras entidades que ya desarrollamos (Marca, Unidad y Categoría). Además, utilizaremos la librería typeahead.js para facilitar la selección de la Marca del artículo (luego la volveremos a utilizar con un poco más de complejidad en el formulario de Ventas). Esta librería brinda al usuario una lista de sugerencias a medida que ingresa valores en un campo de texto, de esta manera evitaremos el uso de un popup o un combo box para la selección de la Marca.

Continúa leyendo

¡Hola! Hoy les presento la cuarta parte de la serie de entradas para la creación de un Sistema de Gestión de Negocios con Ruby on Rails 5.

Antes que nada, pido disculpas por la demora en esta entrega, estuve muy complicado con el tiempo. La buena noticia es que el proyecto ya está disponible en Heroku. Pueden visitar el siguiente enlace: http://shopgm.herokuapp.com/

Una cosa que me faltó mencionar en la entrada anterior es que al momento de insertar o actualizar una Marca, se cambió la ruta a la que redirecciona, llevando a la lista de Marcas en lugar de a la vista de la Marca recién creada/actualizada.

Una vez aclarado esto, podemos empezar.

Continúa leyendo

¡Hola! En esta entrada voy a explicar cómo solucioné el problema de la validación de datos y búsqueda ignorando acentos que me encontré mientras desarrollaba el Sistema de Gestión de Negocios con Ruby on Rails 5.

Escenario

Tenemos un modelo (que llamaremos Brand – por Marca -), que debe tener un nombre único en nuestra aplicación, ignorando mayúsculas, acentos y caracteres especiales (por ejemplo, si ya existe «Doña Marca», no debe permitir el ingreso de «Dona Marca», ni «dona marca»). A su vez, cuando se realizan búsquedas se deben ignorar las mayúsculas, acentos y caracteres especiales (es decir que al buscar por «dona marca» debe mostrar «Doña Marca»).

 

Entorno

  • Ruby on Rails 5
  • Ruby 2.3.1
  • PostgreSQL 9.5

 

Solución

Asumo que ya tenemos instalado y configurado PostgreSQL en nuestro sistema, ya que esta entrada no tiene como objetivo explicar esto. Se pueden encontrar muchos tutoriales en la web que explican cómo hacerlo en diferentes sistemas operativos.

Continúa leyendo

¡Hola! Hoy les presento la tercera parte de la serie de entradas para la creación de un Sistema de Gestión de Negocios con Ruby on Rails 5.

En la segunda parte logramos configurar algunas de las gemas y herramientas que vamos a utilizar en nuestro desarrollo. También implementamos una versión inicial del modelo de Usuario y configuramos la seguridad básica del sistema.

Ahora vamos a ajustar la apariencia de nuestra aplicación y a crear un modelo de Marcas para tener como base para la creación del resto de los modelos. Empecemos.

Estilo base

Gracias a Bootstrap, no necesitamos ser expertos en CSS para obtener una interfaz de usuario que sea aceptable para el usuario. Por supuesto, si disponemos de habilidades (y buen gusto), podemos alcanzar resultados mejores.. pero por ahora solo nos vamos a ocupar de utilizar las herramientas que nos proporciona Bootstrap tocando muy poco el CSS.

Continúa leyendo

¡Hola! Hoy voy a continuar con la segunda parte de la implementación de un Sistema de Gestión de Negocios con Rails 5. Se puede visitar la primera parte haciendo click aquí.

Con el entorno de trabajo listo y el proyecto shop recién creado, vamos a realizar las primeras configuraciones para desarrollar nuestro sistema.

Base de Datos

Para nuestro proyecto utilizaremos PostgreSQL, un motor de bases de datos relacionales de código abierto. Al momento de crear nuestro proyecto, dejamos las configuraciones por defecto y esto hizo que nuestra aplicación utilice SQLite. Para cambiar a PostgreSQL, debemos hacer dos modificaciones en nuestro archivo Gemfile:

Comentar la linea gem 'sqlite3' en shop/Gemfile:

# gem 'sqlite3'

Y agregar la siguiente linea:

gem 'pg'

Luego ejecutamos el comando:

$> bundle install

Ahora debemos actualizar nuestro archivo shop/config/database.yml para indicarle nuestra nueva configuración. En mi caso, creé un nuevo usuario shop en PostgreSQL que usaré exclusivamente para este sistema. Es posible usar el usuario por defecto, postgres, pero no es recomendable. En caso de que optes por crear un nuevo usuario y no sepas cómo, puedes seguir este tutorial.

Actualizamos el archivo database.yml de la siguiente manera:

Continúa leyendo

¡Hola! El 30 de Junio pasado se liberó la tan esperada versión 5.0 de Rails trayendo consigo una serie de importantes mejoras (ver más) .

Para hacer una transición a esta nueva versión, voy a crear un Sistema de Gestión de Negocios desde 0 y compartir con ustedes esta experiencia. Voy a intentar construir un sistema relativamente completo y que sea utilizable en la vida real para aprovechar y cambiar el sistema del negocio de mi padre. Para estoy voy a escribir una serie de entradas en las que voy a ir explicando el paso a paso de la construcción.

En esta primera parte, voy a presentar el problema, realizar una breve descripción de las principales funcionalidades, configurar el entorno de trabajo y construir el proyecto en Ruby on Rails 5.0 y Ruby 2.3.1. Empecemos:

Presentación del Sistema de Gestión de Negocios

Mi padre tiene un negocio en un pequeño pueblo en una provincia del norte de Argentina (Salta). En este negocio se venden diversos artículos: comestibles, perfumería, farmacia, ferretería, corralón, etc. (un típico negocio de pueblo, multi-rubro y donde se consigue de todo). Los clientes que tiene son, en su mayoría, conocidos del pueblo. A algunos de estos clientes, le ofrece sacar mercadería al fiado (es decir, que pueden llevar mercadería comprometiéndose a pagarla al cabo de cierto tiempo, una costumbre muy argentina 😉 ). La forma de anotar estas ventas es a través de libretas o «boletas» en las que se anotan las mercaderías llevadas sin reflejar el precio y luego, al momento de pagar se calcula la deuda.

Si bien el negocio tiene muchos años funcionando bien (lo creó mi abuelo cuando mi padre era un niño), las mejoras que se pueden incorporar utilizando un sistema informático son muchas, entre las que podemos destacar:

Continúa leyendo

¡Hola! Antes que nada, gracias por visitar mi blog.

Mi nombre es Germán Martínez y estoy iniciando este blog para compartir con la comunidad la forma en la que resuelvo ciertos problemas con los que me encuentro en mi labor diaria. Estos no se limitan a una sola tecnología ni a una sola área en particular… incluye temas de programación (Ruby on Rails, Android, etc.), generadores de código (Genexus), análisis estratégico de datos, economía y experiencias de vida. Quizás lo que presente no sea algo nuevo, ni la mejor manera de hacerlo, pero son soluciones que a mi me sirvieron y las considero prácticas.

Soy informático de profesión. Actualmente como programador Genexus en una empresa argentina, pero tengo experiencia laboral en diversas organizaciones: desde equipos de trabajos con amigos para proyectos personales, pasando por una PyME en el norte del país, hasta una corporación multinacional interactuando con equipos distribuidos en diversas partes del mundo. Ahora estoy planeando iniciarme como programador freelance, por lo que me estoy perfeccionando en Ruby on Rails y Android.

Espero que la información que comparta le sirva a alguien. Si lo que presento no es la mejor solución y conocés otra, agradezco que lo comentes así aprendo de tu experiencia.

Estamos en contacto.