factory = $factory; } protected $cuentas; public function getCuentas() { if ($this->cuentas === null) { $this->cuentas = $this->factory->find(Cuenta::class)->many(); } return $this->cuentas; } public function isConsolidado(): bool { $cuentas = $this->getCuentas(); if ($cuentas === null) { return true; } foreach ($cuentas as $cuenta) { $transacciones = $cuenta->hasTransacciones(); if (!$transacciones) { continue; } $pendientes = $cuenta->hasConsolidadosPending(); if ($pendientes) { return false; } } return true; } public function queue() { $data = [ 'command' => 'consolidar', 'created' => Carbon::now()->format('Y-m-d H:i:s') ]; $queue = Queue::add($this->factory, $data); $queue->save(); } public function consolidar() { ini_set('max_execution_time', 60*5); foreach ($this->getCuentas() as $cuenta) { if (!$cuenta->hasTransacciones()) { continue; } $first = $this->getFirst($cuenta); $last = $this->getLast($cuenta); for ($current = $first->copy()->startOfMonth(); $current < $last->copy()->addMonthWithoutOverflow()->endOfMonth(); $current = $current->copy()->addMonthWithoutOverflow()) { $transacciones = $this->getTransacciones($cuenta, $current); if (count($transacciones) == 0) { continue; } $f = $this->factory; array_walk($transacciones, function(&$item) use ($cuenta, $f) { $item->setFactory($f); $item->valor = $item->transformar($cuenta->moneda()); }); $saldo = array_reduce($transacciones, function($sum, $item) { return $sum + $item->valor; }); $data = [ 'cuenta_id' => $cuenta->id, 'fecha' => $current->format('Y-m-1'), 'periodo' => 'P1M', 'saldo' => $saldo ]; $consolidado = $this->factory->create(Consolidado::class, $data); $consolidado->save(); } } } public function getFirst(Cuenta $cuenta): ?Carbon { $first = [ Model::factory(Transaccion::class) ->select('fecha') ->whereEqual('debito_id', $cuenta->id) ->orderByAsc('fecha') ->findOne(), Model::factory(Transaccion::class) ->select('fecha') ->whereEqual('credito_id', $cuenta->id) ->orderByAsc('fecha') ->findOne() ]; if (!$first[0]) { if (!$first[1]) { return null; } return $first[1]->fecha(); } if (!$first[1]) { return $first[0]->fecha(); } if ($first[0]->fecha() < $first[1]->fecha()) { return $first[0]->fecha(); } return $first[1]->fecha(); } public function getLast(Cuenta $cuenta): ?Carbon { $fechas = [ Model::factory(Transaccion::class) ->select('fecha') ->whereEqual('debito_id', $cuenta->id) ->orderByDesc('fecha') ->findOne(), Model::factory(Transaccion::class) ->select('fecha') ->whereEqual('credito_id', $cuenta->id) ->orderByDesc('fecha') ->findOne() ]; if (!$fechas[0]) { if (!$fechas[1]) { return null; } return $fechas[1]->fecha(); } if (!$fechas[1]) { return $fechas[0]->fecha(); } if ($fechas[0]->fecha() > $fechas[1]->fecha()) { return $fechas[0]->fecha(); } return $fechas[1]->fecha(); } public function getTransacciones(Cuenta $cuenta, Carbon $fecha) { $start = $fecha->copy()->startOfMonth(); $end = $fecha->copy()->endOfMonth(); $debitos = Model::factory(Transaccion::class) ->whereEqual('debito_id', $cuenta->id) ->whereRaw("fecha BETWEEN '{$start->format('Y-m-d')}' AND '{$end->format('Y-m-d')}'") ->findMany(); if ($debitos) { array_walk($debitos, function(&$item) { $item->valor *= -1; }); } $creditos = Model::factory(Transaccion::class) ->whereEqual('credito_id', $cuenta->id) ->whereRaw("fecha BETWEEN '{$start->format('Y-m-d')}' AND '{$end->format('Y-m-d')}'") ->findMany(); return array_merge($debitos, $creditos); } }