[D365] How to add a custom report type to form letter print management setup

The docs for D365 F&O describe the process of adding a custom report design to the form letter print management setup very well.

But do you know how to introduce a completely new print document type and add an entry to the form letter setup of a module?

Create the enum value for your new type

The first step is to extend the Base Enum PrintMgmtDocumentType to be able to reference your new type and build on that.
Search for the enum at the AOT, right-click it and select Create extension.

Create extension of enum PrintMgmtDocumentType

In your new extension, add a new enum value, name it and give it a proper label.

Add new enum value

Extend the node for your document type

There are already so called node-classes for various standard types and you just need to find the right one for your target module. In this example: purchase.

Available print mgmt nodes

Create an extension of your node class ( PrintMgmtNode_Purch in this example) and add a Chain of Commands method for getDocumentTypes that adds your new type to the result list:

[ExtensionOf(classStr(PrintMgmtNode_Purch))]
public final class PrintMgmtNode_Purch_myproject_Extension
{
    /// 
    /// Gets a list of valid document types for the node.
    /// 
    /// 
    ///    A list of valid document types for the node.
    /// 
    /// 
    /// The results can vary based on what is configured in the application because configuration keys are
    ///    used to determine this list.
    /// 
    public List getDocumentTypes()
    {
        List ret = next getDocumentTypes();

        ret.addEnd(PrintMgmtDocumentType::customPurchPromptLetter);

        return ret;
    }

}

At this point you should see your new document type in the form letter print setup form of the module you chose:

new document type in form letter

Create a FormLetter class for your type

Create a new FormLetter class for your document type to return the hierarchy and the document type. The interesting part here is the attribute PrintMgmtDocumentTypeFactoryAttribute. Go with the minimum implementation like shown below:

[PrintMgmtDocumentTypeFactoryAttribute(PrintMgmtDocumentType::customPurchPromptLetter)]
public class customPurchFormLetterReport_PromptLetter extends PurchFormLetterReport
{
    /// 
    /// Returns the default printer settings for the specified PrintSetupOriginalCopy enumeration value.
    /// 
    /// 
    /// The PrintSetupOriginalCopy enumeration value that specifies whether the Original
    /// or Copy destinations should be retrieved.
    /// 
    /// 
    /// The default printer settings for the specified PrintSetupOriginalCopy enumeration value.
    /// 
    /// 
    /// The general pattern for implementing this method is to use the printer destinations from the appropriate
    /// FormLetter class.  These printer destinations will be used if no Print Management destinations are
    /// found or used.
    /// 
    protected container getDefaultPrintJobSettings(PrintSetupOriginalCopy _printCopyOriginal)
    {
        if (_printCopyOriginal == PrintSetupOriginalCopy::Original)
        {
            return PurchFormLetter::getPrinterSettingsFormletter(DocumentStatus::None,PrintSetupOriginalCopy::Original);
        }
        else
        {
            return PurchFormLetter::getPrinterSettingsFormletter(DocumentStatus::None,PrintSetupOriginalCopy::Copy);
        }
    }
    
    /// 
    /// Returns the PrintMgmtDocumentType enumeration value that specifies what document this FormLetterReport class controls.
    /// 
    /// 
    /// The PrintMgmtDocumentType enumeration value that specifies what document this FormLetterReport class controls.
    /// 
    /// 
    /// This value is used to retrieve the appropriate Print Management settings for the report.
    /// 
    public PrintMgmtDocumentType getPrintMgmtDocumentType()
    {
        return PrintMgmtDocumentType::customPurchPromptLetter;
    }

    /// 
    /// Returns the PrintMgmtHierarchyType enumeration value that specifies what hierarchy this FormLetterReport class uses.
    /// 
    /// 
    /// The PrintMgmtHierarchyType enumeration value that specifies what hierarchy this FormLetterReport class uses.
    /// 
    /// 
    /// This value is used to retrieve the appropriate Print Management settings for the report.
    /// 
    protected PrintMgmtHierarchyType getPrintMgmtHierarchyType()
    {
        return PrintMgmtHierarchyType::Purch;
    }

    /// 
    /// Returns the PrintMgmtNodeType enumeration value that specifies what node this FormLetterReport class uses.
    /// 
    /// 
    /// The PrintMgmtNodeType enumeration value that specifies what node this FormLetterReport class uses.
    /// 
    /// 
    /// This value is used to retrieve the appropriate Print Management settings for the report.
    /// 
    protected PrintMgmtNodeType getPrintMgmtNodeType()
    {
        return PrintMgmtNodeType::PurchTable;
    }
}

As last step, extend the populator class

The class PrintMgmtReportFormatPopulatorAppSuite populates all the report layouts. Simply extend it and add a CoC method on addDocuments like the standard already does in the class PrintMgmtReportFormatPopulatorAppSuite_Extension (have a look as template):

/// 
/// Populates the PrintMgmtReportFormat table used for print management with the MyProject documents.
/// 
[ExtensionOf(classStr(PrintMgmtReportFormatPopulator))]
public final class PrintMgmtReportFormatPopulatorAppSuite_custom_Extension
{
    #ISOCountryRegionCodes
    #PrintMgmtSetup

    protected void addDocuments()
    {
        // Purchasing documents
        this.customAddPurchaseDocuments();

        next addDocuments();
    }

    /// 
    /// Adds purchase records to the PrintMgmtReportFormat table.
    /// 
    protected void customAddPurchaseDocuments()
    {
        this.addOther(PrintMgmtDocumentType::customPurchPromptLetter, ssrsReportStr(customPurchPromptLetterReport, Report), ssrsReportStr(customPurchPromptLetterReport, Report), #NoCountryRegionId);
    }

}

But how to ...

Associate your new type with a default report design

You can create a new setup under the new node but it won't find any report designs to choose from in the dropdown field.

This part is exactly like in the standard documentation to add your custom report designs to standard reports.
Create a new class and implement a subscriber to the delegate PrintMgmtDocType.getDefaultReportFormatDelegate:

class mycustPrintMgtDocTypeHandlerExt
{
    [SubscribesTo(classStr(PrintMgmtDocType), delegateStr(PrintMgmtDocType, getDefaultReportFormatDelegate))]
    public static void getDefaultReportFormatDelegate(PrintMgmtDocumentType _docType, EventHandlerResult _result)
    {
        switch(_docType)
        {
            case PrintMgmtDocumentType::customPurchPromptLetter:
                _result.result(ssrsReportStr(customPurchPromptLetterReport, Report));
                break;
        }
    }

}

Of course this requires you to build this report upfront.

Setup the design for the new type

You only need to navigate to the print management setup of your module again, right-click the new document type, choose New and select your report design from the Report format dropdown on the right.

Selection of design