Informe tesoreria en excel

This commit is contained in:
Juan Pablo Vial
2024-02-23 22:37:09 -03:00
parent 5156858205
commit cfe18c1909
14 changed files with 809 additions and 131 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@
**/modules/ **/modules/
**/.idea/ **/.idea/
**/upload?/ **/upload?/
**/informe?/

View File

@ -0,0 +1,10 @@
<?php
namespace Incoviba\Common\Define;
interface Informe
{
public function setTitle(string $title): Informe;
public function setFilename(string $filename): Informe;
public function addData(array $rows): Informe;
public function build(): void;
}

View File

View File

@ -0,0 +1,6 @@
<?php
use Incoviba\Controller\Contabilidad\Informes;
$app->group('/xlsx', function($app) {
$app->get('/tesoreria/{fecha}[/]', [Informes::class, 'tesoreria']);
});

View File

@ -4,144 +4,153 @@
<div class="ui container"> <div class="ui container">
<h1 class="ui centered header">Informe de Tesorería</h1> <h1 class="ui centered header">Informe de Tesorería</h1>
<h4 class="ui centered sub header">{{$fecha->format('d M Y')}}</h4> <h4 class="ui centered sub header">{{$fecha->format('d M Y')}}</h4>
</div>
<div class="ui grid"> <div class="ui grid">
<div class="four wide column"> <div class="three wide column">
<table class="ui collapsing simple table"> <a href="/contabilidad/informes/xlsx/tesoreria/{{$fecha->format('Y-m-d')}}" target="_blank" style="color: inherit;">
<tr> <div class="ui inverted green center aligned segment">
<td>Informe anterior</td> Descargar en Excel <i class="file excel icon"></i>
<td>{{$anterior->format('d/m/Y')}}</td> </div>
</tr> </a>
<tr>
<td>Informe actual</td>
<td>{{$fecha->format('d/m/Y')}}</td>
</tr>
</table>
</div>
<div class="column"></div>
<div class="four wide column">
<table class="ui collapsing simple table">
<tr>
<td>Valor UF</td>
<td class="right aligned">{{$format->pesos($UF->get($fecha), 2)}}</td>
</tr>
<tr>
<td>Valor Dólar</td>
<td class="right aligned">{{$format->pesos($USD->get($fecha), 2)}}</td>
</tr>
</table>
</div> </div>
</div> </div>
<table class="ui striped table"> </div>
<thead> <div class="ui grid">
<tr> <div class="four wide column">
<th>EMPRESA</th> <table class="ui collapsing simple table">
<th>Banco</th>
<th>Cuenta</th>
<th class="right aligned">Saldo Anterior</th>
<th class="right aligned">Saldo Actual</th>
<th class="right aligned">Diferencia</th>
<th class="right aligned">FFMM</th>
<th class="right aligned">DAP</th>
<th class="right aligned">Saldo Empresa</th>
<th class="right aligned">Total Cuentas</th>
<th class="right aligned">Total FFMM</th>
<th class="right aligned">Total DAP</th>
<th class="right aligned">Caja Total</th>
</tr>
</thead>
<tbody>
@foreach ($informes['inmobiliarias'] as $inmobiliaria_rut => $informe)
@foreach ($informe->cuentas as $i => $cuenta)
<tr> <tr>
@if ($i === 0) <td>Informe anterior</td>
<td rowspan="{{count($informe->cuentas)}}">{{$informe->inmobiliaria->razon}}</td> <td>{{$anterior->format('d/m/Y')}}</td>
@endif
<td>{{$cuenta->banco}}</td>
<td>{{$cuenta->numero}}</td>
<td class="right aligned">{{$format->pesos($cuenta->anterior)}}</td>
<td class="right aligned">{{$format->pesos($cuenta->actual)}}</td>
<td class="right aligned">{{$format->pesos($cuenta->diferencia())}}</td>
<td class="right aligned">{{$format->pesos($cuenta->ffmm)}}</td>
<td class="right aligned">{{$format->pesos($cuenta->deposito)}}</td>
<td class="right aligned">{{$format->pesos($cuenta->saldo())}}</td>
@if ($i === 0)
<td class="right aligned" rowspan="{{count($informe->cuentas)}}">{{$format->pesos($informe->total())}}</td>
<td class="right aligned" rowspan="{{count($informe->cuentas)}}">{{$format->pesos($informe->ffmm())}}</td>
<td class="right aligned" rowspan="{{count($informe->cuentas)}}">{{$format->pesos($informe->deposito())}}</td>
<td class="right aligned" rowspan="{{count($informe->cuentas)}}">{{$format->pesos($informe->caja())}}</td>
@endif
</tr> </tr>
@endforeach <tr>
@endforeach <td>Informe actual</td>
</tbody> <td>{{$fecha->format('d/m/Y')}}</td>
<tfoot> </tr>
<tr class="bold"> </table>
<th colspan="3">TOTAL</th> </div>
<th class="right aligned">{{$format->pesos($informes['totales']->anterior)}}</th> <div class="column"></div>
<th class="right aligned">{{$format->pesos($informes['totales']->actual)}}</th> <div class="four wide column">
<th class="right aligned">{{$format->pesos($informes['totales']->diferencia())}}</th> <table class="ui collapsing simple table">
<th class="right aligned">{{$format->pesos($informes['totales']->ffmm)}}</th> <tr>
<th class="right aligned">{{$format->pesos($informes['totales']->deposito)}}</th> <td>Valor UF</td>
<th class="right aligned">{{$format->pesos($informes['totales']->saldo())}}</th> <td class="right aligned">{{$format->pesos($UF->get($fecha), 2)}}</td>
<th class="right aligned">{{$format->pesos($informes['totales']->cuentas())}}</th> </tr>
<th class="right aligned">{{$format->pesos($informes['totales']->ffmms())}}</th> <tr>
<th class="right aligned">{{$format->pesos($informes['totales']->depositos())}}</th> <td>Valor Dólar</td>
<th class="right aligned">{{$format->pesos($informes['totales']->caja())}}</th> <td class="right aligned">{{$format->pesos($USD->get($fecha), 2)}}</td>
</tr> </tr>
</tfoot> </table>
</table> </div>
<table class="ui table"> </div>
<thead> <table class="ui striped table">
<thead>
<tr>
<th>EMPRESA</th>
<th>Banco</th>
<th>Cuenta</th>
<th class="right aligned">Saldo Anterior</th>
<th class="right aligned">Saldo Actual</th>
<th class="right aligned">Diferencia</th>
<th class="right aligned">FFMM</th>
<th class="right aligned">DAP</th>
<th class="right aligned">Saldo Empresa</th>
<th class="right aligned">Total Cuentas</th>
<th class="right aligned">Total FFMM</th>
<th class="right aligned">Total DAP</th>
<th class="right aligned">Caja Total</th>
</tr>
</thead>
<tbody>
@foreach ($informes['inmobiliarias'] as $inmobiliaria_rut => $informe)
@foreach ($informe->cuentas as $i => $cuenta)
<tr> <tr>
<th>EMPRESA</th> @if ($i === 0)
<th class="right aligned">INGRESOS</th> <td rowspan="{{count($informe->cuentas)}}">{{$informe->inmobiliaria->razon}}</td>
<th class="right aligned">EGRESOS</th>
<th>FECHA</th>
<th>BANCO</th>
<th>DESCRIPCIÓN</th>
</tr>
</thead>
<tbody>
@foreach ($informes['movimientos'] as $tipo => $movimientos)
@if ($tipo === 'capital dap')
@if (count($movimientos['ingresos']) === 0 and count($movimientos['egresos']) === 0)
@continue
@endif
<tr class="grey">
<td colspan="6">{{strtoupper($tipo)}}</td>
</tr>
@foreach ($movimientos as $t => $ms)
@foreach ($ms as $movimiento)
<tr>
<td >{{$movimiento->cuenta->inmobiliaria->razon}}</td>
<td class="right aligned">{{$format->pesos($movimiento->abono)}}</td>
<td class="right aligned">{{$format->pesos($movimiento->cargo)}}</td>
<td>{{$movimiento->fecha->format('d/m/Y')}}</td>
<td>{{$movimiento->cuenta->banco->nombre}}</td>
<td>{{$movimiento->glosa}}</td>
</tr>
@endforeach
@endforeach
@continue
@endif @endif
@if (count($movimientos) === 0) <td>{{$cuenta->banco}}</td>
<td>{{$cuenta->numero}}</td>
<td class="right aligned">{{$format->pesos($cuenta->anterior)}}</td>
<td class="right aligned">{{$format->pesos($cuenta->actual)}}</td>
<td class="right aligned">{{$format->pesos($cuenta->diferencia())}}</td>
<td class="right aligned">{{$format->pesos($cuenta->ffmm)}}</td>
<td class="right aligned">{{$format->pesos($cuenta->deposito)}}</td>
<td class="right aligned">{{$format->pesos($cuenta->saldo())}}</td>
@if ($i === 0)
<td class="right aligned" rowspan="{{count($informe->cuentas)}}">{{$format->pesos($informe->total())}}</td>
<td class="right aligned" rowspan="{{count($informe->cuentas)}}">{{$format->pesos($informe->ffmm())}}</td>
<td class="right aligned" rowspan="{{count($informe->cuentas)}}">{{$format->pesos($informe->deposito())}}</td>
<td class="right aligned" rowspan="{{count($informe->cuentas)}}">{{$format->pesos($informe->caja())}}</td>
@endif
</tr>
@endforeach
@endforeach
</tbody>
<tfoot>
<tr class="bold">
<th colspan="3">TOTAL</th>
<th class="right aligned">{{$format->pesos($informes['totales']->anterior)}}</th>
<th class="right aligned">{{$format->pesos($informes['totales']->actual)}}</th>
<th class="right aligned">{{$format->pesos($informes['totales']->diferencia())}}</th>
<th class="right aligned">{{$format->pesos($informes['totales']->ffmm)}}</th>
<th class="right aligned">{{$format->pesos($informes['totales']->deposito)}}</th>
<th class="right aligned">{{$format->pesos($informes['totales']->saldo())}}</th>
<th class="right aligned">{{$format->pesos($informes['totales']->cuentas())}}</th>
<th class="right aligned">{{$format->pesos($informes['totales']->ffmms())}}</th>
<th class="right aligned">{{$format->pesos($informes['totales']->depositos())}}</th>
<th class="right aligned">{{$format->pesos($informes['totales']->caja())}}</th>
</tr>
</tfoot>
</table>
<table class="ui table">
<thead>
<tr>
<th>EMPRESA</th>
<th class="right aligned">INGRESOS</th>
<th class="right aligned">EGRESOS</th>
<th>FECHA</th>
<th>BANCO</th>
<th>DESCRIPCIÓN</th>
</tr>
</thead>
<tbody>
@foreach ($informes['movimientos'] as $tipo => $movimientos)
@if ($tipo === 'capital dap')
@if (count($movimientos['ingresos']) === 0 and count($movimientos['egresos']) === 0)
@continue @continue
@endif @endif
<tr class="grey"> <tr class="grey">
<td colspan="6">{{strtoupper($tipo)}}</td> <td colspan="6">{{strtoupper($tipo)}}</td>
</tr> </tr>
@foreach ($movimientos as $movimiento) @foreach ($movimientos as $ms)
<tr> @foreach ($ms as $movimiento)
<td >{{$movimiento->cuenta->inmobiliaria->razon}}</td> <tr>
<td class="right aligned">{{$format->pesos($movimiento->abono)}}</td> <td >{{$movimiento->cuenta->inmobiliaria->razon}}</td>
<td class="red right aligned">{{$format->pesos($movimiento->cargo)}}</td> <td class="right aligned">{{$format->pesos($movimiento->abono)}}</td>
<td>{{$movimiento->fecha->format('d/m/Y')}}</td> <td class="right aligned">{{$format->pesos($movimiento->cargo)}}</td>
<td>{{$movimiento->cuenta->banco->nombre}}</td> <td>{{$movimiento->fecha->format('d/m/Y')}}</td>
<td>{{$movimiento->glosa}}</td> <td>{{$movimiento->cuenta->banco->nombre}}</td>
</tr> <td>{{$movimiento->glosa}}</td>
</tr>
@endforeach
@endforeach @endforeach
@continue
@endif
@if (count($movimientos) === 0)
@continue
@endif
<tr class="grey">
<td colspan="6">{{strtoupper($tipo)}}</td>
</tr>
@foreach ($movimientos as $movimiento)
<tr>
<td >{{$movimiento->cuenta->inmobiliaria->razon}}</td>
<td class="right aligned">{{$format->pesos($movimiento->abono)}}</td>
<td class="red right aligned">{{$format->pesos($movimiento->cargo)}}</td>
<td>{{$movimiento->fecha->format('d/m/Y')}}</td>
<td>{{$movimiento->cuenta->banco->nombre}}</td>
<td>{{$movimiento->glosa}}</td>
</tr>
@endforeach @endforeach
</tbody> @endforeach
</table> </tbody>
</table>
@endsection @endsection

View File

@ -8,7 +8,8 @@ return [
'cache' => DI\String('{base}/cache'), 'cache' => DI\String('{base}/cache'),
'templates' => DI\String('{resources}/views'), 'templates' => DI\String('{resources}/views'),
'public' => DI\String('{base}/public'), 'public' => DI\String('{base}/public'),
'uploads' => DI\String('{public}/uploads') 'uploads' => DI\String('{public}/uploads'),
'informes' => DI\String('{public}/informes')
]); ]);
} }
]; ];

View File

@ -61,5 +61,20 @@ return [
new GuzzleHttp\Client(), new GuzzleHttp\Client(),
$container->get(Psr\Http\Message\RequestFactoryInterface::class), $container->get(Psr\Http\Message\RequestFactoryInterface::class),
$container->get('nubox')->get('url')); $container->get('nubox')->get('url'));
},
Incoviba\Service\Informe::class => function(ContainerInterface $container) {
return (new Incoviba\Service\Informe(
$container->get(Psr\Log\LoggerInterface::class),
$container->get('folders')->get('informes'))
)
->register('xlsx', Incoviba\Service\Informe\Excel::class);
},
Incoviba\Service\Contabilidad\Informe\Tesoreria\Excel::class => function(ContainerInterface $container) {
return new Incoviba\Service\Contabilidad\Informe\Tesoreria\Excel(
$container->get(Psr\Log\LoggerInterface::class),
$container->get('folders')->get('informes'),
$container->get(Incoviba\Service\UF::class),
$container->get(Incoviba\Service\USD::class)
);
} }
]; ];

View File

@ -62,12 +62,13 @@ class Contabilidad extends Controller
return $view->render($response, 'contabilidad.depositos', compact('inmobiliarias', 'activos', 'vencidos')); return $view->render($response, 'contabilidad.depositos', compact('inmobiliarias', 'activos', 'vencidos'));
} }
public function tesoreria(ServerRequestInterface $request, ResponseInterface $response, View $view, public function tesoreria(ServerRequestInterface $request, ResponseInterface $response, View $view,
Service\Contabilidad\Informe\Tesoreria $contabilidadService, Service\Contabilidad\Informe\Tesoreria $contabilidadService,
string $fecha = 'today'): ResponseInterface string $fecha = 'today'): ResponseInterface
{ {
$fecha = new DateTimeImmutable($fecha); $fecha = new DateTimeImmutable($fecha);
$anterior = $contabilidadService->getAnterior($fecha); $anterior = $contabilidadService->getAnterior($fecha);
$informes = $contabilidadService->build($fecha); $informes = $contabilidadService->build($fecha);
return $view->render($response, 'contabilidad.informes.tesoreria', compact('fecha', 'anterior', 'informes')); $filename = "Informe de Tesorería {$fecha->format('d.m.Y')}";
return $view->render($response, 'contabilidad.informes.tesoreria', compact('fecha', 'anterior', 'informes', 'filename'));
} }
} }

View File

@ -0,0 +1,20 @@
<?php
namespace Incoviba\Controller\Contabilidad;
use DateTimeImmutable;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Ideal;
use Incoviba\Service;
class Informes extends Ideal\Controller
{
public function tesoreria(ServerRequestInterface $request, ResponseInterface $response, Service\Contabilidad\Informe\Tesoreria $tesoreriaService, string $fecha): ResponseInterface
{
$fecha = new DateTimeImmutable($fecha);
$tesoreriaService->buildInforme($fecha, $tesoreriaService->build($fecha));
$response->getBody()->write(file_get_contents('php://output'));
return $response;
}
}

View File

@ -4,10 +4,12 @@ namespace Incoviba\Service\Contabilidad\Informe;
use DateTimeInterface; use DateTimeInterface;
use DateInterval; use DateInterval;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use PhpOffice\PhpSpreadsheet;
use Incoviba\Common\Ideal; use Incoviba\Common\Ideal;
use Incoviba\Common\Implement; use Incoviba\Common\Implement;
use Incoviba\Repository;
use Incoviba\Model; use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
class Tesoreria extends Ideal\Service class Tesoreria extends Ideal\Service
{ {
@ -16,7 +18,9 @@ class Tesoreria extends Ideal\Service
protected Repository\Inmobiliaria\Cuenta $cuentaRepository, protected Repository\Inmobiliaria\Cuenta $cuentaRepository,
protected Repository\Deposito $depositoRepository, protected Repository\Deposito $depositoRepository,
protected Repository\Cartola $cartolaRepository, protected Repository\Cartola $cartolaRepository,
protected Repository\Movimiento $movimientoRepository) protected Repository\Movimiento $movimientoRepository,
protected Service\Contabilidad\Informe\Tesoreria\Excel $excelService,
protected Service\Contabilidad\Informe\Tesoreria\PDF $pdfService)
{ {
parent::__construct($logger); parent::__construct($logger);
@ -123,8 +127,16 @@ class Tesoreria extends Ideal\Service
} }
$informe['movimientos'] = $this->buildMovimientos(); $informe['movimientos'] = $this->buildMovimientos();
$informe['totales'] = $this->buildTotales(); $informe['totales'] = $this->buildTotales();
//$this->buildInforme($fecha, $informe);
return $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 protected function buildInmobiliaria(Model\Inmobiliaria $inmobiliaria, DateTimeInterface $fecha): object
{ {
@ -277,4 +289,5 @@ class Tesoreria extends Ideal\Service
$this->totales->{$tipo} += $total; $this->totales->{$tipo} += $total;
return $this; return $this;
} }
} }

View File

@ -0,0 +1,493 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria;
use DateTimeInterface;
use DateInterval;
use IntlDateFormatter;
use Psr\Log\LoggerInterface;
use PhpOffice\PhpSpreadsheet;
use Incoviba\Common\Ideal;
use Incoviba\Service;
class Excel extends Ideal\Service
{
protected const CURRENCY_CODE = '_-$* #,##0_-;-$* #,##0_-;_-$* "-"??_-;_-@_-';
public function __construct(LoggerInterface $logger, protected string $folder, protected Service\UF $ufService, protected Service\USD $usdService)
{
parent::__construct($logger);
}
public function build(DateTimeInterface $fecha, array $data): PhpSpreadsheet\Spreadsheet
{
$title = "Informe de Tesorería {$fecha->format('d.m.Y')}";
$informe = new PhpSpreadsheet\Spreadsheet();
$informe->getProperties()
->setCompany('Incoviba')
->setCreator('admin@incoviba.cl')
->setTitle($title)
->setSubject($title)
->setCreated($fecha->getTimestamp());
$styles = [
'font' => [
'name' => 'Gill Sans MT',
'size' => 12
]
];
$informe->getDefaultStyle()->applyFromArray($styles);
$sheet = $informe->getActiveSheet();
$sheet->setTitle($title);
$sheet->getColumnDimension('A')->setWidth('5.43');
$this->fillTitle($sheet, $fecha);
$this->fillFechas($sheet, $fecha);
$this->fillMonedas($sheet, $fecha);
$finalRow = $this->fillEmpresas($sheet, $data);
$finalRow = $this->fillCaja($sheet, $data, $finalRow + 2);
foreach (range('B', 'V') as $columnIndex) {
$sheet->getColumnDimension($columnIndex)->setAutoSize(true);
}
$this->setPageSetup($sheet, $finalRow);
return $informe;
}
public function save(DateTimeInterface $fecha, PhpSpreadsheet\Spreadsheet $informe, string $type = 'Xlsx', ?string $filename = null): void
{
if ($filename === null) {
$ext = strtolower($type);
$filename = implode(DIRECTORY_SEPARATOR, [$this->folder, "{$informe->getActiveSheet()->getTitle()}.{$ext}"]);
}
$writer = PhpSpreadsheet\IOFactory::createWriter($informe, $type);
if (str_starts_with($filename, 'php://')) {
$downloadFilename = "Informe de Tesorería {$fecha->format('d.m.Y')}.xlsx";
// ZipStream, used by PhpSpreadsheet when saving, sends headers
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header("Content-Disposition: attachment;filename=\"{$downloadFilename}\"");
header('Cache-Control: max-age=0');
}
$writer->save($filename);
}
protected 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;
}
protected function fillTitle(PhpSpreadsheet\Worksheet\Worksheet $sheet, DateTimeInterface $fecha): void
{
$intl = new IntlDateFormatter('es-CL');
$intl->setPattern('dd MMM yyyy');
$sheet->getCell('B2')->setValue('CONTROL DIARIO CAJA EMPRESAS');
$sheet->mergeCells('B2:V2');
$styles = [
'font' => [
'bold' => true,
'size' => 18
],
'fill' => [
'fillType' => PhpSpreadsheet\Style\Fill::FILL_SOLID,
'startColor' => [
'argb' => 'FFFFC000'
]
],
'alignment' => [
'horizontal' => PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER
],
'borders' => [
'outline' => [
'borderStyle' => PhpSpreadsheet\Style\Border::BORDER_THIN
]
]
];
$sheet->getStyle('B2:V2')->applyFromArray($styles);
$sheet->getCell('B3')->setValue(PhpSpreadsheet\Shared\Date::PHPToExcel($fecha));
$styles = [
'font' => [
'size' => 18
],
'alignment' => [
'horizontal' => PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER
],
'numberFormat' => [
'formatCode' => 'DD MMMM YYYY'
]
];
$sheet->getCell('B3')->getStyle()->applyFromArray($styles);
$sheet->mergeCells('B3:V3');
}
protected function fillFechas(PhpSpreadsheet\Worksheet\Worksheet $sheet, DateTimeInterface $fecha): void
{
$anterior = $this->getAnterior($fecha);
$sheet->getCell('B4')->setValue('Informe anterior');
$sheet->getCell('B5')->setValue('Informe actual');
$sheet->getCell('C4')->setValue(PhpSpreadsheet\Shared\Date::PHPToExcel($anterior));
$sheet->getCell('C5')->setValue(PhpSpreadsheet\Shared\Date::PHPToExcel($fecha));
$sheet->getStyle('C4:C5')->getNumberFormat()->setFormatCode(PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_DDMMYYYY);
$sheet->getStyle('B4:C5')->getBorders()->getOutline()->setBorderStyle(PhpSpreadsheet\Style\Border::BORDER_THIN);
}
protected function fillMonedas(PhpSpreadsheet\Worksheet\Worksheet $sheet, DateTimeInterface $fecha): void
{
$sheet->getCell('E4')->setValue('Valor UF');
$sheet->getCell('E5')->setValue('Valor Dólar');
$sheet->getCell('F4')->setValue($this->ufService->get($fecha));
$sheet->getCell('F5')->setValue($this->usdService->get($fecha));
$sheet->getStyle('F4:F5')->getNumberFormat()->setFormatCode("$ #,##0.00");
$sheet->getStyle('E4:F5')->getBorders()->getOutline()->setBorderStyle(PhpSpreadsheet\Style\Border::BORDER_THIN);
}
protected function fillEmpresas(PhpSpreadsheet\Worksheet\Worksheet $sheet, array $data, int $startRow = 7): int
{
$columns = ['EMPRESA', 'Banco', 'Cuenta', 'Saldo anterior', 'Saldo actual', 'Diferencia', 'FFMM', 'DAP',
'Saldo empresa', 'Total Cuentas', 'Total FFMM', 'Total DAP', 'Caja Total'];
$styles = [
'alignment' => [
'horizontal' => PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER
],
'borders' => [
'outline' => [
'borderStyle' => PhpSpreadsheet\Style\Border::BORDER_THIN
]
],
'fill' => [
'fillType' => PhpSpreadsheet\Style\Fill::FILL_SOLID,
'color' => [
'argb' => 'FF333F4F'
]
],
'font' => [
'color' => [
'argb' => PhpSpreadsheet\Style\Color::COLOR_WHITE
]
]
];
$this->fillColumns($sheet, $columns, $styles, $startRow);
$rowIndex = $startRow + 1;
foreach ($data['inmobiliarias'] as $dataInmobiliaria) {
$rowIndex += $this->fillInmobiliaria($sheet, $dataInmobiliaria, $rowIndex);
}
$finalRow = $rowIndex;
$sheet->getStyle("B7:N{$finalRow}")->getBorders()->getAllBorders()
->setBorderStyle(PhpSpreadsheet\Style\Border::BORDER_THIN)
->getColor()->setARGB('FFD9D9D9');
$sheet->getStyle("C8:D{$finalRow}")->getAlignment()
->setHorizontal(PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
$this->fillTotals($sheet, 7, $finalRow ++);
$sheet->getStyle("E8:N{$finalRow}")->getNumberFormat()
->setFormatCode(self::CURRENCY_CODE);
return $finalRow;
}
protected function fillCaja(PhpSpreadsheet\Worksheet\Worksheet $sheet, array $data, $startRow): int
{
$sheet->getCell("B{$startRow}")->setValue('CUADRATURA CAJA DÍA ANTERIOR');
$sheet->mergeCells("B{$startRow}:V{$startRow}");
$sheet->getStyle("B{$startRow}:V{$startRow}")->applyFromArray([
'alignment' => [
'horizontal' => PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER
],
'borders' => [
'outline' => [
'borderStyle' => PhpSpreadsheet\Style\Border::BORDER_THIN
]
],
'font' => [
'bold' => true
],
'fill' => [
'fillType' => PhpSpreadsheet\Style\Fill::FILL_SOLID,
'color' => [
'argb' => 'FFFFC000'
]
]
]);
$rowIndex = $startRow;
$columns = ['EMPRESA', 'INGRESOS', 'EGRESOS', 'FECHA', 'BANCO', 'DESCRIPCIÓN', '', 'CATEGORIA', '', 'CC',
'DETALLE', '', 'N° DOC.', 'RUT', 'NOMBRES', '', '', '', '', '', ''];
$styles = [
'borders' => [
'allBorders' => [
'borderStyle' => PhpSpreadsheet\Style\Border::BORDER_THIN
]
],
'fill' => [
'fillType' => PhpSpreadsheet\Style\Fill::FILL_SOLID,
'startColor' => [
'argb' => 'FFD9D9D9'
]
]
];
$this->fillColumns($sheet, $columns, $styles, ++ $rowIndex);
$sheet->mergeCells("G{$rowIndex}:H{$rowIndex}")
->mergeCells("I{$rowIndex}:J{$rowIndex}")
->mergeCells("L{$rowIndex}:M{$rowIndex}")
->mergeCells("P{$rowIndex}:R{$rowIndex}")
->mergeCells("S{$rowIndex}:V{$rowIndex}");
$rowIndex += 2;
$sheet->getCell("T{$rowIndex}")
->setValue("Saldo Consolidado al")
->getStyle()->applyFromArray([
'alignment' => [
'horizontal' => PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT
],
'font' => [
'bold' => true
]
]);
$sheet->getCell("U{$rowIndex}")->setValue("=C5")
->getStyle()->applyFromArray([
'font' => [
'bold' => true
],
'numberFormat' => [
'formatCode' => PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_DDMMYYYY
]
]);
$sheet->getCell("V{$rowIndex}")->setValue(0)->getStyle()->applyFromArray([
'font' => [
'bold' => true
],
'numberFormat' => [
'formatCode' => self::CURRENCY_CODE
]
]);
$rowIndex ++;
$styles = [
'fill' => [
'fillType' => PhpSpreadsheet\Style\Fill::FILL_SOLID,
'startColor' => [
'argb' => 'FFD9E1F2'
]
],
'font' => [
'bold' => true
]
];
foreach ($data['movimientos'] as $tipo => $movimientos) {
if ($tipo === 'capital dap') {
$sheet->getCell("B{$rowIndex}")->setValue('CAPITAL DAP');
$sheet->getCell("T{$rowIndex}")->setValue('SUMA DAP');
$sheet->getStyle("B{$rowIndex}:V{$rowIndex}")->applyFromArray($styles);
$sheet->getCell("V{$rowIndex}")->getStyle()->getNumberFormat()->setFormatCode(self::CURRENCY_CODE);
$totalRow = $rowIndex;
$rowIndex ++;
if (count($movimientos['ingresos']) === 0 and count($movimientos['egresos']) === 0) {
$sheet->getCell("V{$totalRow}")->setValue(0);
continue;
}
$start = $rowIndex;
foreach ($movimientos as $ms) {
foreach ($ms as $movimiento) {
$sheet->getCell("B{$rowIndex}")->setValue($movimiento->cuenta->inmobiliaria->razon);
$sheet->getCell("C{$rowIndex}")->setValue($movimiento->abono);
$sheet->getCell("D{$rowIndex}")->setValue($movimiento->cargo);
$sheet->getCell("E{$rowIndex}")->setValue(PhpSpreadsheet\Shared\Date::PHPToExcel($movimiento->fecha));
$sheet->getCell("F{$rowIndex}")->setValue($movimiento->cuenta->banco->nombre);
$sheet->getCell("G{$rowIndex}")->setValue($movimiento->glosa);
$rowIndex ++;
}
}
$end = $rowIndex;
$sheet->getCell("V{$totalRow}")->setValue("=SUM(C{$start}:D{$end})");
$sheet->getStyle("C{$start}:D{$end}")->getNumberFormat()->setFormatCode(self::CURRENCY_CODE);
continue;
}
$sheet->getCell("B{$rowIndex}")->setValue(strtoupper($tipo));
$sheet->getCell("T{$rowIndex}")->setValue('SUMA '.strtoupper($tipo));
$sheet->getStyle("B{$rowIndex}:V{$rowIndex}")->applyFromArray($styles);
$sheet->getCell("V{$rowIndex}")->getStyle()->getNumberFormat()
->setFormatCode(self::CURRENCY_CODE);
$totalRow = $rowIndex;
$rowIndex ++;
if (count($movimientos) === 0) {
$sheet->getCell("V{$totalRow}")->setValue(0);
continue;
}
$start = $rowIndex;
foreach ($movimientos as $movimiento) {
$sheet->getCell("B{$rowIndex}")->setValue($movimiento->cuenta->inmobiliaria->razon);
$sheet->getCell("C{$rowIndex}")->setValue($movimiento->abono);
$sheet->getCell("D{$rowIndex}")->setValue($movimiento->cargo);
$sheet->getCell("E{$rowIndex}")->setValue(PhpSpreadsheet\Shared\Date::PHPToExcel($movimiento->fecha));
$sheet->getCell("F{$rowIndex}")->setValue($movimiento->cuenta->banco->nombre);
$sheet->getCell("G{$rowIndex}")->setValue($movimiento->glosa);
$rowIndex ++;
}
$end = $rowIndex;
$sheet->getCell("V{$totalRow}")->setValue("=SUM(C{$start}:D{$end})");
$sheet->getStyle("C{$start}:D{$end}")->getNumberFormat()
->setFormatCode(self::CURRENCY_CODE);
}
$end = $rowIndex;
$rowIndex ++;
$sheet->getCell("B{$rowIndex}")->setValue('TOTAL');
$sheet->getCell("C{$rowIndex}")->setValue("=SUM(C{$startRow}:C{$end})");
$sheet->getCell("D{$rowIndex}")->setValue("=SUM(D{$startRow}:D{$end})");
$sheet->getCell("T{$rowIndex}")->setValue('Saldo final al')
->getStyle()->applyFromArray([
'alignment' => [
'horizontal' => PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT
],
'font' => [
'bold' => true
]
]);
$sheet->getCell("U{$rowIndex}")->setValue('=C5')
->getStyle()->applyFromArray([
'font' => [
'bold' => true
],
'numberFormat' => [
'formatCode' => PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_DDMMYYYY
]
]);
$sheet->getCell("V{$rowIndex}")->setValue(0)->getStyle()->applyFromArray([
'font' => [
'bold' => true
],
'numberFormat' => [
'formatCode' => self::CURRENCY_CODE
]
]);
$sheet->getStyle("B{$rowIndex}:V{$rowIndex}")->applyFromArray([
'fill' => [
'fillType' => PhpSpreadsheet\Style\Fill::FILL_SOLID,
'startColor' => [
'argb' => 'FFD9D9D9'
]
],
'font' => [
'bold' => true
]
]);
$sheet->getStyle("C{$startRow}:D{$rowIndex}")->getNumberFormat()->setFormatCode(self::CURRENCY_CODE);
$columnRanges = [
['B', 'B'],
['C', 'C'],
['D', 'D'],
['E', 'E'],
['F', 'F'],
['G', 'H'],
['I', 'J'],
['K', 'K'],
['L', 'M'],
['N', 'N'],
['O', 'O'],
['P', 'R'],
['S', 'V']
];
foreach ($columnRanges as $range) {
$sheet->getStyle("{$range[0]}{$startRow}:{$range[1]}{$rowIndex}")->getBorders()->getOutline()
->setBorderStyle(PhpSpreadsheet\Style\Border::BORDER_THIN);
}
return $rowIndex;
}
protected function fillColumns(PhpSpreadsheet\Worksheet\Worksheet $sheet, array $columns, array $styles, $rowIndex): void
{
$columnIndex = 2;
foreach ($columns as $index => $column) {
$columnIndex = 2 + $index;
$sheet->getCell([$columnIndex, $rowIndex])->setValue($column);
}
$sheet->getStyle([2, $rowIndex, $columnIndex, $rowIndex])->applyFromArray($styles);
}
protected function fillInmobiliaria(PhpSpreadsheet\Worksheet\Worksheet $sheet, object $dataInmobiliaria, int $baseRowIndex): int
{
$rowIndex = $baseRowIndex;
$sheet->getCell("B{$rowIndex}")->setValue($dataInmobiliaria->inmobiliaria->razon);
foreach ($dataInmobiliaria->cuentas as $cuentaRowIndex => $cuenta) {
$this->fillCuenta($sheet, $cuenta, 3, $baseRowIndex + $cuentaRowIndex);
}
$sheet->getCell("K{$rowIndex}")->setValue($dataInmobiliaria->total());
$sheet->getCell("L{$rowIndex}")->setValue($dataInmobiliaria->ffmm());
$sheet->getCell("M{$rowIndex}")->setValue($dataInmobiliaria->deposito());
$sheet->getCell("N{$rowIndex}")->setValue($dataInmobiliaria->caja());
if (count($dataInmobiliaria->cuentas) > 1) {
$finalRow = $rowIndex + count($dataInmobiliaria->cuentas) - 1;
$sheet->mergeCells("B{$rowIndex}:B{$finalRow}");
$sheet->mergeCells("K{$rowIndex}:K{$finalRow}");
$sheet->mergeCells("L{$rowIndex}:L{$finalRow}");
$sheet->mergeCells("M{$rowIndex}:M{$finalRow}");
$sheet->mergeCells("N{$rowIndex}:N{$finalRow}");
}
return count($dataInmobiliaria->cuentas);
}
protected function fillCuenta(PhpSpreadsheet\Worksheet\Worksheet $sheet, object $cuenta, int $startColumnIndex, int $rowIndex): void
{
$columnIndex = $startColumnIndex;
$sheet->getCell([$columnIndex ++, $rowIndex])->setValue($cuenta->banco);
$sheet->getCell([$columnIndex ++, $rowIndex])->setValue($cuenta->numero);
$sheet->getCell([$columnIndex ++, $rowIndex])->setValue($cuenta->anterior);
$sheet->getCell([$columnIndex ++, $rowIndex])->setValue($cuenta->actual);
$sheet->getCell([$columnIndex ++, $rowIndex])->setValue("=F{$rowIndex}-E{$rowIndex}");
$sheet->getCell([$columnIndex ++, $rowIndex])->setValue($cuenta->ffmm);
$sheet->getCell([$columnIndex ++, $rowIndex])->setValue($cuenta->deposito);
$sheet->getCell([$columnIndex, $rowIndex])->setValue("=SUM(F{$rowIndex},H{$rowIndex}:I{$rowIndex})");
}
protected function fillTotals(PhpSpreadsheet\Worksheet\Worksheet $sheet, int $startRow, int $finalRow): void
{
$rowIndex = $finalRow + 1;
$sheet->getCell("B{$rowIndex}")->setValue('TOTAL');
foreach (range('E', 'N') as $columnIndex) {
$sheet->getCell("{$columnIndex}{$rowIndex}")->setValue("=SUBTOTAL(109,{$columnIndex}{$startRow}:{$columnIndex}{$finalRow})");
}
$styles = [
'font' => [
'bold' => true
],
'fill' => [
'fillType' => PhpSpreadsheet\Style\Fill::FILL_SOLID,
'startColor' => [
'argb' => 'FFD9D9D9'
]
],
'borders' => [
'outline' => [
'borderStyle' => PhpSpreadsheet\Style\Border::BORDER_THIN,
'color' => [
'argb' => PhpSpreadsheet\Style\Color::COLOR_BLACK
]
]
]
];
$sheet->getStyle("B{$rowIndex}:N{$rowIndex}")->applyFromArray($styles);
}
protected function setPageSetup(PhpSpreadsheet\Worksheet\Worksheet $sheet, int $finalRow): void
{
$sheet->getPageSetup()
->setPrintArea("B2:V{$finalRow}")
->setFitToWidth(1)
->setPaperSize(PhpSpreadsheet\Worksheet\PageSetup::PAPERSIZE_LEGAL)
->setOrientation(PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);
$sheet->setShowGridlines(false);
$sheet->getSheetView()
->setView(PhpSpreadsheet\Worksheet\SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW)
->setZoomScale(70);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Incoviba\Service\Contabilidad\Informe\Tesoreria;
use DateTimeInterface;
class PDF
{
public function build(DateTimeInterface $fecha, array $data): void
{
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Incoviba\Service;
use Incoviba\Common\Ideal;
use Psr\Log\LoggerInterface;
class Informe extends Ideal\Service
{
public function __construct(LoggerInterface $logger, protected string $folder)
{
parent::__construct($logger);
if (!file_exists($this->folder)) {
mkdir($this->folder);
}
}
protected array $informes;
public function register(string $name, string $informeClass): Informe
{
$this->informes[$name] = $informeClass;
return $this;
}
public function build(string $type, string $filename, string $title, array $data): void
{
$informe = new $this->informes[$type]();
$filename = implode(DIRECTORY_SEPARATOR, [$this->folder, "{$filename}.xlsx"]);
$informe->setFilename($filename);
$informe->setTitle($title);
$informe->addData($data);
$informe->build();
}
}

View File

@ -0,0 +1,63 @@
<?php
namespace Incoviba\Service\Informe;
use PhpOffice\PhpSpreadsheet;
use Incoviba\Common\Define;
class Excel implements Define\Informe
{
protected string $title;
protected string $filename;
protected array $data;
public function setTitle(string $title): Excel
{
$this->title = $title;
return $this;
}
public function setFilename(string $filename): Excel
{
$this->filename = $filename;
return $this;
}
public function addData(array $rows): Excel
{
foreach ($rows as $row) {
$this->addRow($row);
}
return $this;
}
public function addRow(array $row): Excel
{
foreach ($row as $cell) {
$this->addCell($cell);
}
return $this;
}
public function addCell(PhpSpreadsheet\Cell\Cell $cell): Excel
{
$this->data []= $cell;
return $this;
}
public function build(): void
{
$spreadsheet = new PhpSpreadsheet\Spreadsheet();
$spreadsheet->getProperties()
->setCreator('admin@incoviba.cl')
->setSubject($this->title)
->setCompany('Incoviba')
->setTitle($this->title);
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle($this->title);
foreach ($this->data as $rowIndex => $row) {
foreach ($row as $columnIndex => $cell) {
$sheet->getCell([$columnIndex + 1, $rowIndex + 1])->setValue($cell);
}
}
$writer = PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->save($this->filename);
}
}