lunes, 12 de septiembre de 2011

Herramienta de Ingeniería Reversa en Dynamics AX

Navegando por internet encontre información muy interesante acerca de la herramienta de ingeniería reversa que tiene MS Dynamics AX, espero que les guste. :)
--------------------------------------------------------------------------------------------------
Microsoft Dynamics AX dispone de una muy buena herramienta de ingeniería inversa gracias a la cual podemos visualizar un modelo de datos u objetos de la aplicación en UML y ERX.


Generando Modelos y Archivos ERX
La herramienta de ingeniería inversa puede generar un modelo UML de datos u objetos o un archivo .erx para elementos de aplicación desde un proyecto privado o compartido o incluso desde una perspectiva. Si se desea utilizar proyectos privados o compartidos lo primero es crear el proyecto y llevar los elementos, que tu deseas modelar, al proyecto.

Modelo UML de Datos y Objetos
Bien, como ya hemos mencionado la herramienta de ingenería inversa puede crear los siguientes tipos de modelos de datos:
  • Modelo de Datos UML: este modelo nos provee una representación visual de los metadatos de las tablas y de las relaciones y vistas. Este modelo contiene una clase por cada tabla y vista. Esta clase captura los atributos y asociaciones, así como tambien los tipos de datos de los campos, índices, y relaciones. Para crear un modelo de datos UML en Visio debemos seguir los siguientes pasos:
    • En el ciente de Microsoft Dynamics AX, en la barra de menú, seleccionar Herramientas, luego Herramientas de desarrollo y luego hacer clic en Ingeniería inversa. El cuadro de dialogo de Ingeniería inversa se abrirá.
    • Seleccionamos Modelo de datos UML de Visio.
    • Seleccionamos el tipo de ítem desde el que deseamos generar nuestro modelo, estos pueden ser: Proyecto privado, Proyecto compartido, o Perspectiva, y seleccionamos los ítems desde la lista desplegable.
    • Si deseamos cambiar el nombre o la ruta de alojamiento del archivo, hacemos clic en ícono de la carpeta, y especificamos un nombre y una dirección para el archivo.
    • Hacemos clic en OK.
    • Despues de que el modelo de datos es creado, Visio se abrirá y ya contendrá todos los elementos UML con el diagrama en blanco. Usando el explorador de modelo arrastramos los elementos del modelo al diagrama.
  • Modelo de Objetos UML: este modelo nos provee una representación visual de los metadatos de clases, interfaces, vistas, tablas y relaciones. Un modelo de objeto contiene una clase para cada clase, vista, tablas e interfaces para cada interfaz de Microsoft Dynamics AX. Este modelo capatura atributos, así como tambien referencias a tablas y clases, extended data type, base enums, y tipos de datos nativos. El modelo tambien contiene cualquier clase que se extienda de otra clase, clases que son implementadas en las intefaces, y clases que son llamadas por otras. Para crear un modelo de objetos UML en Visio debemos seguir los siguientes pasos:
    • En el cliente de Microsoft Dynamics AX, en la barra de menú, seleccinar Herramientas, luego Herramientas de desarrollo y luego hacer clic en Ingeniería inversa. El cuadro de dialo de Ingeniería inversa se abrirá.
    • Seleccionamos Modelo de Objetos UML de Visio.
    • Seleccionamos el tipo de ítem desde el que deseamos generar nuestro modelo, estos pueden ser: Proyecto privado, Proyecto compartido, o Perspectiva, y seleccionamos los ítems desde la lista desplegable.
    • Si deseamos cambiar el nombre o la ruta de alojamiento del archivo, hacemos clic en ícono de la carpeta, y especificamos un nombre y una dirección para el archivo.
    • Hacemos clic en OK.
    • Despues de que el modelo de objetos es creado, Visio se abrirá y ya contedrná todos los elementos UML con el diagrama en blanco. Usando el explorador de modelo arrastramos los elementos del modelo al diagrama.
En resumen, los siguientes elementos son incluidos en los diagramas UML:
  • Modelo de Datos
    • Tablas
    • Propiedades de los grupos de tablas
    • Campos
    • Campos con información indexada
    • Todos los extended data type
    • Todos los base enums
    • Todos los tipos de datos X++
    • Todas las tablas referenciadas
    • Vistas
    • Campos de vistas
  • Modelo de Objetos
    • Tablas
    • Campos
    • Métodos
    • Parámetros de métodos
    • Clases
    • Todos los extended data type
    • Todos los base enums
    • Todos los tipos de datos X++
    • Todas las referencias a tablas y clases
    • Vistas
    • Campos de vistas
Aqui les dejo un ejemplo para generar en visio un diagrama Entidad Relación, basado en objetos existentes en AX, utilizando el formato ERX de ERwin.
Para facilitar el ejemplo creamos un nuevo proyecto e incluimos algunas tablas con la función Ordenación/filtro avanzados. Se incluira todas las tablas que empiezan por InventDim

Con esto se genera un proyecto razonablemente pequeño.

Ahora vamos a la opción de menú:
Herramientas > Herramientas de desarrollo > Utilizar técnicas de ingeniería inversa
Configuramos un destino para el fichero exportado, elegimos la opción de formato ERX y buscamos el proyecto que acabamos de guardar para decirle al sistema qué objetos debe exportar.

A partir de aquí trabajamos con Microsoft Office Visio, en mi caso con la versión 2007. Vamos a crear un nuevo diagrama de modelo de bases de datos:


Al crear un diagrama de este tipo, visio nos habilita el menú Base de datos > Importar > Importar archivo ERX de ERwin. Buscamos el fichero exportado por AX y Aceptar.
Visio nos incluirá todas las tablas en la ventana Tablas y vistas (Menú Base de datos > Ver > Tablas y vistas). Desde aquí se pueden seleccionar las tablas que se quiera y arrastrarlas directamente al diseño:
Y eso es todo:



Saludos.

sábado, 27 de agosto de 2011

Mover Archivos desde MS Dynamics AX

Hola, mediante este codigo se podra mover archivos desde Dynamics AX, teniendo esto, tambien se puede copiar y eliminar archivos, es cuestion de hacer unos pequeñisimos cambios en la parte del FOR (se los dejo a su investigación :D).

static void MoverArchivos(Args _args)

{
     System.IO.DirectoryInfo di;
     System.Type arrayType;
     System.Array array;
     System.IO.FileInfo fi;
     FilePath filePath, moveFilePath, shortFile;
     FileNameOpen fileNameOpen;
     FileIOPermission dirPermission, filePermission;
     InteropPermission interopPermission;
     Set permissionSet;
     int i;
     int l;
     ;

     interopPermission = new InteropPermission(InteropKind::ClrInterop);
     filePath = '\\\\MSAXPRB\\Prueba\\a\\';
     dirPermission = new FileIOPermission(filePath, 'R');
     permissionSet = new Set(Types::Class);
     permissionSet.add(interopPermission);
     permissionSet.add(dirPermission);
     CodeAccessPermission::assertMultiple(permissionSet);
     di = new System.IO.DirectoryInfo(filePath);
     arrayType = System.Type::GetType("System.IO.FileInfo");
     array = System.Array::CreateInstance(arrayType, 1);
     array = di.GetFiles();
     l = array.get_Length();
     CodeAccessPermission::revertAssert();
     if (l > 0)
    {
          for (i = 0; i < l; i++)
         {
               interopPermission = new InteropPermission(InteropKind::ClrInterop);
               interopPermission.assert();
               fi = array.GetValue(i);
               fileNameOpen = fi.get_FullName();
               CodeAccessPermission::revertAssert();
               filepermission = new FileIOPermission(fileNameOpen, 'W');
               interopPermission = new InteropPermission(InteropKind::ClrInterop);
               permissionSet = new Set(Types::Class);
               permissionSet.add(interopPermission);
               permissionSet.add(dirPermission);
               CodeAccessPermission::assertMultiple(permissionSet);
               shortFile = fi.get_Name();
               moveFilePath = "\\\\MSAXPRB\\Prueba\\b\\" + shortFile;
               fi.MoveTo(moveFilePath);
               CodeAccessPermission::revertAssert();
         }
     }
     box::info("Archivos movidos");
}


Un ejemplo del uso de este codigo podria ser al momento de hacer procesos en batch para importar data de archivos.


Saludos.

viernes, 26 de agosto de 2011

Leer archivos mediante la clase CommaIo

Con esta clase se puede leer archivos externos para poder ingresarlos mediante interface a las tablas de MSDAX.
Este metodo contiene 2 parametros, el primero es donde se pondra la ruta del archivo y el segundo donde pondremos el modo a utilizar, nosotros utilizaremos el modo leer, por lo tanto utilizaremos "R".

CommaIo io;

container con;
FileIoPermission perm;

#define.EjemploArchivo(@"c:\prueba.txt")
#define.EjemploModo("R")
;

perm = new FileIoPermission(#EjemploArchivo, #EjemploModo);

if (perm == null)
{
     info("No existe archivo");
}

// Dando permisos para la ejecución de CommaIo.new method.
perm.assert();

// Cargando archivo.
io = new CommaIo(#ExampleFile, #ExampleOpenMode);
if (io)
{
     con = io.read();
}

// Cerrando los permisos de acceso.
CodeAccessPermission::revertAssert();

-------------------------------------------------------
Teniendo la información en un contenedor, simplemente es cuestión de recorrerlo.
Saludos.

viernes, 22 de julio de 2011

Manipular varios campos al modificar un campo principal de un formulario

Hola, vamos a realizar un caso en que al momento de modificar un campo, se modifiquen otros a consecuencia. Para facilitar el ejemplo los campos seran de tipo enum (NoYes).
Utilizaremos lo siguiente:
TABLA: Table1
     CAMPO: Field1, Field2, Field3
     METODO: Update()
FORMULARIO: Form1
     DATASOURCE: Table1
     DISEÑO: Grid(todos los campos del datasource)
--------------------------------------Pasos---------------------------------------------------
En el metodo update() de la tabla ponemos las condiciones:

public void update()
{
     if(this.Field1 == noyes::Yes)
    {
          this.Field2 = noyes::No;
          this.Field3 = noyes::No;
    }
     if(this.Field2 == noyes::Yes)

    {
          this.Field1 = noyes::No;
          this.Field3 = noyes::No;
    }
     if(this.Field3 == noyes::Yes)
    {
          this.Field1 = noyes::No;
          this.Field2 = noyes::No;
    }
     super();
}

En cada campo del grid del formulario vamos a crear metodos clicked() y poner lo siguiente:

public void clicked()
{
     super();
     Table1_ds.research();
}

Con lo realizado, al momento de que un campo este con check, los otros se van a blanquear.
Saludos.

jueves, 21 de julio de 2011

Manejando columnas y filas de un grid

Hola, hay veces que nos piden capturar especificamente algunas columnas o filas de un grid en un formulario. Daré un ejemplo de cómo hacer dicho procedimiento, utilizando un botón. Para esto pondremos el siguiente código en el metodo clicked() del botón:

void clicked()
{
     int i;
     int numcol, f;
     ;

     numcol = tuGrid.controlCount();
     if (TuDatasource_ds.first())
    {
          do
         {
               for (f=1;f<=numcol;f++)
              {
                   box::info(tuGrid.controlNum(f).valueStr());
              }
          } While (TuDatasource_ds.next());
    }
    super();
}

Nota: es importante tener la propiedad "AutoDeclaration" del grid en TRUE.
Saludos.

martes, 7 de junio de 2011

Controlar desde un formulario hijo a uno padre

Lo que haremos es actualizar un grid que se encuentra en el formulario padre (formulario llamador) desde un formulario hijo (formulario llamado).
Para nuestro ejemplo, vamos a trabajar con el formulario VendInvoiceJournal.
  1. En la tabla VendInvoiceJour creamos el campo PRB_Actualiza (extended: name).
  2. Creamos el botón PRB_Pase en el formulario VendInvoiceJournal (VendInvoiceJournal/Designs/Design/Tab/Overview/OverviewButtonGroup/PRB_Pase).
  3. Creamos la tabla temporal PRB_TablaPase.
  4. Creamos el formulario PRB_PaseActualiza
  5. Creamos el metodo clicked() en el boton PRB_Pase del formulario VendInvoiceJournal.
  6. Agregamos el siguiente código:
    void clicked() { Args args; FormRun formRun; ; super(); args = new Args(formstr(PRB_PaseActualiza)); args.record(vendinvoicejour); formRun = classFactory.formRunClass(args); formRun.init(); formRun.run(); formRun.wait(); vendInvoiceJour_ds.research(); }
  7. Creamos el metodo clicked() en el botón Button del formulario PRB_PaseActualiza
  8. Agreganos el siguiente codigo:
    void clicked()
    { vendinvoicejour vij; vendinvoicejour xxx; super(); vij = element.args().record(); update_recordset xxx setting PRB_Actualiza = DataSource1_PRB_Actualiza.text() where xxx.LedgerVoucher == DataSource1_LedgerVoucher.text(); element.close(); }
  9. Hacemos pruebas:
    a. Abrimos el formulario VendInvoiceJournal (Proveedores/Consultas/Diarios/Facturas) y seleccionamos una linea


    b. Hacemos click en el botón creado “llamada formulario” y nos abre el formulario creado PRB_PaseActualiza

    c. Ponemos data en el campo Actualiza. Ej. Alonso
    d. Presionamos el botón Actualizar. Se cierra el formulario y actualiza el grid del formulario padre. 
Saludos.

domingo, 5 de junio de 2011

Ingresar direccion del proveedor mediante excel desde un JOB

Hola, les dejo como podemos ingresar direcciones de un proveedor en forma masiva desde un job mediante un excel.
  1. El excel debe tener las columnas codigo del proveedor y direccion, con la informacion correspondiente.
Creamos el JOB

static void ActualizaDireccion(Args _args)
{
    container                 conSheets;
    ExcelImportADO      xlImport;
    SysDataExcelCOM   dataExcelCom;
    Filename                  strFlename;
    accountnum             id;
   
str                 direccion;   
    vendtable           vend;   
    dirpartytable      dir;   
   
address             addre;   
    int i = 0;
    ;

    strFilename = "C:\\Users\\PC\\Desktop\\direccion.xls";
    xlImport    = new ExcelImportADO(strFilename);

    try
    {
        // abriendo solo la primera hoja de excel       if(!xlImport.openFile())
            throw error(strfmt("Error opening Excel file «%1»", strFilename));

                while(!xlImport.eof())//previo
                {
                    id              =       xlImport.getFieldValue(1);
                    direccion       =       xlImport.getFieldValue(2);

                    while select vend
                        where vend.AccountNum == id
                    {
                        while select dir
                            where dir.PartyId == vend.PartyId
                        {
                             if(!address::find(2303,dir.RecId,addresstype::None).AddrRecId)
                            {
                                addre.AddrTableId = 2303; //vendtable
                                addre.AddrRecId   = dir.RecId;
                                addre.Street      = direccion;
                                addre.Address     = direccion;
                                addre.insert();
                                i++;
                                   }
                         
}
        }

      xlImport.moveNext();

  }

  xlImport.finalize();

info("direcciones: " + num2str(i,3,2,1,1));

}
catch(Exception::Error)
{
     info("error");
     xlImport.finalize();
}
}

  1. Ejecutar el JOB.
Con esto se podria ver otras funcionalidades como modificacion, eliminacion de direcciones, ademas de hacer pruebas de como hacerlo para clientes (me imagino que es similar).

Saludos.

                          

martes, 31 de mayo de 2011

Exportar excel desde table browser

Para poder exportar el contenido de las tablas (mediante el AOT, función abrir tabla) a Excel, debemos activar la funcionalidad de la barra de herramientas estándar de DAX. Para ello haremos lo siguiente:


1. Ir al formulario SysTableBrowser

2. Ir al nodo SysTableBrowser/Design/design

3. Click derecho y seleccionar propiedades

4. Cambiar la propiedad WindowsType = PopUp por Estándar

Antes
Despues

Saludos.

viernes, 27 de mayo de 2011

Opcion "Ir al formulario de la tabla principal"

Hay veces que necesitamos utilizar esta opcion para hacer referencia a tablas que hemos creado y necesitamos llenar informacion, para el logro del llenado utilizando esta opcion, estamos obligados a crear formularios.
  1. Crear tabla a llenar (campos).
  2. Crear formulario (datasource, grid).
  3. Crear menuitem (jalar el formulario a menuitem/display).
  4. En las propiedad "FormRef" de la  tabla, poner el menuitem creado.  
Saludos.

jueves, 26 de mayo de 2011

Almacenar imagenes en dynamics AX

Hola, aqui les dejo un ejemplo de como almacenar imagenes dentro del AX, esta funcionalidad es una copia de la carga de logotipo de la empresa (Base/Configurar/Informacion de la empresa/Logotipo de la empresa).


  1. Abrir el AOT/Menu Items/Display/CompanyImage.
  2. Abrir otro AOT/Forms/CustTable.
  3. Abrir formulario : CustTable/Design/Design/ButtonGroup.
  4. Jalar el menu item CompanyImage en el ButtonGroup.
  5. Click derecho en el nuevo MenuItemButtom e ir a sus propiedades. En Texto escribir "Imagen Cliente".
  6. Salvar los cambios.
  7. Abrir el formulario CustTable, veremos que tenemos un nuevo boton (Imagen Cliente).
  8. Dar click al boton "Imagen Cliente".
  9. Cargar Imagen.
Si se quisiera ver esta imagen en un reporte, lo que se debe hacer es crear un método display:


• En este ejemplo estoy simulando tener un datasouce custInvoiceJour
x++:
display Bitmap mostrarImagen()
{
     CustTable custTable = CustTable::find(custInvoiceJour.InvoiceAccount);
     ;

     custTable = CustTable::find(custInvoiceJour.InvoiceAccount);
     return CompanyImage::find(custTable.dataAreaId, custTable.TableId, custTable.RecId).Image;
}
-----------------------------------------------------------------------
Para las personas un poquito mas tecnicas, aqui les dejo lo explicado en codigo:
static void ImagenCarga(Args _args)

{
     Image image = new Image();
     str filename;
     CustTable custTable;
     CompanyImage companyImage;
     ;
     filename = "C:\\Rosarojadespedida.jpg";
     select custTable
     where custTable.AccountNum == '1101';
     if (Image::canLoad(filename))
    {
          image.loadImage(filename);
          companyImage.Image = image.getData();
          companyImage.RefTableId = 77;
          companyImage.RefRecId = custTable.RecId;
          companyIMage.RefCompanyId = 'con';
          companyImage.insert();
     }
}


Saludos.

miércoles, 18 de mayo de 2011

Terminar una sesion de un cliente

  • Terminar la sesion de un cliente en específico

    static void TerminateSession(UserId UserId)
    {
    xSession xSession;
    int xSessionId;
    ;
    xSessionId = (select * from SysClientSessions where SysClientSessions.userId==UserId && SysClientSessions.Status==1).SessionId;
    xSession = new xSession(xSessionId);
    if (xSession)
    xSession.terminate(xSession.loginDate(), xSession.loginTime());
    }
  • Terminar la actual sesion

    static void ShutDown(Args _args)

    {
    Info Info = new Info();
    ;
    Info.shutDown(true);
    }
Saludos.

Borrar todas las transacciones de una Cia

Simplemente se debe hacer lo siguiente:
  • Ubicar la clase Clase SysDatabaseTransDelete
  • Ejecutar la clase

Saludos.