Sunday, May 10, 2015

AX2012 AIF Document Services - Include fields which are not part of AOT query

While exporting data from AX to other third party systems. There could be a requirement to send data which is not part of your AOT query. There could be a requirement to include data from other tables which are not part of your query OR cannot become part of query because of complex joins or may be they need some custom business logic which cannot be achieved using Query. You can always include such fields by creating parm methods for these fields in AX<tableName> classes. For example:

public str parmWBS(str _wbs = '')
{
    GeneralJournalEntry     generalJournalEntry;
    ProjInvoiceJour         projInvoiceJour;

    if (this.parmText() == '300')
    {
        select generalJournalEntry
            where generalJournalEntry.RecId == GeneralJournalAccountEntry.GeneralJournalEntry
            && generalJournalEntry.JournalCategory == LedgerTransType::Project
        join projInvoiceJour
            where projInvoiceJour.LedgerVoucher == generalJournalEntry.SubledgerVoucher;

        if (projInvoiceJour)
        {
            _wbs = projInvoiceJour.ProjInvoiceProjId;
        }
    }

    return _wbs;
}

In above method, based on the existing parmText() field on Query, I am trying to fetch the Project Invoice Id from the table which is not part of the query.

Once, parm method is written, you will need to:


  1. Run the Update Document Service Wizar
  2. Open AIFService forms, filter the service you are working on and click Refresh
  3. Generate Incremental IL

AX 2012 upload file to FTP with batch processing support

One of a very common requirements for any ERP systems is to have FTP file upload support to upload files from AX to FTP server. We do have many libraries, tools available to do that. However, it is best to have native X++ code without referencing any DLLs to upload your files to FTP from AX. Following code shows the example of uploading files to FTP.

The code written below can be easily used to upload files, However, if you have to process this as a batch you need to consider that batch runs on server/CIL and for this you need to set permissions and also if that still doesn't work, you can change the method to static server.

private server static void sendToFTP()
{
    System.Object ftpo;
    System.Object ftpResponse;
    System.Net.FtpWebRequest request;
    System.IO.StreamReader reader;
    System.IO.Stream requestStream;
    System.Byte[] bytes;
    
    System.Text.Encoding utf8;
    System.Net.FtpWebResponse response;
    System.Object credential;
    HOSInventParameters hosInventParameters;

    int             fileCount;
    System.Array    files;
    int             i;
    str             nextFile;
    Filename        filepath;
    Filename        fileType,fileNameString;
    FileNameType    pattern = '*.TXT';
    FileName        ftpFileName,fileName;


    select firstOnly custInventParameters;
    new InteropPermission(InteropKind::ClrInterop).assert();



    files           = System.IO.Directory::GetFiles(custInventParameters.PartsFileLocation, pattern);

    if (files)
    {
        fileCount =    files.get_Length();

        for(i=0; i < fileCount; i++)
        {
            nextFile    = files.GetValue(i);

            [filepath, filename, fileType] = fileNameSplit(nextFile);
            fileNameString= filename + fileType;
            ftpFileName = custInventParameters.PartsFTPAddress + '/'custInventParameters.PartsFTPLocation + '/' + fileNameString;

            reader = new System.IO.StreamReader(nextFile);
            utf8 = System.Text.Encoding::get_UTF8();
            bytes = utf8.GetBytes( reader.ReadToEnd() );
            reader.Close();
            // little workaround to get around the casting in .NET
            ftpo = System.Net.WebRequest::Create(ftpFileName);
            request = ftpo;

            credential = new System.Net.NetworkCredential(custInventParameters.PartsUserId,custInventParameters.PartsFTPPassword);
            request.set_Credentials(credential);
            request.set_ContentLength(bytes.get_Length());
            request.set_Method('STOR');
            // "Bypass" a HTTP Proxy (FTP transfer through a proxy causes an exception)
            // request.set_Proxy( System.Net.GlobalProxySelection::GetEmptyWebProxy() );
            requestStream = request.GetRequestStream();
            requestStream.Write(bytes,0,bytes.get_Length());
            requestStream.Close();

            ftpResponse = request.GetResponse();
            response = ftpResponse;
            info(response.get_StatusDescription());
        }
    }

    CodeAccessPermission::revertAssert();
}