Tratamiento de ficheros con D365FO y Azure File Storage

Uno de los puntos que se ha visto más afectado con el cambio de versión de Dynamics AX ha sido sin duda el tratamiento de los ficheros.

Estábamos muy acostumbrados a trabajar con unidades compartidas de red que podíamos utilizar en los procesos por lotes, ya que el servidor (AOS) podía tener acceso a dichas unidades y trabajar con los ficheros ubicados en ellas. Quién más quién menos alguna vez habrá tenido que desarrollar un proceso para leer ficheros de un determinado directorio e incorporar la información al ERP. O a la inversa, exportar información del sistema almacenándola en ficheros CSV o XML.

Pues bien, es evidente que con el paso del software al cloud, la posibilidad de acceder a carpetas compartidas dentro de nuestra red interna, desaparece. No obstante, como dice el dicho popular, siempre que se cierra una puerta, se abre una ventana. Y en este caso, además, se abren múltiples ventanas, tales como Azure File Storage, FTP, Azure Bus, o cualquier sistema de almacenamiento de ficheros o información disponible en la nube.

Dicho esto, el objetivo de este primer artículo es aprender a integrar D365FO con Azure File Storage.

Crear una cuenta de almacenamiento en Azure

Tendremos que entrar a nuestro portal de Azure y crear una cuenta de almacenamiento en caso de no disponer de ella.

Posteriormente, crearemos un recurso compartido de archivos, o dicho de otra forma, un repositorio de ficheros equivalente a una carpeta compartida en nuestros servidores, pero en este caso, en la nube.

Dentro de este directorio, podremos crear tantas subcarpetas como sea necesario. En nuestro caso, hemos creado el recurso d365fo, con las carpetas Clientes y Pedidos:

Mapear el recurso compartido de archivos en nuestro ordenador

Para no tener que estar conectándonos al portal de Azure constantemente para subir o descargar ficheros, podemos mapear este directorio en nuestro PC, y acceder a los ficheros como si de una carpeta convencional se tratara. Para tal propósito, utilizaremos la opción Conectar disponible en Azure, y seguiremos las instrucciones para ejecutar un comando en PowerShell.

Si todo ha finalizado correctamente, deberíamos tener la unidad Y:/ mapeada en nuestro ordenador.

Crear pantalla de parámetros en D365F&O

Necesitaremos una tabla de parámetros (AzureParameters) que almacene los datos necesarios para poder conectarnos a nuestra cuenta de almacenamiento en Azure. Estos son los 3 campos necesarios:

La contraseña la podemos obtener del portal de Azure, a través de la opción Claves de acceso:

Por último, crearemos otra tabla (AzureFilesConfig) donde configuraremos las opciones necesarias para trabajar con el fichero, según el tipo de entidad (clientes o pedidos, por ejemplo). En el siguiente ejemplo, vemos la configuración que se utilizará para exportar un fichero de clientes.

Crear clase AzureUtils

Llegados a este punto, tenemos todo lo necesario para empezar a picar código. Crearemos una clase que contendrá todas las funciones necesarias para interactuar con nuestra cuenta de almacenamiento. En nuestro caso, utilizaremos estas 4 funciones:

  • Leer fichero
  • Escribir fichero
  • Eliminar ficheros
  • Obtener ficheros del directorio

Para no copiar todo el código en este post, os dejo la clase en cuestión con las 4 funciones en GitHub:

Únicamente mencionar, que para poder acceder a la API de Azure File Storage, necesitaremos incluir las siguientes referencias en nuestro código:

using Microsoft.Azure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.File;

Utilizar la clase AzureUtils

A continuación, únicamente nos queda probar que la clase funciona correctamente.

Por ejemplo, a través del siguiente job, crearemos un fichero XML que contendrá información de clientes.

class Job_ExportFileToAzure
{    
    public static void main(Args _args)
    {        
        XmlDocument                 doc;
        XmlNode                     docNode;
        XmlNode                     scriptVersionNode;
        XmlAttribute                scriptVersionAttribute;
        XmlNode                     customersNode;        
        XmlNode                     customerNode;
        XmlNode                     idNode;
        XmlNode                     nameNode;        
                
        /// XML Version information
        doc = new XmlDocument();
        docNode = doc.createXmlDeclaration("1.0", "UTF-8", "");
        doc.appendChild(docNode);

        /// XMLScript version node
        scriptVersionNode = doc.createElement("XMLScript");
        scriptVersionAttribute = doc.createAttribute("Version");
        scriptVersionAttribute.value("2.0");
        scriptVersionNode.attributes().setNamedItem(scriptVersionAttribute);
        doc.appendChild(scriptVersionNode);

        /// XMLScript.Customers node
        customersNode = doc.createElement("Customers");        
        scriptVersionNode.appendChild(customersNode);
             
        customerNode = doc.createElement("Customer");                
        idNode = doc.createElement("Id");
        idNode.appendChild(doc.createTextNode("C00001"));
        nameNode = doc.createElement("Name");
        nameNode.appendChild(doc.createTextNode("Cliente 1"));
        customerNode.appendChild(idNode);
        customerNode.appendChild(nameNode);

        str outXML = doc.outerXml();

        System.IO.Stream streamXML;
        
        System.IO.MemoryStream stream = new System.IO.MemoryStream();
        System.IO.StreamWriter writer = new System.IO.StreamWriter(stream);
        writer.Write(outXML);
        writer.Flush();
        stream.Position = 0;

        AzureUtils::createAzureFile(AzureFilesConfig::find(AzureFileType::Customers), "Customers.xml", conNull(), stream);
    }
}

El resultado es el siguiente:

Otro ejemplo, para obtener todos los ficheros que tenemos en un directorio de Azure, podemos utilizar la siguiente función:

class Job_GetAzureFolderFiles
{            
    public static void main(Args _args)
    {       
        container files;
        int		  i;

        files = AzureUtils::getDirectoryFiles(AzureFilesConfig::find(AzureFileType::Customers));

        for (i=1;i<=conLen(files);i++)
        {
            info(conPeek(files, i));
        }
    }
}

Y ahí va el resultado:

Como siempre, espero que este post te sea de utilidad, y en este caso concreto, que te facilite el trabajo en tus integraciones con Azure File Storage.

Non-stop learning!

Comparte:
Soy Miquel Vidal, ingeniero técnico en informática de sistemas, y actualmente trabajo como analista técnico y formador especializado en las soluciones empresariales de Microsoft (Office 365, Dynamics AX/365 y Power Platform).

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Volver arriba