Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ codeunit 148016 "Digital Vouchers Tests DK"
DigitalVoucherEntrySetupPage."Check Type".SetValue(Format(DigitalVoucherEntrySetup."Check Type"::"No Check"));
asserterror DigitalVoucherEntrySetupPage.Close();
Assert.ExpectedError(NotAllowedToChangeWhenEnforcedErr);
Clear(DigitalVoucherEntrySetupPage);
DigitalVoucherEntrySetupPage.OpenEdit();
DigitalVoucherEntrySetupPage.Filter.SetFilter("Entry Type", Format(DigitalVoucherEntrySetup."Entry Type"::"Sales Document"));
DigitalVoucherEntrySetupPage."Check Type".SetValue(Format(DigitalVoucherEntrySetup."Check Type"::"Attachment"));
DigitalVoucherEntrySetupPage.Close();
UnbindSubscription(DigVouchersEnableEnforce);
end;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,10 @@ codeunit 6134 "E-Doc. Integration Management"

#endregion

internal procedure RunOnAfterUpdateToPostedPurchaseEDocument(var EDocument: Record "E-Document"; PostedRecord: Variant; PostedDocumentNo: Code[20]; DocumentType: Enum "E-Document Type")
begin
this.OnAfterUpdateToPostedPurchaseEDocument(EDocument, PostedRecord, PostedDocumentNo, DocumentType);
end;
var
EDocumentLog: Codeunit "E-Document Log";
EDocumentProcessing: Codeunit "E-Document Processing";
Expand Down Expand Up @@ -649,4 +653,9 @@ codeunit 6134 "E-Doc. Integration Management"
local procedure OnAfterSendDocument(EDocuments: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage)
begin
end;

[IntegrationEvent(false, false)]
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
local procedure OnAfterUpdateToPostedPurchaseEDocument(var EDocument: Record "E-Document"; PostedRecord: Variant; PostedDocumentNo: Code[20]; DocumentType: Enum "E-Document Type")
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
begin
end;
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,8 @@ table 6125 "E-Doc. Data Storage"
}
}

internal procedure GetTempBlob() TempBlob: Codeunit "Temp Blob"
procedure GetTempBlob() TempBlob: Codeunit "Temp Blob"
begin
TempBlob.FromRecord(Rec, Rec.FieldNo("Data Storage"));
end;

}
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ codeunit 6103 "E-Document Subscribers"
EDocService: Record "E-Document Service";
EDocumentLog: Codeunit "E-Document Log";
EDocLogHelper: Codeunit "E-Document Log Helper";
EDocIntegrationManagement: Codeunit "E-Doc. Integration Management";
PostedSourceDocumentHeader: RecordRef;
begin
PostedSourceDocumentHeader.GetTable(PostedRecord);
Expand All @@ -681,7 +682,7 @@ codeunit 6103 "E-Document Subscribers"
EDocument.Status := Enum::"E-Document Status"::Processed;
EDocument.Modify(true);

OnAfterUpdateToPostedPurchaseEDocument(EDocument, PostedRecord, PostedDocumentNo, DocumentType);
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
EDocIntegrationManagement.RunOnAfterUpdateToPostedPurchaseEDocument(EDocument, PostedRecord, PostedDocumentNo, DocumentType);
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved

EDocService := EDocumentLog.GetLastServiceFromLog(EDocument);
EDocLogHelper.InsertLog(EDocument, EDocService, Enum::"E-Document Service Status"::"Imported Document Created");
Expand Down Expand Up @@ -789,11 +790,6 @@ codeunit 6103 "E-Document Subscribers"
Telemetry.LogMessage('0000PYF', DraftChangeTok, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, TelemetryDimensions);
end;

[IntegrationEvent(false, false)]
local procedure OnAfterUpdateToPostedPurchaseEDocument(var EDocument: Record "E-Document"; PostedRecord: Variant; PostedDocumentNo: Code[20]; DocumentType: Enum "E-Document Type")
begin
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Release Sales Document", 'OnAfterReleaseSalesDoc', '', false, false)]
local procedure OnAfterReleaseSalesDoc(var SalesHeader: Record "Sales Header"; PreviewMode: Boolean; var LinesWereModified: Boolean; SkipWhseRequestOperations: Boolean)
var
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ permissionset 5583 "Digital Voucher - Objects"
page "Digital Voucher Guide" = X,
page "Voucher Entry Source Codes" = X,
codeunit "Voucher Attach Or Note Check" = X,
codeunit "Voucher E-Document Check" = X,
codeunit "Voucher Attachment Check" = X,
codeunit "Voucher No Check" = X,
codeunit "Voucher Unknown Check" = X,
Expand Down
14 changes: 13 additions & 1 deletion src/Apps/W1/EnforcedDigitalVouchers/app/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@
"url": "https://go.microsoft.com/fwlink/?LinkId=724011",
"logo": "ExtensionLogo.png",
"contextSensitiveHelpUrl": "https://go.microsoft.com/fwlink/?linkid=2204541",
"dependencies": [],
"dependencies": [
{
"id": "e1d97edc-c239-46b4-8d84-6368bdf67c8b",
"name": "E-Document Core",
"publisher": "Microsoft",
"version": "29.0.0.0"
}
],
"screenshots": [],
"platform": "29.0.0.0",
"internalsVisibleTo": [
Expand All @@ -20,6 +27,11 @@
"name": "Enforced Digital Vouchers Test Library",
"publisher": "Microsoft"
},
{
"id": "f0eb8756-ea72-4ef8-b0de-686d2a44b259",
"name": "Enforced Digital Vouchers Tests",
"publisher": "Microsoft"
},
{
"id": "bb837764-d7cc-4b7b-898a-3ea5a1fab62f",
"name": "Enforced Digital Vouchers (DK)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,26 @@ table 5579 "Digital Voucher Entry Setup"
}
field(2; "Check Type"; Enum "Digital Voucher Check Type")
{
trigger OnValidate()
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
var
CheckTypeEDocErr: Label '%1 %2 is available only for %3 %4 or %5.', Comment = '%1 - Check type field caption, %2 - Check type value, %3 - Entry type field caption, %4 - Entry type value, %5 - Entry type value';
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
begin
if "Check Type" = "Check Type"::"E-Document" then begin
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
if not ("Entry Type" in ["Entry Type"::"Sales Document", "Entry Type"::"Purchase Document"]) then
Error(CheckTypeEDocErr, FieldCaption("Check Type"), "Check Type"::"E-Document", FieldCaption("Entry Type"), "Entry Type"::"Sales Document", "Entry Type"::"Purchase Document");
"Generate Automatically" := true;
end;
end;
}
field(3; "Generate Automatically"; Boolean)
{
trigger OnValidate()
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
var
GenerateAutoMustBeEnabledErr: Label 'Generate Automatically must be enabled when %1 is %2.', Comment = '%1 - Check type field caption, %2 - Check type value';
begin
if ("Check Type" = "Check Type"::"E-Document") and (not "Generate Automatically") then
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
Error(GenerateAutoMustBeEnabledErr, FieldCaption("Check Type"), "Check Type"::"E-Document");
end;
}
field(4; "Skip If Manually Added"; Boolean)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@ tableextension 5582 "Dig. Voucher Inc. Doc. Attach." extends "Incoming Document
{
DataClassification = SystemMetadata;
}
field(5583; "Is E-Document"; Boolean)
{
DataClassification = SystemMetadata;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,9 @@ enum 5580 "Digital Voucher Check Type" implements "Digital Voucher Check"
Caption = 'Attachment or Note';
Implementation = "Digital Voucher Check" = "Voucher Attach Or Note Check";
}
value(3; "E-Document")
{
Caption = 'E-Document';
Implementation = "Digital Voucher Check" = "Voucher E-Document Check";
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
Expand All @@ -24,8 +24,10 @@ using Microsoft.Service.History;
using Microsoft.Service.Posting;
using System.Email;
using System.Environment.Configuration;
using System.IO;
using System.Media;
using System.Reflection;
using System.Telemetry;
using System.Utilities;

codeunit 5579 "Digital Voucher Impl."
Expand Down Expand Up @@ -272,6 +274,142 @@ codeunit 5579 "Digital Voucher Impl."
exit(not IncomingDocumentAttachment.IsEmpty());
end;

local procedure AttachIncomingEDocument(EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob")
var
DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup";
IncomingDocumentAttachment: Record "Incoming Document Attachment";
EDocumentHelper: Codeunit "E-Document Processing";
ImportAttachmentIncDoc: Codeunit "Import Attachment - Inc. Doc.";
FeatureTelemetry: Codeunit "Feature Telemetry";
FileNameTok: Label 'E-Document_%1.xml', Locked = true;
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
RecordLinkTxt: Text;
begin
if not DigitalVoucherFeature.IsFeatureEnabled() then
exit;

GetDigitalVoucherEntrySetup(DigitalVoucherEntrySetup, "Digital Voucher Entry Type"::"Sales Document");
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
if DigitalVoucherEntrySetup."Check Type" <> DigitalVoucherEntrySetup."Check Type"::"E-Document" then
exit;

if not (EDocument."Document Type" in [
EDocument."Document Type"::"Sales Invoice",
EDocument."Document Type"::"Sales Credit Memo",
EDocument."Document Type"::"Sales Order",
EDocument."Document Type"::"Sales Quote",
EDocument."Document Type"::"Sales Return Order"]) then
exit;

RecordLinkTxt := EDocumentHelper.GetRecordLinkText(EDocument);
IncomingDocumentAttachment.SetRange("Document No.", EDocument."Document No.");
IncomingDocumentAttachment.SetRange("Posting Date", EDocument."Posting Date");
IncomingDocumentAttachment.SetContentFromBlob(TempBlob);
if not ImportAttachmentIncDoc.ImportAttachment(IncomingDocumentAttachment, StrSubstNo(FileNameTok, RecordLinkTxt), TempBlob) then begin
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
FeatureTelemetry.LogError('0000SMC', 'E-Documents', 'AttachIncomingEDocument', 'Cannot import attachment');
exit;
end;

IncomingDocumentAttachment."Is E-Document" := true;
IncomingDocumentAttachment.Modify(false);
end;

local procedure AttachOutgoingEDocument(var EDocument: Record "E-Document"; PostedRecord: Variant)
var
DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup";
RecRef: RecordRef;
DocNo: Code[20];
PostingDate: Date;
DocType: Text;
begin
if not DigitalVoucherFeature.IsFeatureEnabled() then
exit;

GetDigitalVoucherEntrySetup(DigitalVoucherEntrySetup, "Digital Voucher Entry Type"::"Purchase Document");
if DigitalVoucherEntrySetup."Check Type" <> DigitalVoucherEntrySetup."Check Type"::"E-Document" then
exit;

if not (EDocument."Document Type" in [
EDocument."Document Type"::"Purchase Invoice",
EDocument."Document Type"::"Purchase Credit Memo",
EDocument."Document Type"::"Purchase Order",
EDocument."Document Type"::"Purchase Quote",
EDocument."Document Type"::"Purchase Return Order"]) then
exit;

RecRef.GetTable(PostedRecord);
DigitalVoucherEntry.GetDocNoAndPostingDateFromRecRef(DocType, DocNo, PostingDate, RecRef);
AttachPurchaseEDocument(EDocument, DocNo, PostingDate);
end;

local procedure AttachPurchaseEDocument(EDocument: Record "E-Document"; DocumentNo: Code[20]; PostingDate: Date)
var
EDocDataStorage: Record "E-Doc. Data Storage";
IncomingDocumentAttachment: Record "Incoming Document Attachment";
ImportAttachmentIncDoc: Codeunit "Import Attachment - Inc. Doc.";
TempBlob: Codeunit "Temp Blob";
FeatureTelemetry: Codeunit "Feature Telemetry";
EDocumentFileNameLbl: Label 'E-Document_%1.%2', Comment = '%1 = E-Document Entry No., %2 = File Format', Locked = true;
FileName: Text[250];
begin
if EDocument."Unstructured Data Entry No." = 0 then
exit;

if not EDocDataStorage.Get(EDocument."Unstructured Data Entry No.") then
exit;

TempBlob := EDocDataStorage.GetTempBlob();
if not TempBlob.HasValue() then
exit;

if EDocument."File Name" <> '' then
FileName := CopyStr(EDocument."File Name", 1, MaxStrLen(FileName))
else
FileName := StrSubstNo(EDocumentFileNameLbl, EDocument."Entry No", EDocDataStorage."File Format");

IncomingDocumentAttachment.SetRange("Document No.", DocumentNo);
IncomingDocumentAttachment.SetRange("Posting Date", PostingDate);
IncomingDocumentAttachment.SetContentFromBlob(TempBlob);
if not ImportAttachmentIncDoc.ImportAttachment(IncomingDocumentAttachment, FileName, TempBlob) then begin
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
FeatureTelemetry.LogError('0000SMD', 'E-Documents', 'AttachPurchaseEDocument', 'Cannot import attachment');
exit;
end;

IncomingDocumentAttachment."Is E-Document" := true;
IncomingDocumentAttachment.Modify(false);

if EDocDataStorage."File Format" = EDocDataStorage."File Format"::PDF then begin
FileName := StrSubstNo(EDocumentFileNameLbl, EDocument."Entry No", EDocDataStorage."File Format"::XML);
ExtractXMLFromPDF(TempBlob, FileName, IncomingDocumentAttachment);
end;
end;

local procedure ExtractXMLFromPDF(var TempBlob: Codeunit System.Utilities."Temp Blob"; FileName: Text[250]; var IncomingDocumentAttachment: Record "Incoming Document Attachment")
var
ImportAttachmentIncDoc: Codeunit "Import Attachment - Inc. Doc.";
PDFDocument: Codeunit "PDF Document";
ExtractedXmlBlob: Codeunit "Temp Blob";
FeatureTelemetry: Codeunit "Feature Telemetry";
PdfInStream: InStream;
begin
TempBlob.CreateInStream(PdfInStream);
if not PDFDocument.GetDocumentAttachmentStream(PdfInStream, ExtractedXmlBlob) then begin
FeatureTelemetry.LogError('0000SME', 'E-Documents', 'ExtractXMLFromPDF', 'Cannot extract XML from PDF');
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
exit;
end;

if not ExtractedXmlBlob.HasValue() then
exit;

IncomingDocumentAttachment.Default := false;
IncomingDocumentAttachment."Main Attachment" := false;
if not ImportAttachmentIncDoc.ImportAttachment(IncomingDocumentAttachment, FileName, ExtractedXmlBlob) then begin
FeatureTelemetry.LogError('0000SMF', 'E-Documents', 'ExtractXMLFromPDF', 'Cannot import extracted XML');
exit;
end;

IncomingDocumentAttachment."Is E-Document" := true;
IncomingDocumentAttachment.Modify(false);
end;

local procedure FilterIncomingDocumentRecordFromRecordRef(var IncomingDocumentAttachment: Record "Incoming Document Attachment"; var IncomingDocument: Record "Incoming Document"; MainRecordRef: RecordRef): Boolean
begin
Clear(IncomingDocument);
Expand Down Expand Up @@ -717,6 +855,7 @@ codeunit 5579 "Digital Voucher Impl."
local procedure ExcludeDigitalVouchersOnAttachIncomingDocumentsOnAfterSetFilter(var IncomingDocumentAttachment: Record "Incoming Document Attachment")
begin
IncomingDocumentAttachment.SetRange("Is Digital Voucher", false);
IncomingDocumentAttachment.SetRange("Is E-Document", false);
end;

[EventSubscriber(ObjectType::Table, Database::"Digital Voucher Setup", 'OnBeforeDeleteEvent', '', false, false)]
Expand All @@ -739,6 +878,21 @@ codeunit 5579 "Digital Voucher Impl."
CopyDigitalVoucherToCorrectiveDocument("Digital Voucher Entry Type"::"Sales Document", SalesInvoiceHeader, SalesHeader."No.", SalesHeader."Posting Date");
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Export", OnExportEDocumentAfterCreateEDocument, '', false, false)]
local procedure EDocExportOnExportEDocumentAfterCreateEDocument(EDocument: Record "E-Document"; SourceDocumentHeaderMapped: RecordRef; SourceDocumentLineMapped: RecordRef; var TempBlob: Codeunit "Temp Blob"; Success: Boolean)
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
begin
if not Success then
exit;

AttachIncomingEDocument(EDocument, TempBlob);
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Integration Management", OnAfterUpdateToPostedPurchaseEDocument, '', false, false)]
local procedure EDocumentSubscribers_OnAfterUpdateToPostedPurchaseEDocument(var EDocument: Record "E-Document"; PostedRecord: Variant; DocumentType: Enum "E-Document Type")
Comment thread
jzaksauskas marked this conversation as resolved.
Resolved
begin
AttachOutgoingEDocument(EDocument, PostedRecord);
end;

[IntegrationEvent(false, false)]
local procedure OnGenerateDigitalVoucherForDocumentOnCaseElse(RecRef: RecordRef)
begin
Expand Down
Loading
Loading