Skip to content

Commit

Permalink
Handled XML errors in UblReader
Browse files Browse the repository at this point in the history
- Handled PHP errors to instead throw InvalidArgumentException to match the documentation
- Added unit test

> Related to #16
  • Loading branch information
josemmo committed Mar 19, 2022
1 parent b461df5 commit 5a25f75
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 8 deletions.
27 changes: 19 additions & 8 deletions src/Readers/UblReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,15 @@ public function import(string $document): Invoice {
if ($exemptionReasonCodeNode === null && $exemptionReasonNode === null) continue;

// Get tax subtotal key
$category = $node->get("{{$cbc}}ID")->asText(); // @phan-suppress-current-line PhanPossiblyNonClassMethodCall
$rate = (float) $node->get("{{$cbc}}Percent")->asText(); // @phan-suppress-current-line PhanPossiblyNonClassMethodCall
$key = "$category:$rate";
$categoryNode = $node->get("{{$cbc}}ID");
if ($categoryNode === null) {
throw new InvalidArgumentException('Missing <cbc:ID /> node from tax item');
}
$rateNode = $node->get("{{$cbc}}Percent");
if ($rateNode === null) {
throw new InvalidArgumentException('Missing <cbc:Percent /> node from tax item');
}
$key = "{$categoryNode->asText()}:{$rateNode->asText()}";

// Save reasons
$taxExemptions[$key] = [
Expand Down Expand Up @@ -651,7 +657,8 @@ private function addAllowanceOrCharge($target, UXML $xml, array &$taxExemptions)
$cbc = UblWriter::NS_CBC;

// Add instance to invoice
if ($xml->get("{{$cbc}}ChargeIndicator")->asText() === "true") { // @phan-suppress-current-line PhanPossiblyNonClassMethodCall
$chargeIndicatorNode = $xml->get("{{$cbc}}ChargeIndicator");
if ($chargeIndicatorNode !== null && $chargeIndicatorNode->asText() === "true") {
$target->addCharge($allowanceOrCharge);
} else {
$target->addAllowance($allowanceOrCharge);
Expand All @@ -671,12 +678,16 @@ private function addAllowanceOrCharge($target, UXML $xml, array &$taxExemptions)

// Amount
$factorNode = $xml->get("{{$cbc}}MultiplierFactorNumeric");
if ($factorNode === null) {
$amount = (float) $xml->get("{{$cbc}}Amount")->asText(); // @phan-suppress-current-line PhanPossiblyNonClassMethodCall
$allowanceOrCharge->setAmount($amount);
} else {
$amountNode = $xml->get("{{$cbc}}Amount");
if ($factorNode !== null) {
$percent = (float) $factorNode->asText();
$allowanceOrCharge->markAsPercentage()->setAmount($percent);
} elseif ($amountNode !== null) {
$amount = (float) $amountNode->asText();
$allowanceOrCharge->setAmount($amount);
} else {
throw new InvalidArgumentException('Missing both <cbc:Amount /> and <cbc:MultiplierFactorNumeric />' .
' nodes from allowance/charge');
}

// VAT attributes
Expand Down
24 changes: 24 additions & 0 deletions tests/Readers/UblReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Einvoicing\Readers\UblReader;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
use function file_get_contents;

final class UblReaderTest extends TestCase {
Expand Down Expand Up @@ -35,4 +36,27 @@ public function testCanReadInvoice(): void {
$this->assertEquals('INV-123', $invoice->getPrecedingInvoiceReferences()[0]->getValue());
$this->assertEquals('This is a sample string', $invoice->getAttachments()[0]->getContents());
}

public function testCannotReadInvoiceFromInvalidXml(): void {
$this->expectException(InvalidArgumentException::class);
$this->reader->import(
'<Invoice xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:CustomizationID>0.0.1</cbc:CustomizationID>
<cbc:ProfileID>Not-a-EN-16931-Invoice</cbc:ProfileID>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">100.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">0.00</cbc:TaxAmount>
<cbc:Percent>0.00</cbc:Percent>
<cac:TaxCategory>
<cbc:TaxExemptionReasonCode>No tax</cbc:TaxExemptionReasonCode>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
</Invoice>'
);
}
}

0 comments on commit 5a25f75

Please sign in to comment.