Monday, 19 September 2022

D365FO Entity insert/update issue Update not allowed for field ‘Entity.FieldName’.

Step 1: Make sure fields properties allow edit is yes in Data entity level(In Table level Allow edit is No). Change to Yes in entity fields property if Not.

Step 2 : Then Write the skip validation code in data entity method.

public void mapEntityToDataSource(DataEntityRuntimeContext _entityCtx, DataEntityDataSourceRuntimeContext _dataSourceCtx)
{
    super(_entityCtx, _dataSourceCtx);
    this.skipDataSourceValidateField(fieldNum(EntityName,Field),true);

}

public void initializeEntityDataSource(DataEntityRuntimeContext _entityCtx, DataEntityDataSourceRuntimeContext _dataSourceCtx)
{
    super(_entityCtx, _dataSourceCtx);
    this.skipDataSourceValidateField(fieldNum(EntityName,Field),true);

}

Step 3: Remove the entity from all the projects and delete it from the data entity list.

Step 4: Rebuild and Synch your project

You will see it will start working and skipping the mentioned fields while import.


Wednesday, 14 October 2020

Configure postman to test D365FO custom or Odata services

Hi Folks,

I will describe the steps to configure Postman app to test D365 FO services.

Step 1: Download postman application and install in your laptop or server. You can download it from https://www.postman.com site.

Step 2: Install the application and open it

Step 3: Configure an environment.

click on new button.


select environment 

Enter a environment name and add variable as mentioned in below screen. I hope you have client id, tenant id, secret key, F&O url. If you don't have this then check with your admin and get it, You need to enter F&O url in resource variable.

Step 4: Configure collection.
Add a new collection by clicking on New collection button


Step 5: Add new request by right clicking over collection


Step 6: Add new request by right clicking over collection
Provide a name (OAuth) and add authentication url 
(https://login.microsoftonline.com/86e72e20-c42b-4288-bb5d-b5f831760843/oauth2/token) and method as Post




 

go to Body tab and add variable as below:

Now go to test tab and paste below script there

var json = JSON.parse(responseBody);
tests["Get Azure AD Token"= !json.error && responseBody !== '' && responseBody !== '{}' && json.access_token !== '';
postman.setEnvironmentVariable("bearerToken"json.access_token);







click on send button. It will create a secure connection and update the bearerToken.
This bearerToken has some expiry time as well so it may expire in 10-15 mins.

Step 8: Now you add new requests (step 5) to check you web services.
In url section, put your customer service url, In body paste your JSON format input value









In Header tab, add keys and values as per below screen










Click on send button and you will receive response from your web service as below:














Similerly you can configure your customer or Odata service and test it.

Monday, 28 September 2020

Create a custom web service in D365FO

Hi Folks,

I am writing this blog to create custom web services in D365 FO. It is same like previous version 2012. All you need to do is to create a class and services. Follow the below process to create a custom web service.

Step 1 // Create a contract class for parameters

[DataContractAttribute('GSCustContract')]

class GSCustContract

{

    AccountNum   custNum;

    [DataMemberAttribute('custNum')]

    public AccountNum parmCustNum(AccountNum   _custNum = custNum)

    {

        custNum  = _custNum;        

        return custNum;

    }

    [DataMemberAttribute('AmountPayable')]

    public str parmAmountPayable(str _amountPayable = amountPayable)

    {

        amountPayable  = _amountPayable;        

        return amountPayable;

    }

    [DataMemberAttribute('LastMonthPaid')]

    public str parmLastMonthPaid(str _lastMonthPaid = lastMonthPaid)

    {

        lastMonthPaid  = _lastMonthPaid;        

        return lastMonthPaid;

    }

}

Step 2:

// Create a service  class for business logic

class GSCustServiceClass

{

[AifCollectionTypeAttribute('return', Types::Class, classStr(GSCustContract)), SysEntryPointAttribute(true)]

    public List customerInfo(CustNo _custNo, DataAreaId _dataAreaId)

    {

        List                                result;

        GSCustContract           contract;

        CustTable                           custTable;

        AmountMST getBalance()

        {

            CustTransOpen           custTrans;            

            select sum(AmountMST) from custTrans

                where custTrans.AccountNum      == custTable.AccountNum;

            if (custTrans.AmountMST < 0)

            {

                return 0;

            }

            else

            {

                return abs(custTrans.AmountMST);

            }

        }

        str getLastPaymMonth()

        {

            CustTransOpen           custTrans;            

            select firstonly AccountNum, TCMBillingType, TransDate from custTrans

                where custTrans.AccountNum      == custTable.AccountNum;            

            return subStr(date2Str(custTrans.TransDate, 123, 2, 0, 2, 0, 2), 3, 6);

        }

        

        changecompany(_dataAreaId)

        {

            result                  = new List(Types::Class);

            custTable               = CustTable::find(_custNo);

            contract  = new GSCustContract();

            contract.parmCustNum(_custNo);

            contract.parmAmountPayable(strReplace(num2Str(getBalance()*100, 10, 0, 0,0), " ", "0"));

                contract.parmLastMonthPaid(getLastPaymMonth());

            }

            result.addEnd(contract);

        }

        return result;

    }

Step 3: Now you need to create a element of service type

go to properties and select the service class which we have created in the above step.
Right click the service operations node and click on new service operations button, go to properties of the service operation node and select the method name.

Step 4: Create a service group element.
add a service to the group and select the service name (created in step 3) in the property of the service node.
Step 5: Build your project

Now your web service is ready to use. use below urls for respective services
<D365FO URL>/api/services/<Service group name>/<Service Name>/<Service operation name>
<D365FO URL>/soap/services/<Service group name>?wsdl

How to schedule a batch job of a class with parameter from X++

 Hi Folks,

sometime we received  a requirement to schedule a batch from x++ code runtime. This kind of requirement comes when there is performance issue while running the same class from previous execution.

For example, we need to write a code to update some data while posting a journal. We want journal posting logic to schedule a batch job for update. In this way journal posting will happen separately and it will schedule a batch job which will do the update and execute other business logic from batch service.

Let say I have a service class which accept a contract class parameter.

// service class

class GSPaymentSettlementService extends SysOperationServiceBase

{

    [SysEntryPoint]

    public void paymentSettlement(GSPaymentSettlementContract     _contract)

    {

        // Your business logic 

        }

}


// contract class

[DataContract]

class GSPaymentSettlementContract

{

    Id       id;

    [DataMember, SysOperationControlVisibility(false)]

    public Id parmId(Id _id = id)

    {

        id = _id;

        return id;

    }

}


Now you want to write a logic to schedule a batch job to call the service class and pass the parameter.

you can write below code to achieve this.


            BatchHeader                         batchHeader;

            SysOperationServiceController       controller;

            GSPaymentSettlementContract     dataContract;

            str                                 captiontext;

            

            captiontext = "Procee the bi for " + <passing value>;

            batchHeader = BatchHeader::construct();

            batchHeader.parmCaption(captiontext);


            //create instances of the classes to use as batch tasks

            controller = new SysOperationServiceController( classStr(GSPaymentSettlementService),

                                                            methodStr(GSPaymentSettlementService, paymentSettlement),

                                                            SysOperationExecutionMode::Synchronous);


            controller.parmLoadFromSysLastValue(false);

            dataContract = controller.getDataContractObject('_contract');

            dataContract.parmId(<passing value>);

            batchHeader.addTask(controller);

            batchHeader.save();


// try this it comment me if it provide you a solution.

Friday, 18 September 2020

Find tax value from tax item code and tax group code

//You have to pass these values to the functions whether it comes from PurchLine or SalesLine or any other table.

//Store the result in variable

Tax::calcTaxAmount(purchLine.TaxGroup, purchLine.TaxItemGroup, Systemdateget(), purchLine.CurrencyCode, purchLine.LineAmount, TaxModuleType::Purch);

You have to pass these values to the functions, whether they come from SalesLine or PurchLine 

AX basic functions

 

1. Month Start Date : 
 
TransDate dateInMonth=today();  
         TransDate firstDateOfMonth;  
         firstDateOfMonth = DateStartMth(dateInMonth); 
2. Month End Date :

TransDate dateInMonth=today();  
         TransDate endDateOfMonth;  
         endDateOfMonth= endmth(dateInMonth);

3. Declare a constant :
#Define.MonthName("May")
 Const str monthName = "May";

4. Next month of date:
nextMth(date)
5. Date2Str function
        str        dateStr           = date2Str(this.DueMonthDate,           123, DateDay::Digits2,                                                        DateSeparator::Slash, DateMonth::Digits2,                                                                                   DateSeparator::Slash, DateYear::Digits4);
6. Num2Str function
1.should pass 4 parameters ex:
a = num2str(x,1,2,1,0);
rules:
1st place:1–>shows no effect(minimum no of characters to print)
2nd place:2–>ofter decimal /comma how many characters has to print
3rd place:1–>shows to select either comma or decimal
ex: 1 for point
2 for comma
0 for none


How to sort file data before inserting to target table in DMF in D365 FO

Problem: Many a times we receive requirements where we need to upload a file using DMF with a different order sequence. For example a file has data as below:


client wants that this file should get import with ID column in ascending /descending order.

Solution: To achieve this need to customize data entity as below:

1. Add a field integer field "ImportSequence" to staging table (GSCashStaging table).

2. Add below methods to staging table:

public static container orderByFieldListForImportExport(DMFOperationType _operationType = DMFOperationType::All)

{ container fieldList = conNull();
switch (_operationType)
    {
case DMFOperationType::Import, DMFOperationType::Export:
  fieldList += fieldStr(GSCashStaging, ImportSequence);
     break;

default:
    fieldList += fieldStr(Common, RecId);
    break;
    }

return [fieldList, sortOrder];

 

public static void resolveImportSequence(DMFDefinitionGroupExecution _dmfDefinitionGroup)
{
    GSCashStaging    staging;
    int   importSequence;

    ttsbegin;

    while select forupdate staging
order by staging.ID
  where staging.DefinitionGroup ==_dmfDefinitionGroup.DefinitionGroup     && stagingTable.ExecutionId == _dmfDefinitionGroup.ExecutionId      
  && stagingTable.TransferStatus == DMFTransferStatus::NotStarted                
{
    importSequence++;
    stagingTable.ImportSequence =importSequence;
}
       
    ttscommit;
3. Add below method to data entity
public static void postGetStagingData(DMFDefinitionGroupExecution _dmfDefinitionGroupExecution)
{
GSCashStaging::resolveImportSequence(_dmfDefinitionGroupExecution);
}

4. Rebuild your project and sync it. It will solve the issue.


D365FO Entity insert/update issue Update not allowed for field ‘Entity.FieldName’.

Step 1: Make sure fields properties allow edit is yes in Data entity level(In Table level Allow edit is No). Change to Yes in entity fields ...