Redis service

This commit is contained in:
2023-10-19 20:46:52 -03:00
parent 742c0327c2
commit dc217d876a
10 changed files with 228 additions and 97 deletions

View File

@ -0,0 +1,15 @@
<?php
namespace Incoviba\Common\Implement\Exception;
use Throwable;
use Exception;
class EmptyRedis extends Exception
{
public function __construct(string $key, ?Throwable $previous = null)
{
$message = "Redis key {$key} not found in database.";
$code = 750;
parent::__construct($message, $code, $previous);
}
}

View File

@ -9,6 +9,7 @@
"nyholm/psr7-server": "^1.0",
"php-di/php-di": "^7.0",
"php-di/slim-bridge": "^3.4",
"predis/predis": "^2.2",
"slim/slim": "^4.11"
},
"require-dev": {

View File

@ -19,4 +19,11 @@ return [
return (new Incoviba\Service\Money())->register('uf', $mindicador)
->register('ipc', $mindicador);
},
Predis\Client::class => function(ContainerInterface $container) {
return new Predis\Client([
'scheme' => 'tcp',
'host' => $container->get('REDIS_HOST'),
'port' => $container->get('REDIS_PORT')
]);
}
];

View File

@ -1,6 +1,8 @@
<?php
namespace Incoviba\Controller\API;
use DateTimeImmutable;
use Incoviba\Common\Implement\Exception\EmptyRedis;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Implement\Exception\EmptyResult;
@ -10,7 +12,7 @@ use Incoviba\Service;
class Ventas
{
use withJson;
use withJson, withRedis;
public function proyecto(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta $service): ResponseInterface
{
@ -46,29 +48,40 @@ class Ventas
}
return $this->withJson($response, $output);
}
public function porFirmar(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService): ResponseInterface
public function porFirmar(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService, Service\Redis $redisService): ResponseInterface
{
$body = $request->getBody();
$json = json_decode($body->getContents());
$proyecto_id = $json->proyecto_id;
$today = new DateTimeImmutable();
$redisKey = "promesas_por_firmar-{$proyecto_id}-{$today->format('Y-m-d')}";
$output = [
'proyecto_id' => $proyecto_id,
'promesas' => 0
];
try {
$ventas = $ventaService->getByProyecto($proyecto_id);
$promesas = array_filter($ventas, function(Model\Venta $venta) {
return $venta->currentEstado()->tipoEstadoVenta->descripcion === 'vigente';
});
$output['promesas'] = count($promesas);
} catch (EmptyResult) {}
$output = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$ventas = $ventaService->getByProyecto($proyecto_id);
$promesas = array_filter($ventas, function(Model\Venta $venta) {
return $venta->currentEstado()->tipoEstadoVenta->descripcion === 'vigente';
});
$output['promesas'] = count($promesas);
$this->saveRedis($redisService, $redisKey, $output);
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
public function escrituras(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService, Service\Venta\Pago $pagoService): ResponseInterface
public function escrituras(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService, Service\Venta\Pago $pagoService, Service\Redis $redisService): ResponseInterface
{
$body = $request->getBody();
$json = json_decode($body->getContents());
$proyecto_id = $json->proyecto_id;
$today = new DateTimeImmutable();
$redisKey = "escrituras-{$proyecto_id}-{$today->format('Y-m-d')}";
$output = [
'proyecto_id' => $proyecto_id,
'escrituras' => [
@ -78,35 +91,40 @@ class Ventas
]
];
try {
$ventas = $ventaService->getEscriturasByProyecto($proyecto_id);
$porFirmar = array_filter($ventas, function(Model\Venta $venta) {
return $venta->currentEstado()->tipoEstadoVenta->descripcion === 'escriturando';
});
$output['escrituras']['firmar'] = count($porFirmar);
unset($porFirmar);
$escrituras = array_filter($ventas, function(Model\Venta $venta) {
return $venta->currentEstado()->tipoEstadoVenta->descripcion === 'firmado por inmobiliaria';
});
unset($ventas);
$porPagar = array_filter($escrituras, function(Model\Venta $venta) use ($pagoService) {
$pagos = $pagoService->getByVenta($venta->id);
$porPagar = array_filter($pagos, function(Model\Venta\Pago $pago) {
return $pago->currentEstado->tipoEstadoPago->descripcion === 'no pagado';
$output = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$ventas = $ventaService->getEscriturasByProyecto($proyecto_id);
$porFirmar = array_filter($ventas, function(Model\Venta $venta) {
return $venta->currentEstado()->tipoEstadoVenta->descripcion === 'escriturando';
});
return count($porPagar) > 0;
});
$output['escrituras']['pagar'] = count($porPagar);
unset($porPagar);
$porAbonar = array_filter($escrituras, function(Model\Venta $venta) use ($pagoService) {
$pagos = $pagoService->getByVenta($venta->id);
$porPagar = array_filter($pagos, function(Model\Venta\Pago $pago) {
return $pago->currentEstado->tipoEstadoPago->descripcion === 'depositado';
$output['escrituras']['firmar'] = count($porFirmar);
unset($porFirmar);
$escrituras = array_filter($ventas, function(Model\Venta $venta) {
return $venta->currentEstado()->tipoEstadoVenta->descripcion === 'firmado por inmobiliaria';
});
return count($porPagar) > 0;
});
$output['escrituras']['abonar'] = count($porAbonar);
unset($porAbonar);
} catch (EmptyResult) {}
unset($ventas);
$porPagar = array_filter($escrituras, function(Model\Venta $venta) use ($pagoService) {
$pagos = $pagoService->getByVenta($venta->id);
$porPagar = array_filter($pagos, function(Model\Venta\Pago $pago) {
return $pago->currentEstado->tipoEstadoPago->descripcion === 'no pagado';
});
return count($porPagar) > 0;
});
$output['escrituras']['pagar'] = count($porPagar);
unset($porPagar);
$porAbonar = array_filter($escrituras, function(Model\Venta $venta) use ($pagoService) {
$pagos = $pagoService->getByVenta($venta->id);
$porPagar = array_filter($pagos, function(Model\Venta\Pago $pago) {
return $pago->currentEstado->tipoEstadoPago->descripcion === 'depositado';
});
return count($porPagar) > 0;
});
$output['escrituras']['abonar'] = count($porAbonar);
unset($porAbonar);
$this->saveRedis($redisService, $redisKey, $output);
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
public function comentarios(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $service, Repository\Venta\Comentario $comentarioRepository, int $venta_id): ResponseInterface

View File

@ -3,71 +3,94 @@ namespace Incoviba\Controller\API\Ventas;
use DateTimeImmutable;
use DateInterval;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Controller\API\withRedis;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Implement\Exception\EmptyRedis;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Repository;
use Incoviba\Service;
class Cuotas
{
use withJson;
public function hoy(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository): ResponseInterface
use withJson, withRedis;
public function hoy(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository, Service\Redis $redisService): ResponseInterface
{
$today = new DateTimeImmutable();
$redisKey = "cuotas_hoy-{$today->format('Y-m-d')}";
$output = [
'cuotas' => 0
];
try {
$output['cuotas'] = count($cuotaRepository->fetchHoy());
} catch (EmptyResult) {}
$output['cuotas'] = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$output['cuotas'] = count($cuotaRepository->fetchHoy());
$this->saveRedis($redisService, $redisKey, $output['cuotas']);
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
public function pendiente(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository): ResponseInterface
public function pendiente(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository, Service\Redis $redisService): ResponseInterface
{
$today = new DateTimeImmutable();
$redisKey = "cuotas_pendientes-{$today->format('Y-m-d')}";
$output = [
'cuotas' => 0
];
try {
$output['cuotas'] = count($cuotaRepository->fetchPendientes());
} catch (EmptyResult) {}
$output['cuotas'] = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$output['cuotas'] = count($cuotaRepository->fetchPendientes());
$this->saveRedis($redisService, $redisKey, $output['cuotas']);
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
public function porVencer(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository, Service\Format $formatService): ResponseInterface
public function porVencer(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Cuota $cuotaRepository, Service\Redis $redisService, Service\Format $formatService): ResponseInterface
{
$output = [];
$today = new DateTimeImmutable();
$redisKey = "cuotas_por_vencer-{$today->format('Y-m-d')}";
try {
$benchmark = [
'start' => microtime(true)
];
$cuotas = $cuotaRepository->fetchDatosPorVencer();
$benchmark['cuotas'] = microtime(true) - $benchmark['start'];
foreach ($cuotas as $row) {
$fecha = $row['Fecha'];
$date = new DateTimeImmutable($fecha);
if (($weekday = $date->format('N')) > 5) {
$day_diff = 7 - $weekday + 1;
$date = $date->add(new DateInterval("P{$day_diff}D"));
$fecha = $date->format('Y-m-d');
$output = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
$output = [];
try {
$benchmark = [
'start' => microtime(true)
];
$cuotas = $cuotaRepository->fetchDatosPorVencer();
$benchmark['cuotas'] = microtime(true) - $benchmark['start'];
foreach ($cuotas as $row) {
$fecha = $row['Fecha'];
$date = new DateTimeImmutable($fecha);
if (($weekday = $date->format('N')) > 5) {
$day_diff = 7 - $weekday + 1;
$date = $date->add(new DateInterval("P{$day_diff}D"));
$fecha = $date->format('Y-m-d');
}
$key = $formatService->localDate($fecha, "EEE. dd 'de' MMMM 'de' yyyy", true);
if (!isset($output[$key])) {
$output[$key] = [];
}
if (!isset($output[$key][$row['Proyecto']])) {
$output[$key][$row['Proyecto']] = 0;
}
$output[$key][$row['Proyecto']] += $row['Cantidad'];
}
$key = $formatService->localDate($fecha, "EEE. dd 'de' MMMM 'de' yyyy", true);
if (!isset($output[$key])) {
$output[$key] = [];
foreach ($output as $key => $day) {
uksort($day, function($a, $b) {
return strcmp($a, $b);
});
$output[$key] = $day;
}
if (!isset($output[$key][$row['Proyecto']])) {
$output[$key][$row['Proyecto']] = 0;
}
$output[$key][$row['Proyecto']] += $row['Cantidad'];
}
foreach ($output as $key => $day) {
uksort($day, function($a, $b) {
return strcmp($a, $b);
});
$output[$key] = $day;
}
$benchmark['run'] = microtime(true) - $benchmark['start'];
error_log(var_export($benchmark,true));
} catch (EmptyResult) {}
$benchmark['run'] = microtime(true) - $benchmark['start'];
error_log(var_export($benchmark,true));
$this->saveRedis($redisService, $redisKey, $output);
} catch (EmptyResult) {}
}
return $this->withJson($response, ['cuotas' => $output]);
}
}

View File

@ -1,22 +1,29 @@
<?php
namespace Incoviba\Controller\API\Ventas;
use DateTimeImmutable;
use Incoviba\Common\Implement\Exception\EmptyRedis;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Controller\API\withRedis;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
class Unidades
{
use withJson;
use withJson, withRedis;
public function disponibles(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Unidad $unidadRepository, Repository\Proyecto\TipoUnidad $tipoUnidadRepository): ResponseInterface
public function disponibles(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Unidad $unidadRepository, Repository\Proyecto\TipoUnidad $tipoUnidadRepository, Service\Redis $redisService): ResponseInterface
{
$body = $request->getBody();
$json = json_decode($body->getContents());
$proyecto_id = $json->proyecto_id;
$today = new DateTimeImmutable();
$redisKey = "unidades_disponibles-{$proyecto_id}-{$today->format('Y-m-d')}";
$output = [
'proyecto_id' => $proyecto_id,
'unidades' => [
@ -31,26 +38,31 @@ class Unidades
]
];
try {
$totalUnidades = $unidadRepository->fetchByProyecto($proyecto_id);
$unidades = $unidadRepository->fetchDisponiblesByProyecto($proyecto_id);
$output = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$totalUnidades = $unidadRepository->fetchByProyecto($proyecto_id);
$unidades = $unidadRepository->fetchDisponiblesByProyecto($proyecto_id);
$tiposUnidades = $tipoUnidadRepository->fetchAll();
foreach ($tiposUnidades as $tipoUnidad) {
$tempUnidades = array_filter($totalUnidades, function(Model\Venta\Unidad $unidad) use ($tipoUnidad) {
return $unidad->proyectoTipoUnidad->tipoUnidad->id === $tipoUnidad->id;
});
if (count($tempUnidades) > 0) {
$output['unidades']['total']["{$tipoUnidad->descripcion}s"] = count($tempUnidades);
$tiposUnidades = $tipoUnidadRepository->fetchAll();
foreach ($tiposUnidades as $tipoUnidad) {
$tempUnidades = array_filter($totalUnidades, function(Model\Venta\Unidad $unidad) use ($tipoUnidad) {
return $unidad->proyectoTipoUnidad->tipoUnidad->id === $tipoUnidad->id;
});
if (count($tempUnidades) > 0) {
$output['unidades']['total']["{$tipoUnidad->descripcion}s"] = count($tempUnidades);
}
$tempUnidades = array_filter($unidades, function(Model\Venta\Unidad $unidad) use ($tipoUnidad) {
return $unidad->proyectoTipoUnidad->tipoUnidad->id === $tipoUnidad->id;
});
if (count($tempUnidades) === 0) {
continue;
}
$output['unidades']["{$tipoUnidad->descripcion}s"] = count($tempUnidades);
}
$tempUnidades = array_filter($unidades, function(Model\Venta\Unidad $unidad) use ($tipoUnidad) {
return $unidad->proyectoTipoUnidad->tipoUnidad->id === $tipoUnidad->id;
});
if (count($tempUnidades) === 0) {
continue;
}
$output['unidades']["{$tipoUnidad->descripcion}s"] = count($tempUnidades);
}
} catch (EmptyResult) {}
$this->saveRedis($redisService, $redisKey, $output);
} catch (EmptyResult) {}
}
return $this->withJson($response, $output);
}
}

View File

@ -5,7 +5,7 @@ use Psr\Http\Message\ResponseInterface;
trait withJson
{
public function withJson(ResponseInterface $response, array $data = []): ResponseInterface
public function withJson(ResponseInterface $response, array|object $data = []): ResponseInterface
{
$response->getBody()->write(json_encode($data));
return $response->withHeader('Content-Type', 'application/json');

View File

@ -0,0 +1,24 @@
<?php
namespace Incoviba\Controller\API;
use Incoviba\Common\Implement\Exception\EmptyRedis;
use Incoviba\Service;
trait withRedis
{
public function fetchRedis(Service\Redis $redisService, string $redisKey): mixed
{
$jsonString = $redisService->get($redisKey);
if ($jsonString === null) {
throw new EmptyRedis($redisKey);
}
return json_decode($jsonString);
}
public function saveRedis(Service\Redis $redisService, string $redisKey, mixed $value): void
{
if (is_array($value) or is_object($value)) {
$value = json_encode($value);
}
$redisService->set($redisKey, $value);
}
}

18
app/src/Service/Redis.php Normal file
View File

@ -0,0 +1,18 @@
<?php
namespace Incoviba\Service;
use Predis\Client;
class Redis
{
public function __construct(protected Client $client) {}
public function get(string $name): mixed
{
return $this->client->get($name);
}
public function set(string $name, mixed $value): void
{
$this->client->set($name, $value);
}
}

View File

@ -47,6 +47,18 @@ services:
- default
- adminer_network
redis:
profiles:
- cache
image: redis
container_name: incoviba_redis
<<: *restart
env_file: ${APP_PATH:-.}/.redis.env
volumes:
- incoviba_redis:/data
ports:
- "63790:6379"
python:
profiles:
- python
@ -74,6 +86,7 @@ services:
volumes:
dbdata: {}
incoviba_redis: {}
networks:
adminer_network: {}