diff --git a/.gitignore b/.gitignore
index 94a1003..1646ae8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
**/cache/
**/modules/
**/.idea/
+**/upload?/
diff --git a/app/common/Define/Cartola/Banco.php b/app/common/Define/Cartola/Banco.php
new file mode 100644
index 0000000..2a23f06
--- /dev/null
+++ b/app/common/Define/Cartola/Banco.php
@@ -0,0 +1,9 @@
+group('/cartolas', function($app) {
+ $app->post('/procesar[/]', [Contabilidad::class, 'procesarCartola']);
+});
+$app->group('/cartola', function($app) {
+ $app->post('/exportar[/]', [Contabilidad::class, 'exportarCartola']);
+});
diff --git a/app/resources/routes/api/contabilidad/nubox.php b/app/resources/routes/api/contabilidad/nubox.php
new file mode 100644
index 0000000..e1acbf9
--- /dev/null
+++ b/app/resources/routes/api/contabilidad/nubox.php
@@ -0,0 +1,11 @@
+group('/nubox/{inmobiliaria_rut}', function($app) {
+ $app->get('/token[/]', [Nubox::class, 'token']);
+ $app->get('/sistemas[/]', [Nubox::class, 'sistemas']);
+ $app->group('/libro', function($app) {
+ $app->post('/mayor[/]', [Nubox::class, 'libroMayor']);
+ $app->post('/diario[/]', [Nubox::class, 'libroDiario']);
+ });
+});
diff --git a/app/resources/routes/api/inmobiliarias.php b/app/resources/routes/api/inmobiliarias.php
new file mode 100644
index 0000000..55c61fb
--- /dev/null
+++ b/app/resources/routes/api/inmobiliarias.php
@@ -0,0 +1,10 @@
+group('/inmobiliarias', function($app) {
+ $app->get('[/]', Inmobiliarias::class);
+});
+$app->group('/inmobiliaria/{inmobiliaria_rut}', function($app) {
+ $app->get('/cuentas[/]', [Inmobiliarias::class, 'cuentas']);
+ $app->get('/proyectos[/]', [Inmobiliarias::class, 'proyectos']);
+});
diff --git a/app/resources/routes/contabilidad/centros_costos.php b/app/resources/routes/contabilidad/centros_costos.php
index 8af10b3..d1089a4 100644
--- a/app/resources/routes/contabilidad/centros_costos.php
+++ b/app/resources/routes/contabilidad/centros_costos.php
@@ -2,5 +2,6 @@
use Incoviba\Controller\CentrosCostos;
$app->group('/centros_costos', function($app) {
+ $app->get('/asignar[/]', [CentrosCostos::class, 'asignar']);
$app->get('[/]', CentrosCostos::class);
});
diff --git a/app/resources/views/contabilidad/centros_costos/asignar.blade.php b/app/resources/views/contabilidad/centros_costos/asignar.blade.php
new file mode 100644
index 0000000..2cf50c2
--- /dev/null
+++ b/app/resources/views/contabilidad/centros_costos/asignar.blade.php
@@ -0,0 +1,402 @@
+@extends('layout.base')
+
+@section('page_content')
+
+
+
+
+
+ Fecha |
+ Glosa |
+ Documento |
+ Cargo |
+ Abono |
+ Saldo |
+ Centro de Costo |
+ Detalle |
+ Orden |
+
+
+
+
+
+@endsection
+
+@include('layout.head.styles.datatables')
+@include('layout.body.scripts.datatables')
+
+@push('page_scripts')
+
+@endpush
diff --git a/app/setup/settings/folders.php b/app/setup/settings/folders.php
index 67694f4..e4d1e05 100644
--- a/app/setup/settings/folders.php
+++ b/app/setup/settings/folders.php
@@ -6,7 +6,9 @@ return [
'resources' => DI\String('{base}/resources'),
'routes' => DI\String('{resources}/routes'),
'cache' => DI\String('{base}/cache'),
- 'templates' => DI\String('{resources}/views')
+ 'templates' => DI\String('{resources}/views'),
+ 'public' => DI\String('{base}/public'),
+ 'uploads' => DI\String('{public}/uploads')
]);
}
];
diff --git a/app/setup/settings/nubox.php b/app/setup/settings/nubox.php
new file mode 100644
index 0000000..382f46b
--- /dev/null
+++ b/app/setup/settings/nubox.php
@@ -0,0 +1,8 @@
+ function() {
+ return new DI\Container([
+ 'url' => 'https://api.nubox.com/Nubox.API'
+ ]);
+ }
+];
diff --git a/app/setup/setups/psr7.php b/app/setup/setups/psr7.php
index af7ff76..7e86808 100644
--- a/app/setup/setups/psr7.php
+++ b/app/setup/setups/psr7.php
@@ -2,7 +2,13 @@
use Psr\Container\ContainerInterface;
return [
+ Psr\Http\Message\StreamFactoryInterface::class => function(ContainerInterface $container) {
+ return $container->get(Nyholm\Psr7\Factory\Psr17Factory::class);
+ },
+ Psr\Http\Message\RequestFactoryInterface::class => function(ContainerInterface $container) {
+ return $container->get(Nyholm\Psr7\Factory\Psr17Factory::class);
+ },
Psr\Http\Message\ResponseFactoryInterface::class => function(ContainerInterface $container) {
return $container->get(Nyholm\Psr7\Factory\Psr17Factory::class);
- }
+ },
];
diff --git a/app/setup/setups/services.php b/app/setup/setups/services.php
index 9ba91f9..8b2b709 100644
--- a/app/setup/setups/services.php
+++ b/app/setup/setups/services.php
@@ -1,4 +1,5 @@
$container->get('REDIS_HOST'),
'port' => $container->get('REDIS_PORT')
]);
+ },
+ Incoviba\Service\Cartola::class => function(ContainerInterface $container) {
+ return (new Incoviba\Service\Cartola(
+ $container->get(Psr\Http\Message\StreamFactoryInterface::class),
+ $container->get(Incoviba\Common\Define\Contabilidad\Exporter::class)
+ ))->register('security', $container->get(Incoviba\Service\Cartola\Security::class));
+ },
+ Incoviba\Common\Define\Contabilidad\Exporter::class => function(ContainerInterface $container) {
+ return $container->get(Incoviba\Service\Contabilidad\Exporter\Nubox::class);
+ },
+ Incoviba\Service\Contabilidad\Exporter\Nubox::class => function(ContainerInterface $container) {
+ return new Incoviba\Service\Contabilidad\Exporter\Nubox($container->get(Incoviba\Repository\CentroCosto::class),
+ $container->get('folders')->get('uploads'));
+ },
+ Incoviba\Service\Contabilidad\Nubox::class => function(ContainerInterface $container) {
+ return new Incoviba\Service\Contabilidad\Nubox(
+ $container->get(Incoviba\Repository\Nubox::class),
+ $container->get(Incoviba\Service\Redis::class),
+ new GuzzleHttp\Client(),
+ $container->get(Psr\Http\Message\RequestFactoryInterface::class),
+ $container->get('nubox')->get('url'));
}
];
diff --git a/app/src/Controller/API/Contabilidad.php b/app/src/Controller/API/Contabilidad.php
new file mode 100644
index 0000000..bf35b84
--- /dev/null
+++ b/app/src/Controller/API/Contabilidad.php
@@ -0,0 +1,52 @@
+getParsedBody();
+ $output = [
+ 'input' => $body,
+ 'movimientos' => []
+ ];
+ try {
+ $inmobiliaria = $inmobiliariaRepository->fetchById($body['inmobiliaria']);
+ $banco = $bancoRepository->fetchById($body['banco']);
+ $mes = new DateTimeImmutable($body['mes']);
+ $file = $request->getUploadedFiles()['file'];
+ $output['movimientos'] = $cartolaService->process($inmobiliaria, $banco, $mes, $file);
+ } catch (EmptyResult) {}
+ return $this->withJson($response, $output);
+ }
+ public function exportarCartola(ServerRequestInterface $request, ResponseInterface $response,
+ Repository\Inmobiliaria $inmobiliariaRepository,
+ Repository\Banco $bancoRepository,
+ Service\Cartola $cartolaService): ResponseInterface
+ {
+ $body = $request->getParsedBody();
+ $output = [
+ 'input' => $body,
+ 'filename' => ''
+ ];
+ try {
+ $inmobiliaria = $inmobiliariaRepository->fetchById($body['inmobiliaria']);
+ $banco = $bancoRepository->fetchById($body['banco']);
+ $mes = new DateTimeImmutable($body['mes']);
+ $output['filename'] = $cartolaService->export($inmobiliaria, $banco, $mes, json_decode($body['movimientos']));
+ } catch (EmptyResult) {}
+ return $this->withJson($response, $output);
+ }
+}
diff --git a/app/src/Controller/API/Informes.php b/app/src/Controller/API/Informes.php
new file mode 100644
index 0000000..5e06ea1
--- /dev/null
+++ b/app/src/Controller/API/Informes.php
@@ -0,0 +1,25 @@
+getParsedBody();
+ $output = [
+ 'input' => $body,
+ 'data' => []
+ ];
+ try {
+ $file = $request->getUploadedFiles()['file'];
+ $output['data'] = $diarioService->process($file);
+ } catch (\Error) {}
+ return $this->withJson($response, $output);
+ }
+}
diff --git a/app/src/Controller/API/Inmobiliarias.php b/app/src/Controller/API/Inmobiliarias.php
new file mode 100644
index 0000000..273e49d
--- /dev/null
+++ b/app/src/Controller/API/Inmobiliarias.php
@@ -0,0 +1,48 @@
+ $inmobiliaria_rut,
+ 'cuentas' => []
+ ];
+ try {
+ $inmobiliaria = $inmobiliariaRepository->fetchById($inmobiliaria_rut);
+ $output['cuentas'] = $cuentaRepository->fetchByInmobiliaria($inmobiliaria->rut);
+ } catch (EmptyResult) {}
+ return $this->withJson($response, $output);
+ }
+ public function proyectos(ServerRequestInterface $request, ResponseInterface $response,
+ Repository\Inmobiliaria $inmobiliariaRepository,
+ Service\Proyecto $proyectoService, int $inmobiliaria_rut): ResponseInterface
+ {
+ $output = [
+ 'inmobiliaria_rut' => $inmobiliaria_rut,
+ 'proyectos' => []
+ ];
+ try {
+ $inmobiliaria = $inmobiliariaRepository->fetchById($inmobiliaria_rut);
+ $output['proyectos'] = array_map(function(Model\Proyecto $proyecto) {
+ $p = json_decode(json_encode($proyecto));
+ $p->current_estado = $proyecto->currentEstado();
+ $p->estados = $proyecto->estados();
+ return $p;
+ },$proyectoService->getByInmobiliaria($inmobiliaria->rut));
+ } catch (EmptyResult) {}
+ return $this->withJson($response, $output);
+ }
+}
diff --git a/app/src/Controller/API/Nubox.php b/app/src/Controller/API/Nubox.php
new file mode 100644
index 0000000..cc1d323
--- /dev/null
+++ b/app/src/Controller/API/Nubox.php
@@ -0,0 +1,90 @@
+ $inmobiliaria_rut,
+ 'token' => ''
+ ];
+ try {
+ $output['token'] = $nuboxService->getToken($inmobiliaria_rut);
+ } catch (HttpResponse $exception) {
+ $output['error'] = [
+ 'code' => $exception->getCode(),
+ 'message' => $exception->getMessage()
+ ];
+ }
+ return $this->withJson($response, $output);
+ }
+ public function sistemas(ServerRequestInterface $request, ResponseInterface $response,
+ Service\Contabilidad\Nubox $nuboxService, int $inmobiliaria_rut): ResponseInterface
+ {
+ $output = [
+ 'inmobiliaria_rut' => $inmobiliaria_rut,
+ 'sistemas' => []
+ ];
+ try {
+ $output['sistemas'] = $nuboxService->getSistemas($inmobiliaria_rut);
+ } catch (HttpResponse $exception) {
+ $output['error'] = [
+ 'code' => $exception->getCode(),
+ 'message' => $exception->getMessage()
+ ];
+ }
+ return $this->withJson($response, $output);
+ }
+ public function libroMayor(ServerRequestInterface $request, ResponseInterface $response,
+ Service\Contabilidad\Nubox $nuboxService, int $inmobiliaria_rut): ResponseInterface
+ {
+ $body = $request->getParsedBody();
+ $output = [
+ 'inmobiliaria_rut' => $inmobiliaria_rut,
+ 'input' => $body,
+ 'libro_mayor' => []
+ ];
+ try {
+ $from = new DateTimeImmutable($body['inicio']);
+ $to = new DateTimeImmutable($body['termino']);
+ $output['libro_mayor'] = $nuboxService->getLibroMayor($inmobiliaria_rut, $from, $to);
+ } catch (HttpResponse $exception) {
+ $output['error'] = [
+ 'code' => $exception->getCode(),
+ 'message' => $exception->getMessage()
+ ];
+ }
+ return $this->withJson($response, $output);
+ }
+ public function libroDiario(ServerRequestInterface $request, ResponseInterface $response,
+ Service\Contabilidad\Nubox $nuboxService, int $inmobiliaria_rut): ResponseInterface
+ {
+ $body = $request->getParsedBody();
+ $output = [
+ 'inmobiliaria_rut' => $inmobiliaria_rut,
+ 'input' => $body,
+ 'libro_diario' => []
+ ];
+ try {
+ $from = new DateTimeImmutable($body['inicio']);
+ $to = new DateTimeImmutable($body['termino']);
+ $output['libro_diario'] = $nuboxService->getLibroDiario($inmobiliaria_rut, $from, $to);
+ } catch (HttpResponse $exception) {
+ $output['error'] = [
+ 'code' => $exception->getCode(),
+ 'message' => $exception->getMessage()
+ ];
+ }
+ return $this->withJson($response, $output);
+ }
+}
diff --git a/app/src/Controller/API/Proyectos.php b/app/src/Controller/API/Proyectos.php
index 616b6eb..dc5e46f 100644
--- a/app/src/Controller/API/Proyectos.php
+++ b/app/src/Controller/API/Proyectos.php
@@ -155,4 +155,19 @@ class Proyectos
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
+ public function tiposUnidades(ServerRequestInterface $request, ResponseInterface $response,
+ Repository\Proyecto $proyectoRepository,
+ Repository\Proyecto\TipoUnidad $tipoUnidadRepository,
+ int $proyecto_id): ResponseInterface
+ {
+ $output = [
+ 'proyecto_id' => $proyecto_id,
+ 'tipos' => []
+ ];
+ try {
+ $proyecto = $proyectoRepository->fetchById($proyecto_id);
+ $output['tipos'] = $tipoUnidadRepository->fetchByProyecto($proyecto->id);
+ } catch (EmptyResult) {}
+ return $this->withJson($response, $output);
+ }
}
diff --git a/app/src/Controller/CentrosCostos.php b/app/src/Controller/CentrosCostos.php
index 13fb89a..6854b8b 100644
--- a/app/src/Controller/CentrosCostos.php
+++ b/app/src/Controller/CentrosCostos.php
@@ -21,4 +21,12 @@ class CentrosCostos
return $view->render($response, 'contabilidad.centros_costos', compact('centrosCostos',
'tiposCentros', 'categorias', 'tiposCuentas'));
}
+ public function asignar(ServerRequestInterface $request, ResponseInterface $response, View $view,
+ Repository\CentroCosto $centroCostoRepository,
+ Repository\Inmobiliaria $inmobiliariaRepository): ResponseInterface
+ {
+ $centrosCostos = $centroCostoRepository->fetchAll();
+ $inmobiliarias = $inmobiliariaRepository->fetchAllActive('razon');
+ return $view->render($response, 'contabilidad.centros_costos.asignar', compact('centrosCostos', 'inmobiliarias'));
+ }
}
diff --git a/app/src/Model/Nubox.php b/app/src/Model/Nubox.php
new file mode 100644
index 0000000..05b223a
--- /dev/null
+++ b/app/src/Model/Nubox.php
@@ -0,0 +1,18 @@
+usuario, $this->password]));
+ }
+}
diff --git a/app/src/Repository/Inmobiliaria.php b/app/src/Repository/Inmobiliaria.php
index 9b4af20..decedf3 100644
--- a/app/src/Repository/Inmobiliaria.php
+++ b/app/src/Repository/Inmobiliaria.php
@@ -46,4 +46,20 @@ class Inmobiliaria extends Ideal\Repository
{
return $this->update($model, ['dv', 'razon', 'abreviacion', 'cuenta', 'banco', 'sociedad'], $new_data);
}
+
+ public function fetchAllActive(null|string|array $sorting = null): array
+ {
+ $query = $this->connection->getQueryBuilder()
+ ->select('a.*')
+ ->from("{$this->getTable()} a")
+ ->joined('JOIN proyecto ON a.rut = proyecto.inmobiliaria')
+ ->joined('JOIN (SELECT ep1.* FROM estado_proyecto ep1 JOIN (SELECT MAX(id) AS id, proyecto FROM estado_proyecto GROUP BY proyecto) ep0 ON ep0.id = ep1.id) ep ON ep.proyecto = proyecto.id')
+ ->joined('JOIN tipo_estado_proyecto tep ON tep.id = ep.estado')
+ ->joined('JOIN etapa_proyecto ON etapa_proyecto.id = tep.etapa')
+ ->where('etapa_proyecto.orden BETWEEN ? AND ?');
+ if ($sorting !== null) {
+ $query->order($sorting);
+ }
+ return $this->fetchMany($query, [1, 8]);
+ }
}
diff --git a/app/src/Repository/Inmobiliaria/Cuenta.php b/app/src/Repository/Inmobiliaria/Cuenta.php
new file mode 100644
index 0000000..71e3b5d
--- /dev/null
+++ b/app/src/Repository/Inmobiliaria/Cuenta.php
@@ -0,0 +1,52 @@
+setTable('cuenta');
+ }
+
+ public function create(?array $data = null): Model\Inmobiliaria\Cuenta
+ {
+ $map = (new Implement\Repository\MapperParser(['cuenta']))
+ ->register('inmobiliaria', (new Implement\Repository\Mapper())
+ ->setFunction(function(array $data) {
+ return $this->inmobiliariaRepository->fetchById($data['inmobiliaria']);
+ }))
+ ->register('banco', (new Implement\Repository\Mapper())
+ ->setFunction(function(array $data) {
+ return $this->bancoRepository->fetchById($data['banco']);
+ }));
+ return $this->parseData(new Model\Inmobiliaria\Cuenta(), $data, $map);
+ }
+ public function save(Define\Model $model): Model\Inmobiliaria\Cuenta
+ {
+ $model->id = $this->saveNew(['inmobiliaria', 'banco', 'cuenta'],
+ [$model->inmobiliaria->rut, $model->banco->id, $model->cuenta]);
+ return $model;
+ }
+ public function edit(Define\Model $model, array $new_data): Model\Inmobiliaria\Cuenta
+ {
+ return $this->update($model, ['inmobiliaria', 'banco', 'cuenta'], $new_data);
+ }
+
+ public function fetchByInmobiliaria(int $inmobiliaria_rut): array
+ {
+ $query = $this->connection->getQueryBuilder()
+ ->select()
+ ->from($this->getTable())
+ ->where('inmobiliaria = ?');
+ return $this->fetchMany($query, [$inmobiliaria_rut]);
+ }
+}
diff --git a/app/src/Repository/Nubox.php b/app/src/Repository/Nubox.php
new file mode 100644
index 0000000..3f91268
--- /dev/null
+++ b/app/src/Repository/Nubox.php
@@ -0,0 +1,55 @@
+setTable('inmobiliarias_nubox');
+ }
+
+ public function create(?array $data = null): Model\Nubox
+ {
+ $map = (new Implement\Repository\MapperParser(['usuario', 'alias']))
+ ->register('inmobiliaria_rut', (new Implement\Repository\Mapper())
+ ->setProperty('inmobiliaria')
+ ->setFunction(function(array $data) {
+ return $this->inmobiliariaRepository->fetchById($data['inmobiliaria_rut']);
+ }))
+ ->register('contraseña', (new Implement\Repository\Mapper())
+ ->setProperty('password'));
+ return $this->parseData(new Model\Nubox(), $data, $map);
+ }
+ public function save(Define\Model $model): Model\Nubox
+ {
+ $this->saveNew(
+ ['inmobiliaria_rut', 'alias', 'usuario', 'contraseña'],
+ [$model->inmobiliaria->rut, $model->alias, $model->usuario, $model->password]
+ );
+ return $model;
+ }
+ public function edit(Define\Model $model, array $new_data): Model\Nubox
+ {
+ return $this->update($model, ['inmobiliaria_rut', 'alias', 'usuario', 'contraseña'], $new_data);
+ }
+
+ public function fetchByInmobiliaria(int $inmobiliaria_rut): Model\Nubox
+ {
+ $query = $this->connection->getQueryBuilder()
+ ->select()
+ ->from($this->getTable())
+ ->where('inmobiliaria_rut = ?');
+ return $this->fetchOne($query, [$inmobiliaria_rut]);
+ }
+
+ protected function getKey(): string
+ {
+ return 'inmobiliaria_rut';
+ }
+}
diff --git a/app/src/Service/Cartola.php b/app/src/Service/Cartola.php
new file mode 100644
index 0000000..231ba7a
--- /dev/null
+++ b/app/src/Service/Cartola.php
@@ -0,0 +1,29 @@
+bancos[$name] = $banco;
+ return $this;
+ }
+ public function process(Model\Inmobiliaria $inmobiliaria, Model\Banco $banco, DateTimeInterface $mes, UploadedFileInterface $file): array
+ {
+ return $this->bancos[strtolower($banco->nombre)]->process($file);
+ }
+ public function export(Model\Inmobiliaria $inmobiliaria, Model\Banco $banco, DateTimeInterface $mes, array $movimientos): string
+ {
+ return $this->exporter->export($inmobiliaria, $banco, $mes, $movimientos);
+ }
+}
diff --git a/app/src/Service/Cartola/Security.php b/app/src/Service/Cartola/Security.php
new file mode 100644
index 0000000..9df63d0
--- /dev/null
+++ b/app/src/Service/Cartola/Security.php
@@ -0,0 +1,54 @@
+moveTo($filename);
+ $xlsx = $reader->load($filename);
+ $worksheet = $xlsx->getActiveSheet();
+ $rows = $worksheet->getRowIterator();
+ $dataFound = false;
+ $columns = [];
+ $data = [];
+ foreach ($rows as $row) {
+ $cells = $row->getCellIterator();
+ $rowData = [];
+ foreach ($cells as $cell) {
+ if ($cell->getColumn() === 'A' and $cell->getCalculatedValue() === "fecha ") {
+ $cols = $row->getColumnIterator();
+ foreach ($cols as $col) {
+ $columns[$col->getColumn()] = trim($col->getCalculatedValue());
+ }
+ $dataFound = true;
+ break;
+ }
+ if ($cell->getColumn() === 'A' and $cell->getCalculatedValue() === null) {
+ $dataFound = false;
+ break;
+ }
+ if (!$dataFound) {
+ break;
+ }
+ $col = $columns[$cell->getColumn()];
+ $value = $cell->getCalculatedValue();
+ if ($col === 'fecha') {
+ $value = PhpSpreadsheet\Shared\Date::excelToDateTimeObject($cell->getValue(), 'America/Santiago')->format('Y-m-d');
+ }
+ $rowData[$col] = $value;
+ }
+ if (count($rowData) > 0) {
+ $data []= $rowData;
+ }
+ }
+ unlink($filename);
+ return $data;
+ }
+}
diff --git a/app/src/Service/Contabilidad/Exporter/Nubox.php b/app/src/Service/Contabilidad/Exporter/Nubox.php
new file mode 100644
index 0000000..ba32e09
--- /dev/null
+++ b/app/src/Service/Contabilidad/Exporter/Nubox.php
@@ -0,0 +1,115 @@
+getActiveSheet();
+
+ $rowIndex = $this->buildHeaders($sheet);
+
+ foreach ($movimientos as $movimiento) {
+ $tipoCentro = '';
+ $cuenta = '';
+ $centro = '';
+ if ($movimiento->centro_costo !== '') {
+ $centroCosto = $this->centroCostoRepository->fetchById($movimiento->centro_costo);
+ $tipoCentro = substr($centroCosto->tipoCentro->descripcion, 0, 1);
+ $cuenta = $centroCosto->cuentaContable;
+ $centro = $centroCosto->id;
+ }
+ $fecha = (new DateTimeImmutable($movimiento->fecha))->format('d/m/Y');
+ $rowIndex = $this->add($sheet, [
+ 'Número' => '0',
+ 'Tipo' => $tipoCentro,
+ 'Fecha' => $fecha,
+ 'Glosa' => $movimiento->detalle,
+ 'Cuenta Detalle' => $cuenta,
+ 'Glosa Detalle' => '',
+ 'Centro Costo' => $centro,
+ 'Sucursal' => '',
+ 'Debe' => $movimiento->abono === 0 ? '' : $movimiento->abono,
+ 'Haber' => $movimiento->cargo === 0 ? '' : $movimiento->cargo,
+ 'Tipo Auxiliar' => 'B',
+ 'A: Rut Cliente-Proveedor/H: Rut Prestador' => '',
+ 'A: Razon Social/B: Descripción Movimiento Bancario/ H: Nombre Prestador' => $movimiento->glosa,
+ 'A: Tipo De Documento/H: Tipo De Boleta Honorario' => '',
+ 'A: Folio /B: Numero Documento/H: Folio Boleta' => $movimiento->documento,
+ 'A/B/H: Monto' => ($movimiento->abono === 0) ? $movimiento->cargo : $movimiento->abono,
+ 'A: Fecha Vencimiento /B: Fecha /H: Fecha Emisión (DD/MM/AAAA)' => $fecha
+ ], $rowIndex);
+ }
+ $sheet->getStyle("I1:J{$rowIndex}")->getNumberFormat()
+ ->setFormatCode('#,##0');
+ $sheet->getStyle("O1:O{$rowIndex}")->getNumberFormat()
+ ->setFormatCode('##0');
+ $sheet->getStyle("P1:P{$rowIndex}")->getNumberFormat()
+ ->setFormatCode('#,##0');
+ foreach (range('A', 'Q') as $col) {
+ $sheet->getColumnDimension($col)->setAutoSize(true);
+ }
+ $sheet->getSheetView()->setZoomScale(90);
+
+ $writer = PhpSpreadsheet\IOFactory::createWriter($workbook, 'Xlsx');
+ $filename = "Cartola {$banco->nombre} - {$inmobiliaria->abreviacion} - {$mes->format('M Y')}.xlsx";
+ $writer->save(implode(DIRECTORY_SEPARATOR, [
+ $this->uploadFolder,
+ $filename
+ ]));
+ return $filename;
+ }
+
+ protected function getHeaders(): array
+ {
+ return [
+ 'Número',
+ 'Tipo',
+ 'Fecha',
+ 'Glosa',
+ 'Cuenta Detalle',
+ 'Glosa Detalle',
+ 'Centro Costo',
+ 'Sucursal',
+ 'Debe',
+ 'Haber',
+ 'Tipo Auxiliar',
+ 'A: Rut Cliente-Proveedor/H: Rut Prestador',
+ 'A: Razon Social/B: Descripción Movimiento Bancario/ H: Nombre Prestador',
+ 'A: Tipo De Documento/H: Tipo De Boleta Honorario',
+ 'A: Folio /B: Numero Documento/H: Folio Boleta',
+ 'A/B/H: Monto',
+ 'A: Fecha Vencimiento /B: Fecha /H: Fecha Emisión (DD/MM/AAAA)'
+ ];
+ }
+ protected function buildHeaders(PhpSpreadsheet\Worksheet\Worksheet &$sheet, int $rowIndex = 1): int
+ {
+ $map = $this->getHeaders();
+ foreach ($map as $index => $header) {
+ $columnIndex = $index + 1;
+ $sheet->getCell([$columnIndex, $rowIndex])->setValue($header);
+ }
+ return $rowIndex + 1;
+ }
+ protected function add(PhpSpreadsheet\Worksheet\Worksheet &$sheet, array $row, int $rowIndex): int
+ {
+ $headers = $this->getHeaders();
+ foreach ($headers as $index => $header) {
+ $columnIndex = $index + 1;
+ $sheet->getCell([$columnIndex, $rowIndex])->setValue($row[$header]);
+ $sheet->getCell([$columnIndex, $rowIndex + 1])->setValue(($header === 'Tipo Auxiliar') ? 'A' : '');
+ }
+ return $rowIndex + 2;
+ }
+}
diff --git a/app/src/Service/Contabilidad/Nubox.php b/app/src/Service/Contabilidad/Nubox.php
new file mode 100644
index 0000000..01b432a
--- /dev/null
+++ b/app/src/Service/Contabilidad/Nubox.php
@@ -0,0 +1,139 @@
+tokens[$inmobiliaria_rut])) {
+ $redisKey = "token_nubox:{$inmobiliaria_rut}";
+ try {
+ $this->tokens[$inmobiliaria_rut] = $this->redisService->get($redisKey);
+ } catch (Exception\EmptyRedis) {
+ $nubox = $this->nuboxRepository->fetchByInmobiliaria($inmobiliaria_rut);
+ $request = $this->requestFactory
+ ->createRequest('POST', implode('/', [$this->api_url, 'autenticar']))
+ ->withHeader('Authorization', "Basic {$nubox->getLogin()}")
+ ->withHeader('Content-Type', 'application/json')
+ ->withHeader('Accept', 'application/json');
+ $response = $this->client->sendRequest($request);
+ if ($response->getStatusCode() !== 200) {
+ throw new Exception\HttpResponse($response->getReasonPhrase(), $response->getStatusCode());
+ }
+ $sistemas = json_decode($response->getBody()->getContents(), JSON_OBJECT_AS_ARRAY);
+
+ $this->setToken($inmobiliaria_rut, $response->getHeaderLine('Token'))
+ ->setSistemas($inmobiliaria_rut, $sistemas['Sistemas']);
+ }
+ }
+ return $this->tokens[$inmobiliaria_rut];
+ }
+ public function setToken(int $inmobiliaria_rut, string $token): Nubox
+ {
+ $this->tokens[$inmobiliaria_rut] = $token;
+
+ $redisKey = "token_nubox:{$inmobiliaria_rut}";
+ $this->redisService->set($redisKey, $this->tokens[$inmobiliaria_rut], 60 * 15);
+
+ return $this;
+ }
+
+ protected array $sistemas;
+ public function getSistemas(int $inmobiliaria_rut): array
+ {
+ if (!isset($this->sistemas[$inmobiliaria_rut])) {
+ $redisKey = "nubox:{$inmobiliaria_rut}";
+ $this->sistemas[$inmobiliaria_rut] = json_decode($this->redisService->get($redisKey));
+ }
+ return $this->sistemas[$inmobiliaria_rut];
+ }
+ public function setSistemas(int $inmobiliaria_rut, array $sistemas): Nubox
+ {
+ $this->sistemas[$inmobiliaria_rut] = $sistemas;
+
+ $redisKey = "nubox:{$inmobiliaria_rut}";
+ $this->redisService->set($redisKey, json_encode($sistemas));
+
+ return $this;
+ }
+
+ public function getLibroMayor(int $inmobiliaria_rut, DateTimeInterface $from, DateTimeInterface $to): array
+ {
+ $inmobiliaria = $this->nuboxRepository->fetchByInmobiliaria($inmobiliaria_rut);
+ $query = [
+ 'NumeroSerie' => 1,
+ 'CodigoEmpresa' => $inmobiliaria->alias,
+ 'DDInicio' => $from->format('j'),
+ 'MMInicio' => $from->format('n'),
+ 'YYInicio' => $from->format('Y'),
+ 'DDTermino' => $to->format('j'),
+ 'MMTermino' => $to->format('n'),
+ 'YYTermino' => $to->format('Y'),
+ 'CodigoCentroDeCosto' => 0,
+ 'CodigoSucursal' => 0,
+ 'CodigoCuenta' => 0,
+ 'ModoIFRS' => 'false',
+ 'CuentasConSaldo' => 'false',
+ 'IncluirCodigoCuenta' => 'true',
+ ];
+ $uri = 'contabilidad/libro-mayor?' . http_build_query($query);
+ $response = $this->send($uri, $inmobiliaria_rut);
+ if ($response->getStatusCode() !== 200) {
+ throw new Exception\HttpResponse($response->getReasonPhrase(), $response->getStatusCode());
+ }
+ return json_decode($response->getBody()->getContents(), JSON_OBJECT_AS_ARRAY);
+ }
+ public function getLibroDiario(int $inmobiliaria_rut, DateTimeInterface $from, DateTimeInterface $to): array
+ {
+ $inmobiliaria = $this->nuboxRepository->fetchByInmobiliaria($inmobiliaria_rut);
+ $query = [
+ 'ModoIFRS' => 0,
+ 'DDInicio' => $from->format('j'),
+ 'MMInicio' => $from->format('n'),
+ 'YYInicio' => $from->format('Y'),
+ 'DDTermino' => $to->format('j'),
+ 'MMTermino' => $to->format('n'),
+ 'YYTermino' => $to->format('Y'),
+ 'Sucursal' => 0,
+ 'codigoEmpresa' => $inmobiliaria->alias,
+ 'NumeroSerie' => 1,
+ 'CuentasConSaldo' => 0,
+ 'incluirCodigoCuenta' => 1
+ ];
+ $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');
+ throw new Exception\HttpResponse($response->getReasonPhrase(), $response->getStatusCode());
+ }
+ return json_decode($response->getBody()->getContents(), JSON_OBJECT_AS_ARRAY);
+ }
+
+ private function send(string $uri, int $inmobiliaria_rut, string $method = 'GET', ?StreamInterface $body = null): ResponseInterface
+ {
+ $request = $this->requestFactory
+ ->createRequest($method, implode('/', [$this->api_url, $uri]))
+ ->withHeader('token', $this->getToken($inmobiliaria_rut));
+ if ($body !== null) {
+ $request = $request->withBody($body);
+ }
+ return $this->client->sendRequest($request);
+ }
+}