giovedì 17 marzo 2022

D365FFO -- RSAT for WHS terminal

In order to implement RSAT using the WHS terminal, we have first of all to check if the following parameter is set (Enable RSAT support) at the following path Warehouse management > Setup >  Warehouse management parameters.


Once set the previous parameter, we should access the following path Warehouse management > Periodic task >  Warehouse app task validation.


In order to create a new test case we should click on the button new as reported above. Then once we have set the fields userid and description of the task we can start the recording of the tasks with warehouse app clincking on Start recording.


Once we started the registration we can do the activities to be recorded in the warehouse app.






Once we have done this procedure we must load the parameters from the recording clicking on the button Generate variables.


The system automatically fills the variables defined in the registration. In case we want to run the script we must access the same form and clicking Run task, as reported below.







martedì 8 marzo 2022

D365FFO - Check the number of rows in a table / add a total in a table / Group by a specific value

 In D365FO some new functions have been added in order to speed up the check of the number of lines / totals in the form.

For example accessing a specific form (purchase invoice form), we can add a footer in the form clicking with the left button of the mouse and selecting the function "Show footer".



 

The system will add in the bottom part of the form the total number of rows selected.

In case we want to group by a specific value of the form we can do it right clicking on the column and selecting "Group by this column" as reported below.


The system will show all the records grouped by the values shown in that field as reported below.


In case we want to calculate the total of a numerical field we can right click on that field and select the function Total this column.


The result will be the following one.




venerdì 17 dicembre 2021

AX 2012 - Disabilitare indice tabella via codice

Tutte le proprietà di un oggetto  dell'AOT che possono essere cambiate a mano, possono anche essere pilotate via codice usando la classe "TreeNode". Con questo job possiamo disabilitare l'indice della tabella "Accountant_BR"

 static void LILIndexDisable(Args _args)  
 {  
      TreeNode objTreeNode;  
      #Properties  
      objTreeNode = TreeNode::findNode(@"\Data dictionary\Tables\Accountant_BR\indexes\AccountantIdx");  
   
      if (objTreeNode)  
      {  
           objTreeNode.AOTsetProperty(#PropertyEnabled,"No");  
           objTreeNode.AOTsave();  
      }  
 }  

martedì 2 novembre 2021

D365FFO - Creazione indirizzo magazzino a partire dall'indirizzo di un site

 Con questo job è possibile creare un indirizzo (a partire da un indirizzo associato ad un site) e collegarlo ad un magazzino. Questo job è stato di grande aiuto:

http://axcorner.blogspot.com/2014/01/create-warehouse-addresses-through-code.html


   public static void main(Args _args)  
   {  
     InventSite                 inventSite;  
     InventLocation               inventLocation;  
     InventSiteId                inventSiteid = "K1";    //sito di partenza  
     InventLocationId              inventLocationId = "lil01"; //magazzino su cui creare l'indirizzo  
     LogisticsPostalAddress           postalAddress;  
     LogisticsPostalAddressView         postalAddressView;  
     LogisticsPostalAddress           logisticsPostalAddressSite;  
     LogisticsEntityLocationMap         locationMap;  
     container                  role, roleMap;  
     Map                     LocationRoleMap;  
     LogisticsLocation              logisticsLocation;  
     LogisticsElectronicAddress         LogisticsElectronicAddress;  
                         
   
     inventSite = inventSite::find(inventSiteid);  
     inventLocation = inventLocation::find(inventLocationId);  
   
     //quì prendo l'indirizzo sorgente del site  
     logisticsPostalAddressSite = inventSite.logisticsPostalAddress();  
             
     logisticsLocation = LogisticsLocation::find(logisticsPostalAddressSite.Location);  
     LogisticsElectronicAddress::findByLocation(logisticsLocation.RecId);  
       
   
     LogisticsPostalAddressEntity  postalAddressEntity = new LogisticsPostalAddressEntity();    
       
     postalAddressView.Street      = logisticsPostalAddressSite.Street;  
     postalAddressView.City       = logisticsPostalAddressSite.City;  
     postalAddressView.State       = logisticsPostalAddressSite.State;  
     postalAddressView.ZipCode      = logisticsPostalAddressSite.ZipCode;  
     postalAddressView.CountryRegionId  = logisticsPostalAddressSite.CountryRegionId;      
     postalAddressView.LocationName   = logisticsLocation.Description;  
   
     postalAddress    = postalAddressEntity.createPostalAddress(postalAddressView);  
         
     locationMap.initValue();  
   
     locationMap      = LogisticsEntityLocationMap::find(tableNum(InventLocationLogisticsLocation), inventLocation.RecId, postalAddress.Location);  
       
     locationMap.Entity       = inventLocation.RecId;  
     locationMap.Location      = postalAddress.Location;  
     locationMap.IsPostalAddress   = logisticsLocation.IsPostalAddress;  
     locationMap.IsPrimary      = LogisticsElectronicAddress.IsPrimary;  
     locationMap.IsPrivate      = LogisticsElectronicAddress.IsPrivate;  
   
     LocationRoleMap    = LogisticsLocationEntity::getDefaultLocationRoleFromEntity(tableNum(InventLocation));  
   
     roleMap        = map2Con(LocationRoleMap);  
     role         = conpeek(roleMap, 1);  
   
     locationMap.addEntityLocation(role ,true);  
   
     info("Terminato");  
   
   }  

giovedì 7 ottobre 2021

D365FO - New cut and paste options

 Is it possible to copy data directly with a cut and paste from excel for multiple lines?

Now yes, I'll show how.

Starting from an excel having all the lines properly ordered.


We copy using CTRL-C function the lines to be copied.

Then we open the correspondent form in D3650FO, create a new line.


And finally click CTRL-V.

It applies also to multiple rows, and in case of errors it is requested a correction by the user in interactive mode.

mercoledì 6 ottobre 2021

D365FFO - Richiamare metodi privati all'esterno della classe

Questo link mostra come usare la  reflection del C# per richiamare metodi privati statici o di istanza di una determinata classe in AX.

https://axvigneshvaran.wordpress.com/2018/01/05/how-to-access-call-private-protected-methods-variables-in-a-class-table-using-reflection/

Supponiamo di avere una classe fatta così:

 class MyClass  
 {  
      private static int sumPrivate(int a, int b)  
      {  
           return a+b;  
      }  
   
      private int sumInstancePrivate(int a, int b)  
      {  
           return a+b;  
      }  
 }  
possiamo accedere ai due metodi privati così:

 using System.Reflection;  
   
 class testReflection  
 {  
   public static void main(Args _args)  
   {  
     int      ret;  
     System.Object[] parametersArray = new System.Object[2]();  
     parametersArray.SetValue(5, 0);  
     parametersArray.SetValue(2, 1);  
       
     System.Type   myType;  
     DictClass    dt = new DictClass(classNum(MyClass));  
     Object     classInstance = dt.makeObject();  
             
     var bindFlags = BindingFlags::InvokeMethod |   
                               BindingFlags::NonPublic |   
                               BindingFlags::Static | BindingFlags::Instance;  
     
     myType = classInstance.GetType();  
   
     //richiama il metodo statico  
     ret = myType.InvokeMember(staticMethodStr(MyClass,sumPrivate),bindFlags,null,null,parametersArray);  
   
     //richiama il un metodo di instanza  
     var methodInfo = myType.GetMethod(methodStr(MyClass, sumInstancePrivate), bindFlags);  
   
     if (methodInfo)  
     {  
                // Or use “new System.Object[0]()” instead of parametersArray if you do not have any parameters  
       ret = methodInfo.Invoke(classInstance, parametersArray);   
     }  
   }  
 }  

Con questo metodo possiamo invece richiamare un metodo privato statico su una tabella.

   NumberSequenceTable numSeqTab;  
  System.Reflection.MethodInfo mi;  
  System.Object[] parametersArray = new System.Object[3]();  
   
  NumberSequenceReference   NumberSequenceReference;  
  NumberSequenceGroupId    NumberSequenceGroupId = "abc";  
  TransDate          invoiceDate = today();  
   
  select firstonly NumberSequenceReference;  
   
  parametersArray.SetValue(invoiceDate, 0);  
  parametersArray.SetValue(NumberSequenceReference, 1);  
  parametersArray.SetValue(NumberSequenceGroupId, 2);  
    
  System.Type  myType;  
  dictTable  dt = new dictTable(tableNum(CustInvoiceJour));  
  common   classInstance = dt.makeRecord();  
       
  var bindFlags = BindingFlags::InvokeMethod |  
              BindingFlags::NonPublic |  
              BindingFlags::Static | BindingFlags::Instance;  
      
  myType = classInstance.GetType();  
   
  mi = myType.GetMethod(tableStaticMethodStr(CustInvoiceJour,getNumberSequenceTableForChronologicalDateValidation_W), bindFlags);  
   
  numSeqTab = mi.Invoke(null, parametersArray);  
N:B: Mina le basi della programmazione ad oggetti :)