diff --git a/app/resources/routes/api/contabilidad/daps.php b/app/resources/routes/api/contabilidad/daps.php new file mode 100644 index 0000000..9d929fa --- /dev/null +++ b/app/resources/routes/api/contabilidad/daps.php @@ -0,0 +1,7 @@ +group('/depositos', function($app) { + $app->post('/add[/]', [DAPs::class, 'add']); + $app->get('/inmobiliaria/{inmobiliaria_rut}[/]', [DAPs::class, 'inmobiliaria']); +}); diff --git a/app/resources/routes/contabilidad/daps.php b/app/resources/routes/contabilidad/daps.php new file mode 100644 index 0000000..312c207 --- /dev/null +++ b/app/resources/routes/contabilidad/daps.php @@ -0,0 +1,6 @@ +group('/depositos', function($app) { + $app->get('[/]', [Contabilidad::class, 'depositos']); +}); diff --git a/app/resources/routes/contabilidad/informes.php b/app/resources/routes/contabilidad/informes.php new file mode 100644 index 0000000..66bad08 --- /dev/null +++ b/app/resources/routes/contabilidad/informes.php @@ -0,0 +1,10 @@ +group('/informes', function($app) { + $files = new FilesystemIterator(implode(DIRECTORY_SEPARATOR, [__DIR__, 'informes'])); + foreach ($files as $file) { + if ($file->isDir()) { + continue; + } + include_once $file->getRealPath(); + } +}); diff --git a/app/resources/routes/contabilidad/informes/tesoreria.php b/app/resources/routes/contabilidad/informes/tesoreria.php new file mode 100644 index 0000000..9cbca00 --- /dev/null +++ b/app/resources/routes/contabilidad/informes/tesoreria.php @@ -0,0 +1,6 @@ +group('/tesoreria', function($app) { + $app->get('[/[{fecha}[/]]]', [Contabilidad::class, 'tesoreria']); +}); diff --git a/app/resources/views/contabilidad/depositos.blade.php b/app/resources/views/contabilidad/depositos.blade.php new file mode 100644 index 0000000..d090039 --- /dev/null +++ b/app/resources/views/contabilidad/depositos.blade.php @@ -0,0 +1,235 @@ +@extends('layout.base') + +@section('page_content') +
+

Depósitos a Plazo

+ + + + + + + + + + + + + + + + + + @foreach ($depositos as $deposito) + + + + + + + + + + + + + @endforeach + +
InmobiliariaBancoN° DepósitoCapitalInicioPlazoVencimientoMonto al VencimientoTasa + +
{{$deposito->cuenta->inmobiliaria->razon}}{{$deposito->cuenta->banco->nombre}}{{$deposito->id}}{{$format->pesos($deposito->capital)}}{{$deposito->inicio->format('d-m-Y')}}{{$deposito->plazo()}}{{$deposito->termino->format('d-m-Y')}}{{$format->pesos($deposito->futuro)}}{{$format->percent($deposito->tasa() * 100, 4)}} + +
+
+ +@endsection + +@include('layout.head.styles.datatables') +@include('layout.body.scripts.datatables') + +@push('page_scripts') + +@endpush diff --git a/app/resources/views/contabilidad/informes/tesoreria.blade.php b/app/resources/views/contabilidad/informes/tesoreria.blade.php new file mode 100644 index 0000000..d79bf17 --- /dev/null +++ b/app/resources/views/contabilidad/informes/tesoreria.blade.php @@ -0,0 +1,147 @@ +@extends('layout.base') + +@section('page_content') +
+

Informe de Tesorería

+

{{$fecha->format('d M Y')}}

+
+
+
+ + + + + + + + + +
Informe anterior{{$anterior->format('d/m/Y')}}
Informe actual{{$fecha->format('d/m/Y')}}
+
+
+
+ + + + + + + + + +
Valor UF{{$format->pesos($UF->get($fecha), 2)}}
Valor Dólar{{$format->pesos($USD->get($fecha), 2)}}
+
+
+ + + + + + + + + + + + + + + + + + + + @foreach ($informes['inmobiliarias'] as $inmobiliaria_rut => $informe) + @foreach ($informe->cuentas as $i => $cuenta) + + @if ($i === 0) + + @endif + + + + + + + + + @if ($i === 0) + + + + + @endif + + @endforeach + @endforeach + + + + + + + + + + + + + + + + +
EMPRESABancoCuentaSaldo AnteriorSaldo ActualDiferenciaFFMMDAPSaldo EmpresaTotal CuentasTotal FFMMTotal DAPCaja Total
{{$informe->inmobiliaria->razon}}{{$cuenta->banco}}{{$cuenta->numero}}{{$format->pesos($cuenta->anterior)}}{{$format->pesos($cuenta->actual)}}{{$format->pesos($cuenta->diferencia())}}{{$format->pesos($cuenta->ffmm)}}{{$format->pesos($cuenta->deposito)}}{{$format->pesos($cuenta->saldo())}}{{$format->pesos($informe->total())}}{{$format->pesos($informe->ffmm())}}{{$format->pesos($informe->deposito())}}{{$format->pesos($informe->caja())}}
TOTAL{{$format->pesos($informes['totales']->anterior)}}{{$format->pesos($informes['totales']->actual)}}{{$format->pesos($informes['totales']->diferencia())}}{{$format->pesos($informes['totales']->ffmm)}}{{$format->pesos($informes['totales']->deposito)}}{{$format->pesos($informes['totales']->saldo())}}{{$format->pesos($informes['totales']->cuentas())}}{{$format->pesos($informes['totales']->ffmms())}}{{$format->pesos($informes['totales']->depositos())}}{{$format->pesos($informes['totales']->caja())}}
+ + + + + + + + + + + + + @foreach ($informes['movimientos'] as $tipo => $movimientos) + @if ($tipo === 'capital dap') + @if (count($movimientos['ingresos']) === 0 and count($movimientos['egresos']) === 0) + @continue + @endif + + + + @foreach ($movimientos as $t => $ms) + @foreach ($ms as $movimiento) + + + + + + + + + @endforeach + @endforeach + @continue + @endif + @if (count($movimientos) === 0) + @continue + @endif + + + + @foreach ($movimientos as $movimiento) + + + + + + + + + @endforeach + @endforeach + +
EMPRESAINGRESOSEGRESOSFECHABANCODESCRIPCIÓN
{{strtoupper($tipo)}}
{{$movimiento->cuenta->inmobiliaria->razon}}{{$format->pesos($movimiento->abono)}}{{$format->pesos($movimiento->cargo)}}{{$movimiento->fecha->format('d/m/Y')}}{{$movimiento->cuenta->banco->nombre}}{{$movimiento->glosa}}
{{strtoupper($tipo)}}
{{$movimiento->cuenta->inmobiliaria->razon}}{{$format->pesos($movimiento->abono)}}{{$format->pesos($movimiento->cargo)}}{{$movimiento->fecha->format('d/m/Y')}}{{$movimiento->cuenta->banco->nombre}}{{$movimiento->glosa}}
+@endsection diff --git a/app/resources/views/layout/body/header/menu/contabilidad.blade.php b/app/resources/views/layout/body/header/menu/contabilidad.blade.php index 4962aad..3339500 100644 --- a/app/resources/views/layout/body/header/menu/contabilidad.blade.php +++ b/app/resources/views/layout/body/header/menu/contabilidad.blade.php @@ -2,6 +2,13 @@ Contabilidad + Cartola Diaria + Depósitos a Plazo diff --git a/app/setup/setups/services.php b/app/setup/setups/services.php index d0e986c..146b6f1 100644 --- a/app/setup/setups/services.php +++ b/app/setup/setups/services.php @@ -20,7 +20,9 @@ return [ $ine = new Incoviba\Service\Money\Ine(new GuzzleHttp\Client([ 'base_uri' => 'https://api-calculadora.ine.cl/ServiciosCalculadoraVariacion' ])); - return (new Incoviba\Service\Money())->register('uf', $mindicador) + return (new Incoviba\Service\Money($container->get(Psr\Log\LoggerInterface::class))) + ->register('uf', $mindicador) + ->register('usd', $mindicador) ->register('ipc', $ine); }, Predis\Client::class => function(ContainerInterface $container) { @@ -35,6 +37,7 @@ return [ $container->get(Psr\Log\LoggerInterface::class), $container->get(Psr\Http\Message\StreamFactoryInterface::class), $container->get(Incoviba\Common\Define\Contabilidad\Exporter::class), + $container->get(Incoviba\Repository\Inmobiliaria::class), $container->get(Incoviba\Repository\Inmobiliaria\Cuenta::class), $container->get(Incoviba\Repository\Movimiento::class), $container->get(Incoviba\Repository\Cartola::class) diff --git a/app/setup/setups/views.php b/app/setup/setups/views.php index 0046530..a502dd4 100644 --- a/app/setup/setups/views.php +++ b/app/setup/setups/views.php @@ -11,6 +11,7 @@ return [ 'format' => $container->get(Incoviba\Service\Format::class), 'API_KEY' => $container->get('API_KEY'), 'UF' => $container->get(Incoviba\Service\UF::class), + 'USD' => $container->get(Incoviba\Service\USD::class), 'IPC' => $container->get(Incoviba\Service\IPC::class) ]; if ($global_variables['login']->isIn()) { diff --git a/app/src/Controller/API/Contabilidad/DAPs.php b/app/src/Controller/API/Contabilidad/DAPs.php index d968318..a7d7a5a 100644 --- a/app/src/Controller/API/Contabilidad/DAPs.php +++ b/app/src/Controller/API/Contabilidad/DAPs.php @@ -1,6 +1,7 @@ $inmobiliaria_rut, - 'daps' => [] + 'depositos' => [] ]; try { $inmobiliaria = $inmobiliariaRepository->fetchById($inmobiliaria_rut); $cuentas = $cuentaRepository->fetchByInmobiliaria($inmobiliaria->rut); foreach ($cuentas as $cuenta) { - $daps = $dapRepository->fetchByCuenta($cuenta->id); + $output['depositos'] = $dapRepository->fetchByCuenta($cuenta->id); } } catch (Implement\Exception\EmptyResult) {} return $this->withJson($response, $output); } -} \ No newline at end of file + public function add(ServerRequestInterface $request, ResponseInterface $response, + Repository\Inmobiliaria $inmobiliariaRepository, Repository\Banco $bancoRepository, + Repository\Inmobiliaria\Cuenta $cuentaRepository, + Repository\Deposito $dapRepository): ResponseInterface + { + $body = $request->getParsedBody(); + $output = [ + 'input' => $body, + 'status' => false + ]; + try { + $inmobiliaria = $inmobiliariaRepository->fetchById($body['inmobiliaria_rut']); + $banco = $bancoRepository->fetchById($body['banco_id']); + $cuenta = $cuentaRepository->fetchByInmobiliariaAndBanco($inmobiliaria->rut, $banco->id); + $data = [ + 'id' => $body['id'], + 'cuenta_id' => $cuenta->id, + 'capital' => $body['capital'], + 'futuro' => $body['futuro'], + 'inicio' => (new DateTimeImmutable($body['inicio']))->format('Y-m-d'), + 'termino' => (new DateTimeImmutable($body['termino']))->format('Y-m-d') + ]; + try { + $dapRepository->fetchById($body['id']); + } catch (Implement\Exception\EmptyResult) { + $dap = $dapRepository->create($data); + $dapRepository->save($dap); + } + $output['status'] = true; + } catch (Implement\Exception\EmptyResult) {} + return $this->withJson($response, $output); + } +} diff --git a/app/src/Controller/Contabilidad.php b/app/src/Controller/Contabilidad.php index 8653d8c..c9bc21e 100644 --- a/app/src/Controller/Contabilidad.php +++ b/app/src/Controller/Contabilidad.php @@ -1,6 +1,9 @@ fetchRedis($redisService, $redisKey); } catch (EmptyRedis) { try { - $inmobiliarias = $inmobiliariaRepository->fetchAll(); + $inmobiliarias = $inmobiliariaRepository->fetchAllActive(); $this->saveRedis($redisService, $redisKey, $inmobiliarias, 30 * 24 * 60 * 60); } catch (EmptyResult) {} } return $view->render($response, 'contabilidad.cartolas.diaria', compact('inmobiliarias')); } + public function depositos(ServerRequestInterface $request, ResponseInterface $response, View $view, + Service\Redis $redisService, + Repository\Inmobiliaria $inmobiliariaRepository, + Repository\Deposito $dapRepository): ResponseInterface + { + $redisKey = 'inmobiliarias'; + $inmobiliarias = []; + try { + $inmobiliarias = $this->fetchRedis($redisService, $redisKey); + } catch (EmptyRedis) { + try { + $inmobiliarias = $inmobiliariaRepository->fetchAllActive(); + $this->saveRedis($redisService, $redisKey, $inmobiliarias, 30 * 24 * 60 * 60); + } catch (EmptyResult) {} + } + $depositos = []; + try { + $depositos = $dapRepository->fetchAll(); + } catch (EmptyResult) {} + return $view->render($response, 'contabilidad.depositos', compact('inmobiliarias', 'depositos')); + } + public function tesoreria(ServerRequestInterface $request, ResponseInterface $response, View $view, + Service\Contabilidad\Informe\Tesoreria $contabilidadService, + string $fecha = 'today'): ResponseInterface + { + $fecha = new DateTimeImmutable($fecha); + $anterior = $contabilidadService->getAnterior($fecha); + $informes = $contabilidadService->build($fecha); + return $view->render($response, 'contabilidad.informes.tesoreria', compact('fecha', 'anterior', 'informes')); + } } diff --git a/app/src/Model/DAP.php b/app/src/Model/Deposito.php similarity index 77% rename from app/src/Model/DAP.php rename to app/src/Model/Deposito.php index 5e440d4..da32727 100644 --- a/app/src/Model/DAP.php +++ b/app/src/Model/Deposito.php @@ -4,7 +4,7 @@ namespace Incoviba\Model; use DateTimeInterface; use Incoviba\Common\Ideal; -class DAP extends Ideal\Model +class Deposito extends Ideal\Model { public Inmobiliaria\Cuenta $cuenta; public int $capital; @@ -12,13 +12,13 @@ class DAP extends Ideal\Model public DateTimeInterface $inicio; public DateTimeInterface $termino; - public function periodo(): int + public function plazo(): int { return $this->termino->diff($this->inicio)->days; } - public function interes(): float + public function tasa(): float { - return ($this->futuro - $this->capital) / $this->capital / $this->periodo() * 365; + return ($this->futuro - $this->capital) / $this->capital; } public function jsonSerialize(): mixed @@ -29,8 +29,8 @@ class DAP extends Ideal\Model 'futuro' => $this->futuro, 'inicio' => $this->inicio->format('Y-m-d'), 'termino' => $this->termino->format('Y-m-d'), - 'periodo' => $this->periodo(), - 'interes' => $this->interes() + 'plazo' => $this->plazo(), + 'tasa' => $this->tasa() ]); } -} \ No newline at end of file +} diff --git a/app/src/Repository/Cartola.php b/app/src/Repository/Cartola.php index be03b12..23e9cc1 100644 --- a/app/src/Repository/Cartola.php +++ b/app/src/Repository/Cartola.php @@ -49,6 +49,14 @@ class Cartola extends Ideal\Repository return $this->update($model, ['cuenta_id', 'fecha', 'cargos', 'abonos', 'saldo'], $new_data); } + public function fetchByFecha(DateTimeInterface $fecha): array + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('fecha = ?'); + return $this->fetchMany($query, [$fecha->format('Y-m-d')]); + } public function fetchByCuentaAndFecha(int $cuenta_id, DateTimeInterface $fecha): Model\Cartola { $query = $this->connection->getQueryBuilder() diff --git a/app/src/Repository/DAP.php b/app/src/Repository/Deposito.php similarity index 73% rename from app/src/Repository/DAP.php rename to app/src/Repository/Deposito.php index 8baaf0a..c47dd87 100644 --- a/app/src/Repository/DAP.php +++ b/app/src/Repository/Deposito.php @@ -7,7 +7,7 @@ use Incoviba\Common\Implement; use Incoviba\Repository; use Incoviba\Model; -class DAP extends Ideal\Repository +class Deposito extends Ideal\Repository { public function __construct(Define\Connection $connection, protected Repository\Inmobiliaria\Cuenta $cuentaRepository) { @@ -15,9 +15,9 @@ class DAP extends Ideal\Repository $this->setTable('depositos'); } - public function create(?array $data = null): Model\DAP + public function create(?array $data = null): Model\Deposito { - $map = (new Implement\Repository\MapperParser(['capital', 'futuro'])) + $map = (new Implement\Repository\MapperParser(['id', 'capital', 'futuro'])) ->register('cuenta_id', (new Implement\Repository\Mapper()) ->setProperty('cuenta') ->setFunction(function(array $data) { @@ -25,20 +25,20 @@ class DAP extends Ideal\Repository })) ->register('inicio', new Implement\Repository\Mapper\DateTime('inicio')) ->register('termino', new Implement\Repository\Mapper\DateTime('termino')); - return $this->parseData(new Model\DAP(), $data, $map); + return $this->parseData(new Model\Deposito(), $data, $map); } - public function save(Define\Model $model): Model\DAP + public function save(Define\Model $model): Model\Deposito { - $model->id = $this->saveNew([ - 'cuenta_id', 'capital', 'futuro', 'inicio', 'termino' + $this->saveNew([ + 'id', 'cuenta_id', 'capital', 'futuro', 'inicio', 'termino' ], [ - $model->cuenta->id, $model->capital, $model->futuro, + $model->id, $model->cuenta->id, $model->capital, $model->futuro, $model->inicio->format('Y-m-d'), $model->termino->format('Y-m-d') ]); return $model; } - public function edit(Define\Model $model, array $new_data): Model\DAP + public function edit(Define\Model $model, array $new_data): Model\Deposito { return $this->update($model, ['cuenta_id', 'capital', 'futuro', 'inicio', 'termino'], $new_data); } @@ -51,4 +51,4 @@ class DAP extends Ideal\Repository ->where('cuenta_id = ?'); return $this->fetchMany($query, [$cuenta_id]); } -} \ No newline at end of file +} diff --git a/app/src/Repository/Movimiento.php b/app/src/Repository/Movimiento.php index 8e11f06..f74704e 100644 --- a/app/src/Repository/Movimiento.php +++ b/app/src/Repository/Movimiento.php @@ -53,6 +53,14 @@ class Movimiento extends Ideal\Repository return $this->update($model, ['cuenta_id', 'fecha', 'glosa', 'documento', 'cargo', 'abono', 'saldo'], $new_data); } + public function fetchByCuentaAndFecha(int $cuenta_id, DateTimeInterface $fecha): array + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('cuenta_id = ? AND fecha = ?'); + return $this->fetchMany($query, [$cuenta_id, $fecha->format('Y-m-d')]); + } public function fetchByCuentaAndFechaAndMonto(int $cuenta_id, DateTimeInterface $fecha, int $monto): Model\Movimiento { $query = $this->connection->getQueryBuilder() diff --git a/app/src/Service/Cartola.php b/app/src/Service/Cartola.php index ae7f927..835abfa 100644 --- a/app/src/Service/Cartola.php +++ b/app/src/Service/Cartola.php @@ -3,6 +3,7 @@ namespace Incoviba\Service; use DateTimeInterface; use DateTimeImmutable; +use DateInterval; use Psr\Http\Message\StreamFactoryInterface; use Psr\Http\Message\UploadedFileInterface; use Psr\Log\LoggerInterface; @@ -17,6 +18,7 @@ class Cartola extends Service { public function __construct(LoggerInterface $logger, protected StreamFactoryInterface $streamFactory, protected Exporter $exporter, + protected Repository\Inmobiliaria $inmobiliariaRepository, protected Repository\Inmobiliaria\Cuenta $cuentaRepository, protected Repository\Movimiento $movimientoRepository, protected Repository\Cartola $cartolaRepository) { diff --git a/app/src/Service/Contabilidad.php b/app/src/Service/Contabilidad.php new file mode 100644 index 0000000..a5e87fd --- /dev/null +++ b/app/src/Service/Contabilidad.php @@ -0,0 +1,20 @@ +tesoreriaService->build($fecha); + } +} diff --git a/app/src/Service/Contabilidad/Informe/Tesoreria.php b/app/src/Service/Contabilidad/Informe/Tesoreria.php new file mode 100644 index 0000000..a8f9114 --- /dev/null +++ b/app/src/Service/Contabilidad/Informe/Tesoreria.php @@ -0,0 +1,277 @@ +movimientos = new class() { + public function __construct() + { + $this->dap = new class() + { + public array $ingresos = []; + public array $egresos = []; + }; + } + public object $dap; + public array $ingresos = []; + public array $egresos = []; + + const INGRESOS = 'ingresos'; + const EGRESOS = 'egresos'; + public function addDap(string $tipo, array $movimientos) + { + foreach ($movimientos as $movimiento) { + $this->dap->{$tipo} []= $movimiento; + } + return $this; + } + public function build(): array + { + return [ + 'capital dap' => [ + 'ingresos' => $this->dap->ingresos, + 'egresos' => $this->dap->egresos + ], + 'ingresos' => $this->ingresos, + 'egresos' => $this->egresos + ]; + } + }; + $this->totales = new class() { + public int $anterior = 0; + public int $actual = 0; + public int $ffmm = 0; + public int $deposito = 0; + + public function diferencia(): int + { + return $this->actual - $this->anterior; + } + public function saldo(): int + { + return $this->diferencia() + $this->ffmm + $this->deposito; + } + public function cuentas(): int + { + return $this->actual; + } + public function ffmms(): int + { + return $this->ffmm; + } + public function depositos(): int + { + return $this->deposito; + } + public function caja(): int + { + return $this->cuentas() + $this->ffmms() + $this->depositos(); + } + }; + } + + const DAP_INGRESOS = 'dap->ingresos'; + const DAP_EGRESOS = 'dap->egresos'; + const INGRESOS = 'ingresos'; + const EGRESOS = 'egresos'; + const TOTAL_ANTERIOR = 'anterior'; + const TOTAL_ACTUAL = 'actual'; + const TOTAL_FFMM = 'ffmm'; + const TOTAL_DAP = 'deposito'; + + protected DateTimeInterface $anterior; + protected object $totales; + protected object $movimientos; + + public function getAnterior(DateTimeInterface $fecha): DateTimeInterface + { + if (!isset($this->anterior)) { + $this->anterior = $fecha->sub(new DateInterval('P1D')); + if ($this->anterior->format('N') === '7') { + $this->anterior = $fecha->sub(new DateInterval('P3D')); + } + } + return $this->anterior; + } + public function build(DateTimeInterface $fecha): array + { + try { + $inmobiliarias = $this->inmobiliariaRepository->fetchAllActive(); + } catch (Implement\Exception\EmptyResult) { + return []; + } + $informe = ['inmobiliarias' => []]; + foreach ($inmobiliarias as $inmobiliaria) { + $informe['inmobiliarias'][$inmobiliaria->rut] = $this->buildInmobiliaria($inmobiliaria, $fecha); + } + $informe['movimientos'] = $this->buildMovimientos(); + $informe['totales'] = $this->buildTotales(); + return $informe; + } + + protected function buildInmobiliaria(Model\Inmobiliaria $inmobiliaria, DateTimeInterface $fecha): object + { + $dataInmobiliaria = new class() { + public Model\Inmobiliaria $inmobiliaria; + public array $cuentas = []; + public function total(): int + { + return array_reduce($this->cuentas, function(int $sum, $cuenta) { + return $sum + $cuenta->actual; + }, 0); + } + public function ffmm(): int + { + return array_reduce($this->cuentas, function(int $sum, $cuenta) { + return $sum + $cuenta->ffmm; + }, 0); + } + public function deposito(): int + { + return array_reduce($this->cuentas, function(int $sum, $cuenta) { + return $sum + $cuenta->deposito; + }, 0); + } + public function caja(): int + { + return array_reduce($this->cuentas, function(int $sum, $cuenta) { + return $sum + $cuenta->saldo(); + }, 0); + } + }; + $dataInmobiliaria->inmobiliaria = $inmobiliaria; + try { + $cuentas = $this->cuentaRepository->fetchByInmobiliaria($inmobiliaria->rut); + } catch (Implement\Exception\EmptyResult) { + return $dataInmobiliaria; + } + foreach ($cuentas as $cuenta) { + $data = new class() { + public string $banco; + public string $numero; + public int $anterior = 0; + public int $actual = 0; + public int $ffmm = 0; + public int $deposito = 0; + + public function diferencia(): int + { + return $this->actual - $this->anterior; + } + public function saldo(): int + { + return $this->diferencia() + $this->ffmm + $this->deposito; + } + }; + $data->banco = $cuenta->banco->nombre; + $data->numero = $cuenta->cuenta; + try { + $depositos = $this->depositoRepository->fetchByCuenta($cuenta->id); + foreach ($depositos as $deposito) { + $data->deposito += $deposito->capital; + $this->addTotal(self::TOTAL_DAP, $deposito->capital); + + if ($deposito->inicio === $fecha) { + $this->addMovimientos(self::DAP_EGRESOS, [(object) [ + 'cuenta' => $deposito->cuenta, + 'fecha' => $deposito->inicio, + 'cargo' => - $deposito->capital, + 'abono' => 0, + 'saldo' => - $deposito->capital, + 'glosa' => 'INVERSION DAP' + ]]); + } + if ($deposito->termino === $fecha) { + $data->deposito -= $deposito->capital; + $this->addTotal(self::TOTAL_DAP, -$deposito->capital); + + $this->addMovimientos(self::DAP_INGRESOS, [(object) [ + 'cuenta' => $deposito->cuenta, + 'fecha' => $deposito->termino, + 'cargo' => 0, + 'abono' => $deposito->futuro, + 'saldo' => $deposito->futuro, + 'glosa' => 'RESCATE DAP' + ]]); + } + } + } catch (Implement\Exception\EmptyResult) {} + try { + $cartola = $this->cartolaRepository->fetchByCuentaAndFecha($cuenta->id, $fecha); + $data->actual = $cartola->saldo; + } catch (Implement\Exception\EmptyResult) {} + try { + $cartola = $this->cartolaRepository->fetchByCuentaAndFecha($cuenta->id, $this->getAnterior($fecha)); + $data->anterior = $cartola->saldo; + } catch (Implement\Exception\EmptyResult) {} + if ($data->diferencia() !== 0) { + try { + $movimientos = $this->movimientoRepository->fetchByCuentaAndFecha($cuenta->id, $fecha); + $this->addMovimientos(self::INGRESOS, + array_filter($movimientos, function(Model\Movimiento $movimiento) { + return $movimiento->abono > 0; + })); + $this->addMovimientos(self::EGRESOS, + array_filter($movimientos, function(Model\Movimiento $movimiento) { + return $movimiento->cargo > 0; + })); + } catch (Implement\Exception\EmptyResult) {} + } + $dataInmobiliaria->cuentas []= $data; + + $this->addTotal( + [self::TOTAL_ANTERIOR, self::TOTAL_ACTUAL], + [$data->anterior, $data->actual] + ); + } + return $dataInmobiliaria; + } + protected function buildMovimientos(): array + { + return $this->movimientos->build(); + } + protected function buildTotales(): object + { + return $this->totales; + } + protected function addMovimientos(string $tipo, array $movimientos): Tesoreria + { + if (str_contains($tipo, 'dap')) { + list($d, $t) = explode('->', $tipo); + $this->movimientos->addDap($t, $movimientos); + return $this; + } + foreach ($movimientos as $movimiento) { + $this->movimientos->{$tipo} []= $movimiento; + } + return $this; + } + protected function addTotal(string|array $tipo, int|array $total): Tesoreria + { + if (is_array($tipo)) { + foreach ($tipo as $i => $t) { + $this->addTotal($t, $total[$i]); + } + return $this; + } + $this->totales->{$tipo} += $total; + return $this; + } +} diff --git a/app/src/Service/Contabilidad/Nubox.php b/app/src/Service/Contabilidad/Nubox.php index 01b432a..2d880cf 100644 --- a/app/src/Service/Contabilidad/Nubox.php +++ b/app/src/Service/Contabilidad/Nubox.php @@ -4,20 +4,25 @@ namespace Incoviba\Service\Contabilidad; use DateTimeInterface; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamInterface; +use Psr\Log\LoggerInterface; use Incoviba\Common\Implement\Exception; use Incoviba\Repository; use Incoviba\Service; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; -use function Symfony\Component\Translation\t; +use Incoviba\Common\Ideal; -class Nubox +class Nubox extends Ideal\Service { - public function __construct(protected Repository\Nubox $nuboxRepository, + public function __construct(protected LoggerInterface $logger, + protected Repository\Nubox $nuboxRepository, protected Service\Redis $redisService, protected ClientInterface $client, protected RequestFactoryInterface $requestFactory, - protected string $api_url) {} + protected string $api_url) + { + parent::__construct($logger); + } protected array $tokens; public function getToken(int $inmobiliaria_rut): string @@ -120,7 +125,7 @@ class Nubox $uri = 'contabilidad/libro-diario?' . http_build_query($query); $response = $this->send($uri, $inmobiliaria_rut); if ($response->getStatusCode() !== 200) { - error_log(var_export($uri,true).PHP_EOL,3,'/logs/debug'); + $this->logger->debug($uri); throw new Exception\HttpResponse($response->getReasonPhrase(), $response->getStatusCode()); } return json_decode($response->getBody()->getContents(), JSON_OBJECT_AS_ARRAY); diff --git a/app/src/Service/Format.php b/app/src/Service/Format.php index 21546e0..69bde98 100644 --- a/app/src/Service/Format.php +++ b/app/src/Service/Format.php @@ -25,12 +25,12 @@ class Format { return "{$this->number($number, $decimal_places)}%"; } - public function pesos(string $valor): string + public function pesos(string $valor, int $decimal_places = 0): string { - return "$ {$this->number($valor)}"; + return "$ {$this->number($valor, $decimal_places)}"; } - public function ufs(string $valor): string + public function ufs(string $valor, int $decimal_places = 2): string { - return "{$this->number($valor, 2)} UF"; + return "{$this->number($valor, $decimal_places)} UF"; } } diff --git a/app/src/Service/Money.php b/app/src/Service/Money.php index c9a7b8c..5a9dddf 100644 --- a/app/src/Service/Money.php +++ b/app/src/Service/Money.php @@ -7,9 +7,12 @@ use DateInterval; use Incoviba\Common\Define\Money\Provider; use Incoviba\Common\Implement\Exception\EmptyResponse; use Incoviba\Service\Money\MiIndicador; +use Psr\Log\LoggerInterface; class Money { + public function __construct(protected LoggerInterface $logger) {} + protected array $providers; public function register(string $name, Provider $provider): Money { @@ -49,4 +52,13 @@ class Money return 0; } } + public function getUSD(DateTimeInterface $dateTime): float + { + try { + return $this->getProvider('usd')->get(MiIndicador::USD, $dateTime); + } catch (EmptyResponse $exception) { + $this->logger->critical($exception); + return 0; + } + } } diff --git a/app/src/Service/Money/MiIndicador.php b/app/src/Service/Money/MiIndicador.php index a223250..21dba16 100644 --- a/app/src/Service/Money/MiIndicador.php +++ b/app/src/Service/Money/MiIndicador.php @@ -11,7 +11,7 @@ class MiIndicador implements Provider { const UF = 'uf'; const IPC = 'ipc'; - const USD = 'dolar_intercambio'; + const USD = 'dolar'; public function __construct(protected ClientInterface $client) {} diff --git a/app/src/Service/USD.php b/app/src/Service/USD.php new file mode 100644 index 0000000..edfeed5 --- /dev/null +++ b/app/src/Service/USD.php @@ -0,0 +1,34 @@ +redisService->get($this->redisKey), JSON_OBJECT_AS_ARRAY); + if (!isset($usds[$date->format('Y-m-d')])) { + throw new EmptyRedis($this->redisKey); + } + $usd = $usds[$date->format('Y-m-d')]; + } catch (EmptyRedis) { + $usd = $this->moneyService->getUSD($date); + $usds[$date->format('Y-m-d')] = $usd; + ksort($usds); + $this->redisService->set($this->redisKey, json_encode($usds), 60 * 60 * 24 * 30); + } + return $usd; + } +}