Search your query

Thursday, July 24, 2025

Rename SQL Database (AxDB) to other name after bacpac file import (After Restoring UAT DB to Development Server)

 > Some cases, we might have issue with renaming Database once we import from UAT server to DEV server. In order to rectify this, we need to execute the following commands in SQL SERVER.


-- RENAME DATABASE ONE TO ANOTHER IN SQL SERVER.


-- Set Database in Single User Mode:

ALTER DATABASE AxDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE


-- Try to Rename the Database:

ALTER DATABASE AxDB MODIFY NAME = AxDB_Initial_Backup_15072025


-- Set the Database to Multi User Mode:

ALTER DATABASE AxDB_Initial_Backup_15072025 SET MULTI_USER WITH ROLLBACK IMMEDIATE


Tuesday, July 1, 2025

X++ code to fetch the Project total cost value from Project WBS based on Project ID

 X++ code to fetch Project total cost value from Project WBS based on Project ID


public static AmountMST findProjectWBSTotalCostValue(ProjTable _projTable)

{

    ProjTable                                       projTableLocal;

    AmountMST                                   totalWBSCost;

    PSAActivityEstimates                    projectActivityEstimates;

    SmmActivityParentLinkTable         activityParentLinkTable;

    SmmActivities                              smmActivities;


    if  (_projTable)

    {

        while select activityNumber from smmActivities

            exists join activityParentLinkTable

            where activityParentLinkTable.ActivityNumber == smmActivities.ActivityNumber

            exists join projTableLocal

            where projTableLocal.RecId == activityParentLinkTable.refRecId &&

                  activityParentLinkTable.parentType == smmActivityParentType::Project &&

                  projTableLocal.ProjId == _projTable.ProjId

        {

            while select projectActivityEstimates

            where projectActivityEstimates.ActivityNumber == smmActivities.ActivityNumber

            {

                    totalWBSCost += projectActivityEstimates.TotalCostPrice;

            }

        }

    }

    return totalWBSCost;

}

Friday, March 28, 2025

Create a Multiselect Lookup Control on a Simple Form & Dialog Form

Create a Multiselect Lookup Control on a Simple Form & Dialog Form


Example: Company Info (Legal Entity) list selection on Purchase order.

ON FORM:

 Steps:

1. Create a New String field (String size: based on your requirement) in PurchTable - Table Extension

2. Drag and Drop this field into PurchTable - Form Extension from PurchTable Data source.

3. Create one Simple Query for Company Info Table. (Ex: LegalEntityQueryForFilter)

3. Create a new Extension class for PurchTable form and write some user defined class and add 2 extra - event handler methods (On Initialized the form and On Modified the PurchTable Data Source > Newly created string field): Sample codes on below:


[ExtensionOf(formstr(PurchTable))]

final class PurchTable_YourModelName_Extension

{

    public static SysLookupMultiSelectCtrl legalEntityListMultiSelectCtrl;

    public Query buildDocuTypeQuery()

    {

        Query  legalEntityQry = new Query(queryStr(LegalEntityQueryForFilter));

        return legalEntityQry;

    }

    public SysLookupMultiSelectCtrl parmSysLookupMultiSelectCtrl(SysLookupMultiSelectCtrl  _legalEntityListMultiSelectCtrl = legalEntityListMultiSelectCtrl)
    {
        legalEntityListMultiSelectCtrl = _legalEntityListMultiSelectCtrl;
        return legalEntityListMultiSelectCtrl;
    }

    container getSelectedLegalEntities(str _legalEntitiesStr)
    {
        CompanyInfo     companyInfoTable;
        container       tmpValues, conIds, conName;
        int             idx;
 
        if (_legalEntitiesStr)
        {
            tmpValues = str2con(_legalEntitiesStr, ';');
        }
 
        for (idx = 1; idx <= conLen(tmpValues); idx++)
        {
            companyInfoTable    =  CompanyInfo::findDataArea(conPeek(tmpValues, idx));
            conIds             +=  companyInfoTable.RecId;
            conName            +=  companyInfoTable.DataArea;
        }
 
        return [conIds, conName, conIds];
    }

    // copy OnModified Event handler form PurchTableForm Extension  > Data source > select the newly created field.

    [FormDataFieldEventHandler(formDataFieldStr(IPurchTable, PurchTable,    NewStringField), FormDataFieldEventType::Modified)]

    public static void PurchTable_OnModified(FormDataObject sender, FormDataFieldEventArgs e)
    {
            FormRun                     formRun                 = sender.datasource().formRun();

            SysLookupMultiSelectCtrl    companyMultiSelectCtrl  = formRun.parmSysLookupMultiSelectCtrl();

            PurchTable           PurchTableLocal  = formRun.dataSource(FormDataSourceStr(PurchTable, PurchTable )).cursor() as PurchTable;
    
            PurchTableLocal.NewStringField        = con2Str(companyMultiSelectCtrl.getSelectedFieldValues(), ';');
    }

    [FormEventHandler(formStr(PurchTable), FormEventType::Initialized)]
public static void PurchTable_OnInitialized(xFormRun sender, FormEventArgs e)
{
       FormRun             formRun                 = sender.datasource().formRun();
        Query               legalEntityQry          = formRun.buildDocuTypeQuery();
        FormStringControl   newFilednameObject     = formRun.design().controlName('PurchTable_NewfieldForLegalEntityList');
        PurchTable  PurchTableLocal  = formRun.dataSource(FormDataSourceStr(PurchTable, PurchTable )).cursor() as PurchTable;
 
    legalEntityListMultiSelectCtrl              = SysLookupMultiSelectCtrl::construct(formRun,
                                                                                        newFilednameObject ,
                                                                                        querystr(legalEntityQry ),
                                                                                        false,
                                                                                        [tableNum(PurchTable), fieldNum(PurchTable, NewfieldForLegalEntityList)]);
 
    legalEntityListMultiSelectCtrl.refreshQuery(legalEntityQry);
    legalEntityListMultiSelectCtrl.set(formRun.getSelectedLegalEntities(PurchTable.NewfieldForLegalEntityList));
    formRun.parmSysLookupMultiSelectCtrl(legalEntityListMultiSelectCtrl);
}
----------------------------------

ON DIALOG FORM:

Steps:

1. Create Contract Class or Extension of standard contract class and add this mehod - Parm List of legal entities.

    public  List  selectedEntities;

        [ DataMemberAttribute('selectedEntities'),
            SysOperationDisplayOrderAttribute('101'),
             SysOperationGroupMemberAttribute('ProcessIdentifierGroup'),
             AifCollectionTypeAttribute('selectedEntities', Types::String),
             SysOperationLabelAttribute(literalStr("@SYS303247"))
      ]

    public List parmSelectedLegalEntities(List _selectedEntities = selectedEntities)
    {
        selectedEntities = _selectedEntities;

        return selectedEntities;
    }


2. Create UI Builder Class or Extension of standard UI Builder class and Register lookup method.

    Example:

    [ExtensionOf(classStr(StandardClassUIBuilder))]
    final class StandardClassUIBuilder_OurModel_Extension
    {
          public  DialogField          availableCompanies;
          public  DialogField          exchangeRateType;
          public  StandardContract contract; // above created contract or base contract class name

        public void postBuild()
        {
            boolean mustSkipNext = true;

            //DialogField reportIdFieldloc = this.reportIdField;
            //DialogField runInBundleloc = this.runInBundle;

            try
            {
                if (mustSkipNext)
                {
                    throw Exception::UpdateConflict;
               }
                next postBuild();
            }
 
            catch (Exception::UpdateConflict)
             {
                    //standardcode
           
                    // if require check with company info table buffer find method and set empty value.
                reportIdField.value('');

                    runInBundle.visible(true);
        
                    contract     = this.dataContractObject() as aboveContractClassName;
                    availableCompanies = this.bindInfo().getDialogField(contract, methodStr(aboveContractClassName, parmSelectedLegalEntities));

                    availableCompanies.lookupButton(FormLookupButton::Always);

            }


         }

        public void postRun()
        {
                boolean mustSkipNext = true;
                try
                {
                    if (mustSkipNext)
                    {
                            throw Exception::UpdateConflict;
                    }
                    next postRun();
                }
 
                catch (Exception::UpdateConflict)
                {
                        Query             query     = new Query();
                        QueryBuildDataSource    qbdsLegalEntity     = query.addDataSource(tablenum(CompanyInfo));

                        qbdsLegalEntity.fields().addField(fieldNum(CompanyInfo, DataArea));
                        qbdsLegalEntity.fields().addField(fieldNum(CompanyInfo, Name));

                        container selectedFields = [tableNum(CompanyInfo), fieldNum(CompanyInfo, DataArea)];

                        SysLookupMultiSelectCtrl::constructWithQuery(this.dialog().dialogForm().formRun(), availableCompanies.control(), query, false, selectedFields);
        
                }

        }       
    
  }

Thursday, January 23, 2025

D365: Download HCM Person Image (Container field) to Local Folder without Download option

 

internal final class SaveImageFromTableToLocalFile

{

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

    {

        HcmWorker           hcmWorker;

        HcmPersonImage      personImageTable;

        container           imageContainer;


        str                 filePath;

        int                 fileSize;

        SysParameters    sysParameterTable;

        FilePath            staticParameterFilePath;

        BinData             bin;

        boolean            isSuccess = false;

        sysParameterTable = SYSParameterTable::find();

        staticParameterFilePath = sysParameterTable.StaticFilePath; // New Field, EDT: FilePath


        if (!staticParameterFilePath)

        {

            throw error ("Specify file Path in System Parameter form to download employee images.");

        }

        

        while select hcmWorker

        {

            // Retrieve the image data from your table

            select personImageTable where personImageTable.Person == hcmWorker.Person;         

            // Check if the image data exists

            if (personImageTable.Image != conNull())

            {

                //filePath = strFmt("C:\\temp\\%1.jpg", hcmWorker.PersonnelNumber);


                bin = new BinData();


                filePath = strFmt(staticParameterFilePath +"\\%1.jpg", hcmWorker.PersonnelNumber);


                imageContainer = personImageTable.Image;

                fileSize = conLen(imageContainer);


                bin.setData(imageContainer);


                bin.saveFile(filePath);

                isSuccess = true;

            }

        }


        if (isSuccess)

        {

            info(strFmt("Files are saved in given static file path: %1", staticParameterFilePath));

        }

    }


}

Monday, August 26, 2024

How to create Self Signed Certificate (.cer) file for License code and activate the ISV Solution in Dynamics 365 F&O Development Server

Follow below steps to create SSL certificate for DEV server:

1. Login into Development Server (Either Cloud Hosted or OnPremises)


2. Goto Windows Powershell and execute below code to create our own certificate.

$cert = New-SelfSignedCertificate -CertStoreLocation cert:\LocalMachine\My -DnsName "MyISVSolutionCert" -Type CodeSigningCert -KeyExportPolicy Exportable -HashAlgorithm Sha256 -KeyLength 2048 -KeySpec Signature -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotBefore (Get-Date -Year 2024 -Month 8 -Day 1) -NotAfter (Get-Date -Year 2025 -Month 12 -Day 31)


3. Click Start > Manage computer certificates path > Personal (Folder) > Certificates (sub folder) and Find the new certificate which we created just now - "MyISVSolutionCert".


4. Once you find it, Execute the below code to add reference to this new certificate file.

[String]$certpath = join-path -Path "cert:\LocalMachine\My\" -childpath "$($cert.Thumbprint)"


5. Create the secure string password that the certificate uses. (Replace "###############" with your defined certificate password)

[System.Security.SecureString]$certPassword = ConvertTo-SecureString -String "###############" -Force -AsPlainText


6. Export the certificate private key as .pfx file using password and store this file into C:\Temp folder.

Export-pfxCertificate -Cert $certPath -FilePath "C:\Temp\MyISVSolutionCert.pfx" -Password $certPassword


7. Export the certificate public key as a .cer file by using below powershell command

Export-Certificate -Cert $certPath -FilePath "C:\Temp\MyISVSolutionCert.cer"


8. Add this new certificate to the root store:

certutil -addstore root C:\Temp\MyISVSolutionCert.cer


9. Now we can see this certificate in "Trusted Root Certificates" folder in "Manage computer certificates" form from windows.


10. System is now generated new certificate and placed at "Trusted Root Certificates". 


11. Create New Resource from AOT (Name: MyISVSolutionCertResource) from AOT and choose the certificate file (.cer) from C:/Temp folder.


12. Create License code from AOT (For example: MyISVSolutionCertLicense) and select Resource property of License code and Lookup and select the newly created Resource (MyISVSolutionCertResource).


13. Give some meaningful name into Certificate name property.


14. Create Configuration key from AOT and assigned this License code into this Configuration.


15. Still you are unable to see your custom configuration key in System Admin > Setup > License information form.

<< Close powershell window>>


16. Then, Go to Browser > Application Page - Home > Help and Support (? mark logo) > About > Click - Licenses and find below details

DNS: (Domain or Customer (licensed for)): myworkingcompany.ae

Serial number: for example: 84atef28-09f4-1jk6-387d-b01cfa66c24x


17. **Open command prompt and Copy the below code: till bin folder: (To initialize customer and serial number for this license)

K:\AosService\PackagesLocalDirectory\bin\axutil genlicense /file:c:\Temp\MyISVSolutionCert.txt /certificatepath:c:\Temp\MyISVSolutionCert.pfx /licensecode:MyISVSolutionCertLicense /customer:myworkingcompany.ae /serialnumber:84atef28-09f4-1jk6-387d-b01cfa66c24x /password:mypassword@123


18. ** The same command prompt and Copy the below code: till bin folder: (To Import the license into the target environment):


* Prerequisites : Open SQL Server create new login under Security: Create new username and password and give "SysAdmin" Role access.

For example:

username: MyCompanyNameAdmin

Password: pass@word1


** The same command prompt and Copy below code and execute:

K:\AosService\PackagesLocalDirectory\bin\Microsoft.Dynamics.AX.Deployment.Setup.exe --setupmode importlicensefile --metadatadir K:\AosService\PackagesLocalDirectory --bindir K:\AosService\PackagesLocalDirectory --sqlserver . --sqldatabase AxDB --sqluser MyCompanyNameAdmin --sqlpwd pass@word1 --licensefilename c:\Temp\MyISVSolutionCert.txt