diff --git a/app/resources/views/ventas/facturacion/show.blade.php b/app/resources/views/ventas/facturacion/show.blade.php
index b5e3f0d..63b08ba 100644
--- a/app/resources/views/ventas/facturacion/show.blade.php
+++ b/app/resources/views/ventas/facturacion/show.blade.php
@@ -44,6 +44,7 @@
facturas: () => {
document.getElementById(this.ids.facturas).innerHTML = this.venta.draw().facturas(this.formatters)
this.venta.watch().facturas()
+ $('[data-html]').popup()
}
}
},
diff --git a/app/resources/views/ventas/facturacion/show/factura.blade.php b/app/resources/views/ventas/facturacion/show/factura.blade.php
index 44547c3..ab909ba 100644
--- a/app/resources/views/ventas/facturacion/show/factura.blade.php
+++ b/app/resources/views/ventas/facturacion/show/factura.blade.php
@@ -220,9 +220,47 @@
},
resumen: ({no, classes, formatters}) => {
const emptyTerreno = '
0
'
+ const calculoTerreno = [
+ [
+ `Base Terreno (${formatters.date.format(this.props.terreno.fecha)})`,
+ `\$${formatters.pesos.format(this.props.terreno.valor)}`
+ ],
+ [
+ `IPC (${formatters.date.format(this.props.fecha)})`,
+ `${formatters.percent.format({{ $ipc }})}%`
+ ],
+ [
+ 'Prorrateo',
+ `${formatters.percent.format(this.props.detalle.descuento * 100)}%`
+ ],
+ [
+ 'Proporcion',
+ `${(this.props.proporcion * 100).toFixed(2).replace('.', ',')}%`
+ ],
+ [
+ 'Terreno Aplicado',
+ `\$${formatters.pesos.format(this.props.detalle.terreno)}`
+ ]
+ ]
+ const tableClasses = [
+ '',
+ " align='right'"
+ ]
+ const calculoTerrenoTable = [
+ '
'
+ ]
+ calculoTerreno.forEach(items => {
+ const row = []
+ items.forEach((cell, idx) => {
+ row.push(`| ${cell} | `)
+ })
+ calculoTerrenoTable.push(`${row.join('')}
`)
+ })
+ calculoTerrenoTable.push('
')
+
const data = [
no,
- 'Valor con Terreno: $' + formatters.pesos.format(this.props.detalle.base) + ' - Menos valor terreno: $' + ((this.props.detalle.terreno > 0) ? formatters.pesos.format(-this.props.detalle.terreno) : emptyTerreno) + '
' +
+ 'Valor con Terreno: $' + formatters.pesos.format(this.props.detalle.base) + ' - Menos valor terreno:
$' + ((this.props.detalle.terreno > 0) ? formatters.pesos.format(-this.props.detalle.terreno) : emptyTerreno) + '' +
'Base imponible (Neto): $' + formatters.pesos.format(this.props.detalle.neto) + '
' +
'IVA: $' + formatters.pesos.format(this.props.detalle.iva) + '
' +
'SUBTOTAL (Bruto): $' + formatters.pesos.format(this.props.detalle.bruto) + '
' +
diff --git a/app/setup/setups/services.php b/app/setup/setups/services.php
index e5cf4de..51df011 100644
--- a/app/setup/setups/services.php
+++ b/app/setup/setups/services.php
@@ -15,21 +15,24 @@ return [
);
},
Incoviba\Service\Money::class => function(ContainerInterface $container) {
- $mindicador = new Incoviba\Service\Money\MiIndicador(new GuzzleHttp\Client([
+ $mindicador = new Incoviba\Service\Money\MiIndicador($container->get(Psr\Log\LoggerInterface::class), new GuzzleHttp\Client([
'base_uri' => 'https://mindicador.cl/api/',
'headers' => ['Accept' => 'application/json']
]));
- $ine = new Incoviba\Service\Money\Ine(new GuzzleHttp\Client([
+ $ine = new Incoviba\Service\Money\Ine($container->get(Psr\Log\LoggerInterface::class), new GuzzleHttp\Client([
'base_uri' => 'https://api-calculadora.ine.cl/ServiciosCalculadoraVariacion'
]));
- $sii = new Incoviba\Service\Money\SII(new GuzzleHttp\Client([
+ $sii = new Incoviba\Service\Money\SII($container->get(Psr\Log\LoggerInterface::class), new GuzzleHttp\Client([
'base_uri' => 'https://www.sii.cl/valores_y_fechas/'
]), $container->get(Incoviba\Repository\UF::class));
- return (new Incoviba\Service\Money($container->get(Psr\Log\LoggerInterface::class)))
- ->register('uf', $mindicador)
- ->register('uf', $sii)
- ->register('usd', $mindicador)
- ->register('ipc', $ine);
+ $findic = new Incoviba\Service\Money\Findic($container->get(Psr\Log\LoggerInterface::class), new GuzzleHttp\Client([
+ 'base_uri' => 'https://findic.cl/api/'
+ ]));
+ return new Incoviba\Service\Money($container->get(Psr\Log\LoggerInterface::class))
+ ->register($findic)
+ ->register($sii)
+ ->register($ine)
+ ->register($mindicador);
},
Predis\ClientInterface::class => function(ContainerInterface $container) {
$options = [
@@ -46,7 +49,7 @@ return [
return new Predis\Client($options);
},
Incoviba\Service\Contabilidad\Cartola::class => function(ContainerInterface $container) {
- return (new Incoviba\Service\Contabilidad\Cartola(
+ return new Incoviba\Service\Contabilidad\Cartola(
$container->get(Psr\Log\LoggerInterface::class),
$container->get(Psr\Http\Message\StreamFactoryInterface::class),
$container->get(Incoviba\Common\Define\Contabilidad\Exporter::class),
@@ -55,7 +58,7 @@ return [
$container->get(Incoviba\Repository\Contabilidad\Movimiento::class),
$container->get(Incoviba\Service\Contabilidad\Movimiento::class),
$container->get(Incoviba\Repository\Contabilidad\Cartola::class)
- ))
+ )
->register('security', $container->get(Incoviba\Service\Contabilidad\Cartola\Security::class))
->register('itau', $container->get(Incoviba\Service\Contabilidad\Cartola\Itau::class))
->register('santander', $container->get(Incoviba\Service\Contabilidad\Cartola\Santander::class))
@@ -89,11 +92,10 @@ return [
$container->get('nubox')->get('url'));
},
Incoviba\Service\Informe::class => function(ContainerInterface $container) {
- return (new Incoviba\Service\Informe(
+ return new Incoviba\Service\Informe(
$container->get(Psr\Log\LoggerInterface::class),
$container->get('folders')->get('informes'))
- )
- ->register('xlsx', Incoviba\Service\Informe\Excel::class);
+ ->register('xlsx', Incoviba\Service\Informe\Excel::class);
},
Incoviba\Service\Contabilidad\Informe\Tesoreria\Output\Excel::class => function(ContainerInterface $container) {
return new Incoviba\Service\Contabilidad\Informe\Tesoreria\Output\Excel(
@@ -104,15 +106,15 @@ return [
);
},
Incoviba\Service\Contabilidad\Cartola\Santander::class => function(ContainerInterface $container) {
- return (new Incoviba\Service\Contabilidad\Cartola\Santander(
+ return new Incoviba\Service\Contabilidad\Cartola\Santander(
$container->get(Psr\Log\LoggerInterface::class),
- ))
+ )
->registerSub($container->get(Incoviba\Service\Contabilidad\Cartola\Santander\OfficeBanking::class));
},
Incoviba\Service\Contabilidad\Cartola\BCI::class => function(ContainerInterface $container) {
- return (new Incoviba\Service\Contabilidad\Cartola\BCI(
+ return new Incoviba\Service\Contabilidad\Cartola\BCI(
$container->get(Psr\Log\LoggerInterface::class),
- ))
+ )
->registerSub($container->get(Incoviba\Service\Contabilidad\Cartola\BCI\Mes::class));
},
'TokuClient' => function(ContainerInterface $container) {
diff --git a/app/src/Controller/API/Contabilidad/Cartolas.php b/app/src/Controller/API/Contabilidad/Cartolas.php
index 88cfc33..b1d63bb 100644
--- a/app/src/Controller/API/Contabilidad/Cartolas.php
+++ b/app/src/Controller/API/Contabilidad/Cartolas.php
@@ -127,6 +127,9 @@ class Cartolas extends Controller
$output['errors'] []= ['filename' => $file->getClientFilename(), 'error' => $errors[$file->getError()]];
continue;
}
+ if (empty($body['cuenta_id'])) {
+ continue;
+ }
try {
$output['movimientos'] = array_merge($output['movimientos'], $cartolaService->import($body['cuenta_id'][$i], $file));
} catch (Read $exception) {
diff --git a/app/src/Repository/Contabilidad/Movimiento/Detalle.php b/app/src/Repository/Contabilidad/Movimiento/Detalle.php
index b70a059..b8fa540 100644
--- a/app/src/Repository/Contabilidad/Movimiento/Detalle.php
+++ b/app/src/Repository/Contabilidad/Movimiento/Detalle.php
@@ -28,6 +28,9 @@ class Detalle extends Ideal\Repository
->register('centro_costo_id', (new Implement\Repository\Mapper())
->setProperty('centroCosto')
->setFunction(function(array $data) {
+ if (empty($data['centro_costo_id'])) {
+ return null;
+ }
return $this->centroCostoRepository->fetchById($data['centro_costo_id']);
})
->setDefault(null));
diff --git a/app/src/Service/IPC.php b/app/src/Service/IPC.php
index b8a51b2..8d1a546 100644
--- a/app/src/Service/IPC.php
+++ b/app/src/Service/IPC.php
@@ -5,11 +5,13 @@ use DateTimeInterface;
use DateTimeImmutable;
use DateInterval;
use Incoviba\Common\Implement\Exception\EmptyRedis;
+use Psr\Log\LoggerInterface;
class IPC
{
protected string $redisKey = 'ipc';
- public function __construct(protected Redis $redisService, protected Money $moneyService) {}
+ public function __construct(protected LoggerInterface $logger, protected Redis $redisService,
+ protected Money $moneyService) {}
public function get(DateTimeInterface $from, DateTimeInterface $to = new DateTimeImmutable()): float
{
@@ -33,7 +35,7 @@ class IPC
ksort($ipcs);
$this->redisService->set($this->redisKey, json_encode($ipcs), 60 * 60 * 24 * 30);
}
- return $ipcs[$dateKey];
+ return $ipcs[$dateKey] * ($ipcs[$dateKey] > 1 ? 1/100 : 1);
}
public function readjust(float $base, DateTimeInterface $from, DateTimeInterface $to = new DateTimeImmutable()):float
{
diff --git a/app/src/Service/Money.php b/app/src/Service/Money.php
index 3405f3a..ab01137 100644
--- a/app/src/Service/Money.php
+++ b/app/src/Service/Money.php
@@ -8,32 +8,29 @@ use Incoviba\Common\Implement\Exception\EmptyResponse;
class Money
{
- const UF = 'uf';
- const USD = 'usd';
- const IPC = 'ipc';
+ const string UF = 'uf';
+ const string USD = 'usd';
+ const string IPC = 'ipc';
public function __construct(protected LoggerInterface $logger) {}
- protected array $providers;
- public function register(string $name, Provider $provider): Money
+ protected array $providers = [];
+ public function register(Provider $provider): Money
{
- if (isset($this->providers) and isset($this->providers[$name]) and in_array($provider, $this->providers[$name])) {
+ if (in_array($provider, $this->providers)) {
return $this;
}
- if (!isset($this->providers[$name])) {
- $this->providers[$name] = [];
- }
- $this->providers[$name] []= $provider;
+ $this->providers []= $provider;
return $this;
}
public function getProviders(string $name): array
{
- return $this->providers[$name];
+ return array_values(array_filter($this->providers, fn($provider) => $provider->supported($name)));
}
- public function get(string $provider, DateTimeInterface $dateTime): float
+ public function get(string $name, DateTimeInterface $dateTime): float
{
- $providers = $this->getProviders($provider);
+ $providers = $this->getProviders($name);
foreach ($providers as $provider) {
try {
return $provider->get(self::getSymbol($provider), $dateTime);
@@ -45,7 +42,7 @@ class Money
}
public function getUF(?DateTimeInterface $dateTime = null): float
{
- $providers = $this->getProviders('uf');
+ $providers = $this->getProviders(self::UF);
foreach ($providers as $provider) {
try {
return $provider->get(self::UF, $dateTime);
@@ -60,10 +57,13 @@ class Money
if ($start >= $end) {
return 0;
}
- $providers = $this->getProviders('ipc');
+ $providers = $this->getProviders(self::IPC);
foreach ($providers as $provider) {
try {
- return $provider->getVar($start, $end);
+ if (method_exists($provider, 'getVar')) {
+ return $provider->getVar($start, $end);
+ }
+ return $provider->get(self::IPC, $end);
} catch (EmptyResponse $exception) {
$this->logger->notice($exception);
}
@@ -72,7 +72,7 @@ class Money
}
public function getUSD(DateTimeInterface $dateTime): float
{
- $providers = $this->getProviders('usd');
+ $providers = $this->getProviders(self::USD);
foreach ($providers as $provider) {
try {
return $provider->get(self::USD, $dateTime);
diff --git a/app/src/Service/Money/Findic.php b/app/src/Service/Money/Findic.php
new file mode 100644
index 0000000..2f5d1e3
--- /dev/null
+++ b/app/src/Service/Money/Findic.php
@@ -0,0 +1,112 @@
+supported($money_symbol)) {
+ throw new EmptyResponse($money_symbol);
+ }
+ if ($dateTime === null) {
+ $dateTime = new DateTimeImmutable();
+ }
+ return match (strtolower($money_symbol)) {
+ Money::UF, Money::USD => $this->getDate(strtolower($money_symbol), $dateTime),
+ Money::IPC => $this->getSum(strtolower($money_symbol), $dateTime,
+ DateTimeImmutable::createFromFormat('Y-m-d',
+ $dateTime->modify('-1 year')->format('Y-11-01'))),
+ default => throw new EmptyResponse($money_symbol),
+ };
+ }
+
+ protected array $supportedMap = [
+ Money::UF => 'uf',
+ Money::IPC => 'ipc',
+ Money::USD => 'dolar'
+ ];
+
+ /**
+ * @param string $request_uri
+ * @return float
+ * @throws EmptyResponse
+ */
+ protected function sendRequest(string $request_uri): array
+ {
+ try {
+ $response = $this->client->get($request_uri);
+ } catch (ClientExceptionInterface $exception) {
+ throw new EmptyResponse($request_uri, $exception);
+ }
+
+ if ((int) floor($response->getStatusCode() / 100) !== 2) {
+ throw new EmptyResponse($request_uri);
+ }
+ $body = $response->getBody();
+ try {
+ $json = json_decode($body->getContents(), true, 512, JSON_THROW_ON_ERROR);
+ } catch (JsonException $exception) {
+ throw new EmptyResponse($request_uri, $exception);
+ }
+
+ if (!array_key_exists('serie', $json) or count($json['serie']) === 0) {
+ throw new EmptyResponse($request_uri);
+ }
+ return $json['serie'];
+ }
+
+ /**
+ * @param string $symbol
+ * @param DateTimeInterface $dateTime
+ * @return float
+ * @throws EmptyResponse
+ */
+ protected function getDate(string $symbol, DateTimeInterface $dateTime): float
+ {
+ $request_uri = "{$this->supportedMap[strtolower($symbol)]}/{$dateTime->format('d-m-Y')}";
+ return (float) $this->sendRequest($request_uri)[0]['valor'];
+ }
+
+ /**
+ * @param string $symbol
+ * @param DateTimeInterface $dateTime
+ * @param DateTimeInterface|null $fromDateTime
+ * @return float
+ * @throws EmptyResponse
+ */
+ protected function getSum(string $symbol, DateTimeInterface $dateTime, ?DateTimeInterface $fromDateTime = null): float
+ {
+ $dateTime = $dateTime->modify('last day of this month');
+ $requestUri = "{$this->supportedMap[strtolower($symbol)]}/{$dateTime->format('Y')}";
+ $serie = $this->sendRequest($requestUri);
+ $values = array_filter($serie, fn($month) => DateTimeImmutable::createFromFormat('Y-m-d', $month['fecha']) <= $dateTime);
+ $value = array_reduce($values, fn($value, $month) => $value + ((float) $month['valor']), 0.0);
+
+ if ($fromDateTime === null) {
+ $fromDateTime = $dateTime->modify('-1 year');
+ } else {
+ $fromDateTime = $fromDateTime->modify('last day of this month');
+ }
+ $requestUri = "{$this->supportedMap[strtolower($symbol)]}/{$fromDateTime->format('Y')}";
+ $serie = $this->sendRequest($requestUri);
+ $values = array_filter($serie, fn($month) => DateTimeImmutable::createFromFormat('Y-m-d', $month['fecha']) > $fromDateTime);
+ return array_reduce($values, fn($value, $month) => $value + ((float) $month['valor']), $value);
+ }
+}
diff --git a/app/src/Service/Money/Ine.php b/app/src/Service/Money/Ine.php
index a4d78cf..8a4c449 100644
--- a/app/src/Service/Money/Ine.php
+++ b/app/src/Service/Money/Ine.php
@@ -6,14 +6,19 @@ use DateTimeInterface;
use DateTimeImmutable;
use DateInterval;
use Psr\Http\Client\ClientInterface;
+use Psr\Log\LoggerInterface;
use GuzzleHttp\Exception\GuzzleException;
use Incoviba\Common\Implement\Exception\EmptyResponse;
-use Incoviba\Common\Define\Money\Provider;
+use Incoviba\Common\Ideal;
+use Incoviba\Service\Money;
-class Ine implements Provider
+class Ine extends Ideal\Money\Provider
{
protected string $uri = 'https://api-calculadora.ine.cl/ServiciosCalculadoraVariacion';
- public function __construct(protected ClientInterface $client) {}
+ public function __construct(LoggerInterface $logger, protected ClientInterface $client)
+ {
+ parent::__construct($logger);
+ }
/**
* @throws EmptyResponse
@@ -21,6 +26,9 @@ class Ine implements Provider
*/
public function get(string $money_symbol, ?DateTimeInterface $dateTime = null): float
{
+ if (!$this->supported($money_symbol)) {
+ throw new EmptyResponse($money_symbol);
+ }
if ($dateTime === null) {
$dateTime = new DateTimeImmutable();
}
@@ -29,6 +37,10 @@ class Ine implements Provider
return $this->getVar($start, $end);
}
+ protected array $supportedMap = [
+ Money::IPC => 'ipc'
+ ];
+
/**
* @throws EmptyResponse
*/
diff --git a/app/src/Service/Money/MiIndicador.php b/app/src/Service/Money/MiIndicador.php
index 302f978..df353b9 100644
--- a/app/src/Service/Money/MiIndicador.php
+++ b/app/src/Service/Money/MiIndicador.php
@@ -3,13 +3,18 @@ namespace Incoviba\Service\Money;
use DateTimeInterface;
use Psr\Http\Client\ClientInterface;
+use Psr\Log\LoggerInterface;
use GuzzleHttp\Exception\GuzzleException;
-use Incoviba\Common\Define\Money\Provider;
+use Incoviba\Common\Ideal;
use Incoviba\Common\Implement\Exception\EmptyResponse;
+use Incoviba\Service\Money;
-class MiIndicador implements Provider
+class MiIndicador extends Ideal\Money\Provider
{
- public function __construct(protected ClientInterface $client) {}
+ public function __construct(LoggerInterface $logger, protected ClientInterface $client)
+ {
+ parent::__construct($logger);
+ }
/**
* @param string $money_symbol
@@ -19,9 +24,12 @@ class MiIndicador implements Provider
*/
public function get(string $money_symbol, ?DateTimeInterface $dateTime = null): float
{
- $request_uri = "{$money_symbol}";
+ if (!$this->supported($money_symbol)) {
+ throw new EmptyResponse($money_symbol);
+ }
+ $request_uri = "{$this->supportedMap[strtolower($money_symbol)]}";
if ($dateTime !== null) {
- $request_uri = "{$money_symbol}/{$dateTime->format('d-m-Y')}";
+ $request_uri = "{$request_uri}/{$dateTime->format('d-m-Y')}";
}
try {
$response = $this->client->get($request_uri);
@@ -41,4 +49,9 @@ class MiIndicador implements Provider
}
return $json->serie[0]->valor;
}
+ protected array $supportedMap = [
+ Money::UF => 'uf',
+ Money::IPC => 'ipc',
+ Money::USD => 'dolar'
+ ];
}
diff --git a/app/src/Service/Money/SII.php b/app/src/Service/Money/SII.php
index 04a0460..29d9fee 100644
--- a/app/src/Service/Money/SII.php
+++ b/app/src/Service/Money/SII.php
@@ -6,27 +6,38 @@ use DateTimeImmutable;
use PDO;
use PDOException;
use Psr\Http\Client\ClientInterface;
+use Psr\Log\LoggerInterface;
use Dom\HTMLDocument;
use GuzzleHttp\Exception\GuzzleException;
use Incoviba\Common\Implement\Exception\EmptyResponse;
-use Incoviba\Common\Define;
+use Incoviba\Common\Ideal;
use Incoviba\Repository;
use Incoviba\Service;
-class SII implements Define\Money\Provider
+class SII extends Ideal\Money\Provider
{
- public function __construct(protected ClientInterface $client,
- protected Repository\UF $ufRepository) {}
+ public function __construct(LoggerInterface $logger, protected ClientInterface $client,
+ protected Repository\UF $ufRepository)
+ {
+ parent::__construct($logger);
+ }
public function get(string $money_symbol, ?DateTimeInterface $dateTime = null): float
{
- if ($money_symbol === Service\Money::UF) {
+ if (!$this->supported($money_symbol)) {
+ throw new EmptyResponse("{$money_symbol} not found in " . __CLASS__);
+ }
+ if (strtolower($money_symbol) === Service\Money::UF) {
return $this->getUF($dateTime);
}
$class = __CLASS__;
throw new EmptyResponse("{$money_symbol} not found in {$class}");
}
+ protected array $supportedMap = [
+ Service\Money::UF => 'uf'
+ ];
+
/**
* @param DateTimeInterface|null $dateTime
* @return float