diff --git a/Apps/W1/EnforcedDigitalVouchers/app/Permissions/DigitalVoucherObjects.PermissionSet.al b/Apps/W1/EnforcedDigitalVouchers/app/Permissions/DigitalVoucherObjects.PermissionSet.al
index b9ed6c23e5..c23da3955c 100644
--- a/Apps/W1/EnforcedDigitalVouchers/app/Permissions/DigitalVoucherObjects.PermissionSet.al
+++ b/Apps/W1/EnforcedDigitalVouchers/app/Permissions/DigitalVoucherObjects.PermissionSet.al
@@ -12,15 +12,16 @@ permissionset 5583 "Digital Voucher - Objects"
Permissions = table "Digital Voucher Entry Setup" = X,
table "Digital Voucher Setup" = X,
table "Voucher Entry Source Code" = X,
- page "Digital Voucher Entry Setup" = X,
- page "Digital Voucher Setup" = X,
- page "Digital Voucher Guide" = X,
- page "Voucher Entry Source Codes" = X,
- codeunit "Voucher Attach Or Note Check" = X,
+ codeunit "Digital Voucher Entry" = X,
+ codeunit "Digital Voucher Feature" = X,
+ codeunit "Digital Voucher Impl." = X,
codeunit "Voucher Attachment Check" = X,
+ codeunit "Voucher Attach Or Note Check" = X,
+ codeunit "Voucher E-Document Check" = X,
codeunit "Voucher No Check" = X,
codeunit "Voucher Unknown Check" = X,
- codeunit "Digital Voucher Impl." = X,
- codeunit "Digital Voucher Feature" = X,
- codeunit "Digital Voucher Entry" = X;
+ page "Digital Voucher Entry Setup" = X,
+ page "Digital Voucher Guide" = X,
+ page "Digital Voucher Setup" = X,
+ page "Voucher Entry Source Codes" = X;
}
diff --git a/Apps/W1/EnforcedDigitalVouchers/app/app.json b/Apps/W1/EnforcedDigitalVouchers/app/app.json
index 838ba947f3..afccec4c73 100644
--- a/Apps/W1/EnforcedDigitalVouchers/app/app.json
+++ b/Apps/W1/EnforcedDigitalVouchers/app/app.json
@@ -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": "28.0.0.0"
+ }
+ ],
"screenshots": [],
"platform": "28.0.0.0",
"internalsVisibleTo": [
@@ -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)",
@@ -42,4 +54,4 @@
},
"application": "29.0.0.0",
"target": "Cloud"
-}
+}
\ No newline at end of file
diff --git a/Apps/W1/EnforcedDigitalVouchers/app/src/EntrySetup/DigitalVoucherEntrySetup.Table.al b/Apps/W1/EnforcedDigitalVouchers/app/src/EntrySetup/DigitalVoucherEntrySetup.Table.al
index 270499c647..9a530b3fd6 100644
--- a/Apps/W1/EnforcedDigitalVouchers/app/src/EntrySetup/DigitalVoucherEntrySetup.Table.al
+++ b/Apps/W1/EnforcedDigitalVouchers/app/src/EntrySetup/DigitalVoucherEntrySetup.Table.al
@@ -21,9 +21,26 @@ table 5579 "Digital Voucher Entry Setup"
}
field(2; "Check Type"; Enum "Digital Voucher Check Type")
{
+ trigger OnValidate()
+ 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';
+ begin
+ if "Check Type" = "Check Type"::"E-Document" then begin
+ 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()
+ 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
+ Error(GenerateAutoMustBeEnabledErr, FieldCaption("Check Type"), "Check Type"::"E-Document");
+ end;
}
field(4; "Skip If Manually Added"; Boolean)
{
@@ -47,4 +64,4 @@ table 5579 "Digital Voucher Entry Setup"
Clustered = true;
}
}
-}
+}
\ No newline at end of file
diff --git a/Apps/W1/EnforcedDigitalVouchers/app/src/Extensions/DigVoucherIncDocAttach.TableExt.al b/Apps/W1/EnforcedDigitalVouchers/app/src/Extensions/DigVoucherIncDocAttach.TableExt.al
index a86976dc86..aef35ff27e 100644
--- a/Apps/W1/EnforcedDigitalVouchers/app/src/Extensions/DigVoucherIncDocAttach.TableExt.al
+++ b/Apps/W1/EnforcedDigitalVouchers/app/src/Extensions/DigVoucherIncDocAttach.TableExt.al
@@ -12,5 +12,9 @@ tableextension 5582 "Dig. Voucher Inc. Doc. Attach." extends "Incoming Document
{
DataClassification = SystemMetadata;
}
+ field(5583; "Is E-Document"; Boolean)
+ {
+ DataClassification = SystemMetadata;
+ }
}
}
\ No newline at end of file
diff --git a/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/DigitalVoucherCheckType.Enum.al b/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/DigitalVoucherCheckType.Enum.al
index e522f49d46..528ffcba8c 100644
--- a/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/DigitalVoucherCheckType.Enum.al
+++ b/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/DigitalVoucherCheckType.Enum.al
@@ -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";
+ }
}
diff --git a/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/DigitalVoucherImpl.Codeunit.al b/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/DigitalVoucherImpl.Codeunit.al
index 0868541b1e..e07710c656 100644
--- a/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/DigitalVoucherImpl.Codeunit.al
+++ b/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/DigitalVoucherImpl.Codeunit.al
@@ -24,6 +24,7 @@ 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.Utilities;
@@ -38,13 +39,13 @@ codeunit 5579 "Digital Voucher Impl."
Tabledata "Purch. Cr. Memo Hdr." = m;
var
- DigitalVoucherFeature: Codeunit "Digital Voucher Feature";
DigitalVoucherEntry: Codeunit "Digital Voucher Entry";
- AssistedSetupTxt: Label 'Set up a digital voucher feature';
+ DigitalVoucherFeature: Codeunit "Digital Voucher Feature";
AssistedSetupDescriptionTxt: Label 'In some countries authorities require to make sure that for every single general ledger register ther is a digital vouchers assigned.';
AssistedSetupHelpTxt: Label 'https://learn.microsoft.com/en-us/dynamics365/business-central/across-how-setup-digital-vouchers', Locked = true;
- CannotRemoveReferenceRecordFromIncDocErr: Label 'Cannot remove the reference record from the incoming document because it is used for the enforced digital voucher functionality';
+ AssistedSetupTxt: Label 'Set up a digital voucher feature';
CannotChangeIncomDocWithEnforcedDigitalVoucherErr: Label 'Cannot change incoming document with the enforced digital voucher functionality';
+ CannotRemoveReferenceRecordFromIncDocErr: Label 'Cannot remove the reference record from the incoming document because it is used for the enforced digital voucher functionality';
DigitalVoucherFileTxt: Label 'DigitalVoucher_%1_%2_%3.pdf', Comment = '%1 = doc type; %2 = posting date; %3 = doc no.';
procedure HandleDigitalVoucherForDocument(var ErrorMessageMgt: Codeunit "Error Message Management"; EntryType: Enum "Digital Voucher Entry Type"; Record: Variant)
@@ -103,13 +104,13 @@ codeunit 5579 "Digital Voucher Impl."
[CommitBehavior(CommitBehavior::Ignore)]
procedure GenerateDigitalVoucherForDocument(RecRef: RecordRef)
var
- SalesInvHeader: Record "Sales Invoice Header";
- SalesCrMemoHeader: Record "Sales Cr.Memo Header";
- ServInvHeader: Record "Service Invoice Header";
- ServCrMemoHeader: Record "Service Cr.Memo Header";
- PurchInvHeader: Record "Purch. Inv. Header";
PurchCrMemoHeader: Record "Purch. Cr. Memo Hdr.";
+ PurchInvHeader: Record "Purch. Inv. Header";
ReportSelections: Record "Report Selections";
+ SalesCrMemoHeader: Record "Sales Cr.Memo Header";
+ SalesInvHeader: Record "Sales Invoice Header";
+ ServCrMemoHeader: Record "Service Cr.Memo Header";
+ ServInvHeader: Record "Service Invoice Header";
begin
case RecRef.Number of
Database::"Sales Invoice Header":
@@ -246,7 +247,7 @@ codeunit 5579 "Digital Voucher Impl."
exit;
DataTypeManagement.GetRecordRef(RelatedRecord, RecRef);
if DigitalVoucherFeature.IsDigitalVoucherEnabledForTableNumber(RecRef.Number) then
- error(CannotChangeIncomDocWithEnforcedDigitalVoucherErr);
+ Error(CannotChangeIncomDocWithEnforcedDigitalVoucherErr);
end;
procedure GetDigitalVoucherEntrySetup(var DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup"; EntryType: Enum "Digital Voucher Entry Type"): Boolean
@@ -266,6 +267,132 @@ codeunit 5579 "Digital Voucher Impl."
exit(not IncomingDocumentAttachment.IsEmpty());
end;
+ local procedure AttachIncomingEDocument(EDocument: Record "E-Document"; SourceDocumentHeader: RecordRef; 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.";
+ FileNameTok: Label 'E-Document_%1.xml', Locked = true;
+ RecordLinkTxt: Text;
+ begin
+ if not DigitalVoucherFeature.IsFeatureEnabled() then
+ exit;
+
+ GetDigitalVoucherEntrySetup(DigitalVoucherEntrySetup, "Digital Voucher Entry Type"::"Sales Document");
+ 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
+ exit;
+
+ 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";
+ VoucherEDocumentCheck: Codeunit "Voucher E-Document Check";
+ 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";
+ 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
+ exit;
+
+ 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";
+ PdfInStream: InStream;
+ begin
+ TempBlob.CreateInStream(PdfInStream);
+ if not PDFDocument.GetDocumentAttachmentStream(PdfInStream, ExtractedXmlBlob) then
+ exit;
+
+ if not ExtractedXmlBlob.HasValue() then
+ exit;
+
+ IncomingDocumentAttachment.Default := false;
+ IncomingDocumentAttachment."Main Attachment" := false;
+ if not ImportAttachmentIncDoc.ImportAttachment(IncomingDocumentAttachment, FileName, ExtractedXmlBlob) then
+ exit;
+
+ 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);
@@ -334,8 +461,8 @@ codeunit 5579 "Digital Voucher Impl."
local procedure IsPaymentReconciliationJournal(DigitalVoucherEntryType: Enum "Digital Voucher Entry Type"; RecRef: RecordRef): Boolean
var
- SourceCodeSetup: Record "Source Code Setup";
GenJournalLine: Record "Gen. Journal Line";
+ SourceCodeSetup: Record "Source Code Setup";
FieldRef: FieldRef;
SourceCodeValue: Text;
begin
@@ -351,8 +478,8 @@ codeunit 5579 "Digital Voucher Impl."
local procedure IsGenJnlLineWithIncDocAttachedToAdjLine(DigitalVoucherEntryType: Enum "Digital Voucher Entry Type"; RecRef: RecordRef): Boolean
var
- GenJournalLine: Record "Gen. Journal Line";
AdjacentGenJournalLine: Record "Gen. Journal Line";
+ GenJournalLine: Record "Gen. Journal Line";
IncomingDocument: Record "Incoming Document";
begin
if DigitalVoucherEntryType <> DigitalVoucherEntryType::"General Journal" then
@@ -538,8 +665,8 @@ codeunit 5579 "Digital Voucher Impl."
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Service-Post", 'OnAfterPostServiceDoc', '', true, true)]
local procedure CheckServiceVoucherOnAfterPostServiceDoc(ServInvoiceNo: Code[20]; ServCrMemoNo: Code[20]; PassedInvoice: Boolean)
var
- ServInvHeader: Record "Service Invoice Header";
ServCrMemoHeader: Record "Service Cr.Memo Header";
+ ServInvHeader: Record "Service Invoice Header";
RecVar: Variant;
begin
if not DigitalVoucherFeature.IsFeatureEnabled() then
@@ -639,8 +766,8 @@ codeunit 5579 "Digital Voucher Impl."
[EventSubscriber(ObjectType::Table, Database::"Incoming Document", 'OnBeforeCanReplaceMainAttachment', '', false, false)]
local procedure CheckVoucherOnBeforeCanReplaceMainAttachment(var CanReplaceMainAttachment: Boolean; IncomingDocument: Record "Incoming Document"; var IsHandled: Boolean)
var
- RecRef: RecordRef;
RelatedRecordID: RecordId;
+ RecRef: RecordRef;
begin
RelatedRecordID := IncomingDocument."Related Record ID";
if RelatedRecordID.TableNo = 0 then
@@ -653,8 +780,8 @@ codeunit 5579 "Digital Voucher Impl."
[EventSubscriber(ObjectType::Table, Database::"Incoming Document", 'OnBeforeRemoveReferencedRecords', '', false, false)]
local procedure CheckVoucherOnBeforeRemoveReferencedRecords(IncomingDocument: Record "Incoming Document"; var IsHandled: Boolean)
var
- RecRef: RecordRef;
RelatedRecordID: RecordId;
+ RecRef: RecordRef;
begin
if not DigitalVoucherFeature.IsFeatureEnabled() then
exit;
@@ -677,6 +804,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)]
@@ -699,6 +827,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)
+ begin
+ if not Success then
+ exit;
+
+ AttachIncomingEDocument(EDocument, SourceDocumentHeaderMapped, TempBlob);
+ end;
+
+ [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Document Subscribers", OnAfterUpdateToPostedPurchaseEDocument, '', false, false)]
+ local procedure EDocumentSubscribers_OnAfterUpdateToPostedPurchaseEDocument(var EDocument: Record "E-Document"; PostedRecord: Variant; DocumentType: Enum "E-Document Type")
+ begin
+ AttachOutgoingEDocument(EDocument, PostedRecord);
+ end;
+
[IntegrationEvent(false, false)]
local procedure OnGenerateDigitalVoucherForDocumentOnCaseElse(RecRef: RecordRef)
begin
diff --git a/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/VoucherAttachmentCheck.Codeunit.al b/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/VoucherAttachmentCheck.Codeunit.al
index 575070c823..bdc0daa3e1 100644
--- a/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/VoucherAttachmentCheck.Codeunit.al
+++ b/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/VoucherAttachmentCheck.Codeunit.al
@@ -22,7 +22,7 @@ codeunit 5580 "Voucher Attachment Check" implements "Digital Voucher Check"
if (DigitalVoucherEntryType in [DigitalVoucherEntryType::"General Journal", DigitalVoucherEntryType::"Purchase Journal", DigitalVoucherEntryType::"Sales Journal"]) or
(RecRef.Number() = Database::"Service Header")
then
- error(NotPossibleToPostWithoutVoucherErr);
+ Error(NotPossibleToPostWithoutVoucherErr);
ErrorMessageMgt.LogSimpleErrorMessage(NotPossibleToPostWithoutVoucherErr);
end;
diff --git a/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/VoucherEDocumentCheck.Codeunit.al b/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/VoucherEDocumentCheck.Codeunit.al
new file mode 100644
index 0000000000..613d7e55d5
--- /dev/null
+++ b/Apps/W1/EnforcedDigitalVouchers/app/src/Implementation/VoucherEDocumentCheck.Codeunit.al
@@ -0,0 +1,61 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.EServices.EDocument;
+
+using System.Utilities;
+
+codeunit 5588 "Voucher E-Document Check" implements "Digital Voucher Check"
+{
+ Access = Internal;
+
+ ///
+ /// Validates that an E-Document is attached to the document before posting.
+ /// Only applies to Purchase Documents when the Digital Voucher feature is enabled and Check Type is set to E-Document.
+ ///
+ /// Error message management for logging validation errors.
+ /// The type of digital voucher entry being validated.
+ /// Record reference to the document being validated.
+ internal procedure CheckVoucherIsAttachedToDocument(var ErrorMessageMgt: Codeunit "Error Message Management"; DigitalVoucherEntryType: Enum "Digital Voucher Entry Type"; RecRef: RecordRef)
+ var
+ DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup";
+ EDocument: Record "E-Document";
+ DigitalVoucherFeature: Codeunit "Digital Voucher Feature";
+ DigitalVoucherImpl: Codeunit "Digital Voucher Impl.";
+ NotPossibleToPostWithoutEDocumentErr: Label 'Not possible to post without linking an E-Document.';
+ begin
+ if not DigitalVoucherFeature.IsFeatureEnabled() then
+ exit;
+
+ if DigitalVoucherEntryType <> DigitalVoucherEntryType::"Purchase Document" then
+ exit;
+
+ DigitalVoucherImpl.GetDigitalVoucherEntrySetup(DigitalVoucherEntrySetup, DigitalVoucherEntryType);
+ if DigitalVoucherEntrySetup."Check Type" <> DigitalVoucherEntrySetup."Check Type"::"E-Document" then
+ exit;
+
+ EDocument.SetRange("Document Record ID", RecRef.RecordId());
+ if EDocument.IsEmpty() then begin
+ ErrorMessageMgt.LogSimpleErrorMessage(NotPossibleToPostWithoutEDocumentErr);
+ exit;
+ end;
+ end;
+
+ ///
+ /// Generates a digital voucher for a posted document by delegating to the Attachment check type implementation.
+ /// This procedure retrieves the digital voucher entry setup and invokes the attachment-based voucher generation.
+ ///
+ /// The type of digital voucher entry for the posted document.
+ /// Record reference to the posted document.
+ internal procedure GenerateDigitalVoucherForPostedDocument(DigitalVoucherEntryType: Enum "Digital Voucher Entry Type"; RecRef: RecordRef)
+ var
+ DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup";
+ DigitalVoucherImpl: Codeunit "Digital Voucher Impl.";
+ DigitalVoucherCheck: Interface "Digital Voucher Check";
+ begin
+ DigitalVoucherImpl.GetDigitalVoucherEntrySetup(DigitalVoucherEntrySetup, DigitalVoucherEntryType);
+ DigitalVoucherCheck := DigitalVoucherEntrySetup."Check Type"::Attachment;
+ DigitalVoucherCheck.GenerateDigitalVoucherForPostedDocument(DigitalVoucherEntrySetup."Entry Type", RecRef);
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EnforcedDigitalVouchers/digital-voucher.code-workspace b/Apps/W1/EnforcedDigitalVouchers/digital-voucher.code-workspace
new file mode 100644
index 0000000000..c3cf87c90e
--- /dev/null
+++ b/Apps/W1/EnforcedDigitalVouchers/digital-voucher.code-workspace
@@ -0,0 +1,14 @@
+{
+ "folders": [
+ {
+ "path": "app"
+ },
+ {
+ "path": "test"
+ },
+ {
+ "path": "test library"
+ }
+ ],
+ "settings": {}
+}
\ No newline at end of file
diff --git a/Apps/W1/EnforcedDigitalVouchers/test/app.json b/Apps/W1/EnforcedDigitalVouchers/test/app.json
index 2d8ee2105f..74f3e406e0 100644
--- a/Apps/W1/EnforcedDigitalVouchers/test/app.json
+++ b/Apps/W1/EnforcedDigitalVouchers/test/app.json
@@ -19,6 +19,12 @@
"publisher": "Microsoft",
"version": "29.0.0.0"
},
+ {
+ "id": "e1d97edc-c239-46b4-8d84-6368bdf67c8b",
+ "name": "E-Document Core",
+ "publisher": "Microsoft",
+ "version": "28.0.0.0"
+ },
{
"id": "928f7b70-0dbd-431a-beb5-f45c4adbd361",
"name": "Enforced Digital Vouchers Test Library",
@@ -48,6 +54,10 @@
{
"from": 139515,
"to": 139516
+ },
+ {
+ "from": 139649,
+ "to": 139649
}
],
"contextSensitiveHelpUrl": "https://go.microsoft.com/fwlink/?linkid=2141039",
@@ -60,4 +70,4 @@
"features": [
"TranslationFile"
]
-}
+}
\ No newline at end of file
diff --git a/Apps/W1/EnforcedDigitalVouchers/test/src/EDocAttachmentTests.Codeunit.al b/Apps/W1/EnforcedDigitalVouchers/test/src/EDocAttachmentTests.Codeunit.al
new file mode 100644
index 0000000000..c717cc1929
--- /dev/null
+++ b/Apps/W1/EnforcedDigitalVouchers/test/src/EDocAttachmentTests.Codeunit.al
@@ -0,0 +1,425 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.Test.EServices.EDocument;
+
+using Microsoft.eServices.EDocument;
+using Microsoft.Foundation.Address;
+using Microsoft.Purchases.Document;
+using Microsoft.Purchases.History;
+using Microsoft.Sales.Customer;
+using Microsoft.Sales.Document;
+using Microsoft.Sales.History;
+using Microsoft.Tests.EServices.EDocument;
+
+codeunit 139649 "E-Doc. Attachment Tests"
+{
+ Subtype = Test;
+ TestPermissions = Disabled;
+
+ var
+ Assert: Codeunit Assert;
+ LibraryERM: Codeunit "Library - ERM";
+ LibraryInventory: Codeunit "Library - Inventory";
+ LibraryPurchase: Codeunit "Library - Purchase";
+ LibraryRandom: Codeunit "Library - Random";
+ LibrarySales: Codeunit "Library - Sales";
+ LibraryTestInitialize: Codeunit "Library - Test Initialize";
+ IsInitialized: Boolean;
+ DialogErrorCodeTok: Label 'Dialog', Locked = true;
+ NotPossibleToPostWithoutEDocumentErr: Label 'Not possible to post without linking an E-Document.', Locked = true;
+ EDocumentTok: Label 'E-Document', Locked = true;
+
+ [Test]
+ procedure GenerateAutomaticallyEnabledWhenCheckTypeSetToEDocument()
+ var
+ DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup";
+ begin
+ // [FEATURE] [Digital Voucher] [E-Document]
+ // [SCENARIO] Generate Automatically is auto-enabled when Check Type is set to E-Document
+ Initialize();
+
+ // [GIVEN] Setup record for Purchase Document with Generate Automatically = false
+ DigitalVoucherEntrySetup."Entry Type" := DigitalVoucherEntrySetup."Entry Type"::"Purchase Document";
+ DigitalVoucherEntrySetup."Generate Automatically" := false;
+
+ // [WHEN] Validate Check Type = E-Document
+ DigitalVoucherEntrySetup.Validate("Check Type", DigitalVoucherEntrySetup."Check Type"::"E-Document");
+
+ // [THEN] Generate Automatically is automatically set to true
+ DigitalVoucherEntrySetup.TestField("Generate Automatically", true);
+ end;
+
+ [Test]
+ procedure GenerateAutomaticallyCannotBeDisabledForEDocument()
+ var
+ DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup";
+ GenerateAutomaticallyErrorTok: Label 'Generate Automatically must be enabled', Locked = true;
+ begin
+ // [FEATURE] [Digital Voucher] [E-Document]
+ // [SCENARIO] Generate Automatically cannot be disabled when Check Type = E-Document
+ Initialize();
+
+ // [GIVEN] Entry Type = Purchase Document, Check Type = E-Document
+ DigitalVoucherEntrySetup."Entry Type" := DigitalVoucherEntrySetup."Entry Type"::"Purchase Document";
+ DigitalVoucherEntrySetup.Validate("Check Type", DigitalVoucherEntrySetup."Check Type"::"E-Document");
+
+ // [WHEN] Try to disable Generate Automatically
+ asserterror DigitalVoucherEntrySetup.Validate("Generate Automatically", false);
+
+ // [THEN] Error: Generate Automatically must be enabled when Check Type is E-Document
+ Assert.ExpectedError(GenerateAutomaticallyErrorTok);
+ end;
+
+ [Test]
+ procedure EDocumentCheckTypeNotAllowedForGeneralJournal()
+ var
+ DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup";
+ begin
+ // [FEATURE] [Digital Voucher] [E-Document]
+ // [SCENARIO] E-Document check type is not allowed for General Journal
+ Initialize();
+
+ // [GIVEN] Entry Type = General Journal
+ DigitalVoucherEntrySetup."Entry Type" := DigitalVoucherEntrySetup."Entry Type"::"General Journal";
+
+ // [WHEN] Validate Check Type = E-Document
+ asserterror DigitalVoucherEntrySetup.Validate("Check Type", DigitalVoucherEntrySetup."Check Type"::"E-Document");
+
+ // [THEN] Error mentioning E-Document requires Sales Document or Purchase Document
+ Assert.ExpectedError(EDocumentTok);
+ end;
+
+ [Test]
+ procedure EDocumentCheckTypeNotAllowedForSalesJournal()
+ var
+ DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup";
+ begin
+ // [FEATURE] [Digital Voucher] [E-Document]
+ // [SCENARIO] E-Document check type is not allowed for Sales Journal
+ Initialize();
+
+ // [GIVEN] Entry Type = Sales Journal
+ DigitalVoucherEntrySetup."Entry Type" := DigitalVoucherEntrySetup."Entry Type"::"Sales Journal";
+
+ // [WHEN] Validate Check Type = E-Document
+ asserterror DigitalVoucherEntrySetup.Validate("Check Type", DigitalVoucherEntrySetup."Check Type"::"E-Document");
+
+ // [THEN] Error mentioning E-Document requires Sales Document or Purchase Document
+ Assert.ExpectedError(EDocumentTok);
+ end;
+
+ [Test]
+ procedure EDocumentCheckTypeNotAllowedForPurchaseJournal()
+ var
+ DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup";
+ begin
+ // [FEATURE] [Digital Voucher] [E-Document]
+ // [SCENARIO] E-Document check type is not allowed for Purchase Journal
+ Initialize();
+
+ // [GIVEN] Entry Type = Purchase Journal
+ DigitalVoucherEntrySetup."Entry Type" := DigitalVoucherEntrySetup."Entry Type"::"Purchase Journal";
+
+ // [WHEN] Validate Check Type = E-Document
+ asserterror DigitalVoucherEntrySetup.Validate("Check Type", DigitalVoucherEntrySetup."Check Type"::"E-Document");
+
+ // [THEN] Error mentioning E-Document requires Sales Document or Purchase Document
+ Assert.ExpectedError(EDocumentTok);
+ end;
+
+ [Test]
+ procedure PurchaseInvoiceCannotPostWithoutEDocument()
+ var
+ DummyEDocument: Record "E-Document";
+ PurchaseHeader: Record "Purchase Header";
+ DigVouchersDisableEnforce: Codeunit "Dig. Vouchers Disable Enforce";
+ begin
+ // [FEATURE] [Digital Voucher] [E-Document]
+ // [SCENARIO] Purchase invoice posting fails when E-Document check is enabled but no e-document linked
+ Initialize();
+ BindSubscription(DigVouchersDisableEnforce);
+ EnableDigitalVoucherFeature();
+
+ // [GIVEN] Digital voucher entry setup for purchase document is "E-Document"
+ InitSetupEDocument("Digital Voucher Entry Type"::"Purchase Document");
+
+ // [GIVEN] Purchase invoice WITHOUT linked e-document
+ CreatePurchaseDocument(PurchaseHeader, "Purchase Document Type"::Invoice, DummyEDocument);
+
+ // [WHEN] Post purchase invoice
+ asserterror LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true);
+
+ // [THEN] Error: Not possible to post without linking an E-Document
+ Assert.ExpectedErrorCode(DialogErrorCodeTok);
+ Assert.ExpectedError(NotPossibleToPostWithoutEDocumentErr);
+
+ UnbindSubscription(DigVouchersDisableEnforce);
+ end;
+
+ [Test]
+ procedure PurchaseInvoiceEDocumentAttachedAfterPosting()
+ var
+ EDocument: Record "E-Document";
+ PurchInvHeader: Record "Purch. Inv. Header";
+ PurchaseHeader: Record "Purchase Header";
+ DigVouchersDisableEnforce: Codeunit "Dig. Vouchers Disable Enforce";
+ DocNo: Code[20];
+ begin
+ // [FEATURE] [Digital Voucher] [E-Document]
+ // [SCENARIO] Purchase invoice with e-document creates incoming attachment with Is E-Document = true
+ Initialize();
+ BindSubscription(DigVouchersDisableEnforce);
+ EnableDigitalVoucherFeature();
+
+ // [GIVEN] Digital voucher entry setup for purchase document is "E-Document"
+ InitSetupEDocument("Digital Voucher Entry Type"::"Purchase Document");
+
+ // [GIVEN] Purchase invoice with linked e-document
+ CreatePurchaseDocumentWithEDocument(PurchaseHeader, EDocument, "Purchase Document Type"::Invoice);
+
+ // [WHEN] Post purchase invoice (e-document attachment happens automatically)
+ DocNo := LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true);
+
+ // [THEN] Incoming attachment exists with "Is E-Document" = true
+ PurchInvHeader.Get(DocNo);
+ AssertEDocumentIncomingAttachmentExists(PurchInvHeader."Posting Date", PurchInvHeader."No.");
+
+ UnbindSubscription(DigVouchersDisableEnforce);
+ end;
+
+ [Test]
+ procedure PurchaseCreditMemoEDocumentAttachedAfterPosting()
+ var
+ EDocument: Record "E-Document";
+ PurchCrMemoHdr: Record "Purch. Cr. Memo Hdr.";
+ PurchaseHeader: Record "Purchase Header";
+ DigVouchersDisableEnforce: Codeunit "Dig. Vouchers Disable Enforce";
+ DocNo: Code[20];
+ begin
+ // [FEATURE] [Digital Voucher] [E-Document]
+ // [SCENARIO] Purchase credit memo with e-document creates incoming attachment with Is E-Document = true
+ Initialize();
+ BindSubscription(DigVouchersDisableEnforce);
+ EnableDigitalVoucherFeature();
+
+ // [GIVEN] Digital voucher entry setup for purchase document is "E-Document"
+ InitSetupEDocument("Digital Voucher Entry Type"::"Purchase Document");
+
+ // [GIVEN] Purchase credit memo with linked e-document
+ CreatePurchaseDocumentWithEDocument(PurchaseHeader, EDocument, "Purchase Document Type"::"Credit Memo");
+
+ // [WHEN] Post purchase credit memo (e-document attachment happens automatically)
+ DocNo := LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true);
+
+ // [THEN] Incoming attachment exists with "Is E-Document" = true
+ PurchCrMemoHdr.Get(DocNo);
+ AssertEDocumentIncomingAttachmentExists(PurchCrMemoHdr."Posting Date", PurchCrMemoHdr."No.");
+
+ UnbindSubscription(DigVouchersDisableEnforce);
+ end;
+
+ [Test]
+ procedure SalesInvoiceEDocumentAttachedAfterExport()
+ var
+ SalesHeader: Record "Sales Header";
+ SalesInvoiceHeader: Record "Sales Invoice Header";
+ DigVouchersDisableEnforce: Codeunit "Dig. Vouchers Disable Enforce";
+ DocNo: Code[20];
+ begin
+ // [FEATURE] [Digital Voucher] [E-Document]
+ // [SCENARIO] Sales invoice e-document export creates incoming attachment with Is E-Document = true
+ Initialize();
+ BindSubscription(DigVouchersDisableEnforce);
+ EnableDigitalVoucherFeature();
+
+ // [GIVEN] Digital voucher entry setup for sales document is "E-Document"
+ InitSetupEDocument("Digital Voucher Entry Type"::"Sales Document");
+
+ // [WHEN] Posted sales invoice
+ DocNo := CreateSalesDocumentWithEDocRequirements(SalesHeader, "Sales Document Type"::Invoice);
+ SalesInvoiceHeader.Get(DocNo);
+
+ // [THEN] Incoming attachment exists with "Is E-Document" = true
+ AssertEDocumentIncomingAttachmentExists(SalesInvoiceHeader."Posting Date", SalesInvoiceHeader."No.");
+
+ UnbindSubscription(DigVouchersDisableEnforce);
+ end;
+
+ [Test]
+ procedure SalesCreditMemoEDocumentAttachedAfterExport()
+ var
+ SalesCrMemoHeader: Record "Sales Cr.Memo Header";
+ SalesHeader: Record "Sales Header";
+ DigVouchersDisableEnforce: Codeunit "Dig. Vouchers Disable Enforce";
+ DocNo: Code[20];
+ begin
+ // [FEATURE] [Digital Voucher] [E-Document]
+ // [SCENARIO] Sales credit memo e-document export creates incoming attachment with Is E-Document = true
+ Initialize();
+ BindSubscription(DigVouchersDisableEnforce);
+ EnableDigitalVoucherFeature();
+
+ // [GIVEN] Digital voucher entry setup for sales document is "E-Document"
+ InitSetupEDocument("Digital Voucher Entry Type"::"Sales Document");
+
+ // [WHEN] Posted sales credit memo
+ DocNo := CreateSalesDocumentWithEDocRequirements(SalesHeader, "Sales Document Type"::"Credit Memo");
+ SalesCrMemoHeader.Get(DocNo);
+
+ // [THEN] Incoming attachment exists with "Is E-Document" = true
+ AssertEDocumentIncomingAttachmentExists(SalesCrMemoHeader."Posting Date", SalesCrMemoHeader."No.");
+
+ UnbindSubscription(DigVouchersDisableEnforce);
+ end;
+
+ local procedure Initialize()
+ begin
+ LibraryTestInitialize.OnTestInitialize(Codeunit::"E-Doc. Attachment Tests");
+ if IsInitialized then
+ exit;
+ LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"E-Doc. Attachment Tests");
+
+ IsInitialized := true;
+ Commit();
+ LibraryTestInitialize.OnAfterTestSuiteInitialize(Codeunit::"E-Doc. Attachment Tests");
+ end;
+
+ local procedure EnableDigitalVoucherFeature()
+ var
+ DigitalVoucherSetup: Record "Digital Voucher Setup";
+ begin
+ if DigitalVoucherSetup.Get() then
+ DigitalVoucherSetup.Delete(false);
+ DigitalVoucherSetup.Enabled := true;
+ DigitalVoucherSetup.Insert(false);
+ end;
+
+ local procedure InitSetupEDocument(EntryType: Enum "Digital Voucher Entry Type")
+ var
+ DigitalVoucherEntrySetup: Record "Digital Voucher Entry Setup";
+ begin
+ DigitalVoucherEntrySetup.SetRange("Entry Type", EntryType);
+ DigitalVoucherEntrySetup.DeleteAll(false);
+ DigitalVoucherEntrySetup."Entry Type" := EntryType;
+ DigitalVoucherEntrySetup.Validate("Check Type", DigitalVoucherEntrySetup."Check Type"::"E-Document");
+ DigitalVoucherEntrySetup.Insert(false);
+ end;
+
+ local procedure CreatePurchaseDocumentWithEDocument(var PurchaseHeader: Record "Purchase Header"; var EDocument: Record "E-Document"; DocumentType: Enum "Purchase Document Type")
+ var
+ EDocumentService: Record "E-Document Service";
+ EDocDataStorage: Record "E-Doc. Data Storage";
+ EDocLogHelper: Codeunit "E-Document Log Helper";
+ OutStream: OutStream;
+ EDocType: Enum "E-Document Type";
+ XmlRootTag: Text;
+ FileName: Text;
+ begin
+ case DocumentType of
+ "Purchase Document Type"::Invoice:
+ begin
+ EDocType := EDocType::"Purchase Invoice";
+ XmlRootTag := 'Invoice';
+ FileName := 'test-invoice.xml';
+ end;
+ "Purchase Document Type"::"Credit Memo":
+ begin
+ EDocType := EDocType::"Purchase Credit Memo";
+ XmlRootTag := 'CreditNote';
+ FileName := 'test-credit-memo.xml';
+ end;
+ end;
+
+ CreateService(EDocumentService);
+
+ EDocDataStorage.Init();
+ EDocDataStorage."File Format" := EDocDataStorage."File Format"::XML;
+ EDocDataStorage."Data Storage".CreateOutStream(OutStream);
+ OutStream.WriteText(StrSubstNo('<%1>%2%1>', XmlRootTag, PurchaseHeader."No."));
+ EDocDataStorage.Insert(true);
+
+ EDocument.Init();
+ EDocument.Service := EDocumentService.Code;
+ EDocument.Direction := EDocument.Direction::Incoming;
+ EDocument."Document Type" := EDocType;
+ EDocument."Unstructured Data Entry No." := EDocDataStorage."Entry No.";
+ EDocument."File Name" := FileName;
+ EDocument.Insert(true);
+ EDocLogHelper.InsertLog(EDocument, EDocumentService, Enum::"E-Document Service Status"::Created);
+ CreatePurchaseDocument(PurchaseHeader, DocumentType, EDocument);
+ end;
+
+ local procedure AssertEDocumentIncomingAttachmentExists(PostingDate: Date; DocNo: Code[20])
+ var
+ IncomingDocument: Record "Incoming Document";
+ IncomingDocumentAttachment: Record "Incoming Document Attachment";
+ NoIncomingDocumentTxt: Label 'No incoming document found for %1 on %2', Comment = '%1 = Document No., %2 = Posting Date';
+ begin
+ Assert.IsTrue(
+ IncomingDocument.FindByDocumentNoAndPostingDate(IncomingDocument, DocNo, Format(PostingDate)),
+ StrSubstNo(NoIncomingDocumentTxt, DocNo, PostingDate));
+
+ IncomingDocumentAttachment.SetRange("Incoming Document Entry No.", IncomingDocument."Entry No.");
+ IncomingDocumentAttachment.SetRange("Is E-Document", true);
+
+ Assert.RecordIsNotEmpty(IncomingDocumentAttachment);
+ end;
+
+ local procedure CreateSalesDocumentWithEDocRequirements(var SalesHeader: Record "Sales Header"; DocumentType: Enum "Sales Document Type"): Code[20]
+ var
+ Customer: Record Customer;
+ PostCode: Record "Post Code";
+ begin
+ LibrarySales.CreateCustomer(Customer);
+ LibrarySales.CreateCustomerAddress(Customer);
+ Customer.Validate(GLN, '1234567890128');
+ Customer.Modify(false);
+
+ case DocumentType of
+ "Sales Document Type"::Invoice:
+ LibrarySales.CreateSalesInvoiceForCustomerNo(SalesHeader, Customer."No.");
+ "Sales Document Type"::"Credit Memo":
+ LibrarySales.CreateSalesCreditMemoForCustomerNo(SalesHeader, Customer."No.");
+ end;
+
+ SalesHeader.Validate("Bill-to Address", LibraryRandom.RandText(MaxStrLen(SalesHeader."Bill-to Address")));
+ LibraryERM.CreatePostCode(PostCode);
+ SalesHeader.Validate("Bill-to Post Code", PostCode.Code);
+ SalesHeader.Validate("Your Reference", LibraryRandom.RandText(MaxStrLen(SalesHeader."Your Reference")));
+
+ exit(LibrarySales.PostSalesDocument(SalesHeader, true, true));
+ end;
+
+ local procedure CreateService(var EDocService: Record "E-Document Service")
+ var
+ LibraryUtility: Codeunit "Library - Utility";
+ begin
+ EDocService.Init();
+ EDocService.Code := LibraryUtility.GenerateRandomCode20(EDocService.FieldNo(Code), Database::"E-Document Service");
+ EDocService.Insert(false);
+ end;
+
+ local procedure CreatePurchaseDocument(var PurchaseHeader: Record "Purchase Header"; DocumentType: Enum "Purchase Document Type"; var EDocument: Record "E-Document")
+ var
+ PurchaseLine: Record "Purchase Line";
+ begin
+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, DocumentType, LibraryPurchase.CreateVendorNo());
+ LibraryPurchase.CreatePurchaseLine(
+ PurchaseLine, PurchaseHeader, PurchaseLine.Type::Item,
+ LibraryInventory.CreateItemNo(), LibraryRandom.RandInt(10));
+ PurchaseLine.Validate("Direct Unit Cost", LibraryRandom.RandDec(100, 2));
+ PurchaseLine.Modify(true);
+ PurchaseHeader.CalcFields(Amount, "Amount Including VAT");
+ PurchaseHeader.Validate("Doc. Amount Incl. VAT", PurchaseHeader."Amount Including VAT");
+ PurchaseHeader.Validate("E-Document Link", EDocument.SystemId);
+ PurchaseHeader.Modify(false);
+ if EDocument."Entry No" <> 0 then begin
+ EDocument."Document No." := PurchaseHeader."No.";
+ EDocument."Posting Date" := PurchaseHeader."Posting Date";
+ EDocument."Document Record ID" := PurchaseHeader.RecordId();
+ EDocument.Modify(false);
+ end;
+ end;
+}