Events when validating a SQUEEZE document (Validate action)
Target audience
This documentation is aimed at third-party developers who want to run their own logic when a user triggers the Validate action on the DXP SQZ Document v2 page (page 70954659) – for example additional custom checks before validation, setting further values on the SQUEEZE document, or follow-up actions on the target document that was created.
The events described here are available from SQUEEZE for Dynamics 365 BC version 2.50.
Context: what happens when you choose Validate?
The Validate action calls two routines of the document page in sequence:
1) CheckPlausibility()
Runs the plausibility check of the respective document class and updates the plausibility entries in the lower part of the page. This routine runs not only when you choose Validate, but after almost every field change. It is therefore not a suitable hook for "once, on validation".
To extend the check itself, use the already documented events OnBeforeDoPlausibilityChecks, OnAfterDoHeaderPlausibilityChecks, OnAfterDoLinePlausibilityChecks and OnAfterDoPlausibilityChecks.
2) FinishValidation()
Stops with an error message as long as plausibility entries are still open, handles the duplicate check where applicable, and then calls the ValidateSQUEEZEDocument method of the DXP SQZ Document Mgt. codeunit (70954632). That is where the processed JSON is created, the Core document (DXP Document) is processed further, the target document is created and the SQUEEZE document is completed.
Both events described here are raised in DXP SQZ Document Mgt.ValidateSQUEEZEDocument. They therefore apply uniformly to:
- the Validate action on DXP SQZ Document v2 (
70954659), - the Validate action on DXP SQZ Document (Generic) (
70954670) and the older document pages, - the automatic validation (for example from the processing queue).
There is deliberately no event directly on the action. If you want to distinguish between a manual click and automatic validation, evaluate the AutomaticValidation parameter.
Event matrix (overview)
| Area | Event | Timing | Control | Typical use cases |
|---|---|---|---|---|
DXP SQZ Document Mgt. |
OnBeforeValidateSQUEEZEDocument |
After the plausibility and duplicate checks, before the processed JSON is created and the target document is generated | var IsHandled: Boolean cancels the validation; var DocHeader allows changes to the document |
Custom additional checks with cancellation, filling fields, starting an approval workflow, querying external systems |
DXP SQZ Document Mgt. |
OnAfterValidateSQUEEZEDocument |
After the Core document has been processed and the target document has been created, before the validation dialog | Cancellation not possible | Post-processing the target document, writing custom log tables, sending notifications, informing third-party systems |
Distinction from OnAfterWriteProcessedJsonToBlob
For logic that runs after validation, a Core event already exists. It is described on the page Creating custom documents (custom processing):
[IntegrationEvent(false, false)]
local procedure OnAfterWriteProcessedJsonToBlob(var Document: Record "DXP Document"; var ProcessedJSONObj: JsonObject)
It is raised in the DXP Document Mgt. codeunit (Core) after the processed JSON has been written to the Core document – within the validation process, so it fires when Validate is chosen as well.
OnAfterWriteProcessedJsonToBlob (Core) |
OnAfterValidateSQUEEZEDocument (SQUEEZE) |
|
|---|---|---|
| Raised in | DXP Document Mgt. |
DXP SQZ Document Mgt. |
| Applies to | all Core documents – including those from other DEXPRO source apps. You have to filter by document class yourself. | SQUEEZE documents only |
| Context | DXP Document and the processed JSON |
additionally the complete DXP SQZ Document Header with all recognised values, order matching and splitting information |
| Manual vs. automatic | cannot be distinguished | can be distinguished via AutomaticValidation |
| Timing | directly after the JSON is written, still inside the Core processing | at the end of the validation, after the SQUEEZE document has been completed |
| JSON modifiable | yes (var ProcessedJSONObj) |
no |
Recommendation:
- You want to modify the processed JSON or hand a document over to custom processing →
OnAfterWriteProcessedJsonToBlob. - You want to evaluate SQUEEZE-specific values or react to manual validation only →
OnAfterValidateSQUEEZEDocument. - You want to intervene before the target document is created, or to cancel the validation →
OnBeforeValidateSQUEEZEDocument. There is no Core equivalent for this.
OnBeforeValidateSQUEEZEDocument
[IntegrationEvent(false, false)]
local procedure OnBeforeValidateSQUEEZEDocument(var DocHeader: Record "DXP SQZ Document Header"; AutomaticValidation: Boolean; var IsHandled: Boolean)
| Parameter | Description |
|---|---|
var DocHeader |
The SQUEEZE document to be validated. Changes to fields are written afterwards and flow into the target document. |
AutomaticValidation |
false when Validate is chosen, true for automatic validation. |
var IsHandled |
Set to true to cancel the validation. The SQUEEZE document stays open, unchanged. |
The event is raised after:
- the document has been re-read and has neither the Deleted nor the Rejected status,
- the plausibility check succeeded, in the case of automatic validation,
and before the processed JSON is created. At this point the target document does not exist yet.
OnAfterValidateSQUEEZEDocument
[IntegrationEvent(false, false)]
local procedure OnAfterValidateSQUEEZEDocument(DocHeader: Record "DXP SQZ Document Header"; CoreDocument: Record "DXP Document"; AutomaticValidation: Boolean)
| Parameter | Description |
|---|---|
DocHeader |
The validated SQUEEZE document. At this point its status is already Deleted – this is the regular final state of a validated document and not an error. |
CoreDocument |
The corresponding Core document (DXP Document), including Status and Linked-to Record Id of the target document that was created. |
AutomaticValidation |
false when Validate is chosen, true for automatic validation. |
Use the Core document to determine whether the target document was actually created:
CoreDocument.Status = CoreDocument.Status::Transferred– the target document was created andCoreDocument."Linked-to Record Id"points to it.CoreDocument.Status = CoreDocument.Status::"Custom Processing"– the document was handed over to custom processing; no standard target document exists.
Important: custom checks do not belong in this event
OnBeforeValidateSQUEEZEDocument is the wrong place for checks that are meant to prevent a validation. An Error raised here only appears as a dialog after the user chose Validate – so the user learns about the problem at the very end of their work. Use one of the two approaches below instead. Both make the problem appear as a plausibility entry and disable the Validate action.
Approach 1 (no development): plausibility rule group
In the document class setup, define rules under Plausibility Rule Group. Every active and currently valid rule whose conditions match describes a problem and automatically creates a plausibility entry. Rules that reference the document lines are evaluated per line, so the entry points to the line concerned.
For checks such as "Shortcut Dimension 1 Code must not be empty" this is the preferred approach – no code, no extension, maintainable by the user.
Approach 2 (with development): OnAfterDoPlausibilityChecks
This event is published by all document classes with var TempPlausibilityCheckEntry and is therefore the reliable route. You insert your entry into the temporary record directly:
codeunit 50100 "My SQZ Plausibility Checks"
{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"DXP SQZ P. Inv/Crdt Memo Impl.",
'OnAfterDoPlausibilityChecks', '', false, false)]
local procedure OnAfterChecks(DocHeader: Record "DXP SQZ Document Header"; var TempPlausibilityCheckEntry: Record "DXP Plausibility Check Entry" temporary)
var
CostCenterMissingLbl: Label 'Please enter a cost center.';
begin
if DocHeader."Shortcut Dimension 1 Code" <> '' then
exit;
AddEntry(TempPlausibilityCheckEntry, CostCenterMissingLbl, DocHeader.RecordId(), 0);
end;
local procedure AddEntry(var TempPlausibilityCheckEntry: Record "DXP Plausibility Check Entry" temporary; MessageText: Text; LinkedToRecId: RecordId; LookupPageId: Integer)
var
NewEntryNo: Integer;
begin
NewEntryNo := 1;
TempPlausibilityCheckEntry.Reset();
TempPlausibilityCheckEntry.SetCurrentKey("Entry No.");
if TempPlausibilityCheckEntry.FindLast() then
NewEntryNo := TempPlausibilityCheckEntry."Entry No." + 1;
TempPlausibilityCheckEntry.Init();
TempPlausibilityCheckEntry."Entry No." := NewEntryNo;
TempPlausibilityCheckEntry.Text := CopyStr(MessageText, 1, MaxStrLen(TempPlausibilityCheckEntry.Text));
TempPlausibilityCheckEntry."Linked to Record Id" := LinkedToRecId;
TempPlausibilityCheckEntry."Lookup Page Id" := LookupPageId;
if TempPlausibilityCheckEntry.Insert() then;
end;
}
The publisher object depends on the document class:
| Document class | Codeunit |
|---|---|
| Purchase invoice / credit memo | DXP SQZ P. Inv/Crdt Memo Impl. |
| Order confirmation | DXP SQZ P. Order Conf. Impl. |
| Generic document classes | DXP SQZ Document Mgt. |
Set Linked to Record Id and Lookup Page Id (for lines: Page::"DXP SQZ Document Subform") so that the plausibility entry becomes clickable and jumps to the record concerned.
Alternative: OnAfterDoHeaderPlausibilityChecks
PlausibilityCheck.AddPlausibilityCheckEntry(...) offers a more convenient API that saves you the manual insert into the temporary record:
[EventSubscriber(ObjectType::Codeunit, Codeunit::"DXP SQZ P. Inv/Crdt Memo Impl.",
'OnAfterDoHeaderPlausibilityChecks', '', false, false)]
local procedure OnAfterHeaderChecks(DocHeader: Record "DXP SQZ Document Header"; var PlausibilityCheck: Codeunit "DXP Plausiblity Check Mgt.")
var
CostCenterMissingLbl: Label 'Please enter a cost center.';
begin
if DocHeader."Shortcut Dimension 1 Code" = '' then
PlausibilityCheck.AddPlausibilityCheckEntry(CostCenterMissingLbl, 0);
end;
OnAfterDoLinePlausibilityChecks works the same way for line checks; the AddPlausibilityCheckEntry(Text; LinkedToRecId; LookupPageId) overload makes the entry clickable.
Caution for the order confirmation document class: in
DXP SQZ P. Order Conf. Impl., the eventsOnBeforeDoHeaderPlausibilityChecks,OnBeforeDoLinePlausibilityChecks,OnAfterDoHeaderPlausibilityChecksandOnAfterDoLinePlausibilityCheckswere originally published withoutvaron thePlausibilityCheckparameter. A subscriber receives a copy there, so entries it adds are lost. For this document class, use the variants with theV2suffix from version 2.50 onwards – for exampleOnAfterDoHeaderPlausibilityChecksV2. Their signature is identical to the events of the other document classes. The old events remain available but are marked as obsolete.
Example 1: adding values before the handover to the target document
[EventSubscriber(ObjectType::Codeunit, Codeunit::"DXP SQZ Document Mgt.",
'OnBeforeValidateSQUEEZEDocument', '', false, false)]
local procedure OnBeforeValidateSetPostingDescription(var DocHeader: Record "DXP SQZ Document Header"; AutomaticValidation: Boolean; var IsHandled: Boolean)
begin
if DocHeader."Posting Description" = '' then
DocHeader."Posting Description" := CopyStr(DocHeader."Document Reference", 1, MaxStrLen(DocHeader."Posting Description"));
// No Modify required – the document is written afterwards.
end;
Modifying the target document: please use the Core events
If you want to change the target document that was created, neither event on this page is the right place. Core provides events that hand you the target document directly – most of them even as a typed Purchase Header, so you can skip the detour via Linked-to Record Id and a RecordRef. These events are described on the page Events after the creation of a Core document (DXP Document):
| Target document | Codeunit | Event |
|---|---|---|
| Purchase invoice / credit memo | DXP P. Inv. CredMemo. Creation |
OnAfterProcessStandardDocument(JObject; DocRecRef) |
| Purchase document, general | DXP Document Transfer Mgt. |
OnAfterCreatePurchaseDoc(var JObject; PurchaseHeader) |
| Purchase header | DXP Document Transfer Mgt. |
OnAfterCreatePurchaseHeader(var JObject; PurchaseHeader) |
| Purchase order | DXP P. Order Creation |
OnAfterCreatePurchaseOrder(var JObject; var PurchaseHeader) |
| Order confirmation | DXP P. Order Confirmation |
OnAfterProcessStandardDocument(JObject; var PurchaseHeader) |
OnAfterValidateSQUEEZEDocument is only the better choice if you additionally need values from the DXP SQZ Document Header – for example recognised values, order matching or splitting information that is not contained in the JSON of the Core document.
Example 2: reacting to manual validation only
[EventSubscriber(ObjectType::Codeunit, Codeunit::"DXP SQZ Document Mgt.",
'OnAfterValidateSQUEEZEDocument', '', false, false)]
local procedure OnAfterValidateNotifyUser(DocHeader: Record "DXP SQZ Document Header"; CoreDocument: Record "DXP Document"; AutomaticValidation: Boolean)
var
ValidatedMsg: Label 'Document %1 has been forwarded.', Comment = '%1 = SQUEEZE document no.';
begin
if AutomaticValidation then
exit;
if not GuiAllowed() then
exit;
Message(ValidatedMsg, DocHeader."No.");
end;
Notes and limitations
- No dialogs in automatic processing. Always check
AutomaticValidationandGuiAllowed()beforeMessage,ConfirmorPage.RunModal. Otherwise the processing queue runs into an error. OnBeforeValidateSQUEEZEDocumentruns after the plausibility check. Custom checks that are supposed to appear in the page's plausibility entries and to disable the Validate action belong inOnAfterDoHeaderPlausibilityChecksorOnAfterDoLinePlausibilityChecksinstead.IsHandled := truecancels completely. No target document is created, the Core document stays unchanged and the SQUEEZE document keeps its status. The user does not get a message – issue one yourself if required.- No event for deleted or rejected documents. If the document has the Deleted or Rejected status, validation ends beforehand and neither event is raised.
OnAfterValidateSQUEEZEDocumentruns after aCommit. AnErrorin a subscriber does not roll the validation back; it leaves a validated document plus an error message for the user.
Related pages
- Creating custom documents (custom processing)
- Events after the creation of a SQUEEZE document (CreateSource)
- Events after the creation of a Core document (DXP Document)
- Rule-based next process step (routing documents into custom processing)
No comments to display
No comments to display