bancos[$name] = $banco; return $this; } public function process(Model\Contabilidad\Banco $banco, UploadedFileInterface $file): array { return $this->bancos[strtolower($banco->nombre)]->process($file); } public function export(Model\Inmobiliaria $inmobiliaria, Model\Contabilidad\Banco $banco, DateTimeInterface $mes, array $movimientos): string { return $this->exporter->export($inmobiliaria, $banco, $mes, $movimientos); } public function diaria(Model\Inmobiliaria\Cuenta $cuenta, DateTimeInterface $fecha, UploadedFileInterface $file): array { $ms = $this->getMovimientosDiarios($cuenta->banco, $file); $this->groupedMovimientos = []; $movimientos = []; foreach ($ms as $m) { $movimiento = $this->buildMovimiento($cuenta, $m); $movimiento = $this->movimientoService->process($movimiento); $this->groupMovimientoByDay($movimiento); if ($movimiento->fecha->getTimestamp() === $fecha->getTimestamp()) { $movimientos []= $movimiento; } } foreach ($this->groupedMovimientos as $timestamp => $movimientos) { $cartolaData = [ 'cargos' => 0, 'abonos' => 0, 'saldo' => last($movimientos)->saldo ]; foreach ($movimientos as $movimiento) { $cartolaData['cargos'] += $movimiento->cargo; $cartolaData['abonos'] += $movimiento->abono; } $this->buildCartola($cuenta, last($movimientos)->fecha, $cartolaData); } $cartola = $this->cartolaRepository->fetchByCuentaAndFecha($cuenta->id, $fecha); return compact('cartola', 'movimientos'); } public function diariaManual(Model\Inmobiliaria\Cuenta $cuenta, DateTimeInterface $fecha, array $data): array { $cartolaData = [ 'cargos' => 0, 'abonos' => 0, 'saldos' => 0 ]; $movimientos = []; foreach ($data as $row) { $dataMovimiento = $row; $dataMovimiento['fecha'] = $fecha->format('Y-m-d'); $dataMovimiento['documento'] = ''; $movimiento = $this->buildMovimiento($cuenta, $dataMovimiento); $movimiento = $this->movimientoService->process($movimiento); $movimientos []= $movimiento; $cartolaData['cargos'] += $movimiento->cargo; $cartolaData['abonos'] += $movimiento->abono; $cartolaData['saldo'] = $movimiento->saldo; } $cartola = $this->buildCartola($cuenta, $fecha, $cartolaData); return compact('cartola', 'movimientos'); } public function import(int $cuenta_id, UploadedFileInterface $file): array { $cuenta = $this->cuentaRepository->fetchById($cuenta_id); $movimientos = $this->process($cuenta->banco, $file); $inmobiliaria = $cuenta->inmobiliaria; $addedMovimientos = []; foreach ($movimientos as &$dataMovimiento) { $dataMovimiento['cuenta_id'] = $cuenta->id; if (array_key_exists('centro_costo', $dataMovimiento) and $dataMovimiento['centro_costo'] !== 0) { $dataMovimiento['centro_costo_id'] = $dataMovimiento['centro_costo']; } $dataMovimiento['fecha'] = new DateTimeImmutable($dataMovimiento['fecha']); if (array_key_exists('rut', $dataMovimiento)) { $ruts = $this->parseRut($dataMovimiento['rut']); if (key_exists('rut', $ruts)) { $dataMovimiento['rut'] = $ruts['rut']; $dataMovimiento['digito'] = $ruts['digito']; } else { $dataMovimiento['rut'] = $ruts[0]['rut']; $dataMovimiento['digito'] = $ruts[0]['digito']; } } try { $movimiento = $this->movimientoRepository ->fetchByCuentaAndFechaAndGlosaAndCargoAndAbonoAndSaldo($dataMovimiento['cuenta_id'], $dataMovimiento['fecha'], $dataMovimiento['glosa'], $dataMovimiento['cargo'] ?? 0, $dataMovimiento['abono'] ?? 0, $dataMovimiento['saldo']); } catch (Exception\EmptyResult) { $movimiento = $this->movimientoService->add($dataMovimiento); $dataMovimiento['nuevo'] = true; } $dataMovimiento['id'] = $movimiento->id; $dataMovimiento['sociedad'] = $inmobiliaria; $addedMovimientos []= $movimiento->id; } $fechas = array_unique(array_map(function($movimiento) { return $movimiento['fecha']->format('Y-m-d'); }, $movimientos)); foreach ($fechas as $dia) { try { $this->cartolaRepository->fetchByCuentaAndFecha($cuenta->id, new DateTimeImmutable($dia)); continue; } catch (Exception\EmptyResult) {} $movs = array_filter($movimientos, function($movimiento) use ($dia) { return $movimiento['fecha'] === $dia; }); $cargos = array_sum(array_map(function($movimiento) { return $movimiento['cargo']; }, $movs)); $abonos = array_sum(array_map(function($movimiento) { return $movimiento['abono']; }, $movs)); $saldo = last($movs)['saldo']; $cartolaData = [ 'cargos' => $cargos, 'abonos' => $abonos, 'saldo' => $saldo ]; $this->buildCartola($cuenta, new DateTimeImmutable($dia), $cartolaData); } $startDate = new DateTimeImmutable(min($fechas)); $endDate = new DateTimeImmutable(max($fechas)); $movimientosFaltantes = $this->movimientoService->findMissing($cuenta, $addedMovimientos, $startDate, $endDate); $movimientosObsoletos = []; if (count($movimientosFaltantes) > 0) { $movimientosObsoletos = array_map(function($movimiento) { $arr = (array) $movimiento; $arr['sociedad'] = $movimiento->cuenta->inmobiliaria; $arr['obsoleto'] = true; return $arr; }, $movimientosFaltantes); } return array_map(function($movimiento) { if (is_a($movimiento['fecha'], DateTimeInterface::class)) { $movimiento['fecha'] = $movimiento['fecha']->format('Y-m-d'); } return $movimiento; }, array_merge($movimientos, $movimientosObsoletos)); } public function check(): array { try { $cuentas = $this->cuentaRepository->fetchAll(); $fechas = []; foreach ($cuentas as $cuenta) { $fechas[$cuenta->id] = $this->checkForCuenta($cuenta); } return $fechas; } catch (Exception\EmptyResult) { return []; } } public function checkForCuenta(Model\Inmobiliaria\Cuenta $cuenta): array { $cartolas = $this->cartolaRepository->fetchByCuenta($cuenta->id); $movimientos = $this->movimientoRepository->fetchByCuenta($cuenta->id); $fechasMovimientos = array_unique(array_map(function(Model\Contabilidad\Movimiento $movimiento) { return $movimiento->fecha->format('Y-m-d'); }, $movimientos)); $fechasCartolas = array_map(function(Model\Contabilidad\Cartola $cartola) { return $cartola->fecha->format('Y-m-d'); }, $cartolas); $fechas = array_diff($fechasMovimientos, $fechasCartolas); return array_values($fechas); } public function update(array $cuentas): array { $cartolas = []; foreach ($cuentas as $cuenta_id => $fechas) { $cuenta = $this->cuentaRepository->fetchById($cuenta_id); $cartolas[$cuenta_id] = $this->updateForCuenta($cuenta, $fechas); } return $cartolas; } public function updateForCuenta(Model\Inmobiliaria\Cuenta $cuenta, array $fechas): array { $cartolas = []; foreach ($fechas as $fecha) { $cartolas []= $this->updateForCuentaAndFecha($cuenta, new DateTimeImmutable($fecha)); } return $cartolas; } public function updateForCuentaAndFecha(Model\Inmobiliaria\Cuenta $cuenta, DateTimeInterface $fecha): Model\Contabilidad\Cartola { try { return $this->cartolaRepository->fetchByCuentaAndFecha($cuenta->id, $fecha); } catch (Exception\EmptyResult) {} $movimientos = $this->movimientoRepository->fetchByCuentaAndFecha($cuenta->id, $fecha); $cartolaData = [ 'cargos' => array_sum(array_map(function(Model\Contabilidad\Movimiento $movimiento) { return $movimiento->cargo; }, $movimientos)), 'abonos' => array_sum(array_map(function(Model\Contabilidad\Movimiento $movimiento) { return $movimiento->abono; }, $movimientos)), 'saldo' => last($movimientos)->saldo ]; return $this->buildCartola($cuenta, $fecha, $cartolaData); } protected function getMovimientosDiarios(Model\Contabilidad\Banco $banco, UploadedFileInterface $file): array { $movimientos = $this->bancos[strtolower($banco->nombre)]->process($file); return $this->bancos[strtolower($banco->nombre)]->processMovimientosDiarios($movimientos); } protected array $groupedMovimientos = []; protected function groupMovimientoByDay(Model\Contabilidad\Movimiento $movimiento): Cartola { if (!isset($this->groupedMovimientos[$movimiento->fecha->getTimestamp()])) { $this->groupedMovimientos[$movimiento->fecha->getTimestamp()] = []; } $this->groupedMovimientos[$movimiento->fecha->getTimestamp()] []= $movimiento; return $this; } protected function buildCartola(Model\Inmobiliaria\Cuenta $cuenta, DateTimeInterface $fecha, array $data): Model\Contabilidad\Cartola { try { return $this->cartolaRepository->fetchByCuentaAndFecha($cuenta->id, $fecha); } catch (Exception\EmptyResult) { $data['cuenta_id'] = $cuenta->id; $data['fecha'] = $fecha->format('Y-m-d'); $cartola = $this->cartolaRepository->create($data); return $this->cartolaRepository->save($cartola); } } protected function buildMovimiento(Model\Inmobiliaria\Cuenta $cuenta, array $data): Model\Contabilidad\Movimiento { try { return $this->movimientoRepository ->fetchByCuentaAndFechaAndGlosaAndCargoAndAbonoAndSaldo( $cuenta->id, new DateTimeImmutable($data['fecha']), $data['glosa'], $data['cargo'] ?? 0, $data['abono'] ?? 0, $data['saldo'] ); } catch (Exception\EmptyResult $exception) { $data['cuenta_id'] = $cuenta->id; $movimiento = $this->movimientoRepository->create($data); try { return $this->movimientoRepository->save($movimiento); } catch (\PDOException $exception) { $this->logger->critical(var_export($data,true)); throw $exception; } } } protected function parseRut(string $rut): array { if (str_contains($rut, '/')) { $ruts = explode('/', $rut); $output = []; foreach ($ruts as $rut) { $output []= $this->parseRut($rut); } return $output; } list($rut, $digito) = explode('-', $rut); return ['rut' => trim(preg_replace('/\D+/', '', $rut)), 'digito' => trim($digito)]; } }