Merge branch 'develop' into release
This commit is contained in:
@ -24,4 +24,11 @@ class Base {
|
|||||||
$key = urlencode(base64_encode($signature));
|
$key = urlencode(base64_encode($signature));
|
||||||
return $this->withJson($response, ['key' => $key]);
|
return $this->withJson($response, ['key' => $key]);
|
||||||
}
|
}
|
||||||
|
public function info(Request $request, Response $response): Response {
|
||||||
|
ob_start();
|
||||||
|
phpinfo();
|
||||||
|
$data = ob_get_clean();
|
||||||
|
$response->getBody()->write($data);
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,35 +13,35 @@ class Categorias {
|
|||||||
|
|
||||||
public function __invoke(Request $request, Response $response, Factory $factory, Service $service): Response {
|
public function __invoke(Request $request, Response $response, Factory $factory, Service $service): Response {
|
||||||
$categorias = $factory->find(Categoria::class)->many();
|
$categorias = $factory->find(Categoria::class)->many();
|
||||||
array_walk($categorias, function(&$item) use ($service) {
|
if ($categorias !== null) {
|
||||||
$arr = $item->toArray();
|
array_walk($categorias, function(&$item) use ($service) {
|
||||||
if ($item->cuentas()) {
|
$arr = $item->toArray();
|
||||||
$arr['cuentas'] = array_map(function($item) {
|
if ($item->cuentas()) {
|
||||||
return $item->toArray();
|
$arr['cuentas'] = array_map(function($item) {
|
||||||
}, $item->cuentas());
|
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) {
|
$maps = ['activo', 'pasivo', 'ganancia', 'perdida'];
|
||||||
return $sum + $item->saldo($service, true);
|
foreach ($maps as $m) {
|
||||||
});
|
$p = $m . 's';
|
||||||
}
|
$t = ucfirst($m);
|
||||||
$item = $arr;
|
$cuentas = $item->getCuentasOf($t);
|
||||||
});
|
if ($cuentas === false or $cuentas === null) {
|
||||||
if ($categorias) {
|
$arr[$p] = 0;
|
||||||
usort($categorias, function($a, $b) {
|
continue;
|
||||||
return strcmp($a['nombre'], $b['nombre']);
|
}
|
||||||
});
|
$arr[$p] = array_reduce($cuentas, function($sum, $item) use($service) {
|
||||||
|
return $sum + $item->saldo($service, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$item = $arr;
|
||||||
|
});
|
||||||
|
usort($categorias, function($a, $b) {
|
||||||
|
return strcmp($a['nombre'], $b['nombre']);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
$output = [
|
$output = [
|
||||||
'categorias' => $categorias
|
'categorias' => $categorias
|
||||||
];
|
];
|
||||||
return $this->withJson($response, $output);
|
return $this->withJson($response, $output);
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,47 @@ namespace Contabilidad\Common\Controller;
|
|||||||
|
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
|
use Psr\Container\ContainerInterface as Container;
|
||||||
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\DocumentHandler as Handler;
|
use Contabilidad\Common\Service\DocumentHandler as Handler;
|
||||||
|
use Contabilidad\Cuenta;
|
||||||
|
|
||||||
class Import {
|
class Import {
|
||||||
use Json;
|
use Json;
|
||||||
|
|
||||||
public function __invoke(Request $request, Response $response, Factory $factory): Response {
|
public function __invoke(Request $request, Response $response, Factory $factory, Container $container): Response {
|
||||||
$post = $request->getParsedBody();
|
$post =$request->getParsedBody();
|
||||||
return $this->withJson($response, $post);
|
$cuenta = $factory->find(Cuenta::class)->one($post['cuenta']);
|
||||||
|
$file = $request->getUploadedFiles()['archivo'];
|
||||||
|
$valid_media = [
|
||||||
|
'text/csv' => 'csvs',
|
||||||
|
'application/pdf' => 'pdfs',
|
||||||
|
'application/vnd.ms-excel' => 'xlss',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlss',
|
||||||
|
'application/json' => 'jsons'
|
||||||
|
];
|
||||||
|
if ($file->getError() === 0 and in_array($file->getClientMediaType(), array_keys($valid_media))) {
|
||||||
|
$filenfo = new \SplFileInfo($file->getClientFilename());
|
||||||
|
$new_name = implode('.', [implode(' - ', [$cuenta->nombre, $cuenta->categoria()->nombre, $post['fecha']]), $filenfo->getExtension()]);
|
||||||
|
$to = implode(DIRECTORY_SEPARATOR, [$container->get('folders')->uploads, $valid_media[$file->getClientMediaType()], $new_name]);
|
||||||
|
$file->moveTo($to);
|
||||||
|
$status = file_exists($to);
|
||||||
|
}
|
||||||
|
$output = [
|
||||||
|
'input' => [
|
||||||
|
'name' => $file->getClientFilename(),
|
||||||
|
'type' => $file->getClientMediaType(),
|
||||||
|
'size' => $file->getSize(),
|
||||||
|
'error' => $file->getError()
|
||||||
|
],
|
||||||
|
'new_name' => $new_name,
|
||||||
|
'uploaded' => $status
|
||||||
|
];
|
||||||
|
return $this->withJson($response, $output);
|
||||||
}
|
}
|
||||||
public function uploads(Request $request, Response $response, Handler $handler): Response {
|
public function uploads(Request $request, Response $response, Handler $handler): Response {
|
||||||
$output = $handler->handle();
|
$output = $handler->handle();
|
||||||
return $this->withJson($response, $output);
|
return $this->withJson($response, $output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,31 +13,34 @@ class TiposCategorias {
|
|||||||
|
|
||||||
public function __invoke(Request $request, Response $response, Factory $factory, Service $service): Response {
|
public function __invoke(Request $request, Response $response, Factory $factory, Service $service): Response {
|
||||||
$tipos = $factory->find(TipoCategoria::class)->many();
|
$tipos = $factory->find(TipoCategoria::class)->many();
|
||||||
array_walk($tipos, function(&$item) use ($service) {
|
if ($tipos !== null) {
|
||||||
$arr = $item->toArray();
|
array_walk($tipos, function(&$item) use ($service) {
|
||||||
$arr['categorias'] = array_map(function($item) {
|
$arr = $item->toArray();
|
||||||
return $item->toArray();
|
$arr['categorias'] = $item->categorias();
|
||||||
}, $item->categorias());
|
if ($arr['categorias'] !== null) {
|
||||||
$arr['saldo'] = abs($item->saldo($service));
|
$arr['categorias'] = array_map(function($item) {
|
||||||
$maps = ['activo', 'pasivo', 'ganancia', 'perdida'];
|
return $item->toArray();
|
||||||
foreach ($maps as $m) {
|
}, $item->categorias());
|
||||||
$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) {
|
$arr['saldo'] = abs($item->saldo($service));
|
||||||
return $sum + $item->saldo($service, true);
|
$maps = ['activo', 'pasivo', 'ganancia', 'perdida'];
|
||||||
});
|
foreach ($maps as $m) {
|
||||||
}
|
$p = $m . 's';
|
||||||
$item = $arr;
|
$t = ucfirst($m);
|
||||||
});
|
$cuentas = $item->getCuentasOf($t);
|
||||||
if ($tipos) {
|
if ($cuentas === false or $cuentas === null) {
|
||||||
usort($tipos, function($a, $b) {
|
$arr[$p] = 0;
|
||||||
return strcmp($a['descripcion'], $b['descripcion']);
|
continue;
|
||||||
});
|
}
|
||||||
|
$arr[$p] = array_reduce($cuentas, function($sum, $item) use($service) {
|
||||||
|
return $sum + $item->saldo($service, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$item = $arr;
|
||||||
|
});
|
||||||
|
usort($tipos, function($a, $b) {
|
||||||
|
return strcmp($a['descripcion'], $b['descripcion']);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
$output = [
|
$output = [
|
||||||
'tipos' => $tipos
|
'tipos' => $tipos
|
||||||
|
@ -20,7 +20,7 @@ final class TipoCuenta extends AbstractMigration
|
|||||||
{
|
{
|
||||||
$this->table('tipos_cuenta')
|
$this->table('tipos_cuenta')
|
||||||
->addColumn('descripcion', 'string')
|
->addColumn('descripcion', 'string')
|
||||||
->addColumn('color', 'string', ['length' => 6])
|
->addColumn('color', 'string', ['length' => 6, 'default' => 'ffffff'])
|
||||||
->create();
|
->create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ server {
|
|||||||
access_log /var/log/nginx/access.log;
|
access_log /var/log/nginx/access.log;
|
||||||
root /app/public;
|
root /app/public;
|
||||||
|
|
||||||
|
client_max_body_size 50M;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.php?$query_string;
|
try_files $uri $uri/ /index.php?$query_string;
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
log_errors = true
|
log_errors = true
|
||||||
error_log = /var/log/php/error.log
|
error_log = /var/log/php/error.log
|
||||||
|
upload_max_filesize = 50M
|
||||||
|
max_input_vars = 5000
|
||||||
|
@ -3,4 +3,5 @@ use Contabilidad\Common\Controller\Base;
|
|||||||
|
|
||||||
$app->get('/key/generate[/]', [Base::class, 'generate_key']);
|
$app->get('/key/generate[/]', [Base::class, 'generate_key']);
|
||||||
$app->get('/balance[/]', [Contabilidad\Common\Controller\TiposCategorias::class, 'balance']);
|
$app->get('/balance[/]', [Contabilidad\Common\Controller\TiposCategorias::class, 'balance']);
|
||||||
|
$app->get('/info', [Base::class, 'info']);
|
||||||
$app->get('/', Base::class);
|
$app->get('/', Base::class);
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
use Psr\Container\ContainerInterface as Container;
|
use Psr\Container\ContainerInterface as Container;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
GuzzleHttp\Client::class => function(Container $c) {
|
GuzzleHttp\Client::class => function(Container $c) {
|
||||||
return new GuzzleHttp\Client();
|
return new GuzzleHttp\Client();
|
||||||
},
|
},
|
||||||
Contabilidad\Common\Service\Auth::class => function(Container $c) {
|
Contabilidad\Common\Service\Auth::class => function(Container $c) {
|
||||||
return new Contabilidad\Common\Service\Auth($c->get('api_key'));
|
return new Contabilidad\Common\Service\Auth($c->get('api_key'));
|
||||||
},
|
},
|
||||||
|
@ -10,16 +10,16 @@ use Contabilidad\Common\Service\TiposCambios as Service;
|
|||||||
* @property int $activo
|
* @property int $activo
|
||||||
*/
|
*/
|
||||||
class TipoCategoria extends Model {
|
class TipoCategoria extends Model {
|
||||||
public static $_table = 'tipos_categoria';
|
public static $_table = 'tipos_categoria';
|
||||||
protected static $fields = ['descripcion', 'activo'];
|
protected static $fields = ['descripcion', 'activo'];
|
||||||
|
|
||||||
protected $categorias;
|
protected $categorias;
|
||||||
public function categorias() {
|
public function categorias() {
|
||||||
if ($this->categorias === null) {
|
if ($this->categorias === null) {
|
||||||
$this->categorias = $this->parentOf(Categoria::class, [Model::CHILD_KEY => 'tipo_id']);
|
$this->categorias = $this->parentOf(Categoria::class, [Model::CHILD_KEY => 'tipo_id']);
|
||||||
|
}
|
||||||
|
return $this->categorias;
|
||||||
}
|
}
|
||||||
return $this->categorias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCuentasOf($tipo) {
|
public function getCuentasOf($tipo) {
|
||||||
return $this->factory->find(Cuenta::class)
|
return $this->factory->find(Cuenta::class)
|
||||||
@ -37,7 +37,7 @@ class TipoCategoria extends Model {
|
|||||||
protected $saldo;
|
protected $saldo;
|
||||||
public function saldo(Service $service = null) {
|
public function saldo(Service $service = null) {
|
||||||
if ($this->saldo === null) {
|
if ($this->saldo === null) {
|
||||||
$this->saldo = array_reduce($this->categorias(), function($sum, $item) use ($service) {
|
$this->saldo = array_reduce($this->categorias() ?? [], function($sum, $item) use ($service) {
|
||||||
return $sum + $item->saldo($service);
|
return $sum + $item->saldo($service);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ services:
|
|||||||
image: php-ui
|
image: php-ui
|
||||||
env_file:
|
env_file:
|
||||||
- .api.env
|
- .api.env
|
||||||
|
- .env
|
||||||
build:
|
build:
|
||||||
context: ui
|
context: ui
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
FROM php:8-fpm
|
FROM php:8-fpm
|
||||||
|
|
||||||
|
COPY --from=composer /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
12
ui/common/Controller/Importar.php
Normal file
12
ui/common/Controller/Importar.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 Importar {
|
||||||
|
public function __invoke(Request $request, Response $response, View $view): Response {
|
||||||
|
return $view->render($response, 'importar');
|
||||||
|
}
|
||||||
|
}
|
4
ui/resources/routes/importar.php
Normal file
4
ui/resources/routes/importar.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
use Contabilidad\Common\Controller\Importar;
|
||||||
|
|
||||||
|
$app->get('/importar[/]', Importar::class);
|
92
ui/resources/views/importar.blade.php
Normal file
92
ui/resources/views/importar.blade.php
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
@extends('layout.base')
|
||||||
|
|
||||||
|
@section('page_title')
|
||||||
|
Importar
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('page_content')
|
||||||
|
<h1>Importar</h1>
|
||||||
|
<form class="ui form" action="#" method="post" id="importar_form" enctype="multipart/form-data">
|
||||||
|
<div class="two wide field">
|
||||||
|
<label>Fecha</label>
|
||||||
|
<div class="ui date calendar">
|
||||||
|
<div class="ui icon input">
|
||||||
|
<input type="text" name="fecha" />
|
||||||
|
<i class="calendar outline icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="six wide field">
|
||||||
|
<label>Cuenta</label>
|
||||||
|
<select name="cuenta"></select>
|
||||||
|
</div>
|
||||||
|
<div class="inline field">
|
||||||
|
<input type="file" name="archivo" style="display: none;" />
|
||||||
|
<div class="ui labeled icon input" id="archivo_btn">
|
||||||
|
<div class="ui label">Archivo</div>
|
||||||
|
<input type="text" readonly="" />
|
||||||
|
<i class="search icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="ui button">Importar</button>
|
||||||
|
</form>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script type="text/javascript">
|
||||||
|
function getCuentas() {
|
||||||
|
sendGet(_urls.api + '/cuentas').then((data) => {
|
||||||
|
if (data.cuentas === null || data.cuentas.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const select = $("select[name='cuenta']")
|
||||||
|
let values = []
|
||||||
|
$.each(data.cuentas, (i, el) => {
|
||||||
|
const nombre = [el.nombre, el.categoria.nombre].join(' - ')
|
||||||
|
values.push({
|
||||||
|
name: nombre,
|
||||||
|
value: el.id,
|
||||||
|
text: nombre
|
||||||
|
})
|
||||||
|
})
|
||||||
|
select.dropdown({values})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
$(document).ready(() => {
|
||||||
|
getCuentas()
|
||||||
|
const today = new Date()
|
||||||
|
const start = new Date(today.getFullYear(), today.getMonth() - 1)
|
||||||
|
$('.ui.calendar').calendar({
|
||||||
|
type: 'month',
|
||||||
|
initialDate: start,
|
||||||
|
maxDate: start,
|
||||||
|
months: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
|
||||||
|
monthsShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
|
||||||
|
formatter: {
|
||||||
|
date: function(date, settings) {
|
||||||
|
if (!date) return ''
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = date.getMonth() + 1
|
||||||
|
return [year, month].join('-')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$('#archivo_btn').css('cursor', 'pointer').click(() => {
|
||||||
|
$("[name='archivo']").trigger('click')
|
||||||
|
})
|
||||||
|
$("[name='archivo']").change((e) => {
|
||||||
|
const arch = $(e.currentTarget)
|
||||||
|
const filename = arch[0].files[0].name
|
||||||
|
$('#archivo_btn').find('input').val(filename)
|
||||||
|
})
|
||||||
|
$('#importar_form').submit((e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
const data = new FormData(e.currentTarget)
|
||||||
|
sendPost(_urls.api + '/import', data, true).then((resp) => {
|
||||||
|
console.debug(resp)
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
@endpush
|
@ -2,6 +2,7 @@
|
|||||||
<a class="item" href="{{$urls->base}}">Inicio</a>
|
<a class="item" href="{{$urls->base}}">Inicio</a>
|
||||||
@include('layout.body.menu.cuentas')
|
@include('layout.body.menu.cuentas')
|
||||||
@include('layout.body.menu.categorias')
|
@include('layout.body.menu.categorias')
|
||||||
|
<a class="item" href="{{$urls->base}}/importar">Importar</a>
|
||||||
<div class="right menu">
|
<div class="right menu">
|
||||||
<a class="item" href="{{$urls->base}}config">Config</a>
|
<a class="item" href="{{$urls->base}}config">Config</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,7 +7,18 @@
|
|||||||
base: '{{$urls->base}}',
|
base: '{{$urls->base}}',
|
||||||
api: '{{$urls->api}}'
|
api: '{{$urls->api}}'
|
||||||
}
|
}
|
||||||
function buildAjax(url, method) {
|
function buildAjax(url, method, files=false) {
|
||||||
|
if (files) {
|
||||||
|
return {
|
||||||
|
url: url,
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer ' + API_KEY
|
||||||
|
},
|
||||||
|
method: method,
|
||||||
|
processData: false,
|
||||||
|
contentType: false
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
url: url,
|
url: url,
|
||||||
headers: {
|
headers: {
|
||||||
@ -21,8 +32,8 @@
|
|||||||
let ajax_obj = buildAjax(url, 'GET')
|
let ajax_obj = buildAjax(url, 'GET')
|
||||||
return $.ajax(ajax_obj)
|
return $.ajax(ajax_obj)
|
||||||
}
|
}
|
||||||
function sendPost(url, data) {
|
function sendPost(url, data, files=false) {
|
||||||
let ajax_obj = buildAjax(url, 'POST')
|
let ajax_obj = buildAjax(url, 'POST', files)
|
||||||
ajax_obj['data'] = data
|
ajax_obj['data'] = data
|
||||||
return $.ajax(ajax_obj)
|
return $.ajax(ajax_obj)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user