175 lines
5.8 KiB
PHP
175 lines
5.8 KiB
PHP
<?php
|
|
namespace Contabilidad\Common\Service;
|
|
|
|
use Carbon\Carbon;
|
|
use \Model;
|
|
use ProVM\Common\Factory\Model as ModelFactory;
|
|
use Contabilidad\Consolidado;
|
|
use Contabilidad\Cuenta;
|
|
use Contabilidad\Transaccion;
|
|
|
|
class Consolidar {
|
|
public function __construct(ModelFactory $factory, Queuer $queuer) {
|
|
$this->setFactory($factory);
|
|
$this->setQueuer($queuer);
|
|
}
|
|
protected ModelFactory $factory;
|
|
public function setFactory(ModelFactory $factory): Consolidar {
|
|
$this->factory = $factory;
|
|
return $this;
|
|
}
|
|
protected Queuer $queuer;
|
|
public function setQueuer(Queuer $queuer): Consolidar {
|
|
$this->queuer = $queuer;
|
|
return $this;
|
|
}
|
|
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() {
|
|
$this->queuer->queue('consolidar');
|
|
}
|
|
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()) {
|
|
$this->consolidarCuenta($cuenta, $current);
|
|
}
|
|
}
|
|
}
|
|
public function consolidarCuenta(Cuenta $cuenta, Carbon $mes) {
|
|
if (!$cuenta->hasTransacciones($mes)) {
|
|
return;
|
|
}
|
|
$transacciones = $this->getTransacciones($cuenta, $mes);
|
|
if (count($transacciones) == 0) {
|
|
return;
|
|
}
|
|
array_walk($transacciones, function(&$item) use ($cuenta) {
|
|
$item->valor = $item->transformar($cuenta->moneda());
|
|
});
|
|
$saldo = array_reduce($transacciones, function($sum, $item) {
|
|
return $sum + $item->valor;
|
|
});
|
|
if ($cuenta->tipo()->cargo()) {
|
|
$saldo += -1;
|
|
}
|
|
$consolidado = $this->factory->find(Consolidado::class)->where([['cuenta_id', $cuenta->id], ['fecha', $mes->format('Y-m-1')]])->one();
|
|
if ($consolidado === null) {
|
|
$data = [
|
|
'cuenta_id' => $cuenta->id,
|
|
'fecha' => $mes->format('Y-m-1'),
|
|
'periodo' => 'P1M',
|
|
'saldo' => $saldo
|
|
];
|
|
$consolidado = $this->factory->create(Consolidado::class, $data);
|
|
}
|
|
$consolidado->saldo = $saldo;
|
|
$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();
|
|
$transacciones = array_merge($debitos, $creditos);
|
|
foreach ($transacciones as &$transaccion) {
|
|
$transaccion->setFactory($this->factory);
|
|
}
|
|
return $transacciones;
|
|
}
|
|
}
|