Search your query

Wednesday, December 24, 2025

Add Custom Query Range with standard HCMWorkerLookup Form (HcmWorker name filter will work in this logic)

 > Copy Event Handler class method:


[FormControlEventHandler(formControlStr(PurchRFQCaseTable, PurchRFQCaseLine_NewlyCreatedWorkerRecReferenceField), FormControlEventType::Lookup)]

public static void PurchRFQCaseLine_NewlyCreatedWorkerRecReferenceField_OnLookup(FormControl sender, FormControlEventArgs e)

{

    HcmWorkerLookup         hcmWorkerLookup;

    Query                               query;

    QueryBuildDataSource    dsHcmWorkerTableDS;


    hcmWorkerLookup = HcmWorkerLookup::newOnlyActiveEmployeesWithinCompany();

    query                       = hcmWorkerLookup.updateQuery();


    dsHcmWorkerTableDS = query.dataSourceTable(tableNum(HcmWorker));

    dsHcmWorkerTableDS.addRange(fieldNum(HcmWorker,                   

            NewlyCreatedBooleanFieldInHcmWorkerToFilter)).value(queryValue(NoYes::Yes));


    hcmWorkerLookup.lookupWorker(sender);


}



>> If it is normal lookup method then replace sender by that field name. for example:

private void newlyCreatedWorkerFieldLookup(FormStringControl _newlycreatedFieldForLookup)

{

    HcmWorkerLookup         hcmWorkerLookup;

    Query                               query;

    QueryBuildDataSource    dsHcmWorkerTableDS;


    hcmWorkerLookup = HcmWorkerLookup::newOnlyActiveEmployeesWithinCompany();

    query                       = hcmWorkerLookup.updateQuery();


    dsHcmWorkerTableDS = query.dataSourceTable(tableNum(HcmWorker));

    dsHcmWorkerTableDS.addRange(fieldNum(HcmWorker,                   

            NewlyCreatedBooleanFieldInHcmWorkerToFilter)).value(queryValue(NoYes::Yes));


    hcmWorkerLookup.lookupWorker(_newlycreatedFieldForLookup);

}

Wednesday, November 5, 2025

Amount to Amount in Words (ARABIC) || GLOBAL Class Extension || Numerals To Text in Arabic

X++ Code for Numeral to Text in Arabic Language.


[ExtensionOf(classStr(Global))]

static class Global_OurModelName_Extension

{

    static TempStr numeralsToArabicTxt(real _num)

    {

        int     numOfPennies = any2int(decRound(frac(_num), 2) * 100) mod 100;

        real    test         = _num - frac(_num);


        int64   numOfTenths;

        str 20  ones[19], tenths[9], hundreds, thousands, millions, billions, trillions;


        int64   temp;

        str 200 returntxt;

        int64   testLoc;

        int     fils;


        str     zero;

        str     comma;

        str     and;

        str     cent;


        real modOperator(real a1, real a2)

        {

            int tmpi;

            real tmp1, tmp2;


            tmp1 = a1 / a2;

            tmpi = real2int(tmp1);

            tmp2 = tmpi;

            return (tmp1 - tmp2)*a2;

        }


        str doubleDigit2ARTxt(real doubledigit,boolean _pennies = false)

        {

            str     txt;

            int     firstDigit;

            real    tempdigit;


            //if (_pennies)

            //{

            //    firstDigit = doubledigit * 10;

            //    doubledigit = doubledigit * 100;


            //    if (!firstDigit)

            //    {

            //        doubledigit = doubledigit mod 10;

            //        //txt = zero + " " + ones[doubledigit];

            //        txt = ones[doubledigit];

            //        return txt;

            //    }

            //}


            tempdigit = doubledigit;

            

            if (tempdigit >= 20)

            {

                tempdigit = tempdigit div 10;

                txt = tenths[tempdigit];

                doubledigit = doubledigit mod 10;

            }

            

            if (doubledigit >= 1)

            {

                txt = txt ?  (ones[doubledigit] + and + txt) : ones[doubledigit];

            }


            return txt;

        }


        real checkPower(real  _test,int64 _power)

        {

            int64   numOfPower;


            if (_test >= _power)

            {

                numOfPower = _test div _power;


                if (numOfPower >= 100)

                {

                    temp = numOfPower div 100;


                    if(temp > 9)// The validation was previously on 2

                    {

                        returntxt = returntxt ? (returntxt + and + ones[temp] + ' ' + hundreds) :(returntxt + ' ' + ones[temp] + ' ' + hundreds);

                    }

                    else

                    {

                        switch(temp)

                        {


                            Case 1:

                                returntxt = returntxt ? (returntxt + and + hundreds) : (returntxt + ' ' + hundreds);

                                break;

                            Case 2:

                                // TO DO need to insert a label for two hundred in Arabic

                                returntxt = returntxt ? (returntxt + and + "مائتين") :   returntxt + ' ' + "مائتين";

                                break;

                            Case 3:

                                // TO DO need to insert a label for three hundred in Arabic

                                returntxt = returntxt ? (returntxt + and + "ثلاثمائة") :   returntxt + ' ' + 'ثلاثمائة';

                                break;

                            Case 4:

                                // TO DO need to insert a label for four hundred in Arabic

                                returntxt = returntxt ? (returntxt + and + "اربعمائة") :   returntxt + ' ' + "اربعمائة";

                                break;

                            Case 5:

                                // TO DO need to insert a label for five hundred in Arabic

                                returntxt = returntxt ? (returntxt + and + "خمسمائة") :   returntxt + ' ' + "خمسمائة";

                                break;

                            Case 6:

                                // TO DO need to insert a label for six hundred in Arabic

                                returntxt = returntxt ? (returntxt + and + "ستمائة") :   returntxt + ' ' + "ستمائة";

                                break;

                            Case 7:

                                // TO DO need to insert a label for seven hundred in Arabic

                                returntxt = returntxt ? (returntxt + and + "سبعمائة") :   returntxt + ' ' + "سبعمائة";

                                break;

                            Case 8:

                                // TO DO need to insert a label for eight hundred in Arabic

                                returntxt = returntxt ? (returntxt + and + "ثمانمائة") :   returntxt + ' ' + "ثمانمائة";

                                break;

                            Case 9:

                                // TO DO need to insert a label for nine hundred in Arabic

                                returntxt = returntxt ? (returntxt + and + "تسعمائة") :   returntxt + ' ' + "تسعمائة";

                                break;


                        }

                    }

                    numOfPower = numOfPower mod 100;

                }


                if (numOfPower > 2 && _power > 100)

                {

                    returntxt = returntxt ?  (returntxt + and + doubleDigit2ARTxt(real2int(numOfPower))) : (returntxt  + ' ' + doubleDigit2ARTxt(real2int(numOfPower)));

                }

                else

                {

                    if(returntxt && numOfPower)

                    {

                        returntxt = returntxt + and + ' ';

                    }

                }


                switch(_power)

                {

                    case 1000000000000 :

                    {

                        if( numOfPower == 2)

                        {

                            // TO DO need to insert a label for two trillions in Arabic

                            returntxt = returntxt + "تريليونين ";

                        }

                        else

                        {

                            returntxt = numOfPower > 10 ||  numOfPower == 1 || numOfPower == 0 ? (returntxt + ' ' + trillions) : (returntxt + ' ' + "تريليونات");

                        }

                        _test = modOperator(_test, 1000000000000.00);

                        break;

                    }

                    case 1000000000 :

                    {

                        if( numOfPower == 2)

                        {

                            // TO DO need to insert a label for two billions in Arabic

                            returntxt = returntxt + "مليارين";

                        }

                        else

                        {

                            returntxt = numOfPower > 10 ||  numOfPower == 1 || numOfPower == 0 ? (returntxt + ' ' + billions) : (returntxt + ' ' + "مليارات");

                        }

                        _test = modOperator(_test, 1000000000);

                        break;

                    }

                    case 1000000 :

                    {

                        if( numOfPower == 2)

                        {

                            // TO DO need to insert a label for two Millions in Arabic

                            returntxt = returntxt + "مليونين";

                        }

                        else

                        {


                            returntxt = numOfPower > 10 || numOfPower == 1 || numOfPower == 0 ? (returntxt + ' ' + millions) : (returntxt + ' ' + "ملايين");


                        }

                        _test = modOperator(_test, 1000000);

                        break;

                    }

                    case 1000 :

                    {

                        if( numOfPower == 2)

                        {

                            // TO DO need to insert a label for two Thousands' in Arabic

                            returntxt = returntxt + "ألفين";

                        }

                        else

                        {

                            returntxt = numOfPower > 10 ||  numOfPower == 1 || numOfPower == 0  ? (returntxt + ' ' + thousands) : (returntxt + ' ' + "الاف");

                        }

                        _test = modOperator(_test, 1000);

                        break;

                    }

                    case 100 :

                    {

                        switch (numOfPower)

                        {

                            case 2:

                                returntxt = returntxt + "مائتين";

                                break;


                            case 3:

                                returntxt = returntxt +"ثلاثمائة";

                                break;


                            case 4:

                                returntxt = returntxt + "اربعمائة";

                                break;


                            case 5:

                                returntxt = returntxt + "خمسمائة";

                                break;


                            case 6:

                                returntxt = returntxt + "ستمائة";

                                break;


                            case 7:

                                returntxt = returntxt + "سبعمائة";

                                break;


                            case 8:

                                returntxt = returntxt + "ثمانمائة";

                                break;


                            case 9:

                                returntxt = returntxt + "تسعمائة";

                                break;


                            default:

                                returntxt = returntxt + ' ' + hundreds;

                        }


                        _test = modOperator(_test, 100);

                        break;

                    }

                }


            }

            return _test;


        }


        infolog.language("AR");


        and     = ' ' + "@SYS5534" + ' ';

        comma   = "درهم"; // United Arab Emirates

        comma =  "ريـال"; // Saudi Arabia

        

        //comma = "@SYS80142";

        

        zero    = "@SYS2068";

        cent    = "فلس";    // United Arab Emirates

        cent    = "هللــه"; // Saudi Arabia


        ones[1]     = "@SYS26620";

        ones[2]     = "@SYS26621";

        ones[3]     = "@SYS26622";

        ones[4]     = "@SYS26626";

        ones[5]     = "@SYS26627";

        ones[6]     = "@SYS26628";

        ones[7]     = "@SYS26629";

        ones[8]     = "@SYS26630";

        ones[9]     = "@SYS26631";

        ones[10]    = "@SYS26632";

        ones[11]    = "@SYS26633";

        ones[12]    = "@SYS26634";

        ones[13]    = "@SYS26635";

        ones[14]    = "@SYS26636";

        ones[15]    = "@SYS26637";

        ones[16]    = "@SYS26638";

        ones[17]    = "@SYS26639";

        ones[18]    = "@SYS26640";

        ones[19]    = "@SYS26641";


        tenths[1]   = 'Not used';

        tenths[2]   = "@SYS26643";

        tenths[3]   = "@SYS26644";

        tenths[4]   = "@SYS26645";

        tenths[5]   = "@SYS26646";

        tenths[6]   = "@SYS26647";

        tenths[7]   = "@SYS26648";

        tenths[8]   = "@SYS26649";

        tenths[9]   = "@SYS26650";


        hundreds    = "@SYS26651";

        thousands   = "@SYS26652";

        millions    = "@SYS26653";

        billions    = "@SYS26654";

        trillions   = "@SYS101697";



        test        = checkPower(test, 1000000000000);

        test        = checkPower(test, 1000000000);

        test        = checkPower(test, 1000000);

        test        = checkPower(test, 1000);

        test        = checkPower(test, 100);


        if(returntxt && test)

        {

            returntxt = returntxt + and + doubleDigit2ARTxt(real2int(test));

        }

        else

        {

            returntxt = returntxt + ' ' + doubleDigit2ARTxt(real2int(test));

        }


        if(numOfPennies)

        {

            //Removing the stars and addin the pound and cent wording to fullfil the Egyptian requierment

            returntxt = ' فقط ' + returntxt + ' ' + comma + ' ' + and + doubleDigit2ARTxt(numOfPennies,true) + ' ' + cent + ' لاغير ';

            //returntxt = '***' + returntxt + ' ' + comma + ' ' + doubleDigit2ARTxt(numOfPennies,true);


        }

        else

        {

            //Removing the stars and the zeros if no cents to fullfil the Egyptian requierment

            returntxt = ' فقط ' + returntxt + ' ' + comma + ' لاغير ';


            //returntxt = '***' + returntxt + ' ' + comma + ' ' + zero + ' ' + zero;

        }


      

        return returntxt;

    }

}

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

Wednesday, August 14, 2024

Generate and Place QR Code in D365 F&O Form and SSRS Reports

 Need to follow below steps to generate QR code by using X++ in D365 F&O.

1. Create one container field (QRCodeField) in required Table (Either Regular Table for Form or Temp Table for SSRS report) and set Extended data type property to "BitMap"

2. Create One Class and copy below codes for generating QR Code in X++.

/// <summary>

/// Generate QR Code

/// </summary>

class MyQRCodeHelper

{

    public static container QRCodeGenerator(String255 _qRCodeContainer)

    {

            Microsoft.Dynamics.ApplicationSuite.QRCode.Encoder Encoder;

            System.Drawing.Bitmap bm = null;

            try

            {

                var qrCodeEncoder = new Microsoft.Dynamics.ApplicationSuite.QRCode.Encoder();

                bm = qrCodeEncoder.Encode(_qRCodeContainer);

            }

            catch (Exception::CLRError)

            {

                error(CLRInterop::getLastException().ToString());

            }

           using (var stream = new System.IO.MemoryStream())

            {

                bm.Save(stream, System.Drawing.Imaging.ImageFormat::Bmp);

                bm.Dispose();

                return Binary::constructFromMemoryStream(stream).getContainer();

            }

    }

}

3. Goto Form - init() method or For SSRS report, Goto Insert Temp Table method and write below code to initialize and generate QR code.

    Form init() method:

    {

        str qrCodeInformation;

        super();

        qrCodeInformation    =  strFmt("This is QR code generation development and more information visit: %1", "http://mohamedhussaindynamics365.blogspot.in/");

        MyQRCodeTable.QRCode = MyQRCodeHelper::QRCodeGenerator(qrCodeInformation);

    }


>> Place this container filed in form or report and scan the QR code.

Friday, March 1, 2024

D365 F&O: Virtual Machine (VM) - Software Deployable Package Deployment by command - (When this error comes: "‘The devInstall option is not applicable to the current deployable package")

D365 F&O: Virtual Machine (VM) - Software Deployable Package Deployment by command - (When this error comes: "‘The devInstall option is not applicable to the current deployable package")

    When AxUpdateInstaller.exe devinstall command prompt is not working in VM or Applying software deployable package for cloud hosted dev environment is not working or unable to deploy your package then try the following steps:

Steps:

1. Open Command prompt, as administrator and type below commands.

2. Example > cd C:\Hussain\AXDeployablePackage_20240301_05_05_05 (cd and file path (Specify your deployable package location (unzip your software deployable package) ) 

3. C:\Hussain\AXDeployablePackage_20240301_05_05_05> AXUpdateInstaller.exe generate -runbookid ="DevelopmentPackage" topologyfile="DefaultTopologyData.xml" -servicemodelfile="DefaultServiceModelData.xml" -runbookfile="DevelopmentPackage-runbook.xml" 

4. C:\Hussain\AXDeployablePackage_20240301_05_05_05> AXUpdateInstaller.exe import -runbookfile=DevelopmentPackage-runbook.xml

4. If already runbook exist, just replace the runbook by typing Yes in command prompt.

5.  C:\Hussain\AXDeployablePackage_20240301_05_05_05> AXUpdateInstaller.exe execute -runbookid=DevelopmentPackage


Note: Please ensure that all kind of "Visual studio services" must be stopped and Stop: Microsoft Dynamics services (Data Import, Export and Batch services)

Monday, February 19, 2024

X++ code to create Ledger Journal Line (General Journal) for any ledger account type (Ledger, Vendor, Customer.. etc)

 Find below code will help you with Dimensions when you create GL Journal lines.

 

public void createJournalLines()

{

    LedgerJournalTrans                  ledgerJournalTrans;

    HcmWorker                           HcmWorker;

    Amount                              tmpAmount = 100;

    LedgerJournalTransTaxExtensionIN    ledgerJournalTransTaxExtensionIN;

    LedgerDimensionAccount              ledgerAccount;

    Boolean                             isLedgerTransaction = false;

    accountNum                          ledgerAccountNum_NonLedgerType;

    ledgerJournalCheckPost              ledgerJournalCheckPost;

 

    #ISOCountryRegionCodes

   

    ledgerJournalTrans.Voucher      = NumberSeq::newGetVoucherFromCode(numberSequenceTable.NumberSequence).voucher();

    ledgerJournalTrans.JournalNum   = headerJournal.JournalNum; //From Journal Header Table; //NumberSeq::newGetNum(LedgerParameters::numRefJournalNum()).num();        ledgerJournalTrans.CurrencyCode         = CompanyInfoHelper::standardCurrency();

    ledgerJournalTrans.ExchRate     = ExchangeRateHelper::exchRate(ledgerJournalTrans.CurrencyCode);

       

     //if (General Ledger Journal – Type is Ledger)

     {

         ledgerJournalTrans.AccountType = LedgerJournalACType::Ledger;

         isLedgerTransaction = Yes;

     }

     //else if (Customer, vendor)

     {

        ledgerJournalTrans.AccountType = LedgerJournalACType::Vendor; // select appropriate type based on input of Ledger dimension and account type of Posting profile.

        isLedgerTransaction = false;

    }

    ledgerJournalTrans.DefaultDimension     = // Input: Default dimension from Hcmworker in our example;

     if (isLedgerTransaction)

     {

            ledgerAccount = LedgerDimensionFacade::serviceCreateLedgerDimension(_ledgerJournalTrans.JournalNum, ledgerJournalTrans.DefaultDimension);

           ledgerJournalTrans.LedgerDimension = ledgerAccount;

     }

     else

     {

            ledgerAccountNum_ NonLedgerType  = LedgerDimensionFacade::getDisplayValueForLedgerDimension(ledgerAccount); // either vendor, customer or bank id

             ledgerAccount = LedgerDynamicAccountHelper::getDynamicAccountFromAccountNumber(ledgerAccountNum, ledgerJournalTrans.AccountType);

      }

     //if (if Debit amount)

    {

        ledgerJournalTrans.AmountCurDebit   = CurrencyExchangeHelper::amount(100, ledgerJournalTrans.CurrencyCode);

    }

    // else -- if credit amount.

    {

        ledgerJournalTrans.AmountCurCredit  = CurrencyExchangeHelper::amount(100, ledgerjournalTrans.CurrencyCode);

    }

     ledgerJournalTrans.TransDate                = Today();

    ledgerJournalTrans.Txt                      = "Create a Journal Line";

    ledgerJournalTrans.BankNegInstRecipientName = HcmWorker.name();

    ledgerJournalTrans.insert();

    if (SysCountryRegionCode::isLegalEntityInCountryRegion([#isoIN]))

    {                           

                                       ledgerJournalTransTaxExtensionIN.TaxModelDocLineExtensionIN::initFromBaseTable (ledgerJournalTrans);

                    ledgerJournalTransTaxExtensionIN.TaxModelDocLineExtensionIN::initFromExtensionTable(LedgerJournalTransTaxExtensionIN::findByLedgerJournalTrans(ledgerJournalTrans.RecId));

    ledgerJournalTransTaxExtensionIN.insert();

}

       

    // If post this journal..

    //Post the Journal

    ledgerJournalCheckPost = ledgerJournalCheckPost::newLedgerJournalTable(ledgerJournalTable,NoYes::Yes); // Header Journal Table.

    ledgerJournalCheckPost.run();

}