Search This Blog

Tuesday, 17 March 2020

Adding Subject and Body to the report send in an email by using the Print Management in D365 for Finance and Ops

As you already know there are standard AX Documents that you can print or send in an email using print management destination settings.

By using the below configuration in print management settings.



























But the problem is once you receive the document in an email that was sent through print management. It does not contain any user-friendly subject or body of the email.

Like this:










There was the requirement to include the Subject and Body to the email that is sent through print management.

For this what we did we created a parameter where we set up the email template and inside that email template, we specified the subject and email body.














below is the code snippet that we have used:

/// <summary>
/// Extension for class <c>PrintMgmtReportRun</c>
/// </summary>
[Extensionof(classstr(PrintMgmtReportRun))]
final class FBHPrintMgmtReportRun_Extension
{
    /// <summary>
    /// COC for SettingDetail method
    /// </summary>
    /// <returns></returns>
    public PrintMgmtPrintSettingDetail settingDetail()
    {
        PrintMgmtPrintSettingDetail     currentSettingDetail;
        currentSettingDetail = next settingDetail();

        if (this.parmDocType() == PrintMgmtDocumentType::VendPaymAdvice
            || this.parmDocType() == PrintMgmtDocumentType::CustPaymAdvice)
        {
            SRSPrintDestinationSettings printDestinationSettings;
            printDestinationSettings = currentSettingDetail.parmPrintJobSettings();

            if (printDestinationSettings.printMediumType() == SRSPrintMediumType::Email)
            {
                SysEmailId              sysEmailId;
                SysEmailTable           emailTable;
                SysEmailMessageTable    emailMessageTable;
                FBHVendParametersExt        vendParameters;
                FBHCustParametersExt        custParameters;

                if (this.parmDocType() == PrintMgmtDocumentType::VendPaymAdvice)
                {
                    select firstonly PaymAdviceEmailTemplateId from vendParameters;
                    sysEmailId        = vendParameters.PaymAdviceEmailTemplateId;
                }
                else
                {
                    select firstonly PaymAdviceEmailTemplateId from custParameters;
                    sysEmailId        = custParameters.PaymAdviceEmailTemplateId;
                }

                emailTable        = SysEmailTable::find(sysEmailId);
                emailMessageTable = SysEmailMessageTable::find(sysEmailId, emailTable.DefaultLanguage);

                printDestinationSettings.emailSubject(emailMessageTable.Subject);
                printDestinationSettings.fbhEmailBody(emailMessageTable.Mail);
            }
        }
       
        return currentSettingDetail;
    }


}

now after doing the above change when you try to receive the report in an email that was sent through print management then you will receive the like this which contains the subject and body as well that you have set up in email template.



Monday, 10 February 2020

Queries on Valid Date Time State Tables

Some tables in Ops have valid time state enable like the below example on hcmemployment table:










in order to find a valid record in this kind of table, a simple select statement is not what you have to use.

you have to provide the date range "from" and "to" to see is the record is exists in these date ranges or not.if it exists then its a valid record and if it does not exist then it's not a valid record irrespective of either record exists with other date ranges or not.

For more details, you can check the hcmworker.isEmployee method.

Thanks,
Zahid


Tuesday, 6 August 2019

Installing printer on One Box Dev in D365 for Ops


Installing Network Printer on One Box Environment.

Below are the steps to install network printer on your machine if you want to print document or SSRS report directly to the Printer.

Navigate to Organisation Administration -> Setup -> Network Printers













Download this software and then install it.

After the installation open your document routing agent.

Go to the settings and then set the Azure AD Tenant, your Dev Box URL in Dynamics 365 URL textbox and check the the checkbox enable logging view in application and then press ok
















After that go to the printer tab and select the Printer which you want to use to Print your documents.

Note: Sometime your desire printer won't appear in the list of printers that are showing. In that case you need to install that specific printer first by going to the Control Panel and Printer and settings.

































Here in above image you can see that many Printers are appearing and I have selected one on which I have to do the testing. You can select multiple printers as well.

Once you select the printer and press the register button then that specific printer will appear in the list of registered printers on the following navigation.

Organisation Administration -> Setup -> Network Printers


















Now I will show you while printing the SSRS report when I select the Print destination Printer instead of the screen then the above printer will appear on the available list of printers.







































For more details below is the link from Microsoft:


Monday, 5 August 2019

An error occurred rendering the report. Accessing the report server URL caused an error. The remote server returned an error: (500) Internal Server Error.


We have to customize the transfer order shipment report in Microsoft Dynamics D365 for Operations and while running the report if we sent the report directly to the printer instead of printing on the screen we were getting the following errors.


" An error occurred rendering the report. Accessing the report server URL caused an error. The remote server returned an error: (500) Internal Server Error."





















In the initial investigation I thought there is some issues on the printer cause the report was working fine when I set the printer destination on screen.

But after some research I found below link where its mentioned to check the SSRS logs.


Below is the link where can see the details of how to investigate the SSRS logs.



On the above link I found the navigation to open the SSRS logs.













I tried to open the latest log file in note pad and try to found the text with keyword "error" and found out below.






The Problem was I have created parameter name "inventTransferId" in my contract class and I set it to hide on report level but the problem was its value was not initialised when I was trying to send the Report Directly to Printer.


When I set the following property of the of the parameter then my report was working fine.




Thursday, 2 May 2019

Monday, 4 February 2019

D365 for Finance and Ops X++ Job to Get the Primary Position Title of Employee by Passing Worker Recid

Below is the code snippet to get the Primary Position Title of the employee by passing the worker recid.


private HcmTitleId getPositionTitle(HcmWorkerRecId hcmWorkerRecid)
    {
        HcmWorker                   hcmWorker;
        HcmPositionWorkerAssignment hcmPositionWorkerAssignment;
        HcmPosition                 hcmPosition;
        HcmPositionDetail           hcmPositionDetail;
        HcmTitle                    hcmTitle;

        hcmPositionWorkerAssignment = HcmWorkerHelper::getWorkerPrimaryPositionAssignment(hcmWorkerRecid);
       
        select TitleId from hcmTitle
            join hcmPositionDetail
        where hcmPositionDetail.Title == hcmTitle.RecId
            join hcmPosition
            where hcmPosition.RecId == hcmPositionWorkerAssignment.Position;
       
        return hcmTitle.TitleId;
    }

Note that HcmPositionWorkerAssignment is a validTimeState table. The above query will only retrieve position assignment that is currently active. 
This posting is provided "AS IS" with no warranties, and confers no rights.

Thanks,
Zahid

Wednesday, 7 November 2018

Purchase Order Confirmation Report in Dynamics D365 for Finance and Operations

There are three types of Purchase Order Reports you can generate from Ops.

1. Purchase Order Confirmation.

2. Purchase Order Invoice.

3. Purchase Order Product Receipt.

In this Post, I will talk about only Purchase Order Confirmation Report and this post is basically related to the Configuration that we can enable and disable in the Purchase Order Confirmation Report.

First of all, I will show how to generate the Purchase Order Confirmation Report.

Below are the steps to generate the Purchase Order Confirmation Report.

Go to Accounts Payable -> Purchase Order -> all Purchase Orders.











Select the Purchase Order that is already Approved and then select Confirm button under Purchase Tab in the action section.














Once the Purchase Order is confirmed then its status will be changed to "confirmed" and the "Purhchase order confirmation"  button will be enabled under Journals section in Purchase Tab










Once you click that button a new form will open which contains the versions of this Purchase Order.















Click the Preview/Print button and select the option you want to print the report. if you want to print copy than select copy preview. if you want to print original then select original preview or if you want to use print management settings then use the select the Print Management.

I select the Orginal Preview.

Now Below is the output of the report.



























Now the above steps were related to generating the Purchase Order Confirmation Report.
There are some areas that I have highlighted in the above image. Values of these fields you can change at any time without the customization.

As you can see point 1 in the highlighted area is related to the Company Address, Telephone, Fax, Giro, Tax Registration Number.

These bits you can configure and change at any time. Below are the navigation and screenshot of the form where u can configure company address, telephone, fax etc.

Go to Organisation Adinistration -> Organisation -> Legal Entities

Select the record which is in your log in a company. In my case, it's in usmf.












as you can see in the above image I have highlighted the Address and Contact Information tabs.

In these tabs, you can configure the addresses and contact info. you can add multiple records as well but the records which are set to primary will appear on the PO Confirmation Report.

Now the second thing that I have mentioned in the report are the external header and line level notes that you can set up in Purchase Order Report.

First I will show how you can create header and line level external notes.

Open your Purchase Order Form like the one below:









Now click on the Purchase Order Header Button as highlighted above. Its color will change to blue as you can see in the above image after that click on the attachment button this is also highlighted in the above image.












Now as you can see once you click on the attachment a new screen is open where u can setup notes.

Just create the notes of type "Note" and then set the note text under notes section and set the Restriction to "External".

Note: if you set the restriction to internal than notes will be printed on PO Confirmation Report as internal notes are for internal use only. They are not for reports.

After that close that form and go back to the Purchase Order and then click on the lines and then click the attachment button.

The same new form will be open where you have to set up the External notes for lines.










As you can see in above image create the notes of type "Notes" and set the notes for line level external notes and then set the restriction to external.

Again just mentioning only external notes will appear on the report if the restriction is internal then notes will not appear on the report.

This was all for setting up the external notes. Now I will show you how you can set the configuration to show and hide these notes on PO Confirmation Report.

Just go to the Procurement and sourcing -> Setup -> Forms -> Form Setup












The two drop downs I have highlighted in the above image. First one is related to select to show either header level external notes or line level external notes or both or none of them.

The second drop down is related to the which type of Note you want to show. By default the notes type is Note.

Now the point number three that I have mentioned in the report is the external item number. That you can also show and hide.

On Purchase Order Line Details under the general tab, you can set up your external items number. Mentioned below for reference.












To show and hide this external item number on the report below is the navigation to the configuration form.

Just go to the Procurement and sourcing -> Setup -> Forms -> Forms Stup

 The drop i.e ITEM NUMBER that I have mentioned in the above image.if you set this to both than external item number will be visible on the PO Confirmation Report.

Now the fourth and the last thing that I have highlighted in the PO Confirmation Report is the Form Notes.

You can set up these form notes on the following navigation.

Procurement and Sourcing -> Setup -> Forms -> Form Notes

Select Purchase Order and then specify the notes.













if you don't specify any text on the form notes then nothing will be displayed on the purchase order confirmation report.

This was all related to the PO Confirmation Report. Feel free to Comment if you have any questions.

Thanks,
Zahid

Friday, 20 July 2018

Deleting Usage Data in D365 For Finance and Operations

Select the Settings button on the top right corner of your screen and then select user options like this.










A new screen will open where select the usage data like this.












A new form will open where u can see the usage data in different types and areas. you can delete all usage data or specific usage data as well.

In my case, I have selected form selection and deleted the usage data related to the forms.









Now I will select the record from the form selection tab and click delete and then the framework will delete the usage data related to that specific form.

Note as mentioned earlier we can delete all usage or usage data specific to particular forms or area as well.












That's all feel free to comment if you have any questions.

Thanks,
Zahid

Tuesday, 10 July 2018

what should be the best DataSource type on Data Entity in Dynamics D365 for Operations

Below is the link that contains the discussion on which type of DataSource on DataEntity is good in which scenario:

Feel free to post if you guys have any questions.

https://community.dynamics.com/365/financeandoperations/f/765/p/286025/822134#822134

Thanks,
Zahid


Friday, 1 June 2018

Get Financial Dimension using default dimension through x++ code and Sql in Dynamics AX #D365forOps


Below is the X++ code snippet for getting the Financial Dimensions using Default Dimension by using X++ code:

private str getFinancialDimensionName(Name _dimAttrName, DimensionDefault _defaultDimension)
    {
        DimensionAttribute dimAttr;
        DimensionAttributeValueSetStorage dimStorage;
        DimensionAttributeValue     dimAttrValue;
        Common                      common;
        DictTable                   dictTable;

        select firstOnly dimAttr where dimAttr.Name == _dimAttrName;
        if(dimAttr)
        {
            dimStorage = DimensionAttributeValueSetStorage::find(_defaultDimension);

            select firstonly dimAttrValue
            where dimAttrValue.RecId == dimStorage.getValueByDimensionAttribute(dimAttr.recID)
            join dimAttr
            where dimAttr.RecId == dimAttrValue.DimensionAttribute;

            if (dimAttrValue)
            {
                dictTable = new DictTable(dimAttr.BackingEntityType);
                common = dictTable.makeRecord();

                if (common.TableId)
                {
                    select common where common.(dimAttr.KeyAttribute) == dimAttrValue.EntityInstance;
                    return common.(dimAttr.NameAttribute);
                }
            }
        }

        return "";
}

Where _dimAttrName = name of the dimension attribute like Department, Location etc

and _defaultDimension = value of the defaultDimension like value in DefaultDimension field of table HcmEmployment.

Below is the code snippet to get the department and location in Sql using default dimension.

select dimensionFinancialTag.description from  DefaultDimensionView
join dimensionFinancialTag on dimensionFinancialTag.VALUE = DefaultDimensionView.DISPLAYVALUE
    where DefaultDimensionView.DefaultDimension = 5637144783
      and DefaultDimensionView.Name = 'Location' 


select DisplayValue, dimAttributeOMDepartment.NAME from defaultDimensionView
 join dimAttributeOMDepartment
            on dimAttributeOMDepartment.Value = defaultDimensionView.DisplayValue
        where defaultDimensionView.DefaultDimension = 5637144783

            and defaultDimensionView.name = 'Department'

For Any Question feel free to Comment.

Thanks,
Zahid

Thursday, 10 May 2018

Renaming Database Name using Query in SQL Server

Sometimes if we try to rename the database in our development or any other environment we got the error message that this database is in use by other process and we cant rename it.

So first we need to check if any user is not using that database and try to rename it. If still we got the same error then might be some services using that database.

Instead of investing time to investigate which service is causing the issue to rename the database you can simply write the below query to rename your database.

ALTER DATABASE oldatabasename SET SINGLE_USER WITH ROLLBACK IMMEDIATE;

ALTER DATABASE olddatabasename MODIFY NAME = newdatabasename

ALTER DATABASE newdatabasename SET MULTI_USER WITH ROLLBACK IMMEDIATE;


Thanks,
Zahid

Monday, 30 April 2018

Virtual Fields in Data Entity in Microsoft Dynamics 365 For Operations

Some times we need to populate fields on Data Entity based on some calculated X++ logic instead of binding them directly from table.

To do this below are the some simple steps.

1. right click your fields node of your data entity and than select the string Unmapped field.














note: you can select other type of umapped field if your field is not string.

2. After that go to the properties of that field set the name , label , extended data type and is computed field to no.

























After that right click your data entity and than override the postLoad() method.

and in that postload method you can write your X++ logic to populate that field.













Now after that once you rebuild your code and try to export data entity you will see this field will be populated in data entity.

Note: Data entities are saved as view on back end in sql and the main drawback of using virtual field is that you can see them in sql.You can only see when you use that entity with in Dynamics Domain.

Thanks,
Zahid


Friday, 1 December 2017

Getting Dimension Values from Financial Dimensions in Dynamics 365 For Operations

I got one tasks of report development in which I have to show the Financal Dimension and its Dimension Value in a lookup on report parameter.

To do this the one I have to grab all the Dimension Values against the Financial Dimension to show in a lookup.

Below is the navigation for Financial Dimension Form in D365:

General Ledger -> Chart of Accounts -> Dimension -> Financial Dimensions.


















The form for Financial Dimension is.











As you can see in the above image there is a dimension value button when you click on it a new form will open containing all of the dimensions against that selected Financial Dimension.














So the question is how can we get the Dimension Values based Financial Dimension by using query.

Below is the code for you:

class RunnableClass1
{       
    /// <summary>
    /// Runs the class with the specified arguments.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>
    public static void main(Args _args)
    {   
        DimensionAttribute              dimAttr;
        DimensionAttributeViewContract  dimAttrViewContract;
        Query                           q;
        QueryRun                        qR;
        QueryBuildDataSource            qbds;
        Common                          common;

        dimAttr = DimensionAttribute::findByName("Department");


        dimAttrViewContract =  DimensionAttribute::getViewContract(dimAttr.RecId);

        q = new Query();

        changecompany (dimAttr.company())
        {
            qbds = q.addDataSource(dimAttrViewContract.parmViewId());
            qbds.addSortField(dimAttrViewContract.parmValueFieldId(),SortOrder::Ascending);

            // Apply ranges on language ID fields.
            DimensionAttribute::addTranslViewRangesToBackingEntityQuery(dimAttr.RecId, qbds);

            if (DimensionCache::instance().dimensionAttributeHasCategorization(dimAttr.RecId))
            {
                if (dimAttr.Type == DimensionAttributeType::MainAccount)
                {
                    qbds.addRange(dimAttrViewContract.parmCategoryFieldId()).value(queryValue(LedgerChartOfAccounts::current()));
                }
                else if (dimAttr.Type == DimensionAttributeType::CustomList)
                {
                    qbds = qbds.addDataSource(tablenum(DimensionAttributeDirCategory), 'DimAttDirCat');
                    qbds.relations(true);
                    qbds.joinMode(JoinMode::InnerJoin);
                    qbds.fetchMode(QueryFetchMode::One2One);
                    qbds.addLink(dimAttrViewContract.parmCategoryFieldId(), fieldnum(DimensionAttributeDirCategory, DirCategory));
                    qbds.addRange(fieldnum(DimensionAttributeDirCategory, DimensionAttribute)).value(strfmt('%1', dimAttr.RecId));
                }
            }
        }

        qR = new QueryRun(q);
        while(qR.next())
        {
            common = qR.get(dimAttrViewContract.parmViewId());

            info(strFmt("%1 %2",common.getFieldValue(dimAttrViewContract.parmValueFieldName()), common.getFieldValue(dimAttrViewContract.parmNameFieldName())));
        }
    }

}

For more Details Below is the link:

https://community.dynamics.com/ax/b/hellodax/archive/2015/07/07/get-all-financial-dimension-value-and-description-from-dimensionattribute

Thanks,
Zahid

Thursday, 30 November 2017

Open Table Browser in other than Dat Company in Dynamics 365 for Operations

Some time we want to open the table browser in other than DAT company in Dynamics 365 for operations.

To open table browser in other company below is the link that contains the full description:

https://community.dynamics.com/crm/b/microsoftdynamicscrmsolutions/archive/2016/01/25/open-table-browser-with-different-legal-entity-in-ax-7


Thanks,
Zahid. 

Wednesday, 27 September 2017

Resolved: The field with ID '21' does not exist in table 'smmContactPersonEntityCopy'.

One day one of my Integration Teams was trying to insert records from CRM to Dynamics 365 for Operations using the integration tool i,e Logic apps.

There logic app was configured correctly and they were successfully able to fetch the records from CRM but when they were trying to insert the records in D365 for operations they were getting the following error:

 "An error has occurred.  Error executing code: The field with ID '21' does not exist in table 'smmContactPersonEntityCopy'.\r\nclientRequestId: 4f0ca82f-ff64-46a9-9066-ff62cea0b036" 

I investigated the issue in D365 for operations.Actually they copied the standard AX entity i,e ContactPersonEntity to create the new one smmContactPersonEntityCopy.

I created the job with in D365 for operations to insert the records into the same entity.















After running the above job I was also getting the same error that I have stated above.After some  debugging I found out that the error was on the init value method of my entity i.e

smmContactPersonEntityCopy.initValue();

 When I looked into that method and found out that it was throwing exception on number sequence generation.








After some analysis I found out that the other developer has copy the standard AX entity i.e smmContactPersonEntity and created new Entity with ame smmContactPersonEntityCopy and he forgot to update the refrences in code.

So as you can see in the above image Its smmContactPersonEntity I have change this to smmContactPersonEntityCopy and after that I rebuild the project and I run my job which was successfully able to insert the records in that entity and my logic app was also working fine.

Below is the updated code:





Thanks
Zahid.

Wednesday, 24 May 2017

Development Approach in Dynamics 365 For Operations

The are two ways of development approach in D365 one is Extension Development Approach and Overlayering development approch.

  1. Extension Development Approach.
  2. Overlayerring Development Approach.

Extension Development Approach:

This Approach is use if you want to create new objects or you don’t want to customize the existing standard AX functionality given by Microsoft.

In extension development approach you can enable or disable the controls of standard ax objects and you can do what you want with the new objects that you have created.

Benefit of using the Extension Development approach is  that It would be easier for you to do the future upgrades but sometimes we might need to customize the existing standard AX object based on our requirement. in this  case we use Over layering development Approach.

To do the extension development you first need to create the model and under that model add new objects or refer to the existing objects to enable and disable some of their controls.

Below are the steps for working in extension development approach.

Open Visual Studio Click Dynamics 365 -> model management ->  Create Model










A new wizard will open where you give name and other details of the model.



















Now click next.



















In the above screen you have the option to use the extension development approach or the over layering development approach.

If you choose the 'Create new package' option than it will be the extension development approach.

And if you choose the 'Select existing package' than you have to select the existing model which you will be customizing that would be the over layering development approach.

If you select 'Create new Package' and then click next than you have the option to select the existing package if you want to use objects of that model. (note: you can only enable or disable control of existing AX objects but you cannot customize it)
Like this.



















When you click next final screen will appear where you can check the checkbox Create new project so once you click next a new dialog will appear when u can create new project or u can uncheck the checkbox model will created and then you can create the project manually.










After creating the model In the above image I right click the standard AX form i.e cust table.

Now I have the option of either customize it or create extension. As you can see on the right pane I have use this form as customize and extension both (just for example).

It is because my module is over layering development approach. If my module would be total new I,e extension development approach then I won't be able to customize that form I extend that form.

Now I will show you the properties of the form that I have customize in which I have full authority to change any property.









and below is the properties of the same form which I extended.in which I can change only some properties not all of them.









Feel free to comment if you have any questions.

Thanks,
Muhammad Zahid.