Consolidar
This commit is contained in:
53
api/common/Controller/Consolidados.php
Normal file
53
api/common/Controller/Consolidados.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use Contabilidad\Common\Service\Consolidar as Service;
|
||||
use Contabilidad\Consolidado;
|
||||
|
||||
class Consolidados {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory, $cuenta_id): Response {
|
||||
$consolidados = $factory->find(Consolidados::class)->where([['cuenta_id' => $cuenta_id]])->many();
|
||||
$output = [
|
||||
'consolidados' => array_map(function($item) {
|
||||
return $item->toArray();
|
||||
}, $consolidados)
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function add(Request $request, Response $response, Factory $factory): Response {
|
||||
$input = json_decode($request->getBody()->getContents());
|
||||
$output = [
|
||||
'input' => $input,
|
||||
'consolidados' => []
|
||||
];
|
||||
if (!is_array($input)) {
|
||||
$input = [$input];
|
||||
}
|
||||
foreach ($input as $data) {
|
||||
$consolidado = Consolidado::add($factory, $data);
|
||||
$status = $consolidado->save();
|
||||
$output['consolidados'] []= [
|
||||
'consolidado' => $consolidado->toArray(),
|
||||
'added' => $status
|
||||
];
|
||||
}
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function cli(Request $request, Response $response, Service $service): Response {
|
||||
try {
|
||||
if (!$service->isConsolidado()) {
|
||||
$service->consolidar();
|
||||
}
|
||||
} catch (\Error | \Exception $e) {
|
||||
error_log($e);
|
||||
throw $e;
|
||||
}
|
||||
return $this->withJson($response);
|
||||
}
|
||||
}
|
20
api/common/Middleware/Consolidar.php
Normal file
20
api/common/Middleware/Consolidar.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Middleware;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Server\RequestHandlerInterface as Handler;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Contabilidad\Common\Service\Consolidar as ConsolidarService;
|
||||
|
||||
class Consolidar {
|
||||
protected $service;
|
||||
public function __construct(ConsolidarService $service) {
|
||||
$this->service = $service;
|
||||
}
|
||||
public function __invoke(Request $request, Handler $handler): Response {
|
||||
if (!$this->service->isConsolidado()) {
|
||||
$this->service->consolidar();
|
||||
}
|
||||
return $handler->handle($request);
|
||||
}
|
||||
}
|
148
api/common/Service/Consolidar.php
Normal file
148
api/common/Service/Consolidar.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?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 {
|
||||
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() {
|
||||
$consolidado = true;
|
||||
$cuentas = $this->getCuentas();
|
||||
if ($cuentas === null) {
|
||||
return false;
|
||||
}
|
||||
foreach ($cuentas as $cuenta) {
|
||||
$transacciones = $cuenta->hasTransacciones();
|
||||
if (!$transacciones) {
|
||||
continue;
|
||||
}
|
||||
$consolidados = $cuenta->hasConsolidados();
|
||||
if (!$consolidados and $transacciones) {
|
||||
$consolidado = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $consolidado;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
4
api/resources/routes/consolidar.php
Normal file
4
api/resources/routes/consolidar.php
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
use Contabilidad\Common\Controller\Consolidados;
|
||||
|
||||
$app->get('/consolidar', [Consolidados::class, 'cli']);
|
8
api/setup/setups/03_consolidar.php
Normal file
8
api/setup/setups/03_consolidar.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
use Psr\Container\ContainerInterface as Container;
|
||||
|
||||
return [
|
||||
\Contabilidad\Common\Service\Consolidar::class => function(Container $container) {
|
||||
return new \Contabilidad\Common\Service\Consolidar($container->get(\ProVM\Common\Factory\Model::class));
|
||||
}
|
||||
];
|
51
api/src/Consolidado.php
Normal file
51
api/src/Consolidado.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
namespace Contabilidad;
|
||||
|
||||
use DateTimeInterface;
|
||||
use DateInterval;
|
||||
use Carbon\Carbon;
|
||||
use Carbon\CarbonInterval;
|
||||
use ProVM\Common\Alias\Model;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property Cuenta $cuenta_id
|
||||
* @property DateTimeInterface $fecha
|
||||
* @property DateInterval $periodo
|
||||
* @property float $saldo
|
||||
*/
|
||||
class Consolidado extends Model {
|
||||
public static $_table = 'consolidados';
|
||||
|
||||
protected $cuenta;
|
||||
public function cuenta() {
|
||||
if ($this->cuenta === null) {
|
||||
$this->cuenta = $this->childOf(Cuenta::class, [Model::SELF_KEY => 'cuenta_id']);
|
||||
}
|
||||
return $this->cuenta;
|
||||
}
|
||||
public function fecha(DateTimeInterface $fecha = null) {
|
||||
if ($fecha === null) {
|
||||
return Carbon::parse($this->fecha);
|
||||
}
|
||||
if ($this->periodo()->days > 31) {
|
||||
$this->fecha = $fecha->format('Y-1-1');
|
||||
} else {
|
||||
$this->fecha = $fecha->format('Y-m-1');
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function periodo(DateInterval $periodo = null) {
|
||||
if ($periodo === null) {
|
||||
return new CarbonInterval($this->periodo);
|
||||
}
|
||||
$this->periodo = CarbonInterval::getDateIntervalSpec($periodo);
|
||||
return $this;
|
||||
}
|
||||
public function saldo(DateTimeInterface $fecha = null) {
|
||||
if ($fecha === null) {
|
||||
$fecha = $this->fecha();
|
||||
}
|
||||
return $this->cuenta()->moneda()->cambiar($fecha, $this->saldo);
|
||||
}
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
<?php
|
||||
namespace Contabilidad;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Carbon\Carbon;
|
||||
use PhpParser\Node\Expr\AssignOp\Mod;
|
||||
use ProVM\Common\Alias\Model;
|
||||
use Contabilidad\Common\Service\TiposCambios as Service;
|
||||
|
||||
@ -54,7 +52,34 @@ class Cuenta extends Model {
|
||||
}
|
||||
return $this->abonos;
|
||||
}
|
||||
protected $consolidados;
|
||||
public function consolidados() {
|
||||
if ($this->consolidados === null) {
|
||||
$this->consolidados = $this->parentOf(Consolidado::class, [Model::CHILD_KEY => 'cuenta_id']);
|
||||
}
|
||||
return $this->consolidados;
|
||||
}
|
||||
public function hasConsolidados(): bool {
|
||||
return (bool) Model::factory(Consolidado::class)
|
||||
->whereEqual('cuenta_id', $this->id)
|
||||
->count('id');
|
||||
}
|
||||
public function hasTransacciones(): bool {
|
||||
return (bool) Model::factory(Transaccion::class)
|
||||
->select('transacciones.*')
|
||||
->join('cuentas', 'cuentas.id = transacciones.debito_id OR cuentas.id = transacciones.credito_id')
|
||||
->whereEqual('cuentas.id', $this->id)
|
||||
->count('transacciones.id');
|
||||
}
|
||||
protected $transacciones;
|
||||
protected function parseTransaccion(Transaccion $transaccion) {
|
||||
$transaccion->setFactory($this->factory);
|
||||
if ($transaccion->debito_id === $this->id) {
|
||||
$transaccion->valor = - $transaccion->valor;
|
||||
}
|
||||
$transaccion->valor = $transaccion->transformar($this->moneda());
|
||||
return $transaccion;
|
||||
}
|
||||
public function transacciones($limit = null, $start = 0) {
|
||||
$transacciones = Model::factory(Transaccion::class)
|
||||
->select('transacciones.*')
|
||||
@ -67,10 +92,7 @@ class Cuenta extends Model {
|
||||
}
|
||||
$transacciones = $transacciones->findMany();
|
||||
foreach ($transacciones as &$transaccion) {
|
||||
$transaccion->setFactory($this->factory);
|
||||
if ($transaccion->debito_id === $this->id) {
|
||||
$transaccion->valor = - $transaccion->valor;
|
||||
}
|
||||
$transaccion = $this->parseTransaccion($transaccion);
|
||||
}
|
||||
return $transacciones;
|
||||
}
|
||||
@ -87,30 +109,21 @@ class Cuenta extends Model {
|
||||
$transacciones = $transacciones->findMany();
|
||||
|
||||
foreach ($transacciones as &$transaccion) {
|
||||
$transaccion->setFactory($this->factory);
|
||||
if ($transaccion->desde_id === $this->id) {
|
||||
$transaccion->valor = - $transaccion->valor;
|
||||
}
|
||||
$transaccion = $this->parseTransaccion($transaccion);
|
||||
}
|
||||
|
||||
return $transacciones;
|
||||
}
|
||||
public function acumulacion(Carbon $date) {
|
||||
$abonos = Model::factory(Transaccion::class)
|
||||
->whereEqual('credito_id', $this->id)
|
||||
->whereLt('fecha', $date->format('Y-m-d'))
|
||||
->groupBy('credito_id')
|
||||
->sum('valor');
|
||||
$cargos = Model::factory(Transaccion::class)
|
||||
->whereEqual('debito_id', $this->id)
|
||||
->whereLt('fecha', $date->format('Y-m-d'))
|
||||
->groupBy('debito_id')
|
||||
->sum('valor');
|
||||
|
||||
if (in_array($this->tipo()->descripcion, ['activo', 'banco', 'perdida'])) {
|
||||
return $abonos - $cargos;
|
||||
$consolidados = $this->consolidados();
|
||||
$saldo = 0;
|
||||
foreach ($consolidados as $consolidado) {
|
||||
if ($consolidado->fecha() >= $date) {
|
||||
continue;
|
||||
}
|
||||
$saldo += $consolidado->saldo($date);
|
||||
}
|
||||
return $cargos - $abonos;
|
||||
return $saldo;
|
||||
}
|
||||
protected $saldo;
|
||||
public function saldo(Service $service = null, $in_clp = false) {
|
||||
|
@ -22,19 +22,22 @@ class Moneda extends Model {
|
||||
$this->sufijo
|
||||
]));
|
||||
}
|
||||
public function cambio(\DateTime $fecha) {
|
||||
public function cambio(\DateTime $fecha, Moneda $moneda = null) {
|
||||
if ($moneda === null) {
|
||||
$moneda = $this->factory->find(Moneda::class)->one(1);
|
||||
}
|
||||
$cambio = $this->factory->find(TipoCambio::class)
|
||||
->where([['desde_id', $this->id], ['hasta_id', 1], ['fecha', $fecha->format('Y-m-d H:i:s')]])
|
||||
->where([['desde_id', $this->id], ['hasta_id', $moneda->id], ['fecha', $fecha->format('Y-m-d H:i:s')]])
|
||||
->one();
|
||||
if ($cambio === null) {
|
||||
$cambio = $this->factory->find(TipoCambio::class)
|
||||
->where([['hasta_id', $this->id], ['desde_id', 1], ['fecha', $fecha->format('Y-m-d H:i:s')]])
|
||||
->where([['hasta_id', $this->id], ['desde_id', $moneda->id], ['fecha', $fecha->format('Y-m-d H:i:s')]])
|
||||
->one();
|
||||
}
|
||||
return $cambio;
|
||||
}
|
||||
public function cambiar(\DateTime $fecha, float $valor) {
|
||||
$cambio = $this->cambio($fecha);
|
||||
public function cambiar(\DateTime $fecha, float $valor, Moneda $moneda = null) {
|
||||
$cambio = $this->cambio($fecha, $moneda);
|
||||
if (!$cambio) {
|
||||
return $valor;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ use ProVM\Common\Alias\Model;
|
||||
* @property string $glosa
|
||||
* @property string $detalle
|
||||
* @property double $valor
|
||||
* @property Moneda $moneda_id
|
||||
*/
|
||||
class Transaccion extends Model {
|
||||
public static $_table = 'transacciones';
|
||||
@ -37,6 +38,21 @@ class Transaccion extends Model {
|
||||
return Carbon::parse($this->fecha);
|
||||
}
|
||||
$this->fecha = $fecha->format('Y-m-d');
|
||||
return $this;
|
||||
}
|
||||
protected $moneda;
|
||||
public function moneda() {
|
||||
if ($this->moneda === null) {
|
||||
$this->moneda = $this->childOf(Moneda::class, [Model::SELF_KEY => 'moneda_id']);
|
||||
}
|
||||
return $this->moneda;
|
||||
}
|
||||
|
||||
public function transformar(Moneda $moneda = null) {
|
||||
if (($moneda !== null and $this->moneda()->id === $moneda->id) or ($moneda === null and $this->moneda()->id === 1)) {
|
||||
return $this->valor;
|
||||
}
|
||||
return $this->moneda()->cambiar($this->fecha(), $this->valor, $moneda);
|
||||
}
|
||||
|
||||
public function toArray(): array {
|
||||
|
Reference in New Issue
Block a user