Saturday, July 16, 2022

Get sales totals amount by using x++ code

 Get sales totals amount by  using x++ code.

    //Total Discount from Sales Totals form
    SalesTable      salesTable      = SalesTable::find('sales order number');
    SalesTotals     salesTotals     = SalesTotals::construct(salesTable, salesUpdate::All);
    container       displayFields;
    DiscAmount      totalDisc;
    RealBase        subTotal;
    AmountCur       invoiceAmount;
    AmountMST       salesTax;
    AmountMST       totalCharges;
displayFields = SalesTotals::displayFieldsServer(salesTable, SalesUpdate::All, salesTotals.CurrencyCode()); //Total Discount totalDisc = conpeek(displayFields, TradeTotals::posEndDisc()); info(Strfmt("Total discount %1", totalDisc)); //Subtotal Amount subTotal=conpeek(displayFields, TradeTotals::posBalance()); info(Strfmt("Subtotal Amount %1", subTotal)); //Invoice Amount invoiceAmount =conpeek(displayFields, TradeTotals::posTotalAmount()); info(Strfmt("Invoice Amount %1", invoiceAmount));
   //sales Tax
   salesTax = conpeek(displayFields, TradeTotals::posTaxTotal());
info(Strfmt("sales Tax %1", salesTax));
 //Total Charges
  totalCharges = conpeek(displayFields, TradeTotals::posMarkup());
info(Strfmt("Total Charges
%1", totalCharges));


Keep Daxing!!

Convert Image to Base64 string in D365FO

 Convert Image to Base64 string in D365FO.

    HcmWorker           HcmWorker;
    HcmPersonImage      HcmPersonImage;
    ExecutePermission   perm;
    container           imgObj;
    BinData             bd;
    Notes               result;

    new InteropPermission(InteropKind::ClrInterop).assert();
    perm = new ExecutePermission();
    perm.assert();

    HcmWorker       = HcmWorker::findByPersonnelNumber('employeeId');
    HcmPersonImage  = HcmPersonImage::findByPerson(HcmWorker.Person);
    
    imgObj = HcmPersonImage.Image;
    bd = new BinData();
    bd.setData(imgObj);
    
    result = bd.base64Encode();
    //ssPermission::revertAssert();



Keep Daxing!!




Get workflow pending Approval Name using x++ in D365FO

 Get workflow pending Approval Name using x++ in D365FO.

display HcmWorkerName displayWorkflowApproverName()
{
    WorkflowWorkItemTable workItemTable;

    select workItemTable 
        where workItemTable.RefRecId == this.RecId 
           && workItemTable.RefTableId == this.TableId &&
            ((workItemTable.Status == WorkflowWorkItemStatus::Pending) 
                || (workItemTable.Status == WorkflowWorkItemStatus::Delegated));

    return HcmWorker::find(HcmWorker::userId2Worker(workItemTable.UserId)).name();
}



Keep Daxing!!





convert date time to string using x++ In D365FO

 Convert date time to string using x++ In D365FO.

static void dateToStr(Args _args)
{
    UtcDateTime     dateTime = DateTimeUtil::getSystemDateTime();

    DateTimeUtil::toStr(dateTime);// Convert to str : "2022-06-15T13:00:30.0900000"
---or---
    // If you want special characters.

    system.DateTime sysDateTime;

    sysDateTime =  dateTime;

    print sysDateTime.ToString("yyyy-MM-dd");
    print sysDateTime.ToString("MM/dd/yy H:mm:ss zzz");
----or----
use date2Str:

    str datestr;

    datestr = date2Str(today(),
                        321,
                        DateDay::Digits2,
                        DateSeparator::Hyphen, // separator1
                        DateMonth::Digits2,
                        DateSeparator::Hyphen, // separator2
                        DateYear::Digits4);
    
    info('Today is: ' + datestr);
}
---Or---
    utcDateTime     utcDateTimeFromString   = DateTimeUtil::anyToDateTime("2012-04-01T00:00:00");
    utcDateTime     utcDateTimeISOFormat    = 2012-04-01T00:00:00;
    utcDateTime     utcNow;
    System.DateTime systemDateTime;
    date            dateOnly;
    str             systemDateTimeStr;

    // AX UTC to System.DateTime: Result: "7/17/2022 3:57:25 AM"
    systemDateTime      = Global::utcDateTime2SystemDateTime(DateTimeUtil::utcNow());

    //System.DateTime to AX UTC: Result:"7/17/2022 03:57:52 am"
    utcNow              = Global::clrSystemDateTime2UtcDateTime(System.DateTime::get_UtcNow());

    // date portion from a UTC:  Result:"7/17/2022"
    dateOnly            = DateTimeUtil::date(utcNow);

    // Cast to string for output
    systemDateTimeStr   = systemDateTime.ToString();
     
    info(strFmt("%1, %2, %3",
                systemDateTimeStr,
                utcNow,
                dateOnly));
    
    info(strFmt("%1, %2",
                DateTimeUtil::toStr(DateTimeUtil::utcNow()),//2022-07-17T04:00:58
                DateTimeUtil::toStr(utcNow)));// 2022-07-17T04:00:59





Keep Daxing!!




Wednesday, July 13, 2022

Generate Bearer token using x++ in D365FO.

  Generate Bearer token using x++ in D365FO.

  • While triggering API we need to generate a token.
  • While calling their API We need to send the token, So they will validate that Token and send the response data If i.e. valid.
  • To Generate Token we need
    • Client Id
    • Client secret
    • Tenant Id
  • For the above details, we need to do the app registration in the Azure portal.
  • We need to create one record with the client id in the Azure application in the system administration module.

    AuthenticationResult        authResult; 

        
    ClientCredential        clientCrendential   = new ClientCredential('ClientId', 'ClientSecretKey');
    AuthenticationContext   authContext         = new AuthenticationContext(url);
            // https://login.microsoftonline.com/tenantId/oauth2/token
        
    authResult  = authContext.AcquireToken('Scope or Resource(URL)', clientCrendential);
        
    token =  authResult.AccessToken;

    Info(token);


Scope: ABCD/.default

--> api//:ABCD/.default 

    --> We need to remove api//: 

    --> Otherwise it will throw the error.


Keep Daxing!!

Generate token from key vault parameters using x++ in D365FO.

 Generate token from key vault parameters using x++ in D365FO.

  •  We are saving our token URL in Key vault for security. By using the below code we will get the URL form Key Vault. 
  • We have used same client ID and client secret for key vault also. So I have configured that in key vault parameters. 

    
    str                           url, token;
    KeyVaultParameters            vaultParameter;
    KeyVaultCertificateTable      vaultCertificate;

    select vaultParameter where vaultParameter.Name == 'Name';// which we have created in Key vault.

    if (vaultParameter)
    {
        select vaultCertificate where vaultCertificate.KeyVaultRef == vaultParameter.RecId;

        KeyVaultClientHelper::removeCachedKeyVaultClient(vaultCertificate.KeyVaultCertificate);

        url = KeyVaultCertificateHelper::getManualSecretValue(vaultCertificate.RecId);
        // Here KeyVault will generate the Token URL.
AuthenticationResult authResult; ClientCredential clientCrendential = new ClientCredential(                     vaultParameter.AppClientId, vaultParameter.getClientSecretKey());                     // Based on client Id and client secret key we have created Key vault. AuthenticationContext authContext = new AuthenticationContext(url); authResult = authContext.AcquireToken('Scope or Resource(URL)', clientCrendential);         token = authResult.AccessToken; Info(token); }



Keep Daxing!!

Get the previous value and current value If user changed any Record on form in D365FO

Hi guys, Today I got a requirement If user is changed any value in user info form that time I need to capture the previous value and current value.

For this I have created new table and I have inserting data into that table by using below class.

This class I am calling from write method in form data source.


public class UserModificationLog
{

    public static void updateLogTable(Common    _common)// This method I am calling from write method.
    {
        
        switch (_common.tableId)
        {
            case tablenum(UserInfo) :
                UserModificationLog::updateUserLog(_common);
                break;
        }
    }

    public static void updateUserLog(UserInfo    _userInfo)
    {
        DictTable   dictTable     = new sysDictTable(tableNum(UserInfo));
        //DictTable   dictTable     = new sysDictTable(_userInfo.TableId);
        fieldId     fieldId       = dictTable.fieldNext(0);         dictField   dictField;         UserInfo    userInfoOrg   = _userInfo.orig();         while(fieldId)         {             if (userInfo.(fieldId) != userInfoOrg.(fieldId))                 //|| userInfo.(fieldId) != _userInfo.orig().(fieldId))             {                 UserModifications    userModifications =                                      UserModificationLog::getUserModifications(fieldId);                 if (userModifications != UserModifications::None)                 {                     UserModificationLog::insertData(_userInfo, userInfoOrg, fieldId,                                                      dictTable.fieldObject(fieldId).name(),                                                      userModifications);                 }             }                      fieldId = dictTable.fieldNext(fieldId);         }     }     public static void insertData(Common    common, Common    orgCommon,                                     fieldId     fieldId, str fieldName,                                     UserModifications  _userModifications)     {         SecurityUserRolesLogNew roleLocation;         roleLocation.clear();         roleLocation.ModifiedByUserId           = curUserId();         roleLocation.Company                    = curExt();         roleLocation.ModifiedDateTim            = DateTimeUtil::getSystemDateTime();         roleLocation.UserId                     = _common.(fieldNum(UserInfo, id));         roleLocation.UpdatedRecord              = any2Str(_common.(_fieldId));         roleLocation.PreviousRecord             = any2Str(_orgCommon.(_fieldId));         roleLocation.UserModifications          = _userModifications;                                     //UserModificationLog::getUserModifications(_fieldId);         roleLocation.insert();     }
}


 Keep Daxing!!

Get the company logo and company name in SSRS report in D365FO.

 Get the company logo and company name in SSRS report in D365FO.

          

   CompanyInfo companyInfoCompanyInfo::find();

    tmpTable.CompanyLogo = FormLetter::companyLogo();
                //CompanyImage::findByRecord(CompanyInfo::find()).Image;
    tmpTable.CompanyName = companyInfo.Name; 




Keep Daxing!!


Address in D365Fo

Address in D365Fo.


Vendor address: 

    Info(strFmt('Postal - %1', VendTable::find('Vendor Id').postalAddress().Address));

    Info(strFmt('Delivey - %1', VendTable::find('Vendor Id').deliveryAddress().Address));

    Info(strFmt('Invoice - %1', VendTable::find('Vendor Id').invoiceAddress().Address));


Cusomer address:

    Info(strFmt('Postal - %1', CustTable::find('Customer Id').postalAddress().Address));

    Info(strFmt('Postal - %1', CustTable::find('Customer Id').address()));

    Info(strFmt('Invoice - %1', CustTable::find('Customer Id').invoiceAddress().Address));

Warehouse address:

    Info(strFmt('Address - %1', InventLocation::find('InventLocationId').
                                                    logisticsPostalAddress().Address));

    Info(strFmt('Address - %1', InventLocation::find('InventLocationId').Address())); 

    InventLocationLogisticsLocation        inventLocationLogisticsLocation;
    RecId                                  inventLocationRecId;        
    
    Select firstOnly inventLocationLogisticsLocation
        where inventLocationLogisticsLocation.InventLocation == inventLocationRecId
           && inventLocationLogisticsLocation.IsPrimary == NoYes::Yes;

    LogisticsLocation       logisticsLocation = LogisticsLocation::find(
                                                    inventLocationLogisticsLocation.Location);
    
    LogisticsPostalAddress  logisticsPostalAddress  = LogisticsPostalAddress::findRecId(
                                                                    logisticsLocation.RecId);

    Info(strFmt('Address - %1', logisticsPostalAddress.Address));

Site address:

    Info(strFmt('Address - %1', InventSite::find('Site Id').logisticsPostalAddress().Address));


Different Way to Get any Active address:

    LogisticsLocationEntity::location2PostalAddress(transTaxInformation.CompanyLocation, 
                                            DateTimeUtil::getSystemDateTime(), true)

Keep Daxing!! 

How to display information only on the last page within the page footer in SSRS

How to display information only on the last page within the page footer in SSRS.

In the page footer add rectangle and in the hidden property paste the below one.

=IIF(Globals!PageNumber=Globals!TotalPages,false,true)


Keep Daxing!!

Tuesday, July 12, 2022

How to add Records to include option on report dialog in D365FO

 How to add Records to include option on report dialog in D365FO. Some times user want to apply the filter from UI. That time we need to use Records to include option.

  • In Report -- data set properties -- Dynamic Filters (set as True)
  • Need to create static query.
  • That query we need to call from DP class
  • After that Need to write logic in controller class.
Controller class: 

    public class new MyReportController extends SrsReportRunController

      {

public static void main(Args args) { MyReportController controller = new new MyReportController(); controller.parmReportName(ssrsReportStr(MyReport, Report)); controller.parmArgs(args); if(args && args.dataset() == tableNum(MyTable)) { MyTable myTable = _args.record(); Query query;
                    // Get Contract                     //controller.getDataContractObject()//// for sys operation                     //controller.parmReportContract().parmRdpContract() // For Report query = controller.getFirstQuery();// get the query from dp class query.dataSourceTable(tableNum(MyTable)).clearRanges(); query.dataSourceTable(tableNum(MyTable)).addRange(fieldNum(MyTable, Id)).value(queryValue(myTable.Id)); query.dataSourceTable(tableNum(MyTable)).addRange(fieldNum(MyTable, Status)).value(queryValue(MyTable.Status)); } controller.startOperation(); } }

        --------------------------------or--------------------------------------------

        public class new MyReportController extends SrsReportRunController { public void prePromptModifyContract() { //add a range in the report query SrsReportHelper::addParameterValueRangeToQuery(this.getFirstQuery(), tableNum(Mytable), fieldNum(Mytable, RecId), SysQuery::value(this.parmArgs().record().RecId)); } }         -------------------------------------------------------------------------------           public void runReport()
    { myContract contract; queryRun queryRun = new queryRun(this.getFirstQuery()); int i = 1; contract = this.parmReportContract().parmRdpContract(); contract.intialize(); while (queryRun.next()) {     CompanyInfo companyInfo = queryRun.GetNo(1);     switch (i)     { case 1 : contract.parmcompany1(companyInfo.NameAlias); break; case 2 : contract.parmcompany2(companyInfo.NameAlias); break; case 3 : contract.parmcompany3(companyInfo.NameAlias); break; case 4 : contract.parmcompany4(companyInfo.NameAlias); break; case 5 : contract.parmcompany5(companyInfo.NameAlias); break;     }     i++; }     super();     }
         

Dp class: 

    [ SrsReportQueryAttribute(queryStr(TestQuery)),// This line we need to add SrsReportParameterAttribute(classStr(TestContract)) ] class TestDP extends SRSReportDataProviderBase { TestTmp testTmp; public void processReport() { TestQuery testQuery = this.parmQuery();// get the query queryRun queryRun = new queryRun(testQuery)); while(queryRun.next()) { } } }
        


Keep Daxing!!


         


Monday, July 11, 2022

Get Email information of current user/worker using x++ in D365FO

 Get Email information of current user/worker using x++ in D365FO.


    private Email getToEmail()
    {
        HcmWorker          hcmWorker;
        // Get information of current user/worker

        select firstOnly RecId, Person from hcmWorker
            where hcmWorker.RecId == HcmWorkerLookup::currentWorker();
                   
        return hcmWorker.email();
    }


Keep Daxing!!



record insert list in D365FO

 record insert list in D365FO. By using this system insert the data into SQL at one time.


  • This post is for Regular table

[Table method]

Public static Void getTable(CustTable  _custTable)

{
    MYTempTable         myTable;
    SalesTable          salesTable;
    RecordInsertList    recordInsertList = new RecordInsertList(tableNum(MYTable));

    while select salesTable
       where salesTable.CustAccount == _custTable.CustAccount 	
    {
            myTable.clear();
            myTable.CustAccount = salesTable.custAccount; 
            myTable.SalesId     = salesTable.SalesId;

            recordInsertList.add(myTable);
     }
       recordInsertList.insertDatabase();
}

Keep Daxing!!

How to populate data in form with temp table data source using X++ In D365FO

 How to populate data in form with temp table data source using X++ In D365FO.

Here I am using RecordInsertList to insert data in Temp table.

  • I have added temp table in form.
  • In Form init method I am inserting data into temp table.
  • Using linkPhysicalTableInstance I have assigned to temp table buffer to data source.

Form Init method:

[Form]
Public void init()
{
    CustTable  custTable = element.args().record(); 

    MyTempTable.linkPhysicalTableInstance(MyTempTable::getTempTable(custTable)); // add tempTable instance
 
}
[Table method]

Public static MyTemptable getTempTable(CustTable  _custTable)

{
    MYTempTable         myTempTable;
    SalesTable          salesTable;
    RecordInsertList    tempRecordInsertList = new RecordInsertList(tableNum(MYTempTable),
                                                                     true, true, true, 
                                                                     false, true, myTempTable);
    while select salesTable
       where salesTable.CustAccount == _custTable.CustAccount 	
    {
        myTempTable.clear();
        myTempTable.CustAccount = salesTable.CustAccount;
        myTempTable.SalesId     = salesTable.SalesId;

        tempRecordInsertList.add(myTempTable);
    }

    tempRecordInsertList.insertDatabase();

    return myTempTable;
}

If you want to write select / while select statement for temp table follow the below logic. 
    MyTempTable    MyTempTableLoc; 
    MyTempTableLoc.linkPhysicalTableInstance(MyTempTable);// temp table buffer from init method.
    select MyTempTableLoc where 'your condition';
    while select myTempLoc
    {
        // your logic
    }
Keep Daxing!!

Create Dialog box using x++ in D365FO.

 In D365FO most of the time we are using dialog forms but in some times we need to create dialog box.

Using below code we can create Dialog Box. We can any used


if (Box::okCancel("Dialog message", DialogButton::Cancel, "Dialog title") 
                                                                == DialogButton::Ok)
{
// Your code
}
Box::info("your message");
Box::warning("your message");


Keep Daxing!!

Serialize/Deserialize JSON using contract class In D365FO

 We need to create (Serialize)/ Deserialize JSON using contract class in D365FO.

We can serialzing/ Deserializing in multiple places.

  • 1. Using JSON class
  • 2. Using Contract classes.
Way 1:

Way 2:

JSON response:

{
  "Contract": {
    "CustomerId": "Customer 1",
    "Name"      : "Name 1"
  }
}

Below is the Response contract :

[DataContractAttribute] 
public class responceContract
{
    private Contract CustomerContract;     [DataMemberAttribute('Contract'),     DataCollection(Types::Class, classStr(Contract)),     AifCollectionTypeAttribute('_contractClass', Types::Class, classStr(Contract)),     AifCollectionTypeAttribute('return', Types::Class, classStr(Contract))]     public Contract parmContract(Contract _CustomerContract = CustomerContract)     {           CustomerContract = _CustomerContract;       return CustomerContract;     } }


JSON response:

{
  "Contract": [
    {
      "CustomerId": "Customer 1",
      "Name": "Name 1"
    },
    {
      "CustomerId": "Customer 2",
      "Name": "Name 2"
    }
  ]
}

Below is the Response contract :

[DataContractAttribute] 
public class responceContract
{
    private List    Customer;     [DataMemberAttribute('Contract'),     DataCollection(Types::Class, classStr(Customer Contract)),     AifCollectionTypeAttribute('_contractClass', Types::Class, classStr(Customer Contract)),     AifCollectionTypeAttribute('return', Types::Class, classStr(Customer Contract))]     public List parmCustomer(List _contractClass = Customer)     {         Customer = _Customer;         return Customer;     } }


Contract class:

private str    CustomerId; 
private str    Name; 
[DataMemberAttribute('CustomerId')] 
public Str parmCustomerId(Str _CustomerId = CustomerId)
{
    CustomerId = _CustomerId;

    return CustomerId;
} 

[DataMemberAttribute('Name')] 
public Str parmName(Str _Name = Name)
{
    Name = _Name;

    return Name;
}


Keep Daxing!!


The parameter 'e' is not used in D365FO

 

In D365FO we get few BP warnings. 

  • If you use event handler most of the time we are getting "The parameter 'e' is not"  BP.  
  • (FormDataSourceEventArgs e) Most of the time we are not using this. We use this in lookup method.


To rectify this need to use below command.

SuppressBPWarning('BPParameterNotUsed', 'False positive') 

Below is the example for validate method.

[FormDataSourceEventHandler(formDataSourceStr(WHSLocation, WMSLocation),
                         FormDataSourceEventType::ValidatingWrite), 
SuppressBPWarning('BPParameterNotUsed', 'False positive')]
public static void WMSLocation_OnValidatingWrite(FormDataSource sender, FormDataSourceEventArgs e)
{

}


Keep Daxing!!