Skip to content

Commit

Permalink
Merge pull request #2 from eclipxe13/version-1.1.0
Browse files Browse the repository at this point in the history
Soporte para RET 2.0 (versión 1.1.0)
  • Loading branch information
eclipxe13 committed Jul 11, 2022
2 parents 0c93ba9 + 22ca221 commit 3d95715
Show file tree
Hide file tree
Showing 19 changed files with 355 additions and 106 deletions.
8 changes: 4 additions & 4 deletions .phive/phars.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpcs" version="^3.6.2" installed="3.6.2" location="./tools/phpcs" copy="false"/>
<phar name="phpcbf" version="^3.6.2" installed="3.6.2" location="./tools/phpcbf" copy="false"/>
<phar name="php-cs-fixer" version="^3.8.0" installed="3.8.0" location="./tools/php-cs-fixer" copy="false"/>
<phar name="phpstan" version="^1.6.8" installed="1.6.8" location="./tools/phpstan" copy="false"/>
<phar name="phpcs" version="^3.7.1" installed="3.7.1" location="./tools/phpcs" copy="false"/>
<phar name="phpcbf" version="^3.7.1" installed="3.7.1" location="./tools/phpcbf" copy="false"/>
<phar name="php-cs-fixer" version="^3.9.2" installed="3.9.2" location="./tools/php-cs-fixer" copy="false"/>
<phar name="phpstan" version="^1.8.0" installed="1.8.0" location="./tools/phpstan" copy="false"/>
</phive>
3 changes: 2 additions & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
'@PHP74Migration' => true,
'@PHP74Migration:risky' => true,
// symfony
'ordered_imports' => ['imports_order' => ['class', 'function', 'const']], // @PSR12 sort_algorithm: none
'class_attributes_separation' => true,
'whitespace_after_comma_in_array' => true,
'no_empty_statement' => true,
Expand Down Expand Up @@ -45,6 +46,6 @@
PhpCsFixer\Finder::create()
->in(__DIR__)
->append([__FILE__])
->exclude(['vendor', 'build'])
->exclude(['vendor', 'tools', 'build'])
)
;
10 changes: 10 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@

Utilizamos [Versionado Semántico 2.0.0](SEMVER.md).

## Versión 1.1.0

- Se agrega el soporte para validar retenciones 2.0.

Estos cambios aplican de forma interna:

- Se refactorizaron los lectores de archivos de retenciones para hacerlos específicos a una versión.
- Se actualizan librerías de desarrollo.
- Se actualiza el archivo de configuración `.php-cs-fixer.php`.

## Versión 1.0.1

- Se actualiza el año del archivo de licencia a 2022.
Expand Down
52 changes: 0 additions & 52 deletions src/Internal/RetentionReader.php

This file was deleted.

28 changes: 28 additions & 0 deletions src/Internal/RetentionReader10.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\SatEstadoRetenciones\Internal;

use DOMDocument;
use DOMXPath;

/** @internal */
final class RetentionReader10 extends RetentionReaderXpath
{
public function __construct(DOMDocument $document)
{
$xpath = new DOMXPath($document);
$xpath->registerNamespace('r', 'http://www.sat.gob.mx/esquemas/retencionpago/1');
$xpath->registerNamespace('t', 'http://www.sat.gob.mx/TimbreFiscalDigital');

parent::__construct(
$xpath,
'/r:Retenciones/@Version',
'1.0',
'/r:Retenciones/r:Complemento/t:TimbreFiscalDigital/@UUID',
'/r:Retenciones/r:Emisor/@RFCEmisor',
'/r:Retenciones/r:Receptor/r:Nacional/@RFCRecep'
);
}
}
28 changes: 28 additions & 0 deletions src/Internal/RetentionReader20.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\SatEstadoRetenciones\Internal;

use DOMDocument;
use DOMXPath;

/** @internal */
final class RetentionReader20 extends RetentionReaderXpath
{
public function __construct(DOMDocument $document)
{
$xpath = new DOMXPath($document);
$xpath->registerNamespace('r', 'http://www.sat.gob.mx/esquemas/retencionpago/2');
$xpath->registerNamespace('t', 'http://www.sat.gob.mx/TimbreFiscalDigital');

parent::__construct(
$xpath,
'/r:Retenciones/@Version',
'2.0',
'/r:Retenciones/r:Complemento/t:TimbreFiscalDigital/@UUID',
'/r:Retenciones/r:Emisor/@RfcE',
'/r:Retenciones/r:Receptor/r:Nacional/@RfcR'
);
}
}
17 changes: 17 additions & 0 deletions src/Internal/RetentionReaderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\SatEstadoRetenciones\Internal;

/** @internal */
interface RetentionReaderInterface
{
public function matchDocument(): bool;

public function obtainUUID(): string;

public function obtainRfcIssuer(): string;

public function obtainRfcReceiver(): string;
}
70 changes: 70 additions & 0 deletions src/Internal/RetentionReaderXpath.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\SatEstadoRetenciones\Internal;

use DOMNodeList;
use DOMXPath;

/** @internal */
abstract class RetentionReaderXpath implements RetentionReaderInterface
{
private DOMXPath $xpath;

private string $queryVersion;

private string $expectedVersion;

private string $queryUuid;

private string $queryRfcIssuer;

private string $queryRfcReceiver;

public function __construct(
DOMXPath $xpath,
string $queryVersion,
string $expectedVersion,
string $queryUuid,
string $queryRfcIssuer,
string $queryRfcReceiver
) {
$this->xpath = $xpath;
$this->queryVersion = $queryVersion;
$this->expectedVersion = $expectedVersion;
$this->queryUuid = $queryUuid;
$this->queryRfcIssuer = $queryRfcIssuer;
$this->queryRfcReceiver = $queryRfcReceiver;
}

public function matchDocument(): bool
{
return ($this->expectedVersion === $this->obtainFirstAttributeValue($this->queryVersion));
}

public function obtainUUID(): string
{
return $this->obtainFirstAttributeValue($this->queryUuid);
}

public function obtainRfcIssuer(): string
{
return $this->obtainFirstAttributeValue($this->queryRfcIssuer);
}

public function obtainRfcReceiver(): string
{
return $this->obtainFirstAttributeValue($this->queryRfcReceiver);
}

private function obtainFirstAttributeValue(string $xquery): string
{
$attributes = $this->xpath->query($xquery, null, false) ?: new DOMNodeList();
$attribute = $attributes->item(0);
if (null === $attribute) {
return '';
}
return $attribute->nodeValue ?? '';
}
}
5 changes: 5 additions & 0 deletions src/Parameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ public function __construct(string $uuid, string $rfcIssuer, string $rfcReceiver
$this->receiverRfc = $rfcReceiver;
}

public static function createEmpty(): self
{
return new self('', '', '');
}

public function getUuid(): string
{
return $this->uuid;
Expand Down
26 changes: 24 additions & 2 deletions src/Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

use DOMDocument;
use PhpCfdi\SatEstadoRetenciones\Contracts\ScraperInterface;
use PhpCfdi\SatEstadoRetenciones\Internal\RetentionReader;
use PhpCfdi\SatEstadoRetenciones\Internal\RetentionReader10;
use PhpCfdi\SatEstadoRetenciones\Internal\RetentionReader20;
use PhpCfdi\SatEstadoRetenciones\Internal\RetentionReaderInterface;

final class Service
{
Expand Down Expand Up @@ -72,12 +74,32 @@ public function makeParametersFromXml(string $xml): Parameters
*/
public function makeParametersFromDocument(DOMDocument $document): Parameters
{
$reader = new RetentionReader($document);
$reader = $this->findRetentionReaderToMakeParametersFromDocument($document);
if (null === $reader) {
return Parameters::createEmpty();
}

return new Parameters(
$reader->obtainUUID(),
$reader->obtainRfcIssuer(),
$reader->obtainRfcReceiver(),
);
}

private function findRetentionReaderToMakeParametersFromDocument(DOMDocument $document): ?RetentionReaderInterface
{
/** @var RetentionReaderInterface[] $readers */
$readers = [
new RetentionReader20($document),
new RetentionReader10($document),
];

foreach ($readers as $test) {
if ($test->matchDocument()) {
return $test;
}
}

return null;
}
}
2 changes: 1 addition & 1 deletion tests/Features/QueryWithRealCfdiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class QueryWithRealCfdiTest extends TestCase
{
public function testQueryWithRealCfdi(): void
{
$contents = $this->fileContents('real-sample.xml');
$contents = $this->fileContents('ret10-mexican-real.xml');
$service = new Service();
$parameters = $service->makeParametersFromXml($contents);
$result = $service->query($parameters);
Expand Down
33 changes: 33 additions & 0 deletions tests/Unit/Internal/RetentionReader10Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\SatEstadoRetenciones\Tests\Unit\Internal;

use DOMDocument;
use PhpCfdi\SatEstadoRetenciones\Internal\RetentionReader10;
use PhpCfdi\SatEstadoRetenciones\Internal\RetentionReaderInterface;
use PhpCfdi\SatEstadoRetenciones\Internal\RetentionReaderXpath;
use PhpCfdi\SatEstadoRetenciones\Tests\TestCase;

final class RetentionReader10Test extends TestCase
{
public function testRetentionReaderDefinitionTest(): void
{
$document = new DOMDocument();
$reader = new RetentionReader10($document);
$this->assertInstanceOf(RetentionReaderInterface::class, $reader);
$this->assertInstanceOf(RetentionReaderXpath::class, $reader);
}

public function testReadCfdiRetention(): void
{
$document = new DOMDocument();
$document->load($this->filePath('ret10-mexican-real.xml'));
$reader = new RetentionReader10($document);

$this->assertSame('48C4CE37-E218-4AAE-97BE-20634A36C628', $reader->obtainUUID());
$this->assertSame('DCM991109KR2', $reader->obtainRfcIssuer());
$this->assertSame('SAZD861013FU2', $reader->obtainRfcReceiver());
}
}
42 changes: 42 additions & 0 deletions tests/Unit/Internal/RetentionReader20Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\SatEstadoRetenciones\Tests\Unit\Internal;

use DOMDocument;
use PhpCfdi\SatEstadoRetenciones\Internal\RetentionReader20;
use PhpCfdi\SatEstadoRetenciones\Internal\RetentionReaderInterface;
use PhpCfdi\SatEstadoRetenciones\Tests\TestCase;

final class RetentionReader20Test extends TestCase
{
public function testRetentionReaderDefinitionTest(): void
{
$document = new DOMDocument();
$reader = new RetentionReader20($document);
$this->assertInstanceOf(RetentionReaderInterface::class, $reader);
}

public function testReadCfdiRetentionMexican(): void
{
$document = new DOMDocument();
$document->load($this->filePath('ret20-mexican-fake.xml'));
$reader = new RetentionReader20($document);

$this->assertSame('4E3DD8EA-5220-8C42-85A8-E37F9D7502F8', $reader->obtainUUID());
$this->assertSame('AAA010101AAA', $reader->obtainRfcIssuer());
$this->assertSame('SUL010720JN8', $reader->obtainRfcReceiver());
}

public function testReadCfdiRetentionForeign(): void
{
$document = new DOMDocument();
$document->load($this->filePath('ret20-foreign-fake.xml'));
$reader = new RetentionReader20($document);

$this->assertSame('4E3DD8EA-5220-8C42-85A8-E37F9D7502F8', $reader->obtainUUID());
$this->assertSame('AAA010101AAA', $reader->obtainRfcIssuer());
$this->assertSame('', $reader->obtainRfcReceiver());
}
}
Loading

0 comments on commit 3d95715

Please sign in to comment.