Files
contabilidad/api/common/Service/Consolidar.php
2022-03-25 15:04:10 -03:00

156 lines
5.2 KiB
PHP

<?php
namespace Contabilidad\Common\Service;
use Carbon\Carbon;
use Contabilidad\Queue;
use \Model;
use ProVM\Common\Factory\Model as ModelFactory;
use Contabilidad\Consolidado;
use Contabilidad\Cuenta;
use Contabilidad\Transaccion;
class Consolidar {
protected $factory;
public function __construct(ModelFactory $factory) {
$this->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);
}
}