Skip to content

Using the "Codeunit" Output Type

The Codeunit output type can be used to process and send documents via custom business logic. Instead of using standard output types like E-Mail, FTP, or Download, a codeunit is executed that can transfer or further process the generated documents to any destination.

Info

The Codeunit output type is particularly suitable for integrations where documents are to be transferred to external systems or APIs (e.g., DMS, cloud storage, archive systems).

Typical Use Cases

With this feature, you can, for example:

  • Upload documents via external APIs (e.g., Dropbox, Google Drive, or your own repositories)
  • Transfer documents to third-party systems (e.g., DMS, archive systems)
  • Implement custom processing logic (e.g., encryption, validation, transformation)
  • Integrate into company-specific workflows (e.g., automatically starting approval processes)

Setup

To use the Codeunit output type, you need to set up a corresponding Dispatch Profile and specify the desired codeunit.

  1. Open the Dispatch Profiles page.
  2. Create a new profile or edit an existing one.
  3. In the Output Type field, select the Codeunit option.
  4. Run the Options action in the menu bar.
  5. In the Codeunit ID field, enter the number of the codeunit to be executed (e.g., 50000 from the example below).
  6. Under Dispatch Profile Attachments, configure the documents (reports, files, etc.) to be processed by the codeunit.

When this dispatch profile is now used to send documents, the codeunit you specified will be executed.

How it Works

When a Queue Entry with the Codeunit output type is processed, Document Dispatch performs the following steps:

  1. All configured attachments (reports, files, XML, etc.) are generated.
  2. The codeunit stored in the Dispatch Profile is executed via CODEUNIT.Run().
  3. The codeunit gains access to the generated documents through the Queue Line entries.
  4. The codeunit processes and sends the documents according to the implemented logic (e.g., API upload).

Example: Uploading Documents to a Repository via API

The following example shows how documents can be transferred to an external repository via a REST API.

Example Implementation

AL - Custom Codeunit for API Upload
codeunit 50000 "Doc. Dispatch API Upload"
{
    TableNo = "SIM_EDS Record Attachment";
    Permissions = tabledata "SIM_EDS Queue Line" = RIM;

    trigger OnRun()
    begin
        UploadDocumentsToAPI();
    end;

    var
        GlobalCodeunitSIMEDSSI: Codeunit "SIM_EDS SI";

    /// <summary>
    /// Uploads all generated documents to an external repository via an API
    /// </summary>
    procedure UploadDocumentsToAPI()
    var
        LocalRecordSIMEDSQueueLine: Record "SIM_EDS Queue Line";
        LocalRecordSIMEDSQueueEntry: Record "SIM_EDS Queue Entry";
        LocalCodeunitBase64Convert: Codeunit "Base64 Convert";
        LocalHttpClient: HttpClient;
        LocalHttpContent: HttpContent;
        LocalHttpResponse: HttpResponseMessage;
        LocalHeaders: HttpHeaders;
        LocalInStream: InStream;
        LocalFileBase64Text: Text;
        LocalApiUrlText: Text;
        LocalQueueEntryNo: BigInteger;
        LocalSuccessBoolean: Boolean;
    begin
        // Get Queue Entry No. from Document Dispatch
        LocalQueueEntryNo := GlobalCodeunitSIMEDSSI.GetQueueEntryNo();
        if LocalQueueEntryNo = 0 then 
            Error('No Queue Entry found.');

        if not LocalRecordSIMEDSQueueEntry.Get(LocalQueueEntryNo) then
            Error('Queue Entry %1 not found.', LocalQueueEntryNo);

        // Iterate through all generated Queue Lines (= documents) for this Queue Entry
        LocalRecordSIMEDSQueueLine.SetRange("Queue Entry No.", LocalQueueEntryNo);
        LocalRecordSIMEDSQueueLine.SetRange("Attach Tag", true); // Only tagged attachments

        if LocalRecordSIMEDSQueueLine.FindSet() then
            repeat
                // Get document from Queue Line
                LocalRecordSIMEDSQueueLine.CalcFields("Document Blob");

                if LocalRecordSIMEDSQueueLine."Document Blob".HasValue then begin
                    // Convert document to Base64 for API transfer
                    Clear(LocalInStream);
                    LocalRecordSIMEDSQueueLine."Document Blob".CreateInStream(LocalInStream);
                    LocalFileBase64Text := LocalCodeunitBase64Convert.ToBase64(LocalInStream);

                    // Perform API upload
                    LocalApiUrlText := GetAPIUploadUrl(); // Your API URL
                    LocalSuccessBoolean := UploadFileToAPI(
                        LocalApiUrlText,
                        LocalRecordSIMEDSQueueLine."Document Name",
                        LocalFileBase64Text,
                        LocalRecordSIMEDSQueueEntry
                    );

                    if not LocalSuccessBoolean then
                        Error('Upload failed for document: %1', LocalRecordSIMEDSQueueLine."Document Name");
                end;
            until LocalRecordSIMEDSQueueLine.Next() = 0;

        Message('All documents uploaded successfully.');
    end;

    local procedure UploadFileToAPI(
        ParamApiUrl: Text;
        ParamFilename: Text;
        ParamFileBase64: Text;
        ParamQueueEntry: Record "SIM_EDS Queue Entry"
    ): Boolean
    var
        LocalHttpClient: HttpClient;
        LocalHttpContent: HttpContent;
        LocalHttpResponse: HttpResponseMessage;
        LocalHeaders: HttpHeaders;
        LocalJsonObject: JsonObject;
        LocalJsonText: Text;
        LocalRequestBody: Text;
    begin
        // Create JSON payload for API
        LocalJsonObject.Add('filename', ParamFilename);
        LocalJsonObject.Add('content', ParamFileBase64);
        LocalJsonObject.Add('source_document', Format(ParamQueueEntry."Source ID"));
        LocalJsonObject.Add('queue_entry_no', ParamQueueEntry."Entry No.");

        LocalJsonObject.WriteTo(LocalJsonText);

        // Configure HTTP Request
        LocalHttpContent.WriteFrom(LocalJsonText);
        LocalHttpContent.GetHeaders(LocalHeaders);
        LocalHeaders.Clear();
        LocalHeaders.Add('Content-Type', 'application/json');
        LocalHeaders.Add('Authorization', GetAPIAuthToken()); // Your auth logic

        // Perform API call
        if not LocalHttpClient.Post(ParamApiUrl, LocalHttpContent, LocalHttpResponse) then
            exit(false);

        // Check response
        exit(LocalHttpResponse.IsSuccessStatusCode());
    end;

    local procedure GetAPIUploadUrl(): Text
    var
        LocalSetup: Record "Your API Setup"; // Your setup table
    begin
        LocalSetup.Get();
        LocalSetup.TestField("API Base URL");
        exit(LocalSetup."API Base URL" + '/upload');
    end;

    local procedure GetAPIAuthToken(): Text
    var
        LocalSetup: Record "Your API Setup";
    begin
        LocalSetup.Get();
        LocalSetup.TestField("API Token");
        exit('Bearer ' + LocalSetup."API Token");
    end;
}

Advantages

When you use the Codeunit output type, you get the following advantages, among others:

  • Full Control: You determine where and how documents are handled.
  • Flexibility: Any API, any protocol, any business logic is possible.
  • Integration: Seamless integration into the Document Dispatch Queue mechanism.
  • Error Handling: Use of the standard error handling mechanisms of Document Dispatch.
  • Traceability: Uploads are logged in the Queue History.