diff --git a/Apps/W1/EDocument/app/src/Document/EDocument.Table.al b/Apps/W1/EDocument/app/src/Document/EDocument.Table.al
index 3a9f72288a..2e9537acb3 100644
--- a/Apps/W1/EDocument/app/src/Document/EDocument.Table.al
+++ b/Apps/W1/EDocument/app/src/Document/EDocument.Table.al
@@ -479,6 +479,7 @@ table 6121 "E-Document"
exit(GetEDocumentServiceStatus()."Import Processing Status");
end;
#endif
+
internal procedure ToString(): Text
begin
exit(StrSubstNo(ToStringLbl, SystemId, "Document Record ID", "Workflow Step Instance ID", "Job Queue Entry ID"));
diff --git a/Apps/W1/EDocument/app/src/Document/EDocumentType.Enum.al b/Apps/W1/EDocument/app/src/Document/EDocumentType.Enum.al
index 08b282174e..72a79fb517 100644
--- a/Apps/W1/EDocument/app/src/Document/EDocumentType.Enum.al
+++ b/Apps/W1/EDocument/app/src/Document/EDocumentType.Enum.al
@@ -56,6 +56,7 @@ enum 6121 "E-Document Type" implements IEDocumentFinishDraft
value(10; "Purchase Credit Memo")
{
Caption = 'Purchase Credit Memo';
+ Implementation = IEDocumentFinishDraft = "E-Doc. Create Purch. Cr. Memo";
}
value(11; "Service Order")
{
diff --git a/Apps/W1/EDocument/app/src/Helpers/EDocumentXMLHelper.Codeunit.al b/Apps/W1/EDocument/app/src/Helpers/EDocumentXMLHelper.Codeunit.al
new file mode 100644
index 0000000000..691adeec45
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Helpers/EDocumentXMLHelper.Codeunit.al
@@ -0,0 +1,126 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Helpers;
+
+using Microsoft.Finance.GeneralLedger.Setup;
+
+codeunit 6177 "EDocument XML Helper"
+{
+ Access = Internal;
+
+ ///
+ /// Extracts currency value from XML document and sets it in the currency field if it differs from LCY.
+ ///
+ /// The XML document to search in.
+ /// The XML namespace manager for XPath queries.
+ /// The XPath expression to locate the currency value.
+ /// The maximum length of the currency code.
+ /// The currency field to update with the extracted value.
+ internal procedure SetCurrencyValueInField(XMLDocument: XmlDocument; XMLNamespaces: XmlNamespaceManager; Path: Text; MaxLength: Integer; var CurrencyField: Code[10])
+ var
+ GLSetup: Record "General Ledger Setup";
+ XMLNode: XmlNode;
+ CurrencyCode: Code[10];
+ begin
+ if not XMLDocument.SelectSingleNode(Path, XMLNamespaces, XMLNode) then
+ exit;
+
+ GLSetup.Get();
+
+#pragma warning disable AA0139 // false positive
+ if XMLNode.IsXmlElement() then begin
+ CurrencyCode := CopyStr(XMLNode.AsXmlElement().InnerText(), 1, MaxLength);
+ if GLSetup."LCY Code" <> CurrencyCode then
+ CurrencyField := CurrencyCode;
+ exit;
+ end;
+
+ if XMLNode.IsXmlAttribute() then begin
+ CurrencyCode := CopyStr(XMLNode.AsXmlAttribute().Value, 1, MaxLength);
+ if GLSetup."LCY Code" <> CurrencyCode then
+ CurrencyField := CurrencyCode;
+ exit;
+ end;
+#pragma warning restore AA0139
+ end;
+
+ ///
+ /// Extracts string value from XML document and sets it in the specified field.
+ ///
+ /// The XML document to search in.
+ /// The XML namespace manager for XPath queries.
+ /// The XPath expression to locate the string value.
+ /// The maximum length of the string value.
+ /// The text field to update with the extracted value.
+ internal procedure SetStringValueInField(XMLDocument: XmlDocument; XMLNamespaces: XmlNamespaceManager; Path: Text; MaxLength: Integer; var Field: Text)
+ var
+ XMLNode: XmlNode;
+ begin
+ if not XMLDocument.SelectSingleNode(Path, XMLNamespaces, XMLNode) then
+ exit;
+
+ if XMLNode.IsXmlElement() then begin
+ Field := CopyStr(XMLNode.AsXmlElement().InnerText(), 1, MaxLength);
+ exit;
+ end;
+
+ if XMLNode.IsXmlAttribute() then begin
+ Field := CopyStr(XMLNode.AsXmlAttribute().Value(), 1, MaxLength);
+ exit;
+ end;
+ end;
+
+ ///
+ /// Extracts numeric value from XML document and sets it in the specified decimal field.
+ ///
+ /// The XML document to search in.
+ /// The XML namespace manager for XPath queries.
+ /// The XPath expression to locate the numeric value.
+ /// The decimal field to update with the extracted value.
+ internal procedure SetNumberValueInField(XMLDocument: XmlDocument; XMLNamespaces: XmlNamespaceManager; Path: Text; var DecimalValue: Decimal)
+ var
+ XMLNode: XmlNode;
+ begin
+ if not XMLDocument.SelectSingleNode(Path, XMLNamespaces, XMLNode) then
+ exit;
+
+ if XMLNode.AsXmlElement().InnerText() <> '' then
+ Evaluate(DecimalValue, XMLNode.AsXmlElement().InnerText(), 9);
+ end;
+
+ ///
+ /// Extracts date value from XML document and sets it in the specified date field.
+ ///
+ /// The XML document to search in.
+ /// The XML namespace manager for XPath queries.
+ /// The XPath expression to locate the date value.
+ /// The date field to update with the extracted value.
+ internal procedure SetDateValueInField(XMLDocument: XmlDocument; XMLNamespaces: XmlNamespaceManager; Path: Text; var DateValue: Date)
+ var
+ XMLNode: XmlNode;
+ begin
+ if not XMLDocument.SelectSingleNode(Path, XMLNamespaces, XMLNode) then
+ exit;
+
+ if XMLNode.AsXmlElement().InnerText() <> '' then
+ Evaluate(DateValue, XMLNode.AsXmlElement().InnerText(), 9);
+ end;
+
+ ///
+ /// Retrieves the inner text value of an XML node using XPath expression.
+ ///
+ /// The XML document to search in.
+ /// The XML namespace manager for XPath queries.
+ /// The XPath expression to locate the node.
+ /// The inner text value of the found node, or empty string if node not found.
+ internal procedure GetNodeValue(XmlDoc: XmlDocument; XmlNamespaces: XmlNamespaceManager; XPath: Text): Text
+ var
+ XMLNode: XmlNode;
+ begin
+ if XmlDoc.SelectSingleNode(XPath, XmlNamespaces, XMLNode) then
+ exit(XMLNode.AsXmlElement().InnerText());
+ exit('');
+ end;
+}
diff --git a/Apps/W1/EDocument/app/src/Processing/EDocumentCreatePurchDoc.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/EDocumentCreatePurchDoc.Codeunit.al
index 928cef694e..3520716ddb 100644
--- a/Apps/W1/EDocument/app/src/Processing/EDocumentCreatePurchDoc.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Processing/EDocumentCreatePurchDoc.Codeunit.al
@@ -156,6 +156,10 @@ codeunit 6136 "E-Document Create Purch. Doc."
EDocumentImportHelper.ProcessField(EDocument, DocumentLine, PurchaseField, TempDocumentLine.Field(PurchaseField."No."));
until PurchaseField.Next() = 0;
+ // After processing all fields, set direct unit cost to be the same as in the import file
+ if Format(DocumentLine.Field(PurchaseLine.FieldNo(Type)).Value()) <> '0' then
+ EDocumentImportHelper.ProcessDecimalField(EDocument, DocumentLine, PurchaseLine.FieldNo("Direct Unit Cost"), TempDocumentLine.Field(PurchaseLine.FieldNo("Direct Unit Cost")).Value());
+
OnCreateNewPurchLineOnBeforeRecRefModify(EDocument, TempDocumentHeader, DocumentHeader, TempDocumentLine, DocumentLine);
DocumentLine.Modify(true);
until TempDocumentLine.Next() = 0;
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/EDocEmptyDraft.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/Import/EDocEmptyDraft.Codeunit.al
index 415229e663..5bc2afa1e7 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/EDocEmptyDraft.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/EDocEmptyDraft.Codeunit.al
@@ -50,4 +50,12 @@ codeunit 6193 "E-Doc. Empty Draft" implements IStructureReceivedEDocument, IStru
begin
Error(NoDataErr);
end;
+
+ procedure ResetDraft(EDocument: Record "E-Document")
+ var
+ EDocPurchaseHeader: Record "E-Document Purchase Header";
+ begin
+ EDocPurchaseHeader.GetFromEDocument(EDocument);
+ EDocPurchaseHeader.Delete(true);
+ end;
}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/EDocUnspecifiedImpl.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/Import/EDocUnspecifiedImpl.Codeunit.al
index a47c0c0896..1828308c1f 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/EDocUnspecifiedImpl.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/EDocUnspecifiedImpl.Codeunit.al
@@ -61,6 +61,11 @@ codeunit 6116 "E-Doc. Unspecified Impl." implements IStructureReceivedEDocument,
begin
end;
+ procedure ResetDraft(EDocument: Record "E-Document")
+ begin
+ // No actions to undo
+ end;
+
var
EDocumentNoReadSpecifiedErr: Label 'No method to read the e-document has been provided.';
}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al
new file mode 100644
index 0000000000..c83e29b1fb
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al
@@ -0,0 +1,78 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Processing.Import;
+
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Processing.Import.Purchase;
+using Microsoft.eServices.EDocument.Processing.Interfaces;
+using Microsoft.Finance.Dimension;
+using Microsoft.Purchases.Document;
+
+///
+/// Dealing with the creation of the purchase credit memo after the draft has been populated.
+///
+codeunit 6105 "E-Doc. Create Purch. Cr. Memo" implements IEDocumentFinishDraft, IEDocumentCreatePurchaseCreditMemo
+{
+ Access = Internal;
+ Permissions = tabledata "Dimension Set Tree Node" = im,
+ tabledata "Dimension Set Entry" = im;
+
+ var
+ EDocImpSessionTelemetry: Codeunit "E-Doc. Imp. Session Telemetry";
+
+ ///
+ /// Applies the draft E-Document to Business Central by creating a purchase credit memo from the draft data.
+ ///
+ /// The E-Document record containing the draft data to be applied.
+ /// The import parameters containing processing customizations.
+ /// The RecordId of the created purchase credit memo.
+ internal procedure ApplyDraftToBC(EDocument: Record "E-Document"; EDocImportParameters: Record "E-Doc. Import Parameters"): RecordId
+ var
+ EDocumentPurchaseHeader: Record "E-Document Purchase Header";
+ PurchaseHeader: Record "Purchase Header";
+ EDocPurchaseDocumentHelper: Codeunit "E-Doc Purchase Document Helper";
+ IEDocumentFinishPurchaseDraft: Interface IEDocumentCreatePurchaseCreditMemo;
+ begin
+ EDocumentPurchaseHeader.GetFromEDocument(EDocument);
+ IEDocumentFinishPurchaseDraft := EDocImportParameters."Processing Customizations";
+ PurchaseHeader := IEDocumentFinishPurchaseDraft.CreatePurchaseCreditMemo(EDocument);
+
+ // Post document validation - Silently emit telemetry
+ if not EDocPurchaseDocumentHelper.TryValidateDocumentTotals(PurchaseHeader) then
+ EDocImpSessionTelemetry.SetBool('Totals Validation Failed', true);
+
+ exit(PurchaseHeader.RecordId);
+ end;
+
+ ///
+ /// Reverts the draft actions by deleting the associated purchase credit memo document.
+ ///
+ /// The E-Document record whose draft actions should be reverted.
+ internal procedure RevertDraftActions(EDocument: Record "E-Document")
+ var
+ PurchaseHeader: Record "Purchase Header";
+ begin
+ PurchaseHeader.SetRange("E-Document Link", EDocument.SystemId);
+ if not PurchaseHeader.FindFirst() then
+ exit;
+
+ PurchaseHeader.TestField("Document Type", "Purchase Document Type"::"Credit Memo");
+ Clear(PurchaseHeader."E-Document Link");
+ PurchaseHeader.Delete(true);
+ end;
+
+ ///
+ /// Creates a purchase credit memo from E-Document draft data, including header and line information.
+ ///
+ /// The E-Document record containing the draft data to create the credit memo from.
+ /// The created purchase header record for the credit memo.
+ internal procedure CreatePurchaseCreditMemo(EDocument: Record "E-Document") PurchaseHeader: Record "Purchase Header"
+ var
+ EDocPurchaseDocumentHelper: Codeunit "E-Doc Purchase Document Helper";
+ begin
+ PurchaseHeader := EDocPurchaseDocumentHelper.CreatePurchaseDocumentHeader(EDocument, "Purchase Document Type"::"Credit Memo");
+ exit(PurchaseHeader);
+ end;
+}
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al
index 79c9f369af..0cda9a65a7 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al
@@ -5,15 +5,11 @@
namespace Microsoft.eServices.EDocument.Processing.Import;
using Microsoft.eServices.EDocument;
-using Microsoft.Finance.Dimension;
-using Microsoft.Purchases.Document;
-using Microsoft.eServices.EDocument.Processing.Interfaces;
using Microsoft.eServices.EDocument.Processing.Import.Purchase;
-using Microsoft.Finance.GeneralLedger.Setup;
-using Microsoft.Purchases.Payables;
-using Microsoft.Purchases.Posting;
-using System.Telemetry;
+using Microsoft.eServices.EDocument.Processing.Interfaces;
+using Microsoft.Finance.Dimension;
using Microsoft.Foundation.Attachment;
+using Microsoft.Purchases.Document;
///
/// Dealing with the creation of the purchase invoice after the draft has been populated.
@@ -25,40 +21,35 @@ codeunit 6117 "E-Doc. Create Purchase Invoice" implements IEDocumentFinishDraft,
tabledata "Dimension Set Entry" = im;
var
- Telemetry: Codeunit "Telemetry";
EDocImpSessionTelemetry: Codeunit "E-Doc. Imp. Session Telemetry";
- InvoiceAlreadyExistsErr: Label 'A purchase invoice with external document number %1 already exists for vendor %2.', Comment = '%1 = Vendor Invoice No., %2 = Vendor No.';
- DraftLineDoesNotConstantTypeAndNumberErr: Label 'One of the draft lines do not contain the type and number. Please, specify these fields manually.';
+ ///
+ /// Applies the draft E-Document to Business Central by creating a purchase invoice from the draft data.
+ ///
+ /// The E-Document record containing the draft data to be applied.
+ /// The import parameters containing processing customizations.
+ /// The RecordId of the created purchase invoice.
procedure ApplyDraftToBC(EDocument: Record "E-Document"; EDocImportParameters: Record "E-Doc. Import Parameters"): RecordId
var
EDocumentPurchaseHeader: Record "E-Document Purchase Header";
PurchaseHeader: Record "Purchase Header";
- DocumentAttachmentMgt: Codeunit "Document Attachment Mgmt";
+ EDocPurchaseDocumentHelper: Codeunit "E-Doc Purchase Document Helper";
IEDocumentFinishPurchaseDraft: Interface IEDocumentCreatePurchaseInvoice;
begin
EDocumentPurchaseHeader.GetFromEDocument(EDocument);
IEDocumentFinishPurchaseDraft := EDocImportParameters."Processing Customizations";
PurchaseHeader := IEDocumentFinishPurchaseDraft.CreatePurchaseInvoice(EDocument);
- PurchaseHeader.SetRecFilter();
- PurchaseHeader.FindFirst();
- PurchaseHeader."Doc. Amount Incl. VAT" := EDocumentPurchaseHeader.Total;
- PurchaseHeader."Doc. Amount VAT" := EDocumentPurchaseHeader."Total VAT";
- PurchaseHeader.TestField("Document Type", "Purchase Document Type"::Invoice);
- PurchaseHeader.TestField("No.");
- PurchaseHeader."E-Document Link" := EDocument.SystemId;
- PurchaseHeader.Modify();
-
- // Post document creation
- DocumentAttachmentMgt.CopyAttachments(EDocument, PurchaseHeader);
- DocumentAttachmentMgt.DeleteAttachedDocuments(EDocument);
// Post document validation - Silently emit telemetry
- EDocImpSessionTelemetry.SetBool('Totals Validation', TryValidateDocumentTotals(PurchaseHeader));
+ EDocImpSessionTelemetry.SetBool('Totals Validation', EDocPurchaseDocumentHelper.TryValidateDocumentTotals(PurchaseHeader));
exit(PurchaseHeader.RecordId);
end;
+ ///
+ /// Reverts the draft actions by deleting the associated purchase invoice document.
+ ///
+ /// The E-Document record whose draft actions should be reverted.
procedure RevertDraftActions(EDocument: Record "E-Document")
var
PurchaseHeader: Record "Purchase Header";
@@ -74,124 +65,16 @@ codeunit 6117 "E-Doc. Create Purchase Invoice" implements IEDocumentFinishDraft,
PurchaseHeader.Delete(true);
end;
- procedure CreatePurchaseInvoice(EDocument: Record "E-Document"): Record "Purchase Header"
+ ///
+ /// Creates a purchase invoice from E-Document draft data, including header and line information.
+ ///
+ /// The E-Document record containing the draft data to create the invoice from.
+ /// The created purchase header record for the invoice.
+ procedure CreatePurchaseInvoice(EDocument: Record "E-Document") PurchaseHeader: Record "Purchase Header"
var
- PurchaseHeader: Record "Purchase Header";
- GLSetup: Record "General Ledger Setup";
- VendorLedgerEntry: Record "Vendor Ledger Entry";
- EDocumentPurchaseHeader: Record "E-Document Purchase Header";
- EDocumentPurchaseLine: Record "E-Document Purchase Line";
- PurchaseLine: Record "Purchase Line";
- EDocumentPurchaseHistMapping: Codeunit "E-Doc. Purchase Hist. Mapping";
- DimensionManagement: Codeunit DimensionManagement;
- PurchaseLineCombinedDimensions: array[10] of Integer;
- StopCreatingPurchaseInvoice: Boolean;
- VendorInvoiceNo: Code[35];
- GlobalDim1, GlobalDim2 : Code[20];
+ EDocPurchaseDocumentHelper: Codeunit "E-Doc Purchase Document Helper";
begin
- EDocumentPurchaseHeader.GetFromEDocument(EDocument);
- if not AllDraftLinesHaveTypeAndNumberSpecificed(EDocumentPurchaseHeader) then begin
- Telemetry.LogMessage('0000PLY', 'Draft line does not contain type or number', Verbosity::Error, DataClassification::SystemMetadata, TelemetryScope::All);
- Error(DraftLineDoesNotConstantTypeAndNumberErr);
- end;
- EDocumentPurchaseHeader.TestField("E-Document Entry No.");
- PurchaseHeader.SetRange("Buy-from Vendor No.", EDocumentPurchaseHeader."[BC] Vendor No."); // Setting the filter, so that the insert trigger assigns the right vendor to the purchase header
- PurchaseHeader."Document Type" := "Purchase Document Type"::Invoice;
- PurchaseHeader."Pay-to Vendor No." := EDocumentPurchaseHeader."[BC] Vendor No.";
-
- VendorInvoiceNo := CopyStr(EDocumentPurchaseHeader."Sales Invoice No.", 1, MaxStrLen(PurchaseHeader."Vendor Invoice No."));
- VendorLedgerEntry.SetLoadFields("Entry No.");
- VendorLedgerEntry.ReadIsolation := VendorLedgerEntry.ReadIsolation::ReadUncommitted;
- StopCreatingPurchaseInvoice := PurchaseHeader.FindPostedDocumentWithSameExternalDocNo(VendorLedgerEntry, VendorInvoiceNo);
- if StopCreatingPurchaseInvoice then begin
- Telemetry.LogMessage('0000PHC', InvoiceAlreadyExistsErr, Verbosity::Error, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All);
- Error(InvoiceAlreadyExistsErr, VendorInvoiceNo, EDocumentPurchaseHeader."[BC] Vendor No.");
- end;
-
- PurchaseHeader.Validate("Vendor Invoice No.", VendorInvoiceNo);
- PurchaseHeader.Insert(true);
-
- if EDocumentPurchaseHeader."Document Date" <> 0D then
- PurchaseHeader.Validate("Document Date", EDocumentPurchaseHeader."Document Date");
- if EDocumentPurchaseHeader."Due Date" <> 0D then
- PurchaseHeader.Validate("Due Date", EDocumentPurchaseHeader."Due Date");
- PurchaseHeader."Invoice Received Date" := PurchaseHeader."Document Date";
- PurchaseHeader.Modify();
-
- // Validate of currency has to happen after insert.
- GLSetup.GetRecordOnce();
- if EDocumentPurchaseHeader."Currency Code" <> GLSetup.GetCurrencyCode('') then begin
- PurchaseHeader.Validate("Currency Code", EDocumentPurchaseHeader."Currency Code");
- PurchaseHeader.Modify();
- end;
-
- // Track changes for history
- EDocumentPurchaseHistMapping.TrackRecord(EDocument, EDocumentPurchaseHeader, PurchaseHeader);
-
- EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocument."Entry No");
- if EDocumentPurchaseLine.FindSet() then
- repeat
- PurchaseLine."Document Type" := PurchaseHeader."Document Type";
- PurchaseLine."Document No." := PurchaseHeader."No.";
- PurchaseLine."Line No." += 10000;
- PurchaseLine."Unit of Measure Code" := CopyStr(EDocumentPurchaseLine."[BC] Unit of Measure", 1, MaxStrLen(PurchaseLine."Unit of Measure Code"));
- PurchaseLine."Variant Code" := EDocumentPurchaseLine."[BC] Variant Code";
- PurchaseLine.Type := EDocumentPurchaseLine."[BC] Purchase Line Type";
- PurchaseLine.Validate("No.", EDocumentPurchaseLine."[BC] Purchase Type No.");
- PurchaseLine.Description := EDocumentPurchaseLine.Description;
-
- if EDocumentPurchaseLine."[BC] Item Reference No." <> '' then
- PurchaseLine.Validate("Item Reference No.", EDocumentPurchaseLine."[BC] Item Reference No.");
-
- PurchaseLine.Validate(Quantity, EDocumentPurchaseLine.Quantity);
- PurchaseLine.Validate("Direct Unit Cost", EDocumentPurchaseLine."Unit Price");
- if EDocumentPurchaseLine."Total Discount" > 0 then
- PurchaseLine.Validate("Line Discount Amount", EDocumentPurchaseLine."Total Discount");
- PurchaseLine.Validate("Deferral Code", EDocumentPurchaseLine."[BC] Deferral Code");
-
- Clear(PurchaseLineCombinedDimensions);
- PurchaseLineCombinedDimensions[1] := PurchaseLine."Dimension Set ID";
- PurchaseLineCombinedDimensions[2] := EDocumentPurchaseLine."[BC] Dimension Set ID";
- PurchaseLine.Validate("Dimension Set ID", DimensionManagement.GetCombinedDimensionSetID(PurchaseLineCombinedDimensions, GlobalDim1, GlobalDim2));
- PurchaseLine.Validate("Shortcut Dimension 1 Code", EDocumentPurchaseLine."[BC] Shortcut Dimension 1 Code");
- PurchaseLine.Validate("Shortcut Dimension 2 Code", EDocumentPurchaseLine."[BC] Shortcut Dimension 2 Code");
- EDocumentPurchaseHistMapping.ApplyAdditionalFieldsFromHistoryToPurchaseLine(EDocumentPurchaseLine, PurchaseLine);
- PurchaseLine.Insert();
-
- // Track changes for history
- EDocumentPurchaseHistMapping.TrackRecord(EDocument, EDocumentPurchaseLine, PurchaseLine);
-
- until EDocumentPurchaseLine.Next() = 0;
-
+ PurchaseHeader := EDocPurchaseDocumentHelper.CreatePurchaseDocumentHeader(EDocument, "Purchase Document Type"::Invoice);
exit(PurchaseHeader);
-
end;
-
- [TryFunction]
- local procedure TryValidateDocumentTotals(PurchaseHeader: Record "Purchase Header")
- var
- PurchPost: Codeunit "Purch.-Post";
- begin
- // If document totals are setup, we just run the validation
- PurchPost.CheckDocumentTotalAmounts(PurchaseHeader);
- end;
-
- local procedure AllDraftLinesHaveTypeAndNumberSpecificed(EDocumentPurchaseHeader: Record "E-Document Purchase Header"): Boolean
- var
- EDocumentPurchaseLine: Record "E-Document Purchase Line";
- begin
- EDocumentPurchaseLine.SetLoadFields("[BC] Purchase Line Type", "[BC] Purchase Type No.");
- EDocumentPurchaseLine.ReadIsolation(IsolationLevel::ReadCommitted);
- EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocumentPurchaseHeader."E-Document Entry No.");
- if not EDocumentPurchaseLine.FindSet() then
- exit(true);
- repeat
- if EDocumentPurchaseLine."[BC] Purchase Line Type" = EDocumentPurchaseLine."[BC] Purchase Line Type"::" " then
- exit(false);
- if EDocumentPurchaseLine."[BC] Purchase Type No." = '' then
- exit(false);
- until EDocumentPurchaseLine.Next() = 0;
- exit(true);
- end;
-
}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Enum.al b/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Enum.al
index 2caa2656e3..21093a4f5b 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Enum.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Enum.al
@@ -13,7 +13,8 @@ enum 6105 "E-Doc. Create Purchase Invoice" implements IEDocumentCreatePurchaseIn
{
Extensible = true;
DefaultImplementation = IEDocumentCreatePurchaseInvoice = "E-Doc. Create Purchase Invoice";
- value(0; "Default")
- {
- }
+ ObsoleteState = Pending;
+ ObsoleteReason = 'Replaced by enum 6110 "E-Doc. Proc. Customizations';
+
+ value(0; "Default") { }
}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocPurchaseDocumentHelper.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocPurchaseDocumentHelper.Codeunit.al
new file mode 100644
index 0000000000..07b26c8a72
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Processing/Import/FinishDraft/EDocPurchaseDocumentHelper.Codeunit.al
@@ -0,0 +1,246 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Processing.Import;
+
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Processing.Import.Purchase;
+using Microsoft.Finance.Dimension;
+using Microsoft.Finance.GeneralLedger.Setup;
+using Microsoft.Foundation.Attachment;
+using Microsoft.Purchases.Document;
+using Microsoft.Purchases.Payables;
+using Microsoft.Purchases.Posting;
+using System.Telemetry;
+
+///
+/// Common functionality shared between purchase invoice and credit memo creation from E-Document drafts.
+/// This codeunit contains reusable procedures to eliminate code duplication.
+///
+codeunit 6185 "E-Doc Purchase Document Helper"
+{
+ Access = Internal;
+ Permissions = tabledata "Dimension Set Tree Node" = im,
+ tabledata "Dimension Set Entry" = im;
+
+ var
+ Telemetry: Codeunit "Telemetry";
+
+ ///
+ /// Creates a purchase document header from E-Document draft data, including all lines.
+ ///
+ /// The E-Document record containing the draft data.
+ /// The purchase document type (Invoice or Credit Memo).
+ /// The created purchase header record.
+ internal procedure CreatePurchaseDocumentHeader(EDocument: Record "E-Document";
+ DocumentType: Enum "Purchase Document Type"
+ ) PurchaseHeader: Record "Purchase Header"
+ var
+ GLSetup: Record "General Ledger Setup";
+ EDocumentPurchaseHeader: Record "E-Document Purchase Header";
+ DocumentAttachmentMgt: Codeunit "Document Attachment Mgmt";
+ EDocumentPurchaseHistMapping: Codeunit "E-Doc. Purchase Hist. Mapping";
+ TelemetryEventId: Text;
+ PurchaseDocumentExistsErr: Label 'A purchase %1 with external document number %2 already exists for vendor %3.', Comment = '%1 = Purchase Document Type, %2 = External Document No., %3 = Vendor No.';
+ ExternalDocumentNo: Code[35];
+ begin
+ EDocumentPurchaseHeader.GetFromEDocument(EDocument);
+ case DocumentType of
+ "Purchase Document Type"::Invoice:
+ begin
+ TelemetryEventId := '0000PLY';
+ ExternalDocumentNo := CopyStr(EDocumentPurchaseHeader."Sales Invoice No.", 1, MaxStrLen(PurchaseHeader."Vendor Invoice No."));
+ end;
+ "Purchase Document Type"::"Credit Memo":
+ begin
+ TelemetryEventId := '0000PLZ';
+ ExternalDocumentNo := CopyStr(EDocumentPurchaseHeader."Sales Invoice No.", 1, MaxStrLen(PurchaseHeader."Vendor Cr. Memo No."));
+ end;
+ end;
+ EDocumentPurchaseHeader := ValidateEDocumentDraft(EDocument, TelemetryEventId);
+ EDocumentPurchaseHeader.TestField("E-Document Entry No.");
+ PurchaseHeader.Validate("Document Type", DocumentType);
+ PurchaseHeader.Validate("Buy-from Vendor No.", EDocumentPurchaseHeader."[BC] Vendor No.");
+
+ // Validate external document number for duplicates
+ if ValidateExternalDocumentNumber(PurchaseHeader, ExternalDocumentNo) then
+ Error(PurchaseDocumentExistsErr, PurchaseHeader."Document Type", ExternalDocumentNo, PurchaseHeader."Buy-from Vendor No.");
+
+ case PurchaseHeader."Document Type" of
+ "Purchase Document Type"::Invoice:
+ PurchaseHeader.Validate("Vendor Invoice No.", ExternalDocumentNo);
+ "Purchase Document Type"::"Credit Memo":
+ PurchaseHeader.Validate("Vendor Cr. Memo No.", ExternalDocumentNo);
+ end;
+ PurchaseHeader.Validate("Vendor Order No.", EDocumentPurchaseHeader."Purchase Order No.");
+ PurchaseHeader.Insert(true);
+
+ if EDocumentPurchaseHeader."Document Date" <> 0D then
+ PurchaseHeader.Validate("Document Date", EDocumentPurchaseHeader."Document Date");
+ if EDocumentPurchaseHeader."Due Date" <> 0D then
+ PurchaseHeader.Validate("Due Date", EDocumentPurchaseHeader."Due Date");
+ if DocumentType = "Purchase Document Type"::Invoice then
+ PurchaseHeader."Invoice Received Date" := PurchaseHeader."Document Date";
+ if (DocumentType = "Purchase Document Type"::"Credit Memo") and (EDocumentPurchaseHeader."Applies-to Doc. No." <> '') then begin
+ PurchaseHeader.Validate("Applies-to Doc. Type", PurchaseHeader."Applies-to Doc. Type"::Invoice);
+ PurchaseHeader.Validate("Applies-to Doc. No.", EDocumentPurchaseHeader."Applies-to Doc. No.");
+ end;
+
+ PurchaseHeader.Modify(false);
+
+ // Validate of currency has to happen after insert.
+ GLSetup.GetRecordOnce();
+ if EDocumentPurchaseHeader."Currency Code" <> GLSetup.GetCurrencyCode('') then begin
+ PurchaseHeader.Validate("Currency Code", EDocumentPurchaseHeader."Currency Code");
+ PurchaseHeader.Modify(false);
+ end;
+
+ // Track changes for history
+ EDocumentPurchaseHistMapping.TrackRecord(EDocument, EDocumentPurchaseHeader, PurchaseHeader);
+
+ PurchaseHeader.SetRecFilter();
+ PurchaseHeader.FindFirst();
+ PurchaseHeader."Doc. Amount Incl. VAT" := EDocumentPurchaseHeader.Total;
+ PurchaseHeader."Doc. Amount VAT" := EDocumentPurchaseHeader."Total VAT";
+ case DocumentType of
+ "Purchase Document Type"::Invoice:
+ PurchaseHeader.TestField("Document Type", "Purchase Document Type"::Invoice);
+ "Purchase Document Type"::"Credit Memo":
+ PurchaseHeader.TestField("Document Type", "Purchase Document Type"::"Credit Memo");
+ end;
+ PurchaseHeader.TestField("No.");
+ PurchaseHeader."E-Document Link" := EDocument.SystemId;
+ PurchaseHeader.Modify(false);
+
+ // Post document creation
+ DocumentAttachmentMgt.CopyAttachments(EDocument, PurchaseHeader);
+ DocumentAttachmentMgt.DeleteAttachedDocuments(EDocument);
+
+ CreatePurchaseDocumentLines(EDocument, PurchaseHeader, EDocumentPurchaseHistMapping);
+ exit(PurchaseHeader);
+ end;
+
+ ///
+ /// Creates all purchase document lines from E-Document draft data.
+ ///
+ /// The E-Document record containing the draft data.
+ /// The purchase header record that the lines belong to.
+ /// The history mapping codeunit for tracking changes.
+ local procedure CreatePurchaseDocumentLines(EDocument: Record "E-Document"; PurchaseHeader: Record "Purchase Header"; var EDocumentPurchaseHistMapping: Codeunit "E-Doc. Purchase Hist. Mapping")
+ var
+ EDocumentPurchaseLine: Record "E-Document Purchase Line";
+ PurchaseLine: Record "Purchase Line";
+ DimensionManagement: Codeunit DimensionManagement;
+ PurchaseLineCombinedDimensions: array[10] of Integer;
+ GlobalDim1: Code[20];
+ GlobalDim2: Code[20];
+ begin
+ EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocument."Entry No");
+ if EDocumentPurchaseLine.FindSet() then
+ repeat
+ PurchaseLine.SetRange("Document Type", PurchaseHeader."Document Type");
+ PurchaseLine.SetRange("Document No.", PurchaseHeader."No.");
+ if PurchaseLine.FindLast() then;
+
+ PurchaseLine."Document Type" := PurchaseHeader."Document Type";
+ PurchaseLine."Document No." := PurchaseHeader."No.";
+ PurchaseLine."Line No." += 10000;
+ PurchaseLine."Unit of Measure Code" := CopyStr(EDocumentPurchaseLine."[BC] Unit of Measure", 1, MaxStrLen(PurchaseLine."Unit of Measure Code"));
+ PurchaseLine."Variant Code" := EDocumentPurchaseLine."[BC] Variant Code";
+ PurchaseLine.Type := EDocumentPurchaseLine."[BC] Purchase Line Type";
+ PurchaseLine.Validate("No.", EDocumentPurchaseLine."[BC] Purchase Type No.");
+ PurchaseLine.Description := EDocumentPurchaseLine.Description;
+
+ if EDocumentPurchaseLine."[BC] Item Reference No." <> '' then
+ PurchaseLine.Validate("Item Reference No.", EDocumentPurchaseLine."[BC] Item Reference No.");
+
+ PurchaseLine.Validate(Quantity, EDocumentPurchaseLine.Quantity);
+ PurchaseLine.Validate("Direct Unit Cost", EDocumentPurchaseLine."Unit Price");
+ if EDocumentPurchaseLine."Total Discount" > 0 then
+ PurchaseLine.Validate("Line Discount Amount", EDocumentPurchaseLine."Total Discount");
+ PurchaseLine.Validate("Deferral Code", EDocumentPurchaseLine."[BC] Deferral Code");
+
+ Clear(PurchaseLineCombinedDimensions);
+ PurchaseLineCombinedDimensions[1] := PurchaseLine."Dimension Set ID";
+ PurchaseLineCombinedDimensions[2] := EDocumentPurchaseLine."[BC] Dimension Set ID";
+ PurchaseLine.Validate("Dimension Set ID", DimensionManagement.GetCombinedDimensionSetID(PurchaseLineCombinedDimensions, GlobalDim1, GlobalDim2));
+ PurchaseLine.Validate("Shortcut Dimension 1 Code", EDocumentPurchaseLine."[BC] Shortcut Dimension 1 Code");
+ PurchaseLine.Validate("Shortcut Dimension 2 Code", EDocumentPurchaseLine."[BC] Shortcut Dimension 2 Code");
+
+ EDocumentPurchaseHistMapping.ApplyAdditionalFieldsFromHistoryToPurchaseLine(EDocumentPurchaseLine, PurchaseLine);
+ PurchaseLine.Insert(false);
+
+ // Track changes for history
+ EDocumentPurchaseHistMapping.TrackRecord(EDocument, EDocumentPurchaseLine, PurchaseLine);
+ until EDocumentPurchaseLine.Next() = 0;
+ end;
+
+ local procedure ValidateAllDraftLinesHaveTypeAndNumber(EDocumentPurchaseHeader: Record "E-Document Purchase Header"): Boolean
+ var
+ EDocumentPurchaseLine: Record "E-Document Purchase Line";
+ begin
+ EDocumentPurchaseLine.SetLoadFields("[BC] Purchase Line Type", "[BC] Purchase Type No.");
+ EDocumentPurchaseLine.ReadIsolation(IsolationLevel::ReadCommitted);
+ EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocumentPurchaseHeader."E-Document Entry No.");
+ if not EDocumentPurchaseLine.FindSet() then
+ exit(true);
+ repeat
+ if EDocumentPurchaseLine."[BC] Purchase Line Type" = EDocumentPurchaseLine."[BC] Purchase Line Type"::" " then
+ exit(false);
+ if EDocumentPurchaseLine."[BC] Purchase Type No." = '' then
+ exit(false);
+ until EDocumentPurchaseLine.Next() = 0;
+ exit(true);
+ end;
+
+ local procedure ValidateEDocumentDraft(EDocument: Record "E-Document"; TelemetryEventId: Text) EDocumentPurchaseHeader: Record "E-Document Purchase Header"
+ var
+ EmptyDraftLineErr: Label 'Draft line does not contain type or number';
+ DraftLineDoesNotConstantTypeAndNumberErr: Label 'One of the draft lines do not contain the type and number. Please, specify these fields manually.';
+ begin
+ EDocumentPurchaseHeader.GetFromEDocument(EDocument);
+ if not ValidateAllDraftLinesHaveTypeAndNumber(EDocumentPurchaseHeader) then begin
+ Telemetry.LogMessage(TelemetryEventId, EmptyDraftLineErr, Verbosity::Error, DataClassification::SystemMetadata, TelemetryScope::All);
+ Error(DraftLineDoesNotConstantTypeAndNumberErr);
+ end;
+ exit(EDocumentPurchaseHeader);
+ end;
+
+ ///
+ /// Validates document totals using purchase posting validation.
+ ///
+ /// The purchase header to validate totals for.
+ /// True if validation passes, false otherwise.
+ [TryFunction]
+ internal procedure TryValidateDocumentTotals(PurchaseHeader: Record "Purchase Header")
+ var
+ PurchPost: Codeunit "Purch.-Post";
+ begin
+ // If document totals are setup, we just run the validation
+ PurchPost.CheckDocumentTotalAmounts(PurchaseHeader);
+ end;
+
+ local procedure ValidateExternalDocumentNumber(PurchaseHeader: Record "Purchase Header"; ExternalDocumentNo: Code[35]): Boolean
+ var
+ VendorLedgerEntry: Record "Vendor Ledger Entry";
+ StopCreatingPurchaseDocument: Boolean;
+ InvoiceAlreadyExistsErr: Label 'A purchase invoice with external document number %1 already exists for vendor %2.', Comment = '%1 = Vendor Invoice No., %2 = Vendor No.';
+ TelemetryEventId: Text;
+ begin
+ case PurchaseHeader."Document Type" of
+ "Purchase Document Type"::Invoice:
+ TelemetryEventId := '0000PHC';
+ "Purchase Document Type"::"Credit Memo":
+ TelemetryEventId := '0000PHD';
+ end;
+ VendorLedgerEntry.SetLoadFields("Entry No.");
+ VendorLedgerEntry.ReadIsolation := VendorLedgerEntry.ReadIsolation::ReadUncommitted;
+ StopCreatingPurchaseDocument := PurchaseHeader.FindPostedDocumentWithSameExternalDocNo(VendorLedgerEntry, ExternalDocumentNo);
+ if StopCreatingPurchaseDocument then begin
+ Telemetry.LogMessage(TelemetryEventId, InvoiceAlreadyExistsErr, Verbosity::Error, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All);
+ exit(true);
+ end;
+ exit(false);
+ end;
+}
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/ImportEDocumentProcess.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/Import/ImportEDocumentProcess.Codeunit.al
index ba9f84c5c0..9c1b6658ba 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/ImportEDocumentProcess.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/ImportEDocumentProcess.Codeunit.al
@@ -175,6 +175,7 @@ codeunit 6104 "Import E-Document Process"
var
EDocumentHeaderMapping: Record "E-Document Header Mapping";
IEDocumentFinishDraft: Interface IEDocumentFinishDraft;
+ IStructuredFormatReader: Interface IStructuredFormatReader;
begin
case Step of
Step::"Finish draft":
@@ -184,6 +185,11 @@ codeunit 6104 "Import E-Document Process"
Clear(EDocument."Document Record ID");
EDocument.Modify();
end;
+ Step::"Read into Draft":
+ begin
+ IStructuredFormatReader := EDocument."Read into Draft Impl.";
+ IStructuredFormatReader.ResetDraft(EDocument);
+ end;
Step::"Prepare draft":
begin
EDocumentHeaderMapping.SetRange("E-Document Entry No.", EDocument."Entry No");
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/EDocProcCustomizations.Enum.al b/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/EDocProcCustomizations.Enum.al
index e533729eed..a2ccea3c23 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/EDocProcCustomizations.Enum.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/EDocProcCustomizations.Enum.al
@@ -11,16 +11,16 @@ enum 6110 "E-Doc. Proc. Customizations" implements
IPurchaseOrderProvider,
IPurchaseLineProvider,
IUnitOfMeasureProvider,
- IEDocumentCreatePurchaseInvoice
+ IEDocumentCreatePurchaseInvoice,
+ IEDocumentCreatePurchaseCreditMemo
{
Extensible = true;
DefaultImplementation = IVendorProvider = "E-Doc. Providers",
IPurchaseOrderProvider = "E-Doc. Providers",
IPurchaseLineProvider = "E-Doc. Providers",
IUnitOfMeasureProvider = "E-Doc. Providers",
- IEDocumentCreatePurchaseInvoice = "E-Doc. Create Purchase Invoice";
+ IEDocumentCreatePurchaseInvoice = "E-Doc. Create Purchase Invoice",
+ IEDocumentCreatePurchaseCreditMemo = "E-Doc. Create Purch. Cr. Memo";
- value(0; Default)
- {
- }
+ value(0; Default) { }
}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/EDocProviders.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/EDocProviders.Codeunit.al
index 6e7ee356e7..5ef7a6bdf9 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/EDocProviders.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/EDocProviders.Codeunit.al
@@ -108,7 +108,10 @@ codeunit 6124 "E-Doc. Providers" implements IPurchaseLineProvider, IUnitOfMeasur
if GetPurchaseLineItemRef(EDocumentPurchaseLine, ItemReference) then begin
EDocumentPurchaseLine."[BC] Purchase Line Type" := "Purchase Line Type"::Item;
EDocumentPurchaseLine.Validate("[BC] Purchase Type No.", ItemReference."Item No.");
- EDocumentPurchaseLine.Validate("[BC] Unit of Measure", ItemReference."Unit of Measure");
+ if ItemReference."Unit of Measure" <> '' then
+ EDocumentPurchaseLine.Validate("[BC] Unit of Measure", ItemReference."Unit of Measure")
+ else
+ EDocumentPurchaseLine.Validate("[BC] Unit of Measure", GetDefaultUnitOfMeasure(ItemReference."Item No."));
EDocumentPurchaseLine.Validate("[BC] Variant Code", ItemReference."Variant Code");
EDocumentPurchaseLine.Validate("[BC] Item Reference No.", ItemReference."Reference No.");
EDocImpSessionTelemetry.SetLineBool(EDocumentPurchaseLine.SystemId, 'Item Reference ', true);
@@ -136,6 +139,11 @@ codeunit 6124 "E-Doc. Providers" implements IPurchaseLineProvider, IUnitOfMeasur
if PurchaseHeader.Get("Purchase Document Type"::Order, EDocumentPurchaseHeader."Purchase Order No.") then;
end;
+ procedure GetPurchaseInvoice(EDocumentPurchaseHeader: Record "E-Document Purchase Header") PurchaseHeader: Record "Purchase Header"
+ begin
+ if PurchaseHeader.Get("Purchase Document Type"::Invoice, EDocumentPurchaseHeader."Purchase Order No.") then;
+ end;
+
local procedure GetPurchaseLineItemRef(EDocumentPurchaseLine: Record "E-Document Purchase Line"; var ItemReference: Record "Item Reference"): Boolean
var
EDocument: Record "E-Document";
@@ -171,4 +179,14 @@ codeunit 6124 "E-Doc. Providers" implements IPurchaseLineProvider, IUnitOfMeasur
exit(true);
end;
+ local procedure GetDefaultUnitOfMeasure(ItemNo: Code[20]) UnitOfMeasureCode: Code[20];
+ var
+ Item: Record Item;
+ begin
+ if Item.Get(ItemNo) then
+ if Item."Purch. Unit of Measure" <> '' then
+ UnitOfMeasureCode := Item."Purch. Unit of Measure"
+ else
+ UnitOfMeasureCode := Item."Base Unit of Measure";
+ end;
}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/PreparePurchaseEDocDraft.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/PreparePurchaseEDocDraft.Codeunit.al
index 31a5c8abbc..dd82cbd833 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/PreparePurchaseEDocDraft.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/PrepareDraft/PreparePurchaseEDocDraft.Codeunit.al
@@ -26,7 +26,7 @@ codeunit 6125 "Prepare Purchase E-Doc. Draft" implements IProcessStructuredData
EDocumentPurchaseLine: Record "E-Document Purchase Line";
UnitOfMeasure: Record "Unit of Measure";
Vendor: Record Vendor;
- PurchaseOrder: Record "Purchase Header";
+ PurchaseHeader: Record "Purchase Header";
EDocVendorAssignmentHistory: Record "E-Doc. Vendor Assign. History";
EDocPurchaseLineHistory: Record "E-Doc. Purchase Line History";
EDocPurchaseHistMapping: Codeunit "E-Doc. Purchase Hist. Mapping";
@@ -48,13 +48,23 @@ codeunit 6125 "Prepare Purchase E-Doc. Draft" implements IProcessStructuredData
EDocumentPurchaseHeader."[BC] Vendor No." := Vendor."No.";
end;
- PurchaseOrder := IPurchaseOrderProvider.GetPurchaseOrder(EDocumentPurchaseHeader);
+ case Vendor."Receive E-Document To" of
+ Vendor."Receive E-Document To"::"Purchase Invoice":
+ PurchaseHeader := IPurchaseOrderProvider.GetPurchaseInvoice(EDocumentPurchaseHeader);
+ Vendor."Receive E-Document To"::"Purchase Order":
+ PurchaseHeader := IPurchaseOrderProvider.GetPurchaseOrder(EDocumentPurchaseHeader);
+ end;
- if PurchaseOrder."No." <> '' then begin
- PurchaseOrder.TestField("Document Type", "Purchase Document Type"::Order);
- EDocumentPurchaseHeader."[BC] Purchase Order No." := PurchaseOrder."No.";
+ if PurchaseHeader."No." <> '' then begin
+ case Vendor."Receive E-Document To" of
+ Vendor."Receive E-Document To"::"Purchase Invoice":
+ PurchaseHeader.TestField("Document Type", "Purchase Document Type"::Invoice);
+ Vendor."Receive E-Document To"::"Purchase Order":
+ PurchaseHeader.TestField("Document Type", "Purchase Document Type"::Order);
+ end;
+ EDocumentPurchaseHeader."[BC] Purchase Order No." := PurchaseHeader."No.";
EDocumentPurchaseHeader.Modify();
- exit("E-Document Type"::"Purchase Order");
+ exit(PurchaseHeader."Document Type" = "Purchase Document Type"::Order ? "E-Document Type"::"Purchase Order" : "E-Document Type"::"Purchase Invoice");
end;
if EDocPurchaseHistMapping.FindRelatedPurchaseHeaderInHistory(EDocument, EDocVendorAssignmentHistory) then
EDocPurchaseHistMapping.UpdateMissingHeaderValuesFromHistory(EDocVendorAssignmentHistory, EDocumentPurchaseHeader);
@@ -80,8 +90,6 @@ codeunit 6125 "Prepare Purchase E-Doc. Draft" implements IProcessStructuredData
EDocumentPurchaseLine.Modify();
LogActivitySessionChanges(EDocActivityLogSession);
EDocActivityLogSession.CleanUpLogs();
-
-
until EDocumentPurchaseLine.Next() = 0;
// Ask Copilot to try to find fields that are suited to be matched
@@ -89,7 +97,7 @@ codeunit 6125 "Prepare Purchase E-Doc. Draft" implements IProcessStructuredData
CopilotLineMatching(EDocument."Entry No");
if EDocActivityLogSession.EndSession() then;
- exit("E-Document Type"::"Purchase Invoice");
+ exit(EDocumentPurchaseHeader."E-Document Type");
end;
local procedure LogActivitySessionChanges(EDocActivityLogSession: Codeunit "E-Doc. Activity Log Session")
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al b/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al
index 3668a20614..53b1179575 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al
@@ -33,6 +33,12 @@ page 6183 "E-Doc. Purchase Draft Subform"
{
ApplicationArea = All;
Lookup = true;
+
+ trigger OnValidate()
+ begin
+ if Rec."[BC] Purchase Type No." <> xRec."[BC] Purchase Type No." then
+ Clear(Rec."[BC] Item Reference No.");
+ end;
}
field("Item Reference No."; Rec."[BC] Item Reference No.")
{
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al b/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al
index e9a08397d9..e046107b95 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al
@@ -247,7 +247,7 @@ page 6181 "E-Document Purchase Draft"
Visible = true;
trigger OnAction()
begin
- ResetDraft();
+ this.ResetDraft();
end;
}
action(AnalyzeDocument)
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al b/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al
index 93bb50f1c9..85403f3458 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al
@@ -6,9 +6,10 @@ namespace Microsoft.EServices.EDocument.Processing.Import.Purchase;
using Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.OrderMatch.Copilot;
-using System.Telemetry;
+using Microsoft.eServices.EDocument.Processing.Import;
using Microsoft.Purchases.Document;
using Microsoft.Purchases.Vendor;
+using System.Telemetry;
table 6100 "E-Document Purchase Header"
{
@@ -207,6 +208,16 @@ table 6100 "E-Document Purchase Header"
Caption = 'Vendor Contact Name';
DataClassification = CustomerContent;
}
+ field(38; "E-Document Type"; Enum "E-Document Type")
+ {
+ Caption = 'E-Document Type';
+ DataClassification = CustomerContent;
+ }
+ field(39; "Applies-to Doc. No."; Text[20])
+ {
+ Caption = 'Applies-to Doc. No.';
+ DataClassification = CustomerContent;
+ }
#endregion Purchase fields
#region Business Central Data - Validated fields [101-200]
@@ -233,9 +244,22 @@ table 6100 "E-Document Purchase Header"
}
trigger OnDelete()
+ var
+ EDocumentPurchaseLine: Record "E-Document Purchase Line";
+ EDocumentHeaderMapping: Record "E-Document Header Mapping";
+ EDocumentLineField: Record "E-Document Line - Field";
begin
Session.LogMessage('0000PCQ', DeleteDraftPerformedTxt, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, 'Category', EDocPOCopilotMatching.FeatureName());
FeatureTelemetry.LogUsage('0000PCV', EDocPOCopilotMatching.FeatureName(), 'Discard draft');
+
+ EDocumentPurchaseLine.SetRange("E-Document Entry No.", Rec."E-Document Entry No.");
+ EDocumentPurchaseLine.DeleteAll(true);
+
+ EDocumentHeaderMapping.SetRange("E-Document Entry No.", Rec."E-Document Entry No.");
+ EDocumentHeaderMapping.DeleteAll(true);
+
+ EDocumentLineField.SetRange("E-Document Entry No.", Rec."E-Document Entry No.");
+ EDocumentLineField.DeleteAll(true);
end;
procedure GetFromEDocument(EDocument: Record "E-Document")
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al
index 7dc7cffc71..03378188f3 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al
@@ -131,6 +131,14 @@ codeunit 6174 "E-Document ADI Handler" implements IStructureReceivedEDocument, I
EDocReadablePurchaseDoc.Run();
end;
+ procedure ResetDraft(EDocument: Record "E-Document")
+ var
+ EDocPurchaseHeader: Record "E-Document Purchase Header";
+ begin
+ EDocPurchaseHeader.GetFromEDocument(EDocument);
+ EDocPurchaseHeader.Delete(true);
+ end;
+
local procedure PopulateEDocumentPurchaseLines(ItemsArray: JsonArray; EDocumentEntryNo: Integer; var TempEDocPurchaseLine: Record "E-Document Purchase Line" temporary)
var
JsonTokenTemp, ItemToken : JsonToken;
diff --git a/Apps/W1/EDocument/app/src/Processing/Import/StructureReceivedEDocument/EDocumentPEPPOLHandler.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/Import/StructureReceivedEDocument/EDocumentPEPPOLHandler.Codeunit.al
index 1479acb301..132d442c1e 100644
--- a/Apps/W1/EDocument/app/src/Processing/Import/StructureReceivedEDocument/EDocumentPEPPOLHandler.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Processing/Import/StructureReceivedEDocument/EDocumentPEPPOLHandler.Codeunit.al
@@ -4,12 +4,12 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.eServices.EDocument.Format;
+using Microsoft.EServices.EDocument.Processing.Import.Purchase;
using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Helpers;
using Microsoft.eServices.EDocument.Processing.Import;
-using Microsoft.eServices.EDocument.Processing.Import.Purchase;
using Microsoft.eServices.EDocument.Processing.Interfaces;
using System.Utilities;
-using Microsoft.Finance.GeneralLedger.Setup;
codeunit 6173 "E-Document PEPPOL Handler" implements IStructuredFormatReader
{
@@ -30,7 +30,6 @@ codeunit 6173 "E-Document PEPPOL Handler" implements IStructuredFormatReader
QualifiedDatatypesLbl: Label 'urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2';
UnqualifiedDataTypesSchemaModuleLbl: Label 'urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2';
DefaultInvoiceLbl: Label 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2';
- CreditNoteNotSupportedLbl: Label 'Credit notes are not supported';
begin
EDocumentPurchaseHeader.InsertForEDocument(EDocument);
@@ -47,11 +46,16 @@ codeunit 6173 "E-Document PEPPOL Handler" implements IStructuredFormatReader
case UpperCase(XmlElement.LocalName()) of
'INVOICE':
begin
+ EDocumentPurchaseHeader."E-Document Type" := "E-Document Type"::"Purchase Invoice";
PopulatePurchaseInvoiceHeader(PeppolXML, XmlNamespaces, EDocumentPurchaseHeader);
InsertPurchaseInvoiceLines(PeppolXML, XmlNamespaces, EDocumentPurchaseHeader."E-Document Entry No.");
end;
'CREDITNOTE':
- Error(CreditNoteNotSupportedLbl);
+ begin
+ EDocumentPurchaseHeader."E-Document Type" := "E-Document Type"::"Purchase Credit Memo";
+ PopulatePurchaseCreditMemoHeader(PeppolXML, XmlNamespaces, EDocumentPurchaseHeader);
+ InsertPurchaseCreditMemoLines(PeppolXML, XmlNamespaces, EDocumentPurchaseHeader."E-Document Entry No.");
+ end;
end;
EDocumentPurchaseHeader.Modify();
EDocument.Direction := EDocument.Direction::Incoming;
@@ -81,126 +85,160 @@ codeunit 6173 "E-Document PEPPOL Handler" implements IStructuredFormatReader
end;
end;
+ local procedure InsertPurchaseCreditMemoLines(PeppolXML: XmlDocument; XmlNamespaces: XmlNamespaceManager; EDocumentEntryNo: Integer)
+ var
+ EDocumentPurchaseLine: Record "E-Document Purchase Line";
+ NewLineXML: XmlDocument;
+ LineXMLList: XmlNodeList;
+ LineXMLNode: XmlNode;
+ CreditNoteLinePathLbl: Label '/cn:CreditNote/cac:CreditNoteLine';
+ CreditNoteNamespaceLbl: Label 'urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2';
+ begin
+ // Add CreditNote namespace for proper line parsing
+ XmlNamespaces.AddNamespace('cn', CreditNoteNamespaceLbl);
+
+ if not PeppolXML.SelectNodes(CreditNoteLinePathLbl, XmlNamespaces, LineXMLList) then
+ exit;
+
+ foreach LineXMLNode in LineXMLList do begin
+ Clear(EDocumentPurchaseLine);
+ EDocumentPurchaseLine.Validate("E-Document Entry No.", EDocumentEntryNo);
+ EDocumentPurchaseLine."Line No." := EDocumentPurchaseLine.GetNextLineNo(EDocumentEntryNo);
+ NewLineXML.ReplaceNodes(LineXMLNode);
+ PopulateEDocumentPurchaseCreditMemoLine(NewLineXML, XmlNamespaces, EDocumentPurchaseLine);
+ EDocumentPurchaseLine.Insert(false);
+ end;
+ end;
+
#pragma warning disable AA0139 // false positive: overflow handled by SetStringValueInField
local procedure PopulatePurchaseInvoiceHeader(PeppolXML: XmlDocument; XmlNamespaces: XmlNamespaceManager; var EDocumentPurchaseHeader: Record "E-Document Purchase Header")
var
+ EDocumentXMLHelper: Codeunit "EDocument XML Helper";
XMLNode: XmlNode;
begin
- SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cbc:ID', MaxStrLen(EDocumentPurchaseHeader."Sales Invoice No."), EDocumentPurchaseHeader."Sales Invoice No.");
- SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:OrderReference/cbc:ID', MaxStrLen(EDocumentPurchaseHeader."Purchase Order No."), EDocumentPurchaseHeader."Purchase Order No.");
- SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Vendor Company Name"), EDocumentPurchaseHeader."Vendor Company Name");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cbc:ID', MaxStrLen(EDocumentPurchaseHeader."Sales Invoice No."), EDocumentPurchaseHeader."Sales Invoice No.");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:OrderReference/cbc:ID', MaxStrLen(EDocumentPurchaseHeader."Purchase Order No."), EDocumentPurchaseHeader."Purchase Order No.");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Vendor Company Name"), EDocumentPurchaseHeader."Vendor Company Name");
// Line below, using PayeeParty, shall be used when the Payee is different from the Seller. Otherwise, it will not be shown in the XML.
- SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:PayeeParty/cac:PartyName/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Vendor Company Name"), EDocumentPurchaseHeader."Vendor Company Name");
- SetNumberValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:LegalMonetaryTotal/cbc:AllowanceTotalAmount', EDocumentPurchaseHeader."Total Discount");
- SetNumberValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:LegalMonetaryTotal/cbc:PayableAmount', EDocumentPurchaseHeader."Amount Due");
- SetNumberValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:LegalMonetaryTotal/cbc:PayableAmount', EDocumentPurchaseHeader.Total);
- SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:Contact/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Vendor Contact Name"), EDocumentPurchaseHeader."Vendor Contact Name");
- SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cbc:StreetName', MaxStrLen(EDocumentPurchaseHeader."Vendor Address"), EDocumentPurchaseHeader."Vendor Address");
- SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Customer VAT Id"), EDocumentPurchaseHeader."Customer VAT Id");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:PayeeParty/cac:PartyName/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Vendor Company Name"), EDocumentPurchaseHeader."Vendor Company Name");
+ EDocumentXMLHelper.SetNumberValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:LegalMonetaryTotal/cbc:AllowanceTotalAmount', EDocumentPurchaseHeader."Total Discount");
+ EDocumentXMLHelper.SetNumberValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:LegalMonetaryTotal/cbc:PayableAmount', EDocumentPurchaseHeader."Amount Due");
+ EDocumentXMLHelper.SetNumberValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:LegalMonetaryTotal/cbc:PayableAmount', EDocumentPurchaseHeader.Total);
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:Contact/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Vendor Contact Name"), EDocumentPurchaseHeader."Vendor Contact Name");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cbc:StreetName', MaxStrLen(EDocumentPurchaseHeader."Vendor Address"), EDocumentPurchaseHeader."Vendor Address");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Customer VAT Id"), EDocumentPurchaseHeader."Customer VAT Id");
// Line below, using PayeeParty, shall be used when the Payee is different from the Seller. Otherwise, it will not be shown in the XML.
- SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:PayeeParty/cac:PartyLegalEntity/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Vendor VAT Id"), EDocumentPurchaseHeader."Vendor VAT Id");
- SetNumberValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount', EDocumentPurchaseHeader."Sub Total");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:PayeeParty/cac:PartyLegalEntity/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Vendor VAT Id"), EDocumentPurchaseHeader."Vendor VAT Id");
+ EDocumentXMLHelper.SetNumberValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount', EDocumentPurchaseHeader."Sub Total");
EDocumentPurchaseHeader."Total VAT" := EDocumentPurchaseHeader."Total" - EDocumentPurchaseHeader."Sub Total" - EDocumentPurchaseHeader."Total Discount";
- SetDateValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cbc:DueDate', EDocumentPurchaseHeader."Due Date");
- SetDateValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cbc:IssueDate', EDocumentPurchaseHeader."Document Date");
- SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Vendor VAT Id"), EDocumentPurchaseHeader."Vendor VAT Id");
- SetCurrencyValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cbc:DocumentCurrencyCode', MaxStrLen(EDocumentPurchaseHeader."Currency Code"), EDocumentPurchaseHeader."Currency Code");
- SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyName/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Customer Company Name"), EDocumentPurchaseHeader."Customer Company Name");
- SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Customer VAT Id"), EDocumentPurchaseHeader."Customer VAT Id");
- SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PostalAddress/cbc:StreetName', MaxStrLen(EDocumentPurchaseHeader."Customer Address"), EDocumentPurchaseHeader."Customer Address");
- SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cbc:EndpointID', MaxStrLen(EDocumentPurchaseHeader."Customer GLN"), EDocumentPurchaseHeader."Customer GLN");
- SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cbc:EndpointID/@schemeID', MaxStrLen(EDocumentPurchaseHeader."Customer Company Id"), EDocumentPurchaseHeader."Customer Company Id");
+ EDocumentXMLHelper.SetDateValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cbc:DueDate', EDocumentPurchaseHeader."Due Date");
+ EDocumentXMLHelper.SetDateValueInField(PeppolXML, XMLNamespaces, '/inv:Invoice/cbc:IssueDate', EDocumentPurchaseHeader."Document Date");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Vendor VAT Id"), EDocumentPurchaseHeader."Vendor VAT Id");
+ EDocumentXMLHelper.SetCurrencyValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cbc:DocumentCurrencyCode', MaxStrLen(EDocumentPurchaseHeader."Currency Code"), EDocumentPurchaseHeader."Currency Code");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyName/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Customer Company Name"), EDocumentPurchaseHeader."Customer Company Name");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Customer VAT Id"), EDocumentPurchaseHeader."Customer VAT Id");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PostalAddress/cbc:StreetName', MaxStrLen(EDocumentPurchaseHeader."Customer Address"), EDocumentPurchaseHeader."Customer Address");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cbc:EndpointID', MaxStrLen(EDocumentPurchaseHeader."Customer GLN"), EDocumentPurchaseHeader."Customer GLN");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingCustomerParty/cac:Party/cbc:EndpointID/@schemeID', MaxStrLen(EDocumentPurchaseHeader."Customer Company Id"), EDocumentPurchaseHeader."Customer Company Id");
if PeppolXML.SelectSingleNode('/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cbc:EndpointID/@schemeID', XmlNamespaces, XMLNode) then
if XMLNode.AsXmlAttribute().Value() = '0088' then // GLN
- SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cbc:EndpointID', MaxStrLen(EDocumentPurchaseHeader."Vendor GLN"), EDocumentPurchaseHeader."Vendor GLN");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cbc:EndpointID', MaxStrLen(EDocumentPurchaseHeader."Vendor GLN"), EDocumentPurchaseHeader."Vendor GLN");
end;
- local procedure PopulateEDocumentPurchaseLine(LineXML: XmlDocument; XmlNamespaces: XmlNamespaceManager; var EDocumentPurchaseLine: Record "E-Document Purchase Line")
- begin
- SetNumberValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cbc:InvoicedQuantity', EDocumentPurchaseLine.Quantity);
- SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cbc:InvoicedQuantity/@unitCode', MaxStrLen(EDocumentPurchaseLine."Unit of Measure"), EDocumentPurchaseLine."Unit of Measure");
- SetNumberValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cbc:LineExtensionAmount', EDocumentPurchaseLine."Sub Total");
- SetCurrencyValueInField(LineXML, XmlNamespaces, 'cac:InvoiceLine/cbc:LineExtensionAmount/@currencyID', MaxStrLen(EDocumentPurchaseLine."Currency Code"), EDocumentPurchaseLine."Currency Code");
- SetNumberValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:AllowanceCharge/cbc:Amount', EDocumentPurchaseLine."Total Discount");
- SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cbc:Note', MaxStrLen(EDocumentPurchaseLine.Description), EDocumentPurchaseLine.Description);
- SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Item/cbc:Name', MaxStrLen(EDocumentPurchaseLine.Description), EDocumentPurchaseLine.Description);
- SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Item/cbc:Description', MaxStrLen(EDocumentPurchaseLine.Description), EDocumentPurchaseLine.Description);
- SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Item/cac:SellersItemIdentification/cbc:ID', MaxStrLen(EDocumentPurchaseLine."Product Code"), EDocumentPurchaseLine."Product Code");
- SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Item/cac:StandardItemIdentification/cbc:ID', MaxStrLen(EDocumentPurchaseLine."Product Code"), EDocumentPurchaseLine."Product Code");
- SetNumberValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Item/cac:ClassifiedTaxCategory/cbc:Percent', EDocumentPurchaseLine."VAT Rate");
- SetNumberValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Price/cbc:PriceAmount', EDocumentPurchaseLine."Unit Price");
- end;
-
- local procedure SetCurrencyValueInField(XMLDocument: XmlDocument; XMLNamespaces: XmlNamespaceManager; Path: Text; MaxLength: Integer; var CurrencyField: Code[10])
+ local procedure PopulatePurchaseCreditMemoHeader(PeppolXML: XmlDocument; XmlNamespaces: XmlNamespaceManager; var EDocumentPurchaseHeader: Record "E-Document Purchase Header")
var
- GLSetup: Record "General Ledger Setup";
+ EDocumentXMLHelper: Codeunit "EDocument XML Helper";
XMLNode: XmlNode;
- CurrencyCode: Code[10];
+ CreditNoteNamespaceLbl: Label 'urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2';
begin
- if not XMLDocument.SelectSingleNode(Path, XMLNamespaces, XMLNode) then
- exit;
+ // Add CreditNote namespace for proper header parsing
+ XmlNamespaces.AddNamespace('cn', CreditNoteNamespaceLbl);
- GLSetup.Get();
-
- if XMLNode.IsXmlElement() then begin
- CurrencyCode := CopyStr(XMLNode.AsXmlElement().InnerText(), 1, MaxLength);
- if GLSetup."LCY Code" <> CurrencyCode then
- CurrencyField := CurrencyCode;
- exit;
- end;
-
- if XMLNode.IsXmlAttribute() then begin
- CurrencyCode := CopyStr(XMLNode.AsXmlAttribute().Value, 1, MaxLength);
- if GLSetup."LCY Code" <> CurrencyCode then
- CurrencyField := CurrencyCode;
- exit;
- end;
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cbc:ID', MaxStrLen(EDocumentPurchaseHeader."Sales Invoice No."), EDocumentPurchaseHeader."Sales Invoice No.");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:OrderReference/cbc:ID', MaxStrLen(EDocumentPurchaseHeader."Purchase Order No."), EDocumentPurchaseHeader."Purchase Order No.");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:BillingReference/cac:InvoiceDocumentReference/cbc:ID', MaxStrLen(EDocumentPurchaseHeader."Applies-to Doc. No."), EDocumentPurchaseHeader."Applies-to Doc. No.");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Vendor Company Name"), EDocumentPurchaseHeader."Vendor Company Name");
+ // Line below, using PayeeParty, shall be used when the Payee is different from the Seller. Otherwise, it will not be shown in the XML.
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:PayeeParty/cac:PartyName/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Vendor Company Name"), EDocumentPurchaseHeader."Vendor Company Name");
+ EDocumentXMLHelper.SetNumberValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:LegalMonetaryTotal/cbc:AllowanceTotalAmount', EDocumentPurchaseHeader."Total Discount");
+ EDocumentXMLHelper.SetNumberValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:LegalMonetaryTotal/cbc:PayableAmount', EDocumentPurchaseHeader."Amount Due");
+ EDocumentXMLHelper.SetNumberValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:LegalMonetaryTotal/cbc:PayableAmount', EDocumentPurchaseHeader.Total);
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:AccountingSupplierParty/cac:Party/cac:Contact/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Vendor Contact Name"), EDocumentPurchaseHeader."Vendor Contact Name");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cbc:StreetName', MaxStrLen(EDocumentPurchaseHeader."Vendor Address"), EDocumentPurchaseHeader."Vendor Address");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Customer VAT Id"), EDocumentPurchaseHeader."Customer VAT Id");
+ // Line below, using PayeeParty, shall be used when the Payee is different from the Seller. Otherwise, it will not be shown in the XML.
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:PayeeParty/cac:PartyLegalEntity/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Vendor VAT Id"), EDocumentPurchaseHeader."Vendor VAT Id");
+ EDocumentXMLHelper.SetNumberValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount', EDocumentPurchaseHeader."Sub Total");
+ EDocumentPurchaseHeader."Total VAT" := EDocumentPurchaseHeader."Total" - EDocumentPurchaseHeader."Sub Total" - EDocumentPurchaseHeader."Total Discount";
+ EDocumentXMLHelper.SetDateValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cac:PaymentMeans/cbc:PaymentDueDate', EDocumentPurchaseHeader."Due Date");
+ EDocumentXMLHelper.SetDateValueInField(PeppolXML, XMLNamespaces, '/cn:CreditNote/cbc:IssueDate', EDocumentPurchaseHeader."Document Date");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/cn:CreditNote/cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Vendor VAT Id"), EDocumentPurchaseHeader."Vendor VAT Id");
+ EDocumentXMLHelper.SetCurrencyValueInField(PeppolXML, XmlNamespaces, '/cn:CreditNote/cbc:DocumentCurrencyCode', MaxStrLen(EDocumentPurchaseHeader."Currency Code"), EDocumentPurchaseHeader."Currency Code");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/cn:CreditNote/cac:AccountingCustomerParty/cac:Party/cac:PartyName/cbc:Name', MaxStrLen(EDocumentPurchaseHeader."Customer Company Name"), EDocumentPurchaseHeader."Customer Company Name");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/cn:CreditNote/cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID', MaxStrLen(EDocumentPurchaseHeader."Customer VAT Id"), EDocumentPurchaseHeader."Customer VAT Id");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/cn:CreditNote/cac:AccountingCustomerParty/cac:Party/cac:PostalAddress/cbc:StreetName', MaxStrLen(EDocumentPurchaseHeader."Customer Address"), EDocumentPurchaseHeader."Customer Address");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/cn:CreditNote/cac:AccountingCustomerParty/cac:Party/cbc:EndpointID', MaxStrLen(EDocumentPurchaseHeader."Customer GLN"), EDocumentPurchaseHeader."Customer GLN");
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/cn:CreditNote/cac:AccountingCustomerParty/cac:Party/cbc:EndpointID/@schemeID', MaxStrLen(EDocumentPurchaseHeader."Customer Company Id"), EDocumentPurchaseHeader."Customer Company Id");
+
+ if PeppolXML.SelectSingleNode('/cn:CreditNote/cac:AccountingSupplierParty/cac:Party/cbc:EndpointID/@schemeID', XmlNamespaces, XMLNode) then
+ if XMLNode.AsXmlAttribute().Value() = '0088' then // GLN
+ EDocumentXMLHelper.SetStringValueInField(PeppolXML, XmlNamespaces, '/cn:CreditNote/cac:AccountingSupplierParty/cac:Party/cbc:EndpointID', MaxStrLen(EDocumentPurchaseHeader."Vendor GLN"), EDocumentPurchaseHeader."Vendor GLN");
end;
-#pragma warning restore AA0139
- local procedure SetStringValueInField(XMLDocument: XmlDocument; XMLNamespaces: XmlNamespaceManager; Path: Text; MaxLength: Integer; var Field: Text)
+ local procedure PopulateEDocumentPurchaseLine(LineXML: XmlDocument; XmlNamespaces: XmlNamespaceManager; var EDocumentPurchaseLine: Record "E-Document Purchase Line")
var
- XMLNode: XmlNode;
+ EDocumentXMLHelper: Codeunit "EDocument XML Helper";
begin
- if not XMLDocument.SelectSingleNode(Path, XMLNamespaces, XMLNode) then
- exit;
-
- if XMLNode.IsXmlElement() then begin
- Field := CopyStr(XMLNode.AsXmlElement().InnerText(), 1, MaxLength);
- exit;
- end;
-
- if XMLNode.IsXmlAttribute() then begin
- Field := CopyStr(XMLNode.AsXmlAttribute().Value(), 1, MaxLength);
- exit;
- end;
+ EDocumentXMLHelper.SetNumberValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cbc:InvoicedQuantity', EDocumentPurchaseLine.Quantity);
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cbc:InvoicedQuantity/@unitCode', MaxStrLen(EDocumentPurchaseLine."Unit of Measure"), EDocumentPurchaseLine."Unit of Measure");
+ EDocumentXMLHelper.SetNumberValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cbc:LineExtensionAmount', EDocumentPurchaseLine."Sub Total");
+ EDocumentXMLHelper.SetCurrencyValueInField(LineXML, XmlNamespaces, 'cac:InvoiceLine/cbc:LineExtensionAmount/@currencyID', MaxStrLen(EDocumentPurchaseLine."Currency Code"), EDocumentPurchaseLine."Currency Code");
+ EDocumentXMLHelper.SetNumberValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:AllowanceCharge/cbc:Amount', EDocumentPurchaseLine."Total Discount");
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cbc:Note', MaxStrLen(EDocumentPurchaseLine.Description), EDocumentPurchaseLine.Description);
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Item/cbc:Name', MaxStrLen(EDocumentPurchaseLine.Description), EDocumentPurchaseLine.Description);
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Item/cbc:Description', MaxStrLen(EDocumentPurchaseLine.Description), EDocumentPurchaseLine.Description);
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Item/cac:SellersItemIdentification/cbc:ID', MaxStrLen(EDocumentPurchaseLine."Product Code"), EDocumentPurchaseLine."Product Code");
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Item/cac:StandardItemIdentification/cbc:ID', MaxStrLen(EDocumentPurchaseLine."Product Code"), EDocumentPurchaseLine."Product Code");
+ EDocumentXMLHelper.SetNumberValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Item/cac:ClassifiedTaxCategory/cbc:Percent', EDocumentPurchaseLine."VAT Rate");
+ EDocumentXMLHelper.SetNumberValueInField(LineXML, XMLNamespaces, 'cac:InvoiceLine/cac:Price/cbc:PriceAmount', EDocumentPurchaseLine."Unit Price");
end;
- local procedure SetNumberValueInField(XMLDocument: XmlDocument; XMLNamespaces: XmlNamespaceManager; Path: Text; var DecimalValue: Decimal)
+ local procedure PopulateEDocumentPurchaseCreditMemoLine(LineXML: XmlDocument; XmlNamespaces: XmlNamespaceManager; var EDocumentPurchaseLine: Record "E-Document Purchase Line")
var
- XMLNode: XmlNode;
+ EDocumentXMLHelper: Codeunit "EDocument XML Helper";
begin
- if not XMLDocument.SelectSingleNode(Path, XMLNamespaces, XMLNode) then
- exit;
-
- if XMLNode.AsXmlElement().InnerText() <> '' then
- Evaluate(DecimalValue, XMLNode.AsXmlElement().InnerText(), 9);
+ EDocumentXMLHelper.SetNumberValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cbc:CreditedQuantity', EDocumentPurchaseLine.Quantity);
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cbc:CreditedQuantity/@unitCode', MaxStrLen(EDocumentPurchaseLine."Unit of Measure"), EDocumentPurchaseLine."Unit of Measure");
+ EDocumentXMLHelper.SetNumberValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cbc:LineExtensionAmount', EDocumentPurchaseLine."Sub Total");
+ EDocumentXMLHelper.SetCurrencyValueInField(LineXML, XmlNamespaces, 'cac:CreditNoteLine/cbc:LineExtensionAmount/@currencyID', MaxStrLen(EDocumentPurchaseLine."Currency Code"), EDocumentPurchaseLine."Currency Code");
+ EDocumentXMLHelper.SetNumberValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cac:AllowanceCharge/cbc:Amount', EDocumentPurchaseLine."Total Discount");
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cbc:Note', MaxStrLen(EDocumentPurchaseLine.Description), EDocumentPurchaseLine.Description);
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cac:Item/cbc:Name', MaxStrLen(EDocumentPurchaseLine.Description), EDocumentPurchaseLine.Description);
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cac:Item/cbc:Description', MaxStrLen(EDocumentPurchaseLine.Description), EDocumentPurchaseLine.Description);
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cac:Item/cac:SellersItemIdentification/cbc:ID', MaxStrLen(EDocumentPurchaseLine."Product Code"), EDocumentPurchaseLine."Product Code");
+ EDocumentXMLHelper.SetStringValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cac:Item/cac:StandardItemIdentification/cbc:ID', MaxStrLen(EDocumentPurchaseLine."Product Code"), EDocumentPurchaseLine."Product Code");
+ EDocumentXMLHelper.SetNumberValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cac:Item/cac:ClassifiedTaxCategory/cbc:Percent', EDocumentPurchaseLine."VAT Rate");
+ EDocumentXMLHelper.SetNumberValueInField(LineXML, XMLNamespaces, 'cac:CreditNoteLine/cac:Price/cbc:PriceAmount', EDocumentPurchaseLine."Unit Price");
end;
- local procedure SetDateValueInField(XMLDocument: XmlDocument; XMLNamespaces: XmlNamespaceManager; Path: Text; var DateValue: Date)
+ procedure View(EDocument: Record "E-Document"; TempBlob: Codeunit "Temp Blob")
var
- XMLNode: XmlNode;
+ EDocPurchaseHeader: Record "E-Document Purchase Header";
+ EDocPurchaseLine: Record "E-Document Purchase Line";
+ EDocReadablePurchaseDoc: Page "E-Doc. Readable Purchase Doc.";
begin
- if not XMLDocument.SelectSingleNode(Path, XMLNamespaces, XMLNode) then
- exit;
-
- if XMLNode.AsXmlElement().InnerText() <> '' then
- Evaluate(DateValue, XMLNode.AsXmlElement().InnerText(), 9);
+ EDocPurchaseHeader.GetFromEDocument(EDocument);
+ EDocPurchaseLine.SetRange("E-Document Entry No.", EDocPurchaseHeader."E-Document Entry No.");
+ EDocReadablePurchaseDoc.SetBuffer(EDocPurchaseHeader, EDocPurchaseLine);
+ EDocReadablePurchaseDoc.Run();
end;
- procedure View(EDocument: Record "E-Document"; TempBlob: Codeunit "Temp Blob")
+ procedure ResetDraft(EDocument: Record "E-Document")
+ var
+ EDocPurchaseHeader: Record "E-Document Purchase Header";
begin
- Error('A view is not implemented for this handler.');
+ EDocPurchaseHeader.GetFromEDocument(EDocument);
+ EDocPurchaseHeader.Delete(true);
end;
}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Processing/Interfaces/IEDocumentCreatePurchaseCreditMemo.Interface.al b/Apps/W1/EDocument/app/src/Processing/Interfaces/IEDocumentCreatePurchaseCreditMemo.Interface.al
new file mode 100644
index 0000000000..a657e831b7
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Processing/Interfaces/IEDocumentCreatePurchaseCreditMemo.Interface.al
@@ -0,0 +1,21 @@
+// ------------------------------------------------------------------------------------------------
+// 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.Processing.Interfaces;
+
+using Microsoft.eServices.EDocument;
+using Microsoft.Purchases.Document;
+
+///
+/// Interface for changing the way that purchase credit memos get created from an E-Document.
+///
+interface IEDocumentCreatePurchaseCreditMemo
+{
+ ///
+ /// Creates a purchase credit memo from an E-Document with a draft ready.
+ ///
+ /// The E-Document record to create the purchase credit memo from.
+ /// The created purchase header record for the credit memo.
+ procedure CreatePurchaseCreditMemo(EDocument: Record "E-Document"): Record "Purchase Header";
+}
diff --git a/Apps/W1/EDocument/app/src/Processing/Interfaces/IPurchaseOrderProvider.Interface.al b/Apps/W1/EDocument/app/src/Processing/Interfaces/IPurchaseOrderProvider.Interface.al
index 0d8745628c..8d996ba1c5 100644
--- a/Apps/W1/EDocument/app/src/Processing/Interfaces/IPurchaseOrderProvider.Interface.al
+++ b/Apps/W1/EDocument/app/src/Processing/Interfaces/IPurchaseOrderProvider.Interface.al
@@ -18,4 +18,11 @@ interface IPurchaseOrderProvider
/// The E-Document purchase header record containing order details.
/// A Purchase Header record matching the provided E-Document purchase header.
procedure GetPurchaseOrder(EDocumentPurchaseHeader: Record "E-Document Purchase Header"): Record "Purchase Header";
+
+ ///
+ /// Retrieves the corresponding purchase invoice for a given E-Document purchase header.
+ ///
+ /// The E-Document purchase header record containing invoice details.
+ /// A Purchase Header record matching the provided E-Document purchase header.
+ procedure GetPurchaseInvoice(EDocumentPurchaseHeader: Record "E-Document Purchase Header"): Record "Purchase Header";
}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Processing/Interfaces/IStructuredFormatReader.Interface.al b/Apps/W1/EDocument/app/src/Processing/Interfaces/IStructuredFormatReader.Interface.al
index 219c281c6f..2001cbe86b 100644
--- a/Apps/W1/EDocument/app/src/Processing/Interfaces/IStructuredFormatReader.Interface.al
+++ b/Apps/W1/EDocument/app/src/Processing/Interfaces/IStructuredFormatReader.Interface.al
@@ -14,7 +14,6 @@ using System.Utilities;
///
interface IStructuredFormatReader
{
-
///
/// Read the data into the E-Document data structures.
///
@@ -23,7 +22,6 @@ interface IStructuredFormatReader
/// The data process to run on the structured data.
procedure ReadIntoDraft(EDocument: Record "E-Document"; TempBlob: Codeunit "Temp Blob"): Enum "E-Doc. Process Draft";
-
///
/// Presents a view of the data
///
@@ -31,4 +29,9 @@ interface IStructuredFormatReader
/// The temporary blob that contains the data to read
procedure View(EDocument: Record "E-Document"; TempBlob: Codeunit "Temp Blob");
+ ///
+ /// Resets draft by removing all the created lines associated with the E-Document.
+ ///
+ /// The E-Document record for which to remove the created draft lines.
+ procedure ResetDraft(EDocument: Record "E-Document");
}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Processing/Interfaces/IUnitOfMeasureProvider.Interface.al b/Apps/W1/EDocument/app/src/Processing/Interfaces/IUnitOfMeasureProvider.Interface.al
index 7f99c09200..96e3342d00 100644
--- a/Apps/W1/EDocument/app/src/Processing/Interfaces/IUnitOfMeasureProvider.Interface.al
+++ b/Apps/W1/EDocument/app/src/Processing/Interfaces/IUnitOfMeasureProvider.Interface.al
@@ -5,6 +5,7 @@
namespace Microsoft.eServices.EDocument.Processing.Interfaces;
using Microsoft.eServices.EDocument;
+using Microsoft.Purchases.Document;
using Microsoft.Foundation.UOM;
///
diff --git a/Apps/W1/EDocument/test/src/Processing/EDocPDFMock.Codeunit.al b/Apps/W1/EDocument/test/src/Processing/EDocPDFMock.Codeunit.al
index 34a7851b3e..fd76b624c1 100644
--- a/Apps/W1/EDocument/test/src/Processing/EDocPDFMock.Codeunit.al
+++ b/Apps/W1/EDocument/test/src/Processing/EDocPDFMock.Codeunit.al
@@ -37,5 +37,7 @@ codeunit 139782 "E-Doc PDF Mock" implements IStructureReceivedEDocument, IStruct
begin
exit("E-Doc. Read into Draft"::Unspecified);
end;
-
-}
+ procedure ResetDraft(EDocument: Record "E-Document")
+ begin
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/test/src/Processing/EDocumentStructuredTests.Codeunit.al b/Apps/W1/EDocument/test/src/Processing/EDocumentStructuredTests.Codeunit.al
index ee7a702132..a7a3aa5640 100644
--- a/Apps/W1/EDocument/test/src/Processing/EDocumentStructuredTests.Codeunit.al
+++ b/Apps/W1/EDocument/test/src/Processing/EDocumentStructuredTests.Codeunit.al
@@ -16,6 +16,8 @@ codeunit 139891 "E-Document Structured Tests"
PEPPOLStructuredValidations: Codeunit "PEPPOL Structured Validations";
IsInitialized: Boolean;
EDocumentStatusNotUpdatedErr: Label 'The status of the EDocument was not updated to the expected status after the step was executed.';
+ MockCurrencyCode: Code[10];
+ MockDate: Date;
#region CAPI JSON
[Test]
@@ -75,11 +77,129 @@ codeunit 139891 "E-Document Structured Tests"
Initialize(Enum::"Service Integration"::"Mock");
SetupPEPPOLEDocumentService();
CreateInboundEDocumentFromXML(EDocument, 'peppol/peppol-invoice-0.xml');
- if ProcessEDocumentToStep(EDocument, "Import E-Document Steps"::"Read into Draft") then
- PEPPOLStructuredValidations.AssertFullEDocumentContentExtracted(EDocument."Entry No")
+ if ProcessEDocumentToStep(EDocument, "Import E-Document Steps"::"Read into Draft") then begin
+ PEPPOLStructuredValidations.SetMockCurrencyCode(MockCurrencyCode);
+ PEPPOLStructuredValidations.SetMockDate(MockDate);
+ PEPPOLStructuredValidations.AssertFullEDocumentContentExtracted(EDocument."Entry No");
+ end
else
Assert.Fail(EDocumentStatusNotUpdatedErr);
end;
+
+ [Test]
+ [HandlerFunctions('EDocumentPurchaseHeaderPageHandler')]
+ procedure TestPEPPOLInvoice_ValidDocument_ViewExtractedData()
+ var
+ EDocument: Record "E-Document";
+ EDocImport: Codeunit "E-Doc. Import";
+ begin
+ // [FEATURE] [E-Document] [PEPPOL] [View Data]
+ // [SCENARIO] View extracted data from a valid PEPPOL invoice document
+
+ // [GIVEN] A valid PEPPOL XML invoice document is imported
+ Initialize(Enum::"Service Integration"::"Mock");
+ SetupPEPPOLEDocumentService();
+ CreateInboundEDocumentFromXML(EDocument, 'peppol/peppol-invoice-0.xml');
+
+ // [WHEN] The document is processed to draft status
+ ProcessEDocumentToStep(EDocument, "Import E-Document Steps"::"Read into Draft");
+ EDocument.Get(EDocument."Entry No");
+
+ // [WHEN] View extracted data is called
+ EDocImport.ViewExtractedData(EDocument);
+
+ // [THEN] The extracted data page opens and can be handled properly (verified by page handler)
+ // EDocumentPurchaseHeaderPageHandler
+ end;
+
+ [Test]
+ procedure TestPEPPOLInvoice_ValidDocument_PurchaseInvoiceCreated()
+ var
+ EDocument: Record "E-Document";
+ PurchaseHeader: Record "Purchase Header";
+ DummyItem: Record Item;
+ EDocumentProcessing: Codeunit "E-Document Processing";
+ DataTypeManagement: Codeunit "Data Type Management";
+ RecRef: RecordRef;
+ VariantRecord: Variant;
+ begin
+ // [FEATURE] [E-Document] [PEPPOL] [Purchase Invoice Creation]
+ // [SCENARIO] Create a purchase invoice from a valid PEPPOL invoice document
+
+ // [GIVEN] A valid PEPPOL XML invoice document is imported
+ Initialize(Enum::"Service Integration"::"Mock");
+ SetupPEPPOLEDocumentService();
+ CreateInboundEDocumentFromXML(EDocument, 'peppol/peppol-invoice-0.xml');
+
+ // [WHEN] The document is processed through finish draft step
+ ProcessEDocumentToStep(EDocument, "Import E-Document Steps"::"Finish draft");
+ EDocument.Get(EDocument."Entry No");
+
+ // [WHEN] The created purchase record is retrieved
+ EDocumentProcessing.GetRecord(EDocument, VariantRecord);
+ DataTypeManagement.GetRecordRef(VariantRecord, RecRef);
+ RecRef.SetTable(PurchaseHeader);
+
+ // [THEN] The purchase header is correctly created with PEPPOL data
+ PEPPOLStructuredValidations.SetMockCurrencyCode(MockCurrencyCode);
+ PEPPOLStructuredValidations.SetMockDate(MockDate);
+ PEPPOLStructuredValidations.AssertPurchaseDocument(Vendor."No.", PurchaseHeader, DummyItem);
+ end;
+
+ [Test]
+ procedure TestPEPPOLInvoice_ValidDocument_UpdateDraftAndFinalize()
+ var
+ EDocument: Record "E-Document";
+ PurchaseHeader: Record "Purchase Header";
+ Item: Record Item;
+ EDocImportParameters: Record "E-Doc. Import Parameters";
+ EDocImport: Codeunit "E-Doc. Import";
+ EDocumentProcessing: Codeunit "E-Document Processing";
+ DataTypeManagement: Codeunit "Data Type Management";
+ RecRef: RecordRef;
+ EDocPurchaseDraft: TestPage "E-Document Purchase Draft";
+ VariantRecord: Variant;
+ begin
+ // [FEATURE] [E-Document] [PEPPOL] [Draft Update]
+ // [SCENARIO] Update draft purchase document data and finalize processing
+
+ // [GIVEN] A valid PEPPOL XML invoice document is imported and processed to draft preparation
+ Initialize(Enum::"Service Integration"::"Mock");
+ SetupPEPPOLEDocumentService();
+ CreateInboundEDocumentFromXML(EDocument, 'peppol/peppol-invoice-0.xml');
+ ProcessEDocumentToStep(EDocument, "Import E-Document Steps"::"Prepare draft");
+
+ // [GIVEN] A generic item is created for manual assignment
+ LibraryEDoc.CreateGenericItem(Item,'');
+
+ // [WHEN] The draft document is opened and modified through UI
+ EDocPurchaseDraft.OpenEdit();
+ EDocPurchaseDraft.GoToRecord(EDocument);
+ EDocPurchaseDraft.Lines.First();
+ EDocPurchaseDraft.Lines."No.".SetValue(Item."No.");
+ EDocPurchaseDraft.Lines.Next();
+
+ // [WHEN] The processing is completed to finish draft step
+ EDocImportParameters."Step to Run" := "Import E-Document Steps"::"Finish draft";
+ EDocImport.ProcessIncomingEDocument(EDocument, EDocImportParameters);
+ EDocument.Get(EDocument."Entry No");
+
+ // [WHEN] The final purchase record is retrieved
+ EDocumentProcessing.GetRecord(EDocument, VariantRecord);
+ DataTypeManagement.GetRecordRef(VariantRecord, RecRef);
+ RecRef.SetTable(PurchaseHeader);
+
+ // [THEN] The purchase header contains both imported PEPPOL data and manual updates
+ PEPPOLStructuredValidations.SetMockCurrencyCode(MockCurrencyCode);
+ PEPPOLStructuredValidations.SetMockDate(MockDate);
+ PEPPOLStructuredValidations.AssertPurchaseDocument(Vendor."No.", PurchaseHeader, Item);
+ end;
+
+ [PageHandler]
+ procedure EDocumentPurchaseHeaderPageHandler(var EDocReadablePurchaseDoc: TestPage "E-Doc. Readable Purchase Doc.")
+ begin
+ EDocReadablePurchaseDoc.Close();
+ end;
#endregion
local procedure Initialize(Integration: Enum "Service Integration")
@@ -119,9 +239,13 @@ codeunit 139891 "E-Document Structured Tests"
EDocumentsSetup.InsertNewExperienceSetup();
// Set a currency that can be used across all localizations
+ MockCurrencyCode := 'XYZ';
Currency.Init();
- Currency.Validate(Code, 'XYZ');
+ Currency.Validate(Code, MockCurrencyCode);
if Currency.Insert(true) then;
+ CreateCurrencyExchangeRate();
+
+ MockDate := DMY2Date(22, 01, 2026);
TransformationRule.DeleteAll();
TransformationRule.CreateDefaultTransformations();
@@ -181,6 +305,29 @@ codeunit 139891 "E-Document Structured Tests"
EDocImportParameters."Step to Run" := ProcessingStep;
EDocImport.ProcessIncomingEDocument(EDocument, EDocImportParameters);
EDocument.CalcFields("Import Processing Status");
- exit(EDocument."Import Processing Status" = Enum::"Import E-Doc. Proc. Status"::"Ready for draft");
+
+ // Update the exit condition to handle different processing steps
+ case ProcessingStep of
+ "Import E-Document Steps"::"Read into Draft":
+ exit(EDocument."Import Processing Status" = Enum::"Import E-Doc. Proc. Status"::"Ready for draft");
+ "Import E-Document Steps"::"Finish draft":
+ exit(EDocument."Import Processing Status" = Enum::"Import E-Doc. Proc. Status"::Processed);
+ "Import E-Document Steps"::"Prepare draft":
+ exit(EDocument."Import Processing Status" = Enum::"Import E-Doc. Proc. Status"::"Draft Ready");
+ else
+ exit(EDocument."Import Processing Status" = Enum::"Import E-Doc. Proc. Status"::"Ready for draft");
+ end;
+ end;
+
+ local procedure CreateCurrencyExchangeRate()
+ var
+ CurrencyExchangeRate: Record "Currency Exchange Rate";
+ begin
+ CurrencyExchangeRate.Init();
+ CurrencyExchangeRate."Currency Code" := MockCurrencyCode;
+ CurrencyExchangeRate."Starting Date" := WorkDate();
+ CurrencyExchangeRate."Exchange Rate Amount" := 10;
+ CurrencyExchangeRate."Relational Exch. Rate Amount" := 1.23;
+ CurrencyExchangeRate.Insert(true);
end;
}
diff --git a/Apps/W1/EDocument/test/src/Processing/PEPPOLStructuredValidations.Codeunit.al b/Apps/W1/EDocument/test/src/Processing/PEPPOLStructuredValidations.Codeunit.al
index 32882d89ae..a4866eacf6 100644
--- a/Apps/W1/EDocument/test/src/Processing/PEPPOLStructuredValidations.Codeunit.al
+++ b/Apps/W1/EDocument/test/src/Processing/PEPPOLStructuredValidations.Codeunit.al
@@ -2,52 +2,106 @@ codeunit 139896 "PEPPOL Structured Validations"
{
var
Assert: Codeunit Assert;
+ UnitOfMeasureCodeTok: Label 'PCS', Locked = true;
+ SalesInvoiceNoTok: Label '103033', Locked = true;
+ PurchaseorderNoTok: Label '2', Locked = true;
+ MockDate: Date;
+ MockCurrencyCode: Code[10];
+ MockDataMismatchErr: Label 'The %1 in %2 does not align with the mock data. Expected: %3, Actual: %4', Locked = true, Comment = '%1 = Field caption, %2 = Table caption, %3 = Expected value, %4 = Actual value';
+
internal procedure AssertFullEDocumentContentExtracted(EDocumentEntryNo: Integer)
var
- GLSetup: Record "General Ledger Setup";
EDocumentPurchaseHeader: Record "E-Document Purchase Header";
EDocumentPurchaseLine: Record "E-Document Purchase Line";
begin
- GLSetup.Get();
EDocumentPurchaseHeader.Get(EDocumentEntryNo);
- Assert.AreEqual('103033', EDocumentPurchaseHeader."Sales Invoice No.", 'The sales invoice number does not allign with the mock data.');
- Assert.AreEqual(DMY2Date(22, 01, 2026), EDocumentPurchaseHeader."Document Date", 'The invoice date does not allign with the mock data.');
- Assert.AreEqual(DMY2Date(22, 02, 2026), EDocumentPurchaseHeader."Due Date", 'The due date does not allign with the mock data.');
- Assert.AreEqual('XYZ', EDocumentPurchaseHeader."Currency Code", 'The currency code does not allign with the mock data.');
- Assert.AreEqual('2', EDocumentPurchaseHeader."Purchase Order No.", 'The purchase order number does not allign with the mock data.');
- // Assert.AreEqual('', EDocumentPurchaseHeader."Vendor GLN", 'The endpoint schema is not provided to populate the GLN.');
- Assert.AreEqual('CRONUS International', EDocumentPurchaseHeader."Vendor Company Name", 'The vendor name does not allign with the mock data.');
- Assert.AreEqual('Main Street, 14', EDocumentPurchaseHeader."Vendor Address", 'The vendor street does not allign with the mock data.');
- Assert.AreEqual('GB123456789', EDocumentPurchaseHeader."Vendor VAT Id", 'The vendor VAT id does not allign with the mock data.');
- Assert.AreEqual('Jim Olive', EDocumentPurchaseHeader."Vendor Contact Name", 'The vendor contact name does not allign with the mock data.');
- Assert.AreEqual('The Cannon Group PLC', EDocumentPurchaseHeader."Customer Company Name", 'The customer name does not allign with the mock data.');
- Assert.AreEqual('GB789456278', EDocumentPurchaseHeader."Customer VAT Id", 'The customer VAT id does not allign with the mock data.');
- Assert.AreEqual('192 Market Square', EDocumentPurchaseHeader."Customer Address", 'The customer address does not allign with the mock data.');
+ Assert.AreEqual(SalesInvoiceNoTok, EDocumentPurchaseHeader."Sales Invoice No.", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Sales Invoice No."), EDocumentPurchaseHeader.TableCaption(), SalesInvoiceNoTok, EDocumentPurchaseHeader."Sales Invoice No."));
+ Assert.AreEqual(MockDate, EDocumentPurchaseHeader."Document Date", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Document Date"), EDocumentPurchaseHeader.TableCaption(), MockDate, EDocumentPurchaseHeader."Document Date"));
+ Assert.AreEqual(CalcDate('<+1M>', MockDate), EDocumentPurchaseHeader."Due Date", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Due Date"), EDocumentPurchaseHeader.TableCaption(), CalcDate('<+1M>', MockDate), EDocumentPurchaseHeader."Due Date"));
+ Assert.AreEqual(MockCurrencyCode, EDocumentPurchaseHeader."Currency Code", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Currency Code"), EDocumentPurchaseHeader.TableCaption(), MockCurrencyCode, EDocumentPurchaseHeader."Currency Code"));
+ Assert.AreEqual(PurchaseorderNoTok, EDocumentPurchaseHeader."Purchase Order No.", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Purchase Order No."), EDocumentPurchaseHeader.TableCaption(), PurchaseorderNoTok, EDocumentPurchaseHeader."Purchase Order No."));
+ Assert.AreEqual('CRONUS International', EDocumentPurchaseHeader."Vendor Company Name", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Vendor Company Name"), EDocumentPurchaseHeader.TableCaption(), 'CRONUS International', EDocumentPurchaseHeader."Vendor Company Name"));
+ Assert.AreEqual('Main Street, 14', EDocumentPurchaseHeader."Vendor Address", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Vendor Address"), EDocumentPurchaseHeader.TableCaption(), 'Main Street, 14', EDocumentPurchaseHeader."Vendor Address"));
+ Assert.AreEqual('GB123456789', EDocumentPurchaseHeader."Vendor VAT Id", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Vendor VAT Id"), EDocumentPurchaseHeader.TableCaption(), 'GB123456789', EDocumentPurchaseHeader."Vendor VAT Id"));
+ Assert.AreEqual('Jim Olive', EDocumentPurchaseHeader."Vendor Contact Name", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Vendor Contact Name"), EDocumentPurchaseHeader.TableCaption(), 'Jim Olive', EDocumentPurchaseHeader."Vendor Contact Name"));
+ Assert.AreEqual('The Cannon Group PLC', EDocumentPurchaseHeader."Customer Company Name", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Customer Company Name"), EDocumentPurchaseHeader.TableCaption(), 'The Cannon Group PLC', EDocumentPurchaseHeader."Customer Company Name"));
+ Assert.AreEqual('GB789456278', EDocumentPurchaseHeader."Customer VAT Id", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Customer VAT Id"), EDocumentPurchaseHeader.TableCaption(), 'GB789456278', EDocumentPurchaseHeader."Customer VAT Id"));
+ Assert.AreEqual('192 Market Square', EDocumentPurchaseHeader."Customer Address", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseHeader.FieldCaption("Customer Address"), EDocumentPurchaseHeader.TableCaption(), '192 Market Square', EDocumentPurchaseHeader."Customer Address"));
EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocumentEntryNo);
EDocumentPurchaseLine.FindSet();
- Assert.AreEqual(1, EDocumentPurchaseLine."Quantity", 'The quantity in the purchase line does not allign with the mock data.');
- Assert.AreEqual('PCS', EDocumentPurchaseLine."Unit of Measure", 'The unit of measure in the purchase line does not allign with the mock data.');
- Assert.AreEqual(4000, EDocumentPurchaseLine."Sub Total", 'The total amount before taxes in the purchase line does not allign with the mock data.');
- Assert.AreEqual('XYZ', EDocumentPurchaseLine."Currency Code", 'The currency code in the purchase line does not allign with the mock data.');
- Assert.AreEqual(0, EDocumentPurchaseLine."Total Discount", 'The total discount in the purchase line does not allign with the mock data.');
- Assert.AreEqual('Bicycle', EDocumentPurchaseLine.Description, 'The product description in the purchase line does not allign with the mock data.');
- Assert.AreEqual('1000', EDocumentPurchaseLine."Product Code", 'The product code in the purchase line does not allign with the mock data.');
- Assert.AreEqual(25, EDocumentPurchaseLine."VAT Rate", 'The VAT rate in the purchase line does not allign with the mock data.');
- Assert.AreEqual(4000, EDocumentPurchaseLine."Unit Price", 'The unit price in the purchase line does not allign with the mock data.');
+ Assert.AreEqual(1, EDocumentPurchaseLine."Quantity", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Quantity"), EDocumentPurchaseLine.TableCaption(), 1, EDocumentPurchaseLine."Quantity"));
+ Assert.AreEqual(UnitOfMeasureCodeTok, EDocumentPurchaseLine."Unit of Measure", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Unit of Measure"), EDocumentPurchaseLine.TableCaption(), UnitOfMeasureCodeTok, EDocumentPurchaseLine."Unit of Measure"));
+ Assert.AreEqual(4000, EDocumentPurchaseLine."Sub Total", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Sub Total"), EDocumentPurchaseLine.TableCaption(), 4000, EDocumentPurchaseLine."Sub Total"));
+ Assert.AreEqual(MockCurrencyCode, EDocumentPurchaseLine."Currency Code", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Currency Code"), EDocumentPurchaseLine.TableCaption(), MockCurrencyCode, EDocumentPurchaseLine."Currency Code"));
+ Assert.AreEqual(0, EDocumentPurchaseLine."Total Discount", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Total Discount"), EDocumentPurchaseLine.TableCaption(), 0, EDocumentPurchaseLine."Total Discount"));
+ Assert.AreEqual('Bicycle', EDocumentPurchaseLine.Description, StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption(Description), EDocumentPurchaseLine.TableCaption(), 'Bicycle', EDocumentPurchaseLine.Description));
+ Assert.AreEqual('1000', EDocumentPurchaseLine."Product Code", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Product Code"), EDocumentPurchaseLine.TableCaption(), '1000', EDocumentPurchaseLine."Product Code"));
+ Assert.AreEqual(25, EDocumentPurchaseLine."VAT Rate", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("VAT Rate"), EDocumentPurchaseLine.TableCaption(), 25, EDocumentPurchaseLine."VAT Rate"));
+ Assert.AreEqual(4000, EDocumentPurchaseLine."Unit Price", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Unit Price"), EDocumentPurchaseLine.TableCaption(), 4000, EDocumentPurchaseLine."Unit Price"));
EDocumentPurchaseLine.Next();
- Assert.AreEqual(2, EDocumentPurchaseLine."Quantity", 'The quantity in the purchase line does not allign with the mock data.');
- Assert.AreEqual('PCS', EDocumentPurchaseLine."Unit of Measure", 'The unit of measure in the purchase line does not allign with the mock data.');
- Assert.AreEqual(10000, EDocumentPurchaseLine."Sub Total", 'The total amount before taxes in the purchase line does not allign with the mock data.');
- Assert.AreEqual('XYZ', EDocumentPurchaseLine."Currency Code", 'The currency code in the purchase line does not allign with the mock data.');
- Assert.AreEqual(0, EDocumentPurchaseLine."Total Discount", 'The total discount in the purchase line does not allign with the mock data.');
- Assert.AreEqual('Bicycle v2', EDocumentPurchaseLine.Description, 'The product description in the purchase line does not allign with the mock data.');
- Assert.AreEqual('2000', EDocumentPurchaseLine."Product Code", 'The product code in the purchase line does not allign with the mock data.');
- Assert.AreEqual(25, EDocumentPurchaseLine."VAT Rate", 'The VAT rate in the purchase line does not allign with the mock data.');
- Assert.AreEqual(5000, EDocumentPurchaseLine."Unit Price", 'The unit price in the purchase line does not allign with the mock data.');
+ Assert.AreEqual(2, EDocumentPurchaseLine."Quantity", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Quantity"), EDocumentPurchaseLine.TableCaption(), 2, EDocumentPurchaseLine."Quantity"));
+ Assert.AreEqual(UnitOfMeasureCodeTok, EDocumentPurchaseLine."Unit of Measure", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Unit of Measure"), EDocumentPurchaseLine.TableCaption(), UnitOfMeasureCodeTok, EDocumentPurchaseLine."Unit of Measure"));
+ Assert.AreEqual(10000, EDocumentPurchaseLine."Sub Total", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Sub Total"), EDocumentPurchaseLine.TableCaption(), 10000, EDocumentPurchaseLine."Sub Total"));
+ Assert.AreEqual(MockCurrencyCode, EDocumentPurchaseLine."Currency Code", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Currency Code"), EDocumentPurchaseLine.TableCaption(), MockCurrencyCode, EDocumentPurchaseLine."Currency Code"));
+ Assert.AreEqual(0, EDocumentPurchaseLine."Total Discount", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Total Discount"), EDocumentPurchaseLine.TableCaption(), 0, EDocumentPurchaseLine."Total Discount"));
+ Assert.AreEqual('Bicycle v2', EDocumentPurchaseLine.Description, StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption(Description), EDocumentPurchaseLine.TableCaption(), 'Bicycle v2', EDocumentPurchaseLine.Description));
+ Assert.AreEqual('2000', EDocumentPurchaseLine."Product Code", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Product Code"), EDocumentPurchaseLine.TableCaption(), '2000', EDocumentPurchaseLine."Product Code"));
+ Assert.AreEqual(25, EDocumentPurchaseLine."VAT Rate", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("VAT Rate"), EDocumentPurchaseLine.TableCaption(), 25, EDocumentPurchaseLine."VAT Rate"));
+ Assert.AreEqual(5000, EDocumentPurchaseLine."Unit Price", StrSubstNo(MockDataMismatchErr, EDocumentPurchaseLine.FieldCaption("Unit Price"), EDocumentPurchaseLine.TableCaption(), 5000, EDocumentPurchaseLine."Unit Price"));
+ end;
+
+ internal procedure AssertPurchaseDocument(VendorNo: Code[20]; PurchaseHeader: Record "Purchase Header"; Item: Record Item)
+ var
+ PurchaseLine: Record "Purchase Line";
+ Item1NoTok: Label 'GL00000001', Locked = true;
+ Item2NoTok: Label 'GL00000003', Locked = true;
+ begin
+ Assert.AreEqual(SalesInvoiceNoTok, PurchaseHeader."Vendor Invoice No.", StrSubstNo(MockDataMismatchErr, PurchaseHeader.FieldCaption("Vendor Invoice No."), PurchaseHeader.TableCaption(), SalesInvoiceNoTok, PurchaseHeader."Vendor Invoice No."));
+ Assert.AreEqual(MockDate, PurchaseHeader."Document Date", StrSubstNo(MockDataMismatchErr, PurchaseHeader.FieldCaption("Document Date"), PurchaseHeader.TableCaption(), MockDate, PurchaseHeader."Document Date"));
+ Assert.AreEqual(CalcDate('<+1M>', MockDate), PurchaseHeader."Due Date", StrSubstNo(MockDataMismatchErr, PurchaseHeader.FieldCaption("Due Date"), PurchaseHeader.TableCaption(), CalcDate('<+1M>', MockDate), PurchaseHeader."Due Date"));
+ Assert.AreEqual(MockCurrencyCode, PurchaseHeader."Currency Code", StrSubstNo(MockDataMismatchErr, PurchaseHeader.FieldCaption("Currency Code"), PurchaseHeader.TableCaption(), MockCurrencyCode, PurchaseHeader."Currency Code"));
+ Assert.AreEqual(PurchaseorderNoTok, PurchaseHeader."Vendor Order No.", StrSubstNo(MockDataMismatchErr, PurchaseHeader.FieldCaption("Vendor Order No."), PurchaseHeader.TableCaption(), PurchaseorderNoTok, PurchaseHeader."Vendor Order No."));
+ Assert.AreEqual(VendorNo, PurchaseHeader."Buy-from Vendor No.", StrSubstNo(MockDataMismatchErr, PurchaseHeader.FieldCaption("Buy-from Vendor No."), PurchaseHeader.TableCaption(), VendorNo, PurchaseHeader."Buy-from Vendor No."));
+
+ PurchaseLine.SetRange("Document Type", PurchaseHeader."Document Type");
+ PurchaseLine.SetRange("Document No.", PurchaseHeader."No.");
+ PurchaseLine.FindSet();
+ Assert.AreEqual(1, PurchaseLine.Quantity, StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption(Quantity), PurchaseLine.TableCaption(), 1, PurchaseLine.Quantity));
+ Assert.AreEqual(4000, PurchaseLine."Direct Unit Cost", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("Direct Unit Cost"), PurchaseLine.TableCaption(), 4000, PurchaseLine."Direct Unit Cost"));
+ Assert.AreEqual(MockCurrencyCode, PurchaseLine."Currency Code", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("Currency Code"), PurchaseLine.TableCaption(), MockCurrencyCode, PurchaseLine."Currency Code"));
+ Assert.AreEqual(0, PurchaseLine."Line Discount Amount", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("Line Discount Amount"), PurchaseLine.TableCaption(), 0, PurchaseLine."Line Discount Amount"));
+ // In the import file we have a name 'Bicycle' but because of Item Cross Reference validation Item description is being used
+ if Item."No." <> '' then begin
+ Assert.AreEqual('Bicycle', PurchaseLine.Description, StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption(Description), PurchaseLine.TableCaption(), Item."No.", PurchaseLine.Description));
+ Assert.AreEqual(Item."No.", PurchaseLine."No.", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("No."), PurchaseLine.TableCaption(), Item."No.", PurchaseLine."No."));
+ Assert.AreEqual(Item."Purch. Unit of Measure", PurchaseLine."Unit of Measure Code", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("Unit of Measure Code"), PurchaseLine.TableCaption(), UnitOfMeasureCodeTok, PurchaseLine."Unit of Measure Code"));
+ end else begin
+ Assert.AreEqual(Item1NoTok, PurchaseLine.Description, StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption(Description), PurchaseLine.TableCaption(), Item1NoTok, PurchaseLine.Description));
+ Assert.AreEqual(Item1NoTok, PurchaseLine."No.", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("No."), PurchaseLine.TableCaption(), Item1NoTok, PurchaseLine."No."));
+ Assert.AreEqual(UnitOfMeasureCodeTok, PurchaseLine."Unit of Measure Code", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("Unit of Measure Code"), PurchaseLine.TableCaption(), UnitOfMeasureCodeTok, PurchaseLine."Unit of Measure Code"));
+ end;
+ PurchaseLine.Next();
+ Assert.AreEqual(2, PurchaseLine.Quantity, StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption(Quantity), PurchaseLine.TableCaption(), 2, PurchaseLine.Quantity));
+ Assert.AreEqual(UnitOfMeasureCodeTok, PurchaseLine."Unit of Measure Code", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("Unit of Measure Code"), PurchaseLine.TableCaption(), UnitOfMeasureCodeTok, PurchaseLine."Unit of Measure Code"));
+ Assert.AreEqual(5000, PurchaseLine."Direct Unit Cost", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("Direct Unit Cost"), PurchaseLine.TableCaption(), 5000, PurchaseLine."Direct Unit Cost"));
+ Assert.AreEqual(MockCurrencyCode, PurchaseLine."Currency Code", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("Currency Code"), PurchaseLine.TableCaption(), MockCurrencyCode, PurchaseLine."Currency Code"));
+ Assert.AreEqual(0, PurchaseLine."Line Discount Amount", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("Line Discount Amount"), PurchaseLine.TableCaption(), 0, PurchaseLine."Line Discount Amount"));
+ // In the import file we have a name 'Bicycle v2' but because of Item Cross Reference validation Item description is being used
+ Assert.AreEqual(Item2NoTok, PurchaseLine.Description, StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption(Description), PurchaseLine.TableCaption(), Item2NoTok, PurchaseLine.Description));
+ Assert.AreEqual(Item2NoTok, PurchaseLine."No.", StrSubstNo(MockDataMismatchErr, PurchaseLine.FieldCaption("No."), PurchaseLine.TableCaption(), Item2NoTok, PurchaseLine."No."));
end;
+ procedure SetMockDate(MockDate: Date)
+ begin
+ this.MockDate := MockDate;
+ end;
+
+ procedure SetMockCurrencyCode(MockCurrencyCode: Code[10])
+ begin
+ this.MockCurrencyCode := MockCurrencyCode;
+ end;
}
\ No newline at end of file