diff --git a/src/Apps/W1/EDocument/App/src/Format/EDocImportPEPPOLBIS30.Codeunit.al b/src/Apps/W1/EDocument/App/src/Format/EDocImportPEPPOLBIS30.Codeunit.al
index 804516ec5f..033258ecec 100644
--- a/src/Apps/W1/EDocument/App/src/Format/EDocImportPEPPOLBIS30.Codeunit.al
+++ b/src/Apps/W1/EDocument/App/src/Format/EDocImportPEPPOLBIS30.Codeunit.al
@@ -188,6 +188,7 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
DocumentAttachment: Record "Document Attachment";
DocumentAttachmentData: Codeunit "Temp Blob";
InStream: InStream;
+ LineNo: Integer;
begin
PurchaseHeader."Document Type" := PurchaseHeader."Document Type"::Invoice;
PurchaseHeader."No." := CopyStr(GetNodeByPath(TempXMLBuffer, '/Invoice/cbc:ID'), 1, MaxStrLen(PurchaseHeader."No."));
@@ -198,11 +199,11 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
TempXMLBuffer.Reset();
if TempXMLBuffer.FindSet() then
repeat
- ParseInvoice(EDocument, PurchaseHeader, PurchaseLine, DocumentAttachment, DocumentAttachmentData, TempXMLBuffer);
+ ParseInvoice(EDocument, PurchaseHeader, PurchaseLine, DocumentAttachment, DocumentAttachmentData, TempXMLBuffer, LineNo);
until TempXMLBuffer.Next() = 0;
// Insert last document attachment
- if DocumentAttachment."No." <> '' then begin
+ if (DocumentAttachment."No." <> '') and (DocumentAttachment."File Name" <> '') then begin
DocumentAttachmentData.CreateInStream(InStream, TextEncoding::UTF8);
EDocumentAttachmentGen.Insert(EDocument, InStream, DocumentAttachment.FindUniqueFileName(DocumentAttachment."File Name", DocumentAttachment."File Extension"));
Clear(DocumentAttachment);
@@ -222,6 +223,7 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
DocumentAttachment: Record "Document Attachment";
DocumentAttachmentData: Codeunit "Temp Blob";
InStream: InStream;
+ LineNo: Integer;
begin
PurchaseHeader."Document Type" := PurchaseHeader."Document Type"::"Credit Memo";
PurchaseHeader."No." := CopyStr(GetNodeByPath(TempXMLBuffer, '/CreditNote/cbc:ID'), 1, MaxStrLen(PurchaseHeader."No."));
@@ -230,11 +232,11 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
TempXMLBuffer.Reset();
if TempXMLBuffer.FindSet() then
repeat
- ParseCreditMemo(EDocument, PurchaseHeader, PurchaseLine, DocumentAttachment, DocumentAttachmentData, TempXMLBuffer);
+ ParseCreditMemo(EDocument, PurchaseHeader, PurchaseLine, DocumentAttachment, DocumentAttachmentData, TempXMLBuffer, LineNo);
until TempXMLBuffer.Next() = 0;
// Insert last document attachment
- if DocumentAttachment."No." <> '' then begin
+ if (DocumentAttachment."No." <> '') and (DocumentAttachment."File Name" <> '') then begin
DocumentAttachmentData.CreateInStream(InStream, TextEncoding::UTF8);
EDocumentAttachmentGen.Insert(EDocument, InStream, DocumentAttachment.FindUniqueFileName(DocumentAttachment."File Name", DocumentAttachment."File Extension"));
Clear(DocumentAttachment);
@@ -311,7 +313,7 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
/// Parses credit memo information line by line from TempXMLBuffer.
/// We handle the insert of Purchase Order Line and Document Attachment after the call to this function.
///
- local procedure ParseCreditMemo(EDocument: Record "E-Document"; var PurchaseHeader: Record "Purchase Header" temporary; var PurchaseLine: record "Purchase Line" temporary; var DocumentAttachment: Record "Document Attachment"; DocumentAttachmentData: Codeunit "Temp Blob"; var TempXMLBuffer: Record "XML Buffer" temporary)
+ local procedure ParseCreditMemo(EDocument: Record "E-Document"; var PurchaseHeader: Record "Purchase Header" temporary; var PurchaseLine: record "Purchase Line" temporary; var DocumentAttachment: Record "Document Attachment"; DocumentAttachmentData: Codeunit "Temp Blob"; var TempXMLBuffer: Record "XML Buffer" temporary; var LineNo: Integer)
var
Base64Convert: Codeunit "Base64 Convert";
OutStream: OutStream;
@@ -352,7 +354,7 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
Evaluate(PurchaseHeader.Amount, Value, 9);
'/CreditNote/cac:AdditionalDocumentReference/cbc:ID':
begin
- if DocumentAttachment."No." <> '' then begin
+ if (DocumentAttachment."No." <> '') and (DocumentAttachment."File Name" <> '') then begin
DocumentAttachmentData.CreateInStream(InStream, TextEncoding::UTF8);
EDocumentAttachmentGen.Insert(EDocument, InStream, DocumentAttachment.FindUniqueFileName(DocumentAttachment."File Name", DocumentAttachment."File Extension"));
Clear(DocumentAttachment);
@@ -381,6 +383,8 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
PurchaseLine.Init();
PurchaseLine."Document Type" := PurchaseHeader."Document Type";
PurchaseLine."Document No." := PurchaseHeader."No.";
+ LineNo += 10000;
+ PurchaseLine."Line No." := LineNo;
end;
'/CreditNote/cac:CreditNoteLine/cbc:CreditedQuantity':
if Value <> '' then
@@ -404,8 +408,6 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
PurchaseLine."Item Reference No." := CopyStr(Value, 1, MaxStrLen(PurchaseLine."Item Reference No."));
'/CreditNote/cac:CreditNoteLine/cac:Item/cac:StandardItemIdentification/cbc:ID':
PurchaseLine."No." := CopyStr(Value, 1, MaxStrLen(PurchaseLine."No."));
- '/CreditNote/cac:CreditNoteLine/cbc:ID':
- Evaluate(PurchaseLine."Line No.", Value, 9);
'/CreditNote/cac:CreditNoteLine/cac:Item/cac:ClassifiedTaxCategory/cbc:Percent':
if Value <> '' then
Evaluate(PurchaseLine."VAT %", Value, 9);
@@ -425,7 +427,7 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
/// Parses invoice information line by line from TempXMLBuffer.
/// We handle the insert of Purchase Order Line and Document Attachment after the call to this function.
///
- local procedure ParseInvoice(EDocument: Record "E-Document"; var PurchaseHeader: Record "Purchase Header" temporary; var PurchaseLine: Record "Purchase Line" temporary; var DocumentAttachment: Record "Document Attachment"; DocumentAttachmentData: Codeunit "Temp Blob"; var TempXMLBuffer: Record "XML Buffer" temporary)
+ local procedure ParseInvoice(EDocument: Record "E-Document"; var PurchaseHeader: Record "Purchase Header" temporary; var PurchaseLine: Record "Purchase Line" temporary; var DocumentAttachment: Record "Document Attachment"; DocumentAttachmentData: Codeunit "Temp Blob"; var TempXMLBuffer: Record "XML Buffer" temporary; var LineNo: Integer)
var
Base64Convert: Codeunit "Base64 Convert";
OutStream: OutStream;
@@ -464,7 +466,7 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
Evaluate(PurchaseHeader."Document Date", Value, 9);
'/Invoice/cac:AdditionalDocumentReference/cbc:ID':
begin
- if DocumentAttachment."No." <> '' then begin
+ if (DocumentAttachment."No." <> '') and (DocumentAttachment."File Name" <> '') then begin
DocumentAttachmentData.CreateInStream(InStream, TextEncoding::UTF8);
EDocumentAttachmentGen.Insert(EDocument, InStream, DocumentAttachment.FindUniqueFileName(DocumentAttachment."File Name", DocumentAttachment."File Extension"));
Clear(DocumentAttachment);
@@ -493,6 +495,8 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
PurchaseLine.Init();
PurchaseLine."Document Type" := PurchaseHeader."Document Type";
PurchaseLine."Document No." := PurchaseHeader."No.";
+ LineNo += 10000;
+ PurchaseLine."Line No." := LineNo;
end;
'/Invoice/cac:InvoiceLine/cbc:InvoicedQuantity':
if Value <> '' then
@@ -517,8 +521,6 @@ codeunit 6166 "EDoc Import PEPPOL BIS 3.0"
PurchaseLine."Item Reference No." := CopyStr(Value, 1, MaxStrLen(PurchaseLine."Item Reference No."));
'/Invoice/cac:InvoiceLine/cac:Item/cac:StandardItemIdentification/cbc:ID':
PurchaseLine."No." := CopyStr(Value, 1, MaxStrLen(PurchaseLine."No."));
- '/Invoice/cac:InvoiceLine/cbc:ID':
- Evaluate(PurchaseLine."Line No.", Value, 9);
'/Invoice/cac:InvoiceLine/cac:Item/cac:ClassifiedTaxCategory/cbc:Percent':
if Value <> '' then
Evaluate(PurchaseLine."VAT %", Value, 9);
diff --git a/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-hierarchical-lineids.xml b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-hierarchical-lineids.xml
new file mode 100644
index 0000000000..0ed9e1978b
--- /dev/null
+++ b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-hierarchical-lineids.xml
@@ -0,0 +1,177 @@
+
+
+ urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+ 103033
+ 2026-01-22
+ 2026-02-22
+ 380
+ XYZ
+ 1
+
+ 2
+
+
+ 103033
+
+
+ 103033
+
+
+ dGVzdA==
+
+
+
+
+ 1234567890128
+
+ CRONUS International
+
+
+ Main Street, 14
+ Birmingham
+ B27 4KT
+
+ GB
+
+
+
+ GB123456789
+
+ VAT
+
+
+
+ CRONUS International
+ 123456789
+
+
+ Jim Olive
+ JO@contoso.com
+
+
+
+
+
+ 789456278
+
+ 8712345000004
+
+
+ The Cannon Group PLC
+
+
+ 192 Market Square
+ Birmingham
+ B27 4KT
+
+ GB
+
+
+
+ GB789456278
+
+ VAT
+
+
+
+ The Cannon Group PLC
+
+
+
+
+
+ CRONUS International
+
+
+ GB123456789
+
+
+
+ 30
+ 2026-02-22
+
+ GB12CPBK08929965044991
+
+ BG99999
+
+
+
+
+ 1 Month/2% 8 days
+
+
+ 1000
+
+ 4000
+ 1000
+
+ S
+ 25
+
+ VAT
+
+
+
+
+
+ 14000
+ 14000
+ 14140
+ 0
+ 0.00
+ 0
+ 14140
+
+
+ 1.1
+ Item
+ 1
+ 4000
+
+ Bicycle
+
+ 1000
+
+
+ S
+ 25
+
+ VAT
+
+
+
+
+ 4000.00
+ 1
+
+
+
+ 1.2
+ Item
+ 2
+ 10000
+
+ Bicycle v2
+
+ 2000
+
+
+ S
+ 25
+
+ VAT
+
+
+
+
+ 5000.00
+ 2
+
+
+
diff --git a/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-textonly-docref.xml b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-textonly-docref.xml
new file mode 100644
index 0000000000..269a1d908c
--- /dev/null
+++ b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-textonly-docref.xml
@@ -0,0 +1,185 @@
+
+
+ urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+ 103033
+ 2026-01-22
+ 2026-02-22
+ 380
+ XYZ
+ 1
+
+ 2
+
+
+ 103033
+
+
+ DOC-REF-001
+ Text-only reference without attachment
+
+
+ DOC-REF-002
+ Another text-only reference
+
+
+ 103033
+
+
+ dGVzdA==
+
+
+
+
+ 1234567890128
+
+ CRONUS International
+
+
+ Main Street, 14
+ Birmingham
+ B27 4KT
+
+ GB
+
+
+
+ GB123456789
+
+ VAT
+
+
+
+ CRONUS International
+ 123456789
+
+
+ Jim Olive
+ JO@contoso.com
+
+
+
+
+
+ 789456278
+
+ 8712345000004
+
+
+ The Cannon Group PLC
+
+
+ 192 Market Square
+ Birmingham
+ B27 4KT
+
+ GB
+
+
+
+ GB789456278
+
+ VAT
+
+
+
+ The Cannon Group PLC
+
+
+
+
+
+ CRONUS International
+
+
+ GB123456789
+
+
+
+ 30
+ 2026-02-22
+
+ GB12CPBK08929965044991
+
+ BG99999
+
+
+
+
+ 1 Month/2% 8 days
+
+
+ 1000
+
+ 4000
+ 1000
+
+ S
+ 25
+
+ VAT
+
+
+
+
+
+ 14000
+ 14000
+ 14140
+ 0
+ 0.00
+ 0
+ 14140
+
+
+ 10000
+ Item
+ 1
+ 4000
+
+ Bicycle
+
+ 1000
+
+
+ S
+ 25
+
+ VAT
+
+
+
+
+ 4000.00
+ 1
+
+
+
+ 20000
+ Item
+ 2
+ 10000
+
+ Bicycle v2
+
+ 2000
+
+
+ S
+ 25
+
+ VAT
+
+
+
+
+ 5000.00
+ 2
+
+
+
diff --git a/src/Apps/W1/EDocument/Test/src/Processing/EDocE2ETest.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Processing/EDocE2ETest.Codeunit.al
index 70f194ea57..50d05d79ea 100644
--- a/src/Apps/W1/EDocument/Test/src/Processing/EDocE2ETest.Codeunit.al
+++ b/src/Apps/W1/EDocument/Test/src/Processing/EDocE2ETest.Codeunit.al
@@ -1750,6 +1750,59 @@ codeunit 139624 "E-Doc E2E Test"
Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be in In Progress status.');
end;
+ [Test]
+ procedure ImportPEPPOLInvoiceWithTextOnlyDocumentReferences()
+ var
+ EDocument: Record "E-Document";
+ PurchaseHeader: Record "Purchase Header";
+ PurchaseLine: Record "Purchase Line";
+ EDocImportParams: Record "E-Doc. Import Parameters";
+ begin
+ // [SCENARIO] Import a PEPPOL invoice with AdditionalDocumentReference elements
+ // that have no child (text-only references).
+ // Previously this caused "Please choose a file to attach" error.
+ Initialize(Enum::"Service Integration"::"Mock");
+
+ EDocImportParams."Step to Run" := "Import E-Document Steps"::"Finish draft";
+ WorkDate(DMY2Date(1, 1, 2027));
+ Assert.IsTrue(
+ LibraryEDoc.CreateInboundPEPPOLDocumentToState(
+ EDocument, EDocumentService, 'peppol/peppol-invoice-textonly-docref.xml', EDocImportParams),
+ 'The e-document should be processed');
+
+ EDocument.Get(EDocument."Entry No");
+ PurchaseHeader.Get(EDocument."Document Record ID");
+ PurchaseLine.SetRange("Document Type", PurchaseHeader."Document Type");
+ PurchaseLine.SetRange("Document No.", PurchaseHeader."No.");
+ Assert.AreEqual(2, PurchaseLine.Count(), 'Expected 2 purchase lines to be imported.');
+ end;
+
+ [Test]
+ procedure ImportPEPPOLInvoiceWithHierarchicalLineIds()
+ var
+ EDocument: Record "E-Document";
+ PurchaseHeader: Record "Purchase Header";
+ PurchaseLine: Record "Purchase Line";
+ EDocImportParams: Record "E-Doc. Import Parameters";
+ begin
+ // [SCENARIO] Import a PEPPOL invoice with non-integer line IDs (e.g., "1.1", "1.2").
+ // Previously this caused "The value '1.1' can't be evaluated into type Integer" error.
+ Initialize(Enum::"Service Integration"::"Mock");
+
+ EDocImportParams."Step to Run" := "Import E-Document Steps"::"Finish draft";
+ WorkDate(DMY2Date(1, 1, 2027));
+ Assert.IsTrue(
+ LibraryEDoc.CreateInboundPEPPOLDocumentToState(
+ EDocument, EDocumentService, 'peppol/peppol-invoice-hierarchical-lineids.xml', EDocImportParams),
+ 'The e-document should be processed');
+
+ EDocument.Get(EDocument."Entry No");
+ PurchaseHeader.Get(EDocument."Document Record ID");
+ PurchaseLine.SetRange("Document Type", PurchaseHeader."Document Type");
+ PurchaseLine.SetRange("Document No.", PurchaseHeader."No.");
+ Assert.AreEqual(2, PurchaseLine.Count(), 'Expected 2 purchase lines to be imported.');
+ end;
+
local procedure CheckPDFEmbedToXML(TempBlob: Codeunit "Temp Blob")
var
TempXMLBuffer: Record "XML Buffer" temporary;
diff --git a/src/Apps/W1/EDocument/Test/src/Processing/EDocumentStructuredTests.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Processing/EDocumentStructuredTests.Codeunit.al
index 98e4cd174b..e387307354 100644
--- a/src/Apps/W1/EDocument/Test/src/Processing/EDocumentStructuredTests.Codeunit.al
+++ b/src/Apps/W1/EDocument/Test/src/Processing/EDocumentStructuredTests.Codeunit.al
@@ -97,6 +97,7 @@ codeunit 139891 "E-Document Structured Tests"
else
Assert.Fail(EDocumentStatusNotUpdatedErr);
end;
+
#endregion
local procedure Initialize(Integration: Enum "Service Integration")