Entradas

Mostrando las entradas con la etiqueta sugerencias

DGI, facturación y declaraciones juradas

Imagen
En Uruguay, la DGI (Dirección General de Impositiva), es quien se encarga de recaudar los impuestos de las empresas y las personas físicas. Existe una modalidad, que es la que usamos los profesionales, que se llama Empresa Unipersonal, para las cuales el flujo de trabajo es el siguiente (no conozco como funcionan las demás, pienso que deben ser más complicadas): La empresa hace facturas a sus clientes, sin que la DGI se entere Una vez por mes o cada dos meses (depende de la modalidad de la empresa) se pagan los impuestos: IVA, IRAE, IRPF o lo que corresponda. Para el pago la empresa tiene que imprimir un boleto de pago en blanco, lo llena con los importes que correspondan, y paga eso. Todo esto sin intervención de la DGI, o sea, cada uno paga "como quiere". Una vez al año o cada 6 meses (depende de la modalidad de la empresa), se hace una declaración jurada donde uno declara lo que facturó, lo que compró y los pagos que hizo. Esto es un papel que es totalmente independi...

Código repetido: cálculo del valor en varias monedas

Siguiendo con la inteción de minimizar el código repetido en la base de conocimiento, me encuentro ante un problema que no tengo del todo claro como resolver. Capaz que a alguien se le ocurre alguna solución que no estoy viendo :) En varios lugares de la KB, se manejan valores de productos en tres monedas, llamémosles &Moneda1, &Moneda2 y &Moneda3. Las monedas 1 y 2 son siempre distintas entre sí. La moneda 3 puede ser igual a la 1, igual a la 2, o no coincidir con ninguna. Entonces, el código que se repite es el siguiente: &Valor1 = udp(PAlgunProc, &Moneda1, [otros parámetros]) &Valor2 = udp(PAlgunProc, &Moneda2, [otros parámetros]) if &Moneda3 = &Moneda1     &Valor3 = &Valor1 else     if &Moneda3 = &Moneda2         &Valor3 = &Valor2     else         &Valor3 = udp(PAlgunProc, &Moneda3, [otros parámetros])     endif...

Algoritmos sobre SDTs en GeneXus

Imagen
Los SDTs en GeneXus (Structured Data Type) tienen cierto grado de felxibilidad, pero creo que como están hoy, no es suficiente. Nota: lo que sigue es basado es el conocimiento que tengo de los SDTs en GeneXus 9.0. Creo que no se hizo ninguna mejora significativa en este sentido en las versiones posteriores... Supongamos que tengo un algoritmo que recibe dos SDTs de cierto tipo, los compara y devuelve otros dos SDTs con las diferencias. Es un algoritmo que se pensó bien, se analizaron las condiciones de borde, se testeo, está funcionando en producción. El problema es que ahora preciso hacer lo mismo con otro SDT con otra estructura distinta... ¡Y para hacerlo tengo que repetir la programación de mi algoritmo! Esto claramente no es lo más eficiente... Lo que me gustaría, sería tener una sola versión del algoritmo, que pudiera invocar con distintos tipos de SDTs. De alguna forma debería poder: definir variables de tipo "SDT Collection", genéricas, que se pudieran reci...

Definición de variables en GeneXus

Imagen
En GeneXus, las variables se debe definir indicando el tipo de datos y en algunos casos el largo y la cantidad de decimales. Con esto, estamos ayudando de alguna forma al especificador/generador, que ya sabe de que tipo tiene que definir cada una. Pero en realidad, ¿no debería ser al revés? ¿No debería el especificador solucionarnos los problemas? En algunos casos GeneXus infiere el tipo de las variables, como por ejemplo cuando se llama igual que un atributo, o cuando termina con el nombre de un dominio. Hay otros casos donde los infiere el especificador, pero dando un warning, y en realidad no quedan definidas en el objeto. Por ejemplo, cuando asignamos una valor a una variable que no fue definida. Lo que propongo en realidad es mucho más genérico: que no haya que definir ninguna variable. El especificador debería validar que se usen correctamente (que no se asigne un char a una variable que antes se asignó un número, por ejemplo) y dar errores si corresponde. Otro contro...

Herencia en GeneXus

Imagen
Cuando hablamos de herencia, en GeneXus, en general nos referimos a la herencia entre las distintas entidades. Por ejemplo, Estudiante es una Persona, y los defino con subtipos. En este caso en realidad quiero hablar sobre la herencia entre objetos... que en GeneXus es prácticamente inexistente. Lo único que existe (hasta donde yo se), son los objetos de tipo Style, donde se pueden definir propieades, componentes del form y eventos, que luego son heredados al crear un objeto basado en dicho style. El problema con esta herencia (para el código) es que es solo al momento de crear el objeto, pero luego no se mantiene. Además el código heredado queda en el objeto "hijo" como una copia del código del objeto "padre". Sería bueno poder tener herencia de verdad. Es decir, tener un objeto que tenga el código común, y que los demás puedan heredar de este, sin copiar el código a cada uno de los objetos "hijos". Un claro ejemplo de esto es en el pattern WorkWi...

Application Stores

Parece que el tema de las App Stores está de moda... Ahora parece que Google suma una nueva , para aplicaciones que se integren a Google Apps (mail, docs, calendario, etc.). El negocio es siempre el mismo: el dueño de la tienda pone a la venta aplicaciones de terceros, y cuando un usuario compra la aplicación, una parte va para el desarrollador y la otra para la empresa. La ventaja que tiene, viéndolo desde el punto de vista del desarrollador, es que la aplicación queda a la venta y accesible para cualquier usuario, sin tener que invertir en infraestructura ni preocuparse demasiado por el medio de pago y demás. Esta posibilidad de acceder a un número importante de usuarios, ha hecho que por ejemplo en la App Store de Apple , las aplicaciones valgan (en su mayoría), unos pocos dólares. Esto hace que haya muchos usuarios que las compran... ¿A que voy? Sería muy bueno tener una GeneXus App Store, para user controls, extensions, patterns, etc. Esta idea en realidad ya se había...

Buscar un elemento dentro de un SDT en GeneXus

En GeneXus, no hay una forma de buscar un elemento dentro de una colección (SDT), que no sea recorriendo toda la lista. Hay una función IndexOf , pero compara referencias y no el contenido de los elementos. Ejemplo: &esta = Boolean.False for &depUbiItem in &depUbis     if &depUbiItem.DepId = &DepId and &depUbiItem.CicUbiId = &CicUbiId         &esta = Boolean.True         exit     endif endfor Esto no parece ser lo más elegante... No debería necesitar 7 líneas de código para saber si un elemento está en la colección, lo debería poder hacer en una sola línea. El problema es que dado un SDT, GeneXus no tiene forma de saber cuales son los elementos que quiero comparar. En el ejemplo, estoy comparando DepId y CicUbiId, pero el SDT tiene varios campos más. Una posibilidad sería poder definirle comportamiento a los SDTs, de forma de poder decirle cu...

Atributos y controles como parámetro en GeneXus

Imagen
Capaz que el título no dice mucho, es dificil explicar lo que quiero en una línea... Todos sabemos que es una buena práctica de programación, reutilizar código siempre que sea posible. En GeneXus X con los data selectors se dio un gran paso, pero hay cosas que me siguen faltando. Por ejemplo, tengo el siguiente código que borra los datos de tablas referenciadas, cuando borro una determinada entidad (sí, seguro que es más prolijo hacer un Business Component y borrar con eso, pero no es el punto). ¿Se ve el patrón de código repetido? El problema es que no tengo forma de unificar el código en un procedimiento o subrutina, de forma de pasarle solamente el atributo que va en el defined by . Seguramente no es fácil de implementar, pero sería interesante. Otro caso donde pasa algo similar, es con los controles en pantalla. Por ejemplo, recibo unas variables por parámetro, si vienen cargadas las muestro en el form deshabilitadas, y si no las muestro habilitadas. El código es el...

Pasaje de parámetros entre objetos GeneXus

Acá dejo dos sugerencias con respecto al pasaje de parámetros entre objetos GeneXus: parámetros opcionales parámetros nominados Parámetros opcionales Muchas veces pasa que se agregan parámetros a un objeto GeneXus, porque se precisa pasarlos desde uno de los llamadores, pero no queremos que el resto de los programas llamadores cambien. Lo que hacemos hoy es modificar todos los llamadores, agregando un nuevo parámetro con un valor que sería el valor por defecto. Sería bueno tener la posibilidad de definir que un parámetro es opcional e indicarle cual es el valor por defecto. La definicón podría ser algo así: parm(in:&par1, in:&par2=0, out:&result); En este ejemplo el parámetro &par2 sería opcional, y si no se especifica el valor que se usaría en el objeto sería cero, que es el valor que se le da por defecto. La invocación podría ser así, si se quiere usar el valor por defecto: &result = Programa.udp(1) o así, si se quiere especificar otro valor: ...

Mensajes y formato de strings

Ahora que descubrí la función Format() en GeneXus y que la empecé a usar... creo que se le podría hacer una mejora. La mayoría de las veces, cuando armamos un string, lo queremos para mostrar un mensaje. Muchas veces es para pasárselo a la función msg() o a la función error(). Algo así: &mensaje = Format('El pedido número %1 fue confirmado', PedidoId.ToString()) msg(&mensaje) o simplemente msg( Format('El pedido número %1 fue confirmado', PedidoId.ToString()) ) Sería más práctico e intuitivo, que las funciones msg() y error() recibieran una cantidad variable de parámetros y se comportaran como la función Format(). El código quedaría entonces más simple: msg( 'El pedido número %1 fue confirmado', PedidoId.ToString() )

Valor "Empty" para atributos con dominio en GeneXus

Supongamos que tengo un dominio ESTADO, definido como Char(3), que puede tener valores {'ING', 'ABI', 'CER'} (ingresado, abierto, cerrado). Si fuera una KB nueva posiblemente usaría un dominio enumerado con {ingresado=0, abierto=1, cerrado=2}. Pero no es el caso, y además no siempre es posible elegir los valores que va a tener un dominio, puede depender de otra aplicación o ser una base de datos que ya tiene valores. El problema que tengo, es que si defino una variable o un atributo basados en ese dominio, el valor "empty" (como en IsEmpty() o en SetEmpty()) es '', que no es un valor válido para el dominio. Estaría bueno poder definir cual es el valor "empty" de un dominio... Este valor además sería el "initial value" por defecto para los campos nuevos basados en dicho dominio, y sería el valor con el que se graban los registros nuevos cuando no se referencia el atributo (y se tiene la propiedad "initialize not re...

Objetos que devuelven más de un valor en GeneXus

En GeneXus no tenemos el concepto de función como tenemos en Java o en C#, donde tiene que haber un tipo de datos que es el que devuelve, como en: private int foo() { return 1; } Por el contrario, en GeneXus los parámetros de un objeto pueden ser de entrada, salida o entrada/salida, en cualquier cantidad y orden. (*) Por ejemplo, podría tener una función que dado un producto me devuelve el saldo en cantidad y en importe, de dicho producto en el depósito. (**) La regla parm sería por ejemplo: parm(in:ProductoId, out:&SaldoCantidad, out:&SaldoImporte); Pero entonces, ¿cómo invoco ese programa?. Hay varias opciones, puede ser con call , o incluso con udp ... call(PGetSaldoProducto, ProductoId, &SaldoCantidad, &SaldoImporte) o &SaldoImporte = udp(PGetSaldoProducto, ProductoId, &SaldoCantidad) En una nota hace un tiempo, hablando sobre la legibilidad del código , comentaba sobre la ventaja de usar udp en vez de call ... Pero en este caso las dos opciones s...

When duplicate y campos con índice unique

Si en GeneXus (9.0) se tiene una tabla con un índice unique y se hace un for each que actualiza el campo del índice, al especificar da un warning que dice: spc0070: No When duplicate code found to handle possible duplicate condition when updating [Atributo] La documentación del comando for each en el Wiki, dice lo siguiente con respecto al when duplicate : When duplicate : This clause only makes sense in procedures (because it has to do with updates); it is analyzed below. This clause will be executed if, within the body of the For Each (code1), you try to update an attribute that is a candidate key (it has a unique index) and a record with that value already exists. GeneXus uses the unique index to ensure the uniqueness of that candidate key and in case it finds duplicates, if this clause is programmed in the For Each command, it will execute its code: code2. If the clause is not included, and you try to update an attribute that is a candidate key and a record with that value alre...

Comando "do case" en GeneXus

El comando do case de GeneXus tiene una sintaxis que no me termina de convencer... El problema es que las condiciones de cada case pueden ir sobre variables distintas. Más que un do case , la sintaxis permite usarlo como un if-elseif . En Java y C#, el comando equivalente es el switch , que discrimina según los valores que toma una variable dada. Por ejemplo: switch (variable) {     case 1:         // hago algo para el valor 1         break;     case 2:         // hago algo para el valor 2         break;     default:         // hago algo para los demás valores         break; } En GeneXus, el do case me permite hacer cosas como do case {     case &variable = 1 :      ...

Bloques de reglas en transacciones GeneXus

Una cosa que me gustaría tener en GeneXus, son bloques de reglas. Muchas veces pasa que tenemos varias reglas en una transacción que se ejecutan con las mismas condiciones. Un ejemplo sencillo: msg('Atención: el atributo Att queda con valor "valor"') If [condiciones] on AfterValidate; Att = "valor" If [condiciones] on AfterValidate; Me gustaría poder escribir estas líneas como: { msg('Atención: el atributo Att queda con valor "valor"'); Att = "valor"; } If [condiciones] on AfterValidate; El inicio y fin de bloque no tienen por que ser con { y }, es solo un ejemplo. Me parece que el código quedaría mucho más fácil de leer, sobre todo teniendo en cuenta que ahora las reglas pueden estar separadas por otras reglas en el código. Otra cosa que estaría bueno es poder decirle a GeneXus que las reglas de un determinado bloque se ejecuten en el orden que están escritas, pero eso ya me parece más difícil de conseguir.