Monday, February 6, 2023

Containers

 
Why Containers?

In X++ (Object oriented programming language) the data or values stored in a Variable are of below types:Primitive dataTypes - int, str, real .... etc.
Composite dataTypes - Arrays, Containers, Collection Classes
Temporary Tables
For instance,
  • Primitive dataType variable can hold only 1 value and that too of same dataType, if you want to store 500 values then you have to create/declare 500 variables and intialize them, also it doesn't support variables of different dataTypes. To overcome this problem AX provides composite dataTypes arrays and containers, however arrays solve the former but supports only one dataType.
  • Container solves this problem by storing many elements of different dataypes. However there are few limitations with Containers like "container cannot store objects" and "performance implications" and they can be addressed by collection classes and temporary tables concepts. Containers are most frequently used in AX development so let us explore Containers and its features

Features of Containers:
    A container is a "composite data type"
      A container is 1 based not 0 based.
        A container is not a class therefore classes/objects cannot be passed/put into a container.
          A container contains an ordered sequence of values (primitive dataTypes - int, str, real, date, boolean, enum etc.) or other containers or/and some composite data types.
            A container is a "PASS BY VALUE" type not "pass by reference" type which means while passing container the copy of container with values is passed not the reference.Therefore, any variable declared as a container is automatically initialized to an empty container that contains no values.
              A container is IMMUTABLE which means a container is never modified with any functions rather all X++ statements acting on a container are internally building a new container.For example assignment of a container to another container variable and container functions such as conIns(), conDel(), conPoke(), += etc. are actually creating a new copy of the container.
                A container can be stored in the database as a dataBase coloumn created through AOT especially used to store images/files as a blob.

                Container Functions:

                Below are some of the most common container functions with examples.

                conPeek() Function
                The conPeek() is used to retrieve a specific element from a container.
                Syntax: anytype conPeek(container container, int number)container - The container to return an element from.
                number - The position of the element to return. Specify 1 to get the first element.
                Return value: The element in the container at the position specified by the number parameter. The conPeek function automatically converts the peeked item into the expected return type.

                void daxErp_conPeek()
                {
                    // container declaration and initialization with 2 values
                    container daxConBeta = ["Welcome", 8594]; 
                    str charHolder;
                    ;

                    // conPeek() function returns the value being held in a specific position in the container. 
                    // (Note: It returns anyType)
                    // Here printing 1st and 2nd values from daxConBeta to info
                    charHolder = conPeek(daxConBeta, 1);
                    info(strFmt("Container daxConBeta conPeek() values are :- 
                    %1, %2", charHolder, conPeek(daxConBeta, 2)));
                }


                Reference and credits

                http://imdaxershiv.blogspot.com/2016/03/dynamics-ax-tutorial-x-containers.html

                http://daxingwitheshant.blogspot.com/2018/07/collection-classes.html

                AOS validate method signatures

                   public boolean aosValidateDelete()

                    {

                        boolean ret;

                    

                        ret = super();

                    

                        return ret;

                    }


                   /// <returns></returns>

                    public boolean aosValidateInsert()

                    {

                        boolean ret;

                    

                        ret = super();

                    

                        return ret;

                    }


                  public boolean aosValidateUpdate()

                    {

                        boolean ret;

                    

                        ret = super();

                    

                        return ret;

                    }


                 [ExtensionOf(tableStr(tableName))]

                Monday, January 30, 2023

                Casings Explained

                 

                Capitalization Styles

                Camel Case

                The first letter in the identifier is lowercase and the first letter of its addition is a capital.

                Example: dynamicsAx.

                Pascal Case

                The first letter in the identifier is a capital and the first letter of its addition is a capital.

                Example: DynamicsAx.

                Upper Case

                All letters in the identifier are capitals.

                Example: DYNAMICSAX.

                Lower Case

                All letters in the identifier are lowercase.

                Example: dynamicsax.


                More best practices
                https://www.erpsoftwareblog.com/2020/03/microsoft-dynamics-365-for-finance-and-operations-coding-standards/


                Wednesday, January 25, 2023

                Business event class

                // Business event Contract

                [DataContractAttribute]

                final class XYZ_ICProdRcptLineContract

                {

                  SalesOrderedQty             salesQty;

                  SalesStatus                 salesLineStatus;

                  SalesId                     salesId;

                  ItemId                      itemId;

                  InventTransId               icInventTransId;


                    [DataMember("SalesQty")]

                    public SalesOrderedQty parmSalesQty(SalesOrderedQty _salesQty = salesQty)

                    {

                      salesQty = _salesQty;

                      return salesQty;

                    }


                    [DataMember("IntercompanyInventTransId")]

                    public InventTransId parmICInventTransId(InventTransId _icInventTransId = icInventTransId)

                    {

                      icInventTransId = _icInventTransId;

                      return icInventTransId;

                    }


                    [DataMember("SalesStatus")]

                    public SalesStatus parmSalesLineStatus(SalesStatus _salesLineStatus = salesLineStatus)

                    {

                      salesLineStatus = salesLineStatus;

                      return salesLineStatus;

                    }


                    [DataMember("SalesId")]

                    public SalesId parmSalesId(SalesId _salesId = salesId)

                    {

                      salesId = _salesId;

                      return salesId;

                    }


                    [DataMember("ItemNumber")]

                    public ItemId parmItemNumber(ItemId _itemId = itemId)

                    {

                      itemId = _itemId;

                      return itemId;

                    }


                }


                // Request class

                final class XYZ_ICProdRcptPostingRequest

                {

                    DataAreaId                  legalEntity;

                    SalesId                     salesId;

                    PurchId                     purchId;

                    InterCompanyPurchId         icPurchId;

                    SalesStatus                 salesStatus;

                    List                        salesLineList;

                    PackingSlipId               packingSlipId;


                    [DataMember("PackingslipId")]

                    public packingSlipId parmpackingSlipId(PackingSlipId _packingSlipId = packingSlipId)

                    {

                      packingSlipId = _packingSlipId;

                      return packingSlipId;

                    }


                    [DataMember("PurchId")]

                    public PurchId parmPurchId(PurchId _purchId = purchId)

                    {

                      purchId = _purchId;

                      return purchId;

                    }

                    [DataMember("SalesId")]

                    public SalesId parmSalesId(SalesId _salesId = salesId)

                    {

                      salesId = _salesId;


                      return salesId;

                    }


                   [DataMember("DataAreaId")]

                    public DataAreaId parmDataArea(DataAreaId _legalEntity = legalEntity)

                    {

                      legalEntity = _legalEntity;

                      return legalEntity;

                    }


                    [DataMember("SalesLine"),

                    AifCollectionType('return', Types::Class, classStr(XYZ_ICProdRcptLineContract)),

                    AifCollectionType('_salesLine', Types::Class, classStr(XYZ_ICProdRcptLineContract))]

                    public List parmSalesLine(List _salesLine  =  salesLineList)

                    {

                      salesLineList   = _salesLine;

                      return  salesLineList;

                    }

                    public static XYZ_ICProdRcptPostingRequest construct()

                    {

                      return new XYZ_ICProdRcptPostingRequest();

                    }

                }


                // Response class

                [DataContractAttribute]

                final class XYZ_ICProdRcptPostingResponse

                {

                    private boolean     success;

                    private str         errorMessage;

                    List                valueList;

                    PackingSlipId       packingSlipId;


                    [DataMember('SalesOrderNum')]

                    public PackingSlipId parmpackingSlipId(SalesId _packingSlipId = packingSlipId)

                    {

                      packingSlipId = _packingSlipId;

                      return packingSlipId;

                    }


                    [DataMember("ErrorMessage")]

                    public str parmErrorMessage(str _value = errorMessage)

                    {

                      errorMessage = _value;

                      return errorMessage;

                    }


                    [DataMember("Success")]

                    public Boolean parmSuccess(Boolean _value = success)

                    {

                      success = _value;

                      return success;

                    }


                    [DataMember("Value"),

                    AifCollectionType("Header",Types::Class,classStr(XYZ_ICProdRcptPostingRequest)),

                    AifCollectionType("return",Types::Class,classStr(XYZ_ICProdRcptPostingResponse))]

                    public List parmValue(List _value = valueList)

                    {

                      valueList = _value;

                      return valueList;

                    }

                    public static XYZ_ICProdRcptPostingResponse construct()

                    {

                      return new XYZ_ICProdRcptPostingResponse();

                    }

                }


                // service class

                final class XYZ_ICProdRcptPostingService

                {

                  PurchTable                          purchTable;

                  PurchLine                           purchLine;

                  XYZ_ICProdRcptPostingRequest        req;

                  XYZ_ICProdRcptLineContract          lineContract;

                  XYZ_ICProdRcptPostingResponse       response;

                  ListEnumerator                      leHeader;

                  ListEnumerator                      lineList;

                  PurchFormLetter                     purchFormLetter;

                  PurchFormletterParmData             purchFormLetterParmData;

                  PurchParmUpdate                     purchParmUpdate;

                  PurchParmTable                      purchParmTable;

                  PurchParmLine                       purchParmLine;

                  VendPackingSlipJour                 vendPackingSlipJour;

                  public XYZ_ICProdRcptPostingResponse postProductReceipt(XYZ_ICProdRcptPostingRequest            request)

                  {

                      List            salesLineList = new List(Types::Class);

                      //leHeader                      = header.getEnumerator();

                      salesLineList                 = request.parmSalesLine();

                      lineList                      = salesLineList.getEnumerator();

                      lineList.reset();


                      ttsbegin;

                      changecompany(request.parmDataArea())

                      {

                            select purchTable where purchTable.PurchId == request.parmPurchId();

                            /*

                            //Validate if Purchase order is in Confirmed state.

                            if(purchtable.DocumentState != VersioningDocumentState::Confirmed)

                            {

                              throw error(strFmt("The purchase order should be in confirmed state."));

                            }

                            */


                            purchFormLetterParmData  = PurchFormletterParmData::newData(                                                          DocumentStatus::PackingSlip,

                                                        VersioningUpdateType::Initial);

                        

                            purchFormLetterParmData.parmOnlyCreateParmUpdate(true);

                            purchFormLetterParmData.createData(false);

                        

                            purchParmUpdate = purchFormLetterParmData.parmParmUpdate();

                        

                            purchParmTable.clear();

                            purchParmTable.TransDate                = SystemDateGet();

                            purchParmTable.Ordering                 = DocumentStatus::PackingSlip;

                            purchParmTable.ParmJobStatus            = ParmJobStatus::Waiting;

                            purchParmTable.Num                      = request.parmpackingSlipId(); //packingSlipId;//To-Do                    check for number sequence

                            purchParmTable.PurchId                  = purchTable.PurchId;

                            purchParmTable.PurchName                = purchTable.PurchName;

                            purchParmTable.DeliveryName             = purchTable.DeliveryName;

                            purchParmTable.DeliveryPostalAddress    = purchTable.DeliveryPostalAddress;

                            purchParmTable.OrderAccount             = purchTable.OrderAccount;

                            purchParmTable.CurrencyCode             = purchTable.CurrencyCode;

                            purchParmTable.InvoiceAccount           = purchTable.InvoiceAccount;

                            purchParmTable.ParmId                   = purchParmUpdate.ParmId;

                            purchParmTable.insert();

                            

                            while (lineList.moveNext())

                            {

                              lineContract =  lineList.current();


                            // Set PurchParmLine table

                                select purchLine

                                    where purchLine.PurchId == purchTable.purchId

                                        &&  purchLine.ItemId  == lineContract.parmItemNumber()

                                            &&  purchLine.InterCompanyInventTransId == lineContract.parmICInventTransId();


                                if (purchLine)

                                {

                                  purchParmLine.InitFromPurchLine(purchLine);

                                  purchParmLine.ReceiveNow            = PurchLine.PurchQty;

                                  purchParmLine.ParmId                = purchParmTable.ParmId;

                                  purchParmLine.TableRefId            = purchParmTable.TableRefId;

                                  purchParmLine.setQty(DocumentStatus::PackingSlip, false, true);

                                  purchParmLine.setLineAmount();

                                  purchParmLine.insert();

                                }

                            }

                        

                            purchFormLetter = PurchFormLetter::construct(DocumentStatus::PackingSlip);

                            purchFormLetter.transDate(systemDateGet());

                            purchFormLetter.proforma(false);

                            purchFormLetter.specQty(PurchUpdate::All);

                            purchFormLetter.purchTable(purchTable);

                            //purchFormLetter.showQueryForm(false);


                            // This is the ID we hard code as the product receipt ID, if we do the posting via UI

                            // user would have the option to manually enter this value

                            purchFormLetter.parmParmTableNum(purchParmTable.ParmId);

                            purchFormLetter.parmId(purchParmTable.ParmId);

                            purchFormLetter.purchParmUpdate(purchFormLetterParmData.parmParmUpdate());

                            purchFormLetter.run();

                            info(strFmt("Product Receipt posted successfully."));

                      }

                            ttscommit;    

                            select vendPackingSlipJour where vendPackingSlipJour.PurchId == purchTable.PurchId; 

                            response=    XYZ_ICProdRcptPostingResponse::construct();

                            response.parmpackingSlipId(vendPackingSlipJour.PackingSlipId);

                            return response;

                  }


                  public void purchaseOrderInvoice(XYZ_ICProdRcptPostingRequest _request)

                  {

                    DocumentStatus  documentStatus;

                    PurchTable      purchTableLoc;


                    if (_request.parmPurchId())

                    {

                      purchTable = PurchTable::find(_request.parmPurchId(), true);


                      if (purchTable && purchTable.PurchStatus != PurchStatus::Invoiced)

                      {

                        purchFormLetter = purchFormLetter::construct(DocumentStatus::Invoice);

                        purchFormLetter.update(purchTable, "Inv_"+purchTable.PurchId, systemdateget());

                      }


                      select * from purchTableLoc

                          where purchTableLoc.PurchId == _request.parmPurchId();

                      if (purchTableLoc.RecId && purchTableLoc.DocumentStatus == DocumentStatus::Invoice)

                      {

                        documentStatus = purchTable.DocumentStatus;

                        response.parmSuccess(true);

                        response.parmPackingSlipId('');

                        response.parmErrorMessage(strfmt("Posted invoiced journal for purchase order                                         %1",purchTableLoc.PurchId));

                      }

                      else

                      {

                        response.parmSuccess(false);

                        response.parmPackingSlipId('');

                        response.parmErrorMessage(strFmt("Failed to post invoice for purchase order %1",                                     purchTableLoc.PurchId));

                      }

                    }

                   // return response;

                  }

                      public static XYZ_ICProdRcptPostingService construct()

                      {

                        return new XYZ_ICProdRcptPostingService();

                      }


                }


                How to create BCC in print management

                [ExtensionOf(formstr(SRSPrintDestinationSettingsForm))]

                public final class XYZSRSPrintDestinationSettingsForm_Extension

                {

                  public void init()

                  {

                    CustParameters custParameters = CustParameters::find();

                    FormRun formRun = this as  FormRun;

                   next init();

                    //_printDestinationSettings = this.args().caller() as SRSPrintDestinationSettings;

                   //SrsPrintDestinationSettings printerSettings = new SrsPrintDestinationSettings(this.parm);

                   FormStringControl mailbcccontrol = formRun.design().ControlName(FormControlStr(SRSPrintDestinationSettingsForm, MailBCC));

                    mailbcccontrol.text(custParameters.XYZBCCEmailAddress);

                    //printerSettings.parmBCc(custParameters.XYZBCCEmailAddress);

                  }

                  public void closeOk()

                  {

                    FormRun formRun = this as  FormRun;

                    next closeOk();

                    FormStringControl mailbcccontrol = formRun.design().ControlName(FormControlStr(SRSPrintDestinationSettingsForm, MailBCC));

                    CustParameters custParameters = CustParameters::find(true);

                    if(custParameters.XYZBCCEmailAddress !=  mailbcccontrol.text())

                    {

                      ttsbegin;

                      custParameters.XYZBCCEmailAddress = mailbcccontrol.text();

                      custParameters.update();

                      ttscommit;

                    }

                  }

                }

                [ExtensionOf(classStr(SRSPrintDestinationSettingsFormFormAdaptor))]

                public final class XYZSRSPrintDestinationSettingsFormFormAdaptor_Extension

                {

                  public StringEditAdaptor MailBCC()

                  {

                    return this.adaptorActivateGroup("MainGroup", False).adaptorActivateGroup("RightColumn", False).adaptorActivateGroup("TargetSpecificationGroup", False).adaptorActivateTabPage("MailTab", False).adaptorActivateGroup("MailGroup", False).adaptorActivateGroup("MailDestinationGroup", False).adaptorActivateGroup("MailCCGroup", False).adaptorActivateGroup("MailCCField", False).getStringEdit("MailCC");

                  }


                  public GroupAdaptor MailBCCField()

                  {

                    return this.adaptorActivateGroup("MainGroup", False).adaptorActivateGroup("RightColumn", False).adaptorActivateGroup("TargetSpecificationGroup", False).adaptorActivateTabPage("MailTab", False).adaptorActivateGroup("MailGroup", False).adaptorActivateGroup("MailDestinationGroup", False).adaptorActivateGroup("MailCCGroup", False).getGroup("MailCCField");

                  }


                  public ButtonAdaptor MailBCCEdit()

                  {

                    return this.adaptorActivateGroup("MainGroup", False).adaptorActivateGroup("RightColumn", False).adaptorActivateGroup("TargetSpecificationGroup", False).adaptorActivateTabPage("MailTab", False).adaptorActivateGroup("MailGroup", False).adaptorActivateGroup("MailDestinationGroup", False).adaptorActivateGroup("MailCCGroup", False).getButton("MailCCEdit");

                  }


                  public GroupAdaptor MailBCCGroup()

                  {

                    return this.adaptorActivateGroup("MainGroup", False).adaptorActivateGroup("RightColumn",                 False).adaptorActivateGroup("TargetSpecificationGroup", False).adaptorActivateTabPage("MailTab",     False).adaptorActivateGroup("MailGroup", False).adaptorActivateGroup("MailDestinationGroup",         False).getGroup("MailCCGroup");

                  }

                }



                [ExtensionOf(classStr(SrsReportEMailDataContract))]

                public final class XYZSrsReportEMailDataContract_Extension

                {

                 // public SrsReportEMailDataContract  emailContract;

                  public str emailBCc;


                  [DataMemberAttribute]

                   public str parmBCc(str _value = emailBCc)

                  {

                    emailBCc = _value;

                    return emailBCc;

                  }


                  public void validate()

                  {

                    SrsReportEMailDataContract srsReportEMailDataContract = new SrsReportEMailDataContract();

                    next Validate();


                    if (this.parmBCc() &&

                            !SysEmailDistributor::validateEmails(this.parmBCc()))

                    {

                      throw error(strfmt("@SYS134596", "@SYS80200"));

                    }

                  }


                  public void removeInvalidEmails()

                  {

                    str parmBCcValue;


                    next removeInvalidEmails();


                    Set invalidEmails = new Set(Types::String);


                    str getOnlyValidEmails(str emailsString)

                    {

                      System.Exception ex;

                      container validEmails;


                      if (!emailsString)

                      {

                        return "";

                      }


                      container emails = str2con(emailsString, ';');

                      int i;

                      for (i = 1; i <= conLen(emails); i++)

                      {

                        str currentEmail = conPeek(emails, i);

                        if (!System.String::IsNullOrWhiteSpace(currentEmail))

                        {

                          try

                          {

                            new System.Net.Mail.MailAddress(strLRTrim(currentEmail));

                            if (SysEmailDistributor::validateEmail(currentEmail))

                            {

                              validEmails += strLRTrim(currentEmail);

                            }

                            else

                            {

                              if (invalidEmails.in(currentEmail) < 1)

                              {

                                invalidEmails.add(currentEmail);

                              }

                            }

                          }

                          catch (ex)

                          {

                            if (invalidEmails.in(currentEmail) < 1)

                            {

                              invalidEmails.add(currentEmail);

                            }

                          }

                        }

                      }


                      return con2Str(validEmails, ';');

                    }

                    ;


                    parmBCcValue = getOnlyValidEmails(this.parmBCc());


                    if (SrsReportEMailDataContract::autoRemoveInvalidEmailsLocal())

                    {

                      this.parmBCc(parmBCcValue);

                    }


                    if (invalidEmails && !invalidEmails.empty())

                    {

                      str warningMessage = 'The following emails are invalid:';

                      var setEnumerator = invalidEmails.getEnumerator();

                      setEnumerator.reset();

                      while (setEnumerator.moveNext())

                      {

                        warningMessage += strFmt('%1;', setEnumerator.current());

                      }


                      warning(warningMessage);

                    }

                  }


                  private static boolean autoRemoveInvalidEmailsLocal()

                  {

                    boolean autoRemoveInvalidEmails = false;

                    SysGlobalobjectCache sgoc = new SysGlobalObjectCache();


                    str scope = tableStr(SysReportAdministration);

                    // Read from global cache first.

                    container conSGOC = sgoc.find(scope, [SysReportAdministration::getAutoRemoveInvalidEmailsKey()]);

                    if(conSGOC != conNull())

                    {

                      autoRemoveInvalidEmails = conPeek(conSGOC, 1);

                    }

                    else

                    {

                      autoRemoveInvalidEmails = SysReportAdministration::getAutoRemoveInvalidEmails();

                      sgoc.insert(scope, [SysReportAdministration::getAutoRemoveInvalidEmailsKey()], [autoRemoveInvalidEmails]);

                    }


                    return autoRemoveInvalidEmails;

                  }

                }


                [ExtensionOf(classStr(SrsReportRunMailer))]
                public final class XYZSrsReportRunMailer_Extension
                {
                  public boolean emailReport(SrsReportEMailDataContract emailContract, System.Byte[] reportBytes, str fileName)
                  {
                    boolean result = false;
                    result = next emailReport(emailContract, reportBytes, fileName);


                    //if( mailer)
                    //{
                    //  var messageBuilder = new SysMailerMessageBuilder();

                    //  messageBuilder.setFrom(fromAddress).setSubject(emailContract.parmSubject())
                    //                      .setBody(emailContract.parmBody(strFmt("To address %1", emailContract.parmTo()) +  strFmt("CC address %1", emailContract.parmCc())))
                    //                      .addAttachment(new System.IO.MemoryStream(reportBytes), fileName)
                    //                      .addBcc(emailContract.parmBCc())
                    //                      .addTo(emailContract.parmTo()); //added
                    //  result = mailer.sendNonInteractive(messageBuilder.getMessage());

                    //}

                    return result;
                  }

                }



                Tuesday, January 24, 2023

                How to create print management

                [ExtensionOf(classStr(PrintMgmtDocType))]

                public final class xyzPrintMgmtDocType_Extension

                {

                  [SubscribesTo(classStr(PrintMgmtDocType), delegateStr(PrintMgmtDocType, getDefaultReportFormatDelegate))]

                  public static void PrintMgmtDocType_getDefaultReportFormatDelegate(PrintMgmtDocumentType _docType, EventHandlerResult _result)

                  {

                    switch (_docType)

                    {

                      case PrintMgmtDocumentType:: xyzProFormaInvoice :

                        _result.result(ssrsReportStr(xyzProformaInvoiceSO,Report));

                        break;

                    }

                  }

                }


                [ExtensionOf(classStr(PrintMgmtDocType))]

                public final class xyzPrintMgmtDocType_Extension

                {

                  [SubscribesTo(classStr(PrintMgmtDocType), delegateStr(PrintMgmtDocType, getDefaultReportFormatDelegate))]

                  public static void PrintMgmtDocType_getDefaultReportFormatDelegate(PrintMgmtDocumentType _docType, EventHandlerResult _result)

                  {

                    switch (_docType)

                    {

                      case PrintMgmtDocumentType::xyzProFormaInvoice :

                        _result.result(ssrsReportStr(xyzProformaInvoiceSO,Report));

                        break;

                    }

                  }


                [ExtensionOf(classStr(PrintMgmtReportFormatPublisher))]

                public final class CPLPrintMgmtReportFormatPublisher_Extension

                {

                  [SubscribesTo(classStr(PrintMgmtReportFormatPublisher), delegateStr(PrintMgmtReportFormatPublisher, notifyPopulate))]

                  public static void PrintMgmtReportFormatPublisher_notifyPopulate()

                  {

                    #PrintMgmtSetup

                 

                    void addFormat(PrintMgmtDocumentType _type, PrintMgmtReportFormatName _name,

                                   PrintMgmtReportFormatCountryRegionId _countryRegionId = #NoCountryRegionId)

                    {

                      CPLProformaInvoiceAddPrintMgmtReportFormat::addPrintMgmtReportFormat(_type, _name, _name,

                               _countryRegionId);

                    }

                 

                    addFormat(PrintMgmtDocumentType::CPLProFormaInvoice,

                                      ssrsReportStr(CPLProformaInvoiceSO, Report));

                  }

                }



                class XYZProformaInvoiceAddPrintMgmtReportFormat

                {

                  public static void addPrintMgmtReportFormat(

                        PrintMgmtDocumentType _type,

                        PrintMgmtReportFormatName _name,

                        PrintMgmtReportFormatDescription _description,

                        PrintMgmtReportFormatCountryRegionId _countryRegionId,

                        PrintMgmtReportFormatSystem _system = false,

                        PrintMgmtSSRS _ssrs = PrintMgmtSSRS::SSRS)

                  {

                    PrintMgmtReportFormat printMgmtReportFormat;

                 

                    select firstonly printMgmtReportFormat

                            where printMgmtReportFormat.DocumentType == _type

                                && printMgmtReportFormat.Description == _description

                                && printMgmtReportFormat.CountryRegionId == _countryRegionId;

                 

                    if (!printMgmtReportFormat)

                    {

                      // Add the new format

                      printMgmtReportFormat.clear();

                      printMgmtReportFormat.DocumentType = _type;

                      printMgmtReportFormat.Name = _name;

                      printMgmtReportFormat.Description = _description;

                      printMgmtReportFormat.CountryRegionId = _countryRegionId;

                      printMgmtReportFormat.System = _system;

                      printMgmtReportFormat.ssrs = _ssrs;

                      printMgmtReportFormat.insert();

                    }

                  }


                }



                Monday, January 23, 2023

                Multiselect lookup in d365

                 

                Create static query and add fields.


                class CPLBlockQualityOrdersMultiselectCtrl

                {

                  [FormEventHandler(formStr(InventParameters), FormEventType::Initialized)]

                  public static void InventParameters_OnInitialized(xFormRun sender, FormEventArgs e)

                  {

                    FormRun formRun = sender as FormRun;

                    SysLookupMultiSelectCtrl msCtrl;

                    Query               blockQualityOrder         =   formRun.buildDocuTypeQuery();

                    FormStringControl   blockQualityorderCtrl        =   formRun.design().controlName('CPLSpecificBlockQualityOrder');

                    InventParameters    inventParameters    =   InventParameters::find();

                   msCtrl   =          SysLookupMultiSelectCtrl::construct(formRun,blockQualityOrderCtrl,querystr(CPLBlockQualityOrder), false, [tableNum(WMSJournalName), fieldNum(WMSJournalName,journalNameId)]);

                    msCtrl.refreshQuery(blockQualityOrder);

                    msCtrl.set(formRun.getSelectedNotes(inventParameters.CPLBlockQualityOrder));


                    formRun.setMultiselectCtrl(msCtrl);

                  }


                  [FormDataFieldEventHandler(formDataFieldStr(InventParameters, InventParameters,     CPLBlockQualityOrder), FormDataFieldEventType::Modified)]


                public static void CPLBlockQualityOrder_OnModified(FormDataObject sender, FormDataFieldEventArgs e)

                  {

                    FormRun formRun = sender.datasource().formRun();

                    SysLookupMultiSelectCtrl msCtrl = formRun.parmsCtrl();


                    InventParameters    inventParameters    =              formRun.dataSource(FormDataSourceStr(InventParameters, 

                      inventParameters)).cursor() as InventParameters;

                    inventParameters.CPLBlockQualityOrder     =   con2Str(msCtrl.getSelectedFieldValues(), ';');

                  }

                }

                ----------------------------------------------------------------------------------------------------

                [ExtensionOf(formstr(InventParameters))]

                public final class CPLDevInventParametersForm_Extension

                {

                  public SysLookupMultiSelectCtrl    msCtrl;

                    public SysLookupMultiSelectCtrl parmsCtrl()

                    {

                      return msCtrl;

                    }

                  public void setMultiselectCtrl(SysLookupMultiSelectCtrl multiselect)

                  {

                    msCtrl = multiselect;

                  }

                  public Query buildDocuTypeQuery()

                  {

                    Query       wmsJournalName = new Query(queryStr(CPLBlockQualityOrder));

                    return wmsJournalName;

                  }

                  container getSelectedNotes(str _noteStr)

                  {

                    WMSJournalName wmsJournalName;

                    container   tmpValues, conIds, conName;

                    int         idx;

                    if(_noteStr)

                    {

                      tmpValues = str2con(_noteStr, ';');

                    }

                     

                    for(idx=1; idx<=conLen(tmpValues); idx++)

                    {

                      wmsJournalName = WMSJournalName::find(conPeek(tmpValues, idx));

                      conIds += wmsJournalName.RecId;

                      conName += wmsJournalName.journalNameId;

                    }

                     

                    return [conIds, conName, conIds];

                  }

                }

                Reference 

                https://erpdax.wordpress.com/2022/03/24/multiselect-lookup-in-d365-fo/

                Containers

                  Why Containers? In X++ (Object oriented programming language) the data or values stored in a  Variable  are of below types: Primitive data...