From 1ce251a8ddf2ea5935d119828fad3ed1fed52330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristoffer=20H=C3=B6gberg?= Date: Mon, 25 Oct 2021 20:44:16 +0200 Subject: [PATCH 1/2] Add support for ContractDocumentReference (BT-12) --- src/Invoice.php | 21 +++++++++++++++++++++ src/Readers/UblReader.php | 6 ++++++ src/Writers/UblWriter.php | 6 ++++++ tests/Integration/peppol-base.xml | 3 +++ tests/Writers/UblWriterTest.php | 1 + 5 files changed, 37 insertions(+) diff --git a/src/Invoice.php b/src/Invoice.php index d83da5f..db624b1 100644 --- a/src/Invoice.php +++ b/src/Invoice.php @@ -36,6 +36,7 @@ class Invoice { protected $purchaseOrderReference = null; protected $salesOrderReference = null; protected $tenderOrLotReference = null; + protected $contractReference = null; protected $paidAmount = 0; protected $roundingAmount = 0; protected $seller = null; @@ -354,6 +355,26 @@ public function setTenderOrLotReference(?string $tenderOrLotReference): self { } + /** + * Get contract reference + * @return string|null Contract reference + */ + public function getContractReference(): ?string { + return $this->contractReference; + } + + + /** + * Set contract reference + * @param string|null $contractReference Contract reference + * @return self Invoice instance + */ + public function setContractReference(?string $contractReference): self { + $this->contractReference = $contractReference; + return $this; + } + + /** * Get invoice prepaid amount * NOTE: may be rounded according to the CIUS specification diff --git a/src/Readers/UblReader.php b/src/Readers/UblReader.php index ce33d32..7f543fb 100644 --- a/src/Readers/UblReader.php +++ b/src/Readers/UblReader.php @@ -163,6 +163,12 @@ public function import(string $document): Invoice { $invoice->setTenderOrLotReference($tenderOrLotReferenceNode->asText()); } + // BT-12: Contract reference + $contractReferenceNode = $xml->get("{{$cac}}ContractDocumentReference/{{$cbc}}ID"); + if ($contractReferenceNode !== null) { + $invoice->setContractReference($contractReferenceNode->asText()); + } + // BG-24: Attachment nodes foreach ($xml->getAll("{{$cac}}AdditionalDocumentReference") as $node) { $invoice->addAttachment($this->parseAttachmentNode($node)); diff --git a/src/Writers/UblWriter.php b/src/Writers/UblWriter.php index fb31768..13f26f4 100644 --- a/src/Writers/UblWriter.php +++ b/src/Writers/UblWriter.php @@ -112,6 +112,12 @@ public function export(Invoice $invoice): string { $xml->add('cac:OriginatorDocumentReference')->add('cbc:ID', $tenderOrLotReference); } + // BT-12: Contract reference + $contractReference = $invoice->getContractReference(); + if ($contractReference !== null) { + $xml->add('cac:ContractDocumentReference')->add('cbc:ID', $contractReference); + } + // BG-24: Attachments node foreach ($invoice->getAttachments() as $attachment) { $this->addAttachmentNode($xml, $attachment); diff --git a/tests/Integration/peppol-base.xml b/tests/Integration/peppol-base.xml index 14a6ed0..f4110b7 100644 --- a/tests/Integration/peppol-base.xml +++ b/tests/Integration/peppol-base.xml @@ -29,6 +29,9 @@ PPID-123 + + 123Contractref + INV-123 130 diff --git a/tests/Writers/UblWriterTest.php b/tests/Writers/UblWriterTest.php index 31a73ee..b3190e6 100644 --- a/tests/Writers/UblWriterTest.php +++ b/tests/Writers/UblWriterTest.php @@ -73,6 +73,7 @@ private function getSampleInvoice(): Invoice { ->setBuyerReference('REF-0172637') ->addPrecedingInvoiceReference(new InvoiceReference('INV-123')) ->setTenderOrLotReference('PPID-123') + ->setContractReference('123Contractref') ->setSeller($seller) ->setBuyer($buyer) ->addLine($complexLine) From 30751aa5e9bc85cc92b8406cdb9980c0cd7d0db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Miguel=20Moreno?= Date: Wed, 27 Oct 2021 20:12:23 +0200 Subject: [PATCH 2/2] Added support for tax registration identifier (BT-32) - Added Party::$taxRegistrationId attribute - Updated UblReader and UblWriter - Updated integration test --- src/Party.php | 21 +++++++++++++++++++++ src/Readers/UblReader.php | 18 ++++++++++++++---- src/Writers/UblWriter.php | 11 +++++++++++ tests/Integration/peppol-allowance.xml | 6 ++++++ 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/Party.php b/src/Party.php index 9635f1c..a945bcf 100644 --- a/src/Party.php +++ b/src/Party.php @@ -10,6 +10,7 @@ class Party { protected $tradingName = null; protected $companyId = null; protected $vatNumber = null; + protected $taxRegistrationId = null; protected $contactName = null; protected $contactPhone = null; protected $contactEmail = null; @@ -117,6 +118,26 @@ public function setVatNumber(?string $vatNumber): self { } + /** + * Get tax registration ID + * @return Identifier|null Tax registration ID + */ + public function getTaxRegistrationId(): ?Identifier { + return $this->taxRegistrationId; + } + + + /** + * Set tax registration ID + * @param Identifier|null $taxRegistrationId Tax registration ID + * @return self Party instance + */ + public function setTaxRegistrationId(?Identifier $taxRegistrationId): self { + $this->taxRegistrationId = $taxRegistrationId; + return $this; + } + + /** * Get contact point name * @return string|null Contact name diff --git a/src/Readers/UblReader.php b/src/Readers/UblReader.php index 7f543fb..6be4ba3 100644 --- a/src/Readers/UblReader.php +++ b/src/Readers/UblReader.php @@ -344,10 +344,20 @@ private function parseSellerOrBuyerNode(UXML $xml): Party { $this->parsePostalAddressFields($addressNode, $party); } - // VAT number - $vatNumberNode = $xml->get("{{$cac}}PartyTaxScheme/{{$cbc}}CompanyID"); - if ($vatNumberNode !== null) { - $party->setVatNumber($vatNumberNode->asText()); + // VAT number and tax registration identifier + foreach ($xml->getAll("{{$cac}}PartyTaxScheme") as $taxNode) { + $companyIdNode = $taxNode->get("{{$cbc}}CompanyID"); + if ($companyIdNode === null) continue; + $companyId = $companyIdNode->asText(); + + $taxSchemeNode = $taxNode->get("{{$cac}}TaxScheme/{{$cbc}}ID"); + $taxScheme = ($taxSchemeNode === null) ? null : $taxSchemeNode->asText(); + + if ($taxScheme === "VAT") { + $party->setVatNumber($companyId); + } else { + $party->setTaxRegistrationId(new Identifier($companyId, $taxScheme)); + } } // Legal name diff --git a/src/Writers/UblWriter.php b/src/Writers/UblWriter.php index 13f26f4..d35efcc 100644 --- a/src/Writers/UblWriter.php +++ b/src/Writers/UblWriter.php @@ -379,6 +379,17 @@ private function addSellerOrBuyerNode(UXML $parent, Party $party) { $taxNode->add('cac:TaxScheme')->add('cbc:ID', 'VAT'); } + // Tax registration identifier + $taxRegistrationId = $party->getTaxRegistrationId(); + if ($taxRegistrationId !== null) { + $taxRegistrationNode = $xml->add('cac:PartyTaxScheme'); + $taxRegistrationNode->add('cbc:CompanyID', $taxRegistrationId->getValue()); + $taxRegistrationScheme = $taxRegistrationId->getScheme(); + if ($taxRegistrationScheme !== null) { + $taxRegistrationNode->add('cac:TaxScheme')->add('cbc:ID', $taxRegistrationScheme); + } + } + // Initial legal entity node $legalEntityNode = $xml->add('cac:PartyLegalEntity'); diff --git a/tests/Integration/peppol-allowance.xml b/tests/Integration/peppol-allowance.xml index 2fe6b63..ccec97a 100644 --- a/tests/Integration/peppol-allowance.xml +++ b/tests/Integration/peppol-allowance.xml @@ -42,6 +42,12 @@ VAT + + SE555555555501 + + TAX + + SupplierOfficialName Ltd GB983294