Compare commits
11 Commits
9f301e2175
...
9d2504f016
Author | SHA1 | Date | |
---|---|---|---|
9d2504f016 | |||
8ef4ab1c7d | |||
10b2485cfd | |||
0382f8c286 | |||
a3311f805e | |||
378de3ed86 | |||
69c2cffa6c | |||
61448a2521 | |||
b0f7c9b2b1 | |||
0c44554375 | |||
5ee267568a |
1
.api.env.sample
Normal file
1
.api.env.sample
Normal file
@ -0,0 +1 @@
|
|||||||
|
API_KEY=
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -13,3 +13,5 @@
|
|||||||
|
|
||||||
# Python
|
# Python
|
||||||
**/.idea/
|
**/.idea/
|
||||||
|
|
||||||
|
**/uploads/
|
||||||
|
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
|
</state>
|
||||||
|
</component>
|
81
.idea/contabilidad.iml
generated
Normal file
81
.idea/contabilidad.iml
generated
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/kint-php/kint" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/zeuxisoo/slim-whoops" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phar-io/version" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phar-io/manifest" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/theseer/tokenizer" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/webmozart/assert" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/philo/laravel-blade" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/nesbot/carbon" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/type" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/diff" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/illuminate/support" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/lines-of-code" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/illuminate/filesystem" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/object-enumerator" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/illuminate/events" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/comparator" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/illuminate/contracts" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/psr/simple-cache" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/code-unit" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/illuminate/view" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/psr/http-server-handler" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/doctrine/instantiator" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/exporter" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/illuminate/container" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/psr/http-factory" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/doctrine/inflector" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/cli-parser" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/psr/container" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/version" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/psr/http-message" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/complexity" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/psr/http-server-middleware" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/recursion-context" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/psr/log" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/resource-operations" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/global-state" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/composer" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/environment" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phpdocumentor/reflection-docblock" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/code-unit-reverse-lookup" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phpdocumentor/type-resolver" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/symfony/polyfill-mbstring" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/sebastian/object-reflector" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phpdocumentor/reflection-common" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/symfony/finder" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/symfony/deprecation-contracts" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/symfony/translation-contracts" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/filp/whoops" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/symfony/polyfill-ctype" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/symfony/debug" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/nyholm/psr7-server" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/symfony/translation" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/nyholm/psr7" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/symfony/polyfill-php80" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/nikic/php-parser" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/nikic/fast-route" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/php-di/php-di" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/php-di/phpdoc-reader" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/php-di/slim-bridge" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/php-di/invoker" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phpunit/php-code-coverage" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phpunit/phpunit" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phpunit/php-text-template" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phpunit/php-invoker" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phpunit/php-file-iterator" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phpunit/php-timer" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/myclabs/deep-copy" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/phpspec/prophecy" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/opis/closure" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/php-http/message-factory" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/rubellum/slim-blade-view" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/ui/vendor/slim/slim" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/contabilidad.iml" filepath="$PROJECT_DIR$/.idea/contabilidad.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
87
.idea/php.xml
generated
Normal file
87
.idea/php.xml
generated
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PhpIncludePathManager">
|
||||||
|
<include_path>
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/kint-php/kint" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/zeuxisoo/slim-whoops" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phar-io/version" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phar-io/manifest" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/theseer/tokenizer" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/webmozart/assert" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/philo/laravel-blade" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/nesbot/carbon" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/type" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/diff" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/illuminate/support" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/lines-of-code" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/illuminate/filesystem" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/object-enumerator" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/illuminate/events" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/comparator" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/illuminate/contracts" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/psr/simple-cache" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/code-unit" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/illuminate/view" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/psr/http-server-handler" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/doctrine/instantiator" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/exporter" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/illuminate/container" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/psr/http-factory" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/doctrine/inflector" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/cli-parser" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/psr/container" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/version" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/psr/http-message" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/complexity" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/psr/http-server-middleware" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/recursion-context" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/psr/log" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/resource-operations" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/global-state" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/composer" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/environment" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phpdocumentor/reflection-docblock" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/code-unit-reverse-lookup" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phpdocumentor/type-resolver" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/symfony/polyfill-mbstring" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/sebastian/object-reflector" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phpdocumentor/reflection-common" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/symfony/finder" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/symfony/deprecation-contracts" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/symfony/translation-contracts" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/filp/whoops" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/symfony/polyfill-ctype" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/symfony/debug" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/nyholm/psr7-server" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/symfony/translation" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/nyholm/psr7" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/symfony/polyfill-php80" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/nikic/php-parser" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/nikic/fast-route" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/php-di/php-di" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/php-di/phpdoc-reader" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/php-di/slim-bridge" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/php-di/invoker" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phpunit/php-code-coverage" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phpunit/phpunit" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phpunit/php-text-template" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phpunit/php-invoker" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phpunit/php-file-iterator" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phpunit/php-timer" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/myclabs/deep-copy" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/phpspec/prophecy" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/opis/closure" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/php-http/message-factory" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/rubellum/slim-blade-view" />
|
||||||
|
<path value="$PROJECT_DIR$/ui/vendor/slim/slim" />
|
||||||
|
</include_path>
|
||||||
|
</component>
|
||||||
|
<component name="PhpProjectSharedConfiguration" php_language_level="8.0">
|
||||||
|
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
||||||
|
</component>
|
||||||
|
<component name="PhpUnit">
|
||||||
|
<phpunit_settings>
|
||||||
|
<PhpUnitSettings custom_loader_path="$PROJECT_DIR$/ui/vendor/autoload.php" />
|
||||||
|
</phpunit_settings>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
1
.python.env.sample
Normal file
1
.python.env.sample
Normal file
@ -0,0 +1 @@
|
|||||||
|
PYTHON_KEY=
|
11
TODO.md
Normal file
11
TODO.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Contabilidad
|
||||||
|
|
||||||
|
1. Obtener pdf de cartolas desde email.
|
||||||
|
1. Conectar a Email por IMAP.
|
||||||
|
1. Buscar emails con cartolas.
|
||||||
|
1. Descargar cartolas.
|
||||||
|
1. Guardar de forma ordenada.
|
||||||
|
1. Extraer información e ingresar a base de datos a traves de API.
|
||||||
|
1. Abrir archivos y leer.
|
||||||
|
1. Formatear datos.
|
||||||
|
1. Mandar a API.
|
@ -1,5 +1,9 @@
|
|||||||
FROM php:8-fpm
|
FROM php:8-fpm
|
||||||
|
|
||||||
RUN docker-php-ext-install pdo pdo_mysql
|
RUN apt-get update -y && apt-get install -y git libzip-dev zip libpng-dev libfreetype6-dev libjpeg62-turbo-dev tesseract-ocr
|
||||||
|
|
||||||
|
RUN docker-php-ext-configure gd --with-freetype --with-jpeg && docker-php-ext-install pdo pdo_mysql zip gd
|
||||||
|
|
||||||
|
COPY --from=composer /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
6
api/common/Alias/DocumentHandler.php
Normal file
6
api/common/Alias/DocumentHandler.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad\Common\Alias;
|
||||||
|
|
||||||
|
interface DocumentHandler {
|
||||||
|
public function load(): ?array;
|
||||||
|
}
|
11
api/common/Concept/DocumentHandler.php
Normal file
11
api/common/Concept/DocumentHandler.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
@ -11,4 +11,17 @@ class Base {
|
|||||||
public function __invoke(Request $request, Response $response): Response {
|
public function __invoke(Request $request, Response $response): Response {
|
||||||
return $this->withJson($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.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$salt = mt_rand();
|
||||||
|
$signature = hash_hmac('sha256', $salt, 'contabilidad', true);
|
||||||
|
$key = urlencode(base64_encode($signature));
|
||||||
|
return $this->withJson($response, ['key' => $key]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,34 @@ use Psr\Http\Message\ServerRequestInterface as Request;
|
|||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use ProVM\Common\Define\Controller\Json;
|
use ProVM\Common\Define\Controller\Json;
|
||||||
use ProVM\Common\Factory\Model as Factory;
|
use ProVM\Common\Factory\Model as Factory;
|
||||||
|
use Contabilidad\Common\Service\TiposCambios as Service;
|
||||||
use Contabilidad\Categoria;
|
use Contabilidad\Categoria;
|
||||||
|
|
||||||
class Categorias {
|
class Categorias {
|
||||||
use Json;
|
use Json;
|
||||||
|
|
||||||
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
public function __invoke(Request $request, Response $response, Factory $factory, Service $service): Response {
|
||||||
$categorias = $factory->find(Categoria::class)->array();
|
$categorias = $factory->find(Categoria::class)->many();
|
||||||
|
array_walk($categorias, function(&$item) use ($service) {
|
||||||
|
$arr = $item->toArray();
|
||||||
|
$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;
|
||||||
|
});
|
||||||
if ($categorias) {
|
if ($categorias) {
|
||||||
usort($categorias, function($a, $b) {
|
usort($categorias, function($a, $b) {
|
||||||
return strcmp($a['nombre'], $b['nombre']);
|
return strcmp($a['nombre'], $b['nombre']);
|
||||||
@ -68,14 +89,14 @@ class Categorias {
|
|||||||
];
|
];
|
||||||
return $this->withJson($response, $output);
|
return $this->withJson($response, $output);
|
||||||
}
|
}
|
||||||
public function cuentas(Request $request, Response $response, Factory $factory, $categoria_id): Response {
|
public function cuentas(Request $request, Response $response, Factory $factory, Service $service, $categoria_id): Response {
|
||||||
$categoria = $factory->find(Categoria::class)->one($categoria_id);
|
$categoria = $factory->find(Categoria::class)->one($categoria_id);
|
||||||
$cuentas = null;
|
$cuentas = null;
|
||||||
if ($categoria !== null) {
|
if ($categoria !== null) {
|
||||||
$cuentas = $categoria->cuentas();
|
$cuentas = $categoria->cuentas();
|
||||||
if ($cuentas !== null) {
|
if ($cuentas !== null) {
|
||||||
array_walk($cuentas, function(&$item) {
|
array_walk($cuentas, function(&$item) use ($service) {
|
||||||
$item = $item->toArray();
|
$item = $item->toArray($service);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ use Psr\Http\Message\ServerRequestInterface as Request;
|
|||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use ProVM\Common\Define\Controller\Json;
|
use ProVM\Common\Define\Controller\Json;
|
||||||
use ProVM\Common\Factory\Model as Factory;
|
use ProVM\Common\Factory\Model as Factory;
|
||||||
|
use Contabilidad\Common\Service\TiposCambios as Service;
|
||||||
use Contabilidad\Cuenta;
|
use Contabilidad\Cuenta;
|
||||||
|
|
||||||
class Cuentas {
|
class Cuentas {
|
||||||
@ -14,11 +15,15 @@ class Cuentas {
|
|||||||
$cuentas = $factory->find(Cuenta::class)->array();
|
$cuentas = $factory->find(Cuenta::class)->array();
|
||||||
if ($cuentas) {
|
if ($cuentas) {
|
||||||
usort($cuentas, function($a, $b) {
|
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']);
|
$c = strcmp($a['categoria']['nombre'], $b['categoria']['nombre']);
|
||||||
if ($c == 0) {
|
if ($c != 0) {
|
||||||
return strcmp($a['nombre'], $b['nombre']);
|
return $c;
|
||||||
}
|
}
|
||||||
return $c;
|
return strcmp($a['nombre'], $b['nombre']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
$output = [
|
$output = [
|
||||||
@ -90,15 +95,28 @@ class Cuentas {
|
|||||||
];
|
];
|
||||||
return $this->withJson($response, $output);
|
return $this->withJson($response, $output);
|
||||||
}
|
}
|
||||||
public function transacciones(Request $request, Response $response, Factory $factory, $cuenta_id, $limit = null, $start = 0): Response {
|
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);
|
$cuenta = $factory->find(Cuenta::class)->one($cuenta_id);
|
||||||
$transacciones = null;
|
$transacciones = null;
|
||||||
if ($cuenta !== null) {
|
if ($cuenta !== null) {
|
||||||
$transacciones = $cuenta->transacciones($limit, $start);
|
$transacciones = $cuenta->transacciones($limit, $start);
|
||||||
if (count($transacciones)) {
|
if (count($transacciones) > 0) {
|
||||||
array_walk($transacciones, function(&$item) {
|
foreach ($transacciones as &$transaccion) {
|
||||||
$item = $item->toArray();
|
$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'] = $c->moneda()->cambiar($transaccion->fecha(), $transaccion->valor);
|
||||||
|
$arr['valorFormateado'] = $cuenta->moneda()->format($arr['valor']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$transaccion = $arr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$output = [
|
$output = [
|
||||||
|
21
api/common/Controller/Import.php
Normal file
21
api/common/Controller/Import.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?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\Common\Service\DocumentHandler as Handler;
|
||||||
|
|
||||||
|
class Import {
|
||||||
|
use Json;
|
||||||
|
|
||||||
|
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
||||||
|
$post = $request->getParsedBody();
|
||||||
|
return $this->withJson($response, $post);
|
||||||
|
}
|
||||||
|
public function uploads(Request $request, Response $response, Handler $handler): Response {
|
||||||
|
$output = $handler->handle();
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
|
}
|
71
api/common/Controller/Monedas.php
Normal file
71
api/common/Controller/Monedas.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?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\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);
|
||||||
|
}
|
||||||
|
}
|
95
api/common/Controller/TiposCambios.php
Normal file
95
api/common/Controller/TiposCambios.php
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?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);
|
||||||
|
}
|
||||||
|
}
|
139
api/common/Controller/TiposCategorias.php
Normal file
139
api/common/Controller/TiposCategorias.php
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<?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\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();
|
||||||
|
array_walk($tipos, function(&$item) use ($service) {
|
||||||
|
$arr = $item->toArray();
|
||||||
|
$arr['categorias'] = array_map(function($item) {
|
||||||
|
return $item->toArray();
|
||||||
|
}, $item->categorias());
|
||||||
|
$arr['saldo'] = abs($item->saldo($service));
|
||||||
|
$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;
|
||||||
|
});
|
||||||
|
if ($tipos) {
|
||||||
|
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);
|
||||||
|
$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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$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) {
|
||||||
|
$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);
|
||||||
|
}
|
||||||
|
}
|
71
api/common/Controller/TiposCuentas.php
Normal file
71
api/common/Controller/TiposCuentas.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?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);
|
||||||
|
}
|
||||||
|
}
|
29
api/common/Middleware/Auth.php
Normal file
29
api/common/Middleware/Auth.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?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 Psr\Http\Message\ResponseFactoryInterface as Factory;
|
||||||
|
use Contabilidad\Common\Service\Auth as Service;
|
||||||
|
|
||||||
|
class Auth {
|
||||||
|
protected Factory $factory;
|
||||||
|
protected Service $service;
|
||||||
|
public function __construct(Factory $factory, Service $service) {
|
||||||
|
$this->factory = $factory;
|
||||||
|
$this->service = $service;
|
||||||
|
}
|
||||||
|
public function __invoke(Request $request, Handler $handler): Response {
|
||||||
|
if ($request->getMethod() == 'OPTIONS') {
|
||||||
|
return $handler->handle($request);
|
||||||
|
}
|
||||||
|
if (!$this->service->isValid($request)) {
|
||||||
|
$response = $this->factory->createResponse(401);
|
||||||
|
$response->getBody()->write(json_encode(['message' => 'Invalid API KEY.']));
|
||||||
|
return $response
|
||||||
|
->withHeader('Content-Type', 'application/json');
|
||||||
|
}
|
||||||
|
return $handler->handle($request);
|
||||||
|
}
|
||||||
|
}
|
49
api/common/Service/Auth.php
Normal file
49
api/common/Service/Auth.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad\Common\Service;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
|
|
||||||
|
class Auth {
|
||||||
|
protected string $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;
|
||||||
|
}
|
||||||
|
if (isset($request->getParsedBody()['api_key'])) {
|
||||||
|
$sent_key = $request->getParsedBody()['api_key'];
|
||||||
|
return $this->key == $sent_key;
|
||||||
|
}
|
||||||
|
$post = $request->getParsedBody() ?? json_decode($request->getBody());
|
||||||
|
$sent_key = $this->getArrayKey($post);
|
||||||
|
if ($sent_key !== null) {
|
||||||
|
return $this->key == $sent_key;
|
||||||
|
}
|
||||||
|
$sent_key = $this->getArrayKey($request->getQueryParams());
|
||||||
|
return $this->key == $sent_key;
|
||||||
|
}
|
||||||
|
protected function getAuthKey($auth) {
|
||||||
|
if (is_array($auth)) {
|
||||||
|
$auth = $auth[0];
|
||||||
|
}
|
||||||
|
if (str_contains($auth, 'Bearer')) {
|
||||||
|
$auth = explode(' ', $auth)[1];
|
||||||
|
}
|
||||||
|
return $auth;
|
||||||
|
}
|
||||||
|
protected function getArrayKey($array) {
|
||||||
|
$posible_keys = [
|
||||||
|
'API_KEY',
|
||||||
|
'api_key',
|
||||||
|
];
|
||||||
|
foreach ($posible_keys as $key) {
|
||||||
|
if (isset($array[$key])) {
|
||||||
|
return $array[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
37
api/common/Service/CsvHandler.php
Normal file
37
api/common/Service/CsvHandler.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
16
api/common/Service/DocumentHandler.php
Normal file
16
api/common/Service/DocumentHandler.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
75
api/common/Service/PdfHandler.php
Normal file
75
api/common/Service/PdfHandler.php
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
76
api/common/Service/TiposCambios.php
Normal file
76
api/common/Service/TiposCambios.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad\Common\Service;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Exception\ConnectException;
|
||||||
|
use GuzzleHttp\Exception\RequestException;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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') {
|
||||||
|
if ($fecha->weekday() == 0) {
|
||||||
|
$fecha = $fecha->subWeek()->weekday(5);
|
||||||
|
}
|
||||||
|
if ($fecha->weekday() == 6) {
|
||||||
|
$fecha = $fecha->weekday(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cambio = $moneda->cambio($fecha);
|
||||||
|
if ($cambio) {
|
||||||
|
if ($cambio->desde()->id != $moneda->id) {
|
||||||
|
return 1 / $cambio->valor;
|
||||||
|
}
|
||||||
|
return $cambio->valor;
|
||||||
|
}
|
||||||
|
$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 $e) {
|
||||||
|
error_log($e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if ($response->getStatusCode() !== 200) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$result = json_decode($response->getBody());
|
||||||
|
$valor = $result->serie[0]->valor;
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
}
|
60
api/common/Service/XlsHandler.php
Normal file
60
api/common/Service/XlsHandler.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,13 @@
|
|||||||
"zeuxisoo/slim-whoops": "^0.7.3",
|
"zeuxisoo/slim-whoops": "^0.7.3",
|
||||||
"provm/controller": "^1.0",
|
"provm/controller": "^1.0",
|
||||||
"provm/models": "^1.0.0-rc3",
|
"provm/models": "^1.0.0-rc3",
|
||||||
"nesbot/carbon": "^2.50"
|
"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"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^9.5",
|
"phpunit/phpunit": "^9.5",
|
||||||
|
26
api/db/migrations/20211029150551_tipo_categoria.php
Normal file
26
api/db/migrations/20211029150551_tipo_categoria.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?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();
|
||||||
|
}
|
||||||
|
}
|
25
api/db/migrations/20211029150601_tipo_estado_coneccion.php
Normal file
25
api/db/migrations/20211029150601_tipo_estado_coneccion.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class TipoEstadoConeccion 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_estado_coneccion')
|
||||||
|
->addColumn('descripcion', 'string')
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
26
api/db/migrations/20211029150754_tipo_cuenta.php
Normal file
26
api/db/migrations/20211029150754_tipo_cuenta.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?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])
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
27
api/db/migrations/20211029152716_categoria.php
Normal file
27
api/db/migrations/20211029152716_categoria.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class Categoria 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('categorias')
|
||||||
|
->addColumn('nombre', 'string')
|
||||||
|
->addColumn('tipo_id', 'integer')
|
||||||
|
->addForeignKey('tipo_id', 'tipos_categoria')
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
25
api/db/migrations/20211029152729_coneccion.php
Normal file
25
api/db/migrations/20211029152729_coneccion.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class Coneccion 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('conecciones')
|
||||||
|
->addColumn('key', 'string')
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
29
api/db/migrations/20211029152732_cuenta.php
Normal file
29
api/db/migrations/20211029152732_cuenta.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class Cuenta 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('cuentas')
|
||||||
|
->addColumn('nombre', 'string')
|
||||||
|
->addColumn('categoria_id', 'integer')
|
||||||
|
->addForeignKey('categoria_id', 'categorias')
|
||||||
|
->addColumn('tipo_id', 'integer')
|
||||||
|
->addForeignKey('tipo_id', 'tipos_cuenta')
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
29
api/db/migrations/20211029152738_estado_coneccion.php
Normal file
29
api/db/migrations/20211029152738_estado_coneccion.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class EstadoConeccion 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('estados_coneccion')
|
||||||
|
->addColumn('coneccion_id', 'integer')
|
||||||
|
->addForeignKey('coneccion_id', 'conecciones')
|
||||||
|
->addColumn('fecha', 'date')
|
||||||
|
->addColumn('tipo_id', 'integer')
|
||||||
|
->addForeignKey('tipo_id', 'tipos_estado_coneccion')
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
32
api/db/migrations/20211029152752_transaccion.php
Normal file
32
api/db/migrations/20211029152752_transaccion.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class Transaccion 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('transacciones')
|
||||||
|
->addColumn('debito_id', 'integer')
|
||||||
|
->addForeignKey('debito_id', 'cuentas')
|
||||||
|
->addColumn('credito_id', 'integer')
|
||||||
|
->addForeignKey('credito_id', 'cuentas')
|
||||||
|
->addColumn('fecha', 'datetime')
|
||||||
|
->addColumn('glosa', 'string')
|
||||||
|
->addColumn('detalle', 'text')
|
||||||
|
->addColumn('valor', 'double')
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
29
api/db/migrations/20211204205950_moneda.php
Normal file
29
api/db/migrations/20211204205950_moneda.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class Moneda 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('monedas')
|
||||||
|
->addColumn('denominacion', 'string')
|
||||||
|
->addColumn('codigo', 'string', ['length' => 3])
|
||||||
|
->addColumn('prefijo', 'string', ['default' => ''])
|
||||||
|
->addColumn('sufijo', 'string', ['default' => ''])
|
||||||
|
->addColumn('decimales', 'integer', ['default' => 0])
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
26
api/db/migrations/20211204210207_cuenta_moneda.php
Normal file
26
api/db/migrations/20211204210207_cuenta_moneda.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class CuentaMoneda 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('cuentas')
|
||||||
|
->addColumn('moneda_id', 'integer')
|
||||||
|
->addForeignKey('moneda_id', 'monedas')
|
||||||
|
->update();
|
||||||
|
}
|
||||||
|
}
|
30
api/db/migrations/20211205002439_tipo_cambio.php
Normal file
30
api/db/migrations/20211205002439_tipo_cambio.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class TipoCambio 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_cambio')
|
||||||
|
->addColumn('fecha', 'datetime')
|
||||||
|
->addColumn('desde_id', 'integer')
|
||||||
|
->addForeignKey('desde_id', 'monedas')
|
||||||
|
->addColumn('hasta_id', 'integer')
|
||||||
|
->addForeignKey('hasta_id', 'monedas')
|
||||||
|
->addColumn('valor', 'double')
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
41
api/db/seeds/Moneda.php
Normal file
41
api/db/seeds/Moneda.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
use Phinx\Seed\AbstractSeed;
|
||||||
|
|
||||||
|
class Moneda 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 = [
|
||||||
|
[
|
||||||
|
'denominacion' => 'Pesos Chilenos',
|
||||||
|
'codigo' => 'CLP',
|
||||||
|
'prefijo' => '$ '
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'denominacion' => 'Dólar',
|
||||||
|
'codigo' => 'USD',
|
||||||
|
'prefijo' => 'US$ ',
|
||||||
|
'decimales' => 2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'denominacion' => 'Unidad de Fomento',
|
||||||
|
'codigo' => 'CLF',
|
||||||
|
'sufijo' => ' UF',
|
||||||
|
'decimales' => 2
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$this->table('monedas')
|
||||||
|
->insert($data)
|
||||||
|
->saveData();
|
||||||
|
}
|
||||||
|
}
|
36
api/db/seeds/TipoCuenta.php
Normal file
36
api/db/seeds/TipoCuenta.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?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();
|
||||||
|
}
|
||||||
|
}
|
30
api/db/seeds/TipoEstadoConeccion.php
Normal file
30
api/db/seeds/TipoEstadoConeccion.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
use Phinx\Seed\AbstractSeed;
|
||||||
|
|
||||||
|
class TipoEstadoConeccion 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' => 'Activa'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'descripcion' => 'Inactiva'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$this->table('tipos_estado_coneccion')
|
||||||
|
->insert($data)
|
||||||
|
->saveData();
|
||||||
|
}
|
||||||
|
}
|
41
api/phinx.php
Normal file
41
api/phinx.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return
|
||||||
|
[
|
||||||
|
'paths' => [
|
||||||
|
'migrations' => '%%PHINX_CONFIG_DIR%%/db/migrations',
|
||||||
|
'seeds' => '%%PHINX_CONFIG_DIR%%/db/seeds'
|
||||||
|
],
|
||||||
|
'environments' => [
|
||||||
|
'default_migration_table' => 'phinxlog',
|
||||||
|
'default_environment' => 'development',
|
||||||
|
'production' => [
|
||||||
|
'adapter' => 'mysql',
|
||||||
|
'host' => 'db',
|
||||||
|
'name' => $_ENV['MYSQL_DATABASE'],
|
||||||
|
'user' => $_ENV['MYSQL_USER'],
|
||||||
|
'pass' => $_ENV['MYSQL_PASSWORD'],
|
||||||
|
'port' => '3306',
|
||||||
|
'charset' => 'utf8',
|
||||||
|
],
|
||||||
|
'development' => [
|
||||||
|
'adapter' => 'mysql',
|
||||||
|
'host' => 'db',
|
||||||
|
'name' => $_ENV['MYSQL_DATABASE'],
|
||||||
|
'user' => $_ENV['MYSQL_USER'],
|
||||||
|
'pass' => $_ENV['MYSQL_PASSWORD'],
|
||||||
|
'port' => '3306',
|
||||||
|
'charset' => 'utf8',
|
||||||
|
],
|
||||||
|
'testing' => [
|
||||||
|
'adapter' => 'mysql',
|
||||||
|
'host' => 'db',
|
||||||
|
'name' => $_ENV['MYSQL_DATABASE'],
|
||||||
|
'user' => $_ENV['MYSQL_USER'],
|
||||||
|
'pass' => $_ENV['MYSQL_PASSWORD'],
|
||||||
|
'port' => '3306',
|
||||||
|
'charset' => 'utf8',
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'version_order' => 'creation'
|
||||||
|
];
|
2
api/php.ini
Normal file
2
api/php.ini
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
log_errors = true
|
||||||
|
error_log = /var/log/php/error.log
|
BIN
api/public/uploads/pdfs/BICE-CC-2021-09.pdf
Normal file
BIN
api/public/uploads/pdfs/BICE-CC-2021-09.pdf
Normal file
Binary file not shown.
BIN
api/public/uploads/pdfs/Scotiabank-CC-2021-10.pdf
Normal file
BIN
api/public/uploads/pdfs/Scotiabank-CC-2021-10.pdf
Normal file
Binary file not shown.
@ -1,4 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
use Contabilidad\Common\Controller\Base;
|
use Contabilidad\Common\Controller\Base;
|
||||||
|
|
||||||
|
$app->get('/key/generate[/]', [Base::class, 'generate_key']);
|
||||||
|
$app->get('/balance[/]', [Contabilidad\Common\Controller\TiposCategorias::class, 'balance']);
|
||||||
$app->get('/', Base::class);
|
$app->get('/', Base::class);
|
||||||
|
5
api/resources/routes/import.php
Normal file
5
api/resources/routes/import.php
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
use Contabilidad\Common\Controller\Import;
|
||||||
|
|
||||||
|
$app->post('/import', Import::class);
|
||||||
|
$app->get('/import/uploads', [Import::class, 'uploads']);
|
12
api/resources/routes/monedas.php
Normal file
12
api/resources/routes/monedas.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
use Contabilidad\Common\Controller\Monedas;
|
||||||
|
|
||||||
|
$app->group('/monedas', function($app) {
|
||||||
|
$app->post('/add[/]', [Monedas::class, 'add']);
|
||||||
|
$app->get('[/]', Monedas::class);
|
||||||
|
});
|
||||||
|
$app->group('/moneda/{moneda_id}', function($app) {
|
||||||
|
$app->put('/edit', [Monedas::class, 'edit']);
|
||||||
|
$app->delete('/delete', [Monedas::class, 'delete']);
|
||||||
|
$app->get('[/]', [Monedas::class, 'show']);
|
||||||
|
});
|
16
api/resources/routes/tipos.php
Normal file
16
api/resources/routes/tipos.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
$folder = implode(DIRECTORY_SEPARATOR, [
|
||||||
|
__DIR__,
|
||||||
|
'tipos'
|
||||||
|
]);
|
||||||
|
if (file_exists($folder)) {
|
||||||
|
$app->group('/tipos', function($app) use ($folder) {
|
||||||
|
$files = new DirectoryIterator($folder);
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if ($file->isDir() or $file->getExtension() != 'php') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
include_once $file->getRealPath();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
13
api/resources/routes/tipos/cambios.php
Normal file
13
api/resources/routes/tipos/cambios.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
use Contabilidad\Common\Controller\TiposCambios;
|
||||||
|
|
||||||
|
$app->group('/cambios', function($app) {
|
||||||
|
$app->post('/obtener[/]', [TiposCambios::class, 'obtain']);
|
||||||
|
$app->post('/add[/]', [TiposCambios::class, 'add']);
|
||||||
|
$app->get('[/]', TiposCambios::class);
|
||||||
|
});
|
||||||
|
$app->group('/cambio/{tipo_id}', function($app) {
|
||||||
|
$app->put('/edit[/]', [TiposCambios::class, 'edit']);
|
||||||
|
$app->delete('/delete[/]', [TiposCambios::class, 'delete']);
|
||||||
|
$app->get('[/]', [TiposCambios::class, 'show']);
|
||||||
|
});
|
13
api/resources/routes/tipos/categorias.php
Normal file
13
api/resources/routes/tipos/categorias.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
use Contabilidad\Common\Controller\TiposCategorias;
|
||||||
|
|
||||||
|
$app->group('/categorias', function($app) {
|
||||||
|
$app->post('/add[/]', [TiposCategorias::class, 'add']);
|
||||||
|
$app->get('[/]', TiposCategorias::class);
|
||||||
|
});
|
||||||
|
$app->group('/categoria/{tipo_id}', function($app) {
|
||||||
|
$app->get('/categorias', [TiposCategorias::class, 'categorias']);
|
||||||
|
$app->put('/edit', [TiposCategorias::class, 'edit']);
|
||||||
|
$app->delete('/delete', [TiposCategorias::class, 'delete']);
|
||||||
|
$app->get('[/]', [TiposCategorias::class, 'show']);
|
||||||
|
});
|
12
api/resources/routes/tipos/cuentas.php
Normal file
12
api/resources/routes/tipos/cuentas.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
use Contabilidad\Common\Controller\TiposCuentas;
|
||||||
|
|
||||||
|
$app->group('/cuentas', function($app) {
|
||||||
|
$app->post('/add[/]', [TiposCuentas::class, 'add']);
|
||||||
|
$app->get('[/]', TiposCuentas::class);
|
||||||
|
});
|
||||||
|
$app->group('/cuenta/{tipo_id}', function($app) {
|
||||||
|
$app->put('/edit', [TiposCuentas::class, 'edit']);
|
||||||
|
$app->delete('/delete', [TiposCuentas::class, 'delete']);
|
||||||
|
$app->get('[/]', [TiposCuentas::class, 'show']);
|
||||||
|
});
|
@ -31,7 +31,7 @@ $app->addRoutingMiddleware();
|
|||||||
$app->add(new WhoopsMiddleware());
|
$app->add(new WhoopsMiddleware());
|
||||||
|
|
||||||
|
|
||||||
$folder = 'middlewares';
|
$folder = implode(DIRECTORY_SEPARATOR, [__DIR__, 'middlewares']);
|
||||||
if (file_exists($folder)) {
|
if (file_exists($folder)) {
|
||||||
$files = new DirectoryIterator($folder);
|
$files = new DirectoryIterator($folder);
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
|
4
api/setup/middlewares/01_auth.php
Normal file
4
api/setup/middlewares/01_auth.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
use Contabilidad\Common\Middleware\Auth;
|
||||||
|
|
||||||
|
$app->add($app->getContainer()->get(Auth::class));
|
@ -1,4 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
return [
|
return [
|
||||||
'debug' => $_ENV['DEBUG'] ?? false
|
'debug' => $_ENV['DEBUG'] ?? false,
|
||||||
|
'api_key' => $_ENV['API_KEY'],
|
||||||
|
'python_api' => $_ENV['PYTHON_API'] ?? 'http://python:5000',
|
||||||
|
'python_key' => $_ENV['PYTHON_KEY']
|
||||||
];
|
];
|
||||||
|
@ -14,6 +14,32 @@ return [
|
|||||||
$arr['resources'],
|
$arr['resources'],
|
||||||
'routes'
|
'routes'
|
||||||
]);
|
]);
|
||||||
|
$arr['public'] = implode(DIRECTORY_SEPARATOR, [
|
||||||
|
$arr['base'],
|
||||||
|
'public'
|
||||||
|
]);
|
||||||
|
$arr['uploads'] = implode(DIRECTORY_SEPARATOR, [
|
||||||
|
$arr['public'],
|
||||||
|
'uploads'
|
||||||
|
]);
|
||||||
|
$arr['pdfs'] = implode(DIRECTORY_SEPARATOR, [
|
||||||
|
$arr['uploads'],
|
||||||
|
'pdfs'
|
||||||
|
]);
|
||||||
|
$arr['csvs'] = implode(DIRECTORY_SEPARATOR, [
|
||||||
|
$arr['uploads'],
|
||||||
|
'csvs'
|
||||||
|
]);
|
||||||
|
$arr['xlss'] = implode(DIRECTORY_SEPARATOR, [
|
||||||
|
$arr['uploads'],
|
||||||
|
'xlss'
|
||||||
|
]);
|
||||||
|
return (object) $arr;
|
||||||
|
},
|
||||||
|
'urls' => function(Container $c) {
|
||||||
|
$arr = [
|
||||||
|
'python' => 'http://python:5000'
|
||||||
|
];
|
||||||
return (object) $arr;
|
return (object) $arr;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
46
api/setup/setups/02_common.php
Normal file
46
api/setup/setups/02_common.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
use Psr\Container\ContainerInterface as Container;
|
||||||
|
|
||||||
|
return [
|
||||||
|
GuzzleHttp\Client::class => function(Container $c) {
|
||||||
|
return new GuzzleHttp\Client();
|
||||||
|
},
|
||||||
|
Contabilidad\Common\Service\Auth::class => function(Container $c) {
|
||||||
|
return new Contabilidad\Common\Service\Auth($c->get('api_key'));
|
||||||
|
},
|
||||||
|
Contabilidad\Common\Middleware\Auth::class => function(Container $c) {
|
||||||
|
return new Contabilidad\Common\Middleware\Auth(
|
||||||
|
$c->get(Nyholm\Psr7\Factory\Psr17Factory::class),
|
||||||
|
$c->get(Contabilidad\Common\Service\Auth::class)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
Contabilidad\Common\Service\PdfHandler::class => function(Container $c) {
|
||||||
|
return new Contabilidad\Common\Service\PdfHandler($c->get(GuzzleHttp\Client::class), $c->get('folders')->pdfs, implode('/', [
|
||||||
|
$c->get('urls')->python,
|
||||||
|
'pdf',
|
||||||
|
'parse'
|
||||||
|
]));
|
||||||
|
},
|
||||||
|
Contabilidad\Common\Service\CsvHandler::class => function(Container $c) {
|
||||||
|
return new Contabilidad\Common\Service\CsvHandler($c->get('folders')->csvs);
|
||||||
|
},
|
||||||
|
Contabilidad\Common\Service\XlsHandler::class => function(Container $c) {
|
||||||
|
return new Contabilidad\Common\Service\XlsHandler($c->get('folders')->xlss);
|
||||||
|
},
|
||||||
|
Contabilidad\Common\Service\DocumentHandler::class => function(Container $c) {
|
||||||
|
$handlers = [
|
||||||
|
$c->get(Contabilidad\Common\Service\XlsHandler::class),
|
||||||
|
$c->get(Contabilidad\Common\Service\CsvHandler::class),
|
||||||
|
$c->get(Contabilidad\Common\Service\PdfHandler::class)
|
||||||
|
];
|
||||||
|
return new Contabilidad\Common\Service\DocumentHandler($handlers);
|
||||||
|
},
|
||||||
|
Contabilidad\Common\Service\TiposCambios::class => function(Container $c) {
|
||||||
|
return new Contabilidad\Common\Service\TiposCambios(
|
||||||
|
$c->get(GuzzleHttp\Client::class),
|
||||||
|
$c->get(ProVM\Common\Factory\Model::class),
|
||||||
|
$c->get('python_api'),
|
||||||
|
$c->get('python_key')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
];
|
@ -1,15 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Contabilidad;
|
namespace Contabilidad;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use ProVM\Common\Alias\Model;
|
use ProVM\Common\Alias\Model;
|
||||||
|
use Contabilidad\Common\Service\TiposCambios as Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property string $nombre
|
* @property string $nombre
|
||||||
|
* @property TipoCategoria $tipo_id
|
||||||
*/
|
*/
|
||||||
class Categoria extends Model {
|
class Categoria extends Model {
|
||||||
public static $_table = 'categorias';
|
public static $_table = 'categorias';
|
||||||
protected static $fields = ['nombre'];
|
protected static $fields = ['nombre', 'tipo_id'];
|
||||||
|
|
||||||
protected $cuentas;
|
protected $cuentas;
|
||||||
public function cuentas() {
|
public function cuentas() {
|
||||||
@ -18,24 +21,72 @@ class Categoria extends Model {
|
|||||||
}
|
}
|
||||||
return $this->cuentas;
|
return $this->cuentas;
|
||||||
}
|
}
|
||||||
|
protected $tipo;
|
||||||
|
public function tipo() {
|
||||||
|
if ($this->tipo === null) {
|
||||||
|
$this->tipo = $this->childOf(TipoCategoria::class, [Model::SELF_KEY => 'tipo_id']);
|
||||||
|
}
|
||||||
|
return $this->tipo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCuentasOf($tipo) {
|
||||||
|
return $this->factory->find(Cuenta::class)
|
||||||
|
->select([['cuentas', '*']])
|
||||||
|
->join([
|
||||||
|
['tipos_cuenta', 'tipos_cuenta.id', 'cuentas.tipo_id']
|
||||||
|
])
|
||||||
|
->where([
|
||||||
|
['tipos_cuenta.descripcion', $tipo],
|
||||||
|
['cuentas.categoria_id', $this->id]
|
||||||
|
])
|
||||||
|
->many();
|
||||||
|
}
|
||||||
|
protected $activos;
|
||||||
|
public function activos() {
|
||||||
|
if ($this->activos === null) {
|
||||||
|
$this->activos = $this->getCuentasOf('Activo');
|
||||||
|
}
|
||||||
|
return $this->activos();
|
||||||
|
}
|
||||||
|
protected $pasivos;
|
||||||
|
public function pasivos() {
|
||||||
|
if ($this->pasivos === null) {
|
||||||
|
$this->activos = $this->getCuentasOf('Pasivo');
|
||||||
|
}
|
||||||
|
return $this->pasivos;
|
||||||
|
}
|
||||||
|
protected $ganancias;
|
||||||
|
public function ganancias() {
|
||||||
|
if ($this->ganancias === null) {
|
||||||
|
$this->ganancias = $this->getCuentasOf('Ganancia');
|
||||||
|
}
|
||||||
|
return $this->ganancias;
|
||||||
|
}
|
||||||
|
protected $perdidas;
|
||||||
|
public function perdidas() {
|
||||||
|
if ($this->perdidas === null) {
|
||||||
|
$this->perdidas = $this->getCuentasOf('Perdida');
|
||||||
|
}
|
||||||
|
return $this->perdidas;
|
||||||
|
}
|
||||||
|
|
||||||
protected $saldo;
|
protected $saldo;
|
||||||
public function saldo() {
|
public function saldo(Service $service = null) {
|
||||||
if ($this->saldo === null) {
|
if ($this->saldo === null) {
|
||||||
$this->saldo = 0;
|
$this->saldo = 0;
|
||||||
if ($this->cuentas() !== null) {
|
if ($this->cuentas() !== null) {
|
||||||
$this->saldo = array_reduce($this->cuentas(), function($sum, $item) {
|
$sum = 0;
|
||||||
return $sum + $item->saldo();
|
$debitos = ['Activo', 'Perdida'];
|
||||||
});
|
foreach ($this->cuentas() as $cuenta) {
|
||||||
|
if (array_search($cuenta->tipo()->descripcion, $debitos) !== false) {
|
||||||
|
$sum -= $cuenta->saldo($service, true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$sum += $cuenta->saldo($service, true);
|
||||||
|
}
|
||||||
|
$this->saldo = $sum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $this->saldo;
|
return $this->saldo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toArray(): array {
|
|
||||||
$arr = parent::toArray();
|
|
||||||
$arr['saldo'] = $this->saldo();
|
|
||||||
$arr['saldoFormateado'] = '$' . number_format($this->saldo(), 0, ',', '.');
|
|
||||||
return $arr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
21
api/src/Coneccion.php
Normal file
21
api/src/Coneccion.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad;
|
||||||
|
|
||||||
|
use ProVM\Common\Alias\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $key
|
||||||
|
*/
|
||||||
|
class Coneccion extends Model {
|
||||||
|
public static $_table = 'conecciones';
|
||||||
|
protected static $fields = ['key'];
|
||||||
|
|
||||||
|
protected $estados;
|
||||||
|
public function estados() {
|
||||||
|
if ($this->estados === null) {
|
||||||
|
$this->estados = $this->parentOf(TipoEstadoConeccion::class, [Model::CHILD_KEY => 'coneccion_id']);
|
||||||
|
}
|
||||||
|
return $this->estados;
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Contabilidad;
|
namespace Contabilidad;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use ProVM\Common\Alias\Model;
|
use ProVM\Common\Alias\Model;
|
||||||
|
use Contabilidad\Common\Service\TiposCambios as Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property string $nombre
|
* @property string $nombre
|
||||||
* @property Categoria $categoria_id
|
* @property Categoria $categoria_id
|
||||||
|
* @property TipoCuenta $tipo_id
|
||||||
|
* @property Moneda $moneda_id
|
||||||
*/
|
*/
|
||||||
class Cuenta extends Model {
|
class Cuenta extends Model {
|
||||||
public static $_table = 'cuentas';
|
public static $_table = 'cuentas';
|
||||||
protected static $fields = ['nombre', 'categoria_id'];
|
protected static $fields = ['nombre', 'categoria_id', 'tipo_id', 'moneda_id'];
|
||||||
|
|
||||||
protected $categoria;
|
protected $categoria;
|
||||||
public function categoria() {
|
public function categoria() {
|
||||||
@ -19,26 +23,32 @@ class Cuenta extends Model {
|
|||||||
}
|
}
|
||||||
return $this->categoria;
|
return $this->categoria;
|
||||||
}
|
}
|
||||||
|
protected $tipo;
|
||||||
protected $entradas;
|
public function tipo() {
|
||||||
public function entradas() {
|
if ($this->tipo === null) {
|
||||||
if ($this->entradas === null) {
|
$this->tipo = $this->childOf(TipoCuenta::class, [Model::SELF_KEY => 'tipo_id']);
|
||||||
$this->entradas = $this->parentOf(Entrada::class, [Model::CHILD_KEY => 'cuenta_id']);
|
|
||||||
}
|
}
|
||||||
return $this->entradas;
|
return $this->tipo;
|
||||||
|
}
|
||||||
|
protected $moneda;
|
||||||
|
public function moneda() {
|
||||||
|
if ($this->moneda === null) {
|
||||||
|
$this->moneda = $this->childOf(Moneda::class, [Model::SELF_KEY => 'moneda_id']);
|
||||||
|
}
|
||||||
|
return $this->moneda;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected $cargos;
|
protected $cargos;
|
||||||
public function cargos() {
|
public function cargos() {
|
||||||
if ($this->cargos === null) {
|
if ($this->cargos === null) {
|
||||||
$this->cargos = $this->parentOf(Transaccion::class, [Model::CHILD_KEY => 'hasta_id']);
|
$this->cargos = $this->parentOf(Transaccion::class, [Model::CHILD_KEY => 'credito_id']);
|
||||||
}
|
}
|
||||||
return $this->cargos;
|
return $this->cargos;
|
||||||
}
|
}
|
||||||
protected $abonos;
|
protected $abonos;
|
||||||
public function abonos() {
|
public function abonos() {
|
||||||
if ($this->abonos === null) {
|
if ($this->abonos === null) {
|
||||||
$this->abonos = $this->parentOf(Transaccion::class, [Model::CHILD_KEY => 'desde_id']);
|
$this->abonos = $this->parentOf(Transaccion::class, [Model::CHILD_KEY => 'debito_id']);
|
||||||
}
|
}
|
||||||
return $this->abonos;
|
return $this->abonos;
|
||||||
}
|
}
|
||||||
@ -46,7 +56,7 @@ class Cuenta extends Model {
|
|||||||
public function transacciones($limit = null, $start = 0) {
|
public function transacciones($limit = null, $start = 0) {
|
||||||
if ($this->transacciones === null) {
|
if ($this->transacciones === null) {
|
||||||
$transacciones = Model::factory(Transaccion::class)
|
$transacciones = Model::factory(Transaccion::class)
|
||||||
->join('cuentas', 'cuentas.id = transacciones.desde_id OR cuentas.id = transacciones.hasta_id')
|
->join('cuentas', 'cuentas.id = transacciones.debito_id OR cuentas.id = transacciones.credito_id')
|
||||||
->whereEqual('cuentas.id', $this->id)
|
->whereEqual('cuentas.id', $this->id)
|
||||||
->orderByAsc('transacciones.fecha');
|
->orderByAsc('transacciones.fecha');
|
||||||
if ($limit !== null) {
|
if ($limit !== null) {
|
||||||
@ -64,23 +74,40 @@ class Cuenta extends Model {
|
|||||||
return $this->transacciones;
|
return $this->transacciones;
|
||||||
}
|
}
|
||||||
protected $saldo;
|
protected $saldo;
|
||||||
public function saldo() {
|
public function saldo(Service $service = null, $in_clp = false) {
|
||||||
if ($this->saldo === null) {
|
if ($this->saldo === null) {
|
||||||
$this->saldo = 0;
|
$this->saldo = 0;
|
||||||
if (count($this->transacciones()) > 0) {
|
if (count($this->transacciones()) > 0) {
|
||||||
$this->saldo = array_reduce($this->transacciones(), function($sum, $item) {
|
$this->saldo = array_reduce($this->transacciones(), function($sum, $item) {
|
||||||
return $sum + $item->valor;
|
return $sum + $item->valor;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($in_clp and $this->moneda()->codigo !== 'CLP') {
|
||||||
|
$fecha = Carbon::today();
|
||||||
|
if ($this->moneda()->codigo == 'USD') {
|
||||||
|
$fecha = match ($fecha->weekday()) {
|
||||||
|
0 => $fecha->subWeek()->weekday(5),
|
||||||
|
6 => $fecha->weekday(5),
|
||||||
|
default => $fecha
|
||||||
|
};
|
||||||
|
}
|
||||||
|
$service->get($fecha->format('Y-m-d'), $this->moneda()->id);
|
||||||
|
return $this->moneda()->cambiar($fecha, $this->saldo);
|
||||||
|
}
|
||||||
return $this->saldo;
|
return $this->saldo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toArray(): array {
|
public function format($valor) {
|
||||||
|
return $this->moneda()->format($valor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toArray(Service $service = null, $in_clp = false): array {
|
||||||
$arr = parent::toArray();
|
$arr = parent::toArray();
|
||||||
$arr['categoria'] = $this->categoria()->toArray();
|
$arr['tipo'] = $this->tipo()->toArray();
|
||||||
$arr['saldo'] = $this->saldo();
|
$arr['moneda'] = $this->moneda()->toArray();
|
||||||
$arr['saldoFormateado'] = '$' . number_format($this->saldo(), 0, ',', '.');
|
$arr['saldo'] = $this->saldo($service, $in_clp);
|
||||||
|
$arr['saldoFormateado'] = $this->format($this->saldo($service, $in_clp));
|
||||||
return $arr;
|
return $arr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
30
api/src/EstadoConeccion.php
Normal file
30
api/src/EstadoConeccion.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad;
|
||||||
|
|
||||||
|
use ProVM\Common\Alias\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property Coneccion $coneccion_id
|
||||||
|
* @property DateTime $fecha
|
||||||
|
* @property TipoEstadoConeccion $tipo_id
|
||||||
|
*/
|
||||||
|
class EstadoConeccion extends Model {
|
||||||
|
public static $_table = 'estados_coneccion';
|
||||||
|
protected static $fields = ['coneccion_id', 'fecha', 'tipo_id'];
|
||||||
|
|
||||||
|
protected $coneccion;
|
||||||
|
public function coneccion() {
|
||||||
|
if ($this->coneccion === null) {
|
||||||
|
$this->coneccion = $this->childOf(Coneccion::class, [Model::SELF_KEY => 'coneccion_id']);
|
||||||
|
}
|
||||||
|
return $this->coneccion;
|
||||||
|
}
|
||||||
|
protected $tipo;
|
||||||
|
public function tipo() {
|
||||||
|
if ($this->tipo === null) {
|
||||||
|
$this->tipo = $this->childOf(TipoEstadoConeccion::class, [Model::SELF_KEY => 'tipo_id']);
|
||||||
|
}
|
||||||
|
return $this->tipo;
|
||||||
|
}
|
||||||
|
}
|
46
api/src/Moneda.php
Normal file
46
api/src/Moneda.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad;
|
||||||
|
|
||||||
|
use ProVM\Common\Alias\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $denominacion
|
||||||
|
* @property string $codigo
|
||||||
|
* @property string $sufijo
|
||||||
|
* @property string $prefijo
|
||||||
|
* @property int $decimales
|
||||||
|
*/
|
||||||
|
class Moneda extends Model {
|
||||||
|
public static $_table = 'monedas';
|
||||||
|
protected static $fields = ['denominacion', 'codigo'];
|
||||||
|
|
||||||
|
public function format($valor) {
|
||||||
|
return implode('', [
|
||||||
|
$this->prefijo,
|
||||||
|
number_format($valor, $this->decimales, ',', '.'),
|
||||||
|
$this->sufijo
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
public function cambio(\DateTime $fecha) {
|
||||||
|
$cambio = $this->factory->find(TipoCambio::class)
|
||||||
|
->where([['desde_id', $this->id], ['hasta_id', 1], ['fecha', $fecha->format('Y-m-d H:i:s')]])
|
||||||
|
->one();
|
||||||
|
if (!$cambio) {
|
||||||
|
$cambio = $this->factory->find(TipoCambio::class)
|
||||||
|
->where([['hasta_id', $this->id], ['desde_id', 1], ['fecha', $fecha->format('Y-m-d H:i:s')]])
|
||||||
|
->one();
|
||||||
|
}
|
||||||
|
return $cambio;
|
||||||
|
}
|
||||||
|
public function cambiar(\DateTime $fecha, float $valor) {
|
||||||
|
$cambio = $this->cambio($fecha);
|
||||||
|
if (!$cambio) {
|
||||||
|
return $valor;
|
||||||
|
}
|
||||||
|
if ($cambio->desde()->id != $this->id) {
|
||||||
|
return $cambio->transform($valor, TipoCambio::DESDE);
|
||||||
|
}
|
||||||
|
return $cambio->transform($valor);
|
||||||
|
}
|
||||||
|
}
|
50
api/src/TipoCambio.php
Normal file
50
api/src/TipoCambio.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use DateTime;
|
||||||
|
use ProVM\Common\Alias\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property DateTime $fecha
|
||||||
|
* @property Moneda $desde_id
|
||||||
|
* @property Moneda $hasta_id
|
||||||
|
* @property float $valor
|
||||||
|
*/
|
||||||
|
class TipoCambio extends Model {
|
||||||
|
const DESDE = -1;
|
||||||
|
const HASTA = 1;
|
||||||
|
|
||||||
|
public static $_table = 'tipos_cambio';
|
||||||
|
protected static $fields = ['fecha', 'valor', 'desde_id', 'hasta_id'];
|
||||||
|
|
||||||
|
protected $desde;
|
||||||
|
public function desde() {
|
||||||
|
if ($this->desde === null) {
|
||||||
|
$this->desde = $this->childOf(Moneda::class, [Model::SELF_KEY => 'desde_id']);
|
||||||
|
}
|
||||||
|
return $this->desde;
|
||||||
|
}
|
||||||
|
protected $hasta;
|
||||||
|
public function hasta() {
|
||||||
|
if ($this->hasta === null) {
|
||||||
|
$this->hasta = $this->childOf(Moneda::class, [Model::SELF_KEY => 'hasta_id']);
|
||||||
|
}
|
||||||
|
return $this->hasta;
|
||||||
|
}
|
||||||
|
public function fecha(DateTime $fecha = null) {
|
||||||
|
if ($fecha === null) {
|
||||||
|
return Carbon::parse($this->fecha);
|
||||||
|
}
|
||||||
|
$this->fecha = $fecha->format('Y-m-d H:i:s');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function transform(float $valor, int $direction = TipoCambio::HASTA): float {
|
||||||
|
if ($direction == TipoCambio::HASTA) {
|
||||||
|
return $valor * $this->valor;
|
||||||
|
}
|
||||||
|
return $valor / $this->valor;
|
||||||
|
}
|
||||||
|
}
|
46
api/src/TipoCategoria.php
Normal file
46
api/src/TipoCategoria.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad;
|
||||||
|
|
||||||
|
use ProVM\Common\Alias\Model;
|
||||||
|
use Contabilidad\Common\Service\TiposCambios as Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $descripcion
|
||||||
|
* @property int $activo
|
||||||
|
*/
|
||||||
|
class TipoCategoria extends Model {
|
||||||
|
public static $_table = 'tipos_categoria';
|
||||||
|
protected static $fields = ['descripcion', 'activo'];
|
||||||
|
|
||||||
|
protected $categorias;
|
||||||
|
public function categorias() {
|
||||||
|
if ($this->categorias === null) {
|
||||||
|
$this->categorias = $this->parentOf(Categoria::class, [Model::CHILD_KEY => 'tipo_id']);
|
||||||
|
}
|
||||||
|
return $this->categorias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCuentasOf($tipo) {
|
||||||
|
return $this->factory->find(Cuenta::class)
|
||||||
|
->select([['cuentas', '*']])
|
||||||
|
->join([
|
||||||
|
['tipos_cuenta', 'tipos_cuenta.id', 'cuentas.tipo_id'],
|
||||||
|
['categorias', 'categorias.id', 'cuentas.categoria_id']
|
||||||
|
])
|
||||||
|
->where([
|
||||||
|
['tipos_cuenta.descripcion', $tipo],
|
||||||
|
['categorias.tipo_id', $this->id]
|
||||||
|
])->many();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $saldo;
|
||||||
|
public function saldo(Service $service = null) {
|
||||||
|
if ($this->saldo === null) {
|
||||||
|
$this->saldo = array_reduce($this->categorias(), function($sum, $item) use ($service) {
|
||||||
|
return $sum + $item->saldo($service);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return $this->saldo;
|
||||||
|
}
|
||||||
|
}
|
14
api/src/TipoCuenta.php
Normal file
14
api/src/TipoCuenta.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad;
|
||||||
|
|
||||||
|
use ProVM\Common\Alias\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $descripcion
|
||||||
|
* @property string $color
|
||||||
|
*/
|
||||||
|
class TipoCuenta extends Model {
|
||||||
|
public static $_table = 'tipos_cuenta';
|
||||||
|
protected static $fields = ['descripcion', 'color'];
|
||||||
|
}
|
13
api/src/TipoEstadoConeccion.php
Normal file
13
api/src/TipoEstadoConeccion.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad;
|
||||||
|
|
||||||
|
use ProVM\Common\Alias\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $descripcion
|
||||||
|
*/
|
||||||
|
class TipoEstadoConeccion extends Model {
|
||||||
|
public static $_table = 'tipos_estado_coneccion';
|
||||||
|
protected static $fields = ['descripcion'];
|
||||||
|
}
|
@ -1,37 +1,38 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Contabilidad;
|
namespace Contabilidad;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use ProVM\Common\Alias\Model;
|
use ProVM\Common\Alias\Model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property Cuenta $desde_id
|
* @property Cuenta $debito_id
|
||||||
* @property Cuenta $hasta_id
|
* @property Cuenta $credito_id
|
||||||
* @property \DateTime $fecha
|
* @property DateTime $fecha
|
||||||
* @property string $glosa
|
* @property string $glosa
|
||||||
* @property string $detalle
|
* @property string $detalle
|
||||||
* @property double $valor
|
* @property double $valor
|
||||||
*/
|
*/
|
||||||
class Transaccion extends Model {
|
class Transaccion extends Model {
|
||||||
public static $_table = 'transacciones';
|
public static $_table = 'transacciones';
|
||||||
protected static $fields = ['desde_id', 'hasta_id', 'fecha', 'glosa', 'detalle', 'valor'];
|
protected static $fields = ['debito_id', 'credito_id', 'fecha', 'glosa', 'detalle', 'valor'];
|
||||||
|
|
||||||
protected $desde;
|
protected $debito;
|
||||||
public function desde() {
|
public function debito() {
|
||||||
if ($this->desde === null) {
|
if ($this->debito === null) {
|
||||||
$this->desde = $this->childOf(Cuenta::class, [Model::SELF_KEY => 'desde_id']);
|
$this->debito = $this->childOf(Cuenta::class, [Model::SELF_KEY => 'debito_id']);
|
||||||
}
|
}
|
||||||
return $this->desde;
|
return $this->debito;
|
||||||
}
|
}
|
||||||
protected $hasta;
|
protected $credito;
|
||||||
public function hasta() {
|
public function credito() {
|
||||||
if ($this->hasta === null) {
|
if ($this->credito === null) {
|
||||||
$this->hasta = $this->childOf(Cuenta::class, [Model::SELF_KEY => 'hasta_id']);
|
$this->credito = $this->childOf(Cuenta::class, [Model::SELF_KEY => 'credito_id']);
|
||||||
}
|
}
|
||||||
return $this->hasta;
|
return $this->credito;
|
||||||
}
|
}
|
||||||
public function fecha(\DateTime $fecha = null) {
|
public function fecha(DateTime $fecha = null) {
|
||||||
if ($fecha === null) {
|
if ($fecha === null) {
|
||||||
return Carbon::parse($this->fecha);
|
return Carbon::parse($this->fecha);
|
||||||
}
|
}
|
||||||
@ -40,10 +41,10 @@ class Transaccion extends Model {
|
|||||||
|
|
||||||
public function toArray(): array {
|
public function toArray(): array {
|
||||||
$arr = parent::toArray();
|
$arr = parent::toArray();
|
||||||
$arr['desde'] = $this->desde()->toArray();
|
$arr['debito'] = $this->debito()->toArray();
|
||||||
$arr['hasta'] = $this->hasta()->toArray();
|
$arr['credito'] = $this->credito()->toArray();
|
||||||
$arr['fechaFormateada'] = $this->fecha()->format('d-m-Y');
|
$arr['fechaFormateada'] = $this->fecha()->format('d-m-Y');
|
||||||
$arr['valorFormateado'] = '$' . number_format($this->valor, 0, ',', '.');
|
$arr['valorFormateado'] = $this->debito()->moneda()->format($this->valor);
|
||||||
return $arr;
|
return $arr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,44 +2,87 @@ version: '3'
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
api:
|
api:
|
||||||
|
profiles:
|
||||||
|
- api
|
||||||
|
restart: unless-stopped
|
||||||
image: php
|
image: php
|
||||||
build:
|
build:
|
||||||
context: api
|
context: api
|
||||||
env_file: .env
|
env_file:
|
||||||
|
- .env
|
||||||
|
- .api.env
|
||||||
|
- .python.env
|
||||||
volumes:
|
volumes:
|
||||||
- ./api/:/app/
|
- ./api/:/app/
|
||||||
|
- ./api/php.ini:/usr/local/etc/php/conf.d/php.ini
|
||||||
|
- ./logs/api/php/:/var/log/php/
|
||||||
api-proxy:
|
api-proxy:
|
||||||
|
profiles:
|
||||||
|
- api
|
||||||
|
restart: unless-stopped
|
||||||
image: nginx
|
image: nginx
|
||||||
ports:
|
ports:
|
||||||
- 9001:80
|
- "9001:80"
|
||||||
volumes:
|
volumes:
|
||||||
- ./api/nginx.conf:/etc/nginx/conf.d/default.conf
|
- ./api/nginx.conf:/etc/nginx/conf.d/default.conf
|
||||||
- ./logs/api/:/var/log/nginx/
|
- ./logs/api/:/var/log/nginx/
|
||||||
- ./api/:/app/
|
- ./api/:/app/
|
||||||
db:
|
db:
|
||||||
|
profiles:
|
||||||
|
- api
|
||||||
|
restart: unless-stopped
|
||||||
image: mariadb
|
image: mariadb
|
||||||
env_file: .env
|
env_file: .env
|
||||||
volumes:
|
volumes:
|
||||||
- contabilidad_data:/var/lib/mysql
|
- contabilidad_data:/var/lib/mysql
|
||||||
adminer:
|
adminer:
|
||||||
|
profiles:
|
||||||
|
- api
|
||||||
|
restart: unless-stopped
|
||||||
image: adminer
|
image: adminer
|
||||||
ports:
|
ports:
|
||||||
- 9002:8080
|
- "9002:8080"
|
||||||
|
|
||||||
ui:
|
ui:
|
||||||
|
profiles:
|
||||||
|
- ui
|
||||||
|
restart: unless-stopped
|
||||||
image: php-ui
|
image: php-ui
|
||||||
|
env_file:
|
||||||
|
- .api.env
|
||||||
build:
|
build:
|
||||||
context: ui
|
context: ui
|
||||||
volumes:
|
volumes:
|
||||||
- ./ui/:/app/
|
- ./ui/:/app/
|
||||||
|
- ./ui/php.ini:/usr/local/etc/php/conf.d/php.ini
|
||||||
|
- ./logs/ui/php/:/var/log/php/
|
||||||
ui-proxy:
|
ui-proxy:
|
||||||
|
profiles:
|
||||||
|
- ui
|
||||||
|
restart: unless-stopped
|
||||||
image: nginx
|
image: nginx
|
||||||
ports:
|
ports:
|
||||||
- 9000:80
|
- "9000:80"
|
||||||
volumes:
|
volumes:
|
||||||
- ./ui/nginx.conf:/etc/nginx/conf.d/default.conf
|
- ./ui/nginx.conf:/etc/nginx/conf.d/default.conf
|
||||||
- ./logs/ui/:/var/log/nginx/
|
- ./logs/ui/:/var/log/nginx/
|
||||||
- ./ui/:/app/
|
- ./ui/:/app/
|
||||||
|
|
||||||
|
python:
|
||||||
|
profiles:
|
||||||
|
- python
|
||||||
|
restart: unless-stopped
|
||||||
|
build:
|
||||||
|
context: ./python
|
||||||
|
env_file:
|
||||||
|
- .python.env
|
||||||
|
ports:
|
||||||
|
- "9003:5000"
|
||||||
|
volumes:
|
||||||
|
- ./python/src/:/app/src/
|
||||||
|
- ./python/config/:/app/config/
|
||||||
|
- ./api/public/uploads/pdfs/:/app/data/
|
||||||
|
- ./logs/python/:/var/log/python/
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
contabilidad_data:
|
contabilidad_data:
|
||||||
|
1
python/.gitignore
vendored
Normal file
1
python/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
**/__pycache__/
|
3
python/.idea/.gitignore
generated
vendored
Normal file
3
python/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
6
python/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
python/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
7
python/.idea/misc.xml
generated
Normal file
7
python/.idea/misc.xml
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (contabilidad)" project-jdk-type="Python SDK" />
|
||||||
|
<component name="PyCharmProfessionalAdvertiser">
|
||||||
|
<option name="shown" value="true" />
|
||||||
|
</component>
|
||||||
|
</project>
|
8
python/.idea/modules.xml
generated
Normal file
8
python/.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/python.iml" filepath="$PROJECT_DIR$/.idea/python.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
8
python/.idea/python.iml
generated
Normal file
8
python/.idea/python.iml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.9 (contabilidad)" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
6
python/.idea/vcs.xml
generated
Normal file
6
python/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
15
python/Dockerfile
Normal file
15
python/Dockerfile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
FROM python
|
||||||
|
|
||||||
|
RUN apt-get update -y && apt-get install -y ghostscript python3-tk libgl-dev
|
||||||
|
|
||||||
|
RUN pip install flask pyyaml pypdf4 gunicorn camelot-py[cv] pikepdf
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY ./src/ /app/src/
|
||||||
|
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
WORKDIR /app/src
|
||||||
|
|
||||||
|
CMD ["gunicorn", "-b 0.0.0.0:5000", "app:app"]
|
3
python/config/.passwords.yml
Normal file
3
python/config/.passwords.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
passwords:
|
||||||
|
- 0839
|
||||||
|
- 159608395
|
BIN
python/data/BICE-CC-2021-09.pdf
Normal file
BIN
python/data/BICE-CC-2021-09.pdf
Normal file
Binary file not shown.
BIN
python/data/Scotiabank-CC-2021-10.pdf
Normal file
BIN
python/data/Scotiabank-CC-2021-10.pdf
Normal file
Binary file not shown.
3
python/src/.idea/.gitignore
generated
vendored
Normal file
3
python/src/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
12
python/src/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
12
python/src/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="ignoredIdentifiers">
|
||||||
|
<list>
|
||||||
|
<option value="property.tolist" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
6
python/src/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
python/src/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
4
python/src/.idea/misc.xml
generated
Normal file
4
python/src/.idea/misc.xml
generated
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (python)" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
8
python/src/.idea/modules.xml
generated
Normal file
8
python/src/.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/src.iml" filepath="$PROJECT_DIR$/.idea/src.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
8
python/src/.idea/src.iml
generated
Normal file
8
python/src/.idea/src.iml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.9 (python)" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
6
python/src/.idea/vcs.xml
generated
Normal file
6
python/src/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
56
python/src/app.py
Normal file
56
python/src/app.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import io
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from flask import Flask, request
|
||||||
|
|
||||||
|
import contabilidad.pdf as pdf
|
||||||
|
import contabilidad.passwords as passwords
|
||||||
|
import contabilidad.log as log
|
||||||
|
import contabilidad.text_handler as th
|
||||||
|
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
log.logging['filename'] = '/var/log/python/contabilidad.log'
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/pdf/parse', methods=['POST'])
|
||||||
|
def pdf_parse():
|
||||||
|
data = request.get_json()
|
||||||
|
if not isinstance(data['files'], list):
|
||||||
|
data['files'] = [data['files']]
|
||||||
|
password_file = '/app/config/.passwords.yml'
|
||||||
|
pwds = passwords.get_passwords(password_file)
|
||||||
|
output = []
|
||||||
|
for file in data['files']:
|
||||||
|
filename = os.path.realpath(os.path.join('/app/data', file['filename']))
|
||||||
|
t = file['filename'].split('.')
|
||||||
|
temp = os.path.realpath(os.path.join('/app/data', t[0] + '-temp.pdf'))
|
||||||
|
for p in pwds:
|
||||||
|
if not pdf.check_password(filename, p):
|
||||||
|
continue
|
||||||
|
pdf.remove_encryption(filename, p, temp)
|
||||||
|
obj = pdf.get_data(temp)
|
||||||
|
outputs = []
|
||||||
|
for o in obj:
|
||||||
|
out = json.loads(o.df.to_json(orient='records'))
|
||||||
|
if out[0]['0'] == 'FECHA':
|
||||||
|
for i, line in enumerate(out):
|
||||||
|
if 'FECHA' in line['0'] or 'ACTUALICE' in line['0']:
|
||||||
|
continue
|
||||||
|
if line['0'] == '':
|
||||||
|
spl = line['1'].split(' ')
|
||||||
|
else:
|
||||||
|
spl = line['0'].split(' ')
|
||||||
|
line['0'] = ' '.join(spl[:3])
|
||||||
|
line['1'] = ' '.join(spl[3:])
|
||||||
|
out[i] = line
|
||||||
|
outputs.append(out)
|
||||||
|
os.remove(temp)
|
||||||
|
output.append({'filename': file['filename'], 'text': outputs})
|
||||||
|
return json.dumps(output)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', debug=True)
|
BIN
python/src/contabilidad/__pycache__/log.cpython-39.pyc
Normal file
BIN
python/src/contabilidad/__pycache__/log.cpython-39.pyc
Normal file
Binary file not shown.
BIN
python/src/contabilidad/__pycache__/passwords.cpython-39.pyc
Normal file
BIN
python/src/contabilidad/__pycache__/passwords.cpython-39.pyc
Normal file
Binary file not shown.
19
python/src/contabilidad/log.py
Normal file
19
python/src/contabilidad/log.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
logging = {
|
||||||
|
'filename': '/var/log/python/error.log'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class LOG_LEVEL:
|
||||||
|
INFO = 'INFO'
|
||||||
|
WARNING = 'WARNING'
|
||||||
|
DEBUG = 'DEBUG'
|
||||||
|
ERROR = 'ERROR'
|
||||||
|
|
||||||
|
|
||||||
|
def log(message, level=LOG_LEVEL.INFO):
|
||||||
|
filename = logging['filename']
|
||||||
|
with open(filename, 'a') as f:
|
||||||
|
f.write(time.strftime('[%Y-%m-%d %H:%M:%S] ') + ' - ' + level + ': ' + message)
|
6
python/src/contabilidad/passwords.py
Normal file
6
python/src/contabilidad/passwords.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
def get_passwords(filename):
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
return yaml.load(f, Loader=yaml.Loader)['passwords']
|
51
python/src/contabilidad/pdf.py
Normal file
51
python/src/contabilidad/pdf.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import camelot
|
||||||
|
import PyPDF4
|
||||||
|
import pikepdf
|
||||||
|
|
||||||
|
|
||||||
|
def is_encrypted(filename):
|
||||||
|
with open(filename, 'rb') as file:
|
||||||
|
reader = PyPDF4.PdfFileReader(file)
|
||||||
|
return reader.getIsEncrypted()
|
||||||
|
|
||||||
|
|
||||||
|
def check_password(filename, password):
|
||||||
|
if not is_encrypted(filename):
|
||||||
|
return True
|
||||||
|
with open(filename, 'rb') as file:
|
||||||
|
reader = PyPDF4.PdfFileReader(file)
|
||||||
|
status = reader.decrypt(str(password))
|
||||||
|
if status == 0:
|
||||||
|
return False
|
||||||
|
return reader.getIsEncrypted()
|
||||||
|
|
||||||
|
|
||||||
|
def remove_encryption(filename, password, new_name):
|
||||||
|
pdf = pikepdf.open(filename, password=str(password))
|
||||||
|
if '.pdf' not in new_name:
|
||||||
|
new_name += '.pdf'
|
||||||
|
pdf.save(new_name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_pdf(file, password=''):
|
||||||
|
reader = PyPDF4.PdfFileReader(file)
|
||||||
|
if reader.getIsEncrypted() and password != '':
|
||||||
|
status = reader.decrypt(password=str(password))
|
||||||
|
if status == 0:
|
||||||
|
return None
|
||||||
|
return reader
|
||||||
|
|
||||||
|
|
||||||
|
def get_text(filename, password=''):
|
||||||
|
with open(filename, 'rb') as f:
|
||||||
|
reader = get_pdf(f, password)
|
||||||
|
if reader is None:
|
||||||
|
return None
|
||||||
|
texts = []
|
||||||
|
for p in range(0, reader.getNumPages()):
|
||||||
|
texts.append(reader.getPage(p).extractText())
|
||||||
|
return texts
|
||||||
|
|
||||||
|
|
||||||
|
def get_data(filename):
|
||||||
|
return camelot.read_pdf(filename, pages='all', output_format='json')
|
54
python/src/contabilidad/send_pdf.py
Normal file
54
python/src/contabilidad/send_pdf.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import argparse
|
||||||
|
import yaml
|
||||||
|
import PyPDF4
|
||||||
|
import httpx
|
||||||
|
|
||||||
|
|
||||||
|
def get_pdf(file, password=''):
|
||||||
|
reader = PyPDF4.PdfFileReader(file)
|
||||||
|
if password != '':
|
||||||
|
status = reader.decrypt(password=password)
|
||||||
|
if status == 0:
|
||||||
|
print('Not decrypted')
|
||||||
|
return reader
|
||||||
|
|
||||||
|
|
||||||
|
def send_to_parser(url, text):
|
||||||
|
res = httpx.post(url, data={'to_parse': text})
|
||||||
|
return {'status': res.status_code, 'text': res.json()}
|
||||||
|
|
||||||
|
|
||||||
|
def get_text(filename, password=''):
|
||||||
|
with open(filename, 'rb') as f:
|
||||||
|
reader = get_pdf(f, password)
|
||||||
|
texts = []
|
||||||
|
for p in range(0, reader.getNumPages()):
|
||||||
|
texts.append(reader.getPage(p).extractText())
|
||||||
|
return "\n".join(texts)
|
||||||
|
|
||||||
|
|
||||||
|
def get_config(filename):
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
return yaml.load(f, Loader=yaml.Loader)
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
password = ''
|
||||||
|
if args.config_file is not None:
|
||||||
|
config = get_config(args.config_file)
|
||||||
|
password = config['password']
|
||||||
|
if args.password is not None:
|
||||||
|
password = args.password
|
||||||
|
text = get_text(args.filename, password)
|
||||||
|
res = send_to_parser(args.url, text)
|
||||||
|
print(res)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-f', '--filename', type=str)
|
||||||
|
parser.add_argument('-p', '--password', type=str)
|
||||||
|
parser.add_argument('-c', '--config_file', type=str)
|
||||||
|
parser.add_argument('-u', '--url', type=str)
|
||||||
|
_args = parser.parse_args()
|
||||||
|
main(_args)
|
90
python/src/contabilidad/text_handler.py
Normal file
90
python/src/contabilidad/text_handler.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
def text_cleanup(text, filename: str = None):
|
||||||
|
if isinstance(text, list):
|
||||||
|
output = []
|
||||||
|
for t in text:
|
||||||
|
output.append(text_cleanup(t, filename=filename))
|
||||||
|
return output
|
||||||
|
if filename is None:
|
||||||
|
return text
|
||||||
|
if 'bice' in filename.lower():
|
||||||
|
return bice(text)
|
||||||
|
if 'scotiabank' in filename.lower():
|
||||||
|
return scotiabank(text)
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def bice(text):
|
||||||
|
lines = text.split("\n\n\n")
|
||||||
|
print(lines)
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def scotiabank(text):
|
||||||
|
words = text.split("\n")
|
||||||
|
output = [words[0]]
|
||||||
|
output = output + extract_from_to(words, 'No. CTA.', end='VENCIMIENTO LINEA DE CREDITO', line_length=3)
|
||||||
|
output = output + extract_from_to(words, 'VENCIMIENTO LINEA DE CREDITO',
|
||||||
|
end='NOMBRE EJECUTIVO: LILIAN AVILA MANRIQUEZ', line_length=2)
|
||||||
|
output = output + extract_from_to(words, 'NOMBRE EJECUTIVO: LILIAN AVILA MANRIQUEZ', end='SALDO ANTERIOR',
|
||||||
|
line_length=1)
|
||||||
|
output = output + extract_from_to(words, 'SALDO ANTERIOR', end='FECHA', line_length=4)
|
||||||
|
output = output + extract_data(words, 'FECHA', end='ACTUALICE SIEMPRE ANTECEDENTES LEGALES, ', line_length=6,
|
||||||
|
merge_list=[['DOCTO', 'No.'], ['SALDO', 'DIARIO']])
|
||||||
|
[print(li) for li in output]
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def extract_from_to(word_list, start, line_length, end: str = None, merge_list=None):
|
||||||
|
if end is not None:
|
||||||
|
return extract_by_line(word_list[word_list.index(start):word_list.index(end)], line_length, merge_list)
|
||||||
|
return extract_by_line(word_list[word_list.index(start):], line_length, merge_list)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_by_line(word_list, line_length, merge_list=None):
|
||||||
|
if merge_list is not None:
|
||||||
|
word_list = merge_words(word_list, merge_list)
|
||||||
|
output = []
|
||||||
|
line = []
|
||||||
|
for k, w in enumerate(word_list):
|
||||||
|
if k > 0 and k % line_length == 0:
|
||||||
|
output.append(line)
|
||||||
|
line = []
|
||||||
|
line.append(w)
|
||||||
|
output.append(line)
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def merge_words(word_list, merge_list):
|
||||||
|
for m in merge_list:
|
||||||
|
i = word_list.index(m[0])
|
||||||
|
word_list = word_list[:i] + ["\n".join(m)] + word_list[i+len(m):]
|
||||||
|
return word_list
|
||||||
|
|
||||||
|
|
||||||
|
def extract_data(word_list, start, line_length, end=None, merge_list=None, date_sep='/'):
|
||||||
|
word_list = word_list[word_list.index(start):]
|
||||||
|
if end is not None:
|
||||||
|
word_list = word_list[:word_list.index(end)]
|
||||||
|
if merge_list is not None:
|
||||||
|
word_list = merge_words(word_list, merge_list)
|
||||||
|
output = []
|
||||||
|
line = []
|
||||||
|
line_num = 0
|
||||||
|
col = 0
|
||||||
|
for k, w in enumerate(word_list):
|
||||||
|
if col > 0 and col % line_length == 0:
|
||||||
|
output.append(line)
|
||||||
|
line = []
|
||||||
|
col = 0
|
||||||
|
if col > 0 and date_sep in w and len(line) < line_length:
|
||||||
|
cnt = 0
|
||||||
|
for i in range(len(line), line_length):
|
||||||
|
line.append('')
|
||||||
|
cnt += 1
|
||||||
|
output.append(line)
|
||||||
|
line = [w]
|
||||||
|
col += cnt + 1
|
||||||
|
continue
|
||||||
|
line.append(w)
|
||||||
|
col += 1
|
||||||
|
return output
|
24
python/src/main.py
Normal file
24
python/src/main.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
|
||||||
|
import contabilidad.pdf as pdf
|
||||||
|
import contabilidad.text_handler as th
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
filename = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'data', args.filename))
|
||||||
|
temp = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'data', args.temp_filename))
|
||||||
|
pdf.remove_encryption(filename, args.password, temp)
|
||||||
|
obj = pdf.get_data(temp)
|
||||||
|
obj = pdf.get_text(filename, args.password)
|
||||||
|
text = th.text_cleanup(obj, filename=str(args.filename))
|
||||||
|
os.remove(temp)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-f', '--filename', type=str)
|
||||||
|
parser.add_argument('-p', '--password', type=str, default='')
|
||||||
|
parser.add_argument('-t', '--temp_filename', type=str)
|
||||||
|
_args = parser.parse_args()
|
||||||
|
main(_args)
|
35
python/src/tests/Testing.md
Normal file
35
python/src/tests/Testing.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Tests
|
||||||
|
|
||||||
|
### 1. Conductor
|
||||||
|
+ Set start event
|
||||||
|
+ Get ready events
|
||||||
|
+ Set first step event
|
||||||
|
+ Get first step ready
|
||||||
|
+ Set second step event
|
||||||
|
+ Get second step ready
|
||||||
|
|
||||||
|
### 2. Email
|
||||||
|
+ Connect to IMAP
|
||||||
|
+ Wrong data
|
||||||
|
+ Wrong configuration
|
||||||
|
+ Get mailboxes
|
||||||
|
+ Get mail ids with search
|
||||||
|
+ Get mails by id
|
||||||
|
+ Get mail by id
|
||||||
|
+ Get attachment
|
||||||
|
+ Close connection
|
||||||
|
|
||||||
|
### 3. API Sender
|
||||||
|
+ Get attachments
|
||||||
|
+ Process
|
||||||
|
+ Send to API
|
||||||
|
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
1. Start
|
||||||
|
+ Connect
|
||||||
|
+ Standby
|
||||||
|
2. Find emails, get attachments
|
||||||
|
3. Process attachments
|
||||||
|
4. Send to API
|
||||||
|
5. Close
|
12
ui/common/Controller/Config.php
Normal file
12
ui/common/Controller/Config.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
namespace Contabilidad\Common\Controller;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
|
use Slim\Views\Blade as View;
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
public function __invoke(Request $request, Response $response, View $view): Response {
|
||||||
|
return $view->render($response, 'config.list');
|
||||||
|
}
|
||||||
|
}
|
@ -9,4 +9,7 @@ class Home {
|
|||||||
public function __invoke(Request $request, Response $response, View $view): Response {
|
public function __invoke(Request $request, Response $response, View $view): Response {
|
||||||
return $view->render($response, 'home');
|
return $view->render($response, 'home');
|
||||||
}
|
}
|
||||||
|
public function info(Request $request, Response $response, View $view): Response {
|
||||||
|
return $view->render($response, 'info');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user