Thursday, March 31, 2022

Get the recId from lookup in D365FO

 To get the recid or any other field value we can use lookupReference method in D365FO but it is only for recid relation field only.

We can achieve by 2 ways 

1. create new lookup form and calling from lookup method.

2. need to give recid relation and using lookupReference method.


Way1:

Click here

Way 2: lookupReference method

public Common lookupReference(FormReferenceControl _formReferenceControl)
{
    Common                      ret;
    
   // ret = super(_formReferenceControl);

    SysReferenceTableLookup sysReferenceTableLookup;
    Query query;
    QueryBuildDataSource queryBuildDataSource;
     
    // Add the fields that we want to display in the lookup form.
    sysReferenceTableLookup = SysReferenceTableLookup::newParameters(tableNum(WMSLocation), 
                                                                        _formReferenceControl);
    sysReferenceTableLookup.addLookupfield(fieldNum(WMSLocation, wmsLocationId));
    sysReferenceTableLookup.addLookupfield(fieldNum(WMSLocation, LocProfileId));
    sysReferenceTableLookup.addLookupMethod(tableMethodStr(WMSLocation, inventSiteId));
    sysReferenceTableLookup.addLookupfield(fieldNum(WMSLocation, InventLocationId));

    query = new query();
     
    queryBuildDataSource = query.addDataSource(tableNum(WMSLocation));
    queryBuildDataSource.addRange(fieldNum(WMSLocation, InventLocationId)).value(queryValue(InventLocation));
     
    sysReferenceTableLookup.parmQuery(query);
    
    ret = sysReferenceTableLookup.performFormLookup();

    if (ret)
    {
        InventLocationId    InventLocationId = ret.(fieldNum(WMSLocation, InventLocationId));
        
        Info(InventLocationId);
        Info(strFmt('%1',ret.RecId));
    }

    return ret;

    }
    
}

Keep Daxing!!

More than one form was opened at once for the lookup control In D365Fo.

I have added a new field in standard form and I have written lookup code by using event handler. When I click on that control I am getting " More than one form was opened at once for the lookup control" this error. To resolve this we wan use below code.

[FormControlEventHandler(formControlStr(SalesTable, InventLoaction), FormControlEventType::Lookup)] public static void InventLoaction_OnLookup(FormControl sender, FormControlEventArgs e) {

FormControlCancelableSuperEventArgs     eventArg = e as FormControlCancelableSuperEventArgs;

eventArg.CancelSuperCall();

}


Keep Daxing!!


Args in D365FO

 By using args we can call the form or different types of menu items. 

Args in D365FO.

    Args         args = new Args();
    FormRun      formRun;

    args = new Args();
    //args = new Args(formstr(Myform));

    args.parm('Value');//string value
    args.name(formstr(Myform));//child form name
    args.record(custTable);//Table buffer
    args.parmEnumType(EnumNum(NoYes));//ENum
    args.parmEnum(NoYes::Yes);//Enum elements
    args.parmobject(myList);//Objects we can pass
    args.caller(this);//element

    // Open mode
    //args.parmEnumType(enumNum(FormOpenMode));
    //args.parmEnum(FormOpenMode::ForEdit);
Way 1:
    formrun = classfactory.formrunclass(args);

    formrun.init();
    formrun.run();
    formrun.wait();

formDataSource = formrun.dataSource();
table buffer   = formDataSource.cursor().data();
Way 2:

    new MenuFunction(menuitemdisplaystr(menu item name), 
                    MenuItemType::Display).run(args);

    If (menuFunction.checkAccessRights())
    {

    }




Keep Daxing!!

Wednesday, March 30, 2022

Create site, warehouse, location using x++

 Create site and warehouse using x++.


    InventSite      inventSite;
    ReqSitePolicy   reqSitePolicy;
    InventLocation  inventLocation;

    //site creation
    inventSite.clear();
    inventSite.initValue();
    inventSite.SiteId   = 'Site 1';
    inventSite.Name     = 'Test Site 1';
    inventSite.insert();


    // In site form <ReqSitePolicy> datasource link type is inner join.
    // So creating the record in <ReqSitePolicy> table.

    reqSitePolicy.clear();
    reqSitePolicy.InventSiteId = inventSite.SiteId;
    reqSitePolicy.insert();

    // warehouse creation
    inventLocation.clear();
    inventLocation.initValue();
    inventLocation.InventLocationId = 'WHS 1';
    inventLocation.InventSiteId     = inventSite.SiteId;
    inventLocation.Name             = 'Test WHS 1';
    //inventLocation.WHSEnabled     = true;
    inventLocation.insert();

    // Location
    WMSLocation             wmsLocation;

    wmsLocation.clear();
    wmsLocation.initValue();
    wmsLocation.inventLocationId    = inventLocation.InventLocationId;
    wmsLocation.wMSLocationId       = 'Location 1';
    wmsLocation.LocProfileId        = 'LocProfileId';
    wmsLocation.insert();

Keep Daxing!!

Transaction does not contain a required signature In D365FO

 While updating the table from code I am getting the error "Transaction does not contain a required signature" because e-sign is activated for my table. 

We can use 2 ways.

Way 1 : Use skipDatabaseLog method before update/insert.

mYTable.skipDatabaseLog(true); // It will not populate the dialog.


Way 2 : It will populate the dialog

I have created the below method and I have called before update method.

public static boolean callEsignProcedure(DatabaseLogType    _databaseLogType, Common _common)
{
    Info        info = new Info();

    return info.collectESignature(_databaseLogType, _common);
}



// In my code
if (MyTable::callEsignProcedure(DatabaseLogType::Update, mYTable))
{  
    mYTable.update();
}

To activate E-sign from UI check Below Link:


Keep Daxing!!

Lookup method in D365FO

 Lookup method in D365FO. This lookup is developed by SysTableLookup class. Below code is the simple code.


Query query = new Query(); QueryBuildDataSource qbds; SysTableLookup syslookup; syslookup= SysTableLookup::newParameters(tableNum(InventSite), this);//Sender syslookup.addLookupfield(fieldNum(InventSite, SiteId)); syslookup.addLookupfield(fieldNum(InventSite, Name)); syslookup.addLookupMethod(tableMethodStr(InventSite, Method)); qbds = query.addDataSource(tableNum(InventSite)); qbds.addRange(fieldNum(InventSite, Active)).value(queryValue(NoYes::Yes)); syslookup.parmQuery(query); syslookup.performFormLookup();


Keep Daxing !!

Get the one field data from common table using x++

 Hi guys, Based on table Id we are assigning common buffer value to table buffer. Sometimes I need only few fields data instead of full buffer. Just check below code to get required fields data from caller table.

In Form Init:

element.args().record().(fieldNum(WMSLocation, InventLocationId));

element.args().record().(fieldNum(Table, Field));

Other Place:

Common.(fieldNum(Table, Field));


Keep daxing!!

How to DeSerialize JSON file in d365FO

Hi guys, Today we see how to deSerialize the JSON file using x++.

I have created a new job to upload JSON files and retrieve the data from that file.

Below JSON file I have used.

JSON File: 

Example 1:

[
 {
   "CUSTOMERGROUPID": 10,
   "CLEARINGPERIODPAYMENTTERMNAME": "Net30",
   "CUSTOMERACCOUNTNUMBERSEQUENCE": "",
   "DEFAULTDIMENSIONDISPLAYVALUE": "",
   "DESCRIPTION": "Wholesales customers",
   "ISSALESTAXINCLUDEDINPRICE": "No",
   "PAYMENTTERMID": "Net30",
   "TAXGROUPID": "",
   "WRITEOFFREASON": ""
 },
 {
   "CUSTOMERGROUPID": 100,
   "CLEARINGPERIODPAYMENTTERMNAME": "Net10",
   "CUSTOMERACCOUNTNUMBERSEQUENCE": "",
   "DEFAULTDIMENSIONDISPLAYVALUE": "",
   "DESCRIPTION": "Intercompany retail customers",
   "ISSALESTAXINCLUDEDINPRICE": "No",
   "PAYMENTTERMID": "Net10",
   "TAXGROUPID": "",
   "WRITEOFFREASON": ""
 },
 {
   "CUSTOMERGROUPID": 1000,
   "CLEARINGPERIODPAYMENTTERMNAME": "Net30",
   "CUSTOMERACCOUNTNUMBERSEQUENCE": "",
   "DEFAULTDIMENSIONDISPLAYVALUE": "",
   "DESCRIPTION": "Wholesales customers",
   "ISSALESTAXINCLUDEDINPRICE": "No",
   "PAYMENTTERMID": "Net30",
   "TAXGROUPID": "",
   "WRITEOFFREASON": ""
 }
]


Job:

I created a new job to upload the JSON file. 

class TestJsonFile { public static void main(Args _args) { str jsonString; FileUploadTemporaryStorageResult fileUpload = File::GetFileFromUser()
                                                as FileUploadTemporaryStorageResult; System.IO.Stream stream = fileUpload.openResult(); using (var reader = new System.IO.StreamReader(stream)) { jsonString = reader.ReadToEnd(); } if (jsonString) { custGpService custGpService = new custGpService(); custGpService.test(jsonString); }
    }
}

Upload the file:




Service class:
                Here I wrote the main logic to deSerialize the JSON file
class custGpService { public void test(str json) { List values = new List(Types::String); ListEnumerator value; //custGpMultiContract contract = FormJsonSerializer::deserializeObject(
                            //classnum(custGpMultiContract), json); values = FormJsonSerializer::deserializeCollection(classnum(List),
                                    json, Types::Class, classStr(custGpContractClass)); //value = contract.parmCustomerList().getEnumerator(); value = values.getEnumerator(); while(value.moveNext()) { custGpContractClass custGpContractClass = value.current();
info(strFmt("CustomerGroupId-%1, Description-%2, PAYMENTTERMID-%3",         custGpContractClass.parmId(),
                                    custGpContractClass.parmDescription(),         custGpContractClass.parmPaymentTermId())); } } }


Contract class: 

[DataContract]
class custGpContractClass
{
    private str id;
    private str description;
    private str paymentTermId;

    [DataMember("CustomerGroupId")]
    public str parmId(str _id = id)
    {
        id = _id;
        return id;
    }

    [DataMember("Description")]
    public str parmDescription(str _description = description)
    {
        description = _description;
        return description;
    }

    [DataMember("PAYMENTTERMID")]
    public str parmPaymentTermId(str _paymentTermId = paymentTermId)
    {
        paymentTermId = _paymentTermId;
        return paymentTermId;
    }

}

Output: 




Example 2: 
Json:

{ "result": { "CountryId": "Country 1", "StateList": [ { "StateCode": "St1" }, { "StateCode": "St2" }, { "StateCode": "St3" } ] } }

 For the above schema, we need to create 2 contract classes. One is for the country and the second is for the state code. We need to create a new parm method in the 1st contract class and the return type is list. Like below.

[DataMemberAttribute("Name from Json file"), DataCollection(Types::Class, classStr("2nd contract")), AifCollectionTypeAttribute('_list', Types::Class, classStr("2nd contract")), AifCollectionTypeAttribute('return', Types::Class, classStr("2nd contract")) ] public List parmList(List _list = list) { list = _list; return list; }

Contract class1(Country): 

[datacontract] public class countryContract { CountryCode country; List stateList; [DataMemberAttribute('CountryId')] public CountryCode parmCountryCode(CountryCode _country = country) { country = _country; return country; } [DataMemberAttribute("StateList"), DataCollection(Types::Class, classStr(StateContract)), AifCollectionTypeAttribute('_stateList', Types::Class, classStr(StateContract)), AifCollectionTypeAttribute('return', Types::Class, classStr(StateContract)) ] public List parmCountryList(List _stateList = stateList) { stateList = _stateList; return stateList; } }
Contract class2(State): 

[DataContract] public class stateContract { StateId state; [DataMemberAttribute('StateCode')] public StateId parmStateCode(StateId _state = state) { state = _state; return state; } }

Same service class we can use.
Keep daxing!!