Discover essential insights about D365 Finance and Operations (D365FO) through our user-friendly technical blog. Our content covers implementation, customization, troubleshooting, and key trends in D365FO. Stay informed about performance optimization, security updates, and X++ coding techniques. Learn efficient ways for data migration and workflow automation. Simplify your D365FO experience with our expert guidance. Your top resource for D365FO knowledge, designed for easy understanding.#Learn
Friday, January 6, 2023
How to apply custom range on AOT query in D365 Finance and Operations
Tuesday, December 27, 2022
How to set count on Tile using X++ (Update tile count runtime)
Set Count Value on Tiles using X++ Query
Dear All,
Today, we will explore how to set the count value on Tiles using an X++ query. I encountered this scenario during a recent customization project. This technique is particularly useful when you need to filter the tile data count based on an unbound control on the form, where the control's value is not associated with any of your dataSource columns.
Requirement
Add an Integer control on the form and upon modification of that control, update the count of the Tile with the condition of records created before a given number of days.
Logic
((today's date - Created Date) > number of days given in the control) then show on the count otherwise not.
Implementation Steps
- Create an AOT query to show all the record count without the number of days filter.
- Create a Tile and set the below 2 properties:
- Query: query name
- Type: count
- Create a new form.
- Add a new Integer filter control on the form and set the auto declaration property to Yes. (No of Days)
- Add a new Tile button on your form and set the tile property with the above-created tile name.
- Override the clicked method of your Tile button and add the below code:
public void clicked() {
#Task
super();
element.task(#taskRefresh);
}
- Override the getData method of your Tile button and add the below code:
public TileButtonControlData getData() {
TileButtonControlData ret;
ret = super();
if (FilterNoOfDays.value() != 0) {
int recordCount = element.countFromQuery(queryStr(TestTilePOLInes));
ret.strTileData(any2Str(recordCount));
}
return ret;
}
- Add a new method on the form level with the below code to get the count from the query with the No of days condition:
public Integer countFromQuery(str _query) {
int totalRecords;
Query query = new Query(_query);
QueryRun qr = new QueryRun(query);
while (qr.next()) {
TESTAllPOLinesView dsTest = qr.get(tablenum(TESTAllPOLinesView));
int dateDiff = today() - DateTimeUtil::date(dsTest.CreatedDateTime1);
int filterValue = FilterNoOfDays.value();
if (dateDiff > filterValue) {
totalRecords++;
}
}
return totalRecords;
}
- Build and synchronize your project area and check the result by modifying the Number of days filter control.
Saturday, December 24, 2022
How to add range on AOT query and X++ with two different columns.
Let's learn about how to add two different data source columns range on one column range in AOT Query. also i am covering how can we apply same on X++ query.
Only the point to be consider is we need to use parenthesis correctly and Proper enum name -
DocumentStatus::None.
Apply range on X++ Query.
Override the execute query method of your form Datasource and add below code.
public void executeQuery()
{
this.query.dataSourceTable(tableNum(yourDatasourcename)).clearRanges();
Query query = new Query(this.query());
QueryBuildDataSource TestAllSOLinesView_ds1 = query.dataSourceTable(tableNum(TestAllSOLinesView));
queryBuildRange queryBuildRange = TestAllSOLinesView_ds1.addRange(fieldNum(TestAllSOLinesView, DocumentStatus));
queryBuildRange.value(strFmt('((DocumentStatus == %1) || ((TestConfirmationStatus == "%2")
this.query(query);
super();
}
AOT Range on 2 different date columns
refer below screen shot - I have set the value property with greater than condition on two date column of my data source.
ex - (TestReqShippingDate > TestAllPOLinesView.TestConfirmedShippingDate)
How to create multi selection lookup on form control
Hi All,
In this article will see how to create multi selection lookup on a form control.
For this we need to create one AOT query like CustTablelookup. for that you can refer the documents provides by Microsoft docs.
Expected Result is below:
Step 1: Create a control on form and set auto declaration property to yes.
Step 2: Override the Init() method of form and add below code.
public class TestLookupTestControl extends FormRun
{
SysLookupMultiSelectCtrl custAccountMultiSelectControl;
}
public void init()
{
super();
custAccountMultiSelectControl = SysLookupMultiSelectCtrl::construct(element,FilterCustAccount, queryStr(CustTablelookup));
}
Thats It. Happy Coding.
Monday, December 12, 2022
D365 F&O Warehouse management application customization Part 2- Perform auto click from x++ code.
Welcome to the second part of this series. In this blog will see how we can perform the auto click after auto populating values.
This is required because in standard logic system is working like on first click it will fetch item id , then on second click user will enter the quantity and so on. So if we are auto populating all the values in first click then we need to skip other clicks and process for the next form directly. Refer the issue on this link.
As we have learn in the first blog, you need to identify the child class according to your requirement and execution mode define in your menu item setup.
Below class is the extension of WHSWorkExecuteDisplayPOReceiving and created COC for displayForm() method.
Inside displayForm() method we need to identify the logic to trigger the auto button click.
In below case I have written a logic like once all the values are not equals to blank then perform auto click and for safer side to avoid recursion I have added one flag in pass object.
[ExtensionOf(classStr(WHSWorkExecuteDisplayPOReceiving))]
final class WHSWorkExecuteDisplayPOReceiving_ModelTest_Extension
{
// COC of display form method in extension class.
public container displayForm(container _con, str _buttonClicked)
{
Container returnedCon;
#WHSWorkExecuteControlElements
#WHSRF
//Next statement
returnedCon = next displayForm(_con, _buttonClicked);
//Logic to skip the extra clicks goes here.
if(step == 1 && !pass.exists("AutoClickOk")&&
mode == WHSWorkExecuteMode::PurchaseOrderItemReceivingAndLocate)
{
pass.insert("AutoClickOk",'1');
// this line will perform auto click
returnedCon = this.displayForm(returnedCon, #RFOk);
}
}
D365 F&O Warehouse management application customization Part 1- Auto populate the value to a standard field.
This is the example of QR string format: "PoNum,ItemId,Quantity,date"
Please comment if you have faced any challenge to implement this.
Thursday, September 29, 2022
Deserialize JSON string in D365FO using X++ code
Today we are here to learn one of the common requirement in every integration i.e. how to de-serialize JSON string in D365FO/AX7 using X++ code.
1) Create contract class for both outer and inner node.
Step 1 : Create contract class 1 to hold all the values of data node.
Note : DataMemberAttribute name should be matched with JSON key name i.e. data, ID Nation
[DataContract]
internal final class TestJSONContract
{
String50 parmNationId, parmNation,parmYearId,parmYear,parmPopulation,parmSlugNation;
[DataMemberAttribute('ID Nation')]
public String50 parmNationId(String50 _parmNationId = parmNationId)
{
parmNationId = _parmNationId;
return parmNationId;
}
[DataMemberAttribute('Nation')]
public String50 parmNation(String50 _parmNation = parmNation)
{
parmNation = _parmNation;
return parmNation;
}
[DataMemberAttribute('ID Year')]
public String50 parmYearId(String50 _parmYearId = parmYearId)
{
parmYearId = _parmYearId;
return parmYearId;
}
[DataMemberAttribute('Year')]
public String50 parmYear(String50 _parmYear = parmYear)
{
parmYear = _parmYear;
return parmYear;
}
[DataMemberAttribute('Population')]
public String50 parmPopulation(String50 _parmPopulation = parmPopulation)
{
parmPopulation = _parmPopulation;
return parmPopulation;
}
[DataMemberAttribute('Slug Nation')]
public String50 parmSlugNation(String50 _parmSlugNation = parmSlugNation)
{
parmSlugNation = _parmSlugNation;
return parmSlugNation;
}
}
Step 2 : Create contract class for outer node.
In your case if there is more than one outer node then you need to create your class according to your JOSN. ex- if you have status and data node in your JSON but "status" is string type and "data" node contains multiple sub node then you need to create one more attribute in below class with string type and data with list type.
[DataContract]
internal final class TestJSONDataContract
{
List parmData;
[DataMemberAttribute('data'),DataCollectionAttribute(Types::class, classStr(TestJSONContract))]
public List parmData(List _parmData = parmData)
{
parmData = _parmData;
return parmData;
}
}
Step 3: Create runnable class to call your API and get the result.
internal final class TestConsumeAPITest
{
/// <summary>
/// Class entry point. The system will call this method when a designated menu |
/// is selected or when execution starts and this class is set as the startup class.
/// </summary>
/// <param name = "_args">The specified arguments.</param>
public static void main(Args _args)
{
System.Net.HttpWebRequest webRequest;
System.Net.HttpWebResponse webresponse;
System.Exception ex;
System.IO.Stream responseStream;
System.IO.StreamReader reader;
str output;
ListEnumerator listEnumerator;
try
{
new InteropPermission(InteropKind::ClrInterop).assert();
webRequest = System.Net.WebRequest::Create("##########"); //your API URL goes here.
webRequest.Method = "GET";
webRequest.ContentType = "application/json";
webresponse = webRequest.GetResponse();
responseStream = webresponse.GetResponseStream();
reader = new System.IO.StreamReader(responseStream);
output = reader.ReadToEnd();
TestJSONDataContract TestJSONDataContract = FormJsonSerializer::deserializeObject(classNum(TestJSONDataContract),output);
List listData = new List(Types::Class);
listData = TestJSONDataContract.parmData();
listEnumerator = listData.getEnumerator();
while (listEnumerator.moveNext())
{
TestJSONContract jsonDataContract = listEnumerator.current();
info(strFmt("Nation id %1 : %2 = %3",jsonDataCOntract.parmNationId(), jsonDataContract.parmNation(), jsonDataContract.parmPopulation()));
}
}
catch
{
ex = CLRInterop::getLastException().GetBaseException();
error(ex.get_Message());
}
}
}
Step Final : Execute your runnable class to test the API and JSON format.
Update Values During Data Entity Import in D365FO
Update Values During Data Entity Import in D365FO Updating Field Values During Data Entity Import in Dynamics 365 Finance ...
-
How to Export Data Packages in Microsoft Dynamics 365 finance and operations How to Export Data Packages in Microsof...
-
Data Management Package REST API - Import Package in Dynamics 365FO Using Postman Data Management Package REST...
-
How to Register Return Sales Order Lines in X++ The TestSalesReturnOrderLineRegister Class in X++ The TestSalesRetu...