1 Temmuz 2021 Perşembe

AX 2012 - Enable default posting profile for sales return

There isn't default posting profile in AX 2012 sales return. So you have to select your ledger account manual:

 

 


 After a few debugging I found an exception; there was a parameter (CustParameters.EnableReturnPostingProfiles) shows at screen with just Brasilian setup. If you remove Brasilian tag from this field at Custparameters than parameter will displaying at screen and after checked up we have a default posting profile for sales returns:

  

 Maybe this's not importing so much when create sales return from screen but if you have to create a sales return from a job like me you might be need this.

 

 

 

 

 

 

27 Nisan 2021 Salı

AX 2012 - SFTP Download

SFTP service of one of our customers had upgraded. Old code had been written with Tamir.SharpSSH.DLL which didn't upgraded since 2007. Unfortunately service won't work with Tamir anymore, given with "Tamir.SharpSsh.jsch.JSchException: Algorithm negotiation fail" error. None of the solutions about I fond at internet worked with me. 

I see SSH.NET adviced ad forums. When I tried to copy SSH.NET's DLL to AX folders and add as reference unfortunately I see an optional paremeter of download method uses  Action<ulong> data type which doesn't supported by X++ and worse X++ makes this optional parameter as mandatory. First tried a solution which I see at a blog suggest overload the method, seem a good solution because of SSH.NET is an open source library. But I got some errors when compiled and didn't messed with these errors, instead of wrote a small C# code and build a small DLL. It was easier and in this case never need code update and recompile with new SSH.NET versions.

Compiled this code with just a few modifications which I found a blog page written for Dynamics 365 F&O:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Renci.SshNet;
using System.IO;

namespace SSHNet2
{
    public class SSHNet2
    {
        public SftpClient sftpClient;
        public void OpenSFTPConnection(string host, int port, string username, string password)
        {
            if (this.sftpClient == null)
            {
                this.sftpClient = new Renci.SshNet.SftpClient(host, port, username, password);
            }
            if (!this.sftpClient.IsConnected)
            {
                this.sftpClient.Connect();
            }
        }
        public List<string> GetDirectories(string path)
        {
            return this.sftpClient.ListDirectory(path).Select(n => n.Name).ToList();
        }
        public void MoveFile(string sourcePath, string destinationPath, bool isPosix)
        {
            this.sftpClient.RenameFile(sourcePath, destinationPath, isPosix);
        }

         public void DeleteFile(string sourcePath)
        {
            this.sftpClient.DeleteFile(sourcePath);
        }
        public Stream DownloadFile(string sourcePath)
        {
            var memoryStream = new MemoryStream();
            this.sftpClient.DownloadFile(sourcePath, memoryStream);
            memoryStream.Position = 0;
            return memoryStream;
        }
    }
}

Copied new DLL and SSH.NET's own DLL to AX folders and my SFTP download problem is solved:

System.IO.StreamReader          streamReader; 

System.IO.StreamWriter          streamWriter; 

 SSHNet2.SSHNet2                 sftp = new SSHNet2.SSHNet2();

System.IO.Stream                stream;

 sftp.OpenSFTPConnection(_RemoteAddress,any2int(_RemotePort), _RemoteUser, _RemotePassword);

            stream = sftp.DownloadFile(_RemoteFileName);

streamReader = new System.IO.StreamReader(stream);

streamWriter = new System.IO.StreamWriter("c:\test\test.txt");

streamWriter.Write(_StreamReader.ReadToEnd());

streamWriter.Flush();

streamWriter.Close();

streamReader.Close();  

9 Mart 2021 Salı

D365 F&O - Add right-click popup menu to form control

 In 2015 I shared a sample  about this issue which run both of AX 2009 and AX 2012. Seem Microsoft decided to change this too with 365, so that code doesn't run on 365 anymore. Microsoft shared a white page as before-after, I learned from that page. It was run with one method, since 365 two methods.

We declare these constants at class declaration. Of course these are not mandatory but good for writing human readable code:

public const int listCredit = 1;

public const int listJournal = 2;

We put this metod into control which we run popup. This method run popup menu. This sample has two popup bars:

        public str getContextMenuOptions()
        {
            str ret;
            ContextMenu menu = new ContextMenu();
            List menuOptions = new List(Types::Class);
            ContextMenuOption option;
            
            option = ContextMenuOption::Create("Credit number", listCredit);
            menuOptions.addEnd(option);

            option = ContextMenuOption::Create("Journal number", listJournal);
            menuOptions.addEnd(option);

            menu.ContextMenuOptions(menuOptions);
            return menu.Serialize();
        }

  This method triggers when select a bar at popup:

 public void selectedMenuOption(int selectedOption)
        {
            switch (selectedOption)
            {
                case -1:
                    break;
                case listCredit:

                    info("Bar 1 selected!..");
                    break;
                case listJournal:
                    info("Bar 2 selected!..");
                    break;
            }
        }

In my tests popup menu sometines doesn't showed up. I never see before at neither 2012 nor 2009. I couldn't find reason. When debugged see getContextMenuOptions doesn't triggered when bars doesn't showed up.

4 Mart 2021 Perşembe

AX 2012/365 F&O - Settle customer/vendor transactions

   public static void settlement(CustVendTransOpen _trans1,CustVendTransOpen _trans2,
        CustVendACType _type = CustVendACType::Vend)
    {
        CustVendOpenTransManager manager;

        if (_type == CustVendACType::Vend)
            manager = CustVendOpenTransManager::construct(VendTable::find(_trans1.AccountNum));
        else
            manager = CustVendOpenTransManager::construct(CustTable::find(_trans1.AccountNum));
        manager.updateTransMarked(_trans1, true);
        manager.updateTransMarked(_trans2, true);
        manager.settleMarkedTrans();
    }

26 Ocak 2021 Salı

AX 2012 - Send filter with args

 

If your filter just one record, you can run filter with args.record(). In the other case if you have to filter more than one record, you can't use record method. You can use InitialQueryParameter for this:

            Args                 args = new Args();
            MenuFunction         MenuFunction = new MenuFunction('LedgerJournalTable', MenuItemType::Display);
            Query                q = new Query();
            QueryBuildDataSource QBDS = q.addDataSource(tableNum(LedgerJournalTable));

            if (ABCRCreditTable.AccualJournalNum != "")
                QBDS.addRange(fieldNum(LedgerJournalTable,JournalNum)).value(ABCRCreditTable.AccualJournalNum);
            if (ABCRCreditTable.AccualJournalNum2 != "")
                QBDS.addRange(fieldNum(LedgerJournalTable,JournalNum)).value(ABCRCreditTable.AccualJournalNum2);

            args.initialQuery(InitialQueryParameter::createByQuery(q));
            args.caller(this);

            MenuFunction.run(args);