23 October 2022

Modify Email Subject for a report in D365 F&O from x++

 

Modify Email Subject for a report in D365 F&O from x++



public void printReport()
    {
        if (reportContract.parmRdpName() == "ProjInvoiceDP") //Dp classs name
        {
            ProjInvoiceContract contract = reportContract.parmRdpContract() as PSAProjInvoiceContract;         
          
            ProjInvoiceJour       invoiceJournal;
             
            select firstonly * from invoiceJournal where invoiceJournal.RecId == contract.parmProjInvoiceJourRecId();           //Get the which field we need to add in subjcet 
 
            printSettings.emailSubject(strFmt(" %1", invoiceJournal.ProjInvoiceId));
            printSettings.fileFormat(SRSReportFileFormat::PDF);
            printSettings.fileName(strFmt("SAProjInvoiceModern.Report")); //attached file output  
        }
 
        next printReport();
    }

10 September 2022

Get object of Caller Form In Extension Class/ element to use in init extenion in D365Fo / Is it possible to get element.args() from an extended method in D365FO

Hi, in form method COC we can directly use the this instead of element.Even we can use the control names as it is.
Below is the example.

[ExtensionOf(formstr(ReqTransPO))]
final class ReqTransPOForm_Extension
{
    public void init()
    {
        next init();
        if (this.args().menuItemName() == "ReqPOGridView")
        {
            Contol.visible(false); // form control making visible false
            Control.visible(false);// form control making visible false
        }
    }

}

Get the selected records in the form grid in class 

class ClassParmData

{

         CustTable custTable;// table buffer declaration

}

public static void main(Args args)

{

         ClassParmData parmData;

         Table1 table1;

         FormDataSource fds;

 

         if(args.record().TableId == tablenum(CustTable))

         {

                  custTable = args.record(); // assigning the selected record

         }

 

         fds = custTable.dataSource();// getting the datasource

 

         parmData= new ClassParmData(fds); //passing the form datasource to New() method

}

 

void new(FormDataSource fdst) // receving the datasource to fdst-FormDataSource

{

         // 1st optoin to do this

         MultiSelectionHelper helper = MultiSelectionHelper::construct();

        helper.parmDatasource(fdst);

         custTable = helper.getFirst();

         while (custTable.RecId != 0)

        {

                  custTable = helper.getNext();

         }

         // second way

         for(custTable = fdst.getFirst(true); custTable; custTable = fdst.getNext()) // fdst.getFirst(True) to select marked records

         {

                  info(strfmt(custTable.Field1));

         }

         //if you are updating some records in the form write the below line to refresh the data in form.

         //fdst.research();

}

 

void parmFormDataSource(formDataSource fdst)

{

         for(custTable = fdst.getFirst(true); custTable; custTable = fdst.getNext()) // fdst.getFirst(True) to select marked records

         {

         info(strfmt(custTable.Field1));

         }

         //if you are updating some records in the form write the below line to refresh the data in form.

         //fdst.research();

}

01 August 2022

Sys operation frame work with example and Multi select lookup using Sys operation frame work service class

This post is to get the sysoperation framework exmaple with the multi select lookup using UI builder class.



 Step1. Create a contract class as follows.

[DataContractAttribute,

SysOperationContractProcessingAttribute(classStr(TRGPlannedPOGroupUIBuilder))]


internal final class TRGPlannedPOGroupContract implements SysOperationValidatable

{

    List saesOrderNumber;


        [DataMemberAttribute("Sales order"),AifCollectionTypeAttribute("Sales order", Types::String),

       SysOperationLabelAttribute(literalStr("Sales order"))]

    public List parmSalesOrder(List _saesOrderNumber = saesOrderNumber)

    {

        saesOrderNumber = _saesOrderNumber;


        return saesOrderNumber;

    }

    public boolean validate()

    {

        boolean             isValid = true;

        List            salesOrderList = new List(Types::String);

        salesOrderList = this.parmSalesOrder();

        if(!salesOrderList.elements())

        {

            isValid = checkFailed("Sales order should not be empty");

        }

        return isValid;

    }

}


Step2: Create the service class.

internal final class TRGPlannedPOGroupService

{

    List salesOrderList;

    public void processGroup(TRGPlannedPOGroupContract _contract)

    {

       ListIterator listIterator;


        listIterator = new ListIterator(_contract.parmSalesOrder());


        while (listIterator.more())

        {

            Info(listIterator.value());

            listIterator.next();

        }

    }

}


Step 3: Create controller class:


class TRGPlannedPOGroupController extends SysOperationServiceController

{

    public static void main(Args _args)

    {

        TRGPlannedPOGroupController controller =

            new TRGPlannedPOGroupController(classStr(TRGPlannedPOGroupService),

            methodStr(TRGPlannedPOGroupService, processGroup),SysOperationExecutionMode::Synchronous);


        TRGPlannedPOGroupContract contract = controller.getDataContractObject();

        //contract.parmArgs(_args);

        controller.startOperation();

    }


    public ClassDescription caption()

    {

        return "Group planned purchase orders";

    }


    public LabelType parmDialogCaption(LabelType _dialogCaption = dialogCaption)

    {

        return "Group planned purchase orders";

    }

}


Step 4: Create UI builder class to get multi slection lookup in the dailog.

internal final class TRGPlannedPOGroupUIBuilder extends SysOperationAutomaticUIBuilder

{

    DialogField     dialogSalesOrder;

    TRGPlannedPOGroupContract plannedPOGroupContract;

    DialogField availableCompanies;

    private void SalesIdLookup(FormStringControl _control)

    {

        Query       query;

        container   conSalesOrder;

        query = new Query(queryStr(SalesTableListPage));

        SysLookupMultiSelectGrid::lookup(query,_control,_control,_control,conSalesOrder);

    }


    public void build()

    {

        int i;

        TRGPlannedPOGroupContract Contract;

        contract = this.dataContractObject() as TRGPlannedPOGroupContract;

        dialogSalesOrder = this.addDialogField(methodStr(TRGPlannedPOGroupContract, parmSalesOrder),contract);

    }


    public void postBuild()

    {

        TRGPlannedPOGroupContract Contract;

        super();

        

        contract = this.dataContractObject() as TRGPlannedPOGroupContract;

        dialogSalesOrder = this.bindInfo().getDialogField(contract, methodStr(TRGPlannedPOGroupContract, parmSalesOrder));

        dialogSalesOrder.lookupButton(FormLookupButton::Always);

    }


    public void postRun()

    {

        Query         query     = new Query();

        QueryBuildDataSource    qbdsLegalEntity     = query.addDataSource(tablenum(SalesTable));

        qbdsLegalEntity.fields().addField(fieldNum(SalesTable, SalesId));

        container selectedFields = [tableNum(SalesTable), fieldNum(SalesTable, SalesId)];

 

        SysLookupMultiSelectCtrl::constructWithQuery(this.dialog().dialogForm().formRun(), dialogSalesOrder.control(), query, false, selectedFields);

    }

}

29 July 2022

Multi Select Lookup in Forms with Filters in D365 / Custom multi select lookup in form D365FO

Standard User dimension 1 dropdown. Multi-selection will be allowed in these dropdowns. Multiple selected values will be stored in the field, separated by semi-colon (;).



LookUp code 

     


Event handler class to get the  multi select lookup   


class TRGReqTransPOEventHandler


{    

    [FormControlEventHandler(formControlStr(ReqTransPo,TRGSite), FormControlEventType::Lookup),


        SuppressBPWarning('BPParameterNotUsed','Parameter required by the event method')]


    public static void TRGSite_OnLookup(FormControl sender, FormControlEventArgs e)


    {

        Query                   query = new Query();

        QueryBuildDataSource    queryBuildDataSource;  

        container            selectFieldPurchRef = [tableNum(InventSite), fieldNum(InventSite, SiteId)];

        FormRun             fr = sender.formRun();


        queryBuildDataSource = query.addDataSource(tableNum(InventSite));

        queryBuildDataSource.addSelectionField(fieldNum(InventSite, SiteId));

        queryBuildDataSource.orderMode(ordermode::GroupBy);

        queryBuildDataSource.addSortField(FieldNum(InventSite,SiteId));


        SysLookupMultiSelectCtrl::constructWithQuery(fr,sender,query,false,selectFieldPurchRef);


    }


    [FormControlEventHandler(formControlStr(ReqTransPo, TRGSalesId), FormControlEventType::Lookup),


    SuppressBPWarning('BPParameterNotUsed','Parameter required by the event method')]


    public static void TRGSalesId_OnLookup(FormControl sender, FormControlEventArgs e)


    {


        Query                       query = new Query();

        QueryBuildDataSource        queryBuildDataSource;


        container                   selectFieldPurchRef = [tableNum(TRGReqTransView), fieldNum(TRGReqTransView, InventDimension3)];

        FormRun                     fr = sender.formRun();

        queryBuildDataSource        = query.addDataSource(tableNum(TRGReqTransView));

        queryBuildDataSource.addSelectionField(fieldNum(TRGReqTransView, InventDimension3));

        queryBuildDataSource.orderMode(ordermode::GroupBy);

        queryBuildDataSource.addSortField(FieldNum(TRGReqTransView, InventDimension3));

        queryBuildDataSource.addRange(fieldNum(HDMReqTransView, InventDimension3)).value(SysQuery::valueNotEmptyString());


        SysLookupMultiSelectCtrl::constructWithQuery(fr,sender,query,false,selectFieldPurchRef);


    }

    [FormControlEventHandler(formControlStr(ReqTransPo, TRGSite), FormControlEventType::Modified),


        SuppressBPWarning('BPParameterNotUsed','Parameter required by the event method')]


    public static void TRGSite_OnModified(FormControl sender, FormControlEventArgs e)


    {

        FormRun fr = sender.formRun();

        FormDataSource formDataSourceId  = fr.dataSource(formDataSourceStr(ReqTransPo, InventDim));

        FormDataSource formDataSource  = fr.dataSource(formDataSourceStr(ReqTransPo, ReqPO));

        formDataSourceId.executeQuery();

        formDataSource.executeQuery();

    }

}


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


On Modified :


    


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


[ExtensionOf(formdatasourcestr(ReqTransPO,InventDim))]


internal final class TRGReqTransPOInventDimDS_Extension

{    


    public void executeQuery()

    {           

        #characters

        FreeText1000 siteId = this.formRun().design().controlName(formControlStr(ReqTransPo,TRGSite)).valueStr();

        FreeText1000 salesId = this.formRun().design().controlName(formControlStr(ReqTransPo,TRGSalesId)).valueStr();

        QueryBuildRange siteQBR,salesIdQBR;

        siteQBR = sysquery::findorcreaterange(this.queryBuildDataSource(),fieldnum(InventDim,InventSiteId));

        salesIdQBR = sysquery::findorcreaterange(this.queryBuildDataSource(),fieldnum(InventDim,InventDimension3));


        if (siteId)

        {

            siteQBR.value(strReplace(siteId,#semicolon,#comma));

        }

        else

        {

            siteQBR.value(SysQuery::valueUnlimited());

        }

        if (salesId)

        {

            salesIdQBR.value(strReplace(salesId,#semicolon,#comma));

        }

        else

        {

            salesIdQBR.value(SysQuery::valueUnlimited());

        }

        next executeQuery();

    }

}


How to restore bacpack file in SQL

Work Around: 

You need to Download and install the latest Data Tier Application framework (18.2) (Link:https://www.microsoft.com/en-us/download/confirmation.aspx?id=58207) and run the SQLPACKAGE.exe located in C:\Program Files\Microsoft SQL Server\150\DAC\bin

Open CMD run as admin:

The command would look like below.

CD "C:\Program Files\Microsoft SQL Server\150\DAC\bin"

SqlPackage.exe /a:import /sf:"C:\temp\uatbackup.bacpac" /tsn:localhost /tdn:AxDBFromUAT /p:CommandTimeout=1200


Open Sql server change Database names using below code :

USE master;
GO
ALTER DATABASE AxDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
ALTER DATABASE AxDB MODIFY NAME = AxDB_Old;
GO
ALTER DATABASE AxDB_Old SET MULTI_USER
GO

Do Database Sync ..


Thanks .....

27 July 2022

Form string control modified method COC in D365FO / Extend Form Control methods / Chain of command form string control

Control chain of command to get the selected record in D365FO

[ExtensionOf(formControlStr(ReqTransPO,TRGSite))]

internal final class TRGReqTransPO_TRGSiteCtrl_Extension

{

    public boolean modified()

    {

        boolean ret;

    

        FormStringControl formStringControl = any2Object(this) as FormStringControl;

        FormDataSource formDatasource = formStringControl.formRun().dataSource(formDataSourceStr(ReqTransPO,InventDim));        

        ret = next modified();

        formDatasource.executeQuery();,

    

        return ret;

    }


}

25 July 2022

Query with group by and joins in lookup D365FO

 [FormControlEventHandler(formControlStr(TRGSysMailerMessageEditor, TRGTo), FormControlEventType::Lookup)]

    public static void TRGTo_OnLookup(FormControl sender, FormControlEventArgs e)

    {

        TRGSysMailerExchange   sysMailerExchange   = sender.formRun().args().caller() as TRGSysMailerExchange;

        CustAccount         custAccount         = sysMailerExchange.parmAccountNum();        Query query = new Query();

        QueryBuildDataSource qbds,qbds1,qbds2,qbds3,qbds4,qbds5;

        qbds = query.addDataSource(tableNum(LogisticsLocationRole));

        qbds.addSelectionField(FieldNum(LogisticsLocationRole,Name));

        qbds.orderMode(ordermode::GroupBy);

        qbds.addSortField(FieldNum(LogisticsLocationRole,Name));

        qbds1 = qbds.addDataSource(tableNum(LOGISTICSELECTRONICADDRESSROLE));

        qbds1.joinMode(JoinMode::InnerJoin);

        qbds1.addLink(fieldNum(LOGISTICSLOCATIONROLE,RecId),fieldNum(LOGISTICSELECTRONICADDRESSROLE,LOCATIONROLE));

        qbds2 = qbds1.addDataSource(tableNum(CustTable));

        //qbds2.addRange(fieldNum(CustTable, AccountNum)).value(queryValue(custAccount));

        qbds3 = qbds2.addDataSource(tableNum(DIRPARTYCONTACTINFOVIEW));

        //qbds3.addRange(fieldNum(DIRPARTYCONTACTINFOVIEW, Type)).value(queryValue(LogisticsElectronicAddressMethodType::Email));

        qbds3.joinMode(JoinMode::InnerJoin);

        qbds3.addLink(fieldNum(CustTable,Party),fieldNum(DIRPARTYCONTACTINFOVIEW,party));

        qbds4 = qbds3.addDataSource(tableNum(LOGISTICSELECTRONICADDRESS));

        qbds4.joinMode(JoinMode::InnerJoin);

        qbds4.addLink(fieldNum(DIRPARTYCONTACTINFOVIEW,ELECTRONICADDRESS),fieldNum(LOGISTICSELECTRONICADDRESS,RecId));

        SysTableLookup      sysTableLookup  = SysTableLookup::newParameters(tableNum(LogisticsLocationRole), sender);

        sysTableLookup.addLookupfield(fieldNum(LogisticsLocationRole, Name));        sysTableLookup.parmQuery(query);

        sysTableLookup.performFormLookup();        //cancel the call to super() to prevent the system from trying to show        //the lookup form twice and cause an error.

        FormControlCancelableSuperEventArgs cancelableSuperEventArgs = e as FormControlCancelableSuperEventArgs;

        cancelableSuperEventArgs.CancelSuperCall();

    }

22 July 2022

Form multi select lookup using control in D365FO

 /// <summary>

/// 

/// </summary>

class TRGReqTransPOEventHandler

{

    

    /// <summary>

    ///

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="e"></param>

    [FormControlEventHandler(formControlStr(ReqTransPo, TRGSalesId), FormControlEventType::Lookup)]

    public static void TRGSalesId_OnLookup(FormControl sender, FormControlEventArgs e)

    {

        Query                query = new Query();

        QueryBuildDataSource queryBuildDataSource;

        QueryBuildRange      queryBuildRangeOrderAcc, queryBuildRangeStatus;

        FormDataSource       formDataSource;

        SalesTable           salesTable;

        container            selectFieldPurchRef = [tableNum(SalesTable), fieldNum(SalesTable, SalesId)];


        queryBuildDataSource = query.addDataSource(tableNum(SalesTable));

        queryBuildDataSource.addSelectionField(fieldNum(SalesTable, SalesId));

        queryBuildDataSource.fields().dynamic(NoYes::No);

        queryBuildDataSource.fields().clearFieldList();

        queryBuildDataSource.fields().addField(fieldNum(SalesTable, SalesId));

        SysLookupMultiSelectCtrl::constructWithQuery(fr,sender,query,false,selectFieldPurchRef);

    }

}

21 June 2022

Email the attachments using x++ code in D365FO via SysMailerMessageBuilder, multiple attachments

 class EmailJob

{


    public static void main(Args _args)

    {

        DocuRef     docuRef;

        DocuType    docuType;

        SysMailerMessageBuilder messageBuilder = new SysMailerMessageBuilder();

        Email   toEmail;

        Email   fromEmail;

        SysEmailSystemTable emailSystemTable = SysEmailSystemTable::find("WFEMAIL"); //  system email template email id.

        SysEmailMessageTable sysEmailMessageTable = SysEmailMessageTable::find(emailSystemTable.EmailId, emailSystemTable.DefaultLanguage);       

         

        try

        {

            FromEmail = emailSystemTable.SenderAddr;//"abc@3ELogistics.onmicrosoft.com";

            toEmail   = "to@gmail.com";


            messageBuilder.setBody("Hello from D365", false);

            messageBuilder.setSubject("Email Test from D365");

            messageBuilder.addTo(toEmail);

            // Note: not calling setFrom() defaults to the current user for SMTP client, whereas

            // when sent to Outlook any setFrom() value will be ignored since profiles on the client are used

            messageBuilder.setFrom(fromEmail);


            while select docuRef

                where   docuRef.RefCompanyId    == curExt()

                && docuRef.RefTableId           == tableNum(CustInvoiceTable)

                && docuRef.RefRecId      == 5637151326 // CustInvoiceTable.recId

            Exists join docuType

                where docuType.typeId == docuRef.TypeId

                && docuType.TypeGroup == docuTypeGroup::File

            {

                messageBuilder.addAttachment(DocumentManagement::getAttachmentStream(docuRef),docuRef.Name + '.pdf');

            }

            SysMailerFactory::sendInteractive(messageBuilder.getMessage());

            // Try using sendNonInteractive method too

        }

        catch (Exception::Error)

        {

            throw error("@SYS33567");

        }

    }


}

26 May 2022

Getting Dimension value and description from default dimension in D365FO

 DefaultDimensionView    defaultDimensionView;

    
    select defaultDimensionView
        where defaultDimensionView.DefaultDimension == _defualtDimension//recId
        && defaultDimensionView.Name == 'CostCenter';    

    info(defaultDimensionView.displayvalue);
info(defaultDimensionView.dimensionDiscription());

============================================================

DefaultDimensionView dimensionView;
        DimensionAttribute dimensionAttribute;

        select firstOnly dimensionView
            where dimensionView.DefaultDimension == 5637146834
        join dimensionAttribute
            where dimensionView.Name == dimensionAttribute.Name
            && dimensionView.Name == 'Costcenter';

        info(dimensionView.DisplayValue);

        info(strFmt("Display value= %1",dimensionView.dimensionDiscription()));

04 April 2022

How to get the selected query range value in AX 2012 and D365FO

 QueryBuildRange accountRange;

accountRange = qbd.findRange(fieldNum(VendTable, AccountNum)); if (accountRange) { info(accountRange.value()); }

24 March 2022

COC ,Access to another data source from data source method on form

  FormDataSource     salesLine_ds = this.formRun().dataSource(formDataSourceStr(SalesTable, salesLine));

        SalesLine salesLine = salesLine_ds.cursor();

29 January 2022

How to get sales order delivery postal address Phone ,street in D365FO

 LogisticsPostalAddress deliveryPostalAddress = LogisticsPostalAddress::findRecId(salesTable.DeliveryPostalAddress);

deliveryPostalAddress.City;                   

 deliveryPostalAddress.State;

            

10 January 2022

How to get product variants in D365FO using X++

  public EcoResProductDisplayProductNumber getProductVariants(SalesLine _saleLine)

    {

        InventDimCombination            inventDimCombination  = InventDimCombination::findVariantId(_saleLine.RetailVariantId);

        InventDim                       inventDim;

        InventDistinctProductExpanded   inventDistinctProductExpanded;


        select inventDistinctProductExpanded

            where inventDistinctProductExpanded.ItemId == _saleLine.ItemId

            && inventDistinctProductExpanded.InventDimId == inventDimCombination.InventDimId;


        return inventDistinctProductExpanded.DisplayProductNumber;

    }

Ledger Voucher creation Framework and x++ code to create ledger voucher

 Please click her for MS reference file Below is the out of the box example reference and code. SalesInvoiceJournalPostSubBill_Extension-...