movimientos = new class() { public function __construct() { $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 build(): array { return [ 'capital dap' => [ 'ingresos' => $this->dap->ingresos, 'egresos' => $this->dap->egresos ], 'ingresos' => $this->ingresos, 'egresos' => $this->egresos ]; } }; $this->totales = new class() { 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; } 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 { 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 []; } $informe = ['inmobiliarias' => []]; foreach ($inmobiliarias 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->cuentaRepository->fetchByInmobiliaria($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); if ($deposito->inicio === $fecha) { $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 === $fecha) { $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->capital, 'saldo' => $deposito->capital, 'glosa' => 'RESCATE DAP' ]]); } } } 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; } 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\Movimiento $movimiento) { return $movimiento->abono > 0; })); $this->addMovimientos(self::EGRESOS, array_filter($movimientos, function(Model\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_contains($tipo, 'dap')) { list($d, $t) = explode('->', $tipo); $this->movimientos->addDap($t, $movimientos); return $this; } foreach ($movimientos as $movimiento) { $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; } }