Subir cartolas procesadas

This commit is contained in:
Juan Pablo Vial
2024-07-17 22:33:33 -04:00
parent 390e79ad6d
commit 8e7f43e487
48 changed files with 1692 additions and 530 deletions

View File

@ -5,10 +5,14 @@ use DateTimeImmutable;
use Incoviba\Common\Ideal\Controller;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Model\Contabilidad\Banco;
use Incoviba\Model\Inmobiliaria;
use Incoviba\Repository;
use Incoviba\Service;
use PhpParser\Node\Stmt\TryCatch;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerInterface;
class Cartolas extends Controller
{
@ -95,4 +99,60 @@ class Cartolas extends Controller
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function importar(ServerRequestInterface $request, ResponseInterface $response,
LoggerInterface $logger,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Contabilidad\Banco $bancoRepository,
Repository\Inmobiliaria\Cuenta $cuentaRepository,
Service\Contabilidad\Cartola $cartolaService,
Service\Contabilidad\Movimiento $movimientoService): ResponseInterface
{
$body = $request->getParsedBody();
$files = $request->getUploadedFiles();
$output = [
'input' => $body,
'movimientos' => []
];
if (is_array($files['file'])) {
foreach ($files['file'] as $i => $file) {
if ($file->getError() !== UPLOAD_ERR_OK) {
continue;
}
try {
$inmobiliaria = $inmobiliariaRepository->fetchById($body['sociedad_rut'][$i]);
$banco = $bancoRepository->fetchById($body['banco_id'][$i]);
$movimientos = $cartolaService->process($inmobiliaria, $banco, new DateTimeImmutable($body['mes'][$i]), $file);
$cuenta = $cuentaRepository->fetchByInmobiliariaAndBanco($inmobiliaria->rut, $banco->id);
$this->addMovimientos($movimientoService, $cuenta, $movimientos);
$output['movimientos'] = array_merge($output['movimientos'], $movimientos);
} catch (EmptyResult) {}
}
} else {
try {
$inmobiliaria = $inmobiliariaRepository->fetchById($body['sociedad_rut']);
$banco = $bancoRepository->fetchById($body['banco_id']);
$movimientos = $cartolaService->process($inmobiliaria, $banco, new DateTimeImmutable($body['mes']), $files['file']);
$cuenta = $cuentaRepository->fetchByInmobiliariaAndBanco($inmobiliaria->rut, $banco->id);
$this->addMovimientos($movimientoService, $cuenta, $movimientos);
$output['movimientos'] = $movimientos;
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
protected function addMovimientos(Service\Contabilidad\Movimiento $movimientoService, Inmobiliaria\Cuenta $cuenta, array $movimientos): void
{
foreach ($movimientos as $dataMovimiento) {
$dataMovimiento['cuenta_id'] = $cuenta->id;
$dataMovimiento['centro_costo_id'] = $dataMovimiento['centro_costo'];
$dataMovimiento['fecha'] = new DateTimeImmutable($dataMovimiento['fecha']);
if (array_key_exists('rut', $dataMovimiento)) {
list($rut, $digito) = explode('-', $dataMovimiento['rut']);
$dataMovimiento['rut'] = preg_replace('/\D+/', '', $rut);
$dataMovimiento['digito'] = $digito;
}
$movimientoService->add($dataMovimiento);
}
}
}

View File

@ -23,29 +23,30 @@ class Movimientos extends Ideal\Controller
'movimiento_id' => $movimiento_id,
'input' => $body,
'status' => false,
'movimiento' => null,
'centro' => null,
'detalle' => ''
'movimiento' => null
];
try {
$movimiento = $movimientoService->getById($movimiento_id);
$output['movimiento'] = $this->movimientosToArray([$movimiento])[0];
$data = [];
if (isset($body['centro_id'])) {
$centro = $centroCostoRepository->fetchById($body['centro_id']);
$data['centro_costo_id'] = $centro->id;
}
if (isset($body['detalle'])) {
$data['detalle'] = $body['detalle'];
$fieldMap = [
'centro_costo_id',
'categoria',
'detalle',
'rut',
'digito',
'nombres',
'identificador'
];
foreach ($fieldMap as $field) {
if (key_exists($field, $body)) {
$data[$field] = $body[$field];
}
}
$movimientoService->setDetalles($movimiento, $data);
$output['movimiento'] = $this->movimientosToArray([$movimientoService->getById($movimiento->id)])[0];
if (isset($body['centro_id'])) {
$output['centro'] = $centro;
}
if (isset($body['detalle'])) {
$output['detalle'] = $body['detalle'];
}
$output['status'] = true;
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}

View File

@ -0,0 +1,29 @@
<?php
namespace Incoviba\Controller\API\Contabilidad;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerInterface;
use Incoviba\Controller\API\withJson;
use Incoviba\Service;
class Tesoreria
{
use withJson;
public function import(ServerRequestInterface $request, ResponseInterface $response, LoggerInterface $logger,
Service\Contabilidad\Informe\Tesoreria $tesoreriaService): ResponseInterface
{
$files = $request->getUploadedFiles();
$output = [];
foreach ($files['file'] as $file) {
if ($file->getError() !== UPLOAD_ERR_OK) {
continue;
}
$data = $tesoreriaService->getInput()->loadFromExcel($file);
$tesoreriaService->getInput()->load($data);
$output['informes'] []= $data;
}
return $this->withJson($response, $output);
}
}

View File

@ -34,6 +34,20 @@ class Contabilidad extends Controller
$centrosCostos = $centroCostoRepository->fetchAll();
return $view->render($response, 'contabilidad.cartolas.diaria', compact('inmobiliarias', 'centrosCostos'));
}
public function importar(ServerRequestInterface $request, ResponseInterface $response, View $view,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Contabilidad\Banco $bancoRepository): ResponseInterface
{
$inmobiliarias = [];
try {
$inmobiliarias = $inmobiliariaRepository->fetchAll('razon');
} catch (EmptyResult) {}
$bancos = [];
try {
$bancos = $bancoRepository->fetchAll('nombre');
} catch (EmptyResult) {}
return $view->render($response, 'contabilidad.cartolas.import', compact('inmobiliarias', 'bancos'));
}
public function depositos(ServerRequestInterface $request, ResponseInterface $response, View $view,
Service\Redis $redisService,
Repository\Inmobiliaria $inmobiliariaRepository,
@ -68,7 +82,7 @@ class Contabilidad extends Controller
string $fecha = 'today'): ResponseInterface
{
$fecha = new DateTimeImmutable($fecha);
$anterior = $contabilidadService->getAnterior($fecha);
$anterior = $contabilidadService->getOutput()->getAnterior($fecha);
$yesterday = new DateTimeImmutable('yesterday');
$siguiente = null;
if ($yesterday > $fecha) {
@ -77,16 +91,16 @@ class Contabilidad extends Controller
$siguiente = $fecha->add(new DateInterval('P3D'));
}
}
$informes = $contabilidadService->build($fecha);
$informes = $contabilidadService->getOutput()->build($fecha);
$filename = "Informe de Tesorería {$fecha->format('d.m.Y')}";
return $view->render($response, 'contabilidad.informes.tesoreria', compact('fecha', 'anterior', 'siguiente', 'informes', 'filename'));
}
public function semanal(ServerRequestInterface $request, ResponseInterface $response, View $view,
/*public function semanal(ServerRequestInterface $request, ResponseInterface $response, View $view,
Service\Contabilidad\Informe\Semanal $semanalService,
string $fecha = 'today'): ResponseInterface
{
}
}*/
public function cuadratura(ServerRequestInterface $request, ResponseInterface $response, View $view,
Repository\Inmobiliaria $inmobiliariaRepository): ResponseInterface
{

View File

@ -13,7 +13,7 @@ class Informes extends Ideal\Controller
{
$fecha = new DateTimeImmutable($fecha);
$tesoreriaService->buildInforme($fecha, $tesoreriaService->build($fecha));
$tesoreriaService->getOutput()->buildInforme($fecha, $tesoreriaService->getOutput()->build($fecha));
$response->getBody()->write(file_get_contents('php://output'));
return $response;
}

View File

@ -0,0 +1,14 @@
<?php
namespace Incoviba\Controller\Contabilidad;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Alias\View;
class Tesoreria
{
public function import(ServerRequestInterface $request, ResponseInterface $response, View $view): ResponseInterface
{
return $view->render($response, 'contabilidad.tesoreria.import');
}
}

View File

@ -26,14 +26,14 @@ class Movimiento extends Ideal\Model
return $this->detalles;
}
protected ?array $auxiliares;
/*protected ?array $auxiliares;
public function getAuxiliares(): ?array
{
if (!isset($this->auxiliares)) {
$this->auxiliares = $this->runFactory('auxiliares');
}
return $this->auxiliares;
}
}*/
public function jsonSerialize(): mixed
{
@ -46,7 +46,7 @@ class Movimiento extends Ideal\Model
'abono' => $this->abono,
'saldo' => $this->saldo,
'detalles' => $this->getDetalles(),
'auxiliares' => $this->getAuxiliares()
//'auxiliares' => $this->getAuxiliares()
]);
}
}

View File

@ -10,9 +10,10 @@ class Detalle extends Ideal\Model
public ?Model\Contabilidad\CentroCosto $centroCosto;
public ?int $rut;
public ?string $digito;
public ?string $nombre;
public ?string $nombres;
public ?string $categoria;
public ?string $detalle;
public ?string $identificador;
public function rut(): string
{
@ -30,9 +31,10 @@ class Detalle extends Ideal\Model
'centro_costo' => $this->centroCosto,
'rut' => $this->rut,
'digito' => $this->digito,
'nombre' => $this->nombre,
'nombres' => $this->nombres,
'categoria' => $this->categoria,
'detalle' => $this->detalle,
'identificador' => $this->identificador,
'rutFormatted' => $this->rutFormatted()
];
}

View File

@ -31,4 +31,13 @@ class Banco extends Ideal\Repository
{
return $this->update($model, ['nombre'], $new_data);
}
public function fetchByNombre(string $nombre): Model\Contabilidad\Banco
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('nombre = :nombre');
return $this->fetchOne($query, ['nombre' => $nombre]);
}
}

View File

@ -62,13 +62,13 @@ class Movimiento extends Ideal\Repository
->where('cuenta_id = ? AND fecha = ?');
return $this->fetchMany($query, [$cuenta_id, $fecha->format('Y-m-d')]);
}
public function fetchByCuentaAndFechaAndCargoAndAbonoAndSaldo(int $cuenta_id, DateTimeInterface $fecha, int $cargo, int $abono, int $saldo): Model\Contabilidad\Movimiento
public function fetchByCuentaAndFechaAndGlosaAndCargoAndAbonoAndSaldo(int $cuenta_id, DateTimeInterface $fecha, string $glosa, int $cargo, int $abono, int $saldo): Model\Contabilidad\Movimiento
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('cuenta_id = ? AND fecha = ? AND cargo = ? AND abono = ? AND saldo = ?');
return $this->fetchOne($query, [$cuenta_id, $fecha->format('Y-m-d'), $cargo, $abono, $saldo]);
->where('cuenta_id = ? AND fecha = ? AND glosa = ? AND cargo = ? AND abono = ? AND saldo = ?');
return $this->fetchOne($query, [$cuenta_id, $fecha->format('Y-m-d'), $glosa, $cargo, $abono, $saldo]);
}
public function fetchAmountStartingFrom(int $start, int $amount): array
{

View File

@ -19,7 +19,7 @@ class Detalle extends Ideal\Repository
public function create(?array $data = null): Model\Contabilidad\Movimiento\Detalle
{
$map = (new Implement\Repository\MapperParser(['detalle']))
$map = (new Implement\Repository\MapperParser(['rut', 'digito', 'nombres', 'categoria', 'detalle', 'identificador']))
->register('movimiento_id', (new Implement\Repository\Mapper())
->setProperty('movimiento')
->setFunction(function(array $data) {
@ -29,20 +29,21 @@ class Detalle extends Ideal\Repository
->setProperty('centroCosto')
->setFunction(function(array $data) {
return $this->centroCostoRepository->fetchById($data['centro_costo_id']);
}));
})
->setDefault(null));
return $this->parseData(new Model\Contabilidad\Movimiento\Detalle(), $data, $map);
}
public function save(Define\Model $model): Model\Contabilidad\Movimiento\Detalle
{
$this->saveNew(
['movimiento_id', 'centro_costo_id', 'detalle'],
[$model->movimiento->id, $model->centroCosto->id, $model->detalles]
['movimiento_id', 'centro_costo_id', 'rut', 'digito', 'nombres', 'categoria', 'detalle', 'identificador'],
[$model->movimiento->id, $model->centroCosto?->id, $model->rut, $model->digito, $model->nombres, $model->categoria, $model->detalle, $model->identificador]
);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\Contabilidad\Movimiento\Detalle
{
return $this->update($model, ['movimiento_id', 'centro_costo_id', 'detalle'], $new_data);
return $this->update($model, ['movimiento_id', 'centro_costo_id', 'rut', 'digito', 'nombres', 'categoria', 'detalle', 'identificador'], $new_data);
}
public function fetchByMovimiento(int $movimiento_id): Model\Contabilidad\Movimiento\Detalle

View File

@ -15,6 +15,6 @@ class Contabilidad extends Ideal\Controller
public function tesoreria(DateTimeInterface $fecha): array
{
return $this->tesoreriaService->build($fecha);
return $this->tesoreriaService->getOutput()->build($fecha);
}
}

View File

@ -121,9 +121,10 @@ class Cartola extends Service
{
try {
return $this->movimientoRepository
->fetchByCuentaAndFechaAndCargoAndAbonoAndSaldo(
->fetchByCuentaAndFechaAndGlosaAndCargoAndAbonoAndSaldo(
$cuenta->id,
new DateTimeImmutable($data['fecha']),
$data['glosa'],
$data['cargo'] ?? 0,
$data['abono'] ?? 0,
$data['saldo']

View File

@ -14,7 +14,13 @@ class BCI extends Banco
'Cargo $ (-)' => 'cargo',
'Abono $ (+)' => 'abono',
'Descripción' => 'glosa',
'Saldo' => 'saldo'
'Saldo' => 'saldo',
'Categoría' => 'categoria',
'Centro costos' => 'centro_costo',
'Detalle' => 'detalle',
'Factura Boleta' => 'identificador',
'RUT' => 'rut',
'Nombres' => 'nombres',
];
}
protected function getFilename(UploadedFileInterface $uploadedFile): string

View File

@ -26,7 +26,14 @@ class Itau extends Banco
'Giros o cargos' => 'cargo',
'Documentos' => 'documento',
'Movimientos' => 'glosa',
'Saldos' => 'saldo'
'Saldos' => 'saldo',
'Categoría' => 'categoria',
'Centro costo' => 'centro_costo',
'Detalle' => 'detalle',
'Factura Boleta' => 'identificador',
'RUT' => 'rut',
'Nombres' => 'nombres',
'Depto' => 'identificador',
];
}
protected function getFilename(UploadedFileInterface $uploadedFile): string

View File

@ -20,7 +20,13 @@ class Santander extends Banco
'Cargo ($)' => 'cargo',
'Abono ($)' => 'abono',
'Descripcin' => 'glosa',
'Saldo Diario' => 'saldo'
'Saldo Diario' => 'saldo',
'Categoría' => 'categoria',
'Centro costos' => 'centro_costo',
'Detalle' => 'detalle',
'Factura Boleta' => 'identificador',
'RUT' => 'rut',
'Nombres' => 'nombres',
];
}
protected function getFilename(UploadedFileInterface $uploadedFile): string

View File

@ -41,7 +41,14 @@ class Security extends Banco
'nº documento' => 'documento',
'cargos' => 'cargo',
'abonos' => 'abono',
'saldos' => 'saldo'
'saldos' => 'saldo',
'categoría' => 'categoria',
'centro costos' => 'centro_costo',
'detalle' => 'detalle',
'factura boleta' => 'identificador',
'rut' => 'rut',
'nombres' => 'nombres',
'depto' => 'identificador',
];
}

View File

@ -1,378 +1,23 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe;
use DateInterval;
use DateTimeInterface;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
use Psr\Log\LoggerInterface;
class Tesoreria extends Ideal\Service
{
protected const ORDEN_SOCIEDADES = [
99543380,
78017310,
76837020,
76743916,
76519798,
76309587,
77023196,
77023201,
76309592,
76163347,
76158424
];
public function __construct(LoggerInterface $logger,
protected Repository\Inmobiliaria $inmobiliariaRepository,
protected Service\Inmobiliaria\Cuenta $cuentaService,
protected Repository\Contabilidad\Deposito $depositoRepository,
protected Repository\Contabilidad\Cartola $cartolaRepository,
protected Repository\Contabilidad\Movimiento $movimientoRepository,
protected Service\Contabilidad\Informe\Tesoreria\Excel $excelService,
protected Service\Contabilidad\Informe\Tesoreria\PDF $pdfService)
public function __construct(LoggerInterface $logger,
protected Tesoreria\Output $outputService,
protected Tesoreria\Input $inputService)
{
parent::__construct($logger);
$this->movimientos = new class(self::ORDEN_SOCIEDADES) {
public function __construct(protected array $ordenSociedades)
{
$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 updateDap(object $movimiento): void
{
foreach ($this->ingresos as $ingreso) {
if ($movimiento->cuenta->inmobiliaria->rut !== $ingreso->cuenta->inmobiliaria->rut) {
continue;
}
if ($movimiento->fecha->format('Y-m-d') !== $ingreso->fecha->format('Y-m-d')) {
continue;
}
if ($movimiento->documento !== $ingreso->documento) {
continue;
}
$ingreso->glosa = $movimiento->glosa;
break;
}
}
public function build(): array
{
$this->dap->ingresos = $this->sortBySociedades($this->dap->ingresos);
$this->dap->egresos = $this->sortBySociedades($this->dap->egresos);
$this->ingresos = $this->sortBySociedades($this->ingresos);
$this->egresos = $this->sortBySociedades($this->egresos);
return [
'capital dap' => [
'ingresos' => $this->dap->ingresos,
'egresos' => $this->dap->egresos
],
'ingresos' => $this->ingresos,
'egresos' => $this->egresos
];
}
private function sortBySociedades(array $movimientos): array
{
$temp = [];
foreach ($this->ordenSociedades as $sociedad_rut) {
$date = null;
foreach ($movimientos as $movimiento) {
if ($date === null) {
$date = $movimiento->fecha;
}
if ($movimiento->fecha !== $date) {
if ($movimiento->cuenta->inmobiliaria->rut === $sociedad_rut) {
$temp []= $movimiento;
}
$date = $movimiento->fecha;
continue;
}
if ($movimiento->cuenta->inmobiliaria->rut === $sociedad_rut) {
$temp []= $movimiento;
}
}
}
foreach ($movimientos as $movimiento) {
if (!in_array($movimiento, $temp)) {
$temp []= $movimiento;
}
}
return $temp;
}
};
$this->totales = new class() {
public int $anterior = 0;
public int $actual = 0;
public int $ffmm = 0;
public int $deposito = 0;
public int $saldo = 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
public function getOutput(): Tesoreria\Output
{
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;
return $this->outputService;
}
public function build(DateTimeInterface $fecha): array
public function getInput(): Tesoreria\Input
{
try {
$inmobiliarias = $this->inmobiliariaRepository->fetchAll();
} catch (Implement\Exception\EmptyResult) {
return [];
}
$temp = [];
foreach (self::ORDEN_SOCIEDADES as $sociedad_rut) {
foreach ($inmobiliarias as $inmobiliaria) {
if ($inmobiliaria->rut === $sociedad_rut) {
$temp []= $inmobiliaria;
}
}
}
foreach ($inmobiliarias as $inmobiliaria) {
if (!in_array($inmobiliaria, $temp)) {
$temp []= $inmobiliaria;
}
}
$informe = ['inmobiliarias' => []];
foreach ($temp as $inmobiliaria) {
$informe['inmobiliarias'][$inmobiliaria->rut] = $this->buildInmobiliaria($inmobiliaria, $fecha);
}
$informe['movimientos'] = $this->buildMovimientos();
$informe['totales'] = $this->buildTotales();
//$this->buildInforme($fecha, $informe);
return $informe;
}
public function buildInforme(DateTimeInterface $fecha, array $data, string $type = 'Xlsx', ?string $filename = 'php://output'): void
{
$informe = $this->excelService->build($fecha, $data);
$this->excelService->save($fecha, $informe, $type, $filename);
}
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->cuentaService->getAllActiveByInmobiliaria($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) {
if ($deposito->termino < $fecha) {
continue;
}
$data->deposito += $deposito->capital;
$this->addTotal(self::TOTAL_DAP, $deposito->capital);
$this->totales->saldo += $deposito->capital;
if ($deposito->inicio->format('Y-m-d') === $fecha->format('Y-m-d')) {
$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->format('Y-m-d') === $fecha->format('Y-m-d')) {
$data->deposito -= $deposito->capital;
$this->addTotal(self::TOTAL_DAP, -$deposito->capital);
$this->addMovimientos(self::INGRESOS, [(object) [
'cuenta' => $deposito->cuenta,
'fecha' => $deposito->termino,
'cargo' => 0,
'abono' => $deposito->futuro - $deposito->capital,
'saldo' => $deposito->futuro - $deposito->capital,
'glosa' => 'RESCATE DAP',
'documento' => $deposito->id
]]);
}
}
} catch (Implement\Exception\EmptyResult) {}
$anterior = $this->getAnterior($fecha);
try {
$cartola = $this->cartolaRepository->fetchLastByCuentaAndFecha($cuenta->id, $fecha);
$data->actual = $cartola->saldo;
//$anterior = $this->getAnterior($cartola->fecha);
} catch (Implement\Exception\EmptyResult) {}
try {
$cartola = $this->cartolaRepository->fetchLastByCuentaAndFecha($cuenta->id, $anterior);
$data->anterior = $cartola->saldo;
$this->totales->saldo += $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\Contabilidad\Movimiento $movimiento) {
return $movimiento->abono > 0;
}));
$this->addMovimientos(self::EGRESOS,
array_filter($movimientos, function(Model\Contabilidad\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_starts_with($tipo, 'dap')) {
list($d, $t) = explode('->', $tipo);
$this->movimientos->addDap($t, $movimientos);
return $this;
}
foreach ($movimientos as $movimiento) {
if ($tipo === 'ingresos' and str_contains(strtolower($movimiento->glosa), ' dap ')) {
$this->movimientos->updateDap($movimiento);
continue;
}
$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;
return $this->inputService;
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria;
use Psr\Log\LoggerInterface;
use Psr\Http\Message\UploadedFileInterface;
use Incoviba\Common\Ideal;
class Input extends Ideal\Service
{
public function __construct(LoggerInterface $logger,
protected Input\Excel $excelService,
protected Input\Data\SaldosContables $saldosContablesService,
protected Input\Data\DAPyFFMM $dapYFFMMService)
{
parent::__construct($logger);
}
public function loadFromExcel(UploadedFileInterface $uploadedFile): array
{
if ($uploadedFile->getSize() === 0) {
return [];
}
$tmpFile = '/tmp/' . $uploadedFile->getClientFilename();
$uploadedFile->moveTo($tmpFile);
$data = $this->excelService->load($tmpFile);
unlink($tmpFile);
return $data;
}
public function load(array $data): void
{
$this->saldosContablesService->load($data['saldosContables']);
$this->dapYFFMMService->load($data['dapyffmm']);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Input\Data;
use Incoviba\Common\Ideal;
class DAPyFFMM extends Ideal\Service
{
public function load(array $data): void
{
$this->logger->error('Cargando DAP y FFMM', $data);
}
}

View File

@ -0,0 +1,152 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Input\Data;
use Exception;
use Psr\Log\LoggerInterface;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Repository;
class SaldosContables extends Ideal\Service
{
public function __construct(LoggerInterface $logger,
protected Repository\Inmobiliaria $inmobiliariaRepository,
protected Repository\Inmobiliaria\Cuenta $cuentaRepository,
protected Repository\Contabilidad\Banco $bancoRepository,
protected Repository\Contabilidad\Movimiento $movimientoRepository,
protected Repository\Contabilidad\Movimiento\Detalle $detalleRepository)
{
parent::__construct($logger);
}
public function load(array $data): void
{
$this->data = $data['movimientos'];
foreach ($data['movimientos'] as $type => $dataMovimiento) {
switch ($type) {
case 'total':
$this->saldoInicial = $dataMovimiento;
break;
case 'depositos':
$this->loadDepositos($dataMovimiento);
break;
case 'egresos':
case 'ingresos':
$this->loadMovimiento($dataMovimiento);
break;
}
}
}
protected array $sociedades;
protected int $saldoInicial;
protected array $data;
protected function loadDepositos(array $data): void
{
$this->logger->error('Cargando depositos', $data);
}
protected function loadMovimiento(array $data): void
{
$sociedades = $this->getSociedades();
$unmatched = [];
foreach ($data as $dataMovimiento) {
try {
$sociedad_rut = $this->matchSociedad($sociedades, $dataMovimiento->empresa);
$banco = $this->bancoRepository->fetchByNombre($dataMovimiento->banco);
$cuenta = $this->cuentaRepository->fetchByInmobiliariaAndBanco($sociedad_rut, $banco->id);
$data = [
'cuenta_id' => $cuenta->id,
'fecha' => $dataMovimiento->fecha->format('Y-m-d'),
'glosa' => mb_convert_encoding($dataMovimiento->{'descripción'}, 'UTF-8'),
'documento' => $dataMovimiento->{'n°Doc'},
'cargo' => -$dataMovimiento->egresos,
'abono' => $dataMovimiento->ingresos,
'saldo' => $this->getSaldo($dataMovimiento)
];
try {
$movimiento = $this->movimientoRepository->fetchByCuentaAndFechaAndCargoAndAbonoAndSaldo($cuenta->id, $dataMovimiento->fecha, $data['cargo'], $data['abono'], $data['saldo']);
} catch (Implement\Exception\EmptyResult) {
$movimiento = $this->movimientoRepository->create($data);
$movimiento = $this->movimientoRepository->save($movimiento);
}
list($rut, $digito) = explode('-', $dataMovimiento->rut);
$data = [
'movimiento_id' => $movimiento->id,
'centro_costo_id' => $dataMovimiento->cc,
'rut' => (int) preg_replace('/\D*/', '', $rut),
'digito' => $digito,
'nombre' => $dataMovimiento->nombres,
'categoria' => $dataMovimiento->categoria,
'detalle' => $dataMovimiento->detalle,
];
if ($data['centro_costo_id'] === 0 and ($data['rut'] === 0 or $data['nombre'] === '' or $data['categoria'] === '' or $data['detalle'] === '')) {
continue;
}
try {
$detalles = $this->detalleRepository->fetchByMovimiento($movimiento->id);
$this->detalleRepository->edit($detalles, $data);
} catch (Implement\Exception\EmptyResult) {
$detalles = $this->detalleRepository->create($data);
$this->detalleRepository->save($detalles);
}
} catch (Exception $exception) {
$this->logger->error($exception);
$unmatched []= $dataMovimiento;
}
}
if (count($unmatched) > 0) {
$this->logger->error('Movimientos no asociados', $unmatched);
}
}
protected function getSociedades(): array
{
if (!isset($this->sociedades)) {
$this->sociedades = [];
try {
$this->sociedades = $this->inmobiliariaRepository->fetchAll();
} catch (Implement\Exception\EmptyResult $e) {
$this->logger->error($e->getMessage());
}
}
return $this->sociedades;
}
protected function getSaldo($movimiento): int
{
$saldo = $this->saldoInicial;
foreach ($this->data as $type => $dataMovimientos) {
if (in_array($type, ['total', 'depositos'])) {
continue;
}
foreach ($dataMovimientos as $dataMovimiento) {
if ($dataMovimiento !== $movimiento) {
continue;
}
$saldo += $dataMovimiento->ingresos + $dataMovimiento->egresos;
}
}
return $saldo;
}
protected function matchSociedad(array $sociedades, string $name): int
{
foreach ($sociedades as $sociedad) {
$abreviacion = $sociedad->abreviacion;
if ($abreviacion === 'Incoviba') {
if (preg_match('/(Vial Balmaceda)+/', $name) === 1) {
return $sociedad->rut;
}
continue;
}
if (str_contains($abreviacion, 'Optimus')) {
$abreviacion = 'Óptimus';
}
if (preg_match("/({$abreviacion})+/", $name) === 1) {
return $sociedad->rut;
}
}
throw new Exception("No se encontró la sociedad asociada al nombre '{$name}'");
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Input;
use Psr\Log\LoggerInterface;
use PhpOffice\PhpSpreadsheet;
use Incoviba\Common\Ideal;
class Excel extends Ideal\Service
{
public function __construct(LoggerInterface $logger,
protected Excel\SaldosCuentas $saldosCuentasService,
protected Excel\DAPyFFMM $dapyFFMMService,
protected Excel\DeudaBanco $deudaBancoService)
{
parent::__construct($logger);
}
public function load(string $filename): array
{
try {
$reader = PhpSpreadsheet\IOFactory::createReaderForFile($filename);
} catch (PhpSpreadsheet\Reader\Exception $e) {
$this->logger->error($e->getMessage());
return [];
}
$excel = $reader->load($filename);
$data = [];
$data['saldosContables'] = $this->saldosCuentasService->load($excel);
$data['dapyffmm'] = $this->dapyFFMMService->load($excel);
$data['deudaBanco'] = $this->deudaBancoService->load($excel);
return $data;
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Input\Excel;
use stdClass;
use PhpOffice\PhpSpreadsheet;
class DAPyFFMM extends Sheet
{
public function load(PhpSpreadsheet\Spreadsheet $excel): array
{
if (!$excel->sheetNameExists('DAP y FFMM')) {
return [];
}
$sheet = $excel->getSheetByName('DAP y FFMM');
$data = [];
$rowIndex = 1;
while ($sheet->getCell("B{$rowIndex}")->getValue() !== 'EMPRESA') {
$rowIndex ++;
}
$titleRow = $rowIndex;
$columnOffset = 2;
$titles = $this->getTableTitles($sheet, $titleRow, $columnOffset, 20, 'UF', ['(']);
$rowIndex ++;
while ($sheet->getCell("B{$rowIndex}")->getValue() !== 'TOTAL') {
if ($sheet->getCell("B{$rowIndex}")->getValue() !== null) {
$data []= $this->getRow($sheet, $titles, $titleRow, $rowIndex, $columnOffset);
/*
$dap = [];
$columnIndex = 0;
$dap[$titles[$columnIndex ++]] = $sheet->getCell("B{$rowIndex}")->getValue();
$dap[$titles[$columnIndex ++]] = $sheet->getCell("D{$rowIndex}")->getValue();
$dap[$titles[$columnIndex ++]] = $sheet->getCell("F{$rowIndex}")->getValue();
$dap[$titles[$columnIndex ++]] = $this->getCalculatedValue($sheet, 'H', $rowIndex);
$dap[$titles[$columnIndex ++]] = $this->getCalculatedValue($sheet, 'I', $rowIndex);
$dap[$titles[$columnIndex ++]] = $this->getCalculatedValue($sheet, 'J', $rowIndex);
$dap[$titles[$columnIndex ++]] = $this->getCalculatedValue($sheet, 'K', $rowIndex);
$dap[$titles[$columnIndex ++]] = PhpSpreadsheet\Shared\Date::excelToDateTimeObject($this->getCalculatedValue($sheet, 'L', $rowIndex));
$dap[$titles[$columnIndex ++]] = PhpSpreadsheet\Shared\Date::excelToDateTimeObject($this->getCalculatedValue($sheet, 'M', $rowIndex));
$dap[$titles[$columnIndex ++]] = $this->getCalculatedValue($sheet, 'N', $rowIndex);
$dap[$titles[$columnIndex]] = $this->getCalculatedValue($sheet, 'O', $rowIndex);
$data []= (object) $dap;*/
}
$rowIndex ++;
}
return $data;
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Input\Excel;
use PhpOffice\PhpSpreadsheet;
class DeudaBanco extends Sheet
{
public function load(PhpSpreadsheet\Spreadsheet $excel): array
{
if (!$excel->sheetNameExists('Deuda Banco')) {
return [];
}
$sheet = $excel->getSheetByName('Deuda Banco');
$data = [];
$rowIndex = 1;
$columnOffset = 2;
while ($sheet->getCell([$columnOffset, $rowIndex])->getValue() !== 'EMPRESA') {
$rowIndex ++;
}
$titleRow = $rowIndex;
$titles = $this->getTableTitles($sheet, $titleRow, $columnOffset, 13, 'UF', ['(']);
$rowIndex ++;
while ($sheet->getCell([$columnOffset, $rowIndex])->getValue() !== 'TOTAL GRUPO EMPRESAS') {
if ($sheet->getCell([$columnOffset, $rowIndex])->getValue() !== null) {
$data []= $this->getRow($sheet, $titles, $titleRow, $rowIndex, $columnOffset);
}
$rowIndex ++;
}
return $data;
}
}

View File

@ -0,0 +1,109 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Input\Excel;
use stdClass;
use PhpOffice\PhpSpreadsheet;
class SaldosCuentas extends Sheet
{
public function load(PhpSpreadsheet\Spreadsheet $excel): array
{
if (!$excel->sheetNameExists('Saldos cuentas')) {
return [];
}
$sheet = $excel->getSheetByName('Saldos cuentas');
$data = [];
$data['anterior'] = PhpSpreadsheet\Shared\Date::excelToDateTimeObject($this->getCalculatedValue($sheet, 'C4'));
$data['actual'] = PhpSpreadsheet\Shared\Date::excelToDateTimeObject($this->getCalculatedValue($sheet, 'C5'));
$data['uf'] = $this->getCalculatedValue($sheet, 'F4');
$data['usd'] = $this->getCalculatedValue($sheet, 'F5');
$titleRow = 7;
$data['sociedades'] = $this->getSociedades($sheet, $titleRow);
$titleRow += count($data['sociedades']);
while ($sheet->getCell("B{$titleRow}")->getValue() !== 'EMPRESA') {
$titleRow ++;
}
$data['movimientos'] = $this->getMovimientos($sheet, $titleRow);
return $data;
}
protected function getSociedades(PhpSpreadsheet\Worksheet\Worksheet $sheet, int $titleRow = 7, int $startColumn = 2): array
{
$totalsColumn = $startColumn;
while ($sheet->getCell([$totalsColumn, $titleRow])->getValue() !== null && $sheet->getCell([$totalsColumn, $titleRow])->getValue() !== 'Total Cuentas') {
$totalsColumn ++;
}
$rowIndex = $titleRow + 1;
$sociedades = [];
while ($rowIndex < 100 and $sheet->getCell("B{$rowIndex}")->getValue() !== 'TOTAL') {
$sociedad = new stdClass();
$sociedad->razon = $sheet->getCell("B{$rowIndex}")->getValue();
$sociedad->cuentas = [];
$cuentaColumnIndex = 3;
$cuenta = new stdClass();
while ($cuentaColumnIndex < $totalsColumn) {
$cuenta->banco = $sheet->getCell([$cuentaColumnIndex ++, $rowIndex])->getValue() ?? '';
$cuenta->numero = $sheet->getCell([$cuentaColumnIndex ++, $rowIndex])->getValue() ?? '';
$cuenta->anterior = $this->getCalculatedValue($sheet, $cuentaColumnIndex ++, $rowIndex);
$cuenta->actual = $this->getCalculatedValue($sheet, $cuentaColumnIndex ++, $rowIndex);
$cuenta->diferencia = $this->getCalculatedValue($sheet, $cuentaColumnIndex ++, $rowIndex);
$cuenta->ffmm = $this->getCalculatedValue($sheet, $cuentaColumnIndex ++, $rowIndex);
$cuenta->deposito = $this->getCalculatedValue($sheet, $cuentaColumnIndex ++, $rowIndex);
$cuenta->saldo = $this->getCalculatedValue($sheet, $cuentaColumnIndex ++, $rowIndex);
$sociedad->cuentas []= $cuenta;
if ($sheet->getCell([$cuentaColumnIndex, $rowIndex])->getValue() === null) {
break;
}
$cuenta = new stdClass();
}
$sociedades []= $sociedad;
$rowIndex ++;
}
return $sociedades;
}
protected function getMovimientos(PhpSpreadsheet\Worksheet\Worksheet $sheet, int $titleRow, int $startColumn = 2): array
{
$data = [];
$titles = $this->getTableTitles($sheet, $titleRow, $startColumn, 15);
$totalRow = $titleRow + 2;
$data['total'] = $this->getCalculatedValue($sheet, "V{$totalRow}");
$rowIndex = $titleRow + 4;
$depositos = [];
while ($sheet->getCell("B{$rowIndex}")->getValue() !== 'INGRESOS') {
if ( $sheet->getCell("B{$rowIndex}")->getValue() !== null) {
$depositos []= $this->getRow($sheet, $titles, $titleRow, $rowIndex, $startColumn);
}
$rowIndex ++;
}
$data['depositos'] = $depositos;
$rowIndex ++;
$ingresos = [];
while ($sheet->getCell("B{$rowIndex}")->getValue() !== 'EGRESOS') {
if ($sheet->getCell("B{$rowIndex}")->getValue() !== null) {
$ingresos []= $this->getRow($sheet, $titles, $titleRow, $rowIndex, $startColumn);
}
$rowIndex ++;
}
$data['ingresos'] = $ingresos;
$rowIndex ++;
$egresos = [];
while ($sheet->getCell("B{$rowIndex}")->getValue() !== 'TOTAL') {
if ($sheet->getCell("B{$rowIndex}")->getValue() === null) {
break;
}
$egresos [] = $this->getRow($sheet, $titles, $titleRow, $rowIndex, $startColumn);
$rowIndex ++;
}
$data['egresos'] = $egresos;
return $data;
}
}

View File

@ -0,0 +1,73 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Input\Excel;
use PhpOffice\PhpSpreadsheet;
use Incoviba\Common\Ideal;
abstract class Sheet extends Ideal\Service
{
protected function getCalculatedValue(PhpSpreadsheet\Worksheet\Worksheet $sheet, int|string $columnIndex, ?int $rowIndex = null, mixed $default = 0): mixed
{
try {
if (is_string($columnIndex)) {
if ($rowIndex === null) {
return $sheet->getCell($columnIndex)->getCalculatedValue() ?? $default;
}
return $sheet->getCell("{$columnIndex}{$rowIndex}")->getCalculatedValue() ?? $default;
}
return $sheet->getCell([$columnIndex, $rowIndex])->getCalculatedValue() ?? $default;
} catch (PhpSpreadsheet\Calculation\Exception $e) {
$this->logger->error($e->getMessage());
return $default;
}
}
protected function getTableTitles(PhpSpreadsheet\Worksheet\Worksheet $sheet, int $titleRow, int $columnOffset, int $maxColumns, string $duplicateSuffix = '', array $cutoffCharacters = []): array
{
$titles = [];
$columnIndex = $columnOffset;
while ($columnIndex < $maxColumns or $sheet->getCell([$columnIndex, $titleRow])->getValue() !== null) {
if ($sheet->getCell([$columnIndex, $titleRow])->getValue() !== null) {
$title = $this->transformTitle($sheet->getCell([$columnIndex, $titleRow])->getValue(), $cutoffCharacters);
if (in_array($title, $titles)) {
$title .= $duplicateSuffix;
}
$titles []= $title;
}
$columnIndex ++;
}
return $titles;
}
protected function getRow(PhpSpreadsheet\Worksheet\Worksheet $sheet, array $titles, int $titleRow, int $rowIndex, int $columnOffset): object
{
$row = [];
$columnIndex = $columnOffset;
$titleIndex = 0;
$currentTitle = $this->transformTitle($sheet->getCell([$columnIndex, $titleRow])->getValue());
while ($columnIndex < count($titles) * 3 and $currentTitle !== last($titles)) {
if ($sheet->getCell([$columnIndex, $titleRow])->getValue() === null) {
$columnIndex ++;
continue;
}
if (str_contains($titles[$titleIndex], 'fecha')) {
$row[$titles[$titleIndex ++]] = PhpSpreadsheet\Shared\Date::excelToDateTimeObject($this->getCalculatedValue($sheet, $columnIndex ++, $rowIndex));
continue;
}
$row[$titles[$titleIndex ++]] = $this->getCalculatedValue($sheet, $columnIndex ++, $rowIndex);
}
return (object) $row;
}
protected function transformTitle(string $title, array $cutoffCharacters = []): string
{
$title = str_replace(' ', '', ucwords(mb_strtolower($title)));
$title = strtolower(substr($title, 0, 1)) . substr($title, 1);
foreach ($cutoffCharacters as $cutoffCharacter) {
if (str_contains($title, $cutoffCharacter)) {
$title = substr($title, 0, strpos($title, $cutoffCharacter));
}
}
return $title;
}
abstract public function load(PhpSpreadsheet\Spreadsheet $excel): array;
}

View File

@ -0,0 +1,226 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria;
use DateInterval;
use DateTimeInterface;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
use Psr\Log\LoggerInterface;
class Output extends Ideal\Service
{
protected const ORDEN_SOCIEDADES = [
99543380,
78017310,
76837020,
76743916,
76519798,
76309587,
77023196,
77023201,
76309592,
76163347,
76158424
];
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 __construct(LoggerInterface $logger,
protected Repository\Inmobiliaria $inmobiliariaRepository,
protected Repository\Contabilidad\Deposito $depositoRepository,
protected Repository\Contabilidad\Cartola $cartolaRepository,
protected Repository\Contabilidad\Movimiento $movimientoRepository,
protected Service\Inmobiliaria\Cuenta $cuentaService,
protected Output\Excel $excelService,
protected Output\PDF $pdfService)
{
parent::__construct($logger);
$this->movimientos = new Output\Data\Movimientos(self::ORDEN_SOCIEDADES);
$this->totales = new Output\Data\Totales();
}
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->fetchAll();
} catch (Implement\Exception\EmptyResult) {
return [];
}
$data = $this->sortBySociedad($inmobiliarias);
$informe = ['sociedades' => []];
foreach ($data as $sociedad) {
$informe['sociedades'][$sociedad->rut] = $this->buildInmobiliaria($sociedad, $fecha);
}
$informe['movimientos'] = $this->buildMovimientos();
$informe['totales'] = $this->buildTotales();
//$this->buildInforme($fecha, $informe);
return $informe;
}
public function buildInforme(DateTimeInterface $fecha, array $data, string $type = 'Xlsx', ?string $filename = 'php://output'): void
{
$informe = $this->excelService->build($fecha, $data);
$this->excelService->save($fecha, $informe, $type, $filename);
}
protected function buildInmobiliaria(Model\Inmobiliaria $inmobiliaria, DateTimeInterface $fecha): object
{
$dataInmobiliaria = new Output\Data\Sociedad();
$dataInmobiliaria->sociedad = $inmobiliaria;
try {
$cuentas = $this->cuentaService->getAllActiveByInmobiliaria($inmobiliaria->rut);
} catch (Implement\Exception\EmptyResult) {
return $dataInmobiliaria;
}
foreach ($cuentas as $cuenta) {
$data = new Output\Data\Cuenta();
$data->banco = $cuenta->banco->nombre;
$data->numero = $cuenta->cuenta;
try {
$depositos = $this->depositoRepository->fetchByCuenta($cuenta->id);
foreach ($depositos as $deposito) {
if ($deposito->termino < $fecha) {
continue;
}
$data->deposito += $deposito->capital;
$this->addTotal(self::TOTAL_DAP, $deposito->capital);
$this->totales->saldo += $deposito->capital;
if ($deposito->inicio->format('Y-m-d') === $fecha->format('Y-m-d')) {
$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->format('Y-m-d') === $fecha->format('Y-m-d')) {
$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 - $deposito->capital,
'saldo' => $deposito->futuro - $deposito->capital,
'glosa' => 'RESCATE DAP',
'documento' => $deposito->id
]]);
}
}
} catch (Implement\Exception\EmptyResult) {}
$anterior = $this->getAnterior($fecha);
try {
$cartola = $this->cartolaRepository->fetchLastByCuentaAndFecha($cuenta->id, $fecha);
$data->actual = $cartola->saldo;
//$anterior = $this->getAnterior($cartola->fecha);
} catch (Implement\Exception\EmptyResult) {}
try {
$cartola = $this->cartolaRepository->fetchLastByCuentaAndFecha($cuenta->id, $anterior);
$data->anterior = $cartola->saldo;
$this->totales->saldo += $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\Contabilidad\Movimiento $movimiento) {
return $movimiento->abono > 0;
}));
$this->addMovimientos(self::EGRESOS,
array_filter($movimientos, function(Model\Contabilidad\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): Output
{
if (str_starts_with($tipo, 'dap')) {
list($d, $t) = explode('->', $tipo);
$this->movimientos->addDap($t, $movimientos);
return $this;
}
foreach ($movimientos as $movimiento) {
if ($tipo === 'ingresos' and str_contains(strtolower($movimiento->glosa), ' dap ')) {
$this->movimientos->updateDap($movimiento);
continue;
}
$this->movimientos->{$tipo} []= $movimiento;
}
return $this;
}
protected function addTotal(string|array $tipo, int|array $total): Output
{
if (is_array($tipo)) {
foreach ($tipo as $i => $t) {
$this->addTotal($t, $total[$i]);
}
return $this;
}
$this->totales->{$tipo} += $total;
return $this;
}
protected function sortBySociedad(array $data): array
{
$temp = [];
foreach (self::ORDEN_SOCIEDADES as $sociedad_rut) {
foreach ($data as $inmobiliaria) {
if ($inmobiliaria->rut === $sociedad_rut) {
$temp []= $inmobiliaria;
}
}
}
foreach ($data as $inmobiliaria) {
if (!in_array($inmobiliaria, $temp)) {
$temp []= $inmobiliaria;
}
}
return $temp;
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Output\Data;
class Cuenta
{
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;
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Output\Data;
class Movimientos
{
public function __construct(protected array $ordenSociedades)
{
$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 updateDap(object $movimiento): void
{
foreach ($this->ingresos as $ingreso) {
if ($movimiento->cuenta->inmobiliaria->rut !== $ingreso->cuenta->inmobiliaria->rut) {
continue;
}
if ($movimiento->fecha->format('Y-m-d') !== $ingreso->fecha->format('Y-m-d')) {
continue;
}
if ($movimiento->documento !== $ingreso->documento) {
continue;
}
$ingreso->glosa = $movimiento->glosa;
break;
}
}
public function build(): array
{
$this->dap->ingresos = $this->sortBySociedades($this->dap->ingresos);
$this->dap->egresos = $this->sortBySociedades($this->dap->egresos);
$this->ingresos = $this->sortBySociedades($this->ingresos);
$this->egresos = $this->sortBySociedades($this->egresos);
return [
'capital dap' => [
'ingresos' => $this->dap->ingresos,
'egresos' => $this->dap->egresos
],
'ingresos' => $this->ingresos,
'egresos' => $this->egresos
];
}
private function sortBySociedades(array $movimientos): array
{
$temp = [];
foreach ($this->ordenSociedades as $sociedad_rut) {
$date = null;
foreach ($movimientos as $movimiento) {
if ($date === null) {
$date = $movimiento->fecha;
}
if ($movimiento->fecha !== $date) {
if ($movimiento->cuenta->inmobiliaria->rut === $sociedad_rut) {
$temp []= $movimiento;
}
$date = $movimiento->fecha;
continue;
}
if ($movimiento->cuenta->inmobiliaria->rut === $sociedad_rut) {
$temp []= $movimiento;
}
}
}
foreach ($movimientos as $movimiento) {
if (!in_array($movimiento, $temp)) {
$temp []= $movimiento;
}
}
return $temp;
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Output\Data;
use Incoviba\Model;
class Sociedad
{
public Model\Inmobiliaria $sociedad;
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);
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Output\Data;
class Totales
{
public int $anterior = 0;
public int $actual = 0;
public int $ffmm = 0;
public int $deposito = 0;
public int $saldo = 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();
}
}

View File

@ -1,8 +1,8 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria;
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Output;
use DateTimeInterface;
use DateInterval;
use DateTimeInterface;
use IntlDateFormatter;
use Psr\Log\LoggerInterface;
use PhpOffice\PhpSpreadsheet;
@ -176,7 +176,7 @@ class Excel extends Ideal\Service
$this->fillColumns($sheet, $columns, $styles, $startRow);
$rowIndex = $startRow + 1;
$sociedades = $data['inmobiliarias'];
$sociedades = $data['sociedades'];
foreach ($sociedades as $dataSociedad) {
$rowIndex += $this->fillSociedad($sheet, $dataSociedad, $rowIndex);
}
@ -461,7 +461,7 @@ class Excel extends Ideal\Service
protected function fillSociedad(PhpSpreadsheet\Worksheet\Worksheet $sheet, object $dataSociedad, int $baseRowIndex): int
{
$rowIndex = $baseRowIndex;
$sheet->getCell("B{$rowIndex}")->setValue($dataSociedad->inmobiliaria->razon);
$sheet->getCell("B{$rowIndex}")->setValue($dataSociedad->sociedad->razon);
foreach ($dataSociedad->cuentas as $cuentaRowIndex => $cuenta) {
$this->fillCuenta($sheet, $cuenta, 3, $baseRowIndex + $cuentaRowIndex);
}

View File

@ -1,5 +1,5 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria;
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria\Output;
use DateTimeInterface;

View File

@ -34,6 +34,22 @@ class Movimiento extends Service
{
return array_map([$this, 'process'], $this->movimientoRepository->fetchAmountBySociedadAndMes($sociedad_rut, $mes, $amount));
}
public function getByCuentaAndFechaAndGlosaAndCargoAndAbonoAndSaldo(int $cuenta_id, DateTimeInterface $fecha, string $glosa, int $cargo, int $abono, int $saldo): Model\Contabilidad\Movimiento
{
return $this->process($this->movimientoRepository->fetchByCuentaAndFechaAndGlosaAndCargoAndAbonoAndSaldo($cuenta_id, $fecha, $glosa, $cargo, $abono, $saldo));
}
public function add(array $data): Model\Contabilidad\Movimiento
{
try {
$movimiento = $this->movimientoRepository->fetchByCuentaAndFechaAndGlosaAndCargoAndAbonoAndSaldo($data['cuenta_id'], $data['fecha'], $data['glosa'], $data['cargo'] ?? 0, $data['abono'] ?? 0, $data['saldo']);
} catch (Implement\Exception\EmptyResult) {
$data['fecha'] = $data['fecha']->format('Y-m-d');
$movimiento = $this->movimientoRepository->create($data);
$movimiento = $this->movimientoRepository->save($movimiento);
}
$movimiento = $this->setDetalles($movimiento, $data);
return $this->process($movimiento);
}
public function setDetalles(Model\Contabilidad\Movimiento $movimiento, array $data): Model\Contabilidad\Movimiento
{
try {
@ -58,11 +74,11 @@ class Movimiento extends Service
}
})
->setArgs(['movimiento_id' => $movimiento->id]));
$movimiento->addFactory('auxiliares', (new Implement\Repository\Factory())
/*$movimiento->addFactory('auxiliares', (new Implement\Repository\Factory())
->setCallable(function(int $movimiento_id) {
return $this->auxiliarService->getByMovimiento($movimiento_id);
})
->setArgs(['movimiento_id' => $movimiento->id]));
->setArgs(['movimiento_id' => $movimiento->id]));*/
return $movimiento;
}
}