Files
oficial/app/src/Service/Contabilidad/Informe/Tesoreria/Excel.php
2024-02-28 13:45:20 -03:00

494 lines
20 KiB
PHP

<?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("=C4")
->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);
}
}