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 :)

mercoledì 7 luglio 2021

D365FFO / AX 2012 - Lookup su worker con controllo unbound

Per aprire la lookup standard sugli Employee è sufficente utilizzare i reference group:

https://community.dynamics.com/ax/f/microsoft-dynamics-ax-forum/246930/what-is-a-reference-group/684992

Se invece abbiamo un controllo unbound, possiamo aggiungere alla form un controllo stringa (con EDT = HcmPersonnelNumberId ) e nell'override del metodo lookup del controllo scrivere:

 public void lookup()  
 {  
      FormRun formRun;  
        
      formRun = FormAutoLookupFactory::buildLookupFromCustomForm(this  
                                                                              ,new Form(formStr(HcmWorkerLookUp))  
                                                                              ,AbsoluteFieldBinding::construct(fieldStr(HcmWorker, PersonnelNumber),  
                                                                              tableStr(HcmWorker)));  
      this.performFormLookup(formRun);  
 }  



lunedì 24 maggio 2021

D365FFO - Fetch mode

 In questo post vediamo il funzionamento della proprietà "Fetch Mode" presente nelle query di AX



Riporto questo link molto utile dove spiega anche altre proprietà:


Ho creato una query con SalesTable + SalesLine + CustTable strutturata così:



Se le relation hanno fetch mode 1:1 e stampiano nell’ordine SalesTable.SalesId, SalesLine.InventTransId, CustTable.AccountNum l’esecuzione darà lugo a questa sequenza: 



 Avremo quindi tutti i buffer di tutte le tabelle valorizzate. Se invece imposto 1:n l’esecuzione da luogo a questo: 


Se invece i datasource delle query sono tutti annidati a cascata così: Quindi non tutti I buffer sono disponibili, per esempio CustTable è disponibile solo all’ultima iterazione,nelle iterazioni 1,2,3 CustTable è vuota.

One2One oppure One2Many non fà differenza