Skip to content

[Extensibility]: Add a generic post-render event to inspect or replace generated PDF content #11015

Description

Describe the issue

Business Central provides several ways for extensions to influence report generation and individual document-output pipelines, but there is currently no generic extensibility point that exposes the final rendered PDF content together with enough context to identify the report and source document before that PDF is delivered to its destination.

A concrete example already exists in table Report Selections for the email path:

OnSendEmailDirectlyOnBeforeEmailWithAttachment(
    RecordVariant,
    TempAttachReportSelections,
    TempBlob,
    DocumentMailing,
    DocNo,
    DocName,
    EmailAddress);

At this point the selected report has already been rendered and the mutable TempBlob contains the PDF attachment, allowing an extension to replace or post-process that PDF before it is emailed.

Equivalent functionality is not available generically across PDF report output.

This prevents extensions from implementing output-independent PDF post-processing such as:

  • applying a digital/PAdES signature to the final PDF;
  • adding final document metadata;
  • applying supported PDF transformations;
  • archiving or hashing the exact final document that will be issued;
  • integrating generic compliance or document-processing services.

This becomes particularly important with the newer report OnPreRendering / additionalDocuments functionality.

An extension may, for example, append contractual terms or another PDF to a commercial report during rendering. A digital signature must then be applied to the resulting combined PDF, not to the original report before the additional pages have been appended.

Expected behavior

Please expose a generic event after PDF rendering has completed but before the resulting PDF is returned, downloaded, emailed, attached, or otherwise delivered.

Conceptually, an API could look similar to:

[IntegrationEvent(false, false)]
local procedure OnAfterRenderPdf(
    SourceRecord: Variant;
    ReportId: Integer;
    ReportUsage: Enum "Report Selection Usage";
    var PdfBlob: Codeunit "Temp Blob")
begin
end;

The exact signature does not need to follow this example.

The important requirements are:

  1. The event is raised after the final PDF has been rendered, including PDF documents added through OnPreRendering / additionalDocuments.

  2. The PDF is exposed through a mutable stream or Temp Blob, allowing a subscriber to replace it with a post-processed PDF.

  3. Enough context is provided to identify what is being processed.

Useful context would include, where available:

  • Report ID;
  • source record / RecordVariant;
  • report selection usage;
  • selected report/layout information;
  • document number or other identifying information;
  • output purpose/destination if the same event covers multiple output paths.
  1. The event should be generic rather than tied only to email.

Ideally the same post-processing abstraction would apply to supported PDF output paths such as:

  • email attachment;
  • download/save as PDF;
  • document attachment/archive;
  • other report rendering paths that produce a final PDF stream.

Use case

We are implementing generic document-terms and AdES functionality.

A report can be rendered as:

Sales Quote
    +
Contractual Terms
    =
Final PDF

The combined PDF may then optionally need a PAdES digital signature before being issued.

The required lifecycle is therefore:

Render primary report
        ↓
Apply OnPreRendering additions
        ↓
Produce final combined PDF
        ↓
Post-process final PDF
        ↓
Email / download / archive

There is currently no single supported interception point at the Post-process final PDF stage.

The existing email event demonstrates the desired pattern, but implementing the same logic separately for every output pipeline is fragile and can lead to inconsistent behavior.

Why this should be generic

The requested event is not specific to PAdES or to a particular document type.

It is useful whenever an extension needs to transform or inspect the exact PDF artifact that Business Central is about to issue.

Keeping the event generic also avoids adding individual extensibility requests for each PDF-processing use case.

Steps to reproduce

  1. Create or use an extension that subscribes to the report OnPreRendering event.

  2. Add an additional PDF document through the additionalDocuments parameter, for example by appending contractual terms to a sales quote or sales invoice.

  3. Run the report and generate the final PDF.

  4. Observe that the report output contains both the primary report and the appended PDF document.

  5. Attempt to subscribe to a generic event that exposes this final combined PDF before it is delivered.

  6. Observe that no generic event is available that:

    • runs after all report rendering and additionalDocuments processing has completed;
    • exposes the final PDF content;
    • provides sufficient report and source-record context; and
    • allows the extension to replace the PDF.
  7. As a result, an extension cannot reliably apply a digital signature or other post-processing to the exact PDF that will be emailed, downloaded, attached, or archived.

The email-specific event OnSendEmailDirectlyOnBeforeEmailWithAttachment can be used for the email path, but equivalent interception points are not available consistently for other PDF output paths.

Additional context

The System Application already exposes System.IO."PDF Document" for PDF operations, and the reporting platform supports adding PDF documents during OnPreRendering.

A final rendered-PDF extensibility point would complement these APIs by allowing extensions to operate on the completed artifact.

We would be willing to contribute the application-side change and tests if the appropriate common rendering location is available in AL.

I will provide a fix for a bug

  • I will provide a fix for a bug

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Team: IntegrationsGitHub request for Integrations area

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions