Skip to content

Event Request: handle report RunModal in codeunit "Document-Print" for inventory documents #29564

@rmurriero-alterna

Description

@rmurriero-alterna

Hi, we need to add events during the printing of inventory documents present in codeunit 229 "Document-Print" and replace the standard Report.RunModal instruction with custom logic.

The public procedures are the following:
procedure PrintInvtOrderTest(PhysInvtOrderHeader: Record "Phys. Invt. Order Header"; ShowRequestForm: Boolean)
procedure PrintInvtOrder(PhysInvtOrderHeader: Record "Phys. Invt. Order Header"; ShowRequestForm: Boolean)
procedure PrintPostedInvtOrder(PstdPhysInvtOrderHdr: Record "Pstd. Phys. Invt. Order Hdr"; ShowRequestForm: Boolean)
procedure PrintInvtRecording(PhysInvtRecordHeader: Record "Phys. Invt. Record Header"; ShowRequestForm: Boolean)
procedure PrintPostedInvtRecording(PstdPhysInvtRecordHdr: Record "Pstd. Phys. Invt. Record Hdr"; ShowRequestForm: Boolean)
procedure PrintInvtDocument(var NewInvtDocHeader: Record "Invt. Document Header"; ShowRequestPage: Boolean)
procedure PrintInvtReceipt(NewInvtReceiptHeader: Record "Invt. Receipt Header"; ShowRequestPage: Boolean)
procedure PrintInvtShipment(NewInvtShipmentHeader: Record "Invt. Shipment Header"; ShowRequestPage: Boolean)
procedure PrintDirectTransfer(NewDirectTransHeader: Record "Direct Trans. Header"; ShowRequestPage: Boolean)

The implementation of all the above functions follows the rule of filtering the record to print, filtering the ReportSelection record, and executing the RunModal for the selected reports.

We need to parameterize the print function in a single method similar to the one in the "Report Selections" codeunit, and modify the existing implementations to call the new method, including an event to override the RunModal with custom logic.

procedure PrintInvtShipment(NewInvtShipmentHeader: Record "Invt. Shipment Header"; ShowRequestPage: Boolean)
var
    ReportSelections: Record "Report Selections";
    InvtShipmentHeader: Record "Invt. Shipment Header";
begin
    InvtShipmentHeader.Copy(NewInvtShipmentHeader);
    InvtShipmentHeader.SetRecFilter();

    // old code -->
    ReportSelections.SetRange(Usage, ReportSelections.Usage::"P.Inventory Shipment");
    ReportSelections.SetFilter("Report ID", '<>0');
    if ReportSelections.FindSet() then
        repeat
            REPORT.RunModal(ReportSelections."Report ID", ShowRequestPage, false, InvtShipmentHeader);
        until ReportSelections.Next() = 0;
    // <-- old code

    // new code -->
    PrintDocumentWithReportUsage(InvtShipmentHeader, Enum::"Report Selection Usage"::"P.Inventory Shipment", ShowRequestPage);
    // <-- new code
end;

// new code -->
local procedure PrintDocumentWithReportUsage(DocumentVariant: Variant; ReportUsage: Enum "Report Selection Usage"; ShowRequestPage: Boolean)
var
    ReportSelections: Record "Report Selections";
    IsHandled: Boolean;
begin
    ReportSelections.SetRange(Usage, ReportUsage);
    ReportSelections.SetFilter("Report ID", '<>0');
    if ReportSelections.FindSet() then
        repeat
            IsHandled := false;
            OnBeforePrintDocumentWithReportSelections(ReportSelections, DocumentVariant, ShowRequestPage, IsHandled);
            if not IsHandled then
                Report.RunModal(ReportSelections."Report ID", ShowRequestPage, false, DocumentVariant);
        until ReportSelections.Next() = 0;
end;

[IntegrationEvent(false, false)]
local procedure OnBeforePrintDocumentWithReportSelections(ReportSelections: Record "Report Selections"; DocumentVariant: Variant; ShowRequestPage: Boolean; var IsHandled: Boolean)
begin
end;
// <-- new code

Alternatives Evaluated

The entire printing procedure for the aforementioned documents does not present any events that can be subscribed to as an alternative, therefore the creation of new ones is required.

Justification for IsHandled

We've developed an extension that allows you to set the structure of the data to be exported when printing a document via setup. To do this, rather than creating multiple Report objects via AL code, the app allows you to set up a "template" with the data to be exported: to be able to print with our app, the "Report Selections" record always specifies a fixed ID corresponding to our report that processes all printouts as the Report ID, and a custom "Template Code" field specifies the code corresponding to the setup of the data to be exported. To print with our report, the app doesn't run RunModal by passing the record as a parameter, but calls internal procedures to set up the print record, and then runs RunModal without the Table parameter. Since RunModal returns an error if invoked with a Table parameter that's different from the one in the report (which for us is always a temporary custom table, where our app copies the data from the setup and the print record), we need to "overwrite" the standard RunModal with our custom procedure.

Performance Considerations

We expect customers using our app to always use our custom report with the Template Code set to print, and the subscription simply needs to check if the report ID matches the app's to determine whether to set IsHandled=true or do nothing. Therefore, from a performance perspective, the subscription presents no issues.

Data Sensitivity Review

The event in question would expose the record to be printed and the selected Report Selections to be executed, and all the data "exported" to print from the app is set via setup and uses user permissions to be selected, so no sensitive data is affected by the custom logic.

Multi-Extension Interaction

The subscription that performs printing instead of the standard one would only work if IsHandled=false (and therefore no one has modified the standard behavior), setting IsHandled=true at the end of the process. This way, each parallel subscription would know not to do anything since IsHandled has already been set to true.
Internal work item: AB#621606

Metadata

Metadata

Assignees

No one assigned

    Labels

    FinanceGitHub request for Finance areaevent-requestRequest for adding an event

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions