Merge branch 'develop'

This commit is contained in:
2022-03-07 12:07:51 -03:00
28 changed files with 342 additions and 209 deletions

2
.adminer.env.sample Normal file
View File

@ -0,0 +1,2 @@
ADMINER_DESIGN=dracula
ADMINER_PLUGINS=dump-json

4
.db.env.sample Normal file
View File

@ -0,0 +1,4 @@
MYSQL_DATABASE=
MYSQL_PASSWORD=
MYSQL_ROOT_PASSWORD=
MYSQL_USER=

2
.env.sample Normal file
View File

@ -0,0 +1,2 @@
BASE_URL=
MYSQL_HOST=

19
.gitignore vendored
View File

@ -1,9 +1,10 @@
.env
/vendor/
composer.lock
/node_modules/
package-lock.json
Pipfile.lock
/logs/
/cache/
/modules/
**/*.env
**/vendor/
**/composer.lock
**/node_modules/
**/package-lock.json
**/Pipfile.lock
**/logs/
**/cache/
**/modules/
**/.idea/

View File

@ -1,6 +1,12 @@
FROM php:7.4-fpm
RUN docker-php-ext-install pdo pdo_mysql
RUN apt-get update && apt-get install -y libzip-dev libicu-dev git
RUN docker-php-ext-install pdo pdo_mysql zip intl
RUN pecl install xdebug-3.0.3 \
&& docker-php-ext-enable xdebug
COPY --from=composer /usr/bin/composer /usr/bin/composer
WORKDIR /code

View File

@ -3,8 +3,8 @@
"description" : "Asset manager module for my apps",
"type" : "library",
"require" : {
"aldarien/config" : "dev-master",
"aldarien/contract" : "dev-master"
"aldarien/config" : "*",
"aldarien/contract" : "*"
},
"require-dev" : {
"phpunit/phpunit" : "^6.3"

View File

@ -10,8 +10,8 @@
}
],
"require": {
"aldarien/contract": "dev-master",
"aldarien/root": "dev-master",
"aldarien/contract": "*",
"aldarien/root": "*",
"symfony/yaml": "^3.3"
},
"autoload": {

View File

@ -4,7 +4,7 @@
"type" : "library",
"require-dev" : {
"phpunit/phpunit" : "^6",
"aldarien/config": "dev-master"
"aldarien/config": "*"
},
"license" : "MIT",
"authors" : [{

View File

@ -4,7 +4,7 @@
"type" : "library",
"require" : {
"wixel/gump" : "^1.5",
"aldarien/contract" : "dev-master"
"aldarien/contract" : "*"
},
"require-dev" : {
"phpunit/phpunit" : "^6.3"

View File

@ -4,7 +4,7 @@
"type": "library",
"require": {
"aura/session": "^2.1",
"aldarien/contract": "dev-master"
"aldarien/contract": "*"
},
"require-dev": {
"phpunit/phpunit": "^6.3"

View File

@ -3,8 +3,8 @@
"description" : "Get relative path uri",
"type" : "library",
"require" : {
"aldarien/contract" : "dev-master",
"aldarien/root" : "dev-master",
"aldarien/contract" : "*",
"aldarien/root" : "*",
"league/uri": "^5.2",
"sabre/uri": "^2.1"
},

View File

@ -4,8 +4,8 @@
"type": "library",
"require": {
"philo/laravel-blade": "^3.1",
"aldarien/contract": "dev-master",
"aldarien/config": "dev-master"
"aldarien/contract": "*",
"aldarien/config": "*"
},
"license": "MIT",
"authors": [

View File

@ -1,141 +1,141 @@
from flask import Blueprint, request, Response
import io
import json
import pandas as pd
import numpy as np
import datetime
ventas_blueprint = Blueprint('ventas', __name__,)
def format_data(data):
df = pd.DataFrame(data)
int_columns = ['Departamento', 'Estacionamientos', 'Bodegas']
for col in int_columns:
df[col] = pd.to_numeric(df[col], errors='ignore')
float_columns = ['Valor Promesa', 'Pie', 'Pie Pagado', '% Pie Pagado', 'Bono Pie', 'Valor Operador',
'Premios', 'Subsidio', 'Ahorro', 'Credito', 'Valor Ests & Bods', 'Valor Neto',
'UF/m²*', 'Comision', 'Venta s/Comision', 'Precio']
for col in float_columns:
if col in df.columns:
df[col] = pd.to_numeric(df[col], errors='coerce')
df = df.replace(np.nan, 0, regex=True)
df['Fecha Venta'] = pd.to_datetime(df['Fecha Venta'], format='%Y-%m-%d')
df = df.sort_values(by=['Fecha Venta', 'Departamento'])
df['Fecha Venta'] = df['Fecha Venta'].dt.strftime('%d.%m.%Y')
return df
def format_columns(workbook, columns):
column_settings = [{'header': column} for column in columns]
center_format = workbook.add_format({'align': 'center'})
amount_format = workbook.add_format({'num_format': '#,##0.00'})
percent_format = workbook.add_format({'num_format': '0.00%'})
amount_columns = ['m² Ponderados', 'Valor Promesa', 'Pie', 'Pie Pagado', 'Bono Pie', 'Valor Operador', 'Premios',
'Subsidio', 'Ahorro', 'Credito', 'Valor Ests & Bods', 'Valor Neto', 'UF/m²*', 'Comision',
'Venta s/Comision', 'Precio']
center_columns = ['Departamento', 'Estacionamientos', 'Bodegas']
sum_columns = ['m² Ponderados', 'Valor Promesa', 'Pie', 'Pie Pagado', 'Bono Pie', 'Subsidio', 'Ahorro', 'Credito',
'Valor Operador', 'Premios', 'Valor Ests & Bods', 'Valor Neto', 'Comision']
count_columns = ['Departamento', 'Estacionamientos', 'Bodegas']
for (k, col) in enumerate(column_settings):
if col['header'] in amount_columns:
column_settings[k]['format'] = amount_format
if col['header'] in center_columns:
column_settings[k]['format'] = center_format
if col['header'] in sum_columns:
column_settings[k]['total_function'] = 'sum'
if col['header'] in count_columns:
column_settings[k]['total_function'] = 'count'
if col['header'] == '% Pie Pagado':
column_settings[k]['format'] = percent_format
if col['header'] == 'Propietario':
column_settings[k]['total_string'] = 'TOTAL'
return column_settings
def format_excel(workbook, worksheet, data):
center_format = workbook.add_format({'align': 'center'})
amount_format = workbook.add_format({'num_format': '#,##0.00'})
percent_format = workbook.add_format({'num_format': '0.00%'})
amount_columns = ['m² Ponderados', 'Valor Promesa', 'Pie', 'Pie Pagado', 'Bono Pie', 'Valor Operador', 'Premios',
'Subsidio', 'Ahorro', 'Credito', 'Valor Ests & Bods', 'Valor Neto', 'UF/m²*', 'Comision',
'Venta s/Comision', 'Precio']
center_columns = ['Departamento', 'Estacionamientos', 'Bodegas']
for col in amount_columns:
if col not in data.columns:
continue
k = data.columns.get_loc(col) + 1
worksheet.set_column(k, k, cell_format=amount_format)
for col in center_columns:
if col not in data.columns:
continue
k = data.columns.get_loc(col) + 1
worksheet.set_column(k, k, cell_format=center_format)
col = '% Pie Pagado'
k = data.columns.get_loc(col) + 1
worksheet.set_column(k, k, cell_format=percent_format)
return worksheet
@ventas_blueprint.route('', methods=['POST'])
def ventas():
data = json.loads(request.data)
output = io.BytesIO()
writer = pd.ExcelWriter('tmp.xlsx', engine='xlsxwriter')
df = format_data(data['data'])
start_row = 4
if 'Compañía' in data:
start_row += 1
df.to_excel(writer, startrow=start_row+1, startcol=1, header=False, index=False, sheet_name='Ventas')
wb = writer.book
wb.filename = output
title_format = wb.add_format({'font_size': 16, 'bold': True})
ws = writer.sheets['Ventas']
(max_row, max_col) = df.shape
if 'Compañía' in data:
ws.merge_range(1, 1, 1, max_col, data['Compañía'])
ws.merge_range(start_row-3, 1, start_row-3, max_col, data['Proyecto'], cell_format=title_format)
ws.write_string(start_row-2, 1, 'Ventas')
column_settings = format_columns(wb, df.columns)
ws.add_table(start_row, 1, max_row+start_row+1, max_col, {'name': 'Ventas', 'total_row': 1,
'columns': column_settings,
'style': 'Table Style Medium 1'})
ws = format_excel(wb, ws, df)
column_widths = {
'B': 46,
'C': 16,
'D': 18,
'E': 10,
'F': 13,
'G': 7,
'H': 8,
'I': 16,
'J': 16,
'K': 13,
'L': 14
}
for (col, wd) in column_widths.items():
ws.set_column('{0}:{0}'.format(col), wd)
writer.save()
output.seek(0)
date = datetime.date.today()
filename = "Informe de Ventas - {0} - {1}.xlsx".format(data['Proyecto'], date.strftime('%Y-%m-%d'))
return Response(output, mimetype="application/ms-excel",
headers={"Content-Disposition": "attachment;filename={0}".format(filename),
"Content-Type": 'application/octet-stream; charset=utf-8'})
from flask import Blueprint, request, Response
import io
import json
import pandas as pd
import numpy as np
import datetime
ventas_blueprint = Blueprint('ventas', __name__,)
def format_data(data):
df = pd.DataFrame(data)
int_columns = ['Departamento', 'Estacionamientos', 'Bodegas']
for col in int_columns:
df[col] = pd.to_numeric(df[col], errors='ignore')
float_columns = ['Valor Promesa', 'Pie', 'Pie Pagado', '% Pie Pagado', 'Bono Pie', 'Valor Operador',
'Premios', 'Subsidio', 'Ahorro', 'Credito', 'Valor Ests & Bods', 'Valor Neto',
'UF/m²*', 'Comision', 'Venta s/Comision', 'Precio']
for col in float_columns:
if col in df.columns:
df[col] = pd.to_numeric(df[col], errors='coerce')
df = df.replace(np.nan, 0, regex=True)
df['Fecha Venta'] = pd.to_datetime(df['Fecha Venta'], format='%Y-%m-%d')
df = df.sort_values(by=['Fecha Venta', 'Departamento'])
df['Fecha Venta'] = df['Fecha Venta'].dt.strftime('%d.%m.%Y')
return df
def format_columns(workbook, columns):
column_settings = [{'header': column} for column in columns]
center_format = workbook.add_format({'align': 'center'})
amount_format = workbook.add_format({'num_format': '#,##0.00'})
percent_format = workbook.add_format({'num_format': '0.00%'})
amount_columns = ['m² Ponderados', 'Valor Promesa', 'Pie', 'Pie Pagado', 'Bono Pie', 'Valor Operador', 'Premios',
'Subsidio', 'Ahorro', 'Credito', 'Valor Ests & Bods', 'Valor Neto', 'UF/m²*', 'Comision',
'Venta s/Comision', 'Precio']
center_columns = ['Departamento', 'Estacionamientos', 'Bodegas']
sum_columns = ['m² Ponderados', 'Valor Promesa', 'Pie', 'Pie Pagado', 'Bono Pie', 'Subsidio', 'Ahorro', 'Credito',
'Valor Operador', 'Premios', 'Valor Ests & Bods', 'Valor Neto', 'Comision']
count_columns = ['Departamento', 'Estacionamientos', 'Bodegas']
for (k, col) in enumerate(column_settings):
if col['header'] in amount_columns:
column_settings[k]['format'] = amount_format
if col['header'] in center_columns:
column_settings[k]['format'] = center_format
if col['header'] in sum_columns:
column_settings[k]['total_function'] = 'sum'
if col['header'] in count_columns:
column_settings[k]['total_function'] = 'count'
if col['header'] == '% Pie Pagado':
column_settings[k]['format'] = percent_format
if col['header'] == 'Propietario':
column_settings[k]['total_string'] = 'TOTAL'
return column_settings
def format_excel(workbook, worksheet, data):
center_format = workbook.add_format({'align': 'center'})
amount_format = workbook.add_format({'num_format': '#,##0.00'})
percent_format = workbook.add_format({'num_format': '0.00%'})
amount_columns = ['m² Ponderados', 'Valor Promesa', 'Pie', 'Pie Pagado', 'Bono Pie', 'Valor Operador', 'Premios',
'Subsidio', 'Ahorro', 'Credito', 'Valor Ests & Bods', 'Valor Neto', 'UF/m²*', 'Comision',
'Venta s/Comision', 'Precio']
center_columns = ['Departamento', 'Estacionamientos', 'Bodegas']
for col in amount_columns:
if col not in data.columns:
continue
k = data.columns.get_loc(col) + 1
worksheet.set_column(k, k, cell_format=amount_format)
for col in center_columns:
if col not in data.columns:
continue
k = data.columns.get_loc(col) + 1
worksheet.set_column(k, k, cell_format=center_format)
col = '% Pie Pagado'
k = data.columns.get_loc(col) + 1
worksheet.set_column(k, k, cell_format=percent_format)
return worksheet
@ventas_blueprint.route('', methods=['POST'])
def ventas():
data = json.loads(request.data)
output = io.BytesIO()
writer = pd.ExcelWriter('tmp.xlsx', engine='xlsxwriter')
df = format_data(data['data'])
start_row = 4
if 'Compañía' in data:
start_row += 1
df.to_excel(writer, startrow=start_row+1, startcol=1, header=False, index=False, sheet_name='Ventas')
wb = writer.book
wb.filename = output
title_format = wb.add_format({'font_size': 16, 'bold': True})
ws = writer.sheets['Ventas']
(max_row, max_col) = df.shape
if 'Compañía' in data:
ws.merge_range(1, 1, 1, max_col, data['Compañía'])
ws.merge_range(start_row-3, 1, start_row-3, max_col, data['Proyecto'], cell_format=title_format)
ws.write_string(start_row-2, 1, 'Ventas')
column_settings = format_columns(wb, df.columns)
ws.add_table(start_row, 1, max_row+start_row+1, max_col, {'name': 'Ventas', 'total_row': 1,
'columns': column_settings,
'style': 'Table Style Medium 1'})
ws = format_excel(wb, ws, df)
column_widths = {
'B': 46,
'C': 16,
'D': 18,
'E': 10,
'F': 13,
'G': 7,
'H': 8,
'I': 16,
'J': 16,
'K': 13,
'L': 14
}
for (col, wd) in column_widths.items():
ws.set_column('{0}:{0}'.format(col), wd)
writer.save()
output.seek(0)
date = datetime.date.today()
filename = "Informe de Ventas - {0} - {1}.xlsx".format(data['Proyecto'], date.strftime('%Y-%m-%d'))
return Response(output, mimetype="application/ms-excel",
headers={"Content-Disposition": "attachment;filename={0}".format(filename),
"Content-Type": 'application/octet-stream; charset=utf-8'})

View File

@ -1,6 +1,7 @@
<?php
include_once dirname(__DIR__) . '/vendor/autoload.php';
include_once 'errors.php';
include_once 'dotenv.php';
include_once 'database.php';
include_once 'routes.php';
?>
?>

12
bootstrap/dotenv.php Normal file
View File

@ -0,0 +1,12 @@
<?php
use Dotenv\Dotenv;
$folder = dirname(__DIR__);
$files = new DirectoryIterator($folder);
foreach ($files as $file) {
if ($file->isDir() or $file->getExtension() != 'env') {
continue;
}
$env = Dotenv::createImmutable($file->getPath(), $file->getBasename());
$env->load();
}

View File

@ -3,26 +3,27 @@
"description" : "Intranet portal for Incoviba",
"type" : "project",
"require" : {
"aldarien/config" : "dev-master",
"aldarien/asset" : "dev-master",
"aldarien/format" : "dev-master",
"aldarien/response" : "dev-master",
"aldarien/view" : "dev-master",
"aldarien/session" : "dev-master",
"aldarien/config" : "*",
"aldarien/asset" : "*",
"aldarien/format" : "*",
"aldarien/response" : "*",
"aldarien/view" : "*",
"aldarien/session" : "*",
"aldarien/url": "*",
"j4mie/paris" : "^1.5",
"danielstjules/stringy" : "^3.1",
"phpoffice/phpspreadsheet": "1-beta",
"aldarien/url": "dev-master",
"nesbot/carbon": "^2",
"phpoffice/phpword": "^0.14.0",
"slam/php-excel": "^4.4",
"fabpot/goutte": "^3.2",
"incoviba/modelos": "dev-master",
"incoviba/modelos": "*",
"slim/slim": "4.x-dev",
"php-di/slim-bridge": "dev-master",
"rubellum/slim-blade-view": "dev-master",
"nyholm/psr7": "1.4.x-dev",
"nyholm/psr7-server": "dev-master"
"nyholm/psr7-server": "dev-master",
"vlucas/phpdotenv": "^5.3"
},
"require-dev" : {
"phpunit/phpunit" : "^6.3",
@ -51,15 +52,12 @@
"type": "path",
"url": "./aldarien/**",
"options": {
"symlink": false
}
"symlink": false
}
},
{
"type": "path",
"url": "./incoviba/modelos",
"options": {
"symlink": false
}
"url": "./incoviba/modelos"
}
]
}

View File

@ -1,11 +1,13 @@
<?php
include_once dirname(__DIR__) . '/bootstrap/dotenv.php';
return [
'mysql' => [
'host' => 'localhost',
'host' => $_ENV['MYSQL_HOST'],
//'port' => 3306,
'database' => 'incoviba',
'username' => 'incoviba',
'password' => '5GQYFvRjVw2A4KcD'
'database' => $_ENV['MYSQL_DATABASE'],
'username' => $_ENV['MYSQL_USER'],
'password' => $_ENV['MYSQL_PASSWORD']
],
'mysql_copy' => [
'host' => 'localhost',

View File

@ -13,8 +13,6 @@ services:
php:
build: .
container_name: php
ports:
- 9123:9000
volumes:
- .:/code
@ -22,8 +20,6 @@ services:
container_name: db
image: mariadb:latest
restart: unless-stopped
ports:
- 3308:3306
env_file: .db.env
volumes:
- dbdata:/var/lib/mysql

View File

@ -20,5 +20,10 @@ class Escritura extends Model
{
return $this->belongs_to(Pago::class, 'pago')->findOne();
}
public function valor(string $tipo = 'pesos')
{
return $this->pago()->valor($tipo);
}
}
?>

Submodule modules/operadores updated: 71e10c52bd...4f7241e146

View File

@ -5,32 +5,32 @@ use DI\Bridge\Slim\Bridge;
include_once 'composer.php';
$folders = [
'env',
'common',
$__environment
];
$files = [
'config',
'settings',
'setups'
];
$builder = new Builder();
foreach ($files as $file) {
foreach ($folders as $folder) {
$filename = implode(DIRECTORY_SEPARATOR, [
__DIR__,
$folder,
$file . '.php'
]);
if (!file_exists($filename)) {
foreach ($folders as $f) {
$folder = implode(DIRECTORY_SEPARATOR, [
__DIR__,
$f
]);
if (!file_exists($folder)) {
continue;
}
$files = new DirectoryIterator($folder);
foreach ($files as $file) {
if ($file->isDir() or $file->getExtension() != 'php') {
continue;
}
$builder->addDefinitions($filename);
$builder->addDefinitions($file->getRealPath());
}
}
$container = $builder->build();
$app = Bridge::create($container);
$app->setBasePath($app->getContainer()->get('base_url'));
if ($app->getContainer()->has('base_url') and $app->getContainer()->get('base_url') != '') {
$app->setBasePath($app->getContainer()->get('base_url'));
}
$app->addRoutingMiddleware();
foreach ($folders as $folder) {

View File

@ -10,11 +10,11 @@ return [
'databases' => function() {
$arr = [
'mysql' => [
'host' => 'localhost',
'host' => $_ENV['MYSQL_HOST'],
//'port' => 3306,
'database' => 'incoviba',
'username' => 'incoviba',
'password' => '5GQYFvRjVw2A4KcD'
'database' => $_ENV['MYSQL_DATABASE'],
'username' => $_ENV['MYSQL_USER'],
'password' => $_ENV['MYSQL_PASSWORD']
],
'mysql_copy' => [
'host' => 'localhost',

16
setup/env/config.php vendored
View File

@ -1,6 +1,18 @@
<?php
use Dotenv\Dotenv;
$folder = dirname(__DIR__, 2);
$files = new DirectoryIterator($folder);
foreach ($files as $file) {
if ($file->isDir() or $file->getExtension() != 'env') {
continue;
}
$env = Dotenv::createImmutable($file->getPath(), $file->getBasename());
$env->load();
}
return [
'debug' => false,
'debug' => $_ENV['DEBUG'] ?? false,
'benchmark' => false,
'base_url' => '/incoviba'
'base_url' => $_ENV['BASE_URL']//'/incoviba'
];

18
setup/settings/01_env.php Normal file
View File

@ -0,0 +1,18 @@
<?php
use Dotenv\Dotenv;
$folder = dirname(__DIR__, 2);
$files = new DirectoryIterator($folder);
foreach ($files as $file) {
if ($file->isDir() or $file->getExtension() != 'env') {
continue;
}
$env = Dotenv::createImmutable($file->getPath(), $file->getBasename());
$env->load();
}
return [
'debug' => $_ENV['DEBUG'] ?? false,
'benchmark' => false,
'base_url' => $_ENV['BASE_URL'] ?? '/incoviba'
];

View File

@ -0,0 +1,40 @@
<?php
return [
'timezone' => 'America/Santiago',
'locale' => 'es',
'database' => 'mysql',
'login_hours' => 5*24,
'cierres' => [
'caducidad' => 30
],
'databases' => function() {
$arr = [
'mysql' => [
'host' => $_ENV['MYSQL_HOST'],
//'port' => 3306,
'database' => $_ENV['MYSQL_DATABASE'],
'username' => $_ENV['MYSQL_USER'],
'password' => $_ENV['MYSQL_PASSWORD']
],
'mysql_copy' => [
'host' => 'localhost',
'database' => 'incoviba3',
'username' => 'incoviba',
'password' => '5GQYFvRjVw2A4KcD'
]
];
return $arr;
},
'locations' => function() {
$arr = ['base' => dirname(__DIR__, 2)];
$arr['public'] = $arr['base'] . '/public';
$arr['resources'] = $arr['base'] . '/resources';
$arr['routes'] = $arr['resources'] . '/routes';
$arr['src'] = $arr['base'] . '/src';
$arr['app'] = $arr['base'] . '/app';
$arr['controllers'] = $arr['app'] . '/Controller';
$arr['money'] = 'http://provm.cl/optimus/money';
$arr['api'] = 'http://localhost:8080/api';
return (object) $arr;
}
];

View File

@ -0,0 +1,8 @@
<?php
use Psr\Container\ContainerInterface as Container;
return [
'base_url' => DI\decorate(function($prev, Container $c) {
return $prev . '/api';
})
];

11
setup/settings/04_ui.php Normal file
View File

@ -0,0 +1,11 @@
<?php
use Psr\Container\ContainerInterface as Container;
return [
'locations' => DI\decorate(function($prev, Container $c) {
$arr = (array) $prev;
$arr['cache'] = $prev->base . '/cache';
$arr['views'] = $prev->resources . '/views';
return (object) $arr;
})
];

15
setup/setups/04_ui.php Normal file
View File

@ -0,0 +1,15 @@
<?php
use Psr\Container\ContainerInterface as Container;
return [
Slim\Views\Blade::class => function(Container $c) {
return new Slim\Views\Blade(
$c->get('locations')->views,
$c->get('locations')->cache,
null,
[
'locations' => $c->get('locations')
]
);
}
];