1 Temmuz 2021 Perşembe

AX 2012 - Satış iadeleri için varsayılan deftere nakil profili aktive etme

AX 2012 satışın iadesinde varsayılan deftere nakil profili malesef gelmiyor. Bu yüzden muhasebe kodunu elle seçmek gerekiyor:

 

 


 Biraz debuglayınca bunun bir istisnasının olduğunu farkettim; yalnız Brezilya kurulumuyla ekranda gözüken bir parametre (CustParameters.EnableReturnPostingProfiles) var. Custparameters tablosuna girip bu parametrenin özelliklerinden Brezilya kurulumunu kaldırırsanız ekranda görünmeye başlıyor ve aktive ettikten sonra varsayılan bir muhasebe hesabı gelmesi sağlanabiliyor:

 

 

 Ekrandan iade girerken çok büyük bir problem değil bu belki ama benim gibi bir batch job ile iade oluşturuyorsanız ihtiyacınız olabilir.

 

 

 

 

 

 

27 Nisan 2021 Salı

AX 2012 - SFTP Download

 Bir müşterimizin SFTP download yaptığı veri sağlayıcı SFTP servisini yenilemiş. Mevcut kod 2007'den beri güncellenmeyen Tamir.SharpSSH.DLL'i kullanıyordu. Malesef DLL yeni servisle çalışmadı, "Tamir.SharpSsh.jsch.JSchException: Algorithm negotiation fail" hatası verdi. Hatayla ilgili internette bulduğum çözümlerden hiçbiri malesef çalışmadı. 

Forum sayfalarında yaptığım araştırmadan SSH.NET'in tavsiye edildiğini gördüm. SSH.NET'in DLL'sini direk AX içinden referanslara ekleyip kullanmaya kalktığımda malesef download metodunda opsiyonel olan parametrenin X++'a gelirken zorunlu olduğunu ve daha da kötüsü bu paremetrenin X++ tarafından desteklenmeyen Action<ulong> türü olduğunu gördüm. Önce bir blogda gördüğüm çözümü denedim, metodu overload etmeyi öneriyordu, SSH.NET open source bir library olduğu için yapılabilir bir çözüm gibi geldi, ancak derlemede bir takım hatalar aldım ve hatalarla uğraşmaktansa SSH.NET DLL'yi kullanan bir DLL yazmaya karar verdim. Bu hem daha kolay olacaktı, hem de SSH.NET'in yeni bir versiyonu çıktığında güncellemek için tekrar kod düzenleme ve derleme gerekmeyecekti.

Aşağıdaki C# kodunu Dynamics 365 F&O için yazılmış bir blog sayfasındaki kodu biraz değiştirerek yazdım:


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;
        }
    }
}

Oluşturduğum DLL'yi ve SSH.NET'in kendi DLL'sini AX klasörlerine kopyalayıp aşağıdaki kodla SFTP sorunumu çözmüş oldum:


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 - Form kontrolüne sağ mouse popup menü eklemek

 Bu konuda hem AX 2009 hem AX 2012'de çalışan bir örnek paylaşımı yapmıştım 2015 yılında. 365'de yapı biraz değişmiş, bu sebeple artık o kod çalışmıyor. Microsoft öncesi-sonrası diye bu konuyu anlatan bir paylaşım yapmış, ben de oradan yararlandım. Daha önce tek metodda halledilen iş iki metoda çıkmış.

 Aşağıdaki constantları class declaration'a tanımlıyoruz. Constant kullanımı tabii ki zorunlu değil ama okunurluğu arttırıyor:

public const int listCredit = 1;
public const int listJournal = 2;

Bu metodu popup çalışmasını istediğimiz kontrole koyuyoruz. Bu metod popup menüyü çalıştırıyor. Aşağıdaki örnekte iki popup bar var:

        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();
        }

 


 Bu metod da popup menüde seçim yapılınca çalışıyor:

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

                    info("Bar 1 seçildi!..");
                    break;
                case listJournal:
                    info("Bar 2 seçildi!..");
                    break;
            }
        }


Benim yaptığım denemelerde popup menü bazen görünmedi. Böyle bir duruma 2012 veya 2009'da hiç rastlamamıştım. Sebebini bulamadım. Popup menünün görünmediği durumlarda debug yaptığımda getContextMenuOptions metodunun tetiklenmediğini gördüm.

4 Mart 2021 Perşembe

AX 2012/365 F&O - Satıcı/müşteri hareket kapatma

  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 - Args ile filtre göndermek

Args ile filtreniz sadece bir kayıttan ibaretse args.record() kullanarak filtreleyebilirsiniz, record metodu ile birden fazla kayıt gönderemezsiniz. Bunun için InitialQueryParameter sınıfını kullanabilirsiniz: 

            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);