Provider SII

This commit is contained in:
Juan Pablo Vial
2025-05-05 18:14:50 -04:00
parent af68c4b8ec
commit 594cb68b09

View File

@ -0,0 +1,129 @@
<?php
namespace Incoviba\Service\Money;
use DateTimeInterface;
use DateTimeImmutable;
use PDO;
use PDOException;
use Psr\Http\Client\ClientInterface;
use Dom\HTMLDocument;
use GuzzleHttp\Exception\GuzzleException;
use Incoviba\Common\Implement\Exception\EmptyResponse;
use Incoviba\Common\Define;
use Incoviba\Repository;
use Incoviba\Service;
class SII implements Define\Money\Provider
{
public function __construct(protected ClientInterface $client, protected Service\Valor $valorService,
protected Repository\UF $ufRepository) {}
public function get(string $money_symbol, ?DateTimeInterface $dateTime = null): float
{
if ($money_symbol === Service\Money::UF) {
return $this->getUF($dateTime);
}
$class = __CLASS__;
throw new EmptyResponse("{$money_symbol} not found in {$class}");
}
/**
* @param DateTimeInterface|null $dateTime
* @return float
* @throws EmptyResponse
*/
protected function getUF(?DateTimeInterface $dateTime = null): float
{
if ($dateTime === null) {
$dateTime = new DateTimeImmutable();
}
$year = $this->getUFYear($dateTime);
return $year[$dateTime->format('Y-m-d')];
}
/**
* @param DateTimeImmutable|null $dateTime
* @return array
* @throws EmptyResponse
*/
protected function getUFYear(?DateTimeImmutable $dateTime = null): array
{
if ($dateTime === null) {
$dateTime = new DateTimeImmutable();
}
$request_uri = "uf/uf{$dateTime->format('Y')}.htm";
try {
$response = $this->client->get($request_uri);
} catch (GuzzleException) {
throw new EmptyResponse($request_uri);
}
if ((int) floor($response->getStatusCode() / 100) !== 2) {
throw new EmptyResponse($request_uri);
}
$body = $response->getBody();
$domHandler = HTMLDocument::createFromString($body->getContents());
$table = $domHandler->querySelector('div#mes_all');
$tbody = $table->querySelector('tbody');
$trs = $tbody->querySelectorAll('tr');
/**
* [th Dia, th Ene, Feb, Mar, Abr, May, Jun, Jul, Ago, Sep, Oct, Nov, Dic]
* [th 1, td #, #, #, #, #, #, #, #, #, #, #, #]
*/
$year = [];
foreach ($trs as $i => $tr) {
$tds = $tr->querySelectorAll('td');
foreach ($tds as $j => $td) {
$value = $td->nodeValue;
if (trim($value) === '') {
continue;
}
$d = str_pad($j + 1, 2, '0', STR_PAD_LEFT);
$m = str_pad($i, 2, '0', STR_PAD_LEFT);
$date = "{$dateTime->format('Y')}-{$m}-{$d}";
trigger_error($date);
$value = $this->valorService->clean($value);
$year[$date] = $value;
}
}
$this->saveUFs($year);
return $year;
}
protected function saveUFs(array $ufs): void
{
$dates = array_keys($ufs);
$dateString = "'" . implode("', '", $dates) . "'";
$query1 = $this->ufRepository->getConnection()->getQueryBuilder()
->select('DISTINCT fecha')
->from($this->ufRepository->getTable())
->where("fecha IN ({$dateString})");
try {
$statement = $this->ufRepository->getConnection()->query($query1);
$results = $statement->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $row) {
if (isset($ufs[$row['fecha']])) {
unset($ufs[$row['fecha']]);
}
}
} catch (PDOException) {
return;
}
$values = [];
foreach ($ufs as $fecha => $value) {
$values []= [$fecha, $value];
}
$valueString = implode(', ', array_fill(0, count($values), '(?, ?)'));
$query2 = "INSERT INTO {$this->ufRepository->getTable()} (fecha, valor) VALUES {$valueString}";
$this->ufRepository->getConnection()->getPDO()->beginTransaction();
try {
$this->ufRepository->getConnection()->execute($query2, $values);
if ($this->ufRepository->getConnection()->getPDO()->inTransaction()) {
$this->ufRepository->getConnection()->getPDO()->commit();
}
} catch (PDOException) {
if ($this->ufRepository->getConnection()->getPDO()->inTransaction()) {
$this->ufRepository->getConnection()->getPDO()->rollBack();
}
}
}
}