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/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 ce33d32..6be4ba3 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)); @@ -338,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 fb31768..d35efcc 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); @@ -373,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 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)