<< Click to Display Table of Contents >> Navigation: Zetadocs SDK Guide > Creating a Per Tenant Extension > Document Queues Automation |
Zetadocs AutoLink allows you to archive the documents from the Zetadocs Document Queue against the records in Business Central. The logic is usually reliant on use of barcodes and will require a Per Tenant Extension and to be enabled in the Document Queue Settings.
Autolink Example
The following code illustrates how use the OnBeforeCapture event to autolink a document in the Zetadocs Document Queue to a Business Central record by barcodes:
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Zetadocs Customize", 'OnBeforeCapture', '', true, true)]
local procedure OnBeforeCapture(var onBeforeCaptureHandler: Codeunit "Zetadocs OnBeforeCapture")
var
PurchaseHeader: Record "Purchase Header";
SalesHeader: Record "Sales Header";
DocQueueNo: Record "Zetadocs Document Queue";
documentKeys: List of [Text];
docKey: Text;
documentBarcodes: List of [Text];
barcode: Text;
documentLink: Text;
barcodeFilter: Text;
valuePairs: JsonArray;
begin
//Get the list of documents
onBeforeCaptureHandler.GetDocumentIds(documentKeys);
//If we have multiple queues makes sure we're processing the correct document type
onBeforeCaptureHandler.GetDocumentQueueSettings(DocQueueNo);
case DocQueueNo."No." of
'ZDQ0001':
begin
//Business logic to assign the documents to a record
foreach docKey in documentKeys do begin
onBeforeCaptureHandler.GetDocumentBarcodes(docKey, documentBarcodes);
// Loop over the barcodes and stop when the required one is found.
foreach barcode in documentBarcodes do begin
barcodeFilter := CopyStr(barcode, 1, 5);
documentLink := CopyStr(barcode, 6);
case barcodeFilter of
'ZD-SO':
begin
Salesheader.Reset;
SalesHeader."Document Type" := SalesHeader."Document Type"::Order;
SalesHeader."No." := CopyStr(documentLink, 1, MaxStrLen(SalesHeader."No."));
if (Salesheader.Find()) then begin
onBeforeCaptureHandler.SetRecordId(docKey, Salesheader.RecordId);
//Exit the foreach if we have a match
break;
end;
end;
end;
end;
end;
end;
'ZDQ0002':
begin
//Business logic to assign the documents to a record
foreach docKey in documentKeys do begin
onBeforeCaptureHandler.GetDocumentBarcodes(docKey, documentBarcodes);
// Loop over the barcodes and stop when the required one is found.
foreach barcode in documentBarcodes do begin
barcodeFilter := CopyStr(barcode, 1, 5);
documentLink := CopyStr(barcode, 6);
case barcodeFilter of
'ZD-PO':
begin
PurchaseHeader.Reset;
PurchaseHeader."Document Type" := PurchaseHeader."Document Type"::Order;
PurchaseHeader."No." := CopyStr(documentLink, 1, MaxStrLen(PurchaseHeader."No."));
if (PurchaseHeader.Find()) then begin
onBeforeCaptureHandler.SetRecordId(docKey, PurchaseHeader.RecordId);
//Exit the foreach if we have a match
break;
end;
end;
end;
end;
end;
end;
'ZDQ0003':
begin
//Business logic to give extra logic for automatic processing and form filling
foreach docKey in documentKeys do begin
onBeforeCaptureHandler.GetDocumentBarcodes(docKey, documentBarcodes);
valuePairs := onBeforeCaptureHandler.GetRecognisedKeyValuePairs(docKey);
//Insert logic based on values of valuePairs and decide the Vendor accordingly
onBeforeCaptureHandler.SetVendor(docKey, 'NewCaSup');
end;
end;
end;
end;
Scheduled AutoLink Example
Once covered by AutoLink, the document queue processing can be scheduled using a Business Central Job Queue Entry.
To do so, you will need to:
Consolidate record information after Zetadocs Capture Example
The following code illustrates how use the OnAfterGenerateCaptureResults event to add Dimension information to a Business Central record processed using Zetadocs Capture based on the information of the record matched, or on the Shipping Address or barcodes. As well as extract the the Job No from the recognised KeyValuePairs and set it on the record lines :
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Zetadocs Customize", 'OnAfterGenerateCaptureResults', '', true, true)]
local procedure OnAfterGenerateCaptureResults(var onAfterGenerateCaptureResultsHandler: Codeunit "Zdd OnAfterGenerateCaptureRes")
var
purchaseHeader: record "Purchase Header";
purchaseLines: Record "Purchase Line";
orderLine: Record "Purchase Line";
recId: RecordId;
shippingAddress: Text;
barcodes: List of [Text];
firstBarcode: Text;
lineDimensionsSet: Boolean;
recognisedKeyValuePairs: JsonArray;
jobNo: Text;
begin
onAfterGenerateCaptureResultsHandler.GetGeneratedRecordId(recId);
case recId.TableNo of
38:
begin
if (purchaseHeader.Get(recId)) then begin
purchaseLines.SetFilter(purchaseLines."Document No.", purchaseHeader."No.");
if (purchaseLines.Find('-')) then
repeat
if (orderLine.Get("Purchase Document Type"::Order, purchaseLines."Order No.", purchaseLines."Order Line No.")) then begin
purchaseLines.Description := orderLine.Description;
SetDimension(1, orderLine."Shortcut Dimension 1 Code", purchaseLines);
SetDimension(2, orderLine."Shortcut Dimension 2 Code", purchaseLines);
purchaseLines.Modify();
if (jobNo <> '') then begin
purchaseLines."Job No." := jobNo;
purchaseLines."Job Task No." := CopyStr(jobNo, 1, MaxStrLen(PurchaseHeader."No."));
purchaseLines.Modify();
end;
lineDimensionsSet := true;
end;
until purchaseLines.Next() = 0
end;
if (lineDimensionsSet = false) then begin
shippingAddress := onAfterGenerateCaptureResultsHandler.GetShippingAddressInput();
if shippingAddress <> '' then begin
if shippingAddress.Contains('Ashford Street London W2 8HG') then begin
SetDimension(1, 'ADM', purchaseHeader);
end else begin
SetDimension(1, 'PROD', purchaseHeader);
end;
purchaseHeader.Modify();
end;
onAfterGenerateCaptureResultsHandler.GetDocumentBarcodes(barcodes);
if (barcodes.Count <> 0) then begin
firstBarcode := barcodes.Get(1);
if firstBarcode.Contains('SO-') then begin
SetDimension(1, 'ADM', purchaseHeader);
end else begin
SetDimension(1, 'PROD', purchaseHeader);
end;
purchaseHeader.Modify();
end;
end;
end;
end;
end;
local procedure SetDimension(ShortcutDimensionIndex: integer; ShortcutDimensionValueCode: Code[20]; var PurchaseLine: Record "Purchase Line")
begin
// PurchaseHeader.SetHideValidationDialog(true);
//Values from Demo Business Central
// [1]:'DEPARTMENT'
// [2]:'PROJECT'
// [3]:'CUSTOMERGROUP'
// [4]:'AREA'
// [5]:'BUSINESSGROUP'
// [6]:'SALESCAMPAIGN'
// [7]:''
// [8]:''
case ShortcutDimensionIndex of
1:// Set Shortcut 1
if PurchaseLine."Shortcut Dimension 1 Code" <> ShortcutDimensionValueCode then begin
PurchaseLine."Shortcut Dimension 1 Code" := ShortcutDimensionValueCode;
PurchaseLine.VALIDATE("Shortcut Dimension 1 Code");
end;
2:// Set Shortcut 2
if PurchaseLine."Shortcut Dimension 2 Code" <> ShortcutDimensionValueCode then begin
PurchaseLine."Shortcut Dimension 2 Code" := ShortcutDimensionValueCode;
PurchaseLine.VALIDATE("Shortcut Dimension 2 Code");
end;
else begin
PurchaseLine.ValidateShortcutDimCode(ShortcutDimensionIndex, ShortcutDimensionValueCode);
end;
end;
end;
local procedure SetDimension(ShortcutDimensionIndex: integer; ShortcutDimensionValueCode: Code[20]; var PurchaseHeader: Record "Purchase Header")
begin
PurchaseHeader.SetHideValidationDialog(true);
//Values from Demo Business Central
// [1]:'DEPARTMENT'
// [2]:'PROJECT'
// [3]:'CUSTOMERGROUP'
// [4]:'AREA'
// [5]:'BUSINESSGROUP'
// [6]:'SALESCAMPAIGN'
// [7]:''
// [8]:''
case ShortcutDimensionIndex of
1:// Set Shortcut 1
if PurchaseHeader."Shortcut Dimension 1 Code" <> ShortcutDimensionValueCode then begin
PurchaseHeader."Shortcut Dimension 1 Code" := ShortcutDimensionValueCode;
PurchaseHeader.VALIDATE("Shortcut Dimension 1 Code");
end;
2:// Set Shortcut 2
if PurchaseHeader."Shortcut Dimension 2 Code" <> ShortcutDimensionValueCode then begin
PurchaseHeader."Shortcut Dimension 2 Code" := ShortcutDimensionValueCode;
PurchaseHeader.VALIDATE("Shortcut Dimension 2 Code");
end;
else begin
PurchaseHeader.ValidateShortcutDimCode(ShortcutDimensionIndex, ShortcutDimensionValueCode);
end;
end;
end;
local procedure GetFormRecogniserValue(RecognisedKeyValuePairs: JsonArray; searchKey: Text): Text
var
numItems: Integer;
Index: Integer;
Jtoken: JsonToken;
tokenTemp: JsonToken;
recognisedValue: Text;
valueTemp: Text;
begin
numItems := RecognisedKeyValuePairs.Count;
Index := 0;
if (numItems > 0) then begin
repeat begin
RecognisedKeyValuePairs.Get(Index, JToken);
if (Jtoken.AsObject().Get('Key', tokenTemp)) then begin
valueTemp := tokenTemp.AsValue().AsText().ToUpper();
if (valueTemp.StartsWith(searchKey.ToUpper())) then begin
if (Jtoken.AsObject().Get('Value', tokenTemp)) then recognisedValue := tokenTemp.AsValue().AsText();
end;
end;
Index := Index + 1;
end
until (numItems = Index) or (recognisedValue <> '');
exit(recognisedValue);
end;
Refine the document information available for Zetadocs Capture Ap Automation Example
The following code illustrates how use the OnBeforeCapture event to update the Vendor name based associated with a document to streamline the automatic processing of the documents :
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Zetadocs Customize", 'OnBeforeCapture', '', true, true)]
procedure OnBeforeCapture(var onBeforeCaptureHandler: Codeunit "Zetadocs OnBeforeCapture")
var
documentKeys: List of [Text];
docKey: Text;
valuePairs: JsonArray;
valueText: Text;
begin
//Get the list of documents
onBeforeCaptureHandler.GetDocumentIds(documentKeys);
//Business logic to give extra logic for automatic processing and form filling
foreach docKey in documentKeys do begin
onBeforeCaptureHandler.GetDocumentBarcodes(docKey, documentBarcodes);
valuePairs := onBeforeCaptureHandler.GetRecognisedKeyValuePairs(docKey);
//Insert logic based on values of valuePairs and decide the Vendor accordingly
valueText := GetFormRecogniserValue(valuePairs, 'Subcontractor');
onBeforeCaptureHandler.SetVendor(docKey, valueText);
end;
end;
local procedure GetFormRecogniserValue(RecognisedKeyValuePairs: JsonArray; searchKey: Text): Text
var
numItems: Integer;
Index: Integer;
Jtoken: JsonToken;
tokenTemp: JsonToken;
recognisedValue: Text;
valueTemp: Text;
begin
numItems := RecognisedKeyValuePairs.Count;
Index := 0;
if (numItems > 0) then begin
repeat begin
RecognisedKeyValuePairs.Get(Index, JToken);
if (Jtoken.AsObject().Get('Key', tokenTemp)) then begin
valueTemp := tokenTemp.AsValue().AsText().ToUpper();
if (valueTemp.StartsWith(searchKey.ToUpper())) then begin
if (Jtoken.AsObject().Get('Value', tokenTemp)) then recognisedValue := tokenTemp.AsValue().AsText();
end;
end;
Index := Index + 1;
end
until (numItems = Index) or (recognisedValue <> '');
exit(recognisedValue);
end;
Consolidate record information after Zetadocs Capture Example for VAT exempt companies
The following code illustrates how use the OnAfterGenerateCaptureResults event to add the Tax amount directly in the line Direct Cost to bypass the VAT/TAX handling from Business Central:
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Zetadocs Customize", 'OnAfterGenerateCaptureResults', '', true, true)]
local procedure SpreadTaxProportionallyToLineTotal(var onAfterGenerateCaptureResultsHandler: Codeunit "Zdd OnAfterGenerateCaptureRes")
var
purchaseHeader: Record "Purchase Header";
purchaseLines: Record "Purchase Line";
recId: RecordId;
taxAmount: Decimal;
adjustedTax: Decimal;
invoiceTotal: Decimal;
lineAdjustment: Decimal;
previousLineAmount: Decimal;
begin
taxAmount := onAfterGenerateCaptureResultsHandler.GetInvoiceTax();
onAfterGenerateCaptureResultsHandler.GetGeneratedRecordId(recID);
purchaseHeader.get(recId);
purchaseLines.SetFilter("Document No.", purchaseHeader."No.");
purchaseLines.SetFilter(Quantity, '<>0');
if (purchaseLines.Find('-')) then
repeat
case purchaseLines.type of
purchaseLines.type::"G/L Account",
purchaseLines.type::Item,
purchaseLines.type::"Fixed Asset":
begin
invoiceTotal := invoiceTotal + purchaseLines.amount;
end;
end;
until purchaseLines.Next() = 0;
if (invoiceTotal > 0) then begin
if (purchaseLines.Find('-')) then
repeat
case purchaseLines.type of
purchaseLines.type::"G/L Account",
purchaseLines.type::Item,
purchaseLines.type::"Fixed Asset":
begin
lineAdjustment := taxAmount * purchaseLines.amount / invoiceTotal;
previousLineAmount := purchaseLines."Line Amount";
purchaseLines."Direct Unit Cost" := purchaseLines."Direct Unit Cost" + (lineAdjustment / purchaseLines.Quantity);
purchaseLines.Validate("Direct Unit Cost");
purchaseLines.Modify();
adjustedTax := adjustedTax + (purchaseLines."Line Amount" - previousLineAmount);
end;
end;
until purchaseLines.Next() = 0;
end;
if ((taxAmount - adjustedTax) <> 0) then begin
if (purchaseLines.Find('-')) then
repeat
case purchaseLines.type of
purchaseLines.type::"G/L Account",
purchaseLines.type::Item,
purchaseLines.type::"Fixed Asset":
begin
purchaseLines."Direct Unit Cost" := purchaseLines."Direct Unit Cost" + ((taxAmount - adjustedTax) / purchaseLines.Quantity);
purchaseLines.Validate("Direct Unit Cost");
purchaseLines.Modify();
end;
end;
until (purchaseLines.Next() = 0) or ((taxAmount - adjustedTax) = 0);
end;
end;