diff --git a/app/common/Ideal/Cartola/Banco.php b/app/common/Ideal/Cartola/Banco.php index 16d88e2..253a952 100644 --- a/app/common/Ideal/Cartola/Banco.php +++ b/app/common/Ideal/Cartola/Banco.php @@ -2,9 +2,10 @@ namespace Incoviba\Common\Ideal\Cartola; use Incoviba\Common\Define; +use Incoviba\Common\Ideal\Service; use Psr\Http\Message\UploadedFileInterface; -abstract class Banco implements Define\Cartola\Banco +abstract class Banco extends Service implements Define\Cartola\Banco { public function process(UploadedFileInterface $file): array { @@ -14,6 +15,9 @@ abstract class Banco implements Define\Cartola\Banco foreach ($data as $row) { $r = []; foreach ($columns as $old => $new) { + if (!isset($row[$old])) { + continue; + } $r[$new] = $row[$old]; } $temp []= $r; diff --git a/app/resources/routes/api/contabilidad/cartolas.php b/app/resources/routes/api/contabilidad/cartolas.php index f81baa7..9f86632 100644 --- a/app/resources/routes/api/contabilidad/cartolas.php +++ b/app/resources/routes/api/contabilidad/cartolas.php @@ -5,5 +5,8 @@ $app->group('/cartolas', function($app) { $app->post('/procesar[/]', [Contabilidad::class, 'procesarCartola']); }); $app->group('/cartola', function($app) { + $app->group('/diaria', function($app) { + $app->post('/procesar[/]', [Contabilidad::class, 'procesarCartolaDiaria']); + }); $app->post('/exportar[/]', [Contabilidad::class, 'exportarCartola']); }); diff --git a/app/setup/setups/services.php b/app/setup/setups/services.php index 485eda8..d998cdd 100644 --- a/app/setup/setups/services.php +++ b/app/setup/setups/services.php @@ -39,6 +39,16 @@ return [ ->register('itau', $container->get(Incoviba\Service\Cartola\Itau::class)) ->register('santander', $container->get(Incoviba\Service\Cartola\Santander::class)); }, + Incoviba\Service\Cartola\Diaria::class => function(ContainerInterface $container) { + return (new Incoviba\Service\Cartola\Diaria( + $container->get(Incoviba\Repository\Inmobiliaria\Cuenta::class), + $container->get(Incoviba\Repository\Movimiento::class), + $container->get(Incoviba\Repository\Cartola::class) + )) + ->register('security', $container->get(Incoviba\Service\Cartola\Security::class)) + ->register('itau', $container->get(Incoviba\Service\Cartola\Itau::class)) + ->register('santander', $container->get(Incoviba\Service\Cartola\Santander::class)); + }, Incoviba\Common\Define\Contabilidad\Exporter::class => function(ContainerInterface $container) { return $container->get(Incoviba\Service\Contabilidad\Exporter\Nubox::class); }, diff --git a/app/src/Controller/API/Contabilidad.php b/app/src/Controller/API/Contabilidad.php index bf35b84..47552ff 100644 --- a/app/src/Controller/API/Contabilidad.php +++ b/app/src/Controller/API/Contabilidad.php @@ -2,13 +2,14 @@ namespace Incoviba\Controller\API; use DateTimeImmutable; +use Incoviba\Common\Ideal\Controller; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Incoviba\Common\Implement\Exception\EmptyResult; use Incoviba\Repository; use Incoviba\Service; -class Contabilidad +class Contabilidad extends Controller { use withJson; @@ -49,4 +50,25 @@ class Contabilidad } catch (EmptyResult) {} return $this->withJson($response, $output); } + public function procesarCartolaDiaria(ServerRequestInterface $request, ResponseInterface $response, + Repository\Inmobiliaria $inmobiliariaRepository, + Repository\Banco $bancoRepository, + Service\Cartola\Diaria $cartolaService): ResponseInterface + { + $body = $request->getParsedBody(); + $output = [ + 'input' => $body, + 'cartola' => [] + ]; + try { + $inmobiliaria = $inmobiliariaRepository->fetchById($body['inmobiliaria_rut']); + $banco = $bancoRepository->fetchById($body['banco_id']); + $fecha = new DateTimeImmutable($body['fecha']); + $file = $request->getUploadedFiles()['file']; + $output['cartola'] = $cartolaService->process($inmobiliaria, $banco, $fecha, $file); + } catch (EmptyResult $exception) { + $this->logger->debug($exception); + } + return $this->withJson($response, $output); + } } diff --git a/app/src/Model/Cartola.php b/app/src/Model/Cartola.php new file mode 100644 index 0000000..49363b6 --- /dev/null +++ b/app/src/Model/Cartola.php @@ -0,0 +1,26 @@ + $this->cuenta->id, + 'fecha' => $this->fecha->format('Y-m-d'), + 'cargos' => $this->cargos, + 'abonos' => $this->abonos, + 'saldo' => $this->saldo + ]); + } +} diff --git a/app/src/Model/Movimiento.php b/app/src/Model/Movimiento.php new file mode 100644 index 0000000..6ca1a36 --- /dev/null +++ b/app/src/Model/Movimiento.php @@ -0,0 +1,29 @@ + $this->cuenta->id, + 'fecha' => $this->fecha->format('Y-m-d'), + 'glosa' => $this->glosa, + 'documento' => $this->documento, + 'cargo' => $this->cargo, + 'abono' => $this->abono, + 'saldo' => $this->saldo + ]); + } +} diff --git a/app/src/Repository/Cartola.php b/app/src/Repository/Cartola.php new file mode 100644 index 0000000..be03b12 --- /dev/null +++ b/app/src/Repository/Cartola.php @@ -0,0 +1,60 @@ +setTable('cartolas'); + } + + public function create(?array $data = null): Model\Cartola + { + $map = (new Implement\Repository\MapperParser(['cargos', 'abonos', 'saldo'])) + ->register('fecha', new Implement\Repository\Mapper\DateTime('fecha')) + ->register('cuenta_id', (new Implement\Repository\Mapper()) + ->setProperty('cuenta') + ->setFunction(function($data) { + return $this->cuentaRepository->fetchById($data['cuenta_id']); + })); + return $this->parseData(new Model\Cartola(), $data, $map); + } + public function save(Define\Model $model): Model\Cartola + { + $model->id = $this->saveNew([ + 'cuenta_id', + 'fecha', + 'cargos', + 'abonos', + 'saldo' + ], [ + $model->cuenta->id, + $model->fecha->format('Y-m-d'), + $model->cargos, + $model->abonos, + $model->saldo + ]); + return $model; + } + public function edit(Define\Model $model, array $new_data): Model\Cartola + { + return $this->update($model, ['cuenta_id', 'fecha', 'cargos', 'abonos', 'saldo'], $new_data); + } + + public function fetchByCuentaAndFecha(int $cuenta_id, DateTimeInterface $fecha): Model\Cartola + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('cuenta_id = ? AND fecha = ?'); + return $this->fetchOne($query, [$cuenta_id, $fecha->format('Y-m-d')]); + } +} diff --git a/app/src/Repository/Inmobiliaria/Cuenta.php b/app/src/Repository/Inmobiliaria/Cuenta.php index 71e3b5d..5005723 100644 --- a/app/src/Repository/Inmobiliaria/Cuenta.php +++ b/app/src/Repository/Inmobiliaria/Cuenta.php @@ -6,6 +6,7 @@ use Incoviba\Common\Ideal; use Incoviba\Repository; use Incoviba\Model; use Incoviba\Common\Implement; +use PhpParser\Node\Expr\BinaryOp\Mod; class Cuenta extends Ideal\Repository { @@ -49,4 +50,12 @@ class Cuenta extends Ideal\Repository ->where('inmobiliaria = ?'); return $this->fetchMany($query, [$inmobiliaria_rut]); } + public function fetchByInmobiliariaAndBanco(int $inmobiliaria_rut, int $banco_id): Model\Inmobiliaria\Cuenta + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('inmobiliaria = ? AND banco = ?'); + return $this->fetchOne($query, [$inmobiliaria_rut, $banco_id]); + } } diff --git a/app/src/Repository/Movimiento.php b/app/src/Repository/Movimiento.php new file mode 100644 index 0000000..8e11f06 --- /dev/null +++ b/app/src/Repository/Movimiento.php @@ -0,0 +1,64 @@ +setTable('movimientos'); + } + + public function create(?array $data = null): Model\Movimiento + { + $map = (new Implement\Repository\MapperParser(['cargo', 'abono', 'saldo', 'glosa', 'documento'])) + ->register('fecha', new Implement\Repository\Mapper\DateTime('fecha')) + ->register('cuenta_id', (new Implement\Repository\Mapper()) + ->setProperty('cuenta') + ->setFunction(function($data) { + return $this->cuentaRepository->fetchById($data['cuenta_id']); + }) + ); + return $this->parseData(new Model\Movimiento(), $data, $map); + } + public function save(Define\Model $model): Model\Movimiento + { + $model->id = $this->saveNew([ + 'cuenta_id', + 'fecha', + 'glosa', + 'documento', + 'cargo', + 'abono', + 'saldo' + ], [ + $model->cuenta->id, + $model->fecha->format('Y-m-d'), + $model->glosa, + $model->documento, + $model->cargo, + $model->abono, + $model->saldo + ]); + return $model; + } + public function edit(Define\Model $model, array $new_data): Model\Movimiento + { + return $this->update($model, ['cuenta_id', 'fecha', 'glosa', 'documento', 'cargo', 'abono', 'saldo'], $new_data); + } + + public function fetchByCuentaAndFechaAndMonto(int $cuenta_id, DateTimeInterface $fecha, int $monto): Model\Movimiento + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('cuenta_id = ? AND fecha = ? AND (cargo = ? OR abono = ?)'); + return $this->fetchOne($query, [$cuenta_id, $fecha->format('Y-m-d'), $monto, $monto]); + } +} diff --git a/app/src/Service/Cartola/Diaria.php b/app/src/Service/Cartola/Diaria.php new file mode 100644 index 0000000..0bff8ec --- /dev/null +++ b/app/src/Service/Cartola/Diaria.php @@ -0,0 +1,66 @@ +bancos[$name] = $banco; + return $this; + } + + public function process(Model\Inmobiliaria $inmobiliaria, Model\Banco $banco, DateTimeInterface $fecha, UploadedFileInterface $file): array + { + $cuenta = $this->cuentaRepository->fetchByInmobiliariaAndBanco($inmobiliaria->rut, $banco->id); + + $ms = $this->bancos[strtolower($banco->nombre)]->process($file); + $ms = array_reverse($ms); + $c = array_shift($ms); + $cargos = 0; + $abonos = 0; + $saldo = $c['saldo']; + + $movimientos = []; + foreach ($ms as $m) { + $m['cuenta_id'] = $cuenta->id; + try { + $movimiento = $this->movimientoRepository->fetchByCuentaAndFechaAndMonto($cuenta->id, new DateTimeImmutable($m['fecha']), $m['cargo'] ?? $m['abono']); + } catch (EmptyResult) { + $movimiento = $this->movimientoRepository->create($m); + $movimiento = $this->movimientoRepository->save($movimiento); + } + $movimientos []= $movimiento; + if ($movimiento->fecha === $fecha) { + $cargos += $movimiento->cargo; + $abonos += $movimiento->abono; + } + $saldo = $m['saldo']; + } + try { + $cartola = $this->cartolaRepository->fetchByCuentaAndFecha($cuenta->id, $fecha); + } catch (EmptyResult) { + $cartola = $this->cartolaRepository->create([ + 'cuenta_id' => $cuenta->id, + 'fecha' => $fecha->format('Y-m-d'), + 'cargos' => $cargos, + 'abonos' => $abonos, + 'saldo' => $saldo + ]); + $cartola = $this->cartolaRepository->save($cartola); + } + return compact('cartola', 'movimientos'); + } +} diff --git a/app/src/Service/Cartola/Security.php b/app/src/Service/Cartola/Security.php index 28323a2..c00861c 100644 --- a/app/src/Service/Cartola/Security.php +++ b/app/src/Service/Cartola/Security.php @@ -24,8 +24,10 @@ class Security extends Banco 'fecha' => 'fecha', 'descripción' => 'glosa', 'número de documentos' => 'documento', + 'nº documento' => 'documento', 'cargos' => 'cargo', - 'abonos' => 'abono' + 'abonos' => 'abono', + 'saldos' => 'saldo' ]; } @@ -33,10 +35,9 @@ class Security extends Banco { $filename = '/tmp/cartola.xls'; $file->moveTo($filename); - $reader = PhpSpreadsheet\IOFactory::createReader('Xls'); - $xlsx = $reader->load($filename); + $xlsx = @PhpSpreadsheet\IOFactory::load($filename); $worksheet = $xlsx->getActiveSheet(); - $rows = $worksheet->getRowIterator(); + $rows = $worksheet->getRowIterator(3); $dataFound = false; $columns = []; $data = []; @@ -44,10 +45,10 @@ class Security extends Banco $cells = $row->getCellIterator(); $rowData = []; foreach ($cells as $cell) { - if ($cell->getColumn() === 'A' and $cell->getCalculatedValue() === "fecha ") { + if ($cell->getColumn() === 'A' and $cell->getCalculatedValue() !== null and strtolower($cell->getCalculatedValue()) === "fecha ") { $cols = $row->getColumnIterator(); foreach ($cols as $col) { - $columns[$col->getColumn()] = trim($col->getCalculatedValue()); + $columns[$col->getColumn()] = trim(strtolower($col->getCalculatedValue()), '  '); } $dataFound = true; break; @@ -62,7 +63,11 @@ class Security extends Banco $col = $columns[$cell->getColumn()]; $value = $cell->getCalculatedValue(); if ($col === 'fecha') { - $value = PhpSpreadsheet\Shared\Date::excelToDateTimeObject($cell->getValue(), 'America/Santiago')->format('Y-m-d'); + if ((int) $cell->getValue() !== $cell->getValue()) { + $value = implode('-', array_reverse(explode('-', $cell->getValue()))); + } else { + $value = PhpSpreadsheet\Shared\Date::excelToDateTimeObject($cell->getValue(), 'America/Santiago')->format('Y-m-d'); + } } $rowData[$col] = $value; }