Skip to main content

Guide to implementing customized document creation

Overview

This documentation provides guidance on implementing custom document creation processes using the Integration Event OnDocumentCreation in the DEXPRO Core Framework. While the default implementation creates purchase documents (Tables 38, 39), this guide shows you how to implement your own document creation logic using the provided JSON data.

Requirements

The following setting must be made in the document class setup before validating a document:

  • Next process step: Breeze Interface
  • Target Template: None

image-1737634153644.png

Have you validated a document with the DEXPRO Squeeze app and transferred it to the next process step, Breeze Interface? If so, you will now see it in Breeze Interface in a waiting status (WaitingForRetrieval). At this point, you have the option of transferring the validated document to an approval workflow so that it can be reported back after approval and transferred to the target document creation process. Further information on the Breeze Interface API can be found here.

image-1737637141572.png

Sobald Sie den Status des Breeze Belegs in "Processed" geändert haben, wird dieser an den DEXPRO Core zur weiteren Verarbeitung gemeldet - dies ist der Integrationspunkt, an dem Sie ansetzen müssen.

Once you have changed the status of the Breeze receipt to "Processed", it will be reported to the DEXPRO Core for further processing—this is the integration point where you need to start.

Integration point

DerThe zentralecentral Integrationspunktintegration istpoint das is the OnDocumentCreation-Ereignis event in Codeunit 70954599 “DXP Doc. Creation Def. Impl.” in derthe App DEXPRO Core. Diesesapp. EreignisThis wirdevent währendis dertriggered Dokumentenverarbeitungduring ausgelöstdocument undprocessing ermöglichtand dieenables Implementierungthe einerimplementation benutzerdefiniertenof Dokumentenerstellungslogik.custom document creation logic.

Ereignis-SignaturEvent Signature

[IntegrationEvent(false, false)]
local procedure OnDocumentCreation(JObject: JsonObject; var CreatedDocumentRecordId: RecordId)

Parameter

  • JObject: EnthältContains diethe vollständigencomplete JSON-DatenJSON mitdata denwith Dokumentinformationenthe document information
  • CreatedDocumentRecordId: MussMust mitbe derset with the RecordId desof erstelltenthe Dokumentscreated gesetzt werdendocument

ImplementierungsleitfadenImplementation Guide

SchrittStep 1: Create Subscriber-Codeunit erstellen

ZunächstFirst, erstellencreate Siea einecodeunit Codeunit,that diesubscribes dasto OnDocumentCreation-Ereignisthe abonniert:OnDocumentCreation event:

codeunit 50100 "Custom Document Creation"
{
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"DXP Doc. Creation Def. Impl.", 'OnDocumentCreation', '', false, false)]
    local procedure OnDocumentCreation(JObject: JsonObject; var CreatedDocumentRecordId: RecordId)
    begin
        // Your implementation here
        CreateCustomDocument(JObject, CreatedDocumentRecordId);
    end;
}

SchrittStep 2: DokumentenerstellungslogikImplement implementierendocument creation logic

HierHere einis Beispielan fürexample dieof Implementierunghow derto benutzerdefiniertenimplement Dokumentenerstellung:custom document creation:

local procedure CreateCustomDocument(JObject: JsonObject; var CreatedDocumentRecordId: RecordId)
var
    CustomHeader: Record "Custom Document Header";
    CustomLine: Record "Custom Document Line";
    JsonHelper: Codeunit "DXP Json Helper";
    HeaderJObject: JsonObject;
    LinesJArray: JsonArray;
    LineJToken: JsonToken;
    LineNo: Integer;
begin
    // 1. Create Header
    CustomHeader.Init();
    CustomHeader."Document Type" := GetDocumentType(JObject);
    CustomHeader."Vendor No." := CopyStr(JsonHelper.ValAsTxt(JObject, 'vendorNo', true), 1, MaxStrLen(CustomHeader."Vendor No."));
    CustomHeader."Document Date" := JsonHelper.ValAsDate(JObject, 'docDate', true);
    CustomHeader."Posting Date" := JsonHelper.ValAsDate(JObject, 'postingDate', true);
    CustomHeader."Document Reference" := CopyStr(JsonHelper.ValAsTxt(JObject, 'docReference', true), 1, MaxStrLen(CustomHeader."Document Reference"));
    CustomHeader.Insert(true);

    // 2. Process Lines
    LinesJArray := JsonHelper.ReadJArrayFromObj(JObject, 'lines');
    LineNo := 10000;
    
    foreach LineJToken in LinesJArray do begin
        CustomLine.Init();
        CustomLine."Document No." := CustomHeader."No.";
        CustomLine."Line No." := LineNo;
        CustomLine."Item No." := CopyStr(JsonHelper.ValAsTxt(LineJToken.AsObject(), 'no', true), 1, MaxStrLen(CustomLine."Item No."));
        CustomLine.Quantity := JsonHelper.ValAsDec(LineJToken.AsObject(), 'qty', true);
        CustomLine."Unit Price" := JsonHelper.ValAsDec(LineJToken.AsObject(), 'unitPrice', true);
        CustomLine.Insert(true);
        
        LineNo += 10000;
    end;

    CreatedDocumentRecordId := CustomHeader.RecordId;
end;

JSON-StrukturStructure

DieThe JSON-EingabeJSON folgtinput dieserfollows Struktur:this structure:

{
   "type":"Invoice",
   "vendorNo":"K00170",
   "iban":"DE58520503530052599766",
   "vatRegNo":"DE540026784",
   "barcode":"123456789",
   "docDate":"2023-07-13",
   "serviceDate":"2023-07-13",
   "postingDate":"2025-01-23",
   "postingDesc":"Die ist eine Buchungsbeschreibung.",
   "docReference":"R308154",
   "orderNo":"B23106029",
   "netAmount":7894.71,
   "netAmount2":0.0,
   "netAmount3":0.0,
   "taxRate":19.0,
   "taxRate2":0.0,
   "taxRate3":0.0,
   "taxAmount":1499.99,
   "taxAmount2":0.0,
   "taxAmount3":0.0,
   "totalAmount":9394.7,
   "currency":"EUR",
   "assignedTo":"BERND.FEDDERSEN",
   "note":"Die ist eine Bemerkung!",
   "dimensions":{
      "ABTEILUNG":"PROD",
      "EINKÄUFER":"BF",
      "KOSTENTRÄGER":"IT"
   },
   "dimensionSetID":27,
   "customFields":{
      "docClass":"DXP Invoice / Credit Memo",
      "namesAndValues":[
         {
            "name":"Customer_No",
            "value":"01121212"
         },
         {
            "name":"Custom_Date",
            "value":"2025-01-26"
         }
      ]
   },
   "orderMatchDifference":"false",
   "lines":[
      {
         "orderNo":"B23106029",
         "orderLineNo":10000,
         "receiptNo":"ELIEF107004",
         "receiptLineNo":10000,
         "vendorItemNo":"",
         "type":"Item",
         "no":"90002",
         "description":"JogiTek G 1337 Gaming-Headset",
         "qty":17.0,
         "uom":"STÜCK",
         "unitPrice":99.99,
         "lineDisc":0.0,
         "netAmount":1699.83,
         "totalAmount":2022.8,
         "taxRate":19.0,
         "vatBusPostingGroup":"INLAND",
         "vatProdPostingGroup":"MWST.19",
         "dimensions":{
            "ABTEILUNG":"PROD",
            "BEREICH":"30",
            "EINKÄUFER":"BF",
            "KOSTENTRÄGER":"IT",
            "VERKAUFSKAMPAGNE":"WINTER"
         },
         "dimensionSetID":53,
         "genProdPostingGroup":"HANDEL",
         "genBusPostingGroup":"INLAND",
         "deferralCode":"",
         "quantityDifference":"false",
         "unitPriceDifference":"false",
         "discountDifference":"false",
         "receiptDateDifference":"false",
         "customFields":{
            "docClass":"DXP Invoice / Credit Memo",
            "namesAndValues":[
               {
                  "name":"Custom_Field_1",
                  "value":"Text in Zeile 10000"
               },
               {
                  "name":"Custom_Field_2",
                  "value":"2025-01-31"
               }
            ]
         }
      },
      {
         "orderNo":"B23106029",
         "orderLineNo":30000,
         "receiptNo":"ELIEF107004",
         "receiptLineNo":30000,
         "vendorItemNo":"",
         "type":"Item",
         "no":"90005",
         "description":"Sumsing Galaxy 23",
         "qty":12.0,
         "uom":"STÜCK",
         "unitPrice":349.99,
         "lineDisc":0.0,
         "netAmount":4199.88,
         "totalAmount":4997.86,
         "taxRate":19.0,
         "vatBusPostingGroup":"INLAND",
         "vatProdPostingGroup":"MWST.19",
         "dimensions":{
            "ABTEILUNG":"PROD",
            "BEREICH":"50",
            "EINKÄUFER":"BF",
            "KOSTENTRÄGER":"IT",
            "VERKAUFSKAMPAGNE":"WINTER"
         },
         "dimensionSetID":55,
         "genProdPostingGroup":"HANDEL",
         "genBusPostingGroup":"INLAND",
         "deferralCode":"",
         "quantityDifference":"false",
         "unitPriceDifference":"false",
         "discountDifference":"false",
         "receiptDateDifference":"false",
         "customFields":{
            "docClass":"DXP Invoice / Credit Memo",
            "namesAndValues":[
               {
                  "name":"Custom_Field_1",
                  "value":"Text in Zeile 20000"
               },
               {
                  "name":"Custom_Field_2",
                  "value":"2025-01-30"
               }
            ]
         }
      },
      {
         "orderNo":"B23106029",
         "orderLineNo":20000,
         "receiptNo":"ELIEF107004",
         "receiptLineNo":20000,
         "vendorItemNo":"",
         "type":"Item",
         "no":"90000",
         "description":"Y-Phone Ultra Pro 23",
         "qty":5.0,
         "uom":"STÜCK",
         "unitPrice":399.0,
         "lineDisc":0.0,
         "netAmount":1995.0,
         "totalAmount":2374.05,
         "taxRate":19.0,
         "vatBusPostingGroup":"INLAND",
         "vatProdPostingGroup":"MWST.19",
         "dimensions":{
            "ABTEILUNG":"PROD",
            "BEREICH":"70",
            "EINKÄUFER":"BF",
            "KOSTENTRÄGER":"IT",
            "VERKÄUFER":"JH",
            "VERKAUFSKAMPAGNE":"WINTER"
         },
         "dimensionSetID":58,
         "genProdPostingGroup":"HANDEL",
         "genBusPostingGroup":"INLAND",
         "deferralCode":"",
         "quantityDifference":"false",
         "unitPriceDifference":"false",
         "discountDifference":"false",
         "receiptDateDifference":"false",
         "customFields":{
            "docClass":"DXP Invoice / Credit Memo",
            "namesAndValues":[
               {
                  "name":"Custom_Field_1",
                  "value":"Text in Zeile 30000"
               },
               {
                  "name":"Custom_Field_2",
                  "value":"2025-01-29"
               }
            ]
         }
      }
   ]
}

Best practice

  1. FehlerbehandlungError handling: ImplementierenImplement Sieproper eineerror ordnungsgemäßehandling Fehlerbehandlungfor fürJSON JSON-Parsingparsing undand Datenbankoperationen:database operations:
local procedure CreateCustomDocument(JObject: JsonObject; var CreatedDocumentRecordId: RecordId)
var
    CustomHeader: Record "Custom Document Header";
begin
    if not DoesJsonHaveRequiredFields(JObject) then
        Error('Required fields are missing in the JSON payload');
        
    if not TryCreateCustomHeader(JObject, CustomHeader) then
        Error('Failed to create document header');
        
    // ... rest of the implementation
end;
  1. ValidierungValidation: ImplementierenImplement Sieproper einevalidation ordnungsgemäßebefore Validierungdocument vor der Dokumenterstellung:creation:
local procedure ValidateDocument(JObject: JsonObject): Boolean
var
    Vendor: Record Vendor;
    VendorNo: Code[20];
begin
    VendorNo := CopyStr(JsonHelper.ValAsTxt(JObject, 'vendorNo', true), 1, MaxStrLen(VendorNo));
    if not Vendor.Get(VendorNo) then
        Error('Vendor %1 does not exist', VendorNo);
    // Add more validation as needed
    exit(true);
end;

HäufigeCommon Szenarienscenarios

SzenarioScenario 1: VerschiedeneCreate Dokumenttypendifferent erstellendocument types

local procedure GetDocumentType(JObject: JsonObject): Enum "Custom Document Type"
var
    DocType: Text;
begin
    DocType := JsonHelper.ValAsTxt(JObject, 'type', true);
    case DocType of
        'Invoice':
            exit("Custom Document Type"::Invoice);
        'CreditMemo':
            exit("Custom Document Type"::"Credit Memo");
        else
            Error('Unknown document type: %1', DocType);
    end;
end;

SzenarioScenario 2: BenutzerdefinierteProcessing Feldercustom verarbeitenfields

local procedure ProcessCustomFields(JObject: JsonObject; var CustomDoc: Record "Custom Document Header")
var
    CustomFieldsObj: JsonObject;
    CustomFieldsArr: JsonArray;
    FieldToken: JsonToken;
begin
    if not JsonHelper.TokenExists(JObject, 'customFields') then
        exit;
        
    CustomFieldsObj := JsonHelper.ReadJObjectFromObj(JObject, 'customFields');
    CustomFieldsArr := JsonHelper.ReadJArrayFromObj(CustomFieldsObj, 'namesAndValues');
    
    foreach FieldToken in CustomFieldsArr do
        ProcessCustomField(FieldToken.AsObject(), CustomDoc);
end;

FehlerbehebungTroubleshooting

  1. RecordId istis leerempty: StellenEnsure Siethat sicher,you dassset Siethe denCreatedDocumentRecordId CreatedDocumentRecordId-Parameter setzen:parameter:
CreatedDocumentRecordId := CustomHeader.RecordId;
  1. JSON-Parsing-FehlerError: VerwendenUse Siethe dieJsonHelper JsonHelper-Funktionenfunctions fürfor sicheressecure Parsing:parsing:
if not JsonHelper.TokenExists(JObject, 'vendorNo') then
    Error('Vendor number is missing in JSON');
  1. DatenvalidierungData validation: ImplementierenImplement Sieproper einedata ordnungsgemäße Datenvalidierung:validation:
if JsonHelper.ValAsDec(LineJToken.AsObject(), 'qty', true) <= 0 then
    Error('Quantity must be greater than 0');