In this article we will explain how to develop a new custom report from scratch in Dynamics 365 for Finance and Operations using Docentric.
Requirements for the new report
Let’s say that we want to develop a new report that will show the data from a selected sales agreement but instead of using the existing SSRS report for Sales agreement confirmation (AgreementConfirmation.Report), we will create a completely new one from scratch, which will look like a real-world agreement document. We will name this report as Sales agreement document.
The report data
Sales agreement document should contain the data from the source sales agreement’s header, a list of sold items but also a list of the customer’s contacts.
The report parameters
The report doesn’t have any visible parameters since it should always run in the context of a single sales agreement. Thus, the only parameter (which is hidden) is RecId of the currently selected sales agreement.
The report menu items
The requirements regarding printing the report: a user can preview the report by clicking a menu item placed directly on the Sales agreement form. Additional menu item that opens the Print destination settings form should also be introduced in order to enable emailing the report or sending it to a particular printer.
Read about advantages when developing custom reports in D365FO using Docentric >>
Which artifacts are we going to create and why
We are going to create the following artifacts:
- A new dummy SSRS report with the single Autodesign.
- A dummy DP (Data Provider) class, which is needed only for a dummy SSRS report to compile.
- A new Docentric template (aka design) that we will design in MS Word using DDSP (Docentric Data Source Package).
- A Docentric DSP (Data Source Provider) class that will contain complete business logic for fetching all the data needed for the report (i.e. all three data sets). Please note that we don’t need any temporary tables to create these data sets. Behind the scene is an XML based data source that allows as many as needed "data sets", i.e. collections, sub-collections, groups or hierarchies. Comparing to SSRS flat data sources, Docentric data sources are much more powerful.
The following artifacts plays the same role as for plain SSRS:
- A Data Contract class that will define and carry the values of the report parameters. We will have one hidden parameter: a sales agreement’s RecId.
- A Controller class that will handle the report dialog form, setting the SSRS report design and the value of the hidden parameter.
- A menu item that opens the report in the viewer.
- A menu item that opens the report dialog form.
- Security artifacts for these two menu items.
Why we need a dummy SSRS report and a dummy DP class when using Docentric?
Docentric sits on top of the SSRS framework and reuses SSRS’s artifacts for handling report parameters (Data Contract class), controlling report execution (Controller class) as well as it reuses SSRS’s menu items and security. Consequently, in order to be printed, each Docentric report has to override an existing SSRS report design.
This is why we need to create a dummy SSRS report design – to be able to override it with (one or multiple) Docentric designs (aka templates). We could also develop a fully functional DP class and three temporary tables for this report as we did in the previous article, but it simply doesn’t pay off. A much faster approach is to use a Docentric DSP class to create the report data source, which can be nicely shaped, and at the same time to avoid creating temporary tables completely. We still have to create a dummy DP class because otherwise our dummy SSRS report won’t compile.
Step 1: Create the Controller, Data Contract and Data Provider classes
Create the Controller, Data Contract and Data Provider classes. Go to Add > New Items > Dynamics 365 Items > Code > Class.
Create the following classes:
- DocAgreementDocumentController_WithDocentric > the same as in the previous article.
- DocAgreementDocumentContract_WithDocentric > the same as in the previous article.
- DocAgreementDocumentDP_WithDocentric > a dummy class, see below.
Dummy DP provider class
It is just a dummy class with the only purpose to make the dummy SSRS report, which we are going to create next, compile.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[SRSReportParameterAttribute(classStr(DocAgreementDocumentContract_WithDocentric))] class DocAgreementDocumentDP_WithDocentric extends SRSReportDataProviderBase { TmpRecId dummyTmp; // A dummy report temporary table that actually is not going to be used. // Still, it has to be declared because a dummy SSRS Report Design demands an existing data set. [ SRSReportDataSetAttribute('TmpRecId') ] public TmpRecId getTmpDummyTable() { select dummyTmp; return dummyTmp; } // This method should stay empty since there is no report temporary table to be filled. public void processReport() { } } |
Step 2: Create a dummy SSRS report design
To add a new SSRS report, go to Add > New Items > Dynamics 365 Items > Reports > Report.
Again, this SSRS report is just a dummy report, where we are not designing anything so we will use AutoDesign. Now add the dataset and map it to our dummy DP class DocAgreementDocumentDP_WithDocentric.
Step 3: Create a custom DSP class
In this step, we will create a custom Docentric DSP class in which we will implement the logic for fetching the data for our report. This class should extend the DocDataSourceProviderSrsReporting class and implement at least 2 methods: description() and generateXmlDataSource().
You can also use a VS template to create this class. Learn how >>
The class will look like this:
1 2 3 4 5 6 7 8 9 10 11 12 |
class DocAgreementDocumentDSP extends DocDataSourceProviderSrsReporting { public ClassDescription description() { return 'Sales agreement document DSP custom class'; } protected void generateXmlDataSource(DocXmlRecordBuilder _recordBuilder) { ... } } |
Note that in the generateXmlDataSource() method we operate with so-called Record Builder object that enable efficient adding of the needed data to a report data source. We can simply add any selected table buffer, e.g. salesAgreementHeader like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
salesAgreementHeader = SalesAgreementHeader::find(reportContract.parmSalesAgreementRecId()); agreementHeader = AgreementHeader::find(salesAgreementHeader.RecId); // Add the salesAgreementHeader record including all fields. _recordBuilder.addRecordWithAllFields(salesAgreementHeader); _recordBuilder.addRecordWithAllFields(agreementHeader); recordBuilder.goToParentRecord(); // Add some of the display methods. _recordBuilder.addDisplayMethod(tableMethodStr(SalesAgreementHeader, custName)); _recordBuilder.addCalculatedField('CustAddress', SalesAgreementHeader.custTable().address()); _recordBuilder.addCalculatedField('PaymentTerms', PaymTerm::find(agreementHeaderDefault.PaymentTerms).Description); |
We can also iterate through the sales agreement lines and add them to Record Builder using the same set of APIs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// Iterate through the sales agreement lines and add them to Record Builder. while select ItemId, InventDimId, RecId, Currency from agreementLine where agreementLine.Agreement == salesAgreementHeader.agreementHeaderDefault().agreementHeader().RecId { agreementLineQuantityCommitment = AgreementLineQuantityCommitment::find(agreementLine.RecId); _recordBuilder.addCalculatedRecord('AgreementLine'); _recordBuilder.addCalculatedField('ItemId', agreementLine.ItemId); _recordBuilder.addCalculatedField('ItemName', agreementLine.name()); ... } // Iterate through the customer contacts and add them to Record Builder. while select ContactForParty, Party from contactPerson where contactPerson.ContactForParty == salesAgreementHeader.custTable().Party join Party, Location from dirPartyLocation where dirPartyLocation.Party == contactPerson.Party join Location, Type, Locator from logisticsElectronicAddress where logisticsElectronicAddress.Location == dirPartyLocation.Location && logisticsElectronicAddress.Type == LogisticsElectronicAddressMethodType::Email { recordBuilder.addCalculatedRecord('CustomerContact'); _recordBuilder.addCalculatedField('ContactEmail', logisticsElectronicAddress.Locator); _recordBuilder.addCalculatedField('ContactName', contactPerson.personName()); } |
Learn more about Record Builder APIs >>
Step 4: Create the report menu items
Create two menu items as we did in our previous example and add them to the already created extension of the Sales agreement form. First of them (Preview document) will be used for opening the report on Screen and the second one (Print document) should open the report dialog form, where a user can select the target print destination.
Step 5: Add the dummy SSRS report to Docentric report setup
Add our newly created dummy SSRS report to Docentric report setup. Go to Organization administration > Docentric AX > Reports.
Now set DocAgreementDocumentDSP as Datasource provider class.
We cannot add any template yet; we first have to create one. But before that, we need to generate DDSP (Docentric Data Source Package) first.
Step 6: Generate DDSP
You can generate DDSP (Docentric Data Source Package) in two ways. You can turn on the Generate DDSP when report run option on the Settings > Data source > Generation options form. This way each time when the report runs, DDSP will be generated as well. This approach might come handy for Print management reports, where no report dialog form is open.
The second way is to print the report to a special print destination: Generate DS. In order to select it, click the Print document menu item on the Sales agreement form, which we created in Step 4.
When the report is executed, the DDSP file is downloaded in the browser.
Step 7: Design the Docentric template
Let’s assume that we got a regular Word document from our sales department, which represents a typical Sales agreement document used in our company. We will turn it into a working Docentric template by clicking the Use As Template button in the Docentric AX ribbon, which you will see once you install Docentric Designer.
After we click the Use As Template button, we are prompted to select DDSP. When we do this, all other buttons will become enabled. We can now design the document by replacing those document parts which should be dynamic with Docentric tagging elements such as Field (for simple values such as text, numbers and dates) or List (for tables/collections).
Learn how to use Docentric Designer >>
Download the sample Sales agreement >>
Download the finished Docentric template >>
Step 8: Add Docentric template as AOT Resource
This step is mandatory only if you want to keep your templates in AOT, when they will become so-called System templates. In production, you can skip this step and upload the template in Docentric report setup directly.
Learn more about template storage >>
Let’s say that we want to store out template in AOT; we need to create a new Resource first. Go to Add > New Items > Dynamics 365 Items > Labels and Resources > Resource. When adding a new Resource, you will be prompted to select the corresponding file. Select the above-created Docentric template, which is just a regular Word document with special tags.
Step 9: Add Docentric template to Docentric report setup
There are two options for adding a Docentric template to Docentric report setup:
- Use the Template file > Attach option.
- Use the Reload system templates option – only works for System templates.
Step 10: Run the report
You can now run the report to Screen or any other print destination. The final result is shown below.
Note that if you change the design of your template and upload the new version to Docentric report setup via Template file > Attach, you will see the effects of the changes immediately.
Conclusion
When developing a new custom report from scratch, using Docentric has many advantages over using plain SSRS:
- Design process is faster and simpler – business documents are best designed in MS Word.
- With Docentric Designer we can use advanced formatting, styles, headers, footers, page breaks, etc. In fact, we can use any fancy feature that MS Word offers.
- End-users can change or add additional designs (aka templates) for the same SSRS report, also in production. If multiple templates are provided for the same report, a user get the chance to choose among them before the report is printed.
- End-users can also print reports in MS Word and change something before using it. This can be convenient for agreements, contracts or quotes.
- Development aspect: Much faster, because we can include multiple datasets including hierarchies to a report data source without introducing temporary tables. Also, we can start from a static Word document and turn it into a working Docentric template in just couple of minutes.
- Maintenance aspect: Much faster, especially when we want to add additional fields or even a dataset to a report data source, or just to change the report design. Deploy is not needed if we only change the design.
Is this possible to use the custom reports in Docentric free edition for D365FO?
I’m sorry to say but it’s not possible, because you would need Docentric designer to design such a custom report. Basically, Free Edition is more focused on print destination improvements, while Full Edition is about report design. Please see Full vs. Free Feature List for more details.
Kind regards,
Ana
Thanks for your response. Is this possible to preview the custom report using the Docentric in the free edition?
Yes, it is! You can also use Print management preview, which will become part of Free Edition in the next version release 3.3.9 – it’s coming out in 2 weeks.
Kind regards,
Ana
Hi, After done all the above steps, still my report does not shows the docentric design, its still showing the ssrs dummy design only. could you please help on this.?
Hi Vigneshvaran,
Please check if you’ve added this report to Docentric report setup. Anyway, if you don’t solve this problem, please reach out to our Support at support@docentric.com.
Kind regards,
Ana