Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ Puede que los cambios del ejemplo no sean lógicos, es solo para ilustrar cómo
- Filtrando por únicamente documentos vigentes (excluye cancelados).
- Filtrando por el RFC a cuenta de terceros `XXX01010199A`.
- Filtrando por el RFC contraparte `MAG041126GT8`. Como se solicitan recibidos, entonces son los emidos por ese RFC.
- Filtrando por el UUID `96623061-61fe-49de-b298-c7156476aa8b`
- Filtrando por el UUID `96623061-61fe-49de-b298-c7156476aa8b`.

```php
<?php
Expand Down Expand Up @@ -301,6 +301,23 @@ $query = QueryParameters::create()
;
```

#### Ejemplo de consulta por UUID

En este caso se especifica solamente el UUID a consultar, en el ejemplo es `96623061-61fe-49de-b298-c7156476aa8b`.

Nota: **Todos los demás argumentos de la consulta son ignorados**.

```php
<?php

use PhpCfdi\SatWsDescargaMasiva\Services\Query\QueryParameters;
use PhpCfdi\SatWsDescargaMasiva\Shared\Uuid;

$query = QueryParameters::create()
->withUuid(Uuid::create('96623061-61fe-49de-b298-c7156476aa8b'))
;
```

### Verificar una consulta

La verificación depende de que la consulta haya sido aceptada.
Expand Down
14 changes: 14 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ que nombraremos así: ` Breaking . Feature . Fix `, donde:
**Importante:** Las reglas de SEMVER no aplican si estás usando una rama (por ejemplo `main-dev`)
o estás usando una versión cero (por ejemplo `0.18.4`).

## Versión 0.5.2 2022-09-30

#### Consulta por UUID

Gracias a la solicitud de cambios en [`luisiturrios1/python-cfdiclient#42`](https://github.com/luisiturrios1/python-cfdiclient/pull/42)
por `@alan196`, hemos podido verificar que la documentación del servicio con respecto a la consulta por UUID está incorrecta.

- El campo no se llama `UUID`, se llama `Folio`.
- El campo `RfcSolicitante` no se debe omitir.
- El campo `TipoSolicitud` no se debe omitir.
- Los demás campos no deben existir.

Por lo tanto, se han hecho las correcciones necesarias para hacer la consulta por `UUID`.

## Versión 0.5.1 2022-09-28

### Se corrigen XML mal formados
Expand Down
11 changes: 9 additions & 2 deletions docs/problema-filtros-no-aplicados.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,24 @@ En esta versión se agregan nuevos filtros, permitiendo hacer solicitudes más e

Los siguientes filtros no están funcionando en la consulta de CFDI Regulares:

- Filtro por UUID.
- Filtro de documentos cancelados cuando se solicita un paquete de documentos XML.
El filtro funciona correctamente para paquetes de Metadata.

Los siguientes filtros no están funcionando en la consulta de CFDI de retenciones e información de pagos:

- Filtro por complemento.
- Filtro por UUID.

## Actualizaciones

### 2022-09-30

Hemos notado que la documentación del SAT en relación con la consulta por UUID está incorrecta:

- El campo no se llama `UUID`, se llama `Folio`.
- El campo `RfcSolicitante` se debe especificar.
- El campo `TipoSolicitud` se debe especificar.
- Los demás campos no deben existir.

### 2022-03-04

El SAT actualiza el servicio a la versión 1.2, no resuelve las solicitudes ingresadas.
Expand Down
9 changes: 4 additions & 5 deletions src/PackageReader/Internal/FilteredPackageReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,30 +57,29 @@ public static function createFromFile(string $filename): self
return new self($filename, $archive);
}

/** @inheritDoc */
/**
* @inheritDoc
* @codeCoverageIgnore Unable to produce code coverage for error handling
*/
public static function createFromContents(string $content): self
{
// create temp file
try {
$tmpfile = tempnam(sys_get_temp_dir(), '');
} catch (Throwable $exception) {
/** @codeCoverageIgnore */
throw CreateTemporaryZipFileException::create('Cannot create a temporary file', $exception);
}
if (false === $tmpfile) {
/** @codeCoverageIgnore */
throw CreateTemporaryZipFileException::create('Cannot not create a temporary file');
}

// write contents
try {
$write = file_put_contents($tmpfile, $content);
} catch (Throwable $exception) {
/** @codeCoverageIgnore */
throw CreateTemporaryZipFileException::create('Cannot store contents on temporary file', $exception);
}
if (false === $write) {
/** @codeCoverageIgnore */
throw CreateTemporaryZipFileException::create('Cannot store contents on temporary file');
}

Expand Down
73 changes: 41 additions & 32 deletions src/RequestBuilder/FielRequestBuilder/FielRequestBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,34 +74,57 @@ public function authorization(DateTime $created, DateTime $expires, string $secu

public function query(QueryParameters $queryParameters): string
{
// normalize input
$start = $queryParameters->getPeriod()->getStart()->format('Y-m-d\TH:i:s');
$end = $queryParameters->getPeriod()->getEnd()->format('Y-m-d\TH:i:s');
$queryByUuid = ! $queryParameters->getUuid()->isEmpty();
$xmlRfcReceived = '';
$requestType = $queryParameters->getRequestType()->getQueryAttributeValue($queryParameters->getServiceType());
$rfcSigner = mb_strtoupper($this->getFiel()->getRfc());
if ($queryParameters->getDownloadType()->isIssued()) {
// issued documents, counterparts are receivers
$rfcIssuer = $rfcSigner;
$rfcReceivers = $queryParameters->getRfcMatches();
} else {
// received documents, counterpart is issuer
$rfcIssuer = $queryParameters->getRfcMatches()->getFirst()->getValue();
$rfcReceivers = RfcMatches::createFromValues($rfcSigner);
}

$solicitudAttributes = array_filter(
[
'RfcSolicitante' => $rfcSigner,
$solicitudAttributes = [
'RfcSolicitante' => $rfcSigner,
'TipoSolicitud' => $requestType,
];

if ($queryByUuid) {
$solicitudAttributes = $solicitudAttributes + [
'Folio' => $queryParameters->getUuid()->getValue(),
];
} else {
$start = $queryParameters->getPeriod()->getStart()->format('Y-m-d\TH:i:s');
$end = $queryParameters->getPeriod()->getEnd()->format('Y-m-d\TH:i:s');
if ($queryParameters->getDownloadType()->isIssued()) {
// issued documents, counterparts are receivers
$rfcIssuer = $rfcSigner;
$rfcReceivers = $queryParameters->getRfcMatches();
} else {
// received documents, counterpart is issuer
$rfcIssuer = $queryParameters->getRfcMatches()->getFirst()->getValue();
$rfcReceivers = RfcMatches::createFromValues($rfcSigner);
}
$solicitudAttributes = $solicitudAttributes + [
'FechaInicial' => $start,
'FechaFinal' => $end,
'TipoSolicitud' => $requestType,
'RfcEmisor' => $rfcIssuer,
'TipoComprobante' => $queryParameters->getDocumentType()->value(),
'EstadoComprobante' => $queryParameters->getDocumentStatus()->value(),
'UUID' => $queryParameters->getUuid()->getValue(),
'RfcACuentaTerceros' => $queryParameters->getRfcOnBehalf()->getValue(),
'Complemento' => $queryParameters->getComplement()->value(),
],
];
if (! $rfcReceivers->isEmpty()) {
$xmlRfcReceived = implode('', array_map(
function (RfcMatch $rfcMatch): string {
return sprintf(
'<des:RfcReceptor>%s</des:RfcReceptor>',
$this->parseXml($rfcMatch->getValue())
);
},
iterator_to_array($rfcReceivers)
));
$xmlRfcReceived = "<des:RfcReceptores>{$xmlRfcReceived}</des:RfcReceptores>";
}
}

$solicitudAttributes = array_filter(
$solicitudAttributes,
static function (string $value): bool {
return '' !== $value;
}
Expand All @@ -116,20 +139,6 @@ function (string $name, string $value): string {
$solicitudAttributes,
));

$xmlRfcReceived = '';
if (! $rfcReceivers->isEmpty()) {
$xmlRfcReceived = implode('', array_map(
function (RfcMatch $rfcMatch): string {
return sprintf(
'<des:RfcReceptor>%s</des:RfcReceptor>',
$this->parseXml($rfcMatch->getValue())
);
},
iterator_to_array($rfcReceivers)
));
$xmlRfcReceived = "<des:RfcReceptores>{$xmlRfcReceived}</des:RfcReceptores>";
}

$toDigestXml = <<<EOT
<des:SolicitaDescarga xmlns:des="http://DescargaMasivaTerceros.sat.gob.mx">
<des:solicitud ${solicitudAttributesAsText}>
Expand Down
2 changes: 1 addition & 1 deletion src/Shared/RfcMatches.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static function create(RfcMatch ...$items): self
$map = [];
foreach ($items as $item) {
$key = $item->getValue();
if (! $item->isEmpty() and ! isset($map[$key])) {
if (! $item->isEmpty() && ! isset($map[$key])) {
$map[$item->getValue()] = $item;
}
}
Expand Down
30 changes: 29 additions & 1 deletion tests/Integration/ConsumeCfdiServicesUsingFakeFielTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace PhpCfdi\SatWsDescargaMasiva\Tests\Integration;

use LogicException;
use PhpCfdi\SatWsDescargaMasiva\Services\Query\QueryParameters;
use PhpCfdi\SatWsDescargaMasiva\Shared\ComplementoCfdi;
use PhpCfdi\SatWsDescargaMasiva\Shared\DateTimePeriod;
Expand All @@ -14,6 +15,7 @@
use PhpCfdi\SatWsDescargaMasiva\Shared\RfcMatch;
use PhpCfdi\SatWsDescargaMasiva\Shared\RfcOnBehalf;
use PhpCfdi\SatWsDescargaMasiva\Shared\ServiceEndpoints;
use PhpCfdi\SatWsDescargaMasiva\Shared\ServiceType;
use PhpCfdi\SatWsDescargaMasiva\Shared\Uuid;

final class ConsumeCfdiServicesUsingFakeFielTest extends ConsumeServiceTestCase
Expand All @@ -34,7 +36,6 @@ public function testQueryChangeAllParameters(): void
->withDocumentType(DocumentType::nomina())
->withComplement(ComplementoCfdi::nomina12())
->withDocumentStatus(DocumentStatus::active())
->withUuid(Uuid::create('96623061-61fe-49de-b298-c7156476aa8b'))
->withRfcOnBehalf(RfcOnBehalf::create('XXX01010199A'))
->withRfcMatch(RfcMatch::create('AAA010101AAA'))
;
Expand All @@ -46,4 +47,31 @@ public function testQueryChangeAllParameters(): void
'Expected to receive a 305 - Certificado Inválido from SAT since FIEL is for testing'
);
}

public function testQueryUuid(): void
{
$service = $this->createService();

$parameters = QueryParameters::create()
->withUuid(Uuid::create('96623061-61fe-49de-b298-c7156476aa8b'))
;

$result = $service->query($parameters);
$this->assertSame(
305,
$result->getStatus()->getCode(),
'Expected to receive a 305 - Certificado Inválido from SAT since FIEL is for testing'
);
}

public function testServiceEndpointsDifferentThanQueryEndpointsThrowsError(): void
{
$service = $this->createService();

$otherServiceType = ServiceType::retenciones();
$parameters = QueryParameters::create()->withServiceType($otherServiceType);

$this->expectException(LogicException::class);
$service->query($parameters);
}
}
32 changes: 30 additions & 2 deletions tests/Integration/ConsumeRetencionesServicesUsingFakeFielTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace PhpCfdi\SatWsDescargaMasiva\Tests\Integration;

use LogicException;
use PhpCfdi\SatWsDescargaMasiva\Services\Query\QueryParameters;
use PhpCfdi\SatWsDescargaMasiva\Shared\ComplementoRetenciones;
use PhpCfdi\SatWsDescargaMasiva\Shared\DateTimePeriod;
Expand All @@ -13,6 +14,7 @@
use PhpCfdi\SatWsDescargaMasiva\Shared\RfcMatch;
use PhpCfdi\SatWsDescargaMasiva\Shared\RfcOnBehalf;
use PhpCfdi\SatWsDescargaMasiva\Shared\ServiceEndpoints;
use PhpCfdi\SatWsDescargaMasiva\Shared\ServiceType;
use PhpCfdi\SatWsDescargaMasiva\Shared\Uuid;

/**
Expand All @@ -25,7 +27,7 @@ protected function getServiceEndpoints(): ServiceEndpoints
return ServiceEndpoints::retenciones();
}

public function testQueryChangeAllParameters(): void
public function testQueryChangeFilters(): void
{
$service = $this->createService();

Expand All @@ -35,7 +37,6 @@ public function testQueryChangeAllParameters(): void
->withRequestType(RequestType::xml())
->withComplement(ComplementoRetenciones::undefined())
->withDocumentStatus(DocumentStatus::active())
->withUuid(Uuid::create('96623061-61fe-49de-b298-c7156476aa8b'))
->withRfcOnBehalf(RfcOnBehalf::create('XXX01010199A'))
->withRfcMatch(RfcMatch::create('AAA010101AAA'))
;
Expand All @@ -47,4 +48,31 @@ public function testQueryChangeAllParameters(): void
'Expected to receive a 305 - Certificado Inválido from SAT since FIEL is for testing'
);
}

public function testQueryByUuid(): void
{
$service = $this->createService();

$parameters = QueryParameters::create()
->withUuid(Uuid::create('96623061-61fe-49de-b298-c7156476aa8b'))
;

$result = $service->query($parameters);
$this->assertSame(
305,
$result->getStatus()->getCode(),
'Expected to receive a 305 - Certificado Inválido from SAT since FIEL is for testing'
);
}

public function testServiceEndpointsDifferentThanQueryEndpointsThrowsError(): void
{
$service = $this->createService();

$otherServiceType = ServiceType::cfdi();
$parameters = QueryParameters::create()->withServiceType($otherServiceType);

$this->expectException(LogicException::class);
$service->query($parameters);
}
}
Loading