Skip to content

Commit

Permalink
Merge pull request #78 from eclipxe13/ft/metadatalist-messages
Browse files Browse the repository at this point in the history
Deprecación de `MaximumRecordsHandler` a favor de `MetadataMessageHandler`
  • Loading branch information
eclipxe13 authored Dec 4, 2023
2 parents b739661 + 080e834 commit 4e28300
Show file tree
Hide file tree
Showing 20 changed files with 420 additions and 121 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
php-version: '8.3'
coverage: none
tools: cs2pr, phpcs
env:
Expand All @@ -39,7 +39,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
php-version: '8.3'
coverage: none
tools: cs2pr, php-cs-fixer
env:
Expand All @@ -56,7 +56,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
php-version: '8.3'
coverage: none
tools: composer-normalize
env:
Expand All @@ -73,7 +73,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
php-version: '8.3'
coverage: none
tools: composer:v2, phpstan
env:
Expand All @@ -97,7 +97,7 @@ jobs:
runs-on: "ubuntu-latest"
strategy:
matrix:
php-versions: ['7.3', '7.4', '8.0', '8.1', '8.2']
php-versions: ['7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ on:
jobs:

tests-coverage:
name: Tests on PHP 8.2 (code coverage)
name: Tests on PHP 8.3 (code coverage)
runs-on: "ubuntu-latest"
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
php-version: '8.3'
coverage: xdebug
tools: composer:v2
env:
Expand Down Expand Up @@ -79,7 +79,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
php-version: '8.3'
coverage: none
tools: composer:v2
- name: Get composer cache directory
Expand Down
6 changes: 3 additions & 3 deletions .phive/phars.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="php-cs-fixer" version="^3.20.0" installed="3.20.0" location="./tools/php-cs-fixer" copy="false"/>
<phar name="php-cs-fixer" version="^3.40.0" installed="3.40.0" location="./tools/php-cs-fixer" copy="false"/>
<phar name="phpcs" version="^3.7.2" installed="3.7.2" location="./tools/phpcs" copy="false"/>
<phar name="phpcbf" version="^3.7.2" installed="3.7.2" location="./tools/phpcbf" copy="false"/>
<phar name="phpstan" version="^1.10.22" installed="1.10.22" location="./tools/phpstan" copy="false"/>
<phar name="composer-normalize" version="^2.32.0" installed="2.32.0" location="./tools/composer-normalize" copy="false"/>
<phar name="phpstan" version="^1.10.46" installed="1.10.46" location="./tools/phpstan" copy="false"/>
<phar name="composer-normalize" version="^2.39.0" installed="2.39.0" location="./tools/composer-normalize" copy="false"/>
</phive>
2 changes: 1 addition & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
'whitespace_after_comma_in_array' => true,
'no_empty_statement' => true,
'no_extra_blank_lines' => true,
'function_typehint_space' => true,
'type_declaration_spaces' => true,
'trailing_comma_in_multiline' => ['after_heredoc' => true, 'elements' => ['arrays', 'arguments']],
'no_blank_lines_after_phpdoc' => true,
'object_operator_without_whitespace' => true,
Expand Down
46 changes: 33 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,44 +221,64 @@ $list = $satScraper->listByUuids($uuids, DownloadType::recibidos());
echo json_encode($list);
```

## Aviso de que existen más de 500 comprobantes en un mismo segundo
## Avisos de descargas de Metadata

El servicio ofrecido por el SAT tiene límites, entre ellos, no se pueden obtener más de 500 registros
en un rango de fechas. Esta librería trata de reducir el rango hasta el mínimo de una consulta en un segundo
para obtener todos los datos, sin embargo, si se presenta este caso, entonces se puede invocar a un manejador
que le puede ayudar a registrar este escenario.
en un rango de fechas. Esta librería trata de reducir el rango hasta el mínimo de fabricar una consulta por
un solo segundo para obtener todos los datos, sin embargo, si se presenta este caso, entonces se puede usar
el manejador `MetadataMessageHandler` para registrar este escenario.

El manejador `MetadataMessageHandler` es una interfaz que puede recibir diferentes mensajes:

- `resolved(DateTimeImmutable $since, DateTimeImmutable $until, int $count): void`:
Ocurre cuando se resolvió una consulta entre dos momentos en un mismo día, siempre serán menos de 500 registros.
- `date(DateTimeImmutable $since, DateTimeImmutable $until, int $count): void`:
Ocurre cuando se resolvió una consulta de un día determinado.
Hay un momento inicial y otro final porque las horas podrían ser diferentes a `00:00:00` y `23:59:59`.
- `divide(DateTimeImmutable $since, DateTimeImmutable $until): void`:
Ocurre cuando se encontraron 500 registros en un periodo.
Se dividirá la consulta para intentar descargar el contenido completo.
- `maximum(DateTimeImmutable $moment): void`:
Ocurre cuando se encontraron 500 registros en un solo segundo.

Si al crear el objeto `SatScraper` no se establece un manejador o se establece como `null` entonces se usará
una instancia de `NullMaximumRecordsHandler` que, como su nombre lo indica, no realiza ninguna acción.
una instancia de `NullMetadataMessageHandler` que, como su nombre lo indica, no realiza ninguna acción.

En el siguiente código se muestra un ejemplo que muestra un mensaje al encontrar el problema de 500 registros.

```php
<?php declare(strict_types=1);

use PhpCfdi\CfdiSatScraper\NullMetadataMessageHandler;
use PhpCfdi\CfdiSatScraper\QueryByFilters;
use PhpCfdi\CfdiSatScraper\SatHttpGateway;
use PhpCfdi\CfdiSatScraper\SatScraper;
use PhpCfdi\CfdiSatScraper\Sessions\SessionManager;

// define handler
$handler = new class () implements MaximumRecordsHandler {
public function handle(DateTimeImmutable $date): void
/**
* @var SessionManager $sessionManager
* @var SatHttpGateway $httpGateway
*/

// se define el controlador de mensajes
$handler = new class () extends NullMetadataMessageHandler {
public function maximum(DateTimeImmutable $date): void
{
echo 'Se encontraron más de 500 CFDI en el segundo: ', $date->format('c'), PHP_EOL;
}
};

// create scraper using the handler
/**
* @var SessionManager $sessionManager
* @var SatHttpGateway $httpGateway
*/
// se crea el scraper usando el controlador de mensajes
$satScraper = new SatScraper($sessionManager, $httpGateway, $handler);

$query = new QueryByFilters(new DateTimeImmutable('2019-03-01'), new DateTimeImmutable('2019-03-31'));
$list = $satScraper->listByPeriod($query);
echo json_encode($list);
```

La interfaz `MaximumRecordsHandler` y el objeto `NullMaximumRecordsHandler` han sido deprecados desde la versión `3.3.0`.
Ambos símbolos serán eliminados a partir de la versión `4.0.0`.

## Descargar CFDIS a una carpeta

Ejecutar el método `saveTo` devuelve un arreglo con los UUID que fueron efectivamente descargados.
Expand Down
23 changes: 23 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,29 @@ Usamos [Versionado Semántico 2.0.0](SEMVER.md) por lo que puedes usar esta libr

## Cambios aún no liberados en una versión

## Versión 3.3.0 2023-12-03

Se agregó la interfaz `MetadataMessageHandler` que permite recibir notificaciones de la descarga de *Metadata*.
Dentro de las notificaciones se incluye la que ocurre cuando se encontraron 500 registros en un solo segundo.

Se deprecó la interfaz `MaximumRecordsHandler`, es sustituida por `MetadataMessageHandler`.

Se deprecó el método `SatScraper::getMaximumRecordsHandler()` a favor de `SatScraper::getMetadataMessageHandler()`.

Para no introducir un cambio que rompa la compatibilidad, el constructor de `SatScraper` sigue soportando la
creación del objeto con el argumento `MaximumRecordsHandler $maximumRecordsHandler`.
En su lugar, debería enviar un objeto que implemente la interfaz `MetadataMessageHandler`.

Se introduce el objeto `NullMetadataMessageHandler` que implementa la interfaz `MetadataMessageHandler`,
pero no realiza ninguna acción en sus métodos.

Otros cambios al entorno de desarrollo:

- Se actualizan las dependencias de desarrollo.
- Se agrega PHP 8.3 a la matrix de pruebas.
- Los trabajos se ejecutan con PHP 8.3.
- Para `php-cs-fixer` se sustituye `function_typehint_space` con `type_declaration_spaces`.

## Versión 3.2.5 2023-07-03

Algunos métodos intentaban atrapar una excepción `RuntimeException` proveniente de `Crawler`, sin embargo,
Expand Down
4 changes: 4 additions & 0 deletions src/Contracts/MaximumRecordsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

use DateTimeImmutable;

/**
* @see MetadataMessageHandler
* @deprecated 3.3.0
*/
interface MaximumRecordsHandler
{
public function handle(DateTimeImmutable $moment): void;
Expand Down
32 changes: 32 additions & 0 deletions src/Contracts/MetadataMessageHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\CfdiSatScraper\Contracts;

use DateTimeImmutable;

interface MetadataMessageHandler
{
/**
* Ocurre cuando se resolvió una consulta entre dos momentos en un mismo día, siempre serán menos de 500 registros.
*/
public function resolved(DateTimeImmutable $since, DateTimeImmutable $until, int $count): void;

/**
* Ocurre cuando se resolvió una consulta de un día determinado.
* Hay un momento inicial y otro final porque las horas podrían ser diferentes a 00:00:00 y 23:59:59.
*/
public function date(DateTimeImmutable $since, DateTimeImmutable $until, int $count): void;

/**
* Ocurre cuando se encontraron 500 registros en un periodo.
* Se dividirá la consulta para intentar descargar el contenido completo.
*/
public function divide(DateTimeImmutable $since, DateTimeImmutable $until): void;

/**
* Ocurre cuando se encontraron 500 registros en un solo segundo.
*/
public function maximum(DateTimeImmutable $moment): void;
}
32 changes: 32 additions & 0 deletions src/Internal/MaximumRecordsHandlerWrapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\CfdiSatScraper\Internal;

use DateTimeImmutable;
use PhpCfdi\CfdiSatScraper\Contracts\MaximumRecordsHandler;
use PhpCfdi\CfdiSatScraper\NullMetadataMessageHandler;

/**
* This class wraps a MaximumRecordsHandler into a MetadataMessageHandler.
* This class will be removed on version 4.0.0
*
* @internal
*/
final class MaximumRecordsHandlerWrapper extends NullMetadataMessageHandler
{
/** @var MaximumRecordsHandler */
private $maximumRecordsHandler;

public function __construct(MaximumRecordsHandler $maximumRecordsHandler)
{
$this->maximumRecordsHandler = $maximumRecordsHandler;
}

/** @noinspection PhpMissingParentCallCommonInspection */
public function maximum(DateTimeImmutable $moment): void
{
$this->maximumRecordsHandler->handle($moment);
}
}
29 changes: 14 additions & 15 deletions src/Internal/MetadataDownloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use DateTimeImmutable;
use Generator;
use PhpCfdi\CfdiSatScraper\Contracts\MaximumRecordsHandler;
use PhpCfdi\CfdiSatScraper\Contracts\MetadataMessageHandler;
use PhpCfdi\CfdiSatScraper\Contracts\QueryInterface;
use PhpCfdi\CfdiSatScraper\Exceptions\LogicException;
use PhpCfdi\CfdiSatScraper\Exceptions\SatHttpGatewayException;
Expand All @@ -33,24 +33,24 @@ class MetadataDownloader
/** @var QueryResolver */
private $queryResolver;

/** @var MaximumRecordsHandler */
private $maximumRecordsHandler;
/** @var MetadataMessageHandler */
private $messageHandler;

/** @internal */
public function __construct(QueryResolver $queryResolver, MaximumRecordsHandler $maximumRecordsHandler)
public function __construct(QueryResolver $queryResolver, MetadataMessageHandler $messageHandler)
{
$this->queryResolver = $queryResolver;
$this->maximumRecordsHandler = $maximumRecordsHandler;
$this->messageHandler = $messageHandler;
}

public function getQueryResolver(): QueryResolver
{
return $this->queryResolver;
}

public function getMaximumRecordsHandler(): MaximumRecordsHandler
public function getMessageHandler(): MetadataMessageHandler
{
return $this->maximumRecordsHandler;
return $this->messageHandler;
}

/**
Expand Down Expand Up @@ -109,7 +109,9 @@ public function downloadByDateTime(QueryByFilters $query): MetadataList
{
$result = new MetadataList([]);
foreach ($this->splitQueryByFiltersByDays($query) as $current) {
$result = $result->merge($this->downloadQuery($current));
$list = $this->downloadQuery($current);
$this->messageHandler->date($current->getStartDate(), $current->getEndDate(), $list->count());
$result = $result->merge($list);
}
return $result;
}
Expand All @@ -134,14 +136,16 @@ public function downloadQuery(QueryByFilters $query): MetadataList
$result = $list->count();

if ($result >= 500 && $secondEnd === $secondInitial) {
$this->raiseOnLimit($this->buildDateWithDayAndSeconds($day, $secondInitial));
$this->messageHandler->maximum($currentQuery->getStartDate());
}

if ($result >= 500 && $secondEnd > $secondInitial) {
$secondEnd = (int)floor($secondInitial + (($secondEnd - $secondInitial) / 2));
$this->messageHandler->divide($currentQuery->getStartDate(), $currentQuery->getEndDate());
$secondEnd = (int) floor($secondInitial + (($secondEnd - $secondInitial) / 2));
continue;
}

$this->messageHandler->resolved($currentQuery->getStartDate(), $currentQuery->getEndDate(), $list->count());
$finalList = $finalList->merge($list);
if ($secondEnd >= $upperBound) {
break;
Expand Down Expand Up @@ -179,11 +183,6 @@ public function buildDateWithDayAndSeconds(DateTimeImmutable $day, int $seconds)
return $day->modify(sprintf('midnight + %d seconds', $seconds));
}

public function raiseOnLimit(DateTimeImmutable $date): void
{
$this->maximumRecordsHandler->handle($date);
}

public function createInputsFromQuery(QueryInterface $query): InputsInterface
{
if ($query instanceof QueryByFilters) {
Expand Down
31 changes: 31 additions & 0 deletions src/Internal/MetadataMessageHandlerWrapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace PhpCfdi\CfdiSatScraper\Internal;

use DateTimeImmutable;
use PhpCfdi\CfdiSatScraper\Contracts\MaximumRecordsHandler;
use PhpCfdi\CfdiSatScraper\Contracts\MetadataMessageHandler;

/**
* This class wraps a MetadataMessageHandler into a MaximumRecordsHandler.
* This class will be removed on version 4.0.0
*
* @internal
*/
final class MetadataMessageHandlerWrapper implements MaximumRecordsHandler
{
/** @var MetadataMessageHandler */
private $messageHandler;

public function __construct(MetadataMessageHandler $messageHandler)
{
$this->messageHandler = $messageHandler;
}

public function handle(DateTimeImmutable $moment): void
{
$this->messageHandler->maximum($moment);
}
}
1 change: 1 addition & 0 deletions src/Internal/NullMaximumRecordsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
/**
* Null implementation of MaximumRecordsHandler.
*
* @deprecated
* @internal
*/
final class NullMaximumRecordsHandler implements MaximumRecordsHandler
Expand Down
Loading

0 comments on commit 4e28300

Please sign in to comment.