Implementation of a new, generic document class WIP
SQUEEZE → Core → Your processing
This guide is deliberately focused and pipeline-oriented: It shows how document data is downloaded from SQUEEZE, processed in queues, and persisted in DEXPRO Core—and where a third-party extension comes into play.
Term: In this guide, “SQUEEZE app” refers to the Business Central extension that is connected to the SQUEEZE API and controls imports to DEXPRO Core.
Assumptions:
- Third-party developers typically work with published icons, not with the entire source code.
- The SQUEEZE app handles downloading + import queue + creation of the core document as well as the rudimentary creation of the SQUEEZE document, taking field mapping into account, as soon as setup is complete.
- Your extension takes over the business logic once the core document exists: create or extend source records, validate them, generate “Processed JSON,” and optionally create your own target object or document.
1) The end-to-end process SQUEEZE → Core
Once the document class and setup are configured, the SQUEEZE app's import pipeline typically runs as follows:
DXP Document Classextend and bind your implementation:DXP ISource Document.- Configure settings for this Document class‑Setup.
- When validating
DXP SQZ Document Class ID, the SQUEEZE app automatically retrieves the required setup values from SQUEEZE (e.g.,DXP SQZ Export Interface IDandDXP SQZ Line Table ID) and fills them in.
- When validating
- The SQUEEZE app job calls
DXP SQZ API Mgt.DownloadDocumentData(). Can also be called via “Download documents”.- New entries are created in the DXP SQZ import queue (document ID + target client).
- The SQUEEZE app calls
DXP SQZ Import Queue Mgt.TransferImportQueueEntries().- The orchestration code unit
DXP Sqz Create Documentis executed for the entries in the import queue.
- The orchestration code unit
DXP SQZ API Mgt.CreateCoreAndSQUEEZEDocument(DocClass, DocumentId)loads the complete JSON.DXP Document Mgt.AddDocument(DocClass, DocumentId, RawJson, …)is called up.- Result: A
DXP Document‑Record exists. Status =Imported,JSON Rawis filled.
- The SQUEEZE app calls your implementation
ISourceDocument.CreateSource(Document).- Your implementation begins here.
After step 6, you will have:
- A Core‑Container‑Document (
DXP Document). - A SQUEEZE document in the SQUEEZE app.
- Your source records should exist once
CreateSourcehas completed successfully.
2) What you implement (Interfaces)
Source contract, i.e., squeeze page: DXP ISource Document
You implement this to:
- Create your editable source data sets from
DXP Document.JSON Raw - Validate source data records
- Generate “Processed JSON” and transfer it to core processing
Target contract, i.e., target document: DXP IDocument Processing
You implement this if Core is to create/update its own target data set (your own table/document) from the “Processed JSON.”
3) SchrittStep 1 — DokumentklasseDefine definierendocument undclass Quell‑Implementierungand zuweisenassign source implementation
ErstellenCreate Siean eineenum Enum‑Extensionextension undand bindenbind Sieyour Ihresource Source‑Implementierung:implementation:
enumextension 50100 "MY Document Class Ext." extends "DXP Document Class"
{
value(50100; "MY Generic Document")
{
Caption = 'My Generic Document';
Implementation = "DXP ISource Document" = "MY Source Document Impl.";
}
}
4) SchrittStep 2 — Dokumentenklassen‑EinrichtungConfigure konfigurierendocument class setup (damitso diethat Importwarteschlangethe gefülltimport wird)queue is filled)
KonfigurierenConfigure Siethe SQUEEZE-specific fields in der Dokumentenklassen‑Einrichtung fürthe Ihredocument neueclass Dokumentklassesetup diefor SQUEEZE‑spezifischenyour Felder.new document class.
Wichtig:Important:
DasValidatingValidierenthevonDXP SQZ Document Class IDtriggertdastriggersautomatischetheLadenautomaticderloadingerforderlichenofKonfigurationtheausrequired configuration from SQUEEZE (z. B.e.g.,DXP SQZ Export Interface IDundandDXP SQZ Line Table ID).FallsIfdertheAbrufcallfehlschlägt,fails,werdenthesedieseAPI-derivedAPI‑abgeleitetenfieldsFelderarewiederclearedgeleert.again.
Ergebnis:Result: DieThe SQUEEZE‑AppSQUEEZE kann app can execute DownloadDocumentData() ausführen undand Einträgecreate in entries in the DXP SQZ Import Queue für Ihrefor Klasseyour anlegen.class.
5) SchrittStep 3 — FeldzuordnungEnsure sicherstellenfield mapping (heruntergeladenedownloaded Zuordnungmapping + Ihreyour Standardwerte)default values)
DieThe SQUEEZE‑AppSQUEEZE kannapp dencan Feldkatalogdownload desthe angeschlossenenfield catalog of the connected Squeeze Mandantenclient herunterladenand undpersist it in Core‑Mapping‑TabellenCore persistierenMapping tables (proper Dokumentklasse)document class).
IhreYour Rollerole alsas Dokumentklassen‑Implementierer:a document class implementer:
Standard‑FeldzuordnungProvide„standard field mapping “Squeeze Field Name → AL Field No.“”viaviaInitFieldMapping(...)bereitstellen..AlternativAlternatively,FeldermapüberfieldsdieviaZuordnungs‑Pagesthemappenassignment pages (BenutzerdefiniertecustomFeldzuordnung)field assignment).
5.1 1 Implement InitFieldMapping implementieren (eigenständigesindependent Beispiel)example)
codeunit 50101 "MY Source Document Impl." implements "DXP ISource Document"
{
procedure InitFieldMapping(var HeaderMapping: Dictionary of [Text, Integer]; var LineMapping: Dictionary of [Text, Integer])
var
Header: Record "DXP SQZ Document Header";
Line: Record "DXP SQZ Document Line";
begin
Clear(HeaderMapping);
Clear(LineMapping);
// Header fields
HeaderMapping.Add('vendorNo', Header.FieldNo("Buy-from Vendor No."));
HeaderMapping.Add('documentDate', Header.FieldNo("Document Date"));
HeaderMapping.Add('postingDate', Header.FieldNo("Posting Date"));
HeaderMapping.Add('reference', Header.FieldNo("Document Reference"));
// Line fields
LineMapping.Add('description', Line.FieldNo(Description));
LineMapping.Add('quantity', Line.FieldNo(Quantity));
LineMapping.Add('unitPrice', Line.FieldNo("Direct Unit Cost"));
end;
// other interface methods omitted here...
}
5.2 Validierungs‑SchalterValidation beimswitch Zuweisenwhen vonassigning Feldern:fields: App‑FeldValidate validierenapp field
WennWhen diethe SQUEEZE‑AppSQUEEZE oderapp Ihreor Quell‑Erstelllogikyour JSON‑Wertesource increation „App-/Quellfelder“logic schreibt,writes könnenJSON Sievalues steuern,to ob“app/source der fields,” you can control whether the OnValidate‑TriggerOnValidate trigger ausgeführt wird.is executed.
In DXP Custom Field Mapping:
Validate App Field=App‑FeldValidatewährendthedesappAssignmentsfieldvalidieren.during the assignment.Validate(Ziel)Target) =ValidierungPerformbeimvalidationTransferwhenintransferringdastoZiel‑Feldtheausführen.target field.
NutzenUse Siethis, dasfor z. B.example, wennif Erweiterungsfelderextension Business‑Logikfields in have business logic in OnValidate haben oderor wennif Sieyou bewusstwant trigger‑freito assign deliberately trigger-free (performanter)higher zuweisen wollen.performance).
6) SchrittStep 4 — Source‑DatensätzeCreate in Source data sets in CreateSource erstellen
CreateSource(Document) wird vonis dercalled SQUEEZE‑Appby unmittelbarthe nach SQUEEZE app immediately after DXP Document Mgt.AddDocument(...) aufgerufen, sobaldas dersoon Core‑Container‑Datensatzas existiert.the core container data record exists.
MinimaleMinimum Verantwortlichkeiten:responsibilities:
- Read
DXP Document.JSON Rawlesen.. - Create SQUEEZE‑Source‑Header/Lines
erstellen(DXP SQZ Document Header/DXP SQZ Document Line). - Connect Core‑
Dokumentdocumentmit demwith SQUEEZE‑Source‑HeaderviaviaUpdateDocumentAfterTransferverknüpfen..
Optional (empfohlen,recommended wennif Sieyou Gleichwertigkeitwant derfunctionality Funktionenequivalent zuto denthe Standard‑SQUEEZE‑Dokumentklassenstandard möchten)SQUEEZE document classes): 4) AnhängeDownload herunterladen,attachments wenn if DXP Download Attachments aktiv ist.is active. 5) AutomatischePerform Validierungautomatic ausführen,validation wennif fürenabled dasfor Dokumentthe aktiviert.document.
6.1 Beispiel:Example: Create SQUEEZE‑Header + Lines mitwith dengeneric generischen Helpern erstellenhelpers
WasWhat diethe Helperhelpers machendo (damitso Sieyou esdon't nichthave doppeltto implementieren)implement it twice):
-
SqzDocumentMgt.CreateSQUEEZEDocHeader(Document, DocHeader, RawJson)ErstelltCreatesgenauexactlyeinenoneDatensatzdatainrecord inDXP SQZ Document Headerfürdasfor the Core‑Dokumentdocument (DXP Document).SetztSetsIdentifikationsfelderidentificationwiefields asCore Document No.unddieand the SQUEEZE‑API Document ID.WeistAssignsHeader‑Felderheaderausfields from JSONanhandbasedderonkonfiguriertentheZuordnungenconfiguredzu:mappings:
DXP Field Mapping(Feldzuordnung)field mapping)DXP Custom Field Mapping(BenutzerdefinierteCustomFeldzuordnung)field mapping)
RespektiertRespectsDXP Custom Field Mapping.Validate App Fieldundentscheidetanddamit,thusobdecidesbeimwhetherZuweisenthederOnValidate‑TriggerOnValidate triggerausgeführtwird.is executed when assigning.FührtExecutesdastheIntegration‑Eventintegration eventOnBeforeModifySQUEEZEDocumentHeader(...)alsExtension‑Hookasaus.an extension hook.FürStandarddiepost-processingeingebautenisStandard‑SQUEEZE‑KlassenalsowirdperformedzusätzlichforStandard‑Post‑Processingtheausgeführtbuilt-in standard SQUEEZE classes (z. B.e.g., alternative IBAN/USt‑ID‑Ermittlung,VATLieferantenaktualisierung,IDStandard‑Buchungsdatum,determination,Duplikatsprüfung)supplier update, standard posting date, duplicate check).
-
SqzDocumentMgt.CreateSQUEEZEDocLine(DocHeader, RawJson)ErstelltCreatesdietheDXP SQZ Document Line‑Datensätzedatabasierendsetsaufbaseddenon the JSON‑Rows.WeistAssignLine‑FelderlinenachfieldsdemusinggleichentheMapping‑Prinzipsamezumapping principle (Standardstandard +Custom;custom;optionaloptionallymitwithValidierungstriggern)validation triggers).BefülltFill theCore Document No.aufdeninLines.the lines.FürForStandard‑SQUEEZE‑KlassenstandardwirdSQUEEZEzusätzlichclasses,Standard‑Line‑Post‑Processingstandardangewendetline post-processing is also applied (z. B.e.g.,ÜbertragungtransfererkannterofWerte)recognized values).PersistiertPersistsline‑bezogeneline-relatedHilfsdatenauxiliary data (z. B.e.g.,Koordinaten/Metadaten,coordinates/metadatadiethat use the UIundandMatching‑Logikmatchingnutzen)logic).
procedure CreateSource(Document: Record "DXP Document"): Boolean
var
DocClassSetup: Record "DXP Document Class Setup";
AutoValidationMgt: Codeunit "DXP Automatic Validation Mgt.";
JsonHelper: Codeunit "DXP Json Helper";
DocMgt: Codeunit "DXP Document Mgt.";
SqzDocumentMgt: Codeunit "DXP SQZ Document Mgt.";
SqzApiMgt: Codeunit "DXP SQZ API Mgt.";
RawJson: JsonObject;
DocHeader: Record "DXP SQZ Document Header";
AutomaticValidation: Boolean;
begin
if (not Document."JSON Raw".HasValue()) or (Document.Status <> Document.Status::Imported) then
exit(false);
// 1) Unverarbeitetes JSON lesen
RawJson := JsonHelper.JObjectFromBlob(Document.RecordId(), Document.FieldNo("JSON Raw"));
// 2) SQUEEZE‑Source‑Dokument mit den generischen Hilfsfunktionen erstellen
// (Feldzuordnung + optionales Validierungs‑Trigger‑Verhalten wird im Helper behandelt)
SqzDocumentMgt.CreateSQUEEZEDocHeader(Document, DocHeader, RawJson);
SqzDocumentMgt.CreateSQUEEZEDocLine(DocHeader, RawJson);
// 3) Core → SQUEEZE‑Source‑Header verknüpfen
DocMgt.UpdateDocumentAfterTransfer(Document."No.", Document.Status::Transferred, DocHeader."API Document ID", DocHeader.RecordId());
// 4) Optional: Anhänge herunterladen und speichern
// (gesteuert über die Dokumentenklassen‑Einrichtung)
if DocClassSetup.Get(DocHeader."Document Class") then
if DocClassSetup."DXP Download Attachments" then
SqzApiMgt.DownloadAndSaveAttachments(DocHeader);
// 5) Optional: Automatische Validierung
// Wenn aktiviert, führt die Validierung die Plausibilitätsprüfungen aus und erstellt das „Processed JSON“.
AutomaticValidation := AutoValidationMgt.AutomaticValidationActivated(DocHeader."No.");
if AutomaticValidation then
SqzDocumentMgt.ValidateSQUEEZEDocument(DocHeader, AutomaticValidation);
exit(true);
end;
7) SchrittStep 5 — ValidierungValidation + ÜbergabeHandover „Processed JSON“
7.1 Validierung: Validation: IsSourceDataPlausible
NutzenUse Siethe dasCore Core‑Plausibility‑Framework,Plausibility damitFramework Fehlerto konsistentensure angezeigtthat werden:errors are displayed consistently:
procedure IsSourceDataPlausible(Source: Variant; var TempPlausibilityCheckEntry: Record "DXP Plausibility Check Entry" temporary): Boolean
var
PlausibilityCheck: Codeunit "DXP Plausiblity Check Mgt.";
Header: Record "DXP SQZ Document Header";
begin
if not Source.IsRecord then
exit(false);
Header := Source;
TempPlausibilityCheckEntry.DeleteAll();
PlausibilityCheck.FieldIsEmpty(Header, Header.FieldNo("Buy-from Vendor No."), 0, false, false);
PlausibilityCheck.CheckPostingDate(Header."Posting Date", Header.FieldNo("Posting Date"));
PlausibilityCheck.GetPlausibilityCheckEntries(TempPlausibilityCheckEntry);
exit(TempPlausibilityCheckEntry.IsEmpty());
end;
7.2 Build „Processed JSON“ bauenand undpass anit Coreto übergeben: the core: CreateProcessedJsonFromSource
„Core stores “Processed JSON“JSON” wirdin von Core in DXP Document.JSON Processed gespeichert undand antransfers Ihreit Zielverarbeitungto übergeben.your target processing.
procedure CreateProcessedJsonFromSource(Source: Variant)
var
CoreTokenMgt: Codeunit "DXP Core Token Mgt.";
DocMgt: Codeunit "DXP Document Mgt.";
JsonHelper: Codeunit "DXP Json Helper";
DocTransferMgt: Codeunit "DXP Document Transfer Mgt.";
Header: Record "DXP SQZ Document Header";
Line: Record "DXP SQZ Document Line";
HeaderJObj: JsonObject;
LinesJArr: JsonArray;
LineJObj: JsonObject;
begin
Header := Source;
HeaderJObj.Add(CoreTokenMgt.GetVendorNoTok(), Header."Buy-from Vendor No.");
HeaderJObj.Add(CoreTokenMgt.GetDocDateTok(), Header."Document Date");
HeaderJObj.Add(CoreTokenMgt.GetDocReferenceTok(), Header."Document Reference");
// Benutzerdefinierte Felder (Erweiterungsfelder) aus den Source‑Tabellen hinzufügen
HeaderJObj.Add(CoreTokenMgt.GetCustomFieldsTok(), JsonHelper.Rec2JsonFieldArray(Header, true, true, Header."Document Class", Enum::"DXP Field Type"::Header));
Line.SetRange("Document No.", Header."No.");
if Line.FindSet() then
repeat
Clear(LineJObj);
LineJObj.Add(CoreTokenMgt.GetDescriptionTok(), Line.Description);
LineJObj.Add(CoreTokenMgt.GetQtyTok(), Line.Quantity);
LineJObj.Add(CoreTokenMgt.GetCustomFieldsTok(), JsonHelper.Rec2JsonFieldArray(Line, true, true, Header."Document Class", Enum::"DXP Field Type"::Line));
LinesJArr.Add(LineJObj);
until Line.Next() = 0;
DocTransferMgt.AddDocLinesToHeaderJson(HeaderJObj, LinesJArr);
// An Core‑Zielverarbeitung übergeben
DocMgt.UpdateDocument(
Header."Core Document No.",
Enum::"DXP Document Status"::Transferred,
Enum::"DXP Target Document Process"::"MY Create Custom Document",
Enum::"DXP Next process step"::"Standard document",
HeaderJObj);
end;
8) SchrittStep 6 — EigenesCreate Ziel‑Dokumentyour erstellenown target document
WennIf you want Core Ihrento eigenencreate Ziel‑Datensatzyour erstellenown soll,target erweiterndata Sie set, extend DXP Target Document Process und implementierenand Sie implement DXP IDocument Processing:
enumextension 50102 "MY Target Doc Process Ext." extends "DXP Target Document Process"
{
value(50102; "MY Create Custom Document")
{
Caption = 'Create My Custom Document';
Implementation = "DXP IDocument Processing" = "MY Custom Doc Creation";
}
}
codeunit 50103 "MY Custom Doc Creation" implements "DXP IDocument Processing"
{
procedure ProcessStandardDocument(JObject: JsonObject): RecordId
var
CoreTokenMgt: Codeunit "DXP Core Token Mgt.";
DocTransferMgt: Codeunit "DXP Document Transfer Mgt.";
JsonHelper: Codeunit "DXP Json Helper";
MyDoc: Record "MY Custom Document";
TargetVariant: Variant;
begin
MyDoc.Init();
MyDoc.Validate("Vendor No.", JsonHelper.ValAsTxt(JObject, CoreTokenMgt.GetVendorNoTok(), false));
MyDoc.Validate("Document Date", JsonHelper.ValAsDate(JObject, CoreTokenMgt.GetDocDateTok(), false));
MyDoc.Insert(true);
// Überträgt Metadaten sowie benutzerdefinierte/zusätzliche Felder anhand der Core‑Zuordnungen in den Ziel‑Datensatz.
TargetVariant := MyDoc;
DocTransferMgt.ProcessAdditionalInformation(JObject, TargetVariant);
MyDoc := TargetVariant;
exit(MyDoc.RecordId());
end;
}
Hinweis:Note: DieThe Übertragungtransfer vonof Metadatenmetadata sowieand benutzerdefinierten/zusätzlichenuser-defined/additional Feldernfields istis imalready obigenincluded Beispielin bereitsthe enthaltenabove undexample basiertand aufis denbased Core‑Zuordnungstabellen.on the core mapping tables.
9) FehlerbehebungTroubleshooting (schnellequick Prüfungen)checks)
- Keine Einträge in
DXP SQZ Import Queue→ Dokumentenklassen‑Einrichtung für SQUEEZE ist unvollständig. - Core‑
DXP Documentexistiert, aber kein Source‑Datensatz → IhrCreateSource(Document)ist fehlgeschlagen oder gibtfalsezurück. - Source existiert, aber Ziel wird nicht erstellt →
CreateProcessedJsonFromSourcewird nicht aufgerufen oderDXP Target Document Processist nicht konfiguriert. - Falsches Trigger‑Verhalten beim Zuweisen →
DXP Custom Field Mapping.Validate App FieldundValidateprüfen.Validatesteuert, ob die Validierung des Ziel‑Feldes (OnValidate) ausgeführt wird.
10) Was Core automatisch macht
Wenn Sie DXP Document Mgt.UpdateDocument(...) aufrufen:
- Core speichert das „Processed JSON“ in
DXP Document.JSON Processed. - Core setzt
DXP Document.Statusauf den übergebenen Status. - Core verknüpft/aktualisiert
DXP Document.Linked-to Record Idmit dem Datensatz, den IhreDXP IDocument Processing‑Implementierung zurückgibt. - Core überträgt Core‑Attachments auf den zurückgegebenen Datensatz (und hängt typischerweise das „Processed JSON“ als
.json‑Attachment an).