Skip to content

Commit 5d136dc

Browse files
committed
Version 2.6.3
2 parents a6da05e + 551e4ea commit 5d136dc

File tree

10 files changed

+147
-19
lines changed

10 files changed

+147
-19
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"ext-mbstring": "*",
3131
"ext-openssl": "*",
3232
"ext-soap": "*",
33+
"ext-iconv": "*",
3334
"eclipxe/xmlresourceretriever": "^1.2",
3435
"eclipxe/xmlschemavalidator": "^2.0.1"
3536
},

docs/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@
1212
- Remove `trigger_error` on `\CfdiUtils\Elements\Cfdi33\Comprobante::getCfdiRelacionados` when called with arguments.
1313

1414

15+
## Version 2.6.3 2018-08-21
16+
17+
- Fix validations `COMPIMPUESTOSC02` and `COMPIMPUESTOSC03`
18+
Previously both or any should exists (`xnor`): nodes `Traslado|Retencion` and attributes `TotalImpuestosTrasladados|TotalImpuestosRetenidos`
19+
Now it allows to have `Impuestos` totals even when related nodes does not exists
20+
This is because is not mandatory by Anexo 20
21+
What is mandatory is that if nodes exists then totals must exists
22+
- Add helper method to create a `RequestParameters` from a `Cfdi`
23+
- Fix: add missing dependence `ext-iconv` into `composer.json`
24+
- Testing: add helper development script `tests/estadosat.php`
25+
- Testing: Change compareNames & castNombre visibility for direct testing
26+
27+
1528
## Version 2.6.2 2018-07-17
1629

1730
- Dependence on <https://github.com/eclipxe13/XmlSchemaValidator> has been set to `^2.0.1`

docs/componentes/estado-sat.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,24 @@ N - 602 | No Encontrado | La consulta fue hecha pero el CFDI no existe
8989
El problema que encontré es que alterando solo 1 dato (el total) esperaba encontrar un estado de `N - 602`
9090
pero el estado devuelto fue `N - 601`.
9191

92+
## Ejemplo de uso a partir de un archivo
9293

93-
## Ejemplo de uso
94+
```php
95+
<?php
96+
97+
use \CfdiUtils\Cfdi;
98+
use \CfdiUtils\ConsultaCfdiSat\WebService;
99+
use \CfdiUtils\ConsultaCfdiSat\RequestParameters;
100+
101+
// los datos del cfdi que se van a consultar
102+
$cfdi = Cfdi::newFromString(file_get_contents('cfdi.xml'));
103+
$request = RequestParameters::createFromCfdi($cfdi);
104+
105+
$service = new WebService();
106+
$response = $service->request($request); // $response contiene toda la información
107+
```
108+
109+
## Ejemplo de uso a partir de datos conocidos
94110

95111
```php
96112
<?php

src/CfdiUtils/ConsultaCfdiSat/RequestParameters.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<?php
22
namespace CfdiUtils\ConsultaCfdiSat;
33

4+
use CfdiUtils\Cfdi;
5+
46
class RequestParameters
57
{
68
/** @var string */
@@ -41,6 +43,19 @@ public function __construct(
4143
$this->sello = $sello;
4244
}
4345

46+
public static function createFromCfdi(Cfdi $cfdi): self
47+
{
48+
$qr = $cfdi->getQuickReader();
49+
return new self(
50+
$qr['version'],
51+
$qr->{'emisor'}['rfc'],
52+
$qr->{'receptor'}['rfc'],
53+
$qr['total'],
54+
$qr->{'complemento'}->{'timbrefiscaldigital'}['uuid'],
55+
$qr['sello']
56+
);
57+
}
58+
4459
public function getVersion(): string
4560
{
4661
return $this->version;

src/CfdiUtils/Validate/Cfdi33/Standard/ComprobanteImpuestos.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ public function validate(NodeInterface $comprobante, Asserts $asserts)
5050
$hasTraslados = (null !== $nodeImpuestos->searchNode('cfdi:Traslados', 'cfdi:Traslado'));
5151
$asserts->putStatus(
5252
'COMPIMPUESTOSC02',
53-
Status::when(! ($hasTraslados xor $existsTotalTrasladados))
53+
Status::when(! ($hasTraslados and ! $existsTotalTrasladados))
5454
);
5555

5656
$hasRetenciones = (null !== $nodeImpuestos->searchNode('cfdi:Retenciones', 'cfdi:Retencion'));
5757
$asserts->putStatus(
5858
'COMPIMPUESTOSC03',
59-
Status::when(! ($hasRetenciones xor $existsTotalRetenidos))
59+
Status::when(! ($hasRetenciones and ! $existsTotalRetenidos))
6060
);
6161
}
6262
}

src/CfdiUtils/Validate/Cfdi33/Standard/SelloDigitalCertificado.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,12 @@ private function obtainSello(string $selloBase64): string
177177
return (string) $sello;
178178
}
179179

180-
private function compareNames(string $first, string $second): bool
180+
protected function compareNames(string $first, string $second): bool
181181
{
182182
return (0 === strcasecmp($this->castNombre($first), $this->castNombre($second)));
183183
}
184184

185-
private function castNombre(string $nombre): string
185+
protected function castNombre(string $nombre): string
186186
{
187187
return str_replace([' ', '-', ',', '.', '#', '&', "'", '"'], '', iconv('UTF-8', 'ASCII//TRANSLIT', $nombre));
188188
}

tests/CfdiUtilsTests/ConsultaCfdiSat/RequestParametersTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22
namespace CfdiUtilsTests\ConsultaCfdiSat;
33

4+
use CfdiUtils\Cfdi;
45
use CfdiUtils\ConsultaCfdiSat\RequestParameters;
56
use CfdiUtilsTests\TestCase;
67

@@ -57,6 +58,32 @@ public function testConstructorWithWrongVersion()
5758
);
5859
}
5960

61+
public function testCreateFromCfdiVersion32()
62+
{
63+
$cfdi = Cfdi::newFromString(file_get_contents($this->utilAsset('cfdi32-real.xml')));
64+
$parameters = RequestParameters::createFromCfdi($cfdi);
65+
66+
$this->assertSame('3.2', $parameters->getVersion());
67+
$this->assertSame('CTO021007DZ8', $parameters->getRfcEmisor());
68+
$this->assertSame('XAXX010101000', $parameters->getRfcReceptor());
69+
$this->assertSame('80824F3B-323E-407B-8F8E-40D83FE2E69F', $parameters->getUuid());
70+
$this->assertStringEndsWith('YRbgmmVYiA==', $parameters->getSello());
71+
$this->assertEquals(4685.00, $parameters->getTotalFloat(), '', 0.001);
72+
}
73+
74+
public function testCreateFromCfdiVersion33()
75+
{
76+
$cfdi = Cfdi::newFromString(file_get_contents($this->utilAsset('cfdi33-real.xml')));
77+
$parameters = RequestParameters::createFromCfdi($cfdi);
78+
79+
$this->assertSame('3.3', $parameters->getVersion());
80+
$this->assertSame('POT9207213D6', $parameters->getRfcEmisor());
81+
$this->assertSame('DIM8701081LA', $parameters->getRfcReceptor());
82+
$this->assertSame('CEE4BE01-ADFA-4DEB-8421-ADD60F0BEDAC', $parameters->getUuid());
83+
$this->assertStringEndsWith('XmE4/OAgdg==', $parameters->getSello());
84+
$this->assertEquals(2010.01, $parameters->getTotalFloat(), '', 0.001);
85+
}
86+
6087
/**
6188
* @param string $total
6289
* @param string $expected

tests/CfdiUtilsTests/Validate/Cfdi33/Standard/ComprobanteImpuestosTest.php

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,12 @@ protected function setUp()
1717
$this->validator = new ComprobanteImpuestos();
1818
}
1919

20-
public function providerValidImpuestos()
21-
{
22-
return [
23-
[true, false],
24-
[false, true],
25-
[true, true],
26-
];
27-
}
28-
2920
/**
3021
* @param bool $putTraslados
3122
* @param bool $putRetenciones
32-
* @dataProvider providerValidImpuestos
23+
* @testWith [true, false]
24+
* [false, true]
25+
* [true, true]
3326
*/
3427
public function testValidImpuestos($putTraslados, $putRetenciones)
3528
{
@@ -70,15 +63,15 @@ public function testInvalidTrasladosNodesWithoutTotalTraslados()
7063
$this->assertStatusEqualsCode(Status::error(), 'COMPIMPUESTOSC02');
7164
}
7265

73-
public function testInvalidTotalTrasladosWithoutTrasladosNodes()
66+
public function testValidTotalTrasladosWithoutTrasladosNodes()
7467
{
7568
$this->comprobante->addChild(new Node(
7669
'cfdi:Impuestos',
7770
['TotalImpuestosTrasladados' => '']
7871
));
7972

8073
$this->runValidate();
81-
$this->assertStatusEqualsCode(Status::error(), 'COMPIMPUESTOSC02');
74+
$this->assertStatusEqualsCode(Status::ok(), 'COMPIMPUESTOSC02');
8275
}
8376

8477
public function testInvalidRetencionesNodesWithoutTotalRetenciones()
@@ -93,15 +86,15 @@ public function testInvalidRetencionesNodesWithoutTotalRetenciones()
9386
$this->assertStatusEqualsCode(Status::error(), 'COMPIMPUESTOSC03');
9487
}
9588

96-
public function testInvalidTotalRetencionesWithoutRetencionesNodes()
89+
public function testValidTotalRetencionesWithoutRetencionesNodes()
9790
{
9891
$this->comprobante->addChild(new Node(
9992
'cfdi:Impuestos',
10093
['TotalImpuestosRetenidos' => '']
10194
));
10295

10396
$this->runValidate();
104-
$this->assertStatusEqualsCode(Status::error(), 'COMPIMPUESTOSC03');
97+
$this->assertStatusEqualsCode(Status::ok(), 'COMPIMPUESTOSC03');
10598
}
10699

107100
public function testWithoutNodeImpuestos()

tests/CfdiUtilsTests/Validate/Cfdi33/Standard/SelloDigitalCertificadoTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,23 @@ public function testValidateOk()
148148
}
149149
$this->assertCount(8, $this->asserts, 'All 8 were are tested');
150150
}
151+
152+
/**
153+
* @param bool $expected
154+
* @param string $first
155+
* @param string $second
156+
* @testWith [true, "ABC", "ABC"]
157+
* [true, "Empresa \"Equis\"", "Empresa Equis"]
158+
* [false, "Empresa Equis Sa de Cv", "Empresa Equis SA CV"]
159+
*/
160+
public function testCompareNames(bool $expected, string $first, string $second)
161+
{
162+
$validator = new class() extends SelloDigitalCertificado {
163+
public function testCompareNames(string $first, string $second): bool
164+
{
165+
return $this->compareNames($first, $second);
166+
}
167+
};
168+
$this->assertSame($expected, $validator->testCompareNames($first, $second));
169+
}
151170
}

tests/estadosat.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
use \CfdiUtils\ConsultaCfdiSat\WebService;
4+
5+
require __DIR__ . '/bootstrap.php';
6+
7+
exit(call_user_func(function (string $command, string ...$arguments): int {
8+
$files = [];
9+
$askForHelp = false;
10+
foreach ($arguments as $argument) {
11+
if (in_array($argument, ['-h', '--help'], true)) {
12+
$askForHelp = true;
13+
break; // no need to continue with other arguments
14+
}
15+
$files[] = $argument;
16+
}
17+
$files = array_filter($files);
18+
19+
if ($askForHelp || ! count($files)) {
20+
echo implode(PHP_EOL, [
21+
basename($command) . ' [-h|--help] cfdi.xml...',
22+
' -h, --help Show this help',
23+
" cfdi.xml Files to check, as many as needed, don't allow wilcards",
24+
' WARNING: This program can change at any time! Do not depend on this file or its results!',
25+
]), PHP_EOL;
26+
return 0;
27+
}
28+
29+
$webService = new WebService();
30+
31+
foreach ($files as $file) {
32+
$cfdi = \CfdiUtils\Cfdi::newFromString(file_get_contents($file));
33+
$request = \CfdiUtils\ConsultaCfdiSat\RequestParameters::createFromCfdi($cfdi);
34+
$response = $webService->request($request);
35+
36+
print_r(array_filter([
37+
'file' => $file,
38+
'Status CFDI' => $response->getCfdi(),
39+
'Code' => $response->getCode(),
40+
]));
41+
}
42+
43+
return 0;
44+
}, ...$argv));

0 commit comments

Comments
 (0)