Files
This commit is contained in:
@ -90,7 +90,7 @@ abstract class Model extends BaseModel implements ModelInterface {
|
||||
protected static function parseInput($input): array {
|
||||
return array_intersect_key((array) $input, array_combine(static::$fields, static::$fields));
|
||||
}
|
||||
public static function add(ModelFactory $factory, $input): ?ModelInterface {
|
||||
public static function add(ModelFactory $factory, $input): bool|ModelInterface {
|
||||
$data = static::parseInput($input);
|
||||
$class = get_called_class();
|
||||
if (method_exists($class, 'find')) {
|
||||
@ -103,7 +103,7 @@ abstract class Model extends BaseModel implements ModelInterface {
|
||||
$where = array_values($where);
|
||||
$obj = $factory->find($class)->where($where)->one();
|
||||
}
|
||||
if ($obj === null) {
|
||||
if ($obj === false or $obj === null) {
|
||||
$obj = $factory->create($class, $data);
|
||||
}
|
||||
return $obj;
|
||||
|
82
common/Controller/Auth.php
Normal file
82
common/Controller/Auth.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
namespace Incoviba\API\Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Incoviba\API\Common\Define\Controller\Json;
|
||||
use Incoviba\API\Common\Service\Auth as Service;
|
||||
use Incoviba\API\Common\Factory\Model as Factory;
|
||||
use Incoviba\Auth\User;
|
||||
use Incoviba\Auth\Login;
|
||||
|
||||
class Auth {
|
||||
use Json;
|
||||
|
||||
public function generate(Request $request, Response $response, Service $service): Response {
|
||||
$key = $service->generate();
|
||||
return $this->withJson($response, compact('key'));
|
||||
}
|
||||
public function login(Request $request, Response $response, Service $service, Factory $factory): Response {
|
||||
$post = json_decode($request->getBody());
|
||||
$user = $factory->find(User::class)->where([['name', $post->name]])->one();
|
||||
$output = [
|
||||
'login' => false,
|
||||
'token' => ''
|
||||
];
|
||||
if ($user->enabled == 0) {
|
||||
$this->withJson($response, $output);
|
||||
}
|
||||
if ($user->validate($post->password)) {
|
||||
$token = $service->generateToken();
|
||||
$status = $user->setToken($token->selector, $token->token);
|
||||
if ($status['logged_in']) {
|
||||
$output['login'] = true;
|
||||
$output['token'] = $token->full;
|
||||
$output['expires'] = $status['expires'];
|
||||
}
|
||||
}
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
protected function getLogin(object $post, Factory $factory): bool|Login {
|
||||
list($selector, $token) = explode(':', $post->token); //Token from the cookie
|
||||
$login = $factory->find(Login::class)->where([['selector', $selector]])->one();
|
||||
if ($login === false or !password_verify($token, $login->token) or !$login->isValid()) {
|
||||
return false;
|
||||
}
|
||||
return $login;
|
||||
}
|
||||
public function validate(Request $request, Response $response, Factory $factory): Response {
|
||||
$post = json_decode($request->getBody());
|
||||
if (!$this->getLogin($post, $factory)) {
|
||||
return $this->withJson($response, ['token' => $post->token, 'error' => 'Not authorized'], 401);
|
||||
}
|
||||
return $this->withJson($response, ['token' => $post->token, 'status' => 'Authorized']);
|
||||
}
|
||||
public function user(Request $request, Response $response, Factory $factory): Response {
|
||||
$post = json_decode($request->getBody());
|
||||
$login = $this->getLogin($post, $factory);
|
||||
if (!$login) {
|
||||
return $this->withJson($response, ['token' => $post->token, 'error' => 'Not authorized'], 401);
|
||||
}
|
||||
$output = [
|
||||
'token' => $post->token,
|
||||
'user' => $login->user()->name
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function logout(Request $request, Response $response, Factory $factory): Response {
|
||||
$post = json_decode($request->getBody());
|
||||
list($selector, $token) = explode(':', $post->token); //Token from the cookie
|
||||
$login = $factory->find(Login::class)->where([['selector', $selector]])->one();
|
||||
$output = [
|
||||
'token' => $post->token,
|
||||
'logout' => false
|
||||
];
|
||||
if ($login !== false) {
|
||||
$output['logout'] = $login->user()->logout();
|
||||
} else {
|
||||
$output['logout'] = true;
|
||||
}
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
43
common/Controller/Configs.php
Normal file
43
common/Controller/Configs.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
namespace Incoviba\API\Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Incoviba\API\Common\Factory\Model as Factory;
|
||||
use Incoviba\API\Common\Define\Controller\Json;
|
||||
use Incoviba\Admin\Config;
|
||||
|
||||
class Configs {
|
||||
use Json;
|
||||
|
||||
public function get(Request $request, Response $response, Factory $factory, $config_name): Response {
|
||||
$config = $factory->find(Config::class)->where((['name', $config_name]))->one();
|
||||
$output = [
|
||||
'name' => $config_name,
|
||||
'valid' => $config !== false,
|
||||
'value' => $config->value
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function set(Request $request, Response $response, Factory $factory): Response {
|
||||
$post = $request->getParsedBody();
|
||||
$config = $factory->find(Config::class)->where([['name', $post['name']]])->one();
|
||||
if (!$config) {
|
||||
$config = Config::add($factory, $post);
|
||||
} else {
|
||||
$config->edit($post);
|
||||
}
|
||||
$output = [
|
||||
'input' => $post,
|
||||
'config' => null
|
||||
];
|
||||
if ($config !== false) {
|
||||
$config->save();
|
||||
$output['config'] = [
|
||||
'name' => $config->name,
|
||||
'value' => $config->value
|
||||
];
|
||||
}
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
31
common/Controller/Proyectos/Cierres.php
Normal file
31
common/Controller/Proyectos/Cierres.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
namespace Incoviba\API\Common\Controller\Proyectos;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Incoviba\API\Common\Factory\Model as Factory;
|
||||
use Incoviba\API\Common\Define\Controller\Json;
|
||||
use Incoviba\Proyecto\Proyecto;
|
||||
|
||||
class Cierres {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
||||
$proyectos = $factory->find(Proyecto::class)->many();
|
||||
$cierres = [];
|
||||
foreach ($proyectos as $proyecto) {
|
||||
if (count($proyecto->cierres()) == 0) {
|
||||
continue;
|
||||
}
|
||||
$cierres[$proyecto->descripcion] = [
|
||||
'proyecto' => $proyecto->descripcion,
|
||||
'total' => count($proyecto->cierres()),
|
||||
'promesados' => count($proyecto->cierres(3)),
|
||||
'rechazados' => count($proyecto->cierres(-1)),
|
||||
'pendientes' => count($proyecto->cierres(2)),
|
||||
'ultimo_pendiente' => (count($proyecto->cierres(2)) > 0) ? $proyecto->cierres(2)[0]->periodo() : 0
|
||||
];
|
||||
}
|
||||
return $this->withJson($response, compact('cierres'));
|
||||
}
|
||||
}
|
63
common/Controller/Proyectos/Cuotas.php
Normal file
63
common/Controller/Proyectos/Cuotas.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
namespace Incoviba\API\Common\Controller\Proyectos;
|
||||
|
||||
use Incoviba\Proyecto\Proyecto;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Incoviba\API\Common\Define\Controller\Json;
|
||||
use Incoviba\API\Common\Factory\Model as Factory;
|
||||
|
||||
class Cuotas {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
||||
$proyectos = $factory->find(Proyecto::class)->many();
|
||||
$cuotas = [];
|
||||
foreach ($proyectos as $proyecto) {
|
||||
foreach ($proyecto->cuotas() as $cuota) {
|
||||
$cuotas []= $cuota->toArray();
|
||||
}
|
||||
}
|
||||
return $this->withJson($response, ['cuotas' => $cuotas]);
|
||||
}
|
||||
public function mes(Request $request, Response $response, Factory $factory): Response {
|
||||
$proyectos = $factory->find(Proyecto::class)->many();
|
||||
$dias = [];
|
||||
foreach ($proyectos as $proyecto) {
|
||||
foreach ($proyecto->cuotasMes() as $cuota) {
|
||||
$f = $cuota->pago()->fecha();
|
||||
if ($f->isoWeekday() == 6 or $f->isoWeekDay() == 7) {
|
||||
$f = $f->copy()->addDays(2)->startOfWeek();
|
||||
}
|
||||
$dia = $f->format('Y-m-d');
|
||||
if (!isset($dias[$dia])) {
|
||||
$dias[$dia] = ['dia' => $dia, 'proyectos' => [$proyecto->descripcion => ['proyecto' => $proyecto->descripcion, 'cantidad' => 0]]];
|
||||
}
|
||||
if (!isset($dias[$dia]['proyectos'][$proyecto->descripcion])) {
|
||||
$dias[$dia]['proyectos'][$proyecto->descripcion] = ['proyecto' => $proyecto->descripcion, 'cantidad' => 0];
|
||||
}
|
||||
$dias[$dia]['proyectos'][$proyecto->descripcion]['cantidad'] ++;
|
||||
}
|
||||
}
|
||||
uksort($dias, function($a, $b) {
|
||||
return strcmp($a, $b);
|
||||
});
|
||||
return $this->withJson($response, ['proyecto' => $proyecto->toArray(), 'dias' => $dias]);
|
||||
}
|
||||
public function hoy(Request $request, Response $response, Factory $factory): Response {
|
||||
$proyectos = $factory->find(Proyecto::class)->many();
|
||||
$hoy = 0;
|
||||
foreach ($proyectos as $proyecto) {
|
||||
$hoy += count($proyecto->cuotasHoy());
|
||||
}
|
||||
return $this->withJson($response, ['hoy' => $hoy]);
|
||||
}
|
||||
public function pendientes(Request $request, Response $response, Factory $factory): Response {
|
||||
$proyectos = $factory->find(Proyecto::class)->many();
|
||||
$pendientes = 0;
|
||||
foreach ($proyectos as $proyecto) {
|
||||
$pendientes += count($proyecto->cuotasPendientes());
|
||||
}
|
||||
return $this->withJson($response, ['pendientes' => $pendientes]);
|
||||
}
|
||||
}
|
@ -51,7 +51,7 @@ interface Model {
|
||||
* @param array $input Input data
|
||||
* @return Model|null
|
||||
*/
|
||||
public static function add(ModelFactory $factory, array $input): ?Model;
|
||||
public static function add(ModelFactory $factory, array $input): bool|Model;
|
||||
|
||||
/**
|
||||
* Edit current model parsing {$input} data
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace Incoviba\API\Common\Factory;
|
||||
|
||||
use http\Exception\InvalidArgumentException;
|
||||
use InvalidArgumentException;
|
||||
use ORM;
|
||||
use Incoviba\API\Common\Alias\Model as BaseModel;
|
||||
use Incoviba\API\Common\Define\Model as ModelInterface;
|
||||
@ -27,7 +27,7 @@ class Model {
|
||||
$model = $model->where([[$f, $v]]);
|
||||
}
|
||||
$model = $model->one();
|
||||
if ($model !== null) {
|
||||
if ($model !== false and $model !== null) {
|
||||
return $model;
|
||||
}
|
||||
}
|
||||
@ -142,13 +142,20 @@ class Model {
|
||||
'full', 'full outer', 'full_outer', 'fullouter', 'outer' => 'fullOuterJoin'
|
||||
};
|
||||
if (strtolower($join->type) == 'raw') {
|
||||
if (isset($join->alias)) {
|
||||
$orm = $orm->{$method}($join->table, [$join->from, $join->operator, $join->to], $join->alias, $join->params);
|
||||
if (isset($join->params)) {
|
||||
if (isset($join->alias)) {
|
||||
$orm = $orm->{$method}($join->table, [$join->from, $join->operator, $join->to], $join->alias, $join->params);
|
||||
} else {
|
||||
$orm = $orm->{$method}($join->table, [$join->from, $join->operator, $join->to], $join->params);
|
||||
}
|
||||
} else {
|
||||
$orm = $orm->{$method}($join->table, [$join->from, $join->operator, $join->to], $join->params);
|
||||
if (isset($join->alias)) {
|
||||
$orm = $orm->{$method}($join->table, [$join->from, $join->operator, $join->to], $join->alias);
|
||||
} else {
|
||||
$orm = $orm->{$method}($join->table, [$join->from, $join->operator, $join->to]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($join->alias)) {
|
||||
} elseif (isset($join->alias)) {
|
||||
$orm = $orm->{$method}($join->table, [$join->from, $join->operator, $join->to], $join->alias);
|
||||
} else {
|
||||
$orm = $orm->{$method}($join->table, [$join->from, $join->operator, $join->to]);
|
||||
@ -267,14 +274,34 @@ class Model {
|
||||
return $this;
|
||||
}
|
||||
protected function addOrder($order) {
|
||||
$map = [
|
||||
'column' => ['column', 'col', 'c', 0],
|
||||
'direction' => ['direction', 'dir', 'd', 1]
|
||||
];
|
||||
if (!is_array($order)) {
|
||||
$order = [$order];
|
||||
}
|
||||
$defaults = ['direction' => 'asc'];
|
||||
$required = ['column', 'direction'];
|
||||
$o = [];
|
||||
foreach ($order as $key => $val) {
|
||||
$k = match (strtolower($key)) {
|
||||
/*$k = match (strtolower($key)) {
|
||||
'column', 'col', 'c', 0 => 'column',
|
||||
'direction', 'dir', 'd', 1 => 'direction'
|
||||
};
|
||||
};*/
|
||||
$k = -1;
|
||||
foreach ($map as $i => $m) {
|
||||
if (is_array($m)) {
|
||||
if (in_array($key, $m)) {
|
||||
$k = $i;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ($key == $m) {
|
||||
$k = $i;
|
||||
}
|
||||
}
|
||||
$o[$k] = $val;
|
||||
}
|
||||
foreach ($defaults as $key => $val) {
|
||||
|
@ -4,48 +4,57 @@ namespace Incoviba\API\Common\Service;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class Auth {
|
||||
protected string $key;
|
||||
public function __construct(string $key) {
|
||||
$this->key = $key;
|
||||
}
|
||||
public function isValid(Request $request): bool {
|
||||
$api_key = '';
|
||||
if ($request->hasHeader('Authorization')) {
|
||||
$api_key = $request->getHeader('Authorization');
|
||||
if (is_array($api_key)) {
|
||||
$api_key = $api_key[0];
|
||||
}
|
||||
if (str_contains($api_key, 'Bearer')) {
|
||||
$api_key = explode(' ', $api_key)[1];
|
||||
}
|
||||
} elseif ($request->getParsedBody() !== null and in_array('API_KEY', $request->getParsedBody())) {
|
||||
$api_key = $request->getParsedBody()['API_KEY'];
|
||||
} elseif ($request->getQueryParams() !== null and in_array('API_KEY', array_keys($request->getQueryParams()))) {
|
||||
$api_key = $request->getQueryParams()['API_KEY'];
|
||||
protected string $key;
|
||||
public function __construct(string $key) {
|
||||
$this->key = $key;
|
||||
}
|
||||
if ($this->key == $api_key) {
|
||||
return true;
|
||||
public function isValid(Request $request): bool {
|
||||
$api_key = $this->getRequestKey($request);
|
||||
if ($this->key == $api_key) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public function generate(int $length = 32, bool $removeSimilarCharacters = true): string {
|
||||
$token = "";
|
||||
try {
|
||||
$bytesWithMargin = random_bytes($length*3);
|
||||
|
||||
$base64 = base64_encode($bytesWithMargin);
|
||||
$purified = preg_replace("/[+=\/.]/", "", $base64);
|
||||
|
||||
if ($removeSimilarCharacters){
|
||||
$purified = preg_replace("/[I1l0Oo]/", "", $purified);
|
||||
protected function getRequestKey(Request $request) {
|
||||
if ($request->hasHeader('Authorization')) {
|
||||
return $this->getKeyFromHeader($request);
|
||||
} elseif ($request->getParsedBody() !== null and in_array('API_KEY', $request->getParsedBody())) {
|
||||
return $request->getParsedBody()['API_KEY'];
|
||||
} elseif ($request->getQueryParams() !== null and in_array('API_KEY', array_keys($request->getQueryParams()))) {
|
||||
return $request->getQueryParams()['API_KEY'];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
protected function getKeyFromHeader(Request $request) {
|
||||
$api_key = $request->getHeader('Authorization');
|
||||
if (is_array($api_key)) {
|
||||
$api_key = $api_key[0];
|
||||
}
|
||||
if (str_contains($api_key, 'Bearer')) {
|
||||
$api_key = explode(' ', $api_key)[1];
|
||||
}
|
||||
return $api_key;
|
||||
}
|
||||
public function generate(int $length = 32, bool $removeSimilarCharacters = true): string {
|
||||
$token = "";
|
||||
try {
|
||||
$bytesWithMargin = random_bytes($length*3);
|
||||
$base64 = base64_encode($bytesWithMargin);
|
||||
$purified = preg_replace("/[+=\/.]/", "", $base64);
|
||||
if ($removeSimilarCharacters) {
|
||||
$purified = preg_replace("/[I1l0Oo]/", "", $purified);
|
||||
}
|
||||
$token = substr($purified, 0, $length);
|
||||
} catch (\Exception $e){
|
||||
error_log(var_export($e, true));
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
$token = substr($purified, 0, $length);
|
||||
|
||||
} catch (\Exception $e){
|
||||
echo $e->getMessage();
|
||||
public function generateToken(): object {
|
||||
$selector = bin2hex(\random_bytes(12));
|
||||
$token = bin2hex(\random_bytes(20));
|
||||
$full = "{$selector}:{$token}";
|
||||
$token = password_hash($token, \PASSWORD_DEFAULT);
|
||||
return (object) compact('selector', 'token', 'full');
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ services:
|
||||
volumes:
|
||||
- ./:/code
|
||||
- ./nginx.conf:/etc/nginx/conf.d/default.conf
|
||||
networks:
|
||||
- incoviba
|
||||
api:
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
@ -32,6 +34,8 @@ services:
|
||||
- ./:/code
|
||||
- ./php.ini:/usr/local/etc/php/conf.d/docker.ini
|
||||
- ./logs/php/:/var/log/php/
|
||||
networks:
|
||||
- incoviba
|
||||
|
||||
db:
|
||||
container_name: db
|
||||
@ -41,6 +45,8 @@ services:
|
||||
env_file: .db.env
|
||||
volumes:
|
||||
- incoviba_data:/var/lib/mysql
|
||||
networks:
|
||||
- incoviba
|
||||
adminer:
|
||||
container_name: adminer
|
||||
image: adminer:latest
|
||||
@ -49,6 +55,12 @@ services:
|
||||
ports:
|
||||
- "8083:8080"
|
||||
env_file: .adminer.env
|
||||
networks:
|
||||
- incoviba
|
||||
|
||||
volumes:
|
||||
incoviba_data: {}
|
||||
|
||||
networks:
|
||||
incoviba:
|
||||
external: true
|
||||
|
16
nginx.conf
16
nginx.conf
@ -7,10 +7,24 @@ server {
|
||||
root /code/public;
|
||||
|
||||
location / {
|
||||
try_files $uri /index.php$is_args$args;
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
}
|
||||
|
||||
location ~ \.php {
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Max-Age' 1728000;
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
|
||||
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
|
||||
add_header 'Content-Type' 'application/json';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
|
||||
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
|
||||
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
include fastcgi_params;
|
||||
|
@ -1,12 +1,8 @@
|
||||
<?php
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Incoviba\API\Common\Service\Auth as Service;
|
||||
use Incoviba\API\Common\Controller\Auth;
|
||||
|
||||
$app->get('/auth/generate', function(Request $request, Response $response, Service $service): Response {
|
||||
$key = $service->generate();
|
||||
$response->getBody()->write(json_encode(['key' => $key]));
|
||||
return $response
|
||||
->withStatus(200)
|
||||
->withHeader('content-type', 'application/json');
|
||||
});
|
||||
$app->post('/auth/login[/]', [Auth::class, 'login']);
|
||||
$app->get('/auth/generate[/]', [Auth::class, 'generate']);
|
||||
$app->post('/auth/validate[/]', [Auth::class, 'validate']);
|
||||
$app->post('/auth/user[/]', [Auth::class, 'user']);
|
||||
$app->post('/auth/logout[/]', [Auth::class, 'logout']);
|
||||
|
5
resources/routes/configs.php
Normal file
5
resources/routes/configs.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
use Incoviba\API\Common\Controller\Configs;
|
||||
|
||||
$app->get('/config/{config_name}', [Configs::class, 'get']);
|
||||
$app->post('/config', [Configs::class, 'set']);
|
@ -1,8 +1,18 @@
|
||||
<?php
|
||||
use Incoviba\API\Common\Controller\Proyectos;
|
||||
use Incoviba\API\Common\Controller\Proyectos\Cuotas;
|
||||
use Incoviba\API\Common\Controller\Proyectos\Cierres;
|
||||
|
||||
$app->group('/proyectos', function ($app) {
|
||||
$app->post('/add[/]', [Proyectos::class, 'add']);
|
||||
$app->group('/cuotas', function($app) {
|
||||
$app->get('/hoy[/]', [Cuotas::class, 'hoy']);
|
||||
$app->get('/mes[/]', [Cuotas::class, 'mes']);
|
||||
$app->get('/pendientes[/]', [Cuotas::class, 'pendientes']);
|
||||
});
|
||||
$app->group('/cierres', function($app) {
|
||||
$app->get('[/]', Cierres::class);
|
||||
});
|
||||
$app->get('[/]', Proyectos::class);
|
||||
});
|
||||
$app->group('/proyecto/{proyecto_id}', function ($app) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
return [
|
||||
'debug' => $_ENV['DEBUG'] ?? false,
|
||||
'AUTH_KEY' => $_ENV['API_KEY']
|
||||
'API_KEY' => $_ENV['API_KEY']
|
||||
];
|
||||
|
@ -3,7 +3,7 @@ use Psr\Container\ContainerInterface as Container;
|
||||
|
||||
return [
|
||||
Incoviba\API\Common\Service\Auth::class => function(Container $c) {
|
||||
return new Incoviba\API\Common\Service\Auth($c->get('AUTH_KEY'));
|
||||
return new Incoviba\API\Common\Service\Auth($c->get('API_KEY'));
|
||||
},
|
||||
Incoviba\API\Common\Middleware\Auth::class => function(Container $c) {
|
||||
return new Incoviba\API\Common\Middleware\Auth(
|
||||
|
14
src/Admin/Config.php
Normal file
14
src/Admin/Config.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
namespace Incoviba\Admin;
|
||||
|
||||
use Incoviba\API\Common\Alias\Model;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $value
|
||||
*/
|
||||
class Config extends Model {
|
||||
public static $_table = 'configurations';
|
||||
protected static $fields = ['name', 'value'];
|
||||
}
|
48
src/Auth/Login.php
Normal file
48
src/Auth/Login.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
namespace Incoviba\Auth;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DateTime;
|
||||
use Incoviba\API\Common\Alias\Model;
|
||||
use Incoviba\Admin\Config;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $user_id
|
||||
* @property DateTime $time
|
||||
* @property string $selector
|
||||
* @property string $token
|
||||
* @property int $status
|
||||
*
|
||||
*/
|
||||
class Login extends Model {
|
||||
public static $_table = 'logins';
|
||||
protected static $fields = ['user_id', 'time', 'selector', 'token', 'status'];
|
||||
|
||||
protected $user;
|
||||
public function user() {
|
||||
if ($this->user === null) {
|
||||
$this->user = $this->childOf(User::class, [Model::SELF_KEY => 'user_id']);
|
||||
}
|
||||
return $this->user;
|
||||
}
|
||||
public function time(DateTime $time = null) {
|
||||
if ($time === null) {
|
||||
return Carbon::parse($this->time);
|
||||
}
|
||||
$this->time = $time->format('Y-m-d H:m:s');
|
||||
return null;
|
||||
}
|
||||
public function isValid() {
|
||||
if ($this->status == 0) {
|
||||
return false;
|
||||
}
|
||||
$expiration = $this->factory->find(Config::class)->where([['name', 'cookie_expiration_time']])->one();
|
||||
if ($this->time()->diffInSeconds() > $expiration->value) {
|
||||
$this->status = 0;
|
||||
$this->save();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
79
src/Auth/User.php
Normal file
79
src/Auth/User.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
namespace Incoviba\Auth;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Incoviba\Admin\Config;
|
||||
use Incoviba\API\Common\Alias\Model;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $password
|
||||
* @property int $enabled
|
||||
*/
|
||||
class User extends Model {
|
||||
public static $_table = 'users';
|
||||
|
||||
protected $logins;
|
||||
public function logins() {
|
||||
if ($this->logins === null) {
|
||||
$this->logins = $this->parentOf(Login::class, [Model::CHILD_KEY => 'user_id']);
|
||||
}
|
||||
return $this->logins;
|
||||
}
|
||||
protected $login;
|
||||
public function login() {
|
||||
if ($this->login === null) {
|
||||
$this->login = $this->factory->find(Login::class)
|
||||
->where([['user_id', $this->id]])
|
||||
->order([['column' => 'time', 'direction' => 'desc']])
|
||||
->one(1);
|
||||
}
|
||||
return $this->login;
|
||||
}
|
||||
|
||||
public function isIn(): bool {
|
||||
return $this->login()->isValid();
|
||||
}
|
||||
public function validate($password): bool {
|
||||
return password_verify($password, $this->password);
|
||||
}
|
||||
public function validLogins(): bool|array {
|
||||
return $this->factory->find(Login::class)->where([['user_id', $this->id], ['status', 1]])->many();
|
||||
}
|
||||
public function logout() {
|
||||
$logins = $this->validLogins();
|
||||
if ($logins === false) {
|
||||
return true;
|
||||
}
|
||||
$bool = true;
|
||||
foreach ($logins as $login) {
|
||||
$login->status = 0;
|
||||
$bool &= $login->save();
|
||||
}
|
||||
return $bool;
|
||||
}
|
||||
public function setToken($selector, $token) {
|
||||
$this->logout();
|
||||
$expiration = $this->factory->find(Config::class)->where([['name', 'cookie_expiration_time']])->one();
|
||||
$data = [
|
||||
'user_id' => $this->id,
|
||||
'time' => Carbon::now()->format('Y-m-d H:i:s '),
|
||||
'selector' => $selector,
|
||||
'token' => $token,
|
||||
'status' => 1
|
||||
];
|
||||
$output = [
|
||||
'input' => $data,
|
||||
'login' => null,
|
||||
'logged_in' => false
|
||||
];
|
||||
$login = Login::add($this->factory, $data);
|
||||
$output['login'] = $login;
|
||||
if ($login !== false and $login->is_new()) {
|
||||
$output['logged_in'] = $login->save();
|
||||
$output['expires'] = $login->time()->addSeconds($expiration->value)->timestamp;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
<?php
|
||||
namespace Incoviba\Proyecto;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Incoviba\API\Common\Alias\Model;
|
||||
use Incoviba\Common\Direccion;
|
||||
use Incoviba\Inmobiliaria\Inmobiliaria;
|
||||
use Incoviba\Venta\Cuota;
|
||||
use Incoviba\Venta\Cierre;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
@ -19,22 +22,158 @@ use Incoviba\Inmobiliaria\Inmobiliaria;
|
||||
* @property int $subterraneos;
|
||||
*/
|
||||
class Proyecto extends Model {
|
||||
public static $_table = 'proyecto';
|
||||
protected static $fields = ['inmobiliaria', 'descripcion', 'direccion', 'superficie_terreno', 'valor_terreno',
|
||||
'corredor', 'superficie_sobre_terreno', 'superficie_bajo_terreno', 'pisos', 'subterraneos'];
|
||||
public static $_table = 'proyecto';
|
||||
protected static $fields = ['inmobiliaria', 'descripcion', 'direccion', 'superficie_terreno', 'valor_terreno',
|
||||
'corredor', 'superficie_sobre_terreno', 'superficie_bajo_terreno', 'pisos', 'subterraneos'];
|
||||
|
||||
protected $direccion_o;
|
||||
public function direccion() {
|
||||
if ($this->direccion_o === null) {
|
||||
$this->direccion_o = $this->childOf(Direccion::class, [Model::SELF_KEY => 'direccion']);
|
||||
protected $direccion_o;
|
||||
public function direccion() {
|
||||
if ($this->direccion_o === null) {
|
||||
$this->direccion_o = $this->childOf(Direccion::class, [Model::SELF_KEY => 'direccion']);
|
||||
}
|
||||
return $this->direccion_o;
|
||||
}
|
||||
return $this->direccion_o;
|
||||
}
|
||||
protected $inmobiliaria_o;
|
||||
public function inmobiliaria() {
|
||||
if ($this->inmobiliaria_o === null) {
|
||||
$this->inmobiliaria_o = $this->childOf(Inmobiliaria::class, [Model::SELF_KEY => 'inmobiliaria', Model::PARENT_KEY => 'rut']);
|
||||
protected $inmobiliaria_o;
|
||||
public function inmobiliaria() {
|
||||
if ($this->inmobiliaria_o === null) {
|
||||
$this->inmobiliaria_o = $this->childOf(Inmobiliaria::class, [Model::SELF_KEY => 'inmobiliaria', Model::PARENT_KEY => 'rut']);
|
||||
}
|
||||
return $this->inmobiliaria_o;
|
||||
}
|
||||
|
||||
protected $cuotas;
|
||||
protected function buildCuotas() {
|
||||
return $this->factory->find(Cuota::class)
|
||||
->join([
|
||||
['venta', 'venta.pie', 'cuota.pie'],
|
||||
['JOIN (SELECT e1.* FROM estado_venta e1 JOIN (SELECT MAX(id) AS id, venta FROM estado_venta GROUP BY venta) e0 ON e0.id = e1.id)', 'ev.venta', 'venta.id', 'alias' => 'ev', 'type' => 'raw'],
|
||||
['tipo_estado_venta', 'tev.id', 'ev.estado', 'alias' => 'tev'],
|
||||
['propiedad', 'propiedad.id', 'venta.propiedad'],
|
||||
['propiedad_unidad', 'pu.propiedad', 'propiedad.id', 'alias' => 'pu'],
|
||||
['unidad', 'unidad.id', 'pu.unidad'],
|
||||
['proyecto_tipo_unidad', 'ptu.id', 'unidad.pt', 'alias' => 'ptu'],
|
||||
['proyecto', 'proyecto.id', 'ptu.proyecto'],
|
||||
['pago', 'pago.id', 'cuota.pago'],
|
||||
['JOIN (SELECT e1.* FROM estado_pago e1 JOIN (SELECT MAX(id) AS id, pago FROM estado_pago GROUP BY pago) e0 ON e0.id = e1.id)', 'ep.pago', 'pago.id', 'alias' => 'ep', 'type' => 'raw'],
|
||||
['tipo_estado_pago', 'tep.id', 'ep.estado', 'alias' => 'tep']
|
||||
])
|
||||
->where([
|
||||
['proyecto.id', $this->id],
|
||||
['tev.activa', 1],
|
||||
['tep.active', 1]
|
||||
]);
|
||||
}
|
||||
public function cuotas() {
|
||||
if ($this->cuotas === null or !isset($this->cuotas->total)) {
|
||||
$cuotas = [];
|
||||
if ($this->cuotas !== null) {
|
||||
$cuotas = (array) $this->cuotas;
|
||||
}
|
||||
$cuotas['total'] = $this->$this->buildCuotas()->many();
|
||||
$this->cuotas = (object) $cuotas;
|
||||
}
|
||||
return $this->cuotas->total;
|
||||
}
|
||||
public function cuotasHoy() {
|
||||
if ($this->cuotas === null or !isset($this->cuotas->hoy)) {
|
||||
$cuotas = [];
|
||||
if ($this->cuotas !== null) {
|
||||
$cuotas = (array) $this->cuotas;
|
||||
}
|
||||
$f = Carbon::today();
|
||||
$cuotas['hoy'] = $this->buildCuotas()
|
||||
->where([
|
||||
['pago.fecha', $f->format('Y-m-d')]
|
||||
])
|
||||
->many();
|
||||
$this->cuotas = (object) $cuotas;
|
||||
}
|
||||
return $this->cuotas->hoy;
|
||||
}
|
||||
public function cuotasPendientes() {
|
||||
if (!isset($this->cuotas) or !isset($this->cuotas->mes)) {
|
||||
$cuotas = [];
|
||||
if (isset($this->cuotas)) {
|
||||
$cuotas = (array) $this->cuotas;
|
||||
}
|
||||
$f = Carbon::today();
|
||||
$cuotas['pendientes'] = $this->buildCuotas()
|
||||
->where([
|
||||
['ep.estado', 1, '<'],
|
||||
['ep.estado', 0, '>=']
|
||||
])
|
||||
->many();
|
||||
$this->cuotas = (object) $cuotas;
|
||||
}
|
||||
return $this->cuotas->pendientes;
|
||||
}
|
||||
public function cuotasMes() {
|
||||
if (!isset($this->cuotas) or !isset($this->cuotas->mes)) {
|
||||
$cuotas = [];
|
||||
if (isset($this->cuotas)) {
|
||||
$cuotas = (array) $this->cuotas;
|
||||
}
|
||||
$f = Carbon::today();
|
||||
error_log(var_export($this->buildCuotas(), true));
|
||||
$cuotas['mes'] = $this->buildCuotas()
|
||||
->where([
|
||||
['pago.fecha', $f->format('Y-m-d'), 'operator' => '>'],
|
||||
['pago.fecha', $f->copy()->addMonth(1)->format('Y-m-d'), '<=']
|
||||
])
|
||||
->many();
|
||||
$this->cuotas = (object) $cuotas;
|
||||
}
|
||||
return $this->cuotas->mes;
|
||||
}
|
||||
|
||||
protected $cierres;
|
||||
public function cierres(int $vigentes = 0)
|
||||
{
|
||||
if (!isset($this->cierres[$vigentes]) or $this->cierres[$vigentes] == null) {
|
||||
$orm = $this->factory->find(Cierre::class)
|
||||
->select([['cierre', '*']])
|
||||
->join([
|
||||
['join (select e1.* from estado_cierre e1 join (select cierre, max(id) as id from estado_cierre group by cierre) e0 on e0.id = e1.id)',
|
||||
'ec.cierre', 'cierre.id', 'alias' => 'ec', 'type' => 'raw'],
|
||||
['tipo_estado_cierre', 'tipo_estado_cierre.id', 'ec.tipo'],
|
||||
['proyecto', 'proyecto.id', 'cierre.proyecto'],
|
||||
['unidad_cierre', 'unidad_cierre.cierre', 'cierre.id'],
|
||||
['unidad', 'unidad.id', 'unidad_cierre.unidad']
|
||||
])
|
||||
->where([
|
||||
['proyecto.id', $this->id],
|
||||
['unidad_cierre.principal', 1]
|
||||
])
|
||||
->order([
|
||||
'proyecto.descripcion',
|
||||
'tipo_estado_cierre.vigente',
|
||||
'cierre.fecha',
|
||||
'LPAD(unidad.descripcion, 4, "0")'
|
||||
])
|
||||
->group(['cierre.id']);
|
||||
switch ($vigentes) {
|
||||
case Cierre::VIGENTES:
|
||||
$orm = $orm->where([['tipo_estado_cierre.vigente', 1]]);
|
||||
break;
|
||||
case Cierre::NO_VIGENTES:
|
||||
$orm = $orm->where([['tipo_estado_cierre.vigente', 0]]);
|
||||
break;
|
||||
case (Cierre::VIGENTES + 1):
|
||||
$orm = $orm->where([
|
||||
['tipo_estado_cierre.vigente', 1],
|
||||
['tipo_estado_cierre.descripcion', 'promesado', 'type' => 'not like']
|
||||
]);
|
||||
break;
|
||||
case (Cierre::VIGENTES + 2):
|
||||
$orm = $orm->where([
|
||||
['tipo_estado_cierre.vigente', 1],
|
||||
['tipo_estado_cierre.descripcion', 'promesado', 'type' => 'like']
|
||||
]);
|
||||
break;
|
||||
};
|
||||
error_log(var_export($orm, true));
|
||||
$this->cierres[$vigentes] = $orm->many();
|
||||
}
|
||||
return $this->cierres[$vigentes];
|
||||
}
|
||||
return $this->inmobiliaria_o;
|
||||
}
|
||||
}
|
||||
|
25
src/Venta/Cierre.php
Normal file
25
src/Venta/Cierre.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
namespace Incoviba\Venta;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Incoviba\API\Common\Alias\Model;
|
||||
|
||||
class Cierre extends Model {
|
||||
public static $_table = 'cierre';
|
||||
|
||||
const VIGENTES = 1;
|
||||
const NO_VIGENTES = -1;
|
||||
|
||||
public function fecha(\DateTimeInterface $fecha = null)
|
||||
{
|
||||
if ($fecha == null) {
|
||||
return Carbon::parse($this->fecha);
|
||||
}
|
||||
$this->fecha = $fecha->format('Y-m-d');
|
||||
}
|
||||
public function periodo() {
|
||||
$today = Carbon::today();
|
||||
$dif = $today->diffInDays($this->fecha());
|
||||
return $dif;
|
||||
}
|
||||
}
|
33
src/Venta/Cuota.php
Normal file
33
src/Venta/Cuota.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace Incoviba\Venta;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Incoviba\API\Common\Alias\Model;
|
||||
use Incoviba\Common\Banco;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property Pie $pie
|
||||
* @property DateTimeInterface $fecha
|
||||
* @property float $valor_$
|
||||
* @property bool $estado
|
||||
* @property Banco $banco
|
||||
* @property DateTimeInterface $fecha_pago
|
||||
* @property bool $abonado
|
||||
* @property DateTimeInterface $fecha_abono
|
||||
* @property float $uf
|
||||
* @property Pago $pago
|
||||
* @property int $numero
|
||||
*/
|
||||
class Cuota extends Model {
|
||||
public static $_table = 'cuota';
|
||||
protected static $fields = ['pie', 'fecha', 'valor_$', 'estado', 'banco', 'fecha_pago', 'abonado', 'fecha_abono', 'uf', 'pago', 'numero'];
|
||||
|
||||
protected $pago_o;
|
||||
public function pago() {
|
||||
if ($this->pago_o === null) {
|
||||
$this->pago_o = $this->childOf(Pago::class, [Model::SELF_KEY => 'pago']);
|
||||
}
|
||||
return $this->pago_o;
|
||||
}
|
||||
}
|
@ -1,6 +1,38 @@
|
||||
<?php
|
||||
namespace Incoviba\Venta;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DateTimeInterface;
|
||||
use Incoviba\API\Common\Alias\Model;
|
||||
use Incoviba\Common\Banco;
|
||||
|
||||
class Pago extends Model {}
|
||||
/**
|
||||
* @property int $id
|
||||
* @property float $valor
|
||||
* @property Banco $banco
|
||||
* @property TipoPago $tipo
|
||||
* @property string $identificador
|
||||
* @property DateTimeInterface $fecha
|
||||
* @property float $uf
|
||||
* @property string $pagador
|
||||
* @property Pago $asociado
|
||||
*/
|
||||
class Pago extends Model {
|
||||
public static $_table = 'pago';
|
||||
protected static $fields = ['valor', 'banco', 'tipo', 'identificador', 'fecha', 'uf', 'pagador', 'asociado'];
|
||||
|
||||
protected $tipo_o;
|
||||
public function tipo() {
|
||||
if ($this->tipo_o === null) {
|
||||
$this->tipo_o = $this->childOf(TipoPago::class, [Model::SELF_KEY => 'tipo']);
|
||||
}
|
||||
return $this->tipo_o;
|
||||
}
|
||||
|
||||
public function fecha(DateTimeInterface $fecha = null) {
|
||||
if ($fecha === null) {
|
||||
return Carbon::parse($this->fecha);
|
||||
}
|
||||
$this->fecha = $fecha->format('Y-m-d');
|
||||
}
|
||||
}
|
||||
|
12
src/Venta/TipoPago.php
Normal file
12
src/Venta/TipoPago.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace Incoviba\Venta;
|
||||
|
||||
use Incoviba\API\Common\Alias\Model;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $descripcion
|
||||
*/
|
||||
class TipoPago extends Model {
|
||||
public static $_table = 'tipo_pago';
|
||||
}
|
Reference in New Issue
Block a user