En algunas ocasiones nos enfrentaremos a situaciones en las que es necesario obtener varios valores de devolución en un solo método, por ejemplo, obtener los valores alto y ancho de un control en una sola llamada a un método.
Hoy vamos a crear un método de una clase que permita devolver un registro de InventJournaTable e InventJournalTrans correspondientes a un JournalId usado como parámetro.
Primero, invocaremos a la creatividad para buscar el mejor nombre para esta clase... después de un par de tensos segundos tenemos la respuesta, la llamaremos TestMultiple, y bueno, el método se llamará getDiarioInventario.
01 Container getDiarioInventario(JournalId _journalId)
02 {
03 InventJournalTrans inventJournalTrans;
04 ;
05 select * from inventJournalTrans
06 where inventJournalTrans.JournalId == _journalId;
07
08 return [InventJournalTable::find(_journalId), inventJournalTrans];
09}
Lo interesante de éste método, es el tipo de devolución Container, y la intrucción return, que devuelve dos objetos, ahora vamos a ver como usarlo.
01 static void main(Args _args)
02{
03 InventJournalTable inventJournalTable;
04 InventJournalTrans inventJournalTrans;
05 ;
06
07 [inventJournalTable , inventJournalTrans] = new TestMultiple().getDiarioInventario("INVJ295691");
08
09 info (inventJournalTable.JournalId + " - " + inventJournalTrans.JournalId );
10 }
Quedó coqueto... ¿No les parece?.
Tuesday, November 25, 2014
Friday, November 21, 2014
SetTimeOut, autologOff y la clase Info
Como ya sabemos, Ax permite configurar un parámetro llamado 'Parada Automática' (AutologOff) en la tabla de usuarios (UserInfo).
Lo anterior permite al sistema liberar/terminar la sesión de un usuario por inactividad, es decir, el sistema sabe cuando nada más lo tienes abierto y no ejecutas acciones en el, así que manos a la obra que esas pólizas no se van a capturar solas, o bien, tal vez eres de esos programadores que códifican con la mirada (cómo yo), un talentoso desarrollador adelantado a su época.
¿Cómo lo hace Ax?
Pues bien, la clase Info tiene un método misterioso llamado workSpaceWindowCreated, ahí, Ax inicia algunas tareas que se ejecutan en segundo plano, una de ellas es la llamada a autologOff, pero a traves de la instrucción setTimeOut, donde establece un intervalo de ejecución y además el parámetro _idle inicializado en true.
Con esadiabólica configuración, esa tarea se ejecutará cuando el intervalo se cumpla mientras halla inactividad por parte del usuario.
Seguro a quienes tienen configurado el parámetro AutologOff habrán experimentado el cierre de la sesión sin previo aviso, así que les mostraré como poner un aviso antes de que esto pase, o si no tienen un tiempo de 'Parada Automática' el sistema les avisará de todos modos.
Lo primero es diseñar un mensaje bonito, pero como no soy diseñador, entonces simplemente sacudiremos la ventana de Ax (para que se desempolve), ésto quedará añadido en un método de la calse Info
01 void shake()
02 {
03 int hWnd, i, x, y, w, h;
04 Random random;
05 UserInfo userInfo;
06 ;
07
08 if (!isFirstExec)
09 {
10
11 hWnd = infolog.hWnd();
12 [x,y,w,h] = winapi::getWindowRect(hWnd);
13
14 random= new Random();
15
16 for (i = 0; i<200;i++)
17 winapi::setWindowPos(hWnd,1+(random.nextInt()/1000),1+(random.nextInt()/1000),w -20,h-20);
18
19 winapi::setWindowPos(hWnd,0,0,w,h);
20 }
21 this.setTimeOut(identifierstr(shake), #shakeInterval*60, true);
22 isFirstExec=false;
23}
En la línea 08 me aseguro de que la primera vez que se llame no se ejecute la sacudida, ésto porque lo haré en el arranque, luego, obtengo el hWnd en la línea 11 y después algunos datos de la ventana (línea 12).
En la línea 16 y 17 le establezco la posición con valores aleatorios, y en la 19 dejo la ventana como estaba.
En la 21 vamos a hacer recursiva la tarea.
Previamente definimos el shakeInterval con 2000 y declaramos la variable isFirstExec;
Y para llamarla por primera vez, incluimos las líneas de abajo en el método workSpaceWindowCreated.
15 isFirstExec = true;
16 this.shake();
=)
Lo anterior permite al sistema liberar/terminar la sesión de un usuario por inactividad, es decir, el sistema sabe cuando nada más lo tienes abierto y no ejecutas acciones en el, así que manos a la obra que esas pólizas no se van a capturar solas, o bien, tal vez eres de esos programadores que códifican con la mirada (cómo yo), un talentoso desarrollador adelantado a su época.
¿Cómo lo hace Ax?
Pues bien, la clase Info tiene un método misterioso llamado workSpaceWindowCreated, ahí, Ax inicia algunas tareas que se ejecutan en segundo plano, una de ellas es la llamada a autologOff, pero a traves de la instrucción setTimeOut, donde establece un intervalo de ejecución y además el parámetro _idle inicializado en true.
Con esa
Seguro a quienes tienen configurado el parámetro AutologOff habrán experimentado el cierre de la sesión sin previo aviso, así que les mostraré como poner un aviso antes de que esto pase, o si no tienen un tiempo de 'Parada Automática' el sistema les avisará de todos modos.
Lo primero es diseñar un mensaje bonito, pero como no soy diseñador, entonces simplemente sacudiremos la ventana de Ax (para que se desempolve), ésto quedará añadido en un método de la calse Info
01 void shake()
02 {
03 int hWnd, i, x, y, w, h;
04 Random random;
05 UserInfo userInfo;
06 ;
07
08 if (!isFirstExec)
09 {
10
11 hWnd = infolog.hWnd();
12 [x,y,w,h] = winapi::getWindowRect(hWnd);
13
14 random= new Random();
15
16 for (i = 0; i<200;i++)
17 winapi::setWindowPos(hWnd,1+(random.nextInt()/1000),1+(random.nextInt()/1000),w -20,h-20);
18
19 winapi::setWindowPos(hWnd,0,0,w,h);
20 }
21 this.setTimeOut(identifierstr(shake), #shakeInterval*60, true);
22 isFirstExec=false;
23}
En la línea 08 me aseguro de que la primera vez que se llame no se ejecute la sacudida, ésto porque lo haré en el arranque, luego, obtengo el hWnd en la línea 11 y después algunos datos de la ventana (línea 12).
En la línea 16 y 17 le establezco la posición con valores aleatorios, y en la 19 dejo la ventana como estaba.
En la 21 vamos a hacer recursiva la tarea.
Previamente definimos el shakeInterval con 2000 y declaramos la variable isFirstExec;
Y para llamarla por primera vez, incluimos las líneas de abajo en el método workSpaceWindowCreated.
15 isFirstExec = true;
16 this.shake();
=)
Wednesday, November 19, 2014
Agregar un Script al Editor de Código Dynamics Ax
Es posible añadir funcionalidad al editor de código de Ax en la sección de scripts.
Para poder añadir un nuevo elemento o modificar uno existente, es necesario modificar la clase EditorScripts.
Podemos añadir un nuevo metodo y este se convertirá en un nuevo menú contextual, si queremos crear algún submenú bastará con que el nombre del método tenga un guión bajo que servirá como separador.
Vamos a implementar un metodo con la sintaxis para construir un Lookup, ahí incluiremos las clases necesarias y los rangos.
01 void plantillaLookup(Editor editor)
02 {
03 source source;
04 ;
05
06
07 source = "SysTableLookup sysTableLookup;\n";
08 source += "Query query;\n";
09 source += "QueryRun qr;\n";
10 source += "QueryBuildDataSource qbds;\n";
11 source += ";\n\n";
12 source += "query = new Query();\n\n";
13
14 source += "sysTableLookup = SysTableLookup::newParameters(TableNum(Nombre_tabla), this);\n";
15 source += "sysTableLookup.addLookupfield( fieldnum( Nombre_tabla,campo_a_mostrar_1));\n";
16 source += "sysTableLookup.addLookupfield( fieldnum( Nombre_tabla,campo_a_mostrar_2));\n\n\n\n";
17
18 source += "qbds = query.addDataSource(tablenum( Nombre_tabla));\n";
19 source += "qbds.addRange(fieldnum(Nombre_tabla, campo_rango)).value(valorStr);\n\n\n";
20
21
22 source += "sysTableLookup.parmQuery( query);\n";
23 source += "sysTableLookup.performFormLookup();\n";
24
25 editor.insertLines(source);
26 }
Guardamos la clase con su nuevo método, compilamos la aplicación y abrimos el menú contextual para ver el resultado.

Al dar clic en nuestra nuevo menú obtenemos la siguiente plantilla.
Para poder añadir un nuevo elemento o modificar uno existente, es necesario modificar la clase EditorScripts.
Podemos añadir un nuevo metodo y este se convertirá en un nuevo menú contextual, si queremos crear algún submenú bastará con que el nombre del método tenga un guión bajo que servirá como separador.
Vamos a implementar un metodo con la sintaxis para construir un Lookup, ahí incluiremos las clases necesarias y los rangos.
01 void plantillaLookup(Editor editor)
02 {
03 source source;
04 ;
05
06
07 source = "SysTableLookup sysTableLookup;\n";
08 source += "Query query;\n";
09 source += "QueryRun qr;\n";
10 source += "QueryBuildDataSource qbds;\n";
11 source += ";\n\n";
12 source += "query = new Query();\n\n";
13
14 source += "sysTableLookup = SysTableLookup::newParameters(TableNum(Nombre_tabla), this);\n";
15 source += "sysTableLookup.addLookupfield( fieldnum( Nombre_tabla,campo_a_mostrar_1));\n";
16 source += "sysTableLookup.addLookupfield( fieldnum( Nombre_tabla,campo_a_mostrar_2));\n\n\n\n";
17
18 source += "qbds = query.addDataSource(tablenum( Nombre_tabla));\n";
19 source += "qbds.addRange(fieldnum(Nombre_tabla, campo_rango)).value(valorStr);\n\n\n";
20
21
22 source += "sysTableLookup.parmQuery( query);\n";
23 source += "sysTableLookup.performFormLookup();\n";
24
25 editor.insertLines(source);
26 }
Guardamos la clase con su nuevo método, compilamos la aplicación y abrimos el menú contextual para ver el resultado.
Al dar clic en nuestra nuevo menú obtenemos la siguiente plantilla.
Subscribe to:
Comments (Atom)