giovedì 17 dicembre 2020

D365FFO - Creare un nuovo worker ed associarlo ad uno user

 In questo post vediamo come creare un worker da associare ad uno user. Ho preso spunto da questo post per AX 2012 adattandolo alle nuove classi aggiungendo la parte che creal'associazione User -> Worker:

https://community.dynamics.com/ax/f/microsoft-dynamics-ax-forum/155550/create-worker-through-code/704763

 public static void CreateEmployeeAndAssignTouser(UserId _userId,  
                  FirstName _firstName,  
                  MiddleName _middleName,  
                  LastName _lastName,  
                  str _email,  
                  HcmPersonnelNumberId _employeeId,  
                  date _joiningDate,  
                  HcmTitleId _title,  
                  SelectableDataArea _ReleaseInCompany  
 )  
   {  
     DirPersonName            dirPersonName;  
     HcmWorker              newHcmWorker;  
     HcmWorkerTitle           hcmWorkerTitle;  
     LogisticsLocation          logisticsLocation;  
     DirPartyContactInfoView       dirPartyContactInfoView;  
     DirParty              dirParty;  
     ValidFromDateTime          employmentStartDateTime;  
     ValidToDateTime           employmentEndDateTime;  
     str                 employeeEmailAdress;  
     HcmPersonnelNumberId        employeeid;  
     RecId                compayRecId;  
     HcmCreateWorkerContract       createWorkerParams;  
     ;  
   
     dirPersonName.FirstName   = _firstName;  
     dirPersonName.MiddleName  = _middleName;  
     dirPersonName.LastName   = _lastName;  
     employeeEmailAdress     = _email;  
     employeeid         = _employeeId;  
     compayRecId         = CompanyInfo::findDataArea(_ReleaseInCompany).RecId;  
   
     employmentStartDateTime = DateTimeUtil::newDateTime(_joiningDate,0);  
     employmentEndDateTime  = DateTimeUtil::applyTimeZoneOffset(DateTimeUtil::maxValue(), DateTimeUtil::getUserPreferredTimeZone());  
   
     if(!HcmWorker::findByPersonnelNumber(employeeid))  
     {  
       createWorkerParams = HcmCreateWorkerContract::construct();  
   
       createWorkerParams.parmDirPersonName(dirPersonName);  
       createWorkerParams.parmPersonnelNumber(employeeid);  
       createWorkerParams.parmLegalEntityRecId(compayRecId);  
       createWorkerParams.parmEmploymentType(HcmEmploymentType::Employee);  
       createWorkerParams.parmEmploymentValidFrom(employmentStartDateTime);  
       createWorkerParams.parmEmploymentValidTo(employmentEndDateTime);  
   
       newHcmWorker = HcmWorker::find(HcmWorkerTransition::newCreateHcmWorkerV2(createWorkerParams));  
   
       dirParty = new DirParty(DirPerson::find(dirPersonName.Person));  
   
       if(employeeEmailAdress != '' && newHcmWorker.Person != 0)  
       {  
         logisticsLocation.clear();  
         logisticsLocation  = LogisticsLocation::create("@SYS5845", NoYes::No);  
   
         dirPartyContactInfoView.LocationName        = "@SYS5845";  
         dirPartyContactInfoView.Locator           = employeeEmailAdress;  
         dirPartyContactInfoView.Type            = LogisticsElectronicAddressMethodType::Email;  
         dirPartyContactInfoView.Party            = DirPerson::find(newHcmWorker.Person).RecId;  
         dirPartyContactInfoView.IsPrimary          = NoYes::Yes;  
           
         dirParty.createOrUpdateContactInfo(dirPartyContactInfoView);  
       }  
   
       if (newHcmWorker.RecId != 0)  
       {  
         ttsBegin;  
         hcmWorkerTitle.clear();  
         hcmWorkerTitle.Worker    = newHcmWorker.RecId;  
         hcmWorkerTitle.ValidFrom  = DateTimeUtil::newDateTime(_joiningDate,0);  
         hcmWorkerTitle.ValidTo   = employmentEndDateTime;  
   
         if(_title)  
         {  
           hcmWorkerTitle.Title = HcmTitle::findByTitle(_title).RecId;  
         }  
   
         hcmWorkerTitle.insert();  
         ttsCommit;  
       }  
   
                //assegna il worker all'utente  
       HcmWorker hcmWorker = HcmWorker::findByPersonnelNumber(employeeid);  
       DirPersonUser::createDirPersonUser(_userId, hcmWorker.Person);  
     }  
   }  

Dopo aver lanciato il job possiamo vedere il risultato:





venerdì 2 ottobre 2020

D365FFO - Dialog per caricare e leggere un file excel

In questo post vediamo come creare una semplice dialog che consente di caricare e leggere un file excel in locale. Ho preso spunto da questo post per creare la classe: 


Questa è la classe che effettua la lettura del file:
 class LILFileExcelDataReader  
 {  
   str     fileURL;  
   str     sheetName;  
   container  dataContainer;  
   
   public static LILFileExcelDataReader construct(str _fileUrl, str _sheetName)  
   {  
     LILFileExcelDataReader instance = new LILFileExcelDataReader();  
   
     instance.parmFileURL(_fileUrl);  
   
     instance.parmSheetName(_sheetName);  
   
     return instance;  
   }  
   
   public str parmFileURL(str _fileUrl = fileURL)  
   {  
     fileURL = _fileUrl;  
   
     return fileURL;  
   }  
   
   private str getTMPSheetName()  
   {  
     return strFmt("TMP_%1_%2",date2str(  
                   today(),  
                   321,  
                   DateDay::Digits2,  
                   DateSeparator::None,  
                   DateMonth::Digits2,  
                   DateSeparator::None,  
                   DateYear::Digits4  
                   ),timeNow());  
   }  
   
   public str parmSheetName(str _sheetName = sheetName)  
   {  
     sheetName = _sheetName;  
   
     return sheetName;  
   }  
   
   public container getData()  
   {  
     return dataContainer;  
   }  
   
   private boolean validate()  
   {  
     boolean ret = true;  
   
     if(!this.parmFileURL())  
     {  
       return checkFailed("@SYS91305");  
     }  
   
     if(!this.parmSheetName())  
     {  
       return checkFailed("@GEE33476");  
     }  
   
     return ret;  
   }  
   
   public void read()  
   {  
     System.Byte[] byteArray;  
     System.IO.Stream   stream;  
   
     try  
     {  
       if(!this.validate())  
       {  
         throw error("@SYS93835");  
       }  
   
       stream = File::UseFileFromURL(this.parmFileURL());  
       //this.fillSheetList(stream);  
       dataContainer = this.readExcelData(stream);  
     }  
     catch(Exception::Error)  
     {  
       info(strFmt("%1 %2",Exception::Error,fileUrl));  
     }  
   }  
   
   public static List fillSheetList(System.IO.Stream   _stream)  
   {  
     OfficeOpenXml.ExcelWorksheets  workSheets;  
     OfficeOpenXml.ExcelWorksheet  sheet;  
     List    sheetList = new List(Types::String);  
     OfficeOpenXml.ExcelPackage   package = new OfficeOpenXml.ExcelPackage(_stream);  
   
     workSheets = package.get_Workbook().get_Worksheets();  
   
     var enumerator = workSheets.GetEnumerator();  
   
     while (enumerator.MoveNext())  
     {  
       sheet = enumerator.Current as OfficeOpenXml.ExcelWorksheet;  
   
       sheetList.addEnd(sheet.Name);  
     }  
   
     return sheetList;  
   }  
   
   private container readExcelData(System.IO.Stream   _stream)  
   {  
     OfficeOpenXml.ExcelWorksheet  _worksheet;  
       
     OfficeOpenXml.ExcelPackage   package = new OfficeOpenXml.ExcelPackage(_stream);  
     int               iRowCount,iCellCount;  
     anytype             anyData;  
     container            conRow,  
                     conData;  
     try  
     {  
       if(package)  
       {  
         //copy data to temporany sheet  
         _worksheet = package.get_Workbook().get_Worksheets().Copy(this.parmSheetName(),this.getTMPSheetName());  
         var cells = _worksheet.get_Cells();  
         iRowCount = _worksheet.get_Dimension().get_End().get_Row();  
         iCellCount = _worksheet.get_Dimension().get_End().get_Column();  
   
         for (int i=2;i<=iRowCount;i++)  
         {  
           conRow = conNull();  
   
           for (int j=1;j<=iCellCount;j++)  
           {  
   
             anyData= cells.get_Item(i, j).get_Value();  
   
             if(!anyData && j ==1)  
             {  
               break;  
             }  
   
             if(anyData)  
             {  
               conRow += anyData;  
             }  
             else  
             {  
               conRow += "";  
             }  
           }  
   
           if(conRow)  
           {  
             conRow += iRowCount;  
             conData = conIns(conData,i,conRow);  
           }  
         }  
       }  
     }  
     catch (Exception::CLRError)  
     {  
       throw error("@SYS135884");  
     }  
   
     return conData;  
   }  
   
 }  

Questa classe RunBase mostra come utilizzarla:

 class LILExcelReaderDialog extends RunBase  
 {  
   str       fileUrl;  
   str       sheetName;  
   
   DialogRunbase  dialog;  
   
   FormBuildStringControl sheetNameCtrl;  
   
   DialogField   dlgSheetName;  
   
   container    dataContainer;  
   
   #define.CurrentVersion(1)  
   #define.Version1(1)  
   #localmacro.CurrentList  
     sheetName  
   #endmacro  
   
   public container pack()  
   {  
     return [#CurrentVersion,#CurrentList];  
   }  
   
   public boolean unpack(container _packedClass)  
   {  
     Integer   version   = RunBase::getVersion(_packedClass);  
   
     switch (version)  
     {  
       case #CurrentVersion  :  
         [version,#CurrentList] = _packedClass;  
         break;  
       default :  
         return false;  
     }  
   
     return true;  
   }  
   
   protected boolean canRunInNewSession()  
   {  
     return false;  
   }  
   
   private str getSessionID()  
   {  
     return strFmt("%1_%2",date2str(  
                   today(),  
                   321,  
                   DateDay::Digits2,  
                   DateSeparator::None,  
                   DateMonth::Digits2,  
                   DateSeparator::None,  
                   DateYear::Digits4  
                   ),timeNow());  
   }  
   
   public void sheetName_lookup(FormStringControl _executionControl)  
   {  
     if(!fileUrl)  
     {  
       warning("Please upload a file first!");  
   
       return;  
     }  
   
     List  valueList = LILFileExcelDataReader::fillSheetList(File::UseFileFromURL(fileUrl));  
   
     FormRun lookupForm = classFactory.createSysLookupPicklist(_executionControl);  
     lookupForm.init();  
       
     sysPickList pickList = new sysPickList(lookupForm);  
     lookupForm.choices(list2Con(valueList));  
     _executionControl.performFormLookup(lookupForm);  
   }  
   
   public Object dialog()  
   {  
     dialog = super();  
     FormBuildButtonControl buttonControl;  
     DialogGroup       dlgGroup;  
     FormBuildGroupControl  buttonGroup;  
     #resAppl  
     ;  
   
     dlgGroup    = dialog.addGroup("@SYS7764");  
     dlgGroup.columns(1);  
   
     buttonGroup  = dialog.formBuildDesign().control(dlgGroup.formBuildGroup().id());  
     buttonControl = buttonGroup.addControl(FormControlType::Button, "@ElectronicReporting:Upload");  
     buttonControl.text("@DMF1951");  
     buttonControl.registerOverrideMethod(methodStr(FormButtonControl, clicked),  
                       methodStr(LILExcelReaderDialog, uploadClickedEvent),  
                       this);  
   
     dlgSheetName = dialog.addFieldValue(extendedTypeStr(Name),   sheetName, "Sheet name");  
     sheetNameCtrl = dlgSheetName.fieldControl();  
     sheetNameCtrl.extendedDataType(extendedtypenum(Name));  
     sheetNameCtrl.registerOverrideMethod(methodStr(FormStringControl, lookup),  
                       methodStr(LILExcelReaderDialog, sheetName_lookup),  
                       this);  
   
       
     return dialog;  
   }  
   
   private void uploadClickedEvent(FormButtonControl _formButtonControl)  
   {  
     FileUploadTemporaryStorageResult result = File::GetFileFromUser() as FileUploadTemporaryStorageResult;  
   
     if (result && result.getUploadStatus())  
     {  
       result.getFileContentType();  
       fileUrl = result.getDownloadUrl();  
   
       info("@DMF1952");  
     }  
   }  
   
   Public void  readExcel()  
   {  
     LILFileExcelDataReader fileExcelDataReader = LILFileExcelDataReader::construct(fileUrl,sheetName);  
     fileExcelDataReader.read();  
   
     dataContainer = fileExcelDataReader.getData();  
   }  
   
   public boolean validate(Object calledFrom = null)  
   {  
     boolean ret;  
     
     ret = super(calledFrom);  
   
     if(ret && !fileUrl)  
     {  
       ret = checkFailed(strFmt("@MCR11498",fileUrl));  
     }  
   
     if(ret && !sheetName)  
     {  
       ret = checkFailed(strFmt("@SYS26332","@ElectronicReportingForAx:ExcelSheet"));  
     }  
    
     return ret;  
   }  
   
   protected void update()  
   {  
     //put logic code in this method...  
   }  
   
   public void run()  
   {  
     Voucher   voucher;  
     int     i;  
     container  line;  
     str         s;  
     #OCCRetryCount  
           
   
     if (!this.validate())  
     {  
       throw error("@SYS18447");  
     }  
   
     this.readExcel();  
   
     this.update();  
   }  
   
   public static LILExcelReaderDialog construct()  
   {  
     return new LILExcelReaderDialog();  
   }  
   
   public boolean getFromDialog()  
   {  
     sheetName   = dlgSheetName.value();  
   
     return super();  
   }  
   
   public boolean runsImpersonated()  
   {  
     return true;  
   }  
   
   public boolean init()  
   {  
     return true;  
   }  
   
   public static void main(Args _args)  
   {  
     LILExcelReaderDialog excelReaderDialog = LILExcelReaderDialog::construct();  
   
     if(excelReaderDialog.prompt())  
     {  
       excelReaderDialog.runOperation();  
     }  
   }  
   
 }  

La dialog si presenta così:





giovedì 10 settembre 2020

AX2012 - How to extract TMSCarrier addresses and addresses roles

 If you need to extract from an AX2012 R3 the full list of addresses and their roles you can use the following job.


 static void A_GiaImportCarrierAddresses(Args _args)  
 {  
      TMSCarrier             TMSCarrier;  
      LogisticsPostalAddress       LogisticsPostalAddress;  
      Tmscarrierlogisticslocation     TMScarrierlogisticslocation;  
      TMSCarrierLogisticsLocationRole   TMSCarrierLogisticsLocationRole;  
      LogisticsLocation          LogisticsLocation;  
      LogisticsLocationRole        logisticslocationrole;  
   
      while select TMScarrier  
           join TMScarrierlogisticslocation  
           where TMSCarrier.recid == TMScarrierlogisticslocation.Carrier  
           join LogisticsPostalAddress  
           where LogisticsPostalAddress.Location == TMScarrierlogisticslocation.Location  
           join LogisticsLocation  
           where LogisticsLocation.recid == LogisticsPostalAddress.Location  
           join TMSCarrierLogisticsLocationRole  
           where TMSCarrierLogisticsLocationRole.LocationLogisticsLocation == TMScarrierlogisticslocation.recid  
           join LogisticsLocationRole  
           where logisticslocationrole.RecId == TMSCarrierLogisticsLocationRole.LocationRole  
   {  
     info( strFmt("%1; %2; %3; %4; %5; %6",LogisticsPostalAddress.street,  
                                                         LogisticsPostalAddress.ZipCode,  
                                                         LogisticsPostalAddress.City,  
                                                         LogisticsPostalAddress.CountryRegionId,   
                                                         LogisticsLocation.Description,  
                                                         logisticslocationrole.Name));  
   }  
 }  


The result will be the following one.