Compare commits
9 Commits
81ff87d355
...
develop
Author | SHA1 | Date | |
---|---|---|---|
0f3febc00d | |||
85fef16b27 | |||
cdb4b382b7 | |||
a9968dec58 | |||
06071884c7 | |||
6ff584013f | |||
cf27465d75 | |||
560fb356fa | |||
10e5383a3e |
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,6 +2,7 @@
|
||||
**/cache/
|
||||
**/*.env
|
||||
**/logs/
|
||||
**/documents/
|
||||
|
||||
# Composer
|
||||
**/vendor/
|
||||
|
27
Features.md
Normal file
27
Features.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Features
|
||||
|
||||
+ [ ] Multiples Cuentas
|
||||
+ [ ] Giro, eg: Banco, Caja
|
||||
+ [ ] Inversiones, eg: Crypto
|
||||
+ [ ] Multiples Categorías
|
||||
+ [ ] Ingresos, eg: Boletas, Facturas, Sueldo
|
||||
+ [ ] Únicos
|
||||
+ [ ] Recurrentes
|
||||
+ [ ] Gastos, eg: Comida, Hogar, Movilización
|
||||
+ [ ] Únicos
|
||||
+ [ ] Recurrentes
|
||||
+ [ ] Inversiones, eg: Bitcoin
|
||||
+ [ ] Deudas
|
||||
+ [ ] Nueva transacción
|
||||
+ [ ] Leer cartolas
|
||||
+ [ ] Leer cartolas en pdf
|
||||
+ [ ] Leer cartolas en excel (xls, xlsx)
|
||||
+ [ ] Obtener cartolas de emails
|
||||
+ [ ] Ingresar cartolas a cuenta
|
||||
+ [ ] Cuadrar cuentas
|
||||
+ [ ] Reportes
|
||||
+ [ ] Resultado
|
||||
+ [ ] Mes
|
||||
+ [ ] Línea de tiempo
|
||||
+ [ ] Presupuesto
|
||||
+ [ ] Por cuenta
|
186
api/ProVM/Alias/API/Controller.php
Normal file
186
api/ProVM/Alias/API/Controller.php
Normal file
@ -0,0 +1,186 @@
|
||||
<?php
|
||||
namespace ProVM\Alias\API;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use PDOException;
|
||||
use function Safe\{error_log, json_decode};
|
||||
use ProVM\Alias\Controller\Json;
|
||||
use ProVM\Concept\API\Controller as ControllerInterface;
|
||||
use ProVM\Concept\Repository;
|
||||
|
||||
abstract class Controller implements ControllerInterface
|
||||
{
|
||||
use Json;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->setup($container);
|
||||
}
|
||||
|
||||
abstract public function setup(ContainerInterface $container): void;
|
||||
|
||||
protected array $names;
|
||||
public function setSingular(string $singular): ControllerInterface
|
||||
{
|
||||
$this->names['singular'] = $singular;
|
||||
return $this;
|
||||
}
|
||||
public function setPlural(string $plural): ControllerInterface
|
||||
{
|
||||
$this->names['plural'] = $plural;
|
||||
return $this;
|
||||
}
|
||||
public function getSingular(): string
|
||||
{
|
||||
return $this->names['singular'];
|
||||
}
|
||||
public function getPlural(): string
|
||||
{
|
||||
return $this->names['plural'];
|
||||
}
|
||||
protected Repository $repository;
|
||||
public function setRepository(Repository $repository): ControllerInterface
|
||||
{
|
||||
$this->repository = $repository;
|
||||
return $this;
|
||||
}
|
||||
public function getRepository(): Repository
|
||||
{
|
||||
return $this->repository;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
||||
{
|
||||
$objs = [];
|
||||
try {
|
||||
$objs = $this->getRepository()->fetchAll();
|
||||
} catch (PDOException $e) {
|
||||
error_log($e);
|
||||
}
|
||||
return $this->withJson($response, [$this->getPlural() => $objs]);
|
||||
}
|
||||
public function get(ServerRequestInterface $request, ResponseInterface $response, int $model_id): ResponseInterface
|
||||
{
|
||||
$obj = null;
|
||||
try {
|
||||
$obj = $this->getRepository()->fetchById($model_id);
|
||||
} catch (PDOException $e) {
|
||||
error_log($e);
|
||||
}
|
||||
return $this->withJson($response, [$this->getSingular() => $obj]);
|
||||
}
|
||||
public function add(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
||||
{
|
||||
$body = $request->getBody();
|
||||
$contents = $body->getContents();
|
||||
$json = json_decode($contents)->{$this->getPlural()};
|
||||
if (!is_array($json)) {
|
||||
$json = [$json];
|
||||
}
|
||||
$output = [
|
||||
'input' => $json,
|
||||
$this->getPlural() => []
|
||||
];
|
||||
foreach ($json as $data) {
|
||||
$obj = $this->getRepository()->create((array) $data);
|
||||
$status = true;
|
||||
$exists = true;
|
||||
if ($obj->isNew()) {
|
||||
$exists = false;
|
||||
try {
|
||||
$this->getRepository()->save($obj);
|
||||
} catch (PDOException $e) {
|
||||
error_log($e);
|
||||
$status = false;
|
||||
}
|
||||
$output[$this->getPlural()] []= [
|
||||
$this->getSingular() => $obj,
|
||||
'exists' => $exists,
|
||||
'added' => $status
|
||||
];
|
||||
}
|
||||
}
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function edit(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
||||
{
|
||||
$body = $request->getBody();
|
||||
$contents = $body->getContents();
|
||||
$json = json_decode($contents)->{$this->getPlural()};
|
||||
if (!is_array($json)) {
|
||||
$json = [$json];
|
||||
}
|
||||
$output = [
|
||||
'input' => $json,
|
||||
$this->getPlural() => []
|
||||
];
|
||||
foreach ($json as $data) {
|
||||
$obj = $this->getRepository()->fetchById($data->id);
|
||||
$old = clone $obj;
|
||||
try {
|
||||
$obj->edit((array) $data);
|
||||
$status = $obj->isDirty();
|
||||
if ($status) {
|
||||
$this->getRepository()->save($obj);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
error_log($e);
|
||||
$status = false;
|
||||
}
|
||||
$output[$this->getPlural()] []= [
|
||||
'antes' => $old,
|
||||
$this->getSingular() => $obj,
|
||||
'edited' => $status
|
||||
];
|
||||
}
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function editOne(ServerRequestInterface $request, ResponseInterface $response, int $model_id): ResponseInterface
|
||||
{
|
||||
$obj = $this->getRepository()->fetchById($model_id);
|
||||
$body = $request->getBody();
|
||||
$contents = $body->getContents();
|
||||
$json = json_decode($contents, JSON_OBJECT_AS_ARRAY)[$this->getSingular()];
|
||||
$output = [
|
||||
'input' => $json,
|
||||
'old' => clone $obj
|
||||
];
|
||||
try {
|
||||
$obj->edit((array) $json);
|
||||
$status = $obj->isDirty();
|
||||
if ($status) {
|
||||
$this->getRepository()->save($obj);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
error_log($e);
|
||||
$status = false;
|
||||
}
|
||||
$output[$this->getSingular()] = $obj;
|
||||
$output['edited'] = $status;
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function remove(ServerRequestInterface $request, ResponseInterface $response, int $model_id): ResponseInterface
|
||||
{
|
||||
$output = [
|
||||
$this->getSingular() => null,
|
||||
'exists' => true,
|
||||
'deleted' => false
|
||||
];
|
||||
try {
|
||||
$obj = $this->getRepository()->fetchById($model_id);
|
||||
$output[$this->getSingular()] = clone $obj;
|
||||
try {
|
||||
$this->repository->delete($obj);
|
||||
} catch (PDOException $e) {
|
||||
error_log($e);
|
||||
$output['deleted'] = false;
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
error_log($e);
|
||||
$output['exists'] = false;
|
||||
}
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
107
api/ProVM/Alias/API/Route/Operation.php
Normal file
107
api/ProVM/Alias/API/Route/Operation.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
namespace ProVM\Alias\API\Route;
|
||||
|
||||
use ProVM\Concept\API\Route\Operation as OperationInterface;
|
||||
use ProVM\Concept\API\Route\Parameter;
|
||||
use ProVM\Concept\API\Route\Response;
|
||||
|
||||
abstract class Operation implements OperationInterface
|
||||
{
|
||||
protected array $tags;
|
||||
public function setTags(array $tags): OperationInterface
|
||||
{
|
||||
foreach ($tags as $tag) {
|
||||
$this->addTag($tag);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addTag(string $tag): OperationInterface
|
||||
{
|
||||
$this->tags []= $tag;
|
||||
return $this;
|
||||
}
|
||||
public function getTags(): array
|
||||
{
|
||||
return $this->tags;
|
||||
}
|
||||
protected string $summary;
|
||||
public function setSummary(string $summary): OperationInterface
|
||||
{
|
||||
$this->summary = $summary;
|
||||
return $this;
|
||||
}
|
||||
public function getSummary(): string
|
||||
{
|
||||
return $this->summary;
|
||||
}
|
||||
protected string $description;
|
||||
public function setDescription(string $description): OperationInterface
|
||||
{
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
protected array $parameters;
|
||||
public function setParameters(array $parameters): OperationInterface
|
||||
{
|
||||
foreach ($parameters as $parameter) {
|
||||
$this->addParameter($parameter);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addParameter(Parameter $parameter): OperationInterface
|
||||
{
|
||||
$this->parameters []= $parameter;
|
||||
return $this;
|
||||
}
|
||||
public function getParameters(): array
|
||||
{
|
||||
return $this->parameters;
|
||||
}
|
||||
protected array $responses;
|
||||
public function setResponses(array $responses): OperationInterface
|
||||
{
|
||||
foreach ($responses as $code => $response) {
|
||||
$this->addResponse($code, $response);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addResponse(int $code, Response $response): OperationInterface
|
||||
{
|
||||
$this->responses[$code] = $response;
|
||||
return $this;
|
||||
}
|
||||
public function getResponses(): array
|
||||
{
|
||||
return $this->responses;
|
||||
}
|
||||
protected bool $deprecated;
|
||||
public function setDeprecated(): OperationInterface
|
||||
{
|
||||
$this->deprecated = true;
|
||||
return $this;
|
||||
}
|
||||
public function isDeprecated(): bool
|
||||
{
|
||||
return $this->deprecated ?? false;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
$arr = [];
|
||||
$fields = ['tags', 'summary', 'description', 'parameters', 'responses'];
|
||||
foreach ($fields as $field) {
|
||||
if (isset($this->{$field})) {
|
||||
$method = 'get' . ucwords($field);
|
||||
$arr[$field] = $this->{$method}();
|
||||
}
|
||||
}
|
||||
if ($this->isDeprecated()) {
|
||||
$arr['deprecated'] = true;
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
}
|
74
api/ProVM/Alias/API/Route/Parameter.php
Normal file
74
api/ProVM/Alias/API/Route/Parameter.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
namespace ProVM\Alias\API\Route;
|
||||
|
||||
use ProVM\Concept\API\Route\Parameter as ParameterInterface;
|
||||
|
||||
abstract class Parameter implements ParameterInterface
|
||||
{
|
||||
protected string $name;
|
||||
public function setName(string $name): ParameterInterface
|
||||
{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
protected string $description;
|
||||
public function setDescription(string $description): ParameterInterface
|
||||
{
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
protected string $in;
|
||||
public function setIn(string $in): ParameterInterface
|
||||
{
|
||||
$this->in = $in;
|
||||
return $this;
|
||||
}
|
||||
public function getIn(): string
|
||||
{
|
||||
return $this->in;
|
||||
}
|
||||
protected bool $required;
|
||||
public function setRequired(): ParameterInterface
|
||||
{
|
||||
$this->required = true;
|
||||
return $this;
|
||||
}
|
||||
public function isRequired(): bool
|
||||
{
|
||||
return $this->required ?? false;
|
||||
}
|
||||
protected bool $deprecated;
|
||||
public function setDeprecated(): ParameterInterface
|
||||
{
|
||||
$this->deprecated = true;
|
||||
return $this;
|
||||
}
|
||||
public function isDeprecated(): bool
|
||||
{
|
||||
return $this->deprecated ?? false;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
$arr = [
|
||||
'name' => $this->getName(),
|
||||
'in' => $this->getIn(),
|
||||
'description' => $this->getDescription()
|
||||
];
|
||||
if ($this->isRequired()) {
|
||||
$arr['required'] = true;
|
||||
}
|
||||
if ($this->isDeprecated()) {
|
||||
$arr['deprecated'] = true;
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
}
|
66
api/ProVM/Alias/API/Route/Response.php
Normal file
66
api/ProVM/Alias/API/Route/Response.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
namespace ProVM\Alias\API\Route;
|
||||
|
||||
use ProVM\Concept\API\Route\Response as ResponseInterface;
|
||||
|
||||
abstract class Response implements ResponseInterface
|
||||
{
|
||||
protected string $description;
|
||||
public function setDescription(string $description): ResponseInterface
|
||||
{
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
protected array $headers;
|
||||
public function setHeaders(array $headers): ResponseInterface
|
||||
{
|
||||
foreach ($headers as $header) {
|
||||
$this->addHeader($header);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addHeader(string $header): ResponseInterface
|
||||
{
|
||||
$this->headers []= $header;
|
||||
return $this;
|
||||
}
|
||||
public function getHeaders(): array
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
protected array $contents;
|
||||
public function setContent(array $contents): ResponseInterface
|
||||
{
|
||||
foreach ($contents as $content) {
|
||||
$this->addContent($content);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addContent(string $content): ResponseInterface
|
||||
{
|
||||
$this->contents []= $content;
|
||||
return $this;
|
||||
}
|
||||
public function getContents(): array
|
||||
{
|
||||
return $this->contents;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
$arr = [
|
||||
'description' => $this->getDescription()
|
||||
];
|
||||
if (isset($this->headers) and count($this->headers) > 0) {
|
||||
$arr['headers'] = $this->getHeaders();
|
||||
}
|
||||
if (isset($this->contents) and count($this->contents) > 0) {
|
||||
$arr['content'] = $this->getContents();
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
}
|
95
api/ProVM/Alias/API/Route/Route.php
Normal file
95
api/ProVM/Alias/API/Route/Route.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
namespace ProVM\Alias\API\Route;
|
||||
|
||||
use ProVM\Concept\API\Route\Route as RouteInterface;
|
||||
use ProVM\Concept\API\Route\Operation;
|
||||
use ProVM\Concept\API\Route\Parameter;
|
||||
|
||||
abstract class Route implements RouteInterface
|
||||
{
|
||||
protected string $ref;
|
||||
public function setRef(string $ref): RouteInterface
|
||||
{
|
||||
$this->ref = $ref;
|
||||
return $this;
|
||||
}
|
||||
public function getRef(): string
|
||||
{
|
||||
return $this->ref;
|
||||
}
|
||||
protected string $summary;
|
||||
public function setSummary(string $summary): RouteInterface
|
||||
{
|
||||
$this->summary = $summary;
|
||||
return $this;
|
||||
}
|
||||
public function getSummary(): string
|
||||
{
|
||||
return $this->summary;
|
||||
}
|
||||
protected string $description;
|
||||
public function setDescription(string $description): RouteInterface
|
||||
{
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
protected array $methods;
|
||||
public function setMethods(array $methods): RouteInterface
|
||||
{
|
||||
foreach ($methods as $method => $operation) {
|
||||
$this->addMethod($method, $operation);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addMethod(string $method, Operation $operation): RouteInterface
|
||||
{
|
||||
$this->methods[$method] = $operation;
|
||||
return $this;
|
||||
}
|
||||
public function getMethods(): array
|
||||
{
|
||||
return $this->methods;
|
||||
}
|
||||
protected array $parameters;
|
||||
public function setParameters(array $parameters): RouteInterface
|
||||
{
|
||||
foreach ($parameters as $parameter) {
|
||||
$this->addParameter($parameter);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addParameter(Parameter $parameter): RouteInterface
|
||||
{
|
||||
$this->parameters []= $parameter;
|
||||
return $this;
|
||||
}
|
||||
public function getParameters(): array
|
||||
{
|
||||
return $this->parameters;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
$arr = [];
|
||||
if (isset($this->ref)) {
|
||||
$arr['ref'] = $this->getRef();
|
||||
}
|
||||
if (isset($this->summary)) {
|
||||
$arr['summary'] = $this->getSummary();
|
||||
}
|
||||
if (isset($this->description)) {
|
||||
$arr['description'] = $this->getDescription();
|
||||
}
|
||||
foreach ($this->methods as $method => $operation) {
|
||||
$arr[$method] = $operation;
|
||||
}
|
||||
if (isset($this->parameters)) {
|
||||
$arr['parameters'] = $this->getParameters();
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
}
|
16
api/ProVM/Alias/Controller/Json.php
Normal file
16
api/ProVM/Alias/Controller/Json.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace ProVM\Alias\Controller;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use function Safe\json_encode;
|
||||
|
||||
trait Json
|
||||
{
|
||||
public function withJson(ResponseInterface $response, $json_data, int $status_code = 200): ResponseInterface
|
||||
{
|
||||
$response->getBody()->write(json_encode($json_data));
|
||||
return $response
|
||||
->withStatus($status_code)
|
||||
->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
}
|
153
api/ProVM/Alias/Database.php
Normal file
153
api/ProVM/Alias/Database.php
Normal file
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
namespace ProVM\Alias;
|
||||
|
||||
use Psr\Database\DatabaseInterface;
|
||||
use Exception;
|
||||
use PDO, PDOException, PDOStatement;
|
||||
|
||||
abstract class Database implements DatabaseInterface
|
||||
{
|
||||
protected string $host;
|
||||
protected int $port;
|
||||
public function setHost(string $host, ?int $port = null): DatabaseInterface
|
||||
{
|
||||
$this->host = $host;
|
||||
if ($port !== null) {
|
||||
$this->port = $port;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function getHost(): string
|
||||
{
|
||||
return $this->host;
|
||||
}
|
||||
public function getPort(): int
|
||||
{
|
||||
return $this->port;
|
||||
}
|
||||
protected string $name;
|
||||
public function setName(string $database_name): DatabaseInterface
|
||||
{
|
||||
$this->name = $database_name;
|
||||
return $this;
|
||||
}
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
protected string $username;
|
||||
protected string $password;
|
||||
public function setUser(string $username, string $password): DatabaseInterface
|
||||
{
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
return $this;
|
||||
}
|
||||
public function getUser(): string
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
public function getPassword(): string
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
protected PDO $connection;
|
||||
public function connect(): DatabaseInterface
|
||||
{
|
||||
if ($this->needsUser()) {
|
||||
$this->connection = new PDO($this->getDsn(), $this->getUser(), $this->getPassword());
|
||||
return $this;
|
||||
}
|
||||
$this->connection = new PDO($this->getDsn());
|
||||
return $this;
|
||||
}
|
||||
public function getConnection(): PDO
|
||||
{
|
||||
if (!isset($this->connection)) {
|
||||
return $this->connect()->connection;
|
||||
}
|
||||
return $this->connection;
|
||||
}
|
||||
public function query(string $query): array
|
||||
{
|
||||
$st = $this->getConnection()->query($query);
|
||||
if (!$st) {
|
||||
throw new PDOException("Could not retrieve anything with '{$query}'.");
|
||||
}
|
||||
$results = $st->fetchAll(PDO::FETCH_ASSOC);
|
||||
if (!$results) {
|
||||
throw new PDOException('Could not retrieve any results.');
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
public function beginTransaction(): void
|
||||
{
|
||||
if (!$this->getConnection()->beginTransaction()) {
|
||||
throw new PDOException('Could not begin transaction.');
|
||||
}
|
||||
}
|
||||
public function commit(): void
|
||||
{
|
||||
if (!$this->getConnection()->commit()) {
|
||||
throw new PDOException('Could not commit');
|
||||
}
|
||||
}
|
||||
public function rollBack(): void
|
||||
{
|
||||
if (!$this->getConnection()->rollBack()) {
|
||||
throw new PDOException('Could not rollback.');
|
||||
}
|
||||
}
|
||||
protected PDOStatement $prepared_statement;
|
||||
public function prepare(string $query): DatabaseInterface
|
||||
{
|
||||
$st = $this->getConnection()->prepare($query);
|
||||
if (!$st) {
|
||||
throw new PDOException("Could not prepare query '{$query}'.");
|
||||
}
|
||||
$this->prepared_statement = $st;
|
||||
return $this;
|
||||
}
|
||||
public function execute(array $data): array
|
||||
{
|
||||
if (!isset($this->prepared_statement)) {
|
||||
throw new Exception('No prepared statement.');
|
||||
}
|
||||
if (!$this->prepared_statement->execute($data)) {
|
||||
throw new PDOException('Could not execute prepared statement.');
|
||||
}
|
||||
$results = $this->prepared_statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
if (!$results) {
|
||||
throw new PDOException('Could not retrieve any results.');
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
public function insert(array $values): void
|
||||
{
|
||||
if (!isset($this->prepared_statement)) {
|
||||
throw new Exception('No prepared statement.');
|
||||
}
|
||||
if (!$this->prepared_statement->execute($values)) {
|
||||
throw new PDOException('Could not insert.');
|
||||
}
|
||||
}
|
||||
public function update(array $data): void
|
||||
{
|
||||
if (!isset($this->prepared_statement)) {
|
||||
throw new Exception('No prepared statement.');
|
||||
}
|
||||
if (!$this->prepared_statement->execute($data)) {
|
||||
throw new PDOException('Could not update.');
|
||||
}
|
||||
}
|
||||
public function delete(array $data): void
|
||||
{
|
||||
if (!isset($this->prepared_statement)) {
|
||||
throw new Exception('No prepared statement.');
|
||||
}
|
||||
if (!$this->prepared_statement->execute($data)) {
|
||||
throw new PDOException('Could not delete.');
|
||||
}
|
||||
}
|
||||
}
|
32
api/ProVM/Alias/Database/Query.php
Normal file
32
api/ProVM/Alias/Database/Query.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace ProVM\Alias\Database;
|
||||
|
||||
use Error;
|
||||
use function Safe\error_log;
|
||||
use ProVM\Concept\Database\Query as QueryInterface;
|
||||
|
||||
abstract class Query implements QueryInterface
|
||||
{
|
||||
protected array $errors;
|
||||
protected function error(Error $error): Query
|
||||
{
|
||||
$this->errors []= $error;
|
||||
return $this;
|
||||
}
|
||||
protected function log(): void
|
||||
{
|
||||
if (!isset($this->errors) or count($this->errors) === 0) {
|
||||
return;
|
||||
}
|
||||
$message = ['Query Error'];
|
||||
foreach ($this->errors as $error) {
|
||||
$message []= $error->getMessage();
|
||||
}
|
||||
error_log(implode(PHP_EOL, $message));
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->build();
|
||||
}
|
||||
}
|
25
api/ProVM/Alias/Factory/Model.php
Normal file
25
api/ProVM/Alias/Factory/Model.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
namespace ProVM\Alias\Factory;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use ProVM\Concept\Factory\Model as FactoryInterface;
|
||||
use ProVM\Concept\Repository;
|
||||
|
||||
abstract class Model implements FactoryInterface
|
||||
{
|
||||
protected ContainerInterface $container;
|
||||
public function setContainer(ContainerInterface $container): Model
|
||||
{
|
||||
$this->container = $container;
|
||||
return $this;
|
||||
}
|
||||
public function getContainer(): ContainerInterface
|
||||
{
|
||||
return $this->container;
|
||||
}
|
||||
public function find(string $model_name): Repository
|
||||
{
|
||||
$class = str_replace('Model', 'Repository', $model_name);
|
||||
return $this->getContainer()->get($class);
|
||||
}
|
||||
}
|
46
api/ProVM/Alias/File.php
Normal file
46
api/ProVM/Alias/File.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace ProVM\Alias;
|
||||
|
||||
use function Safe\{fopen,fclose,fwrite};
|
||||
use ProVM\Concept\File as FileInterface;
|
||||
|
||||
abstract class File implements FileInterface
|
||||
{
|
||||
protected string $filename;
|
||||
public function setFilename(string $filename): FileInterface
|
||||
{
|
||||
$this->filename = $filename;
|
||||
return $this;
|
||||
}
|
||||
public function getFilename(): string
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
public function isDir(): bool
|
||||
{
|
||||
return is_dir($this->getFilename());
|
||||
}
|
||||
public function isReadable(): bool
|
||||
{
|
||||
return is_readable($this->getFilename());
|
||||
}
|
||||
public function isWriteable(): bool
|
||||
{
|
||||
return is_writeable($this->getFilename());
|
||||
}
|
||||
|
||||
public function read(?int $length = null): string
|
||||
{
|
||||
$fh = fopen($this->getFilename(), 'r');
|
||||
$str = fgets($fh, $length);
|
||||
fclose($fh);
|
||||
return $str;
|
||||
}
|
||||
public function write(string $data, ?int $length = null): void
|
||||
{
|
||||
$fh = fopen($this->getFilename(), 'r');
|
||||
fwrite($fh, $data, $length);
|
||||
fclose($fh);
|
||||
}
|
||||
}
|
46
api/ProVM/Alias/Filesystem.php
Normal file
46
api/ProVM/Alias/Filesystem.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace ProVM\Alias;
|
||||
|
||||
use function Safe\{touch,mkdir,unlink};
|
||||
use ProVM\Concept\Filesystem as FilesystemInterface;
|
||||
use ProVM\Implement\Path;
|
||||
|
||||
abstract class Filesystem implements FilesystemInterface
|
||||
{
|
||||
protected string $base_path;
|
||||
public function setBasePath(string $path): FilesystemInterface
|
||||
{
|
||||
$this->base_path = $path;
|
||||
return $this;
|
||||
}
|
||||
public function getBasePath(): string
|
||||
{
|
||||
return $this->base_path;
|
||||
}
|
||||
|
||||
public function buildPath(string $relative_path): string
|
||||
{
|
||||
return Path::fromArray([
|
||||
$this->getBasePath(),
|
||||
$relative_path
|
||||
]);
|
||||
}
|
||||
|
||||
public function has(string $relative_path): bool
|
||||
{
|
||||
return file_exists($this->buildPath($relative_path));
|
||||
}
|
||||
|
||||
public function mkdir(string $relative_path): void
|
||||
{
|
||||
mkdir($this->buildPath($relative_path));
|
||||
}
|
||||
public function create(string $relative_path): void
|
||||
{
|
||||
touch($this->buildPath($relative_path));
|
||||
}
|
||||
public function delete(string $relative_path): void
|
||||
{
|
||||
unlink($this->buildPath($relative_path));
|
||||
}
|
||||
}
|
90
api/ProVM/Alias/Model.php
Normal file
90
api/ProVM/Alias/Model.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
namespace ProVM\Alias;
|
||||
|
||||
use ReflectionObject;
|
||||
use ProVM\Concept\Model as ModelInterface;
|
||||
|
||||
abstract class Model implements ModelInterface
|
||||
{
|
||||
protected int $id;
|
||||
public function setId(int $id): ModelInterface
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
protected bool $new = false;
|
||||
public function setNew(): ModelInterface
|
||||
{
|
||||
$this->new = true;
|
||||
return $this;
|
||||
}
|
||||
public function isNew(): bool
|
||||
{
|
||||
return $this->new;
|
||||
}
|
||||
|
||||
protected array $edited;
|
||||
public function setEdited(string $property): ModelInterface
|
||||
{
|
||||
$this->edited []= $property;
|
||||
return $this;
|
||||
}
|
||||
public function getEdited(): array
|
||||
{
|
||||
return $this->edited;
|
||||
}
|
||||
public function isDirty(): bool
|
||||
{
|
||||
return isset($this->edited) and count($this->edited) > 0;
|
||||
}
|
||||
|
||||
public function edit(array $data): void
|
||||
{
|
||||
$this->edited = [];
|
||||
foreach ($data as $key => $val) {
|
||||
if ($key === 'id') {
|
||||
continue;
|
||||
}
|
||||
$getter = Model::parseGetter($key);
|
||||
$setter = Model::parseSetter($key);
|
||||
if (method_exists($this, $getter) and $this->{$getter}() !== $val) {
|
||||
$this->{$setter}($val);
|
||||
$this->setEdited($key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function parseSetter(string $property): string
|
||||
{
|
||||
return 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $property)));
|
||||
}
|
||||
public static function parseGetter(string $property): string
|
||||
{
|
||||
return 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $property)));
|
||||
}
|
||||
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
$ref = new ReflectionObject($this);
|
||||
$properties = ($ref->getProperties());
|
||||
$output = [
|
||||
'id' => $this->getId()
|
||||
];
|
||||
foreach ($properties as $property) {
|
||||
if (get_called_class() !== $property->getDeclaringClass()->getName()) {
|
||||
continue;
|
||||
}
|
||||
$key = $property->getName();
|
||||
$method = Model::parseGetter($key);
|
||||
if (method_exists($this, $method)) {
|
||||
$output[$key] = $this->{$method}();
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
}
|
153
api/ProVM/Alias/Repository.php
Normal file
153
api/ProVM/Alias/Repository.php
Normal file
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
namespace ProVM\Alias;
|
||||
|
||||
use Psr\Database\DatabaseInterface;
|
||||
use Error;
|
||||
use function Safe\error_log;
|
||||
use ProVM\Concept\Model;
|
||||
use ProVM\Concept\Repository as RepositoryInterface;
|
||||
use ProVM\Concept\Factory\Model as FactoryInterface;
|
||||
use ProVM\Implement\Database\QueryBuilder;
|
||||
|
||||
abstract class Repository implements RepositoryInterface
|
||||
{
|
||||
public function __construct(DatabaseInterface $database, QueryBuilder $builder, FactoryInterface $factory)
|
||||
{
|
||||
$this->setDatabase($database);
|
||||
$this->setQueryBuilder($builder);
|
||||
$this->setFactory($factory);
|
||||
$this->setProperties(['id']);
|
||||
$this->setup();
|
||||
}
|
||||
|
||||
abstract public function setup(): void;
|
||||
|
||||
protected QueryBuilder $query;
|
||||
public function setQueryBuilder(QueryBuilder $builder): RepositoryInterface
|
||||
{
|
||||
$this->query = $builder;
|
||||
return $this;
|
||||
}
|
||||
public function getQueryBuilder(): QueryBuilder
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
protected FactoryInterface $factory;
|
||||
public function setFactory(FactoryInterface $factory): RepositoryInterface
|
||||
{
|
||||
$this->factory = $factory;
|
||||
return $this;
|
||||
}
|
||||
public function getFactory(): FactoryInterface
|
||||
{
|
||||
return $this->factory;
|
||||
}
|
||||
|
||||
protected string $table;
|
||||
public function setTable(string $table): RepositoryInterface
|
||||
{
|
||||
$this->table = $table;
|
||||
return $this;
|
||||
}
|
||||
public function getTable(): string
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
protected array $properties;
|
||||
public function addProperty(string $name): RepositoryInterface
|
||||
{
|
||||
$this->properties []= $name;
|
||||
return $this;
|
||||
}
|
||||
public function setProperties(array $properties): RepositoryInterface
|
||||
{
|
||||
$this->properties = [];
|
||||
return $this->addProperties($properties);
|
||||
}
|
||||
public function addProperties(array $properties): RepositoryInterface
|
||||
{
|
||||
foreach ($properties as $property) {
|
||||
$this->addProperty($property);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function getProperties(): array
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
protected DatabaseInterface $database;
|
||||
public function setDatabase(DatabaseInterface $database): RepositoryInterface
|
||||
{
|
||||
$this->database = $database;
|
||||
return $this;
|
||||
}
|
||||
public function getDatabase(): DatabaseInterface
|
||||
{
|
||||
return $this->database;
|
||||
}
|
||||
|
||||
public function fetchAll(): array
|
||||
{
|
||||
$query = $this->getQueryBuilder()->select()->from($this->getTable())->build();
|
||||
return array_map([$this, 'load'], $this->getDatabase()->query($query));
|
||||
}
|
||||
public function fetchById(int $id): Model
|
||||
{
|
||||
$query = $this->getQueryBuilder()->select()->from($this->getTable())->where('id = ?');
|
||||
return $this->load($this->getDatabase()->prepare($query)->execute([$id])[0]);
|
||||
}
|
||||
|
||||
protected function extractProperties(Model $model): array
|
||||
{
|
||||
$properties = [];
|
||||
foreach ($this->getProperties() as $p) {
|
||||
if ($model->isNew() and $p === 'id') {
|
||||
continue;
|
||||
}
|
||||
$method = $model::parseGetter($p);
|
||||
if (method_exists($model, $method)) {
|
||||
try {
|
||||
$properties[$p] = $model->{$method}();
|
||||
} catch (Error $e) {
|
||||
error_log($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $properties;
|
||||
}
|
||||
public function save(Model $model): void
|
||||
{
|
||||
if ($model->isNew()) {
|
||||
$this->saveNew($model);
|
||||
return;
|
||||
}
|
||||
if ($model->isDirty()) {
|
||||
$this->saveUpdate($model);
|
||||
}
|
||||
}
|
||||
protected function saveNew(Model $model): void
|
||||
{
|
||||
$properties = $this->extractProperties($model);
|
||||
$columns = array_keys($properties);
|
||||
$ivalues = array_map(function($item) {return '?';}, array_keys($properties));
|
||||
$values = array_values($properties);
|
||||
$query = $this->getQueryBuilder()->insert()->into($this->getTable())->columns($columns)->values($ivalues)->build();
|
||||
$this->getDatabase()->prepare($query)->insert($values);
|
||||
}
|
||||
protected function saveUpdate(Model $model): void
|
||||
{
|
||||
$edited = $model->getEdited();
|
||||
$properties = array_intersect_key($this->extractProperties($model), array_combine($edited, $edited));
|
||||
$sets = array_map(function($item) {
|
||||
return "{$item} = ?";
|
||||
}, array_keys($properties));
|
||||
$values = array_values($properties);
|
||||
$query = $this->getQueryBuilder()->update()->table($this->getTable())->set($sets)->where('id = ?')->build();
|
||||
$this->getDatabase()->prepare($query)->update(array_merge($values, [$model->getId()]));
|
||||
}
|
||||
public function delete(Model $model): void
|
||||
{
|
||||
$query = $this->getQueryBuilder()->delete()->from($this->getTable())->where('id = ?')->build();
|
||||
$this->getDatabase()->prepare($query)->delete([$model->getId()]);
|
||||
}
|
||||
}
|
23
api/ProVM/Concept/API/Controller.php
Normal file
23
api/ProVM/Concept/API/Controller.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace ProVM\Concept\API;
|
||||
|
||||
use ProVM\Concept\Repository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
interface Controller
|
||||
{
|
||||
public function setSingular(string $singular): Controller;
|
||||
public function setPlural(string $plural): Controller;
|
||||
public function getSingular(): string;
|
||||
public function getPlural(): string;
|
||||
public function setRepository(Repository $repository): Controller;
|
||||
public function getRepository(): Repository;
|
||||
|
||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface;
|
||||
public function get(ServerRequestInterface $request, ResponseInterface $response, int $model_id): ResponseInterface;
|
||||
public function add(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface;
|
||||
public function edit(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface;
|
||||
public function editOne(ServerRequestInterface $request, ResponseInterface $response, int $model_id): ResponseInterface;
|
||||
public function remove(ServerRequestInterface $request, ResponseInterface $response, int $model_id): ResponseInterface;
|
||||
}
|
7
api/ProVM/Concept/API/OpenAPI.php
Normal file
7
api/ProVM/Concept/API/OpenAPI.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
namespace ProVM\Concept\API;
|
||||
|
||||
interface OpenAPI
|
||||
{
|
||||
public static function add(array $data);
|
||||
}
|
24
api/ProVM/Concept/API/Route/Operation.php
Normal file
24
api/ProVM/Concept/API/Route/Operation.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
namespace ProVM\Concept\API\Route;
|
||||
|
||||
use JsonSerializable;
|
||||
use ProVM\Concept\API\OpenAPI;
|
||||
|
||||
interface Operation extends JsonSerializable, OpenAPI
|
||||
{
|
||||
public function setTags(array $tags): Operation;
|
||||
public function addTag(string $tag): Operation;
|
||||
public function getTags(): array;
|
||||
public function setSummary(string $summary): Operation;
|
||||
public function getSummary(): string;
|
||||
public function setDescription(string $description): Operation;
|
||||
public function getDescription(): string;
|
||||
public function setParameters(array $parameters): Operation;
|
||||
public function addParameter(Parameter $parameter): Operation;
|
||||
public function getParameters(): array;
|
||||
public function setResponses(array $responses): Operation;
|
||||
public function addResponse(int $code, Response $response): Operation;
|
||||
public function getResponses(): array;
|
||||
public function setDeprecated(): Operation;
|
||||
public function isDeprecated(): bool;
|
||||
}
|
19
api/ProVM/Concept/API/Route/Parameter.php
Normal file
19
api/ProVM/Concept/API/Route/Parameter.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
namespace ProVM\Concept\API\Route;
|
||||
|
||||
use JsonSerializable;
|
||||
use ProVM\Concept\API\OpenAPI;
|
||||
|
||||
interface Parameter extends JsonSerializable, OpenAPI
|
||||
{
|
||||
public function setName(string $name): Parameter;
|
||||
public function getName(): string;
|
||||
public function setIn(string $in): Parameter;
|
||||
public function getIn(): string;
|
||||
public function setDescription(string $description): Parameter;
|
||||
public function getDescription(): string;
|
||||
public function setRequired(): Parameter;
|
||||
public function isRequired(): bool;
|
||||
public function setDeprecated(): Parameter;
|
||||
public function isDeprecated(): bool;
|
||||
}
|
17
api/ProVM/Concept/API/Route/Response.php
Normal file
17
api/ProVM/Concept/API/Route/Response.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace ProVM\Concept\API\Route;
|
||||
|
||||
use JsonSerializable;
|
||||
use ProVM\Concept\API\OpenAPI;
|
||||
|
||||
interface Response extends JsonSerializable, OpenAPI
|
||||
{
|
||||
public function setDescription(string $description): Response;
|
||||
public function getDescription(): string;
|
||||
public function setHeaders(array $headers): Response;
|
||||
public function addHeader(string $header): Response;
|
||||
public function getHeaders(): array;
|
||||
public function setContent(array $contents): Response;
|
||||
public function addContent(string $content): Response;
|
||||
public function getContents(): array;
|
||||
}
|
21
api/ProVM/Concept/API/Route/Route.php
Normal file
21
api/ProVM/Concept/API/Route/Route.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace ProVM\Concept\API\Route;
|
||||
|
||||
use JsonSerializable;
|
||||
use ProVM\Concept\API\OpenAPI;
|
||||
|
||||
interface Route extends JsonSerializable, OpenAPI
|
||||
{
|
||||
public function setRef(string $ref): Route;
|
||||
public function getRef(): string;
|
||||
public function setSummary(string $summary): Route;
|
||||
public function getSummary(): string;
|
||||
public function setDescription(string $description): Route;
|
||||
public function getDescription(): string;
|
||||
public function setMethods(array $methods): Route;
|
||||
public function addMethod(string $method, Operation $operation): Route;
|
||||
public function getMethods(): array;
|
||||
public function setParameters(array $parameters): Route;
|
||||
public function addParameter(Parameter $parameter): Route;
|
||||
public function getParameters(): array;
|
||||
}
|
7
api/ProVM/Concept/Database/Query.php
Normal file
7
api/ProVM/Concept/Database/Query.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
namespace ProVM\Concept\Database;
|
||||
|
||||
interface Query
|
||||
{
|
||||
public function build(): string;
|
||||
}
|
10
api/ProVM/Concept/Factory/Model.php
Normal file
10
api/ProVM/Concept/Factory/Model.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
namespace ProVM\Concept\Factory;
|
||||
|
||||
use ProVM\Concept\Model as ModelInterface;
|
||||
use ProVM\Concept\Repository;
|
||||
|
||||
interface Model
|
||||
{
|
||||
public function find(string $model_name): Repository;
|
||||
}
|
16
api/ProVM/Concept/File.php
Normal file
16
api/ProVM/Concept/File.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace ProVM\Concept;
|
||||
|
||||
interface File
|
||||
{
|
||||
public function setFilename(string $filename): File;
|
||||
public function getFilename(): string;
|
||||
|
||||
public function isDir(): bool;
|
||||
public function isReadable(): bool;
|
||||
public function isWriteable(): bool;
|
||||
|
||||
public function read(?int $length = null): string;
|
||||
public function write(string $data, ?int $length = null);
|
||||
public function append(string $data, ?int $length = null);
|
||||
}
|
17
api/ProVM/Concept/Filesystem.php
Normal file
17
api/ProVM/Concept/Filesystem.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace ProVM\Concept;
|
||||
|
||||
interface Filesystem
|
||||
{
|
||||
public function setBasePath(string $path): Filesystem;
|
||||
public function getBasePath(): string;
|
||||
|
||||
public function buildPath(string $relative_path): string;
|
||||
|
||||
public function has(string $relative_path): bool;
|
||||
|
||||
public function mkdir(string $relative_path): void;
|
||||
public function create(string $relative_path): void;
|
||||
public function get(string $relative_path): File;
|
||||
public function delete(string $relative_path): void;
|
||||
}
|
16
api/ProVM/Concept/Model.php
Normal file
16
api/ProVM/Concept/Model.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace ProVM\Concept;
|
||||
|
||||
use JsonSerializable;
|
||||
|
||||
interface Model extends JsonSerializable
|
||||
{
|
||||
public function setNew(): Model;
|
||||
public function isNew(): bool;
|
||||
public function setEdited(string $property): Model;
|
||||
public function getEdited(): array;
|
||||
public function isDirty(): bool;
|
||||
public function edit(array $data): void;
|
||||
public static function parseSetter(string $property): string;
|
||||
public static function parseGetter(string $property): string;
|
||||
}
|
15
api/ProVM/Concept/Path.php
Normal file
15
api/ProVM/Concept/Path.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace ProVM\Concept;
|
||||
|
||||
use ArrayAccess;
|
||||
|
||||
interface Path extends ArrayAccess
|
||||
{
|
||||
public function compose(string $base_path): Path;
|
||||
public function add(string $path_segment): Path;
|
||||
public function build(): string;
|
||||
public static function fromArray(array $path): string;
|
||||
|
||||
public static function isAbsolute(string $path): bool;
|
||||
public static function isRelative(string $path): bool;
|
||||
}
|
12
api/ProVM/Concept/Repository.php
Normal file
12
api/ProVM/Concept/Repository.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace ProVM\Concept;
|
||||
|
||||
interface Repository
|
||||
{
|
||||
public function fetchAll(): array;
|
||||
public function fetchById(int $id): Model;
|
||||
public function load(array $data_row): Model;
|
||||
public function create(array $data): Model;
|
||||
public function save(Model $model): void;
|
||||
public function delete(Model $model): void;
|
||||
}
|
37
api/ProVM/Implement/API/Route/Operation.php
Normal file
37
api/ProVM/Implement/API/Route/Operation.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\API\Route;
|
||||
|
||||
use ProVM\Alias\API\Route\Operation as BaseOperation;
|
||||
|
||||
class Operation extends BaseOperation
|
||||
{
|
||||
public static function add(array $data): Operation
|
||||
{
|
||||
$operation = new Operation();
|
||||
if (isset($data['tags'])) {
|
||||
$operation->setTags($data['tags']);
|
||||
}
|
||||
if (isset($data['summary'])) {
|
||||
$operation->setSummary($data['summary']);
|
||||
}
|
||||
if (isset($data['description'])) {
|
||||
$operation->setDescription($data['description']);
|
||||
}
|
||||
if (isset($data['parameters'])) {
|
||||
foreach ($data['parameters'] as $p) {
|
||||
$parameter = Parameter::add($p);
|
||||
$operation->addParameter($parameter);
|
||||
}
|
||||
}
|
||||
if (isset($data['responses'])) {
|
||||
foreach ($data['responses'] as $code => $r) {
|
||||
$response = Response::add($r);
|
||||
$operation->addResponse($code, $response);
|
||||
}
|
||||
}
|
||||
if (isset($data['deprecated'])) {
|
||||
$operation->setDeprecated();
|
||||
}
|
||||
return $operation;
|
||||
}
|
||||
}
|
24
api/ProVM/Implement/API/Route/Parameter.php
Normal file
24
api/ProVM/Implement/API/Route/Parameter.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\API\Route;
|
||||
|
||||
use ProVM\Alias\API\Route\Parameter as BaseParameter;
|
||||
|
||||
class Parameter extends BaseParameter
|
||||
{
|
||||
public static function add(array $data): Parameter
|
||||
{
|
||||
$parameter = new Parameter();
|
||||
$parameter->setName($data['name']);
|
||||
$parameter->setIn($data['in']);
|
||||
if (isset($data['description'])) {
|
||||
$parameter->setDescription($data['description']);
|
||||
}
|
||||
if (isset($data['required'])) {
|
||||
$parameter->setRequired();
|
||||
}
|
||||
if (isset($data['deprecated'])) {
|
||||
$parameter->setDeprecated();
|
||||
}
|
||||
return $parameter;
|
||||
}
|
||||
}
|
20
api/ProVM/Implement/API/Route/Response.php
Normal file
20
api/ProVM/Implement/API/Route/Response.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\API\Route;
|
||||
|
||||
use ProVM\Alias\API\Route\Response as BaseResponse;
|
||||
|
||||
class Response extends BaseResponse
|
||||
{
|
||||
public static function add(array $data): Response
|
||||
{
|
||||
$response = new Response();
|
||||
$response->setDescription($data['description']);
|
||||
if (isset($data['headers'])) {
|
||||
$response->setHeaders($data['headers']);
|
||||
}
|
||||
if (isset($data['content'])) {
|
||||
$response->setContent($data['content']);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
}
|
35
api/ProVM/Implement/API/Route/Route.php
Normal file
35
api/ProVM/Implement/API/Route/Route.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\API\Route;
|
||||
|
||||
use ProVM\Alias\API\Route\Route as BaseRoute;
|
||||
|
||||
class Route extends BaseRoute
|
||||
{
|
||||
public static function add(array $data): Route
|
||||
{
|
||||
$route = new Route();
|
||||
if (isset($data['ref'])) {
|
||||
$route->setRef($data['ref']);
|
||||
}
|
||||
if (isset($data['summary'])) {
|
||||
$route->setSummary($data['summary']);
|
||||
}
|
||||
if (isset($data['description'])) {
|
||||
$route->setDescription($data['description']);
|
||||
}
|
||||
$methods = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'];
|
||||
foreach ($methods as $method) {
|
||||
if (isset($data[$method])) {
|
||||
$operation = Operation::add($data[$method]);
|
||||
$route->addMethod($method, $operation);
|
||||
}
|
||||
}
|
||||
if (isset($data['parameters'])) {
|
||||
foreach ($data['parameters'] as $p) {
|
||||
$parameter = Parameter::add($p);
|
||||
$operation->addParameter($parameter);
|
||||
}
|
||||
}
|
||||
return $route;
|
||||
}
|
||||
}
|
118
api/ProVM/Implement/Collection.php
Normal file
118
api/ProVM/Implement/Collection.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
namespace ProVM\Implement;
|
||||
|
||||
use Psr\Collection\CollectionInterface;
|
||||
use ReflectionFunction;
|
||||
|
||||
class Collection implements CollectionInterface
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->set(CollectionInterface::class, $this);
|
||||
}
|
||||
protected array $data;
|
||||
public function set(mixed $name, $value): CollectionInterface
|
||||
{
|
||||
$this->data[$name] = $value;
|
||||
return $this;
|
||||
}
|
||||
public function has(mixed $name): bool
|
||||
{
|
||||
return isset($this->data[$name]);
|
||||
}
|
||||
public function get(mixed $name)
|
||||
{
|
||||
return $this->process($this->data[$name]) ?? null;
|
||||
}
|
||||
public function remove(mixed $name): CollectionInterface
|
||||
{
|
||||
unset($this->data[$name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function process($value)
|
||||
{
|
||||
if (is_callable($value)) {
|
||||
return $this->processCallable($value);
|
||||
}
|
||||
if (is_array($value)) {
|
||||
return $this->processArray($value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
protected function processCallable(Callable $value)
|
||||
{
|
||||
$ref = new ReflectionFunction($value);
|
||||
$param_array = [];
|
||||
$params = $ref->getParameters();
|
||||
foreach ($params as $p) {
|
||||
$param_array[$p->getName()] = $this->get($p->getType()->getName());
|
||||
}
|
||||
return $ref->invokeArgs($param_array);
|
||||
}
|
||||
protected function processArray(array $value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public static function fromArray(array $source): CollectionInterface
|
||||
{
|
||||
$obj = new Collection();
|
||||
foreach ($source as $key => $value) {
|
||||
$obj->set($key, $value);
|
||||
}
|
||||
return $obj;
|
||||
}
|
||||
public static function fromObject(object $source): CollectionInterface
|
||||
{
|
||||
return Collection::fromArray((array) $source);
|
||||
}
|
||||
|
||||
public function __get(mixed $name): mixed
|
||||
{
|
||||
return $this->get($name);
|
||||
}
|
||||
|
||||
public function current(): mixed
|
||||
{
|
||||
return $this->data[$this->key()];
|
||||
}
|
||||
public function next(): void
|
||||
{
|
||||
next($this->data);
|
||||
}
|
||||
public function key(): mixed
|
||||
{
|
||||
return key($this->data);
|
||||
}
|
||||
public function valid(): bool
|
||||
{
|
||||
return isset($this->data);
|
||||
}
|
||||
public function rewind(): void
|
||||
{
|
||||
reset($this->data);
|
||||
}
|
||||
|
||||
public function offsetExists(mixed $offset): bool
|
||||
{
|
||||
return $this->has($offset);
|
||||
}
|
||||
public function offsetGet(mixed $offset): mixed
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
$this->set($offset, $value);
|
||||
}
|
||||
public function offsetUnset(mixed $offset): void
|
||||
{
|
||||
$this->remove($offset);
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->data);
|
||||
}
|
||||
}
|
27
api/ProVM/Implement/Database/MySQL.php
Normal file
27
api/ProVM/Implement/Database/MySQL.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\Database;
|
||||
|
||||
use ProVM\Alias\Database;
|
||||
|
||||
class MySQL extends Database
|
||||
{
|
||||
public function __construct(string $host, string $username, string $password, string $database_name, int $port = 3306)
|
||||
{
|
||||
$this->setHost($host, $port);
|
||||
$this->setUser($username, $password);
|
||||
$this->setName($database_name);
|
||||
}
|
||||
public function getDsn(): string
|
||||
{
|
||||
$dsn = ["mysql:host={$this->getHost()}"];
|
||||
if ($this->getPort() !== 3306) {
|
||||
$dsn []= "port={$this->getPort()}";
|
||||
}
|
||||
$dsn []= "dbname={$this->getName()}";
|
||||
return implode(';', $dsn);
|
||||
}
|
||||
public function needsUser(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
47
api/ProVM/Implement/Database/Query/MySQL/Delete.php
Normal file
47
api/ProVM/Implement/Database/Query/MySQL/Delete.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\Database\Query\MySQL;
|
||||
|
||||
use ProVM\Alias\Database\Query;
|
||||
|
||||
class Delete extends Query
|
||||
{
|
||||
protected string $table;
|
||||
public function from($table): Delete
|
||||
{
|
||||
$this->table = $table;
|
||||
return $this;
|
||||
}
|
||||
public function getFrom(): string
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
protected array $conditions;
|
||||
public function where(array|string $conditions): Delete
|
||||
{
|
||||
if (is_string($conditions)) {
|
||||
return $this->addCondition($conditions);
|
||||
}
|
||||
foreach ($conditions as $condition) {
|
||||
$this->addCondition($condition);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addCondition(string $condition): Delete
|
||||
{
|
||||
$this->conditions []= $condition;
|
||||
return $this;
|
||||
}
|
||||
public function getWhere(): string
|
||||
{
|
||||
return implode(' AND ', $this->conditions);
|
||||
}
|
||||
|
||||
public function build(): string
|
||||
{
|
||||
$output = ['DELETE FROM'];
|
||||
$output []= $this->getFrom();
|
||||
$output []= "WHERE {$this->getWhere()}";
|
||||
|
||||
return implode(' ', $output);
|
||||
}
|
||||
}
|
105
api/ProVM/Implement/Database/Query/MySQL/Insert.php
Normal file
105
api/ProVM/Implement/Database/Query/MySQL/Insert.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\Database\Query\MySQL;
|
||||
|
||||
use Error;
|
||||
use ProVM\Alias\Database\Query;
|
||||
|
||||
class Insert extends Query
|
||||
{
|
||||
protected string $table;
|
||||
public function into(string $table): Insert
|
||||
{
|
||||
$this->table = $table;
|
||||
return $this;
|
||||
}
|
||||
public function getTable(): string
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
protected Select $select;
|
||||
public function select(Select $select): Insert
|
||||
{
|
||||
$this->select = $select;
|
||||
return $this;
|
||||
}
|
||||
public function getSelect(): string
|
||||
{
|
||||
return $this->select->build();
|
||||
}
|
||||
protected array $columns;
|
||||
public function columns(array $columns): Insert
|
||||
{
|
||||
foreach ($columns as $column) {
|
||||
$this->addColumn($column);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addColumn(string $column): Insert
|
||||
{
|
||||
$this->columns []= $column;
|
||||
return $this;
|
||||
}
|
||||
public function getColumns(): string
|
||||
{
|
||||
return implode(', ', array_map(function($item) {return "`{$item}`";}, $this->columns));
|
||||
}
|
||||
protected array $values;
|
||||
public function values(array $values): Insert
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
$this->addValue($value);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addValue(string $value): Insert
|
||||
{
|
||||
$this->values []= $value;
|
||||
return $this;
|
||||
}
|
||||
public function getValues(): string
|
||||
{
|
||||
return implode(', ', array_map(function($item) {
|
||||
return $item;
|
||||
}, $this->values));
|
||||
}
|
||||
protected array $updates;
|
||||
public function update(array $updates): Insert
|
||||
{
|
||||
foreach ($updates as $update) {
|
||||
$this->addUpdate($update);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addUpdate(string $update_string): Insert
|
||||
{
|
||||
$this->updates []= $update_string;
|
||||
return $this;
|
||||
}
|
||||
public function getUpdates(): string
|
||||
{
|
||||
return implode(', ', $this->updates);
|
||||
}
|
||||
|
||||
public function build(): string
|
||||
{
|
||||
$output = ['INSERT INTO'];
|
||||
$output []= $this->getTable();
|
||||
try {
|
||||
$output []= "({$this->getColumns()})";
|
||||
} catch (Error $e) {
|
||||
$this->error($e);
|
||||
}
|
||||
try {
|
||||
$output []= $this->getSelect();
|
||||
} catch (\Error $e) {
|
||||
$output []= "VALUES ({$this->getValues()})";
|
||||
}
|
||||
try {
|
||||
$output []= "ON DUPLICATE KEY UPDATE {$this->getUpdates()}";
|
||||
} catch (Error $e) {
|
||||
$this->error($e);
|
||||
}
|
||||
$this->log();
|
||||
return implode(' ', $output);
|
||||
}
|
||||
}
|
213
api/ProVM/Implement/Database/Query/MySQL/Select.php
Normal file
213
api/ProVM/Implement/Database/Query/MySQL/Select.php
Normal file
@ -0,0 +1,213 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\Database\Query\MySQL;
|
||||
|
||||
use Error;
|
||||
use function Safe\error_log;
|
||||
use ProVM\Alias\Database\Query;
|
||||
|
||||
class Select extends Query
|
||||
{
|
||||
protected array $columns;
|
||||
public function select(array|string $columns): Select
|
||||
{
|
||||
if (is_string($columns)) {
|
||||
return $this->addColumn($columns);
|
||||
}
|
||||
foreach ($columns as $column) {
|
||||
$this->addColumn($column);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addColumn(string $column): Select
|
||||
{
|
||||
$this->columns []= $column;
|
||||
return $this;
|
||||
}
|
||||
public function getSelect(): string
|
||||
{
|
||||
return implode(', ', array_map(function($item) {
|
||||
return "`{$item}`";
|
||||
}, $this->columns));
|
||||
}
|
||||
protected string $from;
|
||||
public function from(string $table): Select
|
||||
{
|
||||
$this->from = $table;
|
||||
return $this;
|
||||
}
|
||||
public function getFrom(): string
|
||||
{
|
||||
return $this->from;
|
||||
}
|
||||
protected array $joins;
|
||||
public function join(array $joins): Select
|
||||
{
|
||||
if (is_string($joins[0])) {
|
||||
return $this->addJoin($joins[0], $joins[1], $joins[2]);
|
||||
}
|
||||
foreach ($joins as $join) {
|
||||
$this->addJoin($join[0], $join[1], $join[2]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addJoin(string $join_type, string $join_table, string $conditions): Select
|
||||
{
|
||||
$join_type = strtoupper($join_type);
|
||||
$this->joins []= "{$join_type} {$join_table} {$conditions}";
|
||||
return $this;
|
||||
}
|
||||
public function getJoins(): string
|
||||
{
|
||||
return implode('', $this->joins);
|
||||
}
|
||||
protected array $conditions;
|
||||
public function where(array|string $conditions): Select
|
||||
{
|
||||
if (is_string($conditions)) {
|
||||
return $this->addWhere($conditions);
|
||||
}
|
||||
foreach ($conditions as $condition) {
|
||||
$this->addWhere($condition);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addWhere($condition): Select
|
||||
{
|
||||
$this->conditions []= $condition;
|
||||
return $this;
|
||||
}
|
||||
public function getWheres(): string
|
||||
{
|
||||
return implode(' AND ', $this->conditions);
|
||||
}
|
||||
protected array $orders;
|
||||
public function order(array|string $orders): Select
|
||||
{
|
||||
if (is_string($orders)) {
|
||||
return $this->addOrder($orders);
|
||||
}
|
||||
foreach ($orders as $order) {
|
||||
if (is_array($order)) {
|
||||
$this->addOrder($order[0], $order[1]);
|
||||
continue;
|
||||
}
|
||||
$this->addOrder($order);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addOrder(string $order, string $dir = 'desc'): Select
|
||||
{
|
||||
$dir = strtoupper($dir);
|
||||
$this->orders []= "{$order} {$dir}";
|
||||
return $this;
|
||||
}
|
||||
public function getOrders(): string
|
||||
{
|
||||
return implode(', ', $this->orders);
|
||||
}
|
||||
protected array $groups;
|
||||
public function group(array|string $groups): Select
|
||||
{
|
||||
if (is_string($groups)) {
|
||||
return $this->addGroup($groups);
|
||||
}
|
||||
foreach ($groups as $group) {
|
||||
$this->addGroup($group);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addGroup(string $group): Select
|
||||
{
|
||||
$this->groups []= $group;
|
||||
return $this;
|
||||
}
|
||||
public function getGroups(): string
|
||||
{
|
||||
return implode(', ', $this->groups);
|
||||
}
|
||||
protected array $having;
|
||||
public function having(array|string $havings): Select
|
||||
{
|
||||
if (is_string($havings)) {
|
||||
return $this->addHaving($havings);
|
||||
}
|
||||
foreach ($havings as $having) {
|
||||
$this->addHaving($having);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addHaving(string $having): Select
|
||||
{
|
||||
$this->having []= $having;
|
||||
return $this;
|
||||
}
|
||||
public function getHaving(): string
|
||||
{
|
||||
return implode(' AND ', $this->having);
|
||||
}
|
||||
protected int $limit;
|
||||
public function limit(int $limit): Select
|
||||
{
|
||||
$this->limit = $limit;
|
||||
return $this;
|
||||
}
|
||||
protected int $offset;
|
||||
public function offset(int $offset): Select
|
||||
{
|
||||
$this->offset = $offset;
|
||||
return $this;
|
||||
}
|
||||
public function getLimit(): string
|
||||
{
|
||||
$output = [$this->limit];
|
||||
if (isset($this->offset)) {
|
||||
$output []= 'OFFSET';
|
||||
$output []= $this->offset;
|
||||
}
|
||||
return implode(' ', $output);
|
||||
}
|
||||
|
||||
public function build(): string
|
||||
{
|
||||
$output = ['SELECT'];
|
||||
try {
|
||||
$output []= $this->getSelect();
|
||||
} catch (Error $e) {
|
||||
$output []= '*';
|
||||
}
|
||||
$output []= 'FROM';
|
||||
$output []= $this->getFrom();
|
||||
try {
|
||||
$output [] = $this->getJoins();
|
||||
} catch (Error $e) {
|
||||
$this->error($e);
|
||||
}
|
||||
try {
|
||||
$output []= "WHERE {$this->getWheres()}";
|
||||
} catch (Error $e) {
|
||||
$this->error($e);
|
||||
}
|
||||
try {
|
||||
$output []= "GROUP BY {$this->getGroups()}";
|
||||
} catch (Error $e) {
|
||||
$this->error($e);
|
||||
}
|
||||
try {
|
||||
$output []= "HAVING {$this->getHaving()}";
|
||||
} catch (Error $e) {
|
||||
$this->error($e);
|
||||
}
|
||||
try {
|
||||
$output []= "ORDER BY {$this->getOrders()}";
|
||||
} catch (Error $e) {
|
||||
$this->error($e);
|
||||
}
|
||||
try {
|
||||
$output []= "LIMIT {$this->getLimit()}";
|
||||
} catch (Error $e) {
|
||||
$this->error($e);
|
||||
}
|
||||
$this->log();
|
||||
return implode(' ', $output);
|
||||
}
|
||||
}
|
67
api/ProVM/Implement/Database/Query/MySQL/Update.php
Normal file
67
api/ProVM/Implement/Database/Query/MySQL/Update.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\Database\Query\MySQL;
|
||||
|
||||
use ProVM\Alias\Database\Query;
|
||||
|
||||
class Update extends Query
|
||||
{
|
||||
protected string $table;
|
||||
public function table(string $table): Update
|
||||
{
|
||||
$this->table = $table;
|
||||
return $this;
|
||||
}
|
||||
public function getTable(): string
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
protected array $sets;
|
||||
public function set(array|string $set_strings): Update
|
||||
{
|
||||
if (is_string($set_strings)) {
|
||||
return $this->addSet($set_strings);
|
||||
}
|
||||
foreach ($set_strings as $set_string) {
|
||||
$this->addSet($set_string);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addSet(string $set_string): Update
|
||||
{
|
||||
$this->sets []= $set_string;
|
||||
return $this;
|
||||
}
|
||||
public function getSets(): string
|
||||
{
|
||||
return implode(', ', $this->sets);
|
||||
}
|
||||
protected array $conditions;
|
||||
public function where(array|string $conditions): Update
|
||||
{
|
||||
if (is_string($conditions)) {
|
||||
return $this->addCondition($conditions);
|
||||
}
|
||||
foreach ($conditions as $condition) {
|
||||
$this->addCondition($condition);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addCondition(string $condition): Update
|
||||
{
|
||||
$this->conditions []= $condition;
|
||||
return $this;
|
||||
}
|
||||
public function getWhere(): string
|
||||
{
|
||||
return implode(' AND ', $this->conditions);
|
||||
}
|
||||
|
||||
public function build(): string
|
||||
{
|
||||
$output = ['UPDATE'];
|
||||
$output []= $this->getTable();
|
||||
$output []= "SET {$this->getSets()}";
|
||||
$output []= "WHERE {$this->getWhere()}";
|
||||
return implode(' ', $output);
|
||||
}
|
||||
}
|
61
api/ProVM/Implement/Database/QueryBuilder.php
Normal file
61
api/ProVM/Implement/Database/QueryBuilder.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\Database;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use ProVM\Concept\Database\Query;
|
||||
use ProVM\Implement\Database\Query\MySQL\Delete;
|
||||
use ProVM\Implement\Database\Query\MySQL\Insert;
|
||||
use ProVM\Implement\Database\Query\MySQL\Select;
|
||||
use ProVM\Implement\Database\Query\MySQL\Update;
|
||||
|
||||
class QueryBuilder
|
||||
{
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$arr = [
|
||||
'select',
|
||||
'insert',
|
||||
'update',
|
||||
'delete'
|
||||
];
|
||||
foreach ($arr as $b) {
|
||||
$builder = implode("\\", [
|
||||
'ProVM',
|
||||
'Implement',
|
||||
'Database',
|
||||
'Query',
|
||||
'MySQL',
|
||||
ucwords($b)
|
||||
]);
|
||||
$this->addBuilder($container->get($builder));
|
||||
}
|
||||
}
|
||||
protected array $builders;
|
||||
public function addBuilder(Query $builder): QueryBuilder
|
||||
{
|
||||
$name = explode("\\", get_class($builder));
|
||||
$name = array_pop($name);
|
||||
$this->builders[strtolower($name)] = $builder;
|
||||
return $this;
|
||||
}
|
||||
public function start(string $name): Query
|
||||
{
|
||||
return $this->builders[strtolower($name)];
|
||||
}
|
||||
public function select(): Select
|
||||
{
|
||||
return $this->start('select');
|
||||
}
|
||||
public function insert(): Insert
|
||||
{
|
||||
return $this->start('insert');
|
||||
}
|
||||
public function update(): Update
|
||||
{
|
||||
return $this->start('update');
|
||||
}
|
||||
public function delete(): Delete
|
||||
{
|
||||
return $this->start('delete');
|
||||
}
|
||||
}
|
13
api/ProVM/Implement/Factory/Model.php
Normal file
13
api/ProVM/Implement/Factory/Model.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\Factory;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use ProVM\Alias\Factory\Model as BaseModel;
|
||||
|
||||
class Model extends BaseModel
|
||||
{
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->setContainer($container);
|
||||
}
|
||||
}
|
38
api/ProVM/Implement/Factory/Repository.php
Normal file
38
api/ProVM/Implement/Factory/Repository.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace ProVM\Implement\Factory;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use ProVM\Concept\Repository as RepositoryInterface;
|
||||
|
||||
class Repository
|
||||
{
|
||||
protected ContainerInterface $container;
|
||||
public function setContainer(ContainerInterface $container): Repository
|
||||
{
|
||||
$this->container = $container;
|
||||
return $this;
|
||||
}
|
||||
public function getContainer(): ContainerInterface
|
||||
{
|
||||
return $this->container;
|
||||
}
|
||||
protected string $namespace;
|
||||
public function setNamespace(string $namespace): Repository
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
return $this;
|
||||
}
|
||||
public function getNamespace(): string
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
public function find(string $repository_class): RepositoryInterface
|
||||
{
|
||||
$class = implode("\\", [
|
||||
$this->getNamespace(),
|
||||
$repository_class
|
||||
]);
|
||||
return $this->getContainer()->get($class);
|
||||
}
|
||||
}
|
17
api/ProVM/Implement/File.php
Normal file
17
api/ProVM/Implement/File.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace ProVM\Implement;
|
||||
|
||||
use ProVM\Alias\File as BaseFile;
|
||||
|
||||
class File extends BaseFile
|
||||
{
|
||||
public function __construct(string $filename)
|
||||
{
|
||||
$this->setFilename($filename);
|
||||
}
|
||||
|
||||
public function append(string $data, ?int $length = null)
|
||||
{
|
||||
$this->write($data, $length);
|
||||
}
|
||||
}
|
18
api/ProVM/Implement/Filesystem.php
Normal file
18
api/ProVM/Implement/Filesystem.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
namespace ProVM\Implement;
|
||||
|
||||
use ProVM\Concept\File as FileInterface;
|
||||
use ProVM\Alias\Filesystem as BaseFilesystem;
|
||||
|
||||
class Filesystem extends BaseFilesystem
|
||||
{
|
||||
public function __construct(string $path)
|
||||
{
|
||||
$this->setBasePath($path);
|
||||
}
|
||||
|
||||
public function get(string $relative_path): FileInterface
|
||||
{
|
||||
return new File($this->buildPath($relative_path));
|
||||
}
|
||||
}
|
58
api/ProVM/Implement/Path.php
Normal file
58
api/ProVM/Implement/Path.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace ProVM\Implement;
|
||||
|
||||
use ProVM\Concept\Path as PathInterface;
|
||||
|
||||
class Path implements PathInterface
|
||||
{
|
||||
protected array $path;
|
||||
public function compose(string $base_path): PathInterface
|
||||
{
|
||||
$this->path = [];
|
||||
return $this->add($base_path);
|
||||
}
|
||||
public function add(string $path_segment): PathInterface
|
||||
{
|
||||
$this->path []= $path_segment;
|
||||
return $this;
|
||||
}
|
||||
public function build(): string
|
||||
{
|
||||
return implode(DIRECTORY_SEPARATOR, $this->path);
|
||||
}
|
||||
public static function fromArray(array $path): string
|
||||
{
|
||||
$output = new Path();
|
||||
$output->compose(array_shift($path));
|
||||
foreach ($path as $p) {
|
||||
$output->add($p);
|
||||
}
|
||||
return $output->build();
|
||||
}
|
||||
|
||||
public static function isAbsolute(string $path): bool
|
||||
{
|
||||
return !file_exists(Path::fromArray([$path, '..']));
|
||||
}
|
||||
public static function isRelative(string $path): bool
|
||||
{
|
||||
return !Path::isAbsolute($path);
|
||||
}
|
||||
|
||||
public function offsetExists(mixed $offset): bool
|
||||
{
|
||||
return isset($this->path[$offset]);
|
||||
}
|
||||
public function offsetGet(mixed $offset): mixed
|
||||
{
|
||||
return $this->path[$offset];
|
||||
}
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
$this->path[$offset] = $value;
|
||||
}
|
||||
public function offsetUnset(mixed $offset): void
|
||||
{
|
||||
unset($this->path[$offset]);
|
||||
}
|
||||
}
|
14
api/Psr/Collection/CollectionInterface.php
Normal file
14
api/Psr/Collection/CollectionInterface.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
namespace Psr\Collection;
|
||||
|
||||
use Iterator, ArrayAccess, Countable;
|
||||
|
||||
interface CollectionInterface extends Iterator, ArrayAccess, Countable
|
||||
{
|
||||
public function set(mixed $name, $value): CollectionInterface;
|
||||
public function has(mixed $name): bool;
|
||||
public function get(mixed $name);
|
||||
public function remove(mixed $name): CollectionInterface;
|
||||
public static function fromArray(array $source): CollectionInterface;
|
||||
public static function fromObject(object $source): CollectionInterface;
|
||||
}
|
29
api/Psr/Database/DatabaseInterface.php
Normal file
29
api/Psr/Database/DatabaseInterface.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Psr\Database;
|
||||
|
||||
use PDO;
|
||||
|
||||
interface DatabaseInterface
|
||||
{
|
||||
public function setHost(string $host, ?int $port = null): DatabaseInterface;
|
||||
public function getHost(): string;
|
||||
public function getPort(): int;
|
||||
public function setName(string $database_name): DatabaseInterface;
|
||||
public function getName(): string;
|
||||
public function setUser(string $username, string $password): DatabaseInterface;
|
||||
public function getUser(): string;
|
||||
public function getPassword(): string;
|
||||
public function getDsn(): string;
|
||||
public function needsUser(): bool;
|
||||
public function connect(): DatabaseInterface;
|
||||
public function getConnection(): PDO;
|
||||
public function beginTransaction(): void;
|
||||
public function commit(): void;
|
||||
public function rollBack(): void;
|
||||
public function query(string $query): array;
|
||||
public function prepare(string $query): DatabaseInterface;
|
||||
public function execute(array $data): array;
|
||||
public function insert(array $values): void;
|
||||
public function update(array $data): void;
|
||||
public function delete(array $data): void;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Alias;
|
||||
|
||||
interface DocumentHandler {
|
||||
public function load(): ?array;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Concept;
|
||||
|
||||
use Contabilidad\Common\Alias\DocumentHandler as HandlerInterface;
|
||||
|
||||
abstract class DocumentHandler implements HandlerInterface {
|
||||
protected string $folder;
|
||||
public function __construct(string $source_folder) {
|
||||
$this->folder = $source_folder;
|
||||
}
|
||||
}
|
@ -1,34 +1,21 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
namespace Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use function Safe\{json_decode, file_get_contents};
|
||||
use ProVM\Alias\Controller\Json;
|
||||
use ProVM\Implement\Path;
|
||||
|
||||
class Base {
|
||||
use Json;
|
||||
class Base
|
||||
{
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response): Response {
|
||||
return $this->withJson($response, []);
|
||||
}
|
||||
public function generate_key(Request $request, Response $response): Response {
|
||||
$server_addr = explode('.', $request->getServerParams()['SERVER_ADDR']);
|
||||
$remote_addr = explode('.', $request->getServerParams()['REMOTE_ADDR']);
|
||||
for ($i = 0; $i < 3; $i ++) {
|
||||
if ($server_addr[$i] != $remote_addr[$i]) {
|
||||
throw new \InvalidArgumentException('Invalid connection address.');
|
||||
}
|
||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, ContainerInterface $container): ResponseInterface
|
||||
{
|
||||
$filename = $container->get('documentation');
|
||||
$documentation = json_decode(trim(file_get_contents($filename)));
|
||||
return $this->withJson($response, $documentation);
|
||||
}
|
||||
$salt = mt_rand();
|
||||
$signature = hash_hmac('sha256', $salt, 'contabilidad', true);
|
||||
$key = urlencode(base64_encode($signature));
|
||||
return $this->withJson($response, ['key' => $key]);
|
||||
}
|
||||
public function info(Request $request, Response $response): Response {
|
||||
ob_start();
|
||||
phpinfo();
|
||||
$data = ob_get_clean();
|
||||
$response->getBody()->write($data);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
@ -1,112 +1,16 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
namespace Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\Common\Service\TiposCambios as Service;
|
||||
use Contabilidad\Categoria;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use ProVM\Alias\API\Controller;
|
||||
use Contabilidad\Repository\Categoria;
|
||||
|
||||
class Categorias {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory, Service $service): Response {
|
||||
$categorias = $factory->find(Categoria::class)->many();
|
||||
if ($categorias !== null) {
|
||||
array_walk($categorias, function(&$item) use ($service) {
|
||||
$arr = $item->toArray();
|
||||
if ($item->cuentas()) {
|
||||
$arr['cuentas'] = array_map(function($item) {
|
||||
return $item->toArray();
|
||||
}, $item->cuentas());
|
||||
}
|
||||
$maps = ['activo', 'pasivo', 'ganancia', 'perdida'];
|
||||
foreach ($maps as $m) {
|
||||
$p = $m . 's';
|
||||
$t = ucfirst($m);
|
||||
$cuentas = $item->getCuentasOf($t);
|
||||
if ($cuentas === false or $cuentas === null) {
|
||||
$arr[$p] = 0;
|
||||
continue;
|
||||
}
|
||||
$arr[$p] = array_reduce($cuentas, function($sum, $item) use($service) {
|
||||
return $sum + $item->saldo($service, true);
|
||||
});
|
||||
}
|
||||
$item = $arr;
|
||||
});
|
||||
usort($categorias, function($a, $b) {
|
||||
return strcmp($a['nombre'], $b['nombre']);
|
||||
});
|
||||
class Categorias extends Controller
|
||||
{
|
||||
public function setup(ContainerInterface $container): void
|
||||
{
|
||||
$this->setSingular('categoria')
|
||||
->setPlural('categorias')
|
||||
->setRepository($container->get(Categoria::class));
|
||||
}
|
||||
$output = [
|
||||
'categorias' => $categorias
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function show(Request $request, Response $response, Factory $factory, $categoria_id): Response {
|
||||
$categoria = $factory->find(Categoria::class)->one($categoria_id);
|
||||
$output = [
|
||||
'input' => $categoria_id,
|
||||
'categoria' => $categoria?->toArray()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function add(Request $request, Response $response, Factory $factory): Response {
|
||||
$input = json_decode($request->getBody());
|
||||
$results = [];
|
||||
if (is_array($input)) {
|
||||
foreach ($input as $in) {
|
||||
$categoria = Categoria::add($factory, $in);
|
||||
$results []= ['categoria' => $categoria?->toArray(), 'agregado' => $categoria?->save()];
|
||||
}
|
||||
} else {
|
||||
$categoria = Categoria::add($factory, $input);
|
||||
$results []= ['categoria' => $categoria?->toArray(), 'agregado' => $categoria?->save()];
|
||||
}
|
||||
$output = [
|
||||
'input' => $input,
|
||||
'categorias' => $results
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function edit(Request $request, Response $response, Factory $factory, $categoria_id): Response {
|
||||
$categoria = $factory->find(Categoria::class)->one($categoria_id);
|
||||
$output = [
|
||||
'input' => $categoria_id,
|
||||
'old' => $categoria->toArray()
|
||||
];
|
||||
$input = json_decode($request->getBody());
|
||||
$categoria->edit($input);
|
||||
$output['categoria'] = $categoria->toArray();
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function delete(Request $request, Response $response, Factory $factory, $categoria_id): Response {
|
||||
$categoria = $factory->find(Categoria::class)->one($categoria_id);
|
||||
$output = [
|
||||
'input' => $categoria_id,
|
||||
'categoria' => $categoria->toArray(),
|
||||
'eliminado' => $categoria->delete()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function cuentas(Request $request, Response $response, Factory $factory, Service $service, $categoria_id): Response {
|
||||
$categoria = $factory->find(Categoria::class)->one($categoria_id);
|
||||
$cuentas = null;
|
||||
if ($categoria !== null) {
|
||||
$cuentas = $categoria->cuentas();
|
||||
if ($cuentas !== null) {
|
||||
array_walk($cuentas, function(&$item) use ($service) {
|
||||
$item = $item->toArray($service);
|
||||
});
|
||||
}
|
||||
}
|
||||
$output = [
|
||||
'input' => $categoria_id,
|
||||
'categoria' => $categoria?->toArray(),
|
||||
'cuentas' => $cuentas
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
||||
|
16
api/common/Controller/Conecciones.php
Normal file
16
api/common/Controller/Conecciones.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace Common\Controller;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use ProVM\Alias\API\Controller;
|
||||
use Contabilidad\Repository\Coneccion;
|
||||
|
||||
class Conecciones extends Controller
|
||||
{
|
||||
public function setup(ContainerInterface $container): void
|
||||
{
|
||||
$this->setSingular('coneccion')
|
||||
->setPlural('conecciones')
|
||||
->setRepository($container->get(Coneccion::class));
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
<?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, []);
|
||||
}
|
||||
}
|
@ -1,197 +1,16 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
namespace Common\Controller;
|
||||
|
||||
use Contabilidad\Transaccion;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Carbon\Carbon;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\Common\Service\TiposCambios as Service;
|
||||
use Contabilidad\Cuenta;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use ProVM\Alias\API\Controller;
|
||||
use Contabilidad\Repository\Cuenta;
|
||||
|
||||
class Cuentas {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
||||
$cuentas = $factory->find(Cuenta::class)->many();
|
||||
if ($cuentas) {
|
||||
array_walk($cuentas, function (&$item) {
|
||||
$arr = $item->toArray();
|
||||
$arr['categoria'] = $item->categoria()->toArray();
|
||||
$item = $arr;
|
||||
});
|
||||
usort($cuentas, function($a, $b) {
|
||||
$t = strcmp($a['tipo']['descripcion'], $b['tipo']['descripcion']);
|
||||
if ($t != 0) {
|
||||
return $t;
|
||||
}
|
||||
$c = strcmp($a['categoria']['nombre'], $b['categoria']['nombre']);
|
||||
if ($c != 0) {
|
||||
return $c;
|
||||
}
|
||||
return strcmp($a['nombre'], $b['nombre']);
|
||||
});
|
||||
class Cuentas extends Controller
|
||||
{
|
||||
public function setup(ContainerInterface $container): void
|
||||
{
|
||||
$this->setSingular('cuenta')
|
||||
->setPlural('cuentas')
|
||||
->setRepository($container->get(Cuenta::class));
|
||||
}
|
||||
$output = [
|
||||
'cuentas' => $cuentas
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function show(Request $request, Response $response, Factory $factory, $cuenta_id): Response {
|
||||
$cuenta = $factory->find(Cuenta::class)->one($cuenta_id);
|
||||
$output = [
|
||||
'input' => $cuenta_id,
|
||||
'cuenta' => $cuenta?->toArray()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function add(Request $request, Response $response, Factory $factory): Response {
|
||||
$input = json_decode($request->getBody());
|
||||
$results = [];
|
||||
if (is_array($input)) {
|
||||
foreach ($input as $in) {
|
||||
$cuenta = Cuenta::add($factory, $in);
|
||||
$results []= ['cuenta' => $cuenta?->toArray(), 'agregado' => $cuenta?->save()];
|
||||
}
|
||||
} else {
|
||||
$cuenta = Cuenta::add($factory, $input);
|
||||
$results []= ['cuenta' => $cuenta?->toArray(), 'agregado' => $cuenta?->save()];
|
||||
}
|
||||
$output = [
|
||||
'input' => $input,
|
||||
'cuentas' => $results
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function edit(Request $request, Response $response, Factory $factory, $cuenta_id): Response {
|
||||
$cuenta = $factory->find(Cuenta::class)->one($cuenta_id);
|
||||
$output = [
|
||||
'input' => $cuenta_id,
|
||||
'old' => $cuenta->toArray()
|
||||
];
|
||||
$input = json_decode($request->getBody());
|
||||
$cuenta->edit($input);
|
||||
$output['cuenta'] = $cuenta->toArray();
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function delete(Request $request, Response $response, Factory $factory, $cuenta_id): Response {
|
||||
$cuenta = $factory->find(Cuenta::class)->one($cuenta_id);
|
||||
$output = [
|
||||
'input' => $cuenta_id,
|
||||
'cuenta' => $cuenta->toArray(),
|
||||
'eliminado' => $cuenta->delete()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function categoria(Request $request, Response $response, Factory $factory, $cuenta_id): Response {
|
||||
$cuenta = $factory->find(Cuenta::class)->one($cuenta_id);
|
||||
$output = [
|
||||
'input' => $cuenta_id,
|
||||
'cuenta' => $cuenta?->toArray(),
|
||||
'categoria' => $cuenta?->categoria()->toArray()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function entradas(Request $request, Response $response, Factory $factory, $cuenta_id): Response {
|
||||
$cuenta = $factory->find(Cuenta::class)->one($cuenta_id);
|
||||
$entradas = null;
|
||||
if ($cuenta !== null) {
|
||||
$entradas = $cuenta->entradas();
|
||||
if ($entradas !== null) {
|
||||
array_walk($entradas, function(&$item) {
|
||||
$item = $item->toArray();
|
||||
});
|
||||
}
|
||||
}
|
||||
$output = [
|
||||
'input' => $cuenta_id,
|
||||
'cuenta' => $cuenta?->toArray(),
|
||||
'entradas' => $entradas
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
protected function transaccionToArray(Service $service, Cuenta $cuenta, Transaccion $transaccion): array {
|
||||
$arr = $transaccion->toArray();
|
||||
if ($cuenta->moneda()->codigo === 'CLP') {
|
||||
if ($transaccion->debito()->moneda()->codigo !== 'CLP' or $transaccion->credito()->moneda()->codigo !== 'CLP') {
|
||||
if ($transaccion->debito()->moneda()->codigo !== 'CLP') {
|
||||
$c = $transaccion->debito();
|
||||
} else {
|
||||
$c = $transaccion->credito();
|
||||
}
|
||||
$service->get($transaccion->fecha(), $c->moneda()->id);
|
||||
$arr['valor'] = $transaccion->valor;
|
||||
$arr['valorFormateado'] = $cuenta->moneda()->format($arr['valor']);
|
||||
}
|
||||
}
|
||||
$arr['debito']['categoria'] = $transaccion->debito()->categoria()->toArray();
|
||||
$arr['credito']['categoria'] = $transaccion->credito()->categoria()->toArray();
|
||||
return $arr;
|
||||
}
|
||||
public function transacciones(Request $request, Response $response, Factory $factory, Service $service, $cuenta_id, $limit = null, $start = 0): Response {
|
||||
$cuenta = $factory->find(Cuenta::class)->one($cuenta_id);
|
||||
$transacciones = null;
|
||||
if ($cuenta !== null) {
|
||||
$transacciones = $cuenta->transacciones($limit, $start);
|
||||
if (count($transacciones) > 0) {
|
||||
foreach ($transacciones as &$transaccion) {
|
||||
$transaccion = $this->transaccionToArray($service, $cuenta, $transaccion);
|
||||
}
|
||||
}
|
||||
}
|
||||
$output = [
|
||||
'input' => $cuenta_id,
|
||||
'cuenta' => $cuenta?->toArray(),
|
||||
'transacciones' => $transacciones
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function transaccionesMonth(Request $request, Response $response, Factory $factory, Service $service, $cuenta_id, $month): Response {
|
||||
$cuenta = $factory->find(Cuenta::class)->one($cuenta_id);
|
||||
$month = Carbon::parse($month);
|
||||
$transacciones = null;
|
||||
if ($cuenta !== null) {
|
||||
$transacciones = $cuenta->transaccionesMonth($month);
|
||||
if (count($transacciones) > 0) {
|
||||
foreach ($transacciones as &$transaccion) {
|
||||
$transaccion = $this->transaccionToArray($service, $cuenta, $transaccion);
|
||||
}
|
||||
}
|
||||
}
|
||||
$output = [
|
||||
'input' => compact('cuenta_id', 'month'),
|
||||
'cuenta' => $cuenta?->toArray(),
|
||||
'transacciones' => $transacciones
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function transaccionesAcumulation(Request $request, Response $response, Factory $factory, $cuenta_id, $date): Response {
|
||||
$cuenta = $factory->find(Cuenta::class)->one($cuenta_id);
|
||||
$f = Carbon::parse($date);
|
||||
$acum = 0;
|
||||
if ($cuenta !== null) {
|
||||
$acum = $cuenta->acumulacion($f);
|
||||
}
|
||||
$output = [
|
||||
'input' => compact('cuenta_id', 'date'),
|
||||
'cuenta' => $cuenta?->toArray(),
|
||||
'format' => $cuenta->moneda()->toArray(),
|
||||
'acumulation' => $acum
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function transaccionesAmount(Request $request, Response $response, Factory $factory, $cuenta_id): Response {
|
||||
$cuenta = $factory->find(Cuenta::class)->one($cuenta_id);
|
||||
$transacciones = 0;
|
||||
if ($cuenta !== null) {
|
||||
$transacciones = count($cuenta->transacciones());
|
||||
}
|
||||
$output = [
|
||||
'input' => $cuenta_id,
|
||||
'cuenta' => $cuenta?->toArray(),
|
||||
'transacciones' => $transacciones
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
||||
|
17
api/common/Controller/Estado/Conecciones.php
Normal file
17
api/common/Controller/Estado/Conecciones.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace Common\Controller\Estado;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use ProVM\Alias\API\Controller;
|
||||
use Contabilidad\Repository\Estado\Coneccion;
|
||||
|
||||
class Conecciones extends Controller
|
||||
{
|
||||
|
||||
public function setup(ContainerInterface $container): void
|
||||
{
|
||||
$this->setSingular('estado_coneccion')
|
||||
->setPlural('estados_conecciones')
|
||||
->setRepository($container->get(Coneccion::class));
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use Contabilidad\Common\Service\FileHandler as Handler;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\Cuenta;
|
||||
|
||||
class Files {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Handler $handler): Response {
|
||||
$files = $handler->listFiles();
|
||||
usort($files, function($a, $b) {
|
||||
$f = strcmp($a->folder, $b->folder);
|
||||
if ($f == 0) {
|
||||
return strcmp($a->filename, $b->filename);
|
||||
}
|
||||
return $f;
|
||||
});
|
||||
return $this->withJson($response, compact('files'));
|
||||
}
|
||||
public function upload(Request $request, Response $response, Handler $handler, Factory $factory): Response {
|
||||
$post = $request->getParsedBody();
|
||||
$cuenta = $factory->find(Cuenta::class)->one($post['cuenta']);
|
||||
$file = $request->getUploadedFiles()['archivo'];
|
||||
$new_name = implode(' - ', [$cuenta->nombre, $cuenta->categoria()->nombre, $post['fecha']]);
|
||||
$output = [
|
||||
'input' => [
|
||||
'name' => $file->getClientFilename(),
|
||||
'type' => $file->getClientMediaType(),
|
||||
'size' => $file->getSize(),
|
||||
'error' => $file->getError()
|
||||
],
|
||||
'new_name' => $new_name,
|
||||
'uploaded' => $handler->uploadFile($file, $new_name)
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function get(Request $request, Response $response, Handler $handler, $folder, $filename): Response {
|
||||
$file = $handler->getFile($folder, $filename);
|
||||
return $response
|
||||
->withHeader('Content-Type', $handler->getType($folder))
|
||||
->withHeader('Content-Disposition', 'attachment; filename=' . $filename)
|
||||
->withAddedHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
|
||||
->withHeader('Cache-Control', 'post-check=0, pre-check=0')
|
||||
->withHeader('Pragma', 'no-cache')
|
||||
->withBody($file);
|
||||
}
|
||||
public function edit(Request $request, Response $response, Handler $handler, Factory $factory, $folder, $filename): Response {
|
||||
$post = json_decode($request->getBody());
|
||||
$cuenta = $factory->find(Cuenta::class)->one($post->cuenta);
|
||||
$new_name = implode(' - ', [$cuenta->nombre, $cuenta->categoria()->nombre, $post->fecha]);
|
||||
$output = [
|
||||
'input' => [
|
||||
'folder' => $folder,
|
||||
'filename' => $filename,
|
||||
'post' => $post
|
||||
],
|
||||
'edited' => $handler->editFilename($folder, $filename, $new_name)
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function delete(Request $request, Response $response, Handler $handler, $folder, $filename): Response {
|
||||
$output = [
|
||||
'input' => [
|
||||
'folder' => $folder,
|
||||
'filename' => $filename
|
||||
],
|
||||
'deleted' => $handler->deleteFile($folder, $filename)
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Container\ContainerInterface as Container;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\Common\Service\DocumentHandler as Handler;
|
||||
use Contabilidad\Cuenta;
|
||||
|
||||
class Import {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory, Container $container): Response {
|
||||
$post =$request->getParsedBody();
|
||||
$cuenta = $factory->find(Cuenta::class)->one($post['cuenta']);
|
||||
$file = $request->getUploadedFiles()['archivo'];
|
||||
$valid_media = [
|
||||
'text/csv' => 'csvs',
|
||||
'application/pdf' => 'pdfs',
|
||||
'application/vnd.ms-excel' => 'xlss',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlss',
|
||||
'application/json' => 'jsons'
|
||||
];
|
||||
if ($file->getError() === 0 and in_array($file->getClientMediaType(), array_keys($valid_media))) {
|
||||
$filenfo = new \SplFileInfo($file->getClientFilename());
|
||||
$new_name = implode('.', [implode(' - ', [$cuenta->nombre, $cuenta->categoria()->nombre, $post['fecha']]), $filenfo->getExtension()]);
|
||||
$to = implode(DIRECTORY_SEPARATOR, [$container->get('folders')->uploads, $valid_media[$file->getClientMediaType()], $new_name]);
|
||||
$file->moveTo($to);
|
||||
$status = file_exists($to);
|
||||
}
|
||||
$output = [
|
||||
'input' => [
|
||||
'name' => $file->getClientFilename(),
|
||||
'type' => $file->getClientMediaType(),
|
||||
'size' => $file->getSize(),
|
||||
'error' => $file->getError()
|
||||
],
|
||||
'new_name' => $new_name,
|
||||
'uploaded' => $status
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function uploads(Request $request, Response $response, Handler $handler): Response {
|
||||
$output = $handler->handle();
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
@ -1,71 +1,16 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
namespace Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\Moneda;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use ProVM\Alias\API\Controller;
|
||||
use Contabilidad\Repository\Moneda;
|
||||
|
||||
class Monedas {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
||||
$monedas = $factory->find(Moneda::class)->array();
|
||||
if ($monedas) {
|
||||
usort($monedas, function($a, $b) {
|
||||
return strcmp($a['denominacion'], $b['denominacion']);
|
||||
});
|
||||
}
|
||||
$output = [
|
||||
'monedas' => $monedas
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function show(Request $request, Response $response, Factory $factory, $moneda_id): Response {
|
||||
$moneda = $factory->find(Moneda::class)->one($moneda_id);
|
||||
$output = [
|
||||
'input' => $moneda_id,
|
||||
'moneda' => $moneda?->toArray()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function add(Request $request, Response $response, Factory $factory): Response {
|
||||
$input = json_decode($request->getBody());
|
||||
$results = [];
|
||||
if (is_array($input)) {
|
||||
foreach ($input as $in) {
|
||||
$moneda = Moneda::add($factory, $in);
|
||||
$results []= ['moneda' => $moneda?->toArray(), 'agregado' => $moneda?->save()];
|
||||
}
|
||||
} else {
|
||||
$moneda = Moneda::add($factory, $input);
|
||||
$results []= ['moneda' => $moneda?->toArray(), 'agregado' => $moneda?->save()];
|
||||
}
|
||||
$output = [
|
||||
'input' => $input,
|
||||
'monedas' => $results
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function edit(Request $request, Response $response, Factory $factory, $moneda_id): Response {
|
||||
$moneda = $factory->find(Moneda::class)->one($moneda_id);
|
||||
$output = [
|
||||
'input' => $moneda_id,
|
||||
'old' => $moneda->toArray()
|
||||
];
|
||||
$input = json_decode($request->getBody());
|
||||
$moneda->edit($input);
|
||||
$output['moneda'] = $moneda->toArray();
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function delete(Request $request, Response $response, Factory $factory, $moneda_id): Response {
|
||||
$moneda = $factory->find(Moneda::class)->one($moneda_id);
|
||||
$output = [
|
||||
'input' => $moneda_id,
|
||||
'moneda' => $moneda->toArray(),
|
||||
'eliminado' => $moneda->delete()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
class Monedas extends Controller
|
||||
{
|
||||
public function setup(ContainerInterface $container): void
|
||||
{
|
||||
$this->setSingular('moneda');
|
||||
$this->setPlural('monedas');
|
||||
$this->setRepository($container->get(Moneda::class));
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
<?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\Queue;
|
||||
|
||||
class Queues {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
||||
$queues = $factory->find(Queue::class)->many();
|
||||
$output = [
|
||||
'queues' => array_map(function($item) {return $item->toArray();}, $queues)
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function pending(Request $request, Response $response, Factory $factory): Response {
|
||||
$pending = $factory->find(Queue::class)->where([['processed', 0]])->many();
|
||||
$output = [
|
||||
'pending' => array_map(function($item) {return $item->toArray();}, $pending)
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function processed(Request $request, Response $response, Factory $factory): Response {
|
||||
$input = json_decode($request->getBody()->getContents());
|
||||
$output = [
|
||||
'input' => $input,
|
||||
'queues' => []
|
||||
];
|
||||
if (!is_array($input->processed)) {
|
||||
$input->processed = [$input->processed];
|
||||
}
|
||||
foreach ($input->processed as $id) {
|
||||
$queue = $factory->find(Queue::class)->one($id);
|
||||
$queue->setProcessed(true);
|
||||
$status = $queue->save();
|
||||
$output['queues'] []= [
|
||||
'queue' => $queue->toArray(),
|
||||
'processed' => $status
|
||||
];
|
||||
}
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\Common\Service\TiposCambios as Service;
|
||||
use Contabilidad\TipoCambio;
|
||||
|
||||
class TiposCambios {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
||||
$tipos = $factory->find(TipoCambio::class)->array();
|
||||
if ($tipos) {
|
||||
usort($tipos, function($a, $b) {
|
||||
return strcmp($a['fecha'], $b['fecha']);
|
||||
});
|
||||
}
|
||||
$output = [
|
||||
'tipos' => $tipos
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function show(Request $request, Response $response, Factory $factory, $tipo_id): Response {
|
||||
$tipo = $factory->find(TipoCambio::class)->one($tipo_id);
|
||||
$output = [
|
||||
'input' => $tipo_id,
|
||||
'tipo' => $tipo?->toArray()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function add(Request $request, Response $response, Factory $factory): Response {
|
||||
$input = json_decode($request->getBody());
|
||||
$results = [];
|
||||
if (is_array($input)) {
|
||||
foreach ($input as $in) {
|
||||
$tipo = TipoCambio::add($factory, $in);
|
||||
$results []= ['tipo' => $tipo?->toArray(), 'agregado' => $tipo?->save()];
|
||||
}
|
||||
} else {
|
||||
$tipo = TipoCambio::add($factory, $input);
|
||||
$results []= ['tipo' => $tipo?->toArray(), 'agregado' => $tipo?->save()];
|
||||
}
|
||||
$output = [
|
||||
'input' => $input,
|
||||
'tipos' => $results
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function edit(Request $request, Response $response, Factory $factory, $tipo_id): Response {
|
||||
$tipo = $factory->find(TipoCambio::class)->one($tipo_id);
|
||||
$output = [
|
||||
'input' => $tipo_id,
|
||||
'old' => $tipo->toArray()
|
||||
];
|
||||
$input = json_decode($request->getBody());
|
||||
$tipo->edit($input);
|
||||
$output['tipo'] = $tipo->toArray();
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function delete(Request $request, Response $response, Factory $factory, $tipo_id): Response {
|
||||
$tipo = $factory->find(TipoCambio::class)->one($tipo_id);
|
||||
$output = [
|
||||
'input' => $tipo_id,
|
||||
'tipo' => $tipo->toArray(),
|
||||
'eliminado' => $tipo->delete()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function obtain(Request $request, Response $response, Factory $factory, Service $service): Response {
|
||||
$post = $request->getParsedBody();
|
||||
$valor = $service->get($post['fecha'], $post['moneda_id']);
|
||||
if ($valor === null) {
|
||||
return $this->withJson($response, ['input' => $post, 'tipo' => null, 'error' => 'No se encontró valor']);
|
||||
}
|
||||
$data = [
|
||||
'fecha' => $post['fecha'],
|
||||
'desde_id' => $post['moneda_id'],
|
||||
'hasta_id' => 1,
|
||||
'valor' => $valor
|
||||
];
|
||||
$tipo = TipoCambio::add($factory, $data);
|
||||
if ($tipo !== false and $tipo->is_new()) {
|
||||
$tipo->save();
|
||||
}
|
||||
$output = [
|
||||
'input' => $post,
|
||||
'tipo' => $tipo?->toArray()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
|
||||
use Contabilidad\TipoCuenta;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\Common\Service\TiposCambios as Service;
|
||||
use Contabilidad\TipoCategoria;
|
||||
|
||||
class TiposCategorias {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory, Service $service): Response {
|
||||
$tipos = $factory->find(TipoCategoria::class)->many();
|
||||
if ($tipos !== null) {
|
||||
array_walk($tipos, function(&$item) use ($service) {
|
||||
$arr = $item->toArray();
|
||||
$arr['categorias'] = $item->categorias();
|
||||
if ($arr['categorias'] !== null) {
|
||||
$arr['categorias'] = array_map(function($item) {
|
||||
return $item->toArray();
|
||||
}, $item->categorias());
|
||||
}
|
||||
$arr['saldo'] = abs($item->saldo($service));
|
||||
$arr['totales'] = $item->getTotales($service);
|
||||
$item = $arr;
|
||||
});
|
||||
usort($tipos, function($a, $b) {
|
||||
return strcmp($a['descripcion'], $b['descripcion']);
|
||||
});
|
||||
}
|
||||
$output = [
|
||||
'tipos' => $tipos
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function add(Request $request, Response $response, Factory $factory): Response {
|
||||
$input = json_decode($request->getBody());
|
||||
$results = [];
|
||||
if (is_array($input)) {
|
||||
foreach ($input as $in) {
|
||||
$tipo = TipoCategoria::add($factory, $in);
|
||||
$results []= ['tipo' => $tipo?->toArray(), 'agregado' => $tipo?->save()];
|
||||
}
|
||||
} else {
|
||||
$tipo = TipoCategoria::add($factory, $input);
|
||||
$results []= ['tipo' => $tipo?->toArray(), 'agregado' => $tipo?->save()];
|
||||
}
|
||||
$output = [
|
||||
'input' => $input,
|
||||
'tipos' => $results
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function edit(Request $request, Response $response, Factory $factory, $tipo_id): Response {
|
||||
$tipo = $factory->find(TipoCategoria::class)->one($tipo_id);
|
||||
$output = [
|
||||
'input' => $tipo_id,
|
||||
'old' => $tipo->toArray()
|
||||
];
|
||||
$input = json_decode($request->getBody());
|
||||
$tipo->edit($input);
|
||||
$output['tipo'] = $tipo->toArray();
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function delete(Request $request, Response $response, Factory $factory, $tipo_id): Response {
|
||||
$tipo = $factory->find(TipoCategoria::class)->one($tipo_id);
|
||||
$output = [
|
||||
'input' => $tipo_id,
|
||||
'tipo' => $tipo->toArray(),
|
||||
'eliminado' => $tipo->delete()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function categorias(Request $request, Response $response, Factory $factory, Service $service, $tipo_id): Response {
|
||||
$tipo = $factory->find(TipoCategoria::class)->one($tipo_id);
|
||||
$categorias = null;
|
||||
if ($tipo != null) {
|
||||
$categorias = $tipo->categorias();
|
||||
if ($categorias !== null) {
|
||||
array_walk($categorias, function(&$item) use ($service) {
|
||||
$arr = $item->toArray($service);
|
||||
$arr['totales'] = $item->getTotales($service);
|
||||
$item = $arr;
|
||||
});
|
||||
}
|
||||
}
|
||||
$output = [
|
||||
'input' => $tipo_id,
|
||||
'tipo' => $tipo?->toArray(),
|
||||
'categorias' => $categorias
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function balance(Request $request, Response $response, Factory $factory, Service $service): Response {
|
||||
$tipos = $factory->find(TipoCategoria::class)->many();
|
||||
$balance = array_reduce($tipos, function($sum, $item) use ($service) {
|
||||
$totales = $item->getTotales($service);
|
||||
if (!is_array($sum)) {
|
||||
$sum = [];
|
||||
}
|
||||
foreach ($totales as $p => $total) {
|
||||
if (!isset($sum[$p])) {
|
||||
$sum[$p] = 0;
|
||||
}
|
||||
$sum[$p] += $total;
|
||||
}
|
||||
return $sum;
|
||||
});
|
||||
/*$balance = array_reduce($tipos, function($sum, $item) use ($service) {
|
||||
$maps = ['activo', 'pasivo', 'ganancia', 'perdida'];
|
||||
foreach ($maps as $m) {
|
||||
$p = $m . 's';
|
||||
$t = ucfirst($m);
|
||||
if (!isset($sum[$p])) {
|
||||
$sum[$p] = 0;
|
||||
}
|
||||
$cuentas = $item->getCuentasOf($t);
|
||||
if ($cuentas === false or $cuentas === null) {
|
||||
continue;
|
||||
}
|
||||
$sum[$p] += array_reduce($cuentas, function($sum, $item) use($service) {
|
||||
return $sum + $item->saldo($service, true);
|
||||
});
|
||||
}
|
||||
return $sum;
|
||||
});*/
|
||||
return $this->withJson($response, $balance);
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\TipoCuenta;
|
||||
|
||||
class TiposCuentas {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
||||
$tipos = $factory->find(TipoCuenta::class)->array();
|
||||
if ($tipos) {
|
||||
usort($tipos, function($a, $b) {
|
||||
return strcmp($a['descripcion'], $b['descripcion']);
|
||||
});
|
||||
}
|
||||
$output = [
|
||||
'tipos' => $tipos
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function show(Request $request, Response $response, Factory $factory, $tipo_id): Response {
|
||||
$tipo = $factory->find(TipoCuenta::class)->one($tipo_id);
|
||||
$output = [
|
||||
'input' => $tipo_id,
|
||||
'tipo' => $tipo?->toArray()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function add(Request $request, Response $response, Factory $factory): Response {
|
||||
$input = json_decode($request->getBody());
|
||||
$results = [];
|
||||
if (is_array($input)) {
|
||||
foreach ($input as $in) {
|
||||
$tipo = TipoCuenta::add($factory, $in);
|
||||
$results []= ['tipo' => $tipo?->toArray(), 'agregado' => $tipo?->save()];
|
||||
}
|
||||
} else {
|
||||
$tipo = TipoCuenta::add($factory, $input);
|
||||
$results []= ['tipo' => $tipo?->toArray(), 'agregado' => $tipo?->save()];
|
||||
}
|
||||
$output = [
|
||||
'input' => $input,
|
||||
'tipos' => $results
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function edit(Request $request, Response $response, Factory $factory, $tipo_id): Response {
|
||||
$tipo = $factory->find(TipoCuenta::class)->one($tipo_id);
|
||||
$output = [
|
||||
'input' => $tipo_id,
|
||||
'old' => $tipo->toArray()
|
||||
];
|
||||
$input = json_decode($request->getBody());
|
||||
$tipo->edit($input);
|
||||
$output['tipo'] = $tipo->toArray();
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function delete(Request $request, Response $response, Factory $factory, $tipo_id): Response {
|
||||
$tipo = $factory->find(TipoCuenta::class)->one($tipo_id);
|
||||
$output = [
|
||||
'input' => $tipo_id,
|
||||
'tipo' => $tipo->toArray(),
|
||||
'eliminado' => $tipo->delete()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
@ -1,75 +1,16 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
namespace Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\Transaccion;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use ProVM\Alias\API\Controller;
|
||||
use Contabilidad\Repository\Transaccion;
|
||||
|
||||
class Transacciones {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
||||
$transacciones = $factory->find(Transaccion::class)->array();
|
||||
if ($transacciones !== null) {
|
||||
usort($transacciones, function($a, $b) {
|
||||
$d = $a['fecha'] - $b['fecha'];
|
||||
if ($d === 0) {
|
||||
return strcmp($a['cuenta']['nombre'], $b['cuenta']['nombre']);
|
||||
}
|
||||
return $d;
|
||||
});
|
||||
class Transacciones extends Controller
|
||||
{
|
||||
public function setup(ContainerInterface $container): void
|
||||
{
|
||||
$this->setSingular('transaccion');
|
||||
$this->setPlural('transacciones');
|
||||
$this->setRepository($container->get(Transaccion::class));
|
||||
}
|
||||
$output = [
|
||||
'transacciones' => $transacciones
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function show(Request $request, Response $response, Factory $factory, $transaccion_id): Response {
|
||||
$transaccion = $factory->find(Transaccion::class)->one($transaccion_id);
|
||||
$output = [
|
||||
'input' => $transaccion_id,
|
||||
'transaccion' => $transaccion?->toArray()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function add(Request $request, Response $response, Factory $factory): Response {
|
||||
$input = json_decode($request->getBody());
|
||||
$results = [];
|
||||
if (is_array($input)) {
|
||||
foreach ($input as $in) {
|
||||
$transaccion = Transaccion::add($factory, $in);
|
||||
$results []= ['transaccion' => $transaccion?->toArray(), 'agregado' => $transaccion?->save()];
|
||||
}
|
||||
} else {
|
||||
$transaccion = Transaccion::add($factory, $input);
|
||||
$results []= ['transaccion' => $transaccion?->toArray(), 'agregado' => $transaccion?->save()];
|
||||
}
|
||||
$output = [
|
||||
'input' => $input,
|
||||
'transacciones' => $results
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function edit(Request $request, Response $response, Factory $factory, $transaccion_id): Response {
|
||||
$transaccion = $factory->find(Transaccion::class)->one($transaccion_id);
|
||||
$output = [
|
||||
'input' => $transaccion_id,
|
||||
'old' => $transaccion->toArray()
|
||||
];
|
||||
$input = json_decode($request->getBody());
|
||||
$transaccion->edit($input);
|
||||
$output['transaccion'] = $transaccion->toArray();
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function delete(Request $request, Response $response, Factory $factory, $transaccion_id): Response {
|
||||
$transaccion = $factory->find(Transaccion::class)->one($transaccion_id);
|
||||
$output = [
|
||||
'input' => $transaccion_id,
|
||||
'transaccion' => $transaccion->toArray(),
|
||||
'eliminado' => $transaccion->delete()
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use Contabilidad\Common\Service\WorkerHandler as Handler;
|
||||
|
||||
class Workers {
|
||||
use Json;
|
||||
|
||||
public function register(Request $request, Response $response, Handler $handler): Response {
|
||||
$post = $request->getBody();
|
||||
$result = $handler->register($post);
|
||||
$output = [
|
||||
'input' => $post,
|
||||
'result' => $result
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Middleware;
|
||||
namespace Common\Middleware;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Server\RequestHandlerInterface as Handler;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ResponseFactoryInterface as Factory;
|
||||
use Contabilidad\Common\Service\Auth as Service;
|
||||
use Common\Service\Auth as Service;
|
||||
|
||||
class Auth {
|
||||
protected Factory $factory;
|
||||
|
@ -1,20 +0,0 @@
|
||||
<?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->queue();
|
||||
}
|
||||
return $handler->handle($request);
|
||||
}
|
||||
}
|
44
api/common/Middleware/Error.php
Normal file
44
api/common/Middleware/Error.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
namespace Common\Middleware;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Throwable;
|
||||
use Slim\App;
|
||||
use Slim\Interfaces\ErrorHandlerInterface;
|
||||
use function Safe\error_log;
|
||||
|
||||
class Error implements ErrorHandlerInterface
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
$this->setApp($app);
|
||||
}
|
||||
|
||||
protected App $app;
|
||||
public function setApp(App $app): Error
|
||||
{
|
||||
$this->app = $app;
|
||||
return $this;
|
||||
}
|
||||
public function getApp(): App
|
||||
{
|
||||
return $this->app;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request, Throwable $exception, bool $displayErrorDetails, bool $logErrors, bool $logErrorDetails): ResponseInterface
|
||||
{
|
||||
error_log($exception);
|
||||
$response = $this->getApp()->getResponseFactory()->createResponse($exception->getCode());
|
||||
$output = json_encode([
|
||||
'uri' => $request->getUri()->getPath(),
|
||||
'code' => $exception->getCode(),
|
||||
'message' => $exception->getMessage(),
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine(),
|
||||
'trace' => $exception->getTrace()
|
||||
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
$response->getBody()->write($output);
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
}
|
@ -1,36 +1,74 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Service;
|
||||
namespace Common\Service;
|
||||
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use DI\NotFoundException;
|
||||
|
||||
class Auth {
|
||||
protected string $key;
|
||||
public function __construct(string $api_key) {
|
||||
public function __construct(string $api_key)
|
||||
{
|
||||
$this->key = $api_key;
|
||||
}
|
||||
public function isValid(Request $request): bool {
|
||||
if ($request->hasHeader('Authorization')) {
|
||||
$sent_key = $this->getAuthKey($request->getHeader('Authorization'));
|
||||
return $this->key == $sent_key;
|
||||
public function isValid(Request $request): bool
|
||||
{
|
||||
return $this->key == $this->getKey($request);
|
||||
}
|
||||
public function getKey(Request $request): string
|
||||
{
|
||||
$errors = [];
|
||||
try {
|
||||
return $this->getHeaderKey($request);
|
||||
} catch (NotFoundExceptionInterface $e) {
|
||||
$errors []= $e;
|
||||
}
|
||||
try {
|
||||
return $this->getBodyKey($request);
|
||||
} catch (NotFoundExceptionInterface $e) {
|
||||
$errors []= $e;
|
||||
}
|
||||
try {
|
||||
return $this->getQueryKey($request);
|
||||
} catch (NotFoundExceptionInterface $e) {
|
||||
$errors []= $e;
|
||||
}
|
||||
throw new NotFoundException('API Key not found.');
|
||||
}
|
||||
protected function getHeaderKey(Request $request): string
|
||||
{
|
||||
if ($request->hasHeader('Authorization')) {
|
||||
return $this->getAuthKey($request->getHeader('Authorization'));
|
||||
}
|
||||
throw new NotFoundException('API Key not found on header');
|
||||
}
|
||||
protected function getBodyKey(Request $request): string
|
||||
{
|
||||
if (isset($request->getParsedBody()['api_key'])) {
|
||||
$sent_key = $request->getParsedBody()['api_key'];
|
||||
return $this->key == $sent_key;
|
||||
return $request->getParsedBody()['api_key'];
|
||||
}
|
||||
$post = $request->getParsedBody() ?? json_decode($request->getBody());
|
||||
$sent_key = $this->getArrayKey($post);
|
||||
if ($sent_key !== null) {
|
||||
return $this->key == $sent_key;
|
||||
try {
|
||||
return $this->getArrayKey($post);
|
||||
} catch (\Exception $e) {
|
||||
throw new NotFoundException('API Key not found in body.');
|
||||
}
|
||||
$sent_key = $this->getArrayKey($request->getQueryParams());
|
||||
return $this->key == $sent_key;
|
||||
}
|
||||
protected function getAuthKey($auth) {
|
||||
protected function getQueryKey(Request $request): string
|
||||
{
|
||||
try {
|
||||
return $this->getArrayKey($request->getQueryParams());
|
||||
} catch (\Exception $e) {
|
||||
throw new NotFoundException('API Key not found in query.');
|
||||
}
|
||||
}
|
||||
protected function getAuthKey($auth)
|
||||
{
|
||||
if (is_array($auth)) {
|
||||
$auth = $auth[0];
|
||||
}
|
||||
if (str_contains($auth, 'Bearer')) {
|
||||
$auth = explode(' ', $auth)[1];
|
||||
$auth = trim(str_replace('Bearer', '', $auth), ' ,');
|
||||
}
|
||||
return $auth;
|
||||
}
|
||||
|
@ -1,155 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Service;
|
||||
|
||||
use Contabilidad\Common\Concept\DocumentHandler;
|
||||
|
||||
class CsvHandler extends DocumentHandler {
|
||||
public function load(): ?array {
|
||||
$folder = $this->folder;
|
||||
$files = new \DirectoryIterator($folder);
|
||||
$output = [];
|
||||
foreach ($files as $file) {
|
||||
if ($file->isDir() or $file->getExtension() != 'csv') {
|
||||
continue;
|
||||
}
|
||||
$bank = 'unknown';
|
||||
$text = trim(file_get_contents($file->getRealPath()));
|
||||
if (str_contains($text, 'SCOTIABANK')) {
|
||||
$bank = 'Scotiabank';
|
||||
}
|
||||
if (str_contains($text, 'BICE')) {
|
||||
$bank = 'BICE';
|
||||
}
|
||||
$data = explode(PHP_EOL, $text);
|
||||
array_walk($data, function(&$item) {
|
||||
$item = trim($item, '; ');
|
||||
if (str_contains($item, ';') !== false) {
|
||||
$item = explode(';', $item);
|
||||
}
|
||||
});
|
||||
$output []= ['bank' => $bank, 'filename' => $file->getBasename(), 'data' => $data];
|
||||
}
|
||||
return $this->build($output);
|
||||
}
|
||||
protected function build(array $data): ?array {
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Service;
|
||||
|
||||
class DocumentHandler {
|
||||
protected array $handlers;
|
||||
public function __construct(array $handlers) {
|
||||
$this->handlers = $handlers;
|
||||
}
|
||||
public function handle(): array {
|
||||
$output = [];
|
||||
foreach ($this->handlers as $handler) {
|
||||
$output = array_merge($output, $handler->load());
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
}
|
60
api/common/Service/Documenter.php
Normal file
60
api/common/Service/Documenter.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
namespace Common\Service;
|
||||
|
||||
use function Safe\{json_encode, json_decode, file_get_contents, file_put_contents};
|
||||
use ProVM\Concept\API\Route\Route;
|
||||
use ProVM\Implement\API\Route\Route as RouteObj;
|
||||
|
||||
class Documenter
|
||||
{
|
||||
public function __construct(string $filename)
|
||||
{
|
||||
$this->setFilename($filename);
|
||||
}
|
||||
|
||||
protected string $filename;
|
||||
public function setFilename(string $filename): Documenter
|
||||
{
|
||||
$this->filename = $filename;
|
||||
return $this;
|
||||
}
|
||||
public function getFilename(): string
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
protected array $routes;
|
||||
public function setRoutes(array $routes): Documenter
|
||||
{
|
||||
foreach ($routes as $path => $route) {
|
||||
$this->addRoute($path, $route);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addRoute(string $path, Route $route): Documenter
|
||||
{
|
||||
$this->routes[$path] = $route;
|
||||
return $this;
|
||||
}
|
||||
public function getRoutes(): array
|
||||
{
|
||||
return $this->routes;
|
||||
}
|
||||
|
||||
protected function load(): mixed
|
||||
{
|
||||
$json = json_decode(trim(file_get_contents($this->getFilename())), JSON_OBJECT_AS_ARRAY);
|
||||
foreach ($json['paths'] as $path => $data) {
|
||||
$route = RouteObj::add($data);
|
||||
$this->addRoute($path, $route);
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
public function save(): void
|
||||
{
|
||||
$json = $this->load();
|
||||
$json['paths'] = $this->getRoutes();
|
||||
ksort($json['paths']);
|
||||
file_put_contents($this->getFilename(), json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Service;
|
||||
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Nyholm\Psr7\Stream;
|
||||
|
||||
class FileHandler {
|
||||
protected $base_folder;
|
||||
protected $valid_types;
|
||||
protected $folders;
|
||||
public function __construct(object $params) {
|
||||
$this->base_folder = $params->folder;
|
||||
$this->addValidTypes(array_keys($params->types));
|
||||
$this->addFolders($params->types);
|
||||
}
|
||||
public function addFolders(array $folders): FileHandler {
|
||||
foreach ($folders as $type => $folder) {
|
||||
$this->addFolder($type, $folder);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addFolder(string $type, string $folder): FileHandler {
|
||||
$this->folders[$type] = $folder;
|
||||
return $this;
|
||||
}
|
||||
public function addValidTypes(array $valid_types): FileHandler {
|
||||
foreach ($valid_types as $type) {
|
||||
$this->addValidType($type);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addValidType(string $type): FileHandler {
|
||||
$this->valid_types []= $type;
|
||||
return $this;
|
||||
}
|
||||
public function getType(string $folder): string {
|
||||
return array_search($folder, $this->folders);
|
||||
}
|
||||
|
||||
public function uploadFile(UploadedFileInterface $file, string $new_name = null): bool {
|
||||
if ($file->getError() !== UPLOAD_ERR_OK) {
|
||||
return false;
|
||||
}
|
||||
if (!in_array($file->getClientMediaType(), $this->valid_types)) {
|
||||
return false;
|
||||
}
|
||||
if ($new_name === null) {
|
||||
$new_name = $file->getClientFilename();
|
||||
}
|
||||
$filenfo = new \SplFileInfo($file->getClientFilename());
|
||||
if (!str_contains($new_name, $filenfo->getExtension())) {
|
||||
$new_name .= '.' . $filenfo->getExtension();
|
||||
}
|
||||
$to = implode(DIRECTORY_SEPARATOR, [$this->base_folder, $this->folders[$file->getClientMediaType()], $new_name]);
|
||||
$file->moveTo($to);
|
||||
return file_exists($to);
|
||||
}
|
||||
public function listFiles(): array {
|
||||
$output = [];
|
||||
foreach ($this->folders as $f) {
|
||||
$folder = implode(DIRECTORY_SEPARATOR, [$this->base_folder, $f]);
|
||||
if (!file_exists($folder)) {
|
||||
continue;
|
||||
}
|
||||
$files = new \DirectoryIterator($folder);
|
||||
foreach ($files as $file) {
|
||||
if ($file->isDir()) {
|
||||
continue;
|
||||
}
|
||||
$output []= (object) ['folder' => $f, 'filename' => $file->getBasename()];
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
protected function validateFilename(string $folder, string $filename): bool|string {
|
||||
if (!in_array($folder, $this->folders)) {
|
||||
return false;
|
||||
}
|
||||
$f = implode(DIRECTORY_SEPARATOR, [$this->base_folder, $folder, $filename]);
|
||||
if (!file_exists($f)) {
|
||||
return false;
|
||||
}
|
||||
return $f;
|
||||
}
|
||||
public function getInfo(string $folder, string $filename): \SplFileInfo|bool {
|
||||
if (!$f = $this->validateFilename($folder, $filename)) {
|
||||
return false;
|
||||
}
|
||||
return new \SplFileInfo($f);
|
||||
}
|
||||
public function getFile(string $folder, string $filename): StreamInterface|bool {
|
||||
if (!$f = $this->validateFilename($folder, $filename)) {
|
||||
return false;
|
||||
}
|
||||
return Stream::create(file_get_contents($f));
|
||||
}
|
||||
public function editFilename(string $folder, string $filename, string $new_name): bool {
|
||||
if (!$f = $this->validateFilename($folder, $filename)) {
|
||||
return false;
|
||||
}
|
||||
$info = new \SplFileInfo($f);
|
||||
$new = implode(DIRECTORY_SEPARATOR, [$this->base_folder, $folder, $new_name . '.' . $info->getExtension()]);
|
||||
return rename($f, $new);
|
||||
}
|
||||
public function deleteFile(string $folder, string $filename): bool {
|
||||
if (!$f = $this->validateFilename($folder, $filename)) {
|
||||
return false;
|
||||
}
|
||||
return unlink($f);
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Service;
|
||||
|
||||
use Contabilidad\Common\Concept\DocumentHandler;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class PdfHandler extends DocumentHandler {
|
||||
protected Client $client;
|
||||
protected string $url;
|
||||
public function __construct(Client $client, string $pdf_folder, string $url) {
|
||||
parent::__construct($pdf_folder);
|
||||
$this->client = $client;
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
public function load(): ?array {
|
||||
$folder = $this->folder;
|
||||
$files = new \DirectoryIterator($folder);
|
||||
$output = [];
|
||||
foreach ($files as $file) {
|
||||
if ($file->isDir() or $file->getExtension() != 'pdf') {
|
||||
continue;
|
||||
}
|
||||
$output []= ['filename' => $file->getBasename()];
|
||||
}
|
||||
$response = $this->client->post($this->url, ['json' => ['files' => $output]]);
|
||||
$output = json_decode($response->getBody());
|
||||
return $this->build($output);
|
||||
}
|
||||
protected function build(array $data): ?array {
|
||||
foreach ($data as &$file) {
|
||||
$i = $this->findStartRow($file->text);
|
||||
if ($i === -1) {
|
||||
continue;
|
||||
}
|
||||
$e = $this->findEndRow($file->text, $i);
|
||||
if ($e == $i) {
|
||||
continue;
|
||||
}
|
||||
$file->data = array_filter($file->text, function($key) use ($i, $e) {
|
||||
return ($key >= $i) and ($key <= $e);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
protected function findStartRow(array $data): int {
|
||||
foreach ($data as $i => $row) {
|
||||
if (!is_array($row)) {
|
||||
continue;
|
||||
}
|
||||
$maybe = false;
|
||||
foreach ($row as $cell) {
|
||||
if (str_contains($cell, '/')) {
|
||||
$maybe = true;
|
||||
}
|
||||
if ($maybe and str_contains($cell, '$')) {
|
||||
return $i - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
protected function findEndRow(array $data, int $start): int {
|
||||
$l = count($data[$start]);
|
||||
for ($i = $start; $i < count($data); $i ++) {
|
||||
if (!is_array($data[$i])) {
|
||||
return $i - 1;
|
||||
}
|
||||
if (count($data[$i]) != $l) {
|
||||
return $i - 1;
|
||||
}
|
||||
}
|
||||
return $start;
|
||||
}
|
||||
}
|
179
api/common/Service/Router.php
Normal file
179
api/common/Service/Router.php
Normal file
@ -0,0 +1,179 @@
|
||||
<?php
|
||||
namespace Common\Service;
|
||||
|
||||
use Slim\App;
|
||||
use ProVM\Concept\API\Controller;
|
||||
use ProVM\Implement\API\Route\Route;
|
||||
|
||||
class Router
|
||||
{
|
||||
public function __construct(App &$app, Documenter $documenter)
|
||||
{
|
||||
$this->setApp($app);
|
||||
$this->setDocumenter($documenter);
|
||||
}
|
||||
|
||||
protected App $app;
|
||||
public function setApp(App &$app): Router
|
||||
{
|
||||
$this->app = $app;
|
||||
return $this;
|
||||
}
|
||||
public function getApp(): App
|
||||
{
|
||||
return $this->app;
|
||||
}
|
||||
protected Documenter $documenter;
|
||||
public function setDocumenter(Documenter $documenter): Router
|
||||
{
|
||||
$this->documenter = $documenter;
|
||||
return $this;
|
||||
}
|
||||
public function getDocumenter(): Documenter
|
||||
{
|
||||
return $this->documenter;
|
||||
}
|
||||
protected Controller $controller;
|
||||
public function setController(Controller $controller): Router
|
||||
{
|
||||
$this->controller = $controller;
|
||||
return $this;
|
||||
}
|
||||
public function getController(): Controller
|
||||
{
|
||||
return $this->controller;
|
||||
}
|
||||
|
||||
protected function document(): void
|
||||
{
|
||||
$docs = [
|
||||
"/{$this->getController()->getPlural()}" => [
|
||||
'get' => [
|
||||
'description' => "Entrega una lista de {$this->getController()->getPlural()}",
|
||||
'responses' => [
|
||||
'200' => [
|
||||
'description' => "Lista de {$this->getController()->getPlural()}"
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"/{$this->getController()->getPlural()}/add" => [
|
||||
'post' => [
|
||||
'description' => "Agregar {$this->getController()->getPlural()} con una lista",
|
||||
'parameters' => [
|
||||
[
|
||||
'name' => $this->getController()->getPlural(),
|
||||
'in' => 'query',
|
||||
'description' => 'Lista de datos para agregar',
|
||||
'required' => true
|
||||
]
|
||||
],
|
||||
'responses' => [
|
||||
'200' => [
|
||||
'description' => "Entrega un listado de {$this->getController()->getPlural()} y si fueron agregadas"
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"/{$this->getController()->getPlural()}/edit" => [
|
||||
'put' => [
|
||||
'description' => "Editar multiples {$this->getController()->getPlural()} con una lista",
|
||||
'parameters' => [
|
||||
[
|
||||
'name' => $this->getController()->getPlural(),
|
||||
'in' => 'query',
|
||||
'description' => 'Lista de datos para editar',
|
||||
'required' => true
|
||||
]
|
||||
],
|
||||
'responses' => [
|
||||
'200' => [
|
||||
'description' => "Entrega un listado de {$this->getController()->getPlural()} identificando si fueron editados"
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"/{$this->getController()->getSingular()}/{model_id}" => [
|
||||
'get' => [
|
||||
'description' => "Entrega {$this->getController()->getSingular()}",
|
||||
'parameters' => [
|
||||
[
|
||||
'name' => 'id',
|
||||
'in' => 'path',
|
||||
'description' => "{$this->getController()->getSingular()} id",
|
||||
'required' => true
|
||||
]
|
||||
],
|
||||
'responses' => [
|
||||
'200' => [
|
||||
'description' => "{$this->getController()->getSingular()} found or null"
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"/{$this->getController()->getSingular()}/{model_id}/edit" => [
|
||||
'put' => [
|
||||
'description' => '',
|
||||
'parameters' => [
|
||||
[
|
||||
'name' => 'model_id',
|
||||
'in' => 'path',
|
||||
'description' => "{$this->getController()->getSingular()} id",
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'name' => "{$this->getController()->getSingular()}",
|
||||
'in' => 'query',
|
||||
'description' => '',
|
||||
'required' => true
|
||||
]
|
||||
],
|
||||
'responses' => [
|
||||
'200' => [
|
||||
'description' => ''
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"/{$this->getController()->getSingular()}/{model_id}/remove" => [
|
||||
'delete' => [
|
||||
'description' => '',
|
||||
'parameters' => [
|
||||
[
|
||||
'name' => 'model_id',
|
||||
'in' => 'path',
|
||||
'description' => "{$this->getController()->getSingular()} id",
|
||||
'required' => true
|
||||
]
|
||||
],
|
||||
'responses' => [
|
||||
'200' => [
|
||||
'description' => ''
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
foreach ($docs as $path => $r) {
|
||||
$route = Route::add($r);
|
||||
$this->getDocumenter()->addRoute($path, $route);
|
||||
}
|
||||
$this->getDocumenter()->save();
|
||||
}
|
||||
public function build(): void
|
||||
{
|
||||
$this->getApp()->group('/' . $this->getController()->getPlural(), function($app) {
|
||||
$app->post('/add[/]', [get_class($this->getController()), 'add']);
|
||||
$app->put('/edit[/]', [get_class($this->getController()), 'edit']);
|
||||
$app->get('[/]', get_class($this->getController()));
|
||||
});
|
||||
$this->getApp()->group('/' . $this->getController()->getSingular() . '/{model_id}', function($app) {
|
||||
$app->put('/edit[/]', [get_class($this->getController()), 'editOne']);
|
||||
$app->delete('/remove[/]', [get_class($this->getController()), 'remove']);
|
||||
$app->get('[/]', [get_class($this->getController()), 'get']);
|
||||
});
|
||||
|
||||
$this->document();
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Service;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\ServerException;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\Moneda;
|
||||
use Contabilidad\TipoCambio;
|
||||
|
||||
class TiposCambios {
|
||||
protected $client;
|
||||
protected $factory;
|
||||
protected $base_url;
|
||||
protected $key;
|
||||
public function __construct(Client $client, Factory $factory, $api_url, $api_key) {
|
||||
$this->client = $client;
|
||||
$this->factory = $factory;
|
||||
$this->base_url = $api_url;
|
||||
$this->key = $api_key;
|
||||
}
|
||||
protected function getWeekday(\DateTimeInterface $fecha) {
|
||||
if ($fecha->weekday() == 0) {
|
||||
return $fecha->subWeek()->weekday(5);
|
||||
}
|
||||
if ($fecha->weekday() == 6) {
|
||||
return $fecha->weekday(5);
|
||||
}
|
||||
return $fecha;
|
||||
}
|
||||
protected function getValor(\DateTimeInterface $fecha, string $moneda_codigo) {
|
||||
$data = [
|
||||
'fecha' => $fecha->format('Y-m-d'),
|
||||
'desde' => $moneda_codigo
|
||||
];
|
||||
$headers = [
|
||||
'Authorization' => "Bearer {$this->key}"
|
||||
];
|
||||
$url = implode('/', [
|
||||
$this->base_url,
|
||||
'cambio',
|
||||
'get'
|
||||
]);
|
||||
try {
|
||||
$response = $this->client->request('POST', $url, ['json' => $data, 'headers' => $headers]);
|
||||
} catch (ConnectException | RequestException | ServerException $e) {
|
||||
error_log($e);
|
||||
return null;
|
||||
}
|
||||
if ($response->getStatusCode() !== 200) {
|
||||
error_log('Could not connect to python API.');
|
||||
return null;
|
||||
}
|
||||
$result = json_decode($response->getBody());
|
||||
if (isset($result->message) and $result->message === 'Not Authorized') {
|
||||
error_log('Not authorized for connecting to python API.');
|
||||
return null;
|
||||
}
|
||||
return $result->serie[0]->valor;
|
||||
}
|
||||
public function get(string $fecha, int $moneda_id) {
|
||||
$fecha = Carbon::parse($fecha);
|
||||
$moneda = $this->factory->find(Moneda::class)->one($moneda_id);
|
||||
if ($moneda->codigo == 'USD') {
|
||||
$fecha = $this->getWeekday($fecha);
|
||||
}
|
||||
// If a value exists in the database
|
||||
$cambio = $moneda->cambio($fecha);
|
||||
if ($cambio !== null) {
|
||||
if ($cambio->desde()->id != $moneda->id) {
|
||||
return 1 / $cambio->valor;
|
||||
}
|
||||
return $cambio->valor;
|
||||
}
|
||||
$valor = $this->getValor($fecha, $moneda->codigo);
|
||||
if ($valor === null) {
|
||||
return 1;
|
||||
}
|
||||
$data = [
|
||||
'fecha' => $fecha->format('Y-m-d H:i:s'),
|
||||
'desde_id' => $moneda->id,
|
||||
'hasta_id' => 1,
|
||||
'valor' => $valor
|
||||
];
|
||||
$tipo = TipoCambio::add($this->factory, $data);
|
||||
if ($tipo !== false and $tipo->is_new()) {
|
||||
$tipo->save();
|
||||
}
|
||||
return $valor;
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Service;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
|
||||
use thiagoalessio\TesseractOCR\TesseractOCR;
|
||||
use Contabilidad\Common\Concept\DocumentHandler;
|
||||
|
||||
class XlsHandler extends DocumentHandler {
|
||||
public function load(): ?array {
|
||||
$folder = $this->folder;
|
||||
$files = new \DirectoryIterator($folder);
|
||||
$output = [];
|
||||
foreach ($files as $file) {
|
||||
if ($file->isDir() or $file->getExtension() != 'xls') {
|
||||
continue;
|
||||
}
|
||||
$reader = IOFactory::createReader(ucfirst($file->getExtension()));
|
||||
$xls = $reader->load($file->getRealPath());
|
||||
$data = [];
|
||||
$bank = 'unknown';
|
||||
for ($s = 0; $s < $xls->getSheetCount(); $s ++) {
|
||||
$sheet = $xls->getSheet($s);
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
$r = [];
|
||||
foreach ($row->getCellIterator() as $cell) {
|
||||
$r []= $cell->getValue();
|
||||
}
|
||||
$data []= $r;
|
||||
}
|
||||
foreach ($sheet->getDrawingCollection() as $drawing) {
|
||||
if ($drawing instanceof MemoryDrawing) {
|
||||
ob_start();
|
||||
call_user_func(
|
||||
$drawing->getRenderingFunction(),
|
||||
$drawing->getImageResource()
|
||||
);
|
||||
$imageContents = ob_get_contents();
|
||||
$size = ob_get_length();
|
||||
ob_end_clean();
|
||||
$ocr = new TesseractOCR();
|
||||
$ocr->imageData($imageContents, $size);
|
||||
$image = $ocr->run();
|
||||
if (str_contains($image, 'BICE')) {
|
||||
$bank = 'BICE';
|
||||
}
|
||||
if (str_contains($image, 'Scotiabank')) {
|
||||
$bank = 'Scotiabank';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$output []= ['bank' => $bank, 'filename' => $file->getBasename(), 'data' => $data];
|
||||
}
|
||||
return $this->build($output);
|
||||
}
|
||||
protected function build(array $data): ?array {
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -7,16 +7,12 @@
|
||||
"php-di/slim-bridge": "^3.1",
|
||||
"nyholm/psr7": "^1.4",
|
||||
"nyholm/psr7-server": "^1.0",
|
||||
"zeuxisoo/slim-whoops": "^0.7.3",
|
||||
"provm/controller": "^1.0",
|
||||
"provm/models": "^1.0.0-rc3",
|
||||
"nesbot/carbon": "^2.50",
|
||||
"robmorgan/phinx": "^0.12.9",
|
||||
"odan/phinx-migrations-generator": "^5.4",
|
||||
"martin-mikac/csv-to-phinx-seeder": "^1.6",
|
||||
"guzzlehttp/guzzle": "^7.4",
|
||||
"phpoffice/phpspreadsheet": "^1.19",
|
||||
"thiagoalessio/tesseract_ocr": "^2.12"
|
||||
"zeuxisoo/slim-whoops": "^0.7.3",
|
||||
"thecodingmachine/safe": "^2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5",
|
||||
@ -30,20 +26,12 @@
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Contabilidad\\Common\\": "common",
|
||||
"Contabilidad\\": "src"
|
||||
"Common\\": "common/",
|
||||
"Contabilidad\\": "src/",
|
||||
"ProVM\\": "ProVM/",
|
||||
"Psr\\": "Psr/"
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "http://git.provm.cl/ProVM/controller.git"
|
||||
},
|
||||
{
|
||||
"type": "git",
|
||||
"url": "http://git.provm.cl/ProVM/models.git"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"secure-http": false
|
||||
}
|
||||
|
14
api/db/migrations/20211029150354_tipo_categoria.php
Normal file
14
api/db/migrations/20211029150354_tipo_categoria.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class TipoCategoria extends AbstractMigration
|
||||
{
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('tipos_categorias')
|
||||
->addColumn('nombre', 'string')
|
||||
->create();
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class TipoCategoria extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('tipos_categoria')
|
||||
->addColumn('descripcion', 'string')
|
||||
->addColumn('activo', 'boolean')
|
||||
->create();
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ final class TipoEstadoConeccion extends AbstractMigration
|
||||
*/
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('tipos_estado_coneccion')
|
||||
$this->table('tipos_estados_conecciones')
|
||||
->addColumn('descripcion', 'string')
|
||||
->create();
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class TipoCuenta extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('tipos_cuenta')
|
||||
->addColumn('descripcion', 'string')
|
||||
->addColumn('color', 'string', ['length' => 6, 'default' => 'ffffff'])
|
||||
->create();
|
||||
}
|
||||
}
|
@ -21,7 +21,6 @@ final class Categoria extends AbstractMigration
|
||||
$this->table('categorias')
|
||||
->addColumn('nombre', 'string')
|
||||
->addColumn('tipo_id', 'integer')
|
||||
->addForeignKey('tipo_id', 'tipos_categoria', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->create();
|
||||
}
|
||||
}
|
||||
|
15
api/db/migrations/20211029152730_tipo_transaccion.php
Normal file
15
api/db/migrations/20211029152730_tipo_transaccion.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class TipoTransaccion extends AbstractMigration
|
||||
{
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('tipos_transacciones')
|
||||
->addColumn('nombre', 'string')
|
||||
->addColumn('color', 'string')
|
||||
->create();
|
||||
}
|
||||
}
|
@ -20,10 +20,6 @@ final class Cuenta extends AbstractMigration
|
||||
{
|
||||
$this->table('cuentas')
|
||||
->addColumn('nombre', 'string')
|
||||
->addColumn('categoria_id', 'integer')
|
||||
->addForeignKey('categoria_id', 'categorias', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addColumn('tipo_id', 'integer')
|
||||
->addForeignKey('tipo_id', 'tipos_cuenta', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->create();
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,10 @@ final class EstadoConeccion extends AbstractMigration
|
||||
*/
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('estados_coneccion')
|
||||
$this->table('estados_conecciones')
|
||||
->addColumn('coneccion_id', 'integer')
|
||||
->addForeignKey('coneccion_id', 'conecciones', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addColumn('fecha', 'date')
|
||||
->addColumn('tipo_id', 'integer')
|
||||
->addForeignKey('tipo_id', 'tipos_estado_coneccion', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->create();
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,12 @@ final class Transaccion extends AbstractMigration
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('transacciones')
|
||||
->addColumn('debito_id', 'integer')
|
||||
->addForeignKey('debito_id', 'cuentas', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addColumn('credito_id', 'integer')
|
||||
->addForeignKey('credito_id', 'cuentas', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addColumn('fecha', 'datetime')
|
||||
->addColumn('cuenta_id', 'integer')
|
||||
->addColumn('glosa', 'string')
|
||||
->addColumn('detalle', 'text')
|
||||
->addColumn('tipo_id', 'integer')
|
||||
->addColumn('valor', 'double')
|
||||
->addColumn('categoria_id', 'integer')
|
||||
->addColumn('fecha', 'datetime')
|
||||
->create();
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ final class CuentaMoneda extends AbstractMigration
|
||||
{
|
||||
$this->table('cuentas')
|
||||
->addColumn('moneda_id', 'integer')
|
||||
->addForeignKey('moneda_id', 'monedas', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->update();
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ final class TipoCambio extends AbstractMigration
|
||||
$this->table('tipos_cambio')
|
||||
->addColumn('fecha', 'datetime')
|
||||
->addColumn('desde_id', 'integer')
|
||||
->addForeignKey('desde_id', 'monedas', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addForeignKey('desde_id', 'monedas', ['id'], ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addColumn('hasta_id', 'integer')
|
||||
->addForeignKey('hasta_id', 'monedas', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addForeignKey('hasta_id', 'monedas', ['id'], ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addColumn('valor', 'double')
|
||||
->create();
|
||||
}
|
||||
|
14
api/db/migrations/20211329160000_categoria_foreign.php
Normal file
14
api/db/migrations/20211329160000_categoria_foreign.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class CategoriaForeign extends AbstractMigration
|
||||
{
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('categorias')
|
||||
->addForeignKey('tipo_id', 'tipos_categorias', ['id'], ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->update();
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class EstadoConeccionForeign extends AbstractMigration
|
||||
{
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('estados_conecciones')
|
||||
->addForeignKey('coneccion_id', 'conecciones', ['id'], ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addForeignKey('tipo_id', 'tipos_estados_conecciones', ['id'], ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->update();
|
||||
}
|
||||
}
|
16
api/db/migrations/20211329162000_transaccion_foreign.php
Normal file
16
api/db/migrations/20211329162000_transaccion_foreign.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class TransaccionForeign extends AbstractMigration
|
||||
{
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('transacciones')
|
||||
->addForeignKey('cuenta_id', 'cuentas', ['id'], ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addForeignKey('tipo_id', 'tipos_transacciones', ['id'], ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addForeignKey('categoria_id', 'categorias', ['id'], ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->update();
|
||||
}
|
||||
}
|
14
api/db/migrations/20211329163000_cuenta_moneda_foreign.php
Normal file
14
api/db/migrations/20211329163000_cuenta_moneda_foreign.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class CuentaMonedaForeign extends AbstractMigration
|
||||
{
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('cuentas')
|
||||
->addForeignKey('moneda_id', 'monedas', ['id'], ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->update();
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class Queue extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('queue')
|
||||
->addColumn('command', 'string')
|
||||
->addColumn('created', 'datetime')
|
||||
->addColumn('processed', 'boolean', ['default' => 0])
|
||||
->create();
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class QueueArguments extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('queue_arguments')
|
||||
->addColumn('queue_id', 'integer')
|
||||
->addForeignKey('queue_id', 'queue', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addColumn('argument', 'string', ['length' => 100])
|
||||
->addColumn('value', 'string')
|
||||
->create();
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class Consolidados extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change(): void
|
||||
{
|
||||
$this->table('consolidados')
|
||||
->addColumn('cuenta_id', 'integer')
|
||||
->addForeignKey('cuenta_id', 'cuentas', ['delete' => 'cascade', 'update' => 'cascade'])
|
||||
->addColumn('fecha', 'date')
|
||||
->addColumn('periodo', 'string', ['length' => 50])
|
||||
->addColumn('saldo', 'double')
|
||||
->create();
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
use Phinx\Seed\AbstractSeed;
|
||||
|
||||
class TipoCuenta extends AbstractSeed
|
||||
{
|
||||
/**
|
||||
* Run Method.
|
||||
*
|
||||
* Write your database seeder using this method.
|
||||
*
|
||||
* More information on writing seeders is available here:
|
||||
* https://book.cakephp.org/phinx/0/en/seeding.html
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$data = [
|
||||
[
|
||||
'descripcion' => 'Ganancia'
|
||||
],
|
||||
[
|
||||
'descripcion' => 'Activo'
|
||||
],
|
||||
[
|
||||
'descripcion' => 'Pasivo'
|
||||
],
|
||||
[
|
||||
'descripcion' => 'Perdida'
|
||||
]
|
||||
];
|
||||
$this->table('tipos_cuenta')
|
||||
->insert($data)
|
||||
->saveData();
|
||||
}
|
||||
}
|
@ -1,12 +1,8 @@
|
||||
<?php
|
||||
try {
|
||||
require_once implode(DIRECTORY_SEPARATOR, [
|
||||
dirname(__DIR__),
|
||||
'setup',
|
||||
'app.php'
|
||||
]);
|
||||
$app->run();
|
||||
} catch (Error | Exception $e) {
|
||||
error_log($e);
|
||||
throw $e;
|
||||
}
|
||||
ini_set('error_reporting', E_ALL & ~E_NOTICE & ~E_DEPRECATED);
|
||||
$app = require_once implode(DIRECTORY_SEPARATOR, [
|
||||
dirname(__DIR__),
|
||||
'setup',
|
||||
'app.php'
|
||||
]);
|
||||
$app->run();
|
||||
|
433
api/resources/documentation/base.json
Normal file
433
api/resources/documentation/base.json
Normal file
@ -0,0 +1,433 @@
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "Contabilidad",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/coneccion/{model_id}": {
|
||||
"get": {
|
||||
"description": "Entrega coneccion",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "coneccion id",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "coneccion found or null"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/coneccion/{model_id}/edit": {
|
||||
"put": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "model_id",
|
||||
"in": "path",
|
||||
"description": "coneccion id",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "coneccion",
|
||||
"in": "query",
|
||||
"description": "",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/coneccion/{model_id}/remove": {
|
||||
"delete": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "model_id",
|
||||
"in": "path",
|
||||
"description": "coneccion id",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/conecciones": {
|
||||
"get": {
|
||||
"description": "Entrega una lista de conecciones",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Lista de conecciones"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/conecciones/add": {
|
||||
"post": {
|
||||
"description": "Agregar conecciones con una lista",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "conecciones",
|
||||
"in": "query",
|
||||
"description": "Lista de datos para agregar",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Entrega un listado de conecciones y si fueron agregadas"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/conecciones/edit": {
|
||||
"put": {
|
||||
"description": "Editar multiples conecciones con una lista",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "conecciones",
|
||||
"in": "query",
|
||||
"description": "Lista de datos para editar",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Entrega un listado de conecciones identificando si fueron editados"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/cuenta/{model_id}": {
|
||||
"get": {
|
||||
"description": "Entrega cuenta",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "cuenta id",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "cuenta found or null"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/cuenta/{model_id}/edit": {
|
||||
"put": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "model_id",
|
||||
"in": "path",
|
||||
"description": "cuenta id",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "cuenta",
|
||||
"in": "query",
|
||||
"description": "",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/cuenta/{model_id}/remove": {
|
||||
"delete": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "model_id",
|
||||
"in": "path",
|
||||
"description": "cuenta id",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/cuentas": {
|
||||
"get": {
|
||||
"description": "Entrega una lista de cuentas",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Lista de cuentas"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/cuentas/add": {
|
||||
"post": {
|
||||
"description": "Agregar cuentas con una lista",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "cuentas",
|
||||
"in": "query",
|
||||
"description": "Lista de datos para agregar",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Entrega un listado de cuentas y si fueron agregadas"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/cuentas/edit": {
|
||||
"put": {
|
||||
"description": "Editar multiples cuentas con una lista",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "cuentas",
|
||||
"in": "query",
|
||||
"description": "Lista de datos para editar",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Entrega un listado de cuentas identificando si fueron editados"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/moneda/{model_id}": {
|
||||
"get": {
|
||||
"description": "Entrega moneda",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "moneda id",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "moneda found or null"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/moneda/{model_id}/edit": {
|
||||
"put": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "model_id",
|
||||
"in": "path",
|
||||
"description": "moneda id",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "moneda",
|
||||
"in": "query",
|
||||
"description": "",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/moneda/{model_id}/remove": {
|
||||
"delete": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "model_id",
|
||||
"in": "path",
|
||||
"description": "moneda id",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/monedas": {
|
||||
"get": {
|
||||
"description": "Entrega una lista de monedas",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Lista de monedas"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/monedas/add": {
|
||||
"post": {
|
||||
"description": "Agregar monedas con una lista",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "monedas",
|
||||
"in": "query",
|
||||
"description": "Lista de datos para agregar",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Entrega un listado de monedas y si fueron agregadas"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/monedas/edit": {
|
||||
"put": {
|
||||
"description": "Editar multiples monedas con una lista",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "monedas",
|
||||
"in": "query",
|
||||
"description": "Lista de datos para editar",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Entrega un listado de monedas identificando si fueron editados"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/transaccion/{model_id}": {
|
||||
"get": {
|
||||
"description": "Entrega transaccion",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"description": "transaccion id",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "transaccion found or null"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/transaccion/{model_id}/edit": {
|
||||
"put": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "model_id",
|
||||
"in": "path",
|
||||
"description": "transaccion id",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "transaccion",
|
||||
"in": "query",
|
||||
"description": "",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/transaccion/{model_id}/remove": {
|
||||
"delete": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "model_id",
|
||||
"in": "path",
|
||||
"description": "transaccion id",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/transacciones": {
|
||||
"get": {
|
||||
"description": "Entrega una lista de transacciones",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Lista de transacciones"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/transacciones/add": {
|
||||
"post": {
|
||||
"description": "Agregar transacciones con una lista",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "transacciones",
|
||||
"in": "query",
|
||||
"description": "Lista de datos para agregar",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Entrega un listado de transacciones y si fueron agregadas"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/transacciones/edit": {
|
||||
"put": {
|
||||
"description": "Editar multiples transacciones con una lista",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "transacciones",
|
||||
"in": "query",
|
||||
"description": "Lista de datos para editar",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Entrega un listado de transacciones identificando si fueron editados"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,4 @@
|
||||
<?php
|
||||
use Contabilidad\Common\Controller\Base;
|
||||
use Common\Controller\Base;
|
||||
|
||||
$app->get('/key/generate[/]', [Base::class, 'generate_key']);
|
||||
$app->get('/balance[/]', [Contabilidad\Common\Controller\TiposCategorias::class, 'balance']);
|
||||
$app->get('/info', [Base::class, 'info']);
|
||||
$app->get('/', Base::class);
|
||||
|
@ -1,13 +1,6 @@
|
||||
<?php
|
||||
use Contabilidad\Common\Controller\Categorias;
|
||||
use Common\Controller\Categorias;
|
||||
|
||||
$app->group('/categorias', function($app) {
|
||||
$app->post('/add[/]', [Categorias::class, 'add']);
|
||||
$app->get('[/]', Categorias::class);
|
||||
});
|
||||
$app->group('/categoria/{categoria_id}', function($app) {
|
||||
$app->get('/cuentas', [Categorias::class, 'cuentas']);
|
||||
$app->put('/edit', [Categorias::class, 'edit']);
|
||||
$app->delete('/delete', [Categorias::class, 'delete']);
|
||||
$app->get('[/]', [Categorias::class, 'show']);
|
||||
});
|
||||
$router = $app->getContainer()->get(\Common\Service\Router::class);
|
||||
$router->setController($app->getContainer()->get(Categorias::class));
|
||||
$router->build();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user