47 Commits

Author SHA1 Message Date
a33dd341cd Facturacion 2024-04-15 20:13:15 -04:00
8e4b5eaaf8 Listado de Movimientos 2024-04-10 21:18:33 -04:00
91679b164f DAP y saldo anterior 2024-04-05 20:23:58 -03:00
3c7e4b9ef4 Orden sociedades 2024-04-05 17:13:21 -03:00
20045c9a64 Formatos 2024-04-05 16:35:18 -03:00
47d43f504d Informes anteriores y siguientes 2024-04-05 14:48:17 -03:00
0502b8e735 agentes -> proveedores 2024-04-05 14:45:54 -03:00
905e8263bc Login redirect 307 (temporary) 2024-04-03 13:26:12 -03:00
8710c8a111 Agentes 2024-04-02 23:02:52 -03:00
5d9ac2bc51 Tests results in cache 2024-04-02 20:19:59 -03:00
062e0543e4 Ignore app/bin 2024-04-02 19:58:58 -03:00
b97916cfc4 Menu 2024-04-02 19:04:57 -03:00
7af9cafdb6 Moderno 2024-04-02 19:04:26 -03:00
84a2fbd119 Log DB 2024-04-02 13:50:08 -03:00
bc9c71870c No remove nocache 2024-03-26 17:09:43 -03:00
912e8624b2 Nocache after ready 2024-03-26 16:57:07 -03:00
86406bf027 Fecha cuota 2024-03-26 16:41:33 -03:00
7b8d44e8c8 Reordenar 2024-03-26 13:59:18 -03:00
c10f2e5912 Cuotas con detalle de UF y de Pies asociados 2024-03-26 13:21:47 -03:00
bef0a22758 Bin folder 2024-03-26 13:17:08 -03:00
092eb95f06 Cache phpunit 2024-03-26 09:38:35 -03:00
5f56022109 Restructura contabilidad 2024-03-26 09:38:20 -03:00
4b3397dd63 Estado cuenta 2024-03-21 23:10:18 -03:00
529f9e32a1 Inmobiliarias por razon y cuadratura 2024-03-21 22:09:15 -03:00
939adf126f FIX: multiples cartolas 2024-03-21 22:08:30 -03:00
63400af1db Cartola diaria adds all cartolas 2024-03-21 21:57:32 -03:00
019974614c FIX: Saldos cartola diaria 2024-03-21 21:18:40 -03:00
735c341729 FIX: Login, change in separator defined 2024-03-20 23:29:09 -03:00
444ff687fc Base API, and more solid key and check 2024-03-20 23:07:49 -03:00
f3a5fa2cdc Tests 2024-03-20 23:06:38 -03:00
2ed265dcf1 Merge branch 'testing' into develop 2024-03-20 21:11:32 -03:00
dbae630fdd Bold footer 2024-03-20 21:04:43 -03:00
d69976d015 FIX: Remove cache from login when redirecting 2024-03-20 20:55:34 -03:00
2ccbc31ae0 FIX: Auth had all paths starting with slash as valid 2024-03-20 20:48:05 -03:00
e50d80560c FIX: Auth missing from some routes 2024-03-20 20:43:53 -03:00
7cc0333876 Informe tesoreria busca ultima cartola ingresada 2024-03-20 20:22:54 -03:00
eb38236926 FIX: cartola BCI 2024-03-20 17:52:34 -03:00
85ef4dd60e Ignore testing cache 2024-03-20 15:00:54 -03:00
f1e29e3b0b Ignore testing results 2024-03-20 13:50:04 -03:00
6617a92f5f Tests 2024-03-20 13:49:58 -03:00
ca958b8a88 Testing dependencies 2024-03-20 13:45:53 -03:00
dc2e2c7f71 Cartola BCI 2024-03-18 17:54:27 -03:00
936fd2d1e1 Cuota vacia 2024-03-18 18:06:32 +00:00
7c6a397e31 CORS 2024-03-18 14:58:54 -03:00
7385225a2e FIX: Venta cargada sin formaPago 2024-03-15 13:09:58 -03:00
9c335fd350 FIX: Venta 2024-03-13 22:43:37 -03:00
57f9169cc7 Encriptar clave 2024-03-13 21:24:52 -03:00
140 changed files with 2547 additions and 579 deletions

2
.gitignore vendored
View File

@ -10,3 +10,5 @@
**/.idea/
**/upload?/
**/informe?/
**/.phpunit.cache/
**/coverage/

View File

@ -9,6 +9,7 @@ RUN pecl install xdebug-3.1.3 \
&& docker-php-ext-enable xdebug
COPY ./php-errors.ini /usr/local/etc/php/conf.d/docker-php-errors.ini
COPY ./php-xdebug.ini /usr/local/etc/php/conf.d/docker-php-xdebug.ini
COPY --from=composer /usr/bin/composer /usr/bin/composer

1
app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**/bin

13
app/.phpunit-watcher.yml Normal file
View File

@ -0,0 +1,13 @@
watch:
directories:
- src
- tests
- common
fileMask: '*.php'
notifications:
passingTests: false
failingTests: false
hideManual: true
phpunit:
arguments: '--log-events-text /logs/output.txt --stop-on-failure'
timeout: 180

View File

@ -5,6 +5,11 @@ use Psr\Http\Message\UploadedFileInterface;
interface Banco
{
/**
* Process bank movements for database inserts
* @param UploadedFileInterface $file
* @return array
*/
public function process(UploadedFileInterface $file): array;
}

View File

@ -6,5 +6,5 @@ use Incoviba\Model;
interface Exporter
{
public function export(Model\Inmobiliaria $inmobiliaria, Model\Banco $banco, DateTimeInterface $mes, array $movimientos): string;
public function export(Model\Inmobiliaria $inmobiliaria, Model\Contabilidad\Banco $banco, DateTimeInterface $mes, array $movimientos): string;
}

View File

@ -9,7 +9,7 @@ abstract class Banco extends Service implements Define\Cartola\Banco
{
public function process(UploadedFileInterface $file): array
{
$data = $this->parseFile($file);
$data = $this->handleFile($file);
$temp = [];
$columns = $this->columnMap();
foreach ($data as $row) {
@ -24,11 +24,48 @@ abstract class Banco extends Service implements Define\Cartola\Banco
}
return $temp;
}
/**
* There are banks that need some post-processing
* @param array $movimientos
* @return array
*/
public function processMovimientosDiarios(array $movimientos): array
{
return $movimientos;
}
/**
* Move the UploadedFile into a temp file from getFilename and after parseFile remove temp file
* @param UploadedFileInterface $uploadedFile
* @return array
*/
protected function handleFile(UploadedFileInterface $uploadedFile): array
{
$filename = $this->getFilename($uploadedFile);
$uploadedFile->moveTo($filename);
$data = $this->parseFile($filename);
unlink($filename);
return $data;
}
/**
* Get filename where to move UploadedFile
* @param UploadedFileInterface $uploadedFile
* @return string
*/
abstract protected function getFilename(UploadedFileInterface $uploadedFile): string;
/**
* Mapping of uploaded file data columns to database columns
* @return array
*/
abstract protected function columnMap(): array;
abstract protected function parseFile(UploadedFileInterface $uploadedFile): array;
/**
* Translate uploaded file data to database data
* @param string $filename
* @return array
*/
abstract protected function parseFile(string $filename): array;
}

View File

@ -0,0 +1,60 @@
<?php
namespace Incoviba\Common\Implement\Log;
use PDOStatement;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\LogRecord;
use Monolog\Level;
use Incoviba\Common\Define\Connection;
class MySQLHandler extends AbstractProcessingHandler
{
private bool $initialized = false;
private PDOStatement $statement;
public function __construct(protected Connection $connection, int|string|Level $level = Level::Debug, bool $bubble = true)
{
parent::__construct($level, $bubble);
}
public function write(LogRecord $record): void
{
if (!$this->initialized) {
$this->initialized();
}
$this->cleanup();
$this->statement->execute([
'channel' => $record->channel,
'level' => $record->level->getName(),
'message' => $record->formatted,
'time' => $record->datetime->format('Y-m-d H:i:s.u'),
'context' => (count($record->context) > 0) ? json_encode($record->context, JSON_UNESCAPED_SLASHES) : '',
'extra' => (count($record->extra) > 0) ? json_encode($record->extra, JSON_UNESCAPED_SLASHES) : ''
]);
}
private function initialized(): void
{
$query = <<<QUERY
CREATE TABLE IF NOT EXISTS monolog (
channel VARCHAR(255),
level VARCHAR(100),
message LONGTEXT,
time DATETIME,
context LONGTEXT,
extra LONGTEXT
)
QUERY;
$this->connection->getPDO()->exec($query);
$query = <<<QUERY
INSERT INTO monolog (channel, level, message, time, context, extra)
VALUES (:channel, :level, :message, :time, :context, :extra)
QUERY;
$this->statement = $this->connection->getPDO()->prepare($query);
$this->initialized = true;
}
private function cleanup(): void
{
$query = "DELETE FROM monolog WHERE time < DATE_SUB(CURDATE(), INTERVAL 90 DAY)";
$this->connection->query($query);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Incoviba\Common\Implement\Log;
use Monolog\Formatter\JsonFormatter;
use Monolog\LogRecord;
class PDOFormatter extends JsonFormatter
{
public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = false, bool $ignoreEmptyContextAndExtra = false, bool $includeStacktraces = true)
{
parent::__construct($batchMode, $appendNewline, $ignoreEmptyContextAndExtra, $includeStacktraces);
}
public function format(LogRecord $record): string
{
$normalized = $this->normalize($record);
return $normalized['message'];
}
}

View File

@ -1,8 +1,12 @@
{
"name": "incoviba/web",
"version": "2.0.0",
"type": "project",
"require": {
"berrnd/slim-blade-view": "^1.0",
"ext-gd": "*",
"ext-openssl": "*",
"ext-pdo": "*",
"guzzlehttp/guzzle": "^7.8",
"monolog/monolog": "^3.4",
"nyholm/psr7": "^1.8",
@ -14,8 +18,10 @@
"slim/slim": "^4.11"
},
"require-dev": {
"fakerphp/faker": "^1.23",
"kint-php/kint": "^5.1",
"phpunit/phpunit": "^10.2"
"phpunit/phpunit": "^10.2",
"spatie/phpunit-watcher": "^1.23"
},
"authors": [
{
@ -30,6 +36,8 @@
}
},
"config": {
"sort-packages": true
"sort-packages": true,
"process-timeout": 0,
"bin-dir": "bin"
}
}

43
app/phpunit.xml Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
cacheDirectory="/code/cache/tests"
executionOrder="depends,defects"
requireCoverageMetadata="false"
beStrictAboutCoverageMetadata="false"
beStrictAboutOutputDuringTests="true"
colors="true"
failOnRisky="false"
failOnWarning="false">
<testsuites>
<testsuite name="unit">
<directory>tests/units</directory>
</testsuite>
<testsuite name="acceptance">
<directory>tests/integration</directory>
</testsuite>
<testsuite name="performance">
<directory>tests/performance</directory>
</testsuite>
</testsuites>
<source restrictDeprecations="true" restrictNotices="true" restrictWarnings="true">
<include>
<directory>src</directory>
<directory>common</directory>
</include>
</source>
<coverage includeUncoveredFiles="true" pathCoverage="false" ignoreDeprecatedCodeUnits="true" disableCodeCoverageIgnore="true">
<report>
<html outputDirectory="/code/public/coverage/html" />
<php outputFile="/code/public/coverage/coverage.php" />
</report>
</coverage>
<logging>
<junit outputFile="/code/cache/tests/junit.xml" />
<teamcity outputFile="/code/cache/tests/teamcity.txt" />
<testdoxHtml outputFile="/code/cache/tests/testdox.html" />
<testdoxText outputFile="/code/cache/tests/testdox.txt" />
</logging>
</phpunit>

View File

@ -1,4 +1,6 @@
<?php
use Incoviba\Controller\API\Base;
$app->group('/api', function($app) {
$folder = implode(DIRECTORY_SEPARATOR, [__DIR__, 'api']);
if (file_exists($folder)) {
@ -10,4 +12,5 @@ $app->group('/api', function($app) {
include_once $file->getRealPath();
}
}
$app->get('[/]', Base::class);
})->add($app->getContainer()->get(Incoviba\Middleware\API::class));

View File

@ -1,5 +1,6 @@
<?php
use Incoviba\Controller\API\CentrosCostos;
use Incoviba\Controller\API\Contabilidad\CentrosCostos;
$app->group('/centros_costos', function($app) {
$app->post('/add[/]', [CentrosCostos::class, 'add']);

View File

@ -1,6 +1,10 @@
<?php
use Incoviba\Controller\API\Contabilidad\Movimientos;
$app->group('/movimientos', function($app) {
$app->post('/segment', [Movimientos::class, 'segment']);
$app->get('[/]', Movimientos::class);
});
$app->group('/movimiento/{movimiento_id}', function($app) {
$app->post('/detalles', [Movimientos::class, 'detalles']);
});

View File

@ -1,5 +1,6 @@
<?php
use Incoviba\Controller\API\Nubox;
use Incoviba\Controller\API\Contabilidad\Nubox;
$app->group('/nubox/{inmobiliaria_rut}', function($app) {
$app->get('/token[/]', [Nubox::class, 'token']);

View File

@ -2,9 +2,20 @@
use Incoviba\Controller\API\Inmobiliarias;
$app->group('/inmobiliarias', function($app) {
$folder = implode(DIRECTORY_SEPARATOR, [__DIR__, 'inmobiliarias']);
if (file_exists($folder)) {
$files = new FilesystemIterator($folder);
foreach ($files as $file) {
if ($file->isDir()) {
continue;
}
include_once $file->getRealPath();
}
}
$app->get('[/]', Inmobiliarias::class);
});
$app->group('/inmobiliaria/{inmobiliaria_rut}', function($app) {
$app->post('/agentes', [Inmobiliarias::class, 'agentes']);
$app->get('/cuentas[/]', [Inmobiliarias::class, 'cuentas']);
$app->get('/proyectos[/]', [Inmobiliarias::class, 'proyectos']);
});

View File

@ -0,0 +1,11 @@
<?php
use Incoviba\Controller\API\Inmobiliarias\Agentes;
$app->group('/agentes', function($app) {
$app->post('/add[/]', [Agentes::class, 'add']);
$app->post('/register[/]', [Agentes::class, 'register']);
$app->get('[/]', Agentes::class);
});
$app->group('/agente/{agente_id}', function($app) {
$app->post('/edit[/]', [Agentes::class, 'edit']);
});

View File

@ -1,5 +1,6 @@
<?php
use Incoviba\Controller\CentrosCostos;
use Incoviba\Controller\Contabilidad\CentrosCostos;
$app->group('/centros_costos', function($app) {
$app->get('/asignar[/]', [CentrosCostos::class, 'asignar']);

View File

@ -0,0 +1,4 @@
<?php
use Incoviba\Controller\Contabilidad\Movimientos;
$app->get('/movimientos', Movimientos::class);

View File

@ -14,9 +14,10 @@
<i class="dropdown icon"></i>
<div class="default text">Inmobiliaria</div>
<div class="menu">
@foreach ($inmobiliarias as $inmobiliaria)
<div class="item" data-value="{{$inmobiliaria->rut}}">{{$inmobiliaria->razon}}</div>
@endforeach
@foreach ($inmobiliarias as $inmobiliaria)
<div class="item"
data-value="{{$inmobiliaria->rut}}">{{$inmobiliaria->razon}}</div>
@endforeach
</div>
</div>
</div>
@ -40,7 +41,7 @@
</div>
<div class="field">
<label for="file">Cartola</label>
<input type="file" name="file" id="file" class="ui invisible file input" />
<input type="file" name="file" id="file" class="ui invisible file input"/>
<label for="file" class="ui icon button">
<i class="file icon"></i>
Cargar
@ -119,20 +120,20 @@
mes: '',
movimientos: [],
centrosCostos: {
ingresos: JSON.parse('{!! json_encode(array_values(array_map(function(\Incoviba\Model\CentroCosto $centroCosto) {
ingresos: JSON.parse('{!! json_encode(array_values(array_map(function(\Incoviba\Model\Contabilidad\CentroCosto $centroCosto) {
return [
'id' => $centroCosto->id,
'descripcion' => $centroCosto->descripcion
];
}, array_filter($centrosCostos, function(\Incoviba\Model\CentroCosto $centroCosto) {
}, array_filter($centrosCostos, function(\Incoviba\Model\Contabilidad\CentroCosto $centroCosto) {
return $centroCosto->tipoCentro->descripcion === 'Ingreso';
})))) !!}'),
egresos: JSON.parse('{!! json_encode(array_values(array_map(function(\Incoviba\Model\CentroCosto $centroCosto) {
egresos: JSON.parse('{!! json_encode(array_values(array_map(function(\Incoviba\Model\Contabilidad\CentroCosto $centroCosto) {
return [
'id' => $centroCosto->id,
'descripcion' => $centroCosto->descripcion
];
}, array_filter($centrosCostos, function(\Incoviba\Model\CentroCosto $centroCosto) {
}, array_filter($centrosCostos, function(\Incoviba\Model\Contabilidad\CentroCosto $centroCosto) {
return $centroCosto->tipoCentro->descripcion === 'Egreso';
})))) !!}'),
}
@ -170,7 +171,11 @@
return
}
$(this.ids.form.banco).dropdown('change values', json.cuentas.map(cuenta => {
return {value: cuenta.banco.id, text: cuenta.banco.nombre, name: cuenta.banco.nombre}
return {
value: cuenta.banco.id,
text: cuenta.banco.nombre,
name: cuenta.banco.nombre
}
})).dropdown('refresh')
})
})
@ -247,12 +252,12 @@
const movimientos = this.data.movimientos.map((movimiento, idx) => {
const temp = structuredClone(movimiento)
temp.fecha = movimiento.fecha.toISOString()
let centro = $(".centro[data-index='" + (idx+1) + "']").dropdown('get value')
let centro = $(".centro[data-index='" + (idx + 1) + "']").dropdown('get value')
if (centro.length === 0) {
centro = ''
}
temp.centro_costo = centro
let detalle = $("[name='detalle" + (idx+1) + "']").val()
let detalle = $("[name='detalle" + (idx + 1) + "']").val()
if (typeof detalle === 'undefined') {
detalle = ''
}
@ -294,7 +299,10 @@
month: 'numeric',
day: 'numeric'
})
const numberFormatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 0, maximumFractionDigits: 0})
const numberFormatter = new Intl.NumberFormat('es-CL', {
minimumFractionDigits: 0,
maximumFractionDigits: 0
})
this.data.movimientos.forEach((row, idx) => {
tbody.append(
$('<tr></tr>').append(
@ -322,7 +330,7 @@
})
table.DataTable(this.dataTableConfig)
},
centrosDropdown: (idx, ingreso=true) => {
centrosDropdown: (idx, ingreso = true) => {
const menu = $('<div></div>').addClass('menu')
let centros = this.data.centrosCostos.ingresos
if (!ingreso) {

View File

@ -1,5 +1,13 @@
@extends('layout.base')
@push('page_styles')
<style>
tr.bold>th {
font-weight: bold !important;
}
</style>
@endpush
@section('page_content')
<div class="ui container">
<h1 class="ui centered header">Informe de Tesorería</h1>
@ -19,7 +27,11 @@
<table class="ui collapsing simple table">
<tr>
<td>Informe anterior</td>
<td>{{$anterior->format('d/m/Y')}}</td>
<td>
<a href="{{$urls->base}}/contabilidad/informes/tesoreria/{{$anterior->format('Y-m-d')}}">
{{$anterior->format('d/m/Y')}}
</a>
</td>
</tr>
<tr>
<td>Informe actual</td>
@ -40,6 +52,17 @@
</tr>
</table>
</div>
@if ($siguiente !== null)
<div class="five wide column"></div>
<div class="right aligned two wide column">
<div class="ui segment">
Siguiente
<a href="{{$urls->base}}/contabilidad/informes/tesoreria/{{$siguiente->format('Y-m-d')}}">
{{$siguiente->format('d/m/Y')}} >>
</a>
</div>
</div>
@endif
</div>
<table class="ui striped table">
<thead>

View File

@ -0,0 +1,160 @@
@extends('layout.base')
@section('page_content')
<div class="ui container">
<h1 class="ui header">Movimientos Contables</h1>
</div>
<table id="tabla_movimientos" class="ui table">
<thead>
<tr>
<th>Sociedad</th>
<th>Banco - Cuenta</th>
<th>Fecha</th>
<th>ISO Fecha</th>
<th class="right aligned">Valor</th>
<th>Valor</th>
<th>Centro de Costo</th>
<th>Glosa</th>
<th>Detalle</th>
</tr>
</thead>
<tbody id="movimientos"></tbody>
</table>
@endsection
@include('layout.head.styles.datatables')
@include('layout.head.styles.datatables.searchbuilder')
@include('layout.head.styles.datatables.buttons')
@include('layout.body.scripts.datatables')
@include('layout.body.scripts.datatables.searchbuilder')
@include('layout.body.scripts.datatables.buttons')
@push('page_scripts')
<script>
function getData(table_id, from, amount) {
const url = '{{$urls->api}}/contabilidad/movimientos'
const movimientos = []
return fetchAPI(url).then(response => {
if (!response) {
return
}
response.json().then(json => {
if (json.movimientos.length === 0) {
return
}
const formatter = new Intl.NumberFormat('es-CL')
const dateFormatter = new Intl.DateTimeFormat('es-CL', {day: '2-digit', month: '2-digit', year: 'numeric'})
json.movimientos.forEach(movimiento => {
const fecha = new Date(movimiento.fecha)
const valor = movimiento.abono - movimiento.cargo
movimientos.push([
movimiento.cuenta.inmobiliaria.razon,
movimiento.cuenta.banco.nombre + ' - ' + movimiento.cuenta.cuenta,
dateFormatter.format(fecha),
fecha.toISOString(),
formatter.format(valor),
valor,
(movimiento.detalles) ? movimiento.detalles.centro_costo.id + ' - ' + movimiento.detalles.centro_costo.descripcion : '',
movimiento.glosa,
(movimiento.detalles) ? movimiento.detalles.detalle : ''
])
})
}).then(() => {
const table = new DataTable(table_id, {
columnDefs: [
{targets: 3, visible: false},
{targets: 4, className: 'dt-right'},
{targets: 5, visible: false}
],
order: [[3, 'asc']],
language: {
info: 'Mostrando página _PAGE_ de _PAGES_',
infoEmpty: 'No hay cuotas ingresadas',
infoFiltered: '(filtrado de _MAX_ cuotas)',
lengthMenu: 'Mostrando de a _MENU_ cuotas',
zeroRecords: 'No se encotró cuotas con ese criterio',
search: 'Buscar: ',
searchBuilder: {
add: 'Filtrar',
condition: 'Comparador',
clearAll: 'Resetear',
delete: 'Eliminar',
deleteTitle: 'Eliminar Titulo',
data: 'Columna',
left: 'Izquierda',
leftTitle: 'Titulo Izquierdo',
logicAnd: 'Y',
logicOr: 'O',
right: 'Derecha',
rightTitle: 'Titulo Derecho',
title: {
0: 'Filtros',
_: 'Filtros (%d)'
},
value: 'Opciones',
valueJoiner: 'y'
}
},
layout: {
top1: {
searchBuilder: {
columns: [0, 1, 2, 4, 6, 7, 8]
}
},
top1End: {
buttons: [
{
extend: 'excelHtml5',
className: 'green',
text: 'Exportar a Excel <i class="file excel icon"></i>',
title: 'Movimientos Contables',
download: 'open',
exportOptions: {
columns: [0, 1, 2, 5, 6, 7, 8]
}
}
]
}
},
data: movimientos,
})
})
})
}
function updateTable(table, from, amount) {
const url = '{{$urls->api}}/contabilidad/movimientos'
return fetchAPI(url).then(response => {
if (!response) {
return
}
response.json().then(json => {
if (json.movimientos.length === 0) {
return
}
table.clear()
const formatter = new Intl.NumberFormat('es-CL')
const dateFormatter = new Intl.DateTimeFormat('es-CL', {day: '2-digit', month: '2-digit', year: 'numeric'})
json.movimientos.forEach(movimiento => {
const fecha = new Date(movimiento.fecha)
table.row.add([
movimiento.cuenta.inmobiliaria.razon,
movimiento.cuenta.banco.nombre + ' - ' + movimiento.cuenta.cuenta,
dateFormatter.format(fecha),
fecha.toISOString(),
formatter.format(movimiento.abono - movimiento.cargo),
(movimiento.detalles) ? movimiento.detalles.centro_costo.id + ' - ' + movimiento.detalles.centro_costo.descripcion : '',
movimiento.glosa,
(movimiento.detalles) ? movimiento.detalles.detalle : ''
])
})
}).then(() => {
table.draw()
})
})
}
$(document).ready(() => {
getData('#tabla_movimientos', 0, 100)
})
</script>
@endpush

View File

@ -10,11 +10,6 @@
<div class="column">
Inmobiliarias
</div>
{{--<div class="right aligned column">
<button class="ui icon button" type="button">
<i class="plus icon"></i>
</button>
</div>--}}
</h2>
<div class="ui divider"></div>
<div class="ui cards">
@ -22,9 +17,7 @@
<div class="ui card">
<div class="content">
<div class="header">
{{$inmobiliaria->abreviacion}}
{{--<a href="{{$urls->base}}/inmobiliaria/{{$inmobiliaria->rut}}">
</a>--}}
{{$inmobiliaria->abreviacion}}
</div>
<div class="description">{{$inmobiliaria->razon}} {{$inmobiliaria->tipoSociedad->descripcion}}</div>
<div class="meta">{{$inmobiliaria->rut()}}</div>

View File

@ -18,5 +18,6 @@
</div>
<a class="item" href="{{$urls->base}}/contabilidad/cartolas/diaria">Cartola Diaria</a>
<a class="item" href="{{$urls->base}}/contabilidad/depositos">Depósitos a Plazo</a>
<a class="item" href="{{$urls->base}}/contabilidad/movimientos">Movimientos</a>
</div>
</div>

View File

@ -10,7 +10,7 @@
options['headers'] = {}
}
if (!Object.hasOwn(options['headers'], 'Authorization')) {
options['headers']['Authorization'] = 'Bearer {{md5($API_KEY)}}'
options['headers']['Authorization'] = 'Bearer {{md5($API_KEY)}}{{($login->isIn()) ? $login->getSeparator() . $login->getToken() : ''}}'
}
return fetch(url, options).then(response => {
if (response.ok) {

View File

@ -0,0 +1,3 @@
@push('page_scripts')
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js" integrity="sha512-a+SUDuwNzXDvz4XrIcXHuCf089/iJAoN4lmrXJg18XnduKK6YlDHNRalv4yd1N40OKI80tFidF+rqTFKGPoWFQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
@endpush

View File

@ -1,5 +1,4 @@
@push('page_scripts')
{{--<script type="text/javascript" src="https://cdn.datatables.net/2.0.1/js/jquery.dataTables.min.js"></script>--}}
<script type="text/javascript" src="https://cdn.datatables.net/2.0.1/js/dataTables.min.js"></script>
<script src="https://cdn.datatables.net/2.0.1/js/dataTables.semanticui.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/2.0.3/js/dataTables.min.js"></script>
<script src="https://cdn.datatables.net/2.0.3/js/dataTables.semanticui.min.js"></script>
@endpush

View File

@ -1,9 +1,9 @@
@push('page_scripts')
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/pdfmake.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.datatables.net/buttons/3.0.0/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.0/js/buttons.semanticui.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.0/js/buttons.colVis.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.0/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.0/js/buttons.print.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.1/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.1/js/buttons.semanticui.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.1/js/buttons.colVis.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.1/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.0.1/js/buttons.print.min.js"></script>
@endpush

View File

@ -0,0 +1,5 @@
@push('page_scripts')
<script src="https://cdn.datatables.net/datetime/1.5.2/js/dataTables.dateTime.min.js"></script>
<script src="https://cdn.datatables.net/searchbuilder/1.7.0/js/dataTables.searchBuilder.min.js"></script>
<script src="https://cdn.datatables.net/searchbuilder/1.7.0/js/searchBuilder.semanticui.js"></script>
@endpush

View File

@ -1,3 +1,3 @@
@push('page_styles')
<link rel="stylesheet" href="https://cdn.datatables.net/2.0.1/css/dataTables.semanticui.min.css" />
<link rel="stylesheet" href="https://cdn.datatables.net/2.0.3/css/dataTables.semanticui.min.css" />
@endpush

View File

@ -0,0 +1,4 @@
@push('page_styles')
<link rel="stylesheet" href="https://cdn.datatables.net/datetime/1.5.2/css/dataTables.dateTime.min.css" />
<link rel="stylesheet" href="https://cdn.datatables.net/searchbuilder/1.7.0/css/searchBuilder.dataTables.min.css" />
@endpush

View File

@ -16,29 +16,30 @@
</div>
@endsection
@include('layout.body.scripts.cryptojs')
@push('page_scripts')
<script type="text/javascript">
function encryptPassword(password) {
const passphrase = Math.floor(Math.random() * Date.now()).toString()
const encrypted = CryptoJS.AES.encrypt(password, passphrase)
return [passphrase, encrypted.toString()].join('')
}
function sendLogin(name, password) {
const data = new FormData()
data.append('name', name)
data.append('password', password)
return fetch('{{$urls->base}}/login', {
method: 'post',
headers: {
Accept: 'json'
},
body: data
}).then(response => {
const method = 'post'
const headers = {
Accept: 'json'
}
const body = new FormData()
body.append('name', name)
body.append('password', encryptPassword(password))
return fetch('{{$urls->base}}/login', {method, headers, body}).then(response => {
if (response.ok) {
return response.json()
}
}).then(data => {
if (data.login === true) {
@if(isset($redirect_uri))
window.location = '{{$redirect_uri}}'
@else
window.location = '{{$urls->base}}'
@endif
window.location = '{{(isset($redirect_uri)) ? $redirect_uri : $urls->base}}'
}
})
}

View File

@ -177,7 +177,7 @@
const cantidad = this.unidades.length
this.unidades.forEach(unidad => {
const values = [
venta,
'<a href="{{$urls->base}}/ventas/factura/' + this.id + '">' + venta + '</a>',
cantidad,
unidad.tipo,
unidad.descripcion,

View File

@ -184,8 +184,8 @@
totales: {},
proporcion: 1,
precio: {{$UF->transform($venta->currentEstado()->fecha, $venta->valor)}},
terreno: {{(isset($venta->proyecto()->terreno->fecha) and $venta->proyecto()->terreno->fecha >= $lastDic) ?
$IPC->readjust($venta->proyecto()->terreno->valor, $venta->proyecto()->terreno->fecha, $venta->currentEstado()->fecha) : 0}},
terreno: {{(isset($terreno->fecha) and $terreno->fecha >= $lastDic) ?
$IPC->readjust($terreno->valor, $terreno->fecha, $venta->currentEstado()->fecha) : 0}},
uf: {{$UF->get($venta->currentEstado()->fecha)}},
unidades: JSON.parse('{!! json_encode(array_map(function(Incoviba\Model\Venta\PropiedadUnidad $unidad) use ($venta, $UF, $format) {
$precio = ($unidad->valor > 0) ? $unidad->valor : ($unidad->precio($venta->currentEstado()->fecha) ? $unidad->precio($venta->currentEstado()->fecha)->valor : 0);

View File

@ -5,6 +5,29 @@
@endsection
@section('venta_content')
@if (count($asociadas) > 0)
<div class="ui grid">
<div class="two wide column">Asociados</div>
<div class="six wide column">
{!! implode(' - ', array_map(function(Incoviba\Model\Venta $venta) use ($urls) {
return "<a href=\"{$urls->base}/venta/{$venta->id}\">{$venta->propiedad()->departamentos()[0]->descripcion}</a>";
}, $asociadas)) !!}
</div>
</div>
@endif
<div class="ui grid">
<div class="column">Valor</div>
<div class="four wide column">
{{$format->ufs($venta->formaPago()->pie->valor)}}
@if (count($asociadas) > 0)
[{{$format->ufs($venta->formaPago()->pie->valor + array_reduce($asociadas, function(float $sum, Incoviba\Model\Venta $venta) {
return $sum + $venta->formaPago()->pie->valor;
}, 0.0))}}]
@endif
</div>
<div class="column">Cuotas</div>
<div class="column">{{$venta->formaPago()->pie->cuotas}}</div>
</div>
<table class="ui table" id="cuotas">
<thead>
<tr>
@ -37,32 +60,37 @@
<td>{{$cuota->pago->identificador}}</td>
<td class="right aligned">{{$format->pesos($cuota->pago->valor)}}</td>
<td class="right aligned">
@if ($cuota->pago->currentEstado->tipoEstadoPago->descripcion === 'abonado' and $cuota->pago->currentEstado->fecha <= $now)
@if (in_array($cuota->pago->currentEstado->tipoEstadoPago->descripcion, ['depositado', 'abonado'])
and $cuota->pago->currentEstado->fecha <= $now)
{{$format->ufs($cuota->pago->valor())}}
@else
~{{$format->ufs($cuota->pago->valor / $uf_venta)}}
@endif
</td>
<td
@if ($cuota->pago->currentEstado->tipoEstadoPago->descripcion === 'abonado')
class="green"
@elseif ($cuota->pago->currentEstado->tipoEstadoPago->descripcion === 'depositado')
class="yellow"
@elseif ($cuota->pago->currentEstado->tipoEstadoPago->activo !== 1)
class="red"
@endif
>{{ucwords($cuota->pago->currentEstado->tipoEstadoPago->descripcion)}}</td>
<td{!! ($cuota->pago->currentEstado->tipoEstadoPago->descripcion === 'abonado' ? ' class="green"' :
($cuota->pago->currentEstado->tipoEstadoPago->descripcion === 'depositado' ? ' class="yellow"' :
($cuota->pago->currentEstado->tipoEstadoPago->activo !== 1 ? ' class="red"' : ''))) !!}>
{{ucwords($cuota->pago->currentEstado->tipoEstadoPago->descripcion)}}
</td>
<td>
@if (in_array($cuota->pago->currentEstado->tipoEstadoPago->descripcion, ['abonado', 'anulado', 'reemplazado']))
{{$cuota->pago->currentEstado->fecha->format('d-m-Y')}}
@elseif (!in_array($cuota->pago->currentEstado->tipoEstadoPago->descripcion, ['anulado', 'reemplazado']))
@if ($cuota->pago->currentEstado->tipoEstadoPago->descripcion === 'depositado')
{{$cuota->pago->currentEstado->fecha->format('d-m-Y')}}
@endif
<div class="ui calendar fecha_estado" data-date="{{$cuota->pago->currentEstado->fecha->format('Y-m-d')}}">
<div class="ui action left icon input">
<i class="calendar icon"></i>
<input type="text" name="fecha_estado" />
<button class="ui green basic icon button accept_estado" data-pago="{{$cuota->pago->id}}" data-estado="{{$cuota->pago->currentEstado->tipoEstadoPago->descripcion}}">
<button class="ui green basic icon button accept_estado"
data-pago="{{$cuota->pago->id}}"
data-estado="{{$cuota->pago->currentEstado->tipoEstadoPago->descripcion}}">
<i class="check icon"></i>
</button>
@if ($cuota->pago->currentEstado->tipoEstadoPago->descripcion === 'depositado')
<button class="ui red basic icon button reject_estado" data-pago="{{$cuota->pago->id}}">
<button class="ui red basic icon button reject_estado"
data-pago="{{$cuota->pago->id}}">
<i class="remove icon"></i>
</button>
@endif
@ -115,7 +143,7 @@
}, 0.0))}}
</th>
<th class="right aligned">
{{$format->number($pagado / $total * 100, 2)}}%
{{$format->number(($total > 0) ? $pagado / $total * 100 : 0, 2)}}%
</th>
<th colspan="3"></th>
</tr>
@ -128,7 +156,7 @@
{{$format->ufs($total - $pagado)}}
</th>
<th class="right aligned">
{{$format->number(($total - $pagado) / $total * 100, 2)}}%
{{$format->number(($total > 0) ? ($total - $pagado) / $total * 100 : 0, 2)}}%
</th>
<th colspan="3"></th>
</tr>
@ -144,9 +172,10 @@
@push('page_scripts')
<script type="text/javascript">
$(document).ready(() => {
function updateRow({pago_id, fecha, color, estado, remove_fecha=false, add_reject=false, disable=false}) {
function updateRow({pago_id, valor, fecha, color, estado, remove_fecha=false, add_reject=false, disable=false}) {
const tr = $("tr[data-pago='" + pago_id + "']")
tr.find(':nth-child(6)').html(valor)
tr.find(':nth-child(7)').attr('class', color).html(estado)
if (remove_fecha) {
tr.find(':nth-child(8)').html(fecha)
@ -181,7 +210,7 @@
if (!json.depositado) {
return
}
updateRow({pago_id: json.pago_id, fecha: json.input.fecha, estado: 'Depositado', color: 'yellow', add_reject: true})
updateRow({pago_id: json.pago_id, valor: json.pago.valor_uf, fecha: json.input.fecha, estado: 'Depositado', color: 'yellow', add_reject: true})
button.attr('data-estado', 'depositado')
})
})
@ -189,7 +218,7 @@
function abonar(pago_id, fecha) {
const url = '{{$urls->api}}/ventas/pago/' + pago_id + '/abonar'
const body = new FormData()
body.set('fecha', fecha.toISOString())
body.set('fecha', [fecha.getFullYear(), fecha.getMonth() + 1, fecha.getDate()].join('-'))
return fetchAPI(url, {method: 'post', body}).then(response => {
if (!response) {
return

View File

@ -50,7 +50,7 @@
</td>
<td class="right aligned">
@if ($unidad->proyectoTipoUnidad->tipoUnidad->descripcion === 'departamento')
{{$format->number(($unidad->valor ?? $precio) / $unidad->proyectoTipoUnidad->vendible(), 2)}} UF/
{{$format->number((($unidad->valor === null or $unidad->valor === 0.0) ? $precio : $unidad->valor) / $unidad->proyectoTipoUnidad->vendible(), 2)}} UF/
@endif
</td>
<td class="center aligned">

View File

@ -1,2 +1,2 @@
<?php
//$app->add($app->getContainer()->get(Incoviba\Middleware\Authentication::class));
$app->add($app->getContainer()->get(Incoviba\Middleware\Authentication::class));

View File

@ -0,0 +1,2 @@
<?php
$app->add($app->getContainer()->get(Incoviba\Middleware\CORS::class));

View File

@ -4,18 +4,6 @@ use Psr\Container\ContainerInterface;
return [
Psr\Log\LoggerInterface::class => function(ContainerInterface $container) {
return new Monolog\Logger('incoviba', [
new Monolog\Handler\FilterHandler(
(new Monolog\Handler\RotatingFileHandler('/logs/debug.log', 10))
->setFormatter(new Monolog\Formatter\LineFormatter(null, null, false, false, true)),
Monolog\Level::Debug,
Monolog\Level::Debug
),
new Monolog\Handler\FilterHandler(
(new Monolog\Handler\RotatingFileHandler('/logs/info.log', 10))
->setFormatter(new Monolog\Formatter\LineFormatter(null, null, false, false, true)),
Monolog\Level::Info,
Monolog\Level::Warning,
),
new Monolog\Handler\FilterHandler(
(new Monolog\Handler\RotatingFileHandler('/logs/error.log', 10))
->setFormatter(new Monolog\Formatter\LineFormatter(null, null, false, false, true)),
@ -26,6 +14,17 @@ return [
(new Monolog\Handler\RotatingFileHandler('/logs/critical.log', 10))
->setFormatter(new Monolog\Formatter\LineFormatter(null, null, false, false, true)),
Monolog\Level::Critical
),
new Monolog\Handler\FilterHandler(
new Monolog\Handler\RedisHandler($container->get(Predis\ClientInterface::class), 'logs:notices'),
Monolog\Level::Notice,
Monolog\Level::Warning
),
new Monolog\Handler\FilterHandler(
(new Incoviba\Common\Implement\Log\MySQLHandler($container->get(Incoviba\Common\Define\Connection::class)))
->setFormatter(new Incoviba\Common\Implement\Log\PDOFormatter()),
Monolog\Level::Debug,
Monolog\Level::Warning
)
], [
$container->get(Monolog\Processor\PsrLogMessageProcessor::class),

View File

@ -14,6 +14,7 @@ return [
Incoviba\Middleware\API::class => function(ContainerInterface $container) {
return new Incoviba\Middleware\API(
$container->get(Psr\Http\Message\ResponseFactoryInterface::class),
$container->get(Incoviba\Service\Login::class),
$container->get('API_KEY')
);
}

View File

@ -9,7 +9,8 @@ return [
$container->get('COOKIE_NAME'),
$container->get('MAX_LOGIN_HOURS'),
$container->has('COOKIE_DOMAIN') ? $container->get('COOKIE_DOMAIN') : '',
$container->has('COOKIE_PATH') ? $container->get('COOKIE_PATH') : ''
$container->has('COOKIE_PATH') ? $container->get('COOKIE_PATH') : '',
$container->has('COOKIE_SEPARATOR') ? $container->get('COOKIE_SEPARATOR') : 'g'
);
},
Incoviba\Service\Money::class => function(ContainerInterface $container) {
@ -25,39 +26,40 @@ return [
->register('usd', $mindicador)
->register('ipc', $ine);
},
Predis\Client::class => function(ContainerInterface $container) {
Predis\ClientInterface::class => function(ContainerInterface $container) {
return new Predis\Client([
'scheme' => 'tcp',
'host' => $container->get('REDIS_HOST'),
'port' => $container->get('REDIS_PORT')
]);
},
Incoviba\Service\Cartola::class => function(ContainerInterface $container) {
return (new Incoviba\Service\Cartola(
Incoviba\Service\Contabilidad\Cartola::class => function(ContainerInterface $container) {
return (new Incoviba\Service\Contabilidad\Cartola(
$container->get(Psr\Log\LoggerInterface::class),
$container->get(Psr\Http\Message\StreamFactoryInterface::class),
$container->get(Incoviba\Common\Define\Contabilidad\Exporter::class),
$container->get(Incoviba\Repository\Inmobiliaria::class),
$container->get(Incoviba\Repository\Inmobiliaria\Cuenta::class),
$container->get(Incoviba\Repository\Movimiento::class),
$container->get(Incoviba\Service\Movimiento::class),
$container->get(Incoviba\Repository\Cartola::class)
$container->get(Incoviba\Repository\Contabilidad\Movimiento::class),
$container->get(Incoviba\Service\Contabilidad\Movimiento::class),
$container->get(Incoviba\Repository\Contabilidad\Cartola::class)
))
->register('security', $container->get(Incoviba\Service\Cartola\Security::class))
->register('itau', $container->get(Incoviba\Service\Cartola\Itau::class))
->register('santander', $container->get(Incoviba\Service\Cartola\Santander::class));
->register('security', $container->get(Incoviba\Service\Contabilidad\Cartola\Security::class))
->register('itau', $container->get(Incoviba\Service\Contabilidad\Cartola\Itau::class))
->register('santander', $container->get(Incoviba\Service\Contabilidad\Cartola\Santander::class))
->register('bci', $container->get(Incoviba\Service\Contabilidad\Cartola\BCI::class));
},
Incoviba\Common\Define\Contabilidad\Exporter::class => function(ContainerInterface $container) {
return $container->get(Incoviba\Service\Contabilidad\Exporter\Nubox::class);
},
Incoviba\Service\Contabilidad\Exporter\Nubox::class => function(ContainerInterface $container) {
return new Incoviba\Service\Contabilidad\Exporter\Nubox($container->get(Incoviba\Repository\CentroCosto::class),
return new Incoviba\Service\Contabilidad\Exporter\Nubox($container->get(Incoviba\Repository\Contabilidad\CentroCosto::class),
$container->get('folders')->get('uploads'));
},
Incoviba\Service\Contabilidad\Nubox::class => function(ContainerInterface $container) {
return new Incoviba\Service\Contabilidad\Nubox(
$container->get(Psr\Log\LoggerInterface::class),
$container->get(Incoviba\Repository\Nubox::class),
$container->get(Incoviba\Repository\Contabilidad\Nubox::class),
$container->get(Incoviba\Service\Redis::class),
new GuzzleHttp\Client(),
$container->get(Psr\Http\Message\RequestFactoryInterface::class),

View File

@ -0,0 +1,20 @@
<?php
namespace Incoviba\Controller\API;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Ideal\Controller;
class Base extends Controller
{
use withJson;
public function __invoke(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
$output = [
'version' => '2.0.0',
'organization' => 'Ingenieria y Construccion Vial Balmaceda Sociedad Anonima'
];
return $this->withJson($response, $output);
}
}

View File

@ -1,24 +1,23 @@
<?php
namespace Incoviba\Controller\API\Contabilidad;
use DateTimeInterface;
use DateTimeImmutable;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Incoviba\Common\Ideal\Controller;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Repository;
use Incoviba\Service;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Cartolas extends Controller
{
use withJson;
public function procesar(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Banco $bancoRepository,
Service\Cartola $cartolaService): ResponseInterface
public function procesar(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Contabilidad\Banco $bancoRepository,
Service\Contabilidad\Cartola $cartolaService): ResponseInterface
{
$body = $request->getParsedBody();
$output = [
@ -34,10 +33,10 @@ class Cartolas extends Controller
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function exportar(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Banco $bancoRepository,
Service\Cartola $cartolaService): ResponseInterface
public function exportar(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Contabilidad\Banco $bancoRepository,
Service\Contabilidad\Cartola $cartolaService): ResponseInterface
{
$body = $request->getParsedBody();
$output = [
@ -52,9 +51,9 @@ class Cartolas extends Controller
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function diaria(ServerRequestInterface $request, ResponseInterface $response,
public function diaria(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria\Cuenta $cuentaRepository,
Service\Cartola $cartolaService): ResponseInterface
Service\Contabilidad\Cartola $cartolaService): ResponseInterface
{
$body = $request->getParsedBody();
$output = [
@ -80,9 +79,9 @@ class Cartolas extends Controller
}
return $this->withJson($response, $output);
}
public function ayer(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria\Cuenta $cuentaRepository,
Repository\Cartola $cartolaRepository): ResponseInterface
public function ayer(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria\Cuenta $cuentaRepository,
Repository\Contabilidad\Cartola $cartolaRepository): ResponseInterface
{
$body = $request->getParsedBody();
$output = [

View File

@ -0,0 +1,63 @@
<?php
namespace Incoviba\Controller\API\Contabilidad;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Repository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class CentrosCostos
{
use withJson;
public function add(ServerRequestInterface $request, ResponseInterface $response,
Repository\Contabilidad\CentroCosto $centroCostoRepository): ResponseInterface
{
$body = $request->getParsedBody();
$output = [
'input' => $body,
'added' => false
];
try {
$centroCosto = $centroCostoRepository->create($body);
$centroCosto->id = $body['id'];
$centroCostoRepository->save($centroCosto);
$output['added'] = true;
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function edit(ServerRequestInterface $request, ResponseInterface $response,
Repository\Contabilidad\CentroCosto $centroCostoRepository, int $centro_costo_id): ResponseInterface
{
$body = $request->getParsedBody();
$output = [
'centro_costo_id' => $centro_costo_id,
'input' => $body,
'edited' => false
];
try {
$centroCosto = $centroCostoRepository->fetchById($centro_costo_id);
if ($body['tipo_cuenta_id'] === '') {
$body['tipo_cuenta_id'] = null;
}
$centroCostoRepository->edit($centroCosto, $body);
$output['edited'] = true;
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function remove(ServerRequestInterface $request, ResponseInterface $response,
Repository\Contabilidad\CentroCosto $centroCostoRepository, int $centro_costo_id): ResponseInterface
{
$output = [
'centro_costo_id' => $centro_costo_id,
'removed' => false
];
try {
$centroCosto = $centroCostoRepository->fetchById($centro_costo_id);
$centroCostoRepository->remove($centroCosto);
$output['removed'] = true;
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
}

View File

@ -2,23 +2,23 @@
namespace Incoviba\Controller\API\Contabilidad;
use DateTimeImmutable;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Controller\API\withJson;
use Incoviba\Repository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Depositos extends Ideal\Controller
{
use withJson;
public function inmobiliaria(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Banco $bancoRepository,
Repository\Inmobiliaria\Cuenta $cuentaRepository,
Repository\Deposito $dapRepository,
int $inmobiliaria_rut): ResponseInterface
public function inmobiliaria(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Contabilidad\Banco $bancoRepository,
Repository\Inmobiliaria\Cuenta $cuentaRepository,
Repository\Contabilidad\Deposito $dapRepository,
int $inmobiliaria_rut): ResponseInterface
{
$output = [
'inmobiliaria_rut' => $inmobiliaria_rut,
@ -33,10 +33,10 @@ class Depositos extends Ideal\Controller
} catch (Implement\Exception\EmptyResult) {}
return $this->withJson($response, $output);
}
public function add(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository, Repository\Banco $bancoRepository,
Repository\Inmobiliaria\Cuenta $cuentaRepository,
Repository\Deposito $dapRepository): ResponseInterface
public function add(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository, Repository\Contabilidad\Banco $bancoRepository,
Repository\Inmobiliaria\Cuenta $cuentaRepository,
Repository\Contabilidad\Deposito $dapRepository): ResponseInterface
{
$body = $request->getParsedBody();
$output = [

View File

@ -1,21 +1,21 @@
<?php
namespace Incoviba\Controller\API\Contabilidad;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Common\Ideal;
use Incoviba\Repository;
use Incoviba\Service;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Movimientos extends Ideal\Controller
{
use withJson;
public function detalles(ServerRequestInterface $request, ResponseInterface $response,
Service\Movimiento $movimientoService,
Repository\CentroCosto $centroCostoRepository, int $movimiento_id): ResponseInterface
public function detalles(ServerRequestInterface $request, ResponseInterface $response,
Service\Contabilidad\Movimiento $movimientoService,
Repository\Contabilidad\CentroCosto $centroCostoRepository, int $movimiento_id): ResponseInterface
{
$body = $request->getParsedBody();
$output = [
@ -47,4 +47,43 @@ class Movimientos extends Ideal\Controller
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Service\Contabilidad\Movimiento $movimientoService): ResponseInterface
{
$output = [
'movimientos' => []
];
try {
$movimientos = $movimientoService->getAll();
$output['movimientos'] = json_decode(json_encode($movimientos), JSON_OBJECT_AS_ARRAY);
foreach ($output['movimientos'] as $i => &$arrayMovimiento) {
$arrayMovimiento['cuenta'] = json_decode(json_encode($movimientos[$i]->cuenta), JSON_OBJECT_AS_ARRAY);
$arrayMovimiento['cuenta']['inmobiliaria'] = json_decode(json_encode($movimientos[$i]->cuenta->inmobiliaria), JSON_OBJECT_AS_ARRAY);
if ($arrayMovimiento['detalles'] !== null) {
$arrayMovimiento['detalles']['centro_costo'] = $movimientos[$i]->getDetalles()->centroCosto;
}
}
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function segment(ServerRequestInterface $request, ResponseInterface $response,
Service\Contabilidad\Movimiento $movimientoService): ResponseInterface
{
$input = $request->getParsedBody();
$output = [
'input' => $input,
'movimientos' => []
];
try {
$movimientos = $movimientoService->getAmountStartingFrom($input['from'], $input['amount']);
$output['movimientos'] = json_decode(json_encode($movimientos), JSON_OBJECT_AS_ARRAY);
foreach ($output['movimientos'] as $i => &$arrayMovimiento) {
$arrayMovimiento['cuenta'] = json_decode(json_encode($movimientos[$i]->cuenta), JSON_OBJECT_AS_ARRAY);
$arrayMovimiento['cuenta']['inmobiliaria'] = json_decode(json_encode($movimientos[$i]->cuenta->inmobiliaria), JSON_OBJECT_AS_ARRAY);
if ($arrayMovimiento['detalles'] !== null) {
$arrayMovimiento['detalles']['centro_costo'] = $movimientos[$i]->getDetalles()->centroCosto;
}
}
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
}

View File

@ -0,0 +1,91 @@
<?php
namespace Incoviba\Controller\API\Contabilidad;
use DateTimeImmutable;
use Incoviba\Common\Implement\Exception\HttpResponse;
use Incoviba\Controller\API\withJson;
use Incoviba\Service;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Nubox
{
use withJson;
public function token(ServerRequestInterface $request, ResponseInterface $response,
Service\Contabilidad\Nubox $nuboxService, int $inmobiliaria_rut): ResponseInterface
{
$output = [
'inmobiliaria_rut' => $inmobiliaria_rut,
'token' => ''
];
try {
$output['token'] = $nuboxService->getToken($inmobiliaria_rut);
} catch (HttpResponse $exception) {
$output['error'] = [
'code' => $exception->getCode(),
'message' => $exception->getMessage()
];
}
return $this->withJson($response, $output);
}
public function sistemas(ServerRequestInterface $request, ResponseInterface $response,
Service\Contabilidad\Nubox $nuboxService, int $inmobiliaria_rut): ResponseInterface
{
$output = [
'inmobiliaria_rut' => $inmobiliaria_rut,
'sistemas' => []
];
try {
$output['sistemas'] = $nuboxService->getSistemas($inmobiliaria_rut);
} catch (HttpResponse $exception) {
$output['error'] = [
'code' => $exception->getCode(),
'message' => $exception->getMessage()
];
}
return $this->withJson($response, $output);
}
public function libroMayor(ServerRequestInterface $request, ResponseInterface $response,
Service\Contabilidad\Nubox $nuboxService, int $inmobiliaria_rut): ResponseInterface
{
$body = $request->getParsedBody();
$output = [
'inmobiliaria_rut' => $inmobiliaria_rut,
'input' => $body,
'libro_mayor' => []
];
try {
$from = new DateTimeImmutable($body['inicio']);
$to = new DateTimeImmutable($body['termino']);
$output['libro_mayor'] = $nuboxService->getLibroMayor($inmobiliaria_rut, $from, $to);
} catch (HttpResponse $exception) {
$output['error'] = [
'code' => $exception->getCode(),
'message' => $exception->getMessage()
];
}
return $this->withJson($response, $output);
}
public function libroDiario(ServerRequestInterface $request, ResponseInterface $response,
Service\Contabilidad\Nubox $nuboxService, int $inmobiliaria_rut): ResponseInterface
{
$body = $request->getParsedBody();
$output = [
'inmobiliaria_rut' => $inmobiliaria_rut,
'input' => $body,
'libro_diario' => []
];
try {
$from = new DateTimeImmutable($body['inicio']);
$to = new DateTimeImmutable($body['termino']);
$output['libro_diario'] = $nuboxService->getLibroDiario($inmobiliaria_rut, $from, $to);
} catch (HttpResponse $exception) {
$output['error'] = [
'code' => $exception->getCode(),
'message' => $exception->getMessage()
];
}
return $this->withJson($response, $output);
}
}

View File

@ -12,6 +12,16 @@ class Inmobiliarias
{
use withJson;
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Repository\Inmobiliaria $inmobiliariaRepository): ResponseInterface
{
$output = [
'inmobiliarias' => []
];
try {
$output['inmobiliarias'] = $inmobiliariaRepository->fetchAll('razon');
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function cuentas(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Inmobiliaria\Cuenta $cuentaRepository, int $inmobiliaria_rut): ResponseInterface
@ -45,4 +55,29 @@ class Inmobiliarias
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function agentes(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Inmobiliaria\SociedadAgente $sociedadAgenteRepository,
Repository\Inmobiliaria\TipoAgente $tipoAgenteRepository,
int $inmobiliaria_rut): ResponseInterface
{
$input = $request->getParsedBody();
$output = [
'sociedad_rut' => $inmobiliaria_rut,
'input' => $input,
'sociedad' => null,
'agentes' => []
];
try {
$inmobiliaria = $inmobiliariaRepository->fetchById($inmobiliaria_rut);
$output['sociedad'] = $inmobiliaria;
if (isset($input['tipo_agente_id'])) {
$tipo = $tipoAgenteRepository->fetchById($input['tipo_agente_id']);
$output['agentes'] = $sociedadAgenteRepository->fetchBySociedadAndTipo($inmobiliaria->rut, $tipo->id);
} else {
$output['agentes'] = $sociedadAgenteRepository->fetchBySociedad($inmobiliaria->rut);
}
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
}

View File

@ -0,0 +1,90 @@
<?php
namespace Incoviba\Controller\API\Inmobiliarias;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Controller\API\withJson;
use Incoviba\Repository;
class Agentes
{
use withJson;
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Repository\Inmobiliaria\Agente $agenteRepository): ResponseInterface
{
$output = [
'agentes' => []
];
try {
$output['agentes'] = $agenteRepository->fetchAll('abreviacion');
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function add(ServerRequestInterface $request, ResponseInterface $response, Repository\Inmobiliaria\Agente $agenteRepository): ResponseInterface
{
$input = $request->getParsedBody();
$output = [
'input' => $input,
'agente' => null
];
try {
$agente = $agenteRepository->create($input);
$output['agente'] = $agenteRepository->save($agente);
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function edit(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria\Agente $agenteRepository, int $agente_id): ResponseInterface
{
$input = $request->getParsedBody();
$output = [
'agente_id' => $agente_id,
'input' => $input,
'agente' => null
];
try {
$agente = $agenteRepository->fetchById($agente_id);
$output['agente'] = $agenteRepository->edit($agente, $input);
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function register(ServerRequestInterface $request, ResponseInterface $response,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Inmobiliaria\Agente $agenteRepository,
Repository\Inmobiliaria\TipoAgente $tipoAgenteRepository,
Repository\Inmobiliaria\AgenteTipo $agenteTipoRepository,
Repository\Inmobiliaria\SociedadAgente $sociedadAgenteRepository): ResponseInterface
{
$input = $request->getParsedBody();
$output = [
'input' => $input,
'sociedad' => null,
'agente' => null,
'tipo_agente' => null,
'sociedad_agente' => null
];
try {
$sociedad = $inmobiliariaRepository->fetchById($input['sociedad_rut']);
$output['sociedad'] = $sociedad;
$agente = $agenteRepository->fetchById($input['agente_id']);
$output['agente'] = $agente;
$tipo = $tipoAgenteRepository->fetchById($input['tipo_agente_id']);
$output['tipo_agente'] = $tipo;
$agenteTipo = $agenteTipoRepository->fetchByAgenteAndTipo($agente->id, $tipo->id);
try {
$output['sociedad_agente'] = $sociedadAgenteRepository->fetchBySociedadAndAgenteAndTipo($sociedad->rut, $agente->id, $tipo->id);
} catch (EmptyResult) {
$data = [
'sociedad_rut' => $sociedad->rut,
'agente_tipo_id' => $agenteTipo->id
];
$sociedadAgente = $sociedadAgenteRepository->create($data);
$output['sociedad_agente'] = $sociedadAgenteRepository->save($sociedadAgente);
}
} catch (EmptyResult) {
}
return $this->withJson($response, $output);
}
}

View File

@ -13,6 +13,19 @@ class Pagos
{
use withJson;
public function get(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pago $pagoService,
Service\Format $formatService, int $pago_id): ResponseInterface
{
$output = [
'pago_id' => $pago_id,
'pago' => null
];
try {
$output['pago'] = json_decode(json_encode($pagoService->getById($pago_id)), JSON_OBJECT_AS_ARRAY);
$output['pago']['valor_uf'] = $formatService->ufs($output['pago']['valor_uf']);
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function edit(ServerRequestInterface $request, ResponseInterface $response, Repository\Venta\Pago $pagoRepository, int $pago_id): ResponseInterface
{
$body = $request->getParsedBody();
@ -31,33 +44,41 @@ class Pagos
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function depositar(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pago $pagoService, int $pago_id): ResponseInterface
public function depositar(ServerRequestInterface $request, ResponseInterface $response,
Service\Venta\Pago $pagoService, Service\Format $formatService, int $pago_id): ResponseInterface
{
$body = $request->getParsedBody();
$output = [
'pago_id' => $pago_id,
'input' => $body,
'pago' => null,
'depositado' => false
];
try {
$pago = $pagoService->getById($pago_id);
$fecha = new DateTimeImmutable($body->fecha);
$fecha = new DateTimeImmutable($body['fecha']);
$output['depositado'] = $pagoService->depositar($pago, $fecha);
$output['pago'] = json_decode(json_encode($pagoService->getById($pago_id)), JSON_OBJECT_AS_ARRAY);
$output['pago']['valor_uf'] = $formatService->ufs($output['pago']['valor_uf']);
} catch (EmptyResult) {}
return $this->withJson($response, $output);
}
public function abonar(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pago $pagoService, int $pago_id): ResponseInterface
public function abonar(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pago $pagoService,
Service\Format $formatService, int $pago_id): ResponseInterface
{
$body = $request->getParsedBody();
$output = [
'pago_id' => $pago_id,
'input' => $body,
'pago' => null,
'abonado' => false
];
try {
$pago = $pagoService->getById($pago_id);
$fecha = new DateTimeImmutable($body->fecha);
$fecha = new DateTimeImmutable($body['fecha']);
$output['abonado'] = $pagoService->abonar($pago, $fecha);
$output['pago'] = json_decode(json_encode($pagoService->getById($pago_id)), JSON_OBJECT_AS_ARRAY);
$output['pago']['valor_uf'] = $formatService->ufs($output['pago']['valor_uf']);
$output['input']['fecha'] = $fecha->format('d-m-Y');
} catch (EmptyResult) {}
return $this->withJson($response, $output);

View File

@ -1,25 +1,25 @@
<?php
namespace Incoviba\Controller;
use DateTimeImmutable;
use DateInterval;
use Incoviba\Common\Ideal\Controller;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use DateTimeImmutable;
use Incoviba\Common\Alias\View;
use Incoviba\Common\Implement\Exception\{EmptyResult, EmptyRedis};
use Incoviba\Common\Ideal\Controller;
use Incoviba\Common\Implement\Exception\{EmptyRedis, EmptyResult};
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Contabilidad extends Controller
{
use withRedis;
public function diaria(ServerRequestInterface $request, ResponseInterface $response, View $view,
Service\Redis $redisService,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\CentroCosto $centroCostoRepository): ResponseInterface
public function diaria(ServerRequestInterface $request, ResponseInterface $response, View $view,
Service\Redis $redisService,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Contabilidad\CentroCosto $centroCostoRepository): ResponseInterface
{
$redisKey = 'inmobiliarias';
$inmobiliarias = [];
@ -27,17 +27,17 @@ class Contabilidad extends Controller
$inmobiliarias = $this->fetchRedis($redisService, $redisKey);
} catch (EmptyRedis) {
try {
$inmobiliarias = $inmobiliariaRepository->fetchAll();
$inmobiliarias = $inmobiliariaRepository->fetchAll('razon');
$this->saveRedis($redisService, $redisKey, $inmobiliarias, 30 * 24 * 60 * 60);
} catch (EmptyResult) {}
}
$centrosCostos = $centroCostoRepository->fetchAll();
return $view->render($response, 'contabilidad.cartolas.diaria', compact('inmobiliarias', 'centrosCostos'));
}
public function depositos(ServerRequestInterface $request, ResponseInterface $response, View $view,
Service\Redis $redisService,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Deposito $dapRepository): ResponseInterface
public function depositos(ServerRequestInterface $request, ResponseInterface $response, View $view,
Service\Redis $redisService,
Repository\Inmobiliaria $inmobiliariaRepository,
Repository\Contabilidad\Deposito $dapRepository): ResponseInterface
{
$redisKey = 'inmobiliarias';
$inmobiliarias = [];
@ -54,11 +54,11 @@ class Contabilidad extends Controller
$depositos = $dapRepository->fetchAll();
} catch (EmptyResult) {}
$fecha = new DateTimeImmutable('today');
$activos = array_filter($depositos, function(Model\Deposito $deposito) use ($fecha) {
$activos = array_filter($depositos, function(Model\Contabilidad\Deposito $deposito) use ($fecha) {
return $deposito->termino >= $fecha;
});
$mes = $fecha->sub(new DateInterval('P1M'));
$vencidos = array_filter($depositos, function(Model\Deposito $deposito) use ($fecha, $mes) {
$vencidos = array_filter($depositos, function(Model\Contabilidad\Deposito $deposito) use ($fecha, $mes) {
return $deposito->termino < $fecha and $deposito->termino >= $mes;
});
return $view->render($response, 'contabilidad.depositos', compact('inmobiliarias', 'activos', 'vencidos'));
@ -69,8 +69,25 @@ class Contabilidad extends Controller
{
$fecha = new DateTimeImmutable($fecha);
$anterior = $contabilidadService->getAnterior($fecha);
$yesterday = new DateTimeImmutable('yesterday');
$siguiente = null;
if ($yesterday > $fecha) {
$siguiente = $fecha->add(new DateInterval('P1D'));
if ($siguiente->format('N') === '6') {
$siguiente = $fecha->add(new DateInterval('P3D'));
}
}
$informes = $contabilidadService->build($fecha);
$filename = "Informe de Tesorería {$fecha->format('d.m.Y')}";
return $view->render($response, 'contabilidad.informes.tesoreria', compact('fecha', 'anterior', 'informes', 'filename'));
return $view->render($response, 'contabilidad.informes.tesoreria', compact('fecha', 'anterior', 'siguiente', 'informes', 'filename'));
}
public function cuadratura(ServerRequestInterface $request, ResponseInterface $response, View $view,
Repository\Inmobiliaria $inmobiliariaRepository): ResponseInterface
{
$inmobiliarias = [];
try {
$inmobiliarias = $inmobiliariaRepository->fetchAll('razon');
} catch (EmptyResult) {}
return $view->render($response, 'contabilidad.cuadratura', compact('inmobiliarias'));
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Incoviba\Controller\Contabilidad;
use Incoviba\Common\Alias\View;
use Incoviba\Repository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class CentrosCostos
{
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, View $view,
Repository\Contabilidad\CentroCosto $centroCostoRepository,
Repository\Contabilidad\TipoCentro $tipoCentroRepository,
Repository\Contabilidad\CategoriaCentro $categoriaCentroRepository,
Repository\TipoCuenta $tipoCuentaRepository): ResponseInterface
{
$centrosCostos = $centroCostoRepository->fetchAll();
$tiposCentros = $tipoCentroRepository->fetchAll();
$categorias = $categoriaCentroRepository->fetchAll('descripcion');
$tiposCuentas = $tipoCuentaRepository->fetchAll();
return $view->render($response, 'contabilidad.centros_costos', compact('centrosCostos',
'tiposCentros', 'categorias', 'tiposCuentas'));
}
public function asignar(ServerRequestInterface $request, ResponseInterface $response, View $view,
Repository\Contabilidad\CentroCosto $centroCostoRepository,
Repository\Inmobiliaria $inmobiliariaRepository): ResponseInterface
{
$centrosCostos = $centroCostoRepository->fetchAll();
$inmobiliarias = $inmobiliariaRepository->fetchAllActive('razon');
return $view->render($response, 'contabilidad.centros_costos.asignar', compact('centrosCostos', 'inmobiliarias'));
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace Incoviba\Controller\Contabilidad;
use Incoviba\Common\Alias\View;
use Incoviba\Common\Ideal\Controller;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Movimientos extends Controller
{
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, View $view): ResponseInterface
{
return $view->render($response, 'contabilidad.movimientos');
}
}

View File

@ -20,8 +20,8 @@ class Inmobiliarias
$inmobiliarias = [];
try {
$inmobiliarias = array_map(function($row) use ($inmobiliariaRepository) {
return $inmobiliariaRepository->load((array) $row);
}, $this->fetchRedis($redisService, $redisKey));
return $inmobiliariaRepository->load($row);
}, $this->fetchRedis($redisService, $redisKey, true));
} catch (EmptyRedis) {
try {
$inmobiliarias = $inmobiliariaRepository->fetchAll();

View File

@ -1,14 +1,16 @@
<?php
namespace Incoviba\Controller;
use Incoviba\Common\Implement\Exception\EmptyResult;
use PDOException;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Alias\View;
use Incoviba\Common\Ideal\Controller;
use Incoviba\Repository;
use Incoviba\Service;
class Login
class Login extends Controller
{
public function form(ServerRequestInterface $request, ResponseInterface $response, View $view, Service\Login $service): ResponseInterface
{
@ -20,14 +22,17 @@ class Login
public function login(ServerRequestInterface $request, ResponseInterface $response, Repository\User $userRepository, Service\Login $service): ResponseInterface
{
$body = $request->getParsedBody();
$user = $userRepository->fetchByName($body['name']);
$output = [
'name' => $user->name,
'name' => $body['name'],
'login' => false
];
if ($user->validate($body['password'])) {
$output['login'] = $service->login($user);
}
try {
$user = $userRepository->fetchByName($body['name']);
if ($service->validateUser($user, $body['password'])) {
$output['login'] = $service->login($user);
}
} catch (EmptyResult) {}
$response->getBody()->write(json_encode($output));
return $response->withHeader('Content-Type', 'application/json');
}

View File

@ -1,14 +1,14 @@
<?php
namespace Incoviba\Controller;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Alias\View;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Common\Implement\Exception\EmptyRedis;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Ventas
{
@ -101,14 +101,29 @@ class Ventas
View $view, int $venta_id): ResponseInterface
{
$venta = $ventaService->getById($venta_id);
return $view->render($response, 'ventas.pies.cuotas', compact('venta'));
$asociadas = [];
if (isset($venta->formaPago()->pie->asociado)) {
$asociadas []= $ventaService->getByPie($venta->formaPago()->pie->asociado->id);
foreach ($venta->formaPago()->pie->asociado->asociados() as $asociado) {
if ($venta->formaPago()->pie->id === $asociado->id) {
continue;
}
$asociadas []= $ventaService->getByPie($asociado->id);
}
}
if (count($venta->formaPago()->pie->asociados()) > 0) {
foreach ($venta->formaPago()->pie->asociados() as $asociado) {
$asociadas []= $ventaService->getByPie($asociado->id);
}
}
return $view->render($response, 'ventas.pies.cuotas', compact('venta', 'asociadas'));
}
public function escriturar(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService,
Repository\Banco $bancoRepository, View $view, int $venta_id): ResponseInterface
public function escriturar(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService,
Repository\Contabilidad\Banco $bancoRepository, View $view, int $venta_id): ResponseInterface
{
$venta = $ventaService->getById($venta_id);
$bancos = $bancoRepository->fetchAll();
usort($bancos, function(Model\Banco $a, Model\Banco $b) {
usort($bancos, function(Model\Contabilidad\Banco $a, Model\Contabilidad\Banco $b) {
return strcmp($a->nombre, $b->nombre);
});
return $view->render($response, 'ventas.escriturar', compact('venta', 'bancos'));

View File

@ -1,19 +1,20 @@
<?php
namespace Incoviba\Controller\Ventas;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Alias\View;
use Incoviba\Common\Ideal\Controller;
use Incoviba\Repository;
use Incoviba\Service;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Creditos extends Controller
{
public function show(ServerRequestInterface $request, ResponseInterface $response, View $view,
Repository\Venta $ventaRepository, Repository\Banco $bancoRepository,
int $venta_id): ResponseInterface
Service\Venta $ventaService, Repository\Contabilidad\Banco $bancoRepository,
int $venta_id): ResponseInterface
{
$venta = $ventaRepository->fetchById($venta_id);
$venta = $ventaService->getById($venta_id);
$bancos = $bancoRepository->fetchAll('nombre');
return $view->render($response, 'ventas.creditos', compact('venta', 'bancos'));
}

View File

@ -2,13 +2,13 @@
namespace Incoviba\Controller\Ventas;
use DateTimeImmutable;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Common\Alias\View;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
use Incoviba\Model;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Cuotas
{
@ -73,12 +73,12 @@ class Cuotas
$response->getBody()->write(json_encode($output));
return $response->withHeader('Content-Type', 'application/json');
}
public function add(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pie $pieService, Repository\Venta $ventaRepository, Repository\Banco $bancoRepository, View $view, int $pie_id): ResponseInterface
public function add(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pie $pieService, Repository\Venta $ventaRepository, Repository\Contabilidad\Banco $bancoRepository, View $view, int $pie_id): ResponseInterface
{
$pie = $pieService->getById($pie_id);
$venta = $ventaRepository->fetchByPie($pie_id);
$bancos = $bancoRepository->fetchAll();
usort($bancos, function(Model\Banco $a, Model\Banco $b) {
usort($bancos, function(Model\Contabilidad\Banco $a, Model\Contabilidad\Banco $b) {
return strcmp($a->nombre, $b->nombre);
});
return $view->render($response, 'ventas.pies.cuotas.add', compact('pie', 'venta', 'bancos'));

View File

@ -1,11 +1,11 @@
<?php
namespace Incoviba\Controller\Ventas;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Alias\View;
use Incoviba\Repository;
use Incoviba\Service;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Escrituras
{
@ -22,8 +22,8 @@ class Escrituras
return $view->render($response, 'ventas.escrituras.informe', compact('venta'));
}
public function add(ServerRequestInterface $request, ResponseInterface $response, View $view,
Service\Venta $ventaService, Repository\Banco $bancoRepository,
int $venta_id): ResponseInterface
Service\Venta $ventaService, Repository\Contabilidad\Banco $bancoRepository,
int $venta_id): ResponseInterface
{
$venta = $ventaService->getById($venta_id);
$bancos = $bancoRepository->fetchAll('nombre');

View File

@ -8,14 +8,18 @@ use Incoviba\Service;
class Facturacion
{
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, View $view, Service\Proyecto $proyectoService): ResponseInterface
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, View $view,
Service\Proyecto $proyectoService): ResponseInterface
{
$proyectos = $proyectoService->getEscriturando();
return $view->render($response, 'ventas.facturacion', compact('proyectos'));
}
public function show(ServerRequestInterface $request, ResponseInterface $response, View $view, Service\Venta $ventaService, int $venta_id): ResponseInterface
public function show(ServerRequestInterface $request, ResponseInterface $response, View $view,
Service\Venta $ventaService, Service\Proyecto\Terreno $terrenoService,
int $venta_id): ResponseInterface
{
$venta = $ventaService->getById($venta_id);
return $view->render($response, 'ventas.facturacion.show', compact('venta'));
$terreno = $terrenoService->valor($venta->proyecto()->id);
return $view->render($response, 'ventas.facturacion.show', compact('venta', 'terreno'));
}
}

View File

@ -1,23 +1,25 @@
<?php
namespace Incoviba\Controller\Ventas;
use Incoviba\Common\Alias\View;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Alias\View;
use Incoviba\Service;
use Incoviba\Repository;
use Incoviba\Model;
class Pies
{
public function cuotas(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pie $pieService, Repository\Venta $ventaRepository, Repository\Banco $bancoRepository, View $view, int $pie_id): ResponseInterface
public function cuotas(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pie $pieService,
Repository\Venta $ventaRepository, Repository\Contabilidad\Banco $bancoRepository,
View $view, int $pie_id): ResponseInterface
{
$pie = $pieService->getById($pie_id);
$venta = $ventaRepository->fetchByPie($pie_id);
$bancos = $bancoRepository->fetchAll();
usort($bancos, function(Model\Banco $a, Model\Banco $b) {
usort($bancos, function(Model\Contabilidad\Banco $a, Model\Contabilidad\Banco $b) {
return strcmp($a->nombre, $b->nombre);
});
return $view->render($response, 'ventas.pies.cuotas', compact('pie', 'venta', 'bancos'));
return $view->render($response, 'ventas.pies.cuotas', compact('pie', 'venta', 'bancos', 'ventaRepository'));
}
}

View File

@ -6,13 +6,13 @@ use Incoviba\Service;
trait withRedis
{
public function fetchRedis(Service\Redis $redisService, string $redisKey): mixed
public function fetchRedis(Service\Redis $redisService, string $redisKey, ?bool $asArray = null): mixed
{
$jsonString = $redisService->get($redisKey);
if ($jsonString === null) {
throw new EmptyRedis($redisKey);
}
return json_decode($jsonString);
return json_decode($jsonString, $asArray);
}
public function saveRedis(Service\Redis $redisService, string $redisKey, mixed $value, ?int $expiration = null): void
{

View File

@ -6,10 +6,12 @@ use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Incoviba\Exception\MissingAuthorizationHeader;
use Incoviba\Service;
class API
{
public function __construct(protected ResponseFactoryInterface $responseFactory, protected string $key) {}
public function __construct(protected ResponseFactoryInterface $responseFactory, protected Service\Login $loginService,
protected string $key) {}
public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
@ -18,7 +20,7 @@ class API
} catch (MissingAuthorizationHeader $exception) {
return $this->responseFactory->createResponse(401);
}
if ($this->validate($key)) {
if ($this->validate($request, $key)) {
return $handler->handle($request);
}
return $this->responseFactory->createResponse(403);
@ -33,8 +35,26 @@ class API
}
throw new MissingAuthorizationHeader();
}
protected function validate($incoming_key): bool
protected function validate(ServerRequestInterface $request, $incoming_key): bool
{
if (str_contains($incoming_key, $this->loginService->getSeparator())) {
list($incoming_key, $selector, $token) = explode($this->loginService->getSeparator(), $incoming_key);
if (!$this->loginService->isIn()) {
return false;
}
}
if (!$this->loginService->isIn() and !$this->validPermitted($request)) {
return false;
}
return $incoming_key === md5($this->key);
}
protected function validPermitted(ServerRequestInterface $request): bool
{
$uri = $request->getUri();
$validPaths = [
'/api',
'/api/'
];
return in_array($uri->getPath(), $validPaths);
}
}

View File

@ -24,7 +24,7 @@ class Authentication
return $handler->handle($request);
}
$this->logger->notice("Not logged in.");
$response = $this->responseFactory->createResponse(301, 'Not logged in')
$response = $this->responseFactory->createResponse(307, 'Not logged in')
->withHeader('Referer', (string) $request->getUri())
->withHeader('X-Redirected-URI', (string) $request->getUri());
$url = "{$request->getUri()}";
@ -45,13 +45,22 @@ class Authentication
]);
$valid_paths = [
'/',
'/'
];
if (in_array($current_path, $valid_paths, true)) {
return true;
}
$valid_subpaths = [
'/api/'
];
foreach ($valid_subpaths as $path) {
if (str_starts_with($current_path, $path)) {
return true;
}
}
$valid_uris = [
$this->login_url,
"{$this->login_url}/",
];
if (in_array($current_url, $valid_uris, true)) {
return true;

View File

@ -0,0 +1,21 @@
<?php
namespace Incoviba\Middleware;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class CORS
{
public function __construct(protected ResponseFactoryInterface $responseFactory) {}
public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if ($request->getMethod() === 'OPTIONS') {
return $this->responseFactory->createResponse()
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Methods', 'POST,GET,OPTIONS');
}
return $handler->handle($request);
}
}

View File

@ -18,11 +18,11 @@ class Errors
try {
return $handler->handle($request);
} catch (Exception $exception) {
$this->logger->notice($exception);
$this->logger->warning($exception);
} catch (Error $error) {
$this->logger->error($error);
}
$response = $this->responseFactory->createResponse(600, 'Internal Server Error');
$response = $this->responseFactory->createResponse(500, 'Internal Server Error');
if (str_contains($request->getUri()->getPath(), '/api')) {
return $response;
}

View File

@ -1,5 +0,0 @@
<?php
namespace Incoviba\Model;
class CategoriaCentro extends Tipo
{}

View File

@ -1,5 +1,5 @@
<?php
namespace Incoviba\Model;
namespace Incoviba\Model\Contabilidad;
use Incoviba\Common\Ideal\Model;

View File

@ -1,8 +1,9 @@
<?php
namespace Incoviba\Model;
namespace Incoviba\Model\Contabilidad;
use DateTimeInterface;
use Incoviba\Common\Ideal;
use Incoviba\Model\Inmobiliaria;
class Cartola extends Ideal\Model
{

View File

@ -0,0 +1,7 @@
<?php
namespace Incoviba\Model\Contabilidad;
use Incoviba\Model\Tipo;
class CategoriaCentro extends Tipo
{}

View File

@ -1,7 +1,8 @@
<?php
namespace Incoviba\Model;
namespace Incoviba\Model\Contabilidad;
use Incoviba\Common\Ideal;
use Incoviba\Model\TipoCuenta;
class CentroCosto extends Ideal\Model
{

View File

@ -1,8 +1,9 @@
<?php
namespace Incoviba\Model;
namespace Incoviba\Model\Contabilidad;
use DateTimeInterface;
use Incoviba\Common\Ideal;
use Incoviba\Model\Inmobiliaria;
class Deposito extends Ideal\Model
{

View File

@ -1,8 +1,10 @@
<?php
namespace Incoviba\Model;
namespace Incoviba\Model\Contabilidad;
use DateTimeInterface;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Model\Inmobiliaria;
use Incoviba\Model\Movimiento\Detalle;
class Movimiento extends Ideal\Model
@ -19,7 +21,11 @@ class Movimiento extends Ideal\Model
public function getDetalles(): ?Detalle
{
if (!isset($this->detalles)) {
$this->detalles = $this->runFactory('detalles');
try {
$this->detalles = $this->runFactory('detalles');
} catch (EmptyResult) {
$this->detalles = null;
}
}
return $this->detalles;
}

View File

@ -1,8 +1,8 @@
<?php
namespace Incoviba\Model;
namespace Incoviba\Model\Contabilidad;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Model\Inmobiliaria;
class Nubox extends Ideal\Model
{

View File

@ -1,7 +1,8 @@
<?php
namespace Incoviba\Model;
namespace Incoviba\Model\Contabilidad;
use Incoviba\Common\Ideal;
use Incoviba\Model\Venta;
class PagoCentroCosto extends Ideal\Model
{

View File

@ -0,0 +1,7 @@
<?php
namespace Incoviba\Model\Contabilidad;
use Incoviba\Model\Tipo;
class TipoCentro extends Tipo
{}

View File

@ -10,8 +10,6 @@ class Inmobiliaria extends Model
public ?string $dv;
public ?string $razon;
public ?string $abreviacion;
public ?string $cuenta;
public ?Banco $banco;
public ?TipoSociedad $tipoSociedad;
public function rut(): string
@ -37,8 +35,6 @@ class Inmobiliaria extends Model
'rut_formateado' => $this->rut(),
'razon' => $this->razon ?? '',
'abreviacion' => $this->abreviacion ?? '',
'cuenta' => $this->cuenta ?? '',
'banco' => $this->banco ?? '',
'tipo_sociedad' => $this->tipoSociedad ?? ''
];
}

View File

@ -0,0 +1,40 @@
<?php
namespace Incoviba\Model\Inmobiliaria;
use Incoviba\Common\Ideal;
use Incoviba\Model;
class Agente extends Ideal\Model
{
public ?int $rut;
public string $descripcion;
public ?string $contacto;
public ?int $telefono;
public ?string $correo;
public ?Model\Direccion $direccion;
public ?string $giro;
public string $abreviacion;
protected ?array $tiposAgentes;
public function tipos(): ?array
{
if (!isset($this->tiposAgentes)) {
$this->tiposAgentes = $this->runFactory('tipos_agentes');
}
return $this->tiposAgentes;
}
public function jsonSerialize(): mixed
{
return array_merge(parent::jsonSerialize(), [
'rut' => $this->rut,
'descripcion' => $this->descripcion,
'contacto' => $this->contacto,
'telefono' => $this->telefono,
'correo' => $this->correo,
'direccion' => $this->direccion,
'giro' => $this->giro,
'abreviacion' => $this->abreviacion,
]);
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace Incoviba\Model\Inmobiliaria;
use Incoviba\Common\Ideal;
class AgenteTipo extends Ideal\Model
{
public Agente $agente;
public TipoAgente $tipoAgente;
}

View File

@ -2,14 +2,39 @@
namespace Incoviba\Model\Inmobiliaria;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Model;
class Cuenta extends Ideal\Model
{
public Model\Inmobiliaria $inmobiliaria;
public Model\Banco $banco;
public Model\Contabilidad\Banco $banco;
public string $cuenta;
protected array $estados;
public function getEstados(): array
{
if (!isset($this->estados)) {
$this->estados = $this->runFactory('estados');
}
return $this->estados;
}
protected Model\Inmobiliaria\Cuenta\Estado $currentEstado;
public function currentEstado(): Model\Inmobiliaria\Cuenta\Estado
{
if (!isset($this->currentEstado)) {
$estados = $this->getEstados();
if (count($estados) === 0) {
throw new EmptyResult('Current Estado Cuenta');
}
usort($estados, function(Model\Inmobiliaria\Cuenta\Estado $a, Model\Inmobiliaria\Cuenta\Estado $b) {
return $a->id - $b->id;
});
$this->currentEstado = end($estados);
}
return $this->currentEstado;
}
public function jsonSerialize(): mixed
{
return array_merge(parent::jsonSerialize(), [

View File

@ -0,0 +1,22 @@
<?php
namespace Incoviba\Model\Inmobiliaria\Cuenta;
use DateTimeInterface;
use Incoviba\Common\Ideal;
use Incoviba\Model;
class Estado extends Ideal\Model
{
public Model\Inmobiliaria\Cuenta $cuenta;
public DateTimeInterface $fecha;
public bool $active;
public function jsonSerialize(): mixed
{
return array_merge(parent::jsonSerialize(), [
'cuenta_id' => $this->cuenta->id,
'fecha' => $this->fecha->format('Y-m-d'),
'active' => $this->active
]);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Incoviba\Model\Inmobiliaria;
use Incoviba\Common\Ideal;
use Incoviba\Model;
class SociedadAgente extends Ideal\Model
{
public Model\Inmobiliaria $sociedad;
public AgenteTipo $agenteTipo;
public function jsonSerialize(): mixed
{
return [
'sociedad_rut' => $this->sociedad->rut,
'agente_tipo_id' => $this->agenteTipo->id
];
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace Incoviba\Model\Inmobiliaria;
use Incoviba\Model;
class TipoAgente extends Model\Tipo
{
public string $icono;
public string $color;
public string $bgcolor;
}

View File

@ -6,8 +6,8 @@ use Incoviba\Model;
class Detalle extends Ideal\Model
{
public Model\Movimiento $movimiento;
public ?Model\CentroCosto $centroCosto;
public Model\Contabilidad\Movimiento $movimiento;
public ?Model\Contabilidad\CentroCosto $centroCosto;
public ?string $detalle;
public function jsonSerialize(): mixed

View File

@ -1,5 +0,0 @@
<?php
namespace Incoviba\Model;
class TipoCentro extends Tipo
{}

View File

@ -3,9 +3,6 @@ namespace Incoviba\Model;
use DateTimeInterface;
use Incoviba\Common\Ideal;
use Incoviba\Controller\Ventas;
use Incoviba\Model\Venta\FormaPago;
use Incoviba\Model\Venta\Pago;
class Venta extends Ideal\Model
{
@ -18,7 +15,7 @@ class Venta extends Ideal\Model
public bool $relacionado;
protected ?Venta\Entrega $entrega;
public float $uf;
protected ?Pago $resciliacion;
protected ?Venta\Pago $resciliacion;
public ?array $estados;
public ?Venta\EstadoVenta $currentEstado;
@ -44,6 +41,11 @@ class Venta extends Ideal\Model
}
return $this->formaPago;
}
public function setFormaPago(Venta\FormaPago $formaPago): Venta
{
$this->formaPago = $formaPago;
return $this;
}
public function entrega(): ?Venta\Entrega
{
if (!isset($this->entrega)) {
@ -94,9 +96,9 @@ class Venta extends Ideal\Model
}
return $this->valor_util;
}
public function saldo(string $moneda = Pago::UF): float
public function saldo(string $moneda = Venta\Pago::UF): float
{
$valor = $this->valor * (($moneda === Pago::UF) ? 1 : $this->uf);
$valor = $this->valor * (($moneda === Venta\Pago::UF) ? 1 : $this->uf);
return $valor - $this->formaPago()->total($moneda);
}

View File

@ -3,7 +3,7 @@ namespace Incoviba\Model\Venta;
use DateTimeInterface;
use Incoviba\Common\Ideal\Model;
use Incoviba\Model\Banco;
use Incoviba\Model\Contabilidad\Banco;
class Cuota extends Model
{

View File

@ -3,7 +3,7 @@ namespace Incoviba\Model\Venta;
use DateTimeInterface;
use Incoviba\Common\Ideal\Model;
use Incoviba\Model\Banco;
use Incoviba\Model\Contabilidad\Banco;
class Pago extends Model
{
@ -28,10 +28,27 @@ class Pago extends Model
return $this->valor / (($moneda === Pago::UF) ? $uf : 1);
}
public function estado(?string $tipoEstado = null): ?EstadoPago
{
if (!isset($this->estados)) {
return null;
}
if ($tipoEstado === null) {
return $this->currentEstado;
}
foreach ($this->estados as $estado) {
if ($estado->tipoEstado->descripcion === $tipoEstado) {
return $estado;
}
}
return null;
}
public function jsonSerialize(): mixed
{
return array_merge(parent::jsonSerialize(), [
'valor' => $this->valor,
'valor_uf' => $this->valor(),
'banco' => $this->banco ?? '',
'tipo_pago' => $this->tipoPago ?? '',
'identificador' => $this->identificador ?? '',

View File

@ -6,8 +6,7 @@ use Incoviba\Model;
class Propiedad extends Ideal\Model
{
public array $unidades;
public array $unidades = [];
protected array $departamentos;
public function departamentos(): array
{

View File

@ -1,5 +1,5 @@
<?php
namespace Incoviba\Repository;
namespace Incoviba\Repository\Contabilidad;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
@ -17,7 +17,7 @@ class Banco extends Ideal\Repository
public function create(?array $data = null): Define\Model
{
$map = new Implement\Repository\MapperParser(['nombre']);
return $this->parseData(new Model\Banco(), $data, $map);
return $this->parseData(new Model\Contabilidad\Banco(), $data, $map);
}
public function save(Define\Model $model): Define\Model
{

View File

@ -1,5 +1,5 @@
<?php
namespace Incoviba\Repository;
namespace Incoviba\Repository\Contabilidad;
use DateTimeInterface;
use Incoviba\Common\Define;
@ -16,7 +16,7 @@ class Cartola extends Ideal\Repository
$this->setTable('cartolas');
}
public function create(?array $data = null): Model\Cartola
public function create(?array $data = null): Model\Contabilidad\Cartola
{
$map = (new Implement\Repository\MapperParser(['cargos', 'abonos', 'saldo']))
->register('fecha', new Implement\Repository\Mapper\DateTime('fecha'))
@ -25,9 +25,9 @@ class Cartola extends Ideal\Repository
->setFunction(function($data) {
return $this->cuentaRepository->fetchById($data['cuenta_id']);
}));
return $this->parseData(new Model\Cartola(), $data, $map);
return $this->parseData(new Model\Contabilidad\Cartola(), $data, $map);
}
public function save(Define\Model $model): Model\Cartola
public function save(Define\Model $model): Model\Contabilidad\Cartola
{
$model->id = $this->saveNew([
'cuenta_id',
@ -44,7 +44,7 @@ class Cartola extends Ideal\Repository
]);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\Cartola
public function edit(Define\Model $model, array $new_data): Model\Contabilidad\Cartola
{
return $this->update($model, ['cuenta_id', 'fecha', 'cargos', 'abonos', 'saldo'], $new_data);
}
@ -57,7 +57,7 @@ class Cartola extends Ideal\Repository
->where('fecha = ?');
return $this->fetchMany($query, [$fecha->format('Y-m-d')]);
}
public function fetchByCuentaAndFecha(int $cuenta_id, DateTimeInterface $fecha): Model\Cartola
public function fetchByCuentaAndFecha(int $cuenta_id, DateTimeInterface $fecha): Model\Contabilidad\Cartola
{
$query = $this->connection->getQueryBuilder()
->select()
@ -65,4 +65,14 @@ class Cartola extends Ideal\Repository
->where('cuenta_id = ? AND fecha = ?');
return $this->fetchOne($query, [$cuenta_id, $fecha->format('Y-m-d')]);
}
public function fetchLastByCuentaAndFecha(int $cuenta_id, DateTimeInterface $fecha): Model\Contabilidad\Cartola
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('cuenta_id = ? AND fecha <= ?')
->order('fecha DESC')
->limit(1);
return $this->fetchOne($query, [$cuenta_id, $fecha->format('Y-m-d')]);
}
}

View File

@ -1,8 +1,9 @@
<?php
namespace Incoviba\Repository;
namespace Incoviba\Repository\Contabilidad;
use Incoviba\Common\Define;
use Incoviba\Model;
use Incoviba\Repository\Tipo;
class CategoriaCentro extends Tipo
{
@ -14,6 +15,6 @@ class CategoriaCentro extends Tipo
protected function getBlank(): Define\Model
{
return new Model\CategoriaCentro();
return new Model\Contabilidad\CategoriaCentro();
}
}

View File

@ -1,12 +1,12 @@
<?php
namespace Incoviba\Repository;
namespace Incoviba\Repository\Contabilidad;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement\Repository\Mapper;
use Incoviba\Common\Implement\Repository\MapperParser;
use Incoviba\Repository;
use Incoviba\Model;
use Incoviba\Repository\TipoCuenta;
class CentroCosto extends Ideal\Repository
{
@ -18,7 +18,7 @@ class CentroCosto extends Ideal\Repository
$this->setTable('centros_costos');
}
public function create(?array $data = null): Model\CentroCosto
public function create(?array $data = null): Model\Contabilidad\CentroCosto
{
$map = (new MapperParser(['descripcion']))
->register('tipo_centro_id', (new Mapper())
@ -39,9 +39,9 @@ class CentroCosto extends Ideal\Repository
->setDefault(null))
->register('cuenta_contable', (new Mapper())
->setProperty('cuentaContable'));
return $this->parseData(new Model\CentroCosto(), $data, $map);
return $this->parseData(new Model\Contabilidad\CentroCosto(), $data, $map);
}
public function save(Define\Model $model): Model\CentroCosto
public function save(Define\Model $model): Model\Contabilidad\CentroCosto
{
$this->saveNew(
['id', 'tipo_centro_id', 'categoria_id', 'tipo_cuenta_id', 'cuenta_contable', 'descripcion'],
@ -49,12 +49,12 @@ class CentroCosto extends Ideal\Repository
);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\CentroCosto
public function edit(Define\Model $model, array $new_data): Model\Contabilidad\CentroCosto
{
return $this->update($model, ['tipo_centro_id', 'categoria_id', 'tipo_cuenta_id', 'cuenta_contable', 'descripcion'], $new_data);
}
public function fetchByDescripcion(string $descripcion): Model\CentroCosto
public function fetchByDescripcion(string $descripcion): Model\Contabilidad\CentroCosto
{
$query = $this->connection->getQueryBuilder()
->select()

View File

@ -1,12 +1,12 @@
<?php
namespace Incoviba\Repository;
namespace Incoviba\Repository\Contabilidad;
use DateTimeImmutable;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Repository;
use Incoviba\Model;
use Incoviba\Repository;
class Deposito extends Ideal\Repository
{
@ -16,7 +16,7 @@ class Deposito extends Ideal\Repository
$this->setTable('depositos');
}
public function create(?array $data = null): Model\Deposito
public function create(?array $data = null): Model\Contabilidad\Deposito
{
$map = (new Implement\Repository\MapperParser(['id', 'capital', 'futuro']))
->register('cuenta_id', (new Implement\Repository\Mapper())
@ -26,9 +26,9 @@ class Deposito extends Ideal\Repository
}))
->register('inicio', new Implement\Repository\Mapper\DateTime('inicio'))
->register('termino', new Implement\Repository\Mapper\DateTime('termino'));
return $this->parseData(new Model\Deposito(), $data, $map);
return $this->parseData(new Model\Contabilidad\Deposito(), $data, $map);
}
public function save(Define\Model $model): Model\Deposito
public function save(Define\Model $model): Model\Contabilidad\Deposito
{
$this->saveNew([
'id', 'cuenta_id', 'capital', 'futuro', 'inicio', 'termino'
@ -39,7 +39,7 @@ class Deposito extends Ideal\Repository
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\Deposito
public function edit(Define\Model $model, array $new_data): Model\Contabilidad\Deposito
{
return $this->update($model, ['cuenta_id', 'capital', 'futuro', 'inicio', 'termino'], $new_data);
}

View File

@ -1,11 +1,12 @@
<?php
namespace Incoviba\Repository;
namespace Incoviba\Repository\Contabilidad;
use DateTimeInterface;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Model;
use Incoviba\Repository\Inmobiliaria;
class Movimiento extends Ideal\Repository
{
@ -15,7 +16,7 @@ class Movimiento extends Ideal\Repository
$this->setTable('movimientos');
}
public function create(?array $data = null): Model\Movimiento
public function create(?array $data = null): Model\Contabilidad\Movimiento
{
$map = (new Implement\Repository\MapperParser(['cargo', 'abono', 'saldo', 'glosa', 'documento']))
->register('fecha', new Implement\Repository\Mapper\DateTime('fecha'))
@ -25,9 +26,9 @@ class Movimiento extends Ideal\Repository
return $this->cuentaRepository->fetchById($data['cuenta_id']);
})
);
return $this->parseData(new Model\Movimiento(), $data, $map);
return $this->parseData(new Model\Contabilidad\Movimiento(), $data, $map);
}
public function save(Define\Model $model): Model\Movimiento
public function save(Define\Model $model): Model\Contabilidad\Movimiento
{
$model->id = $this->saveNew([
'cuenta_id',
@ -48,7 +49,7 @@ class Movimiento extends Ideal\Repository
]);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\Movimiento
public function edit(Define\Model $model, array $new_data): Model\Contabilidad\Movimiento
{
return $this->update($model, ['cuenta_id', 'fecha', 'glosa', 'documento', 'cargo', 'abono', 'saldo'], $new_data);
}
@ -61,7 +62,7 @@ class Movimiento extends Ideal\Repository
->where('cuenta_id = ? AND fecha = ?');
return $this->fetchMany($query, [$cuenta_id, $fecha->format('Y-m-d')]);
}
public function fetchByCuentaAndFechaAndCargoAndAbonoAndSaldo(int $cuenta_id, DateTimeInterface $fecha, int $cargo, int $abono, int $saldo): Model\Movimiento
public function fetchByCuentaAndFechaAndCargoAndAbonoAndSaldo(int $cuenta_id, DateTimeInterface $fecha, int $cargo, int $abono, int $saldo): Model\Contabilidad\Movimiento
{
$query = $this->connection->getQueryBuilder()
->select()
@ -69,4 +70,12 @@ class Movimiento extends Ideal\Repository
->where('cuenta_id = ? AND fecha = ? AND cargo = ? AND abono = ? AND saldo = ?');
return $this->fetchOne($query, [$cuenta_id, $fecha->format('Y-m-d'), $cargo, $abono, $saldo]);
}
public function fetchAmountStartingFrom(int $start, int $amount): array
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->limit($amount, $start);
return $this->fetchMany($query);
}
}

View File

@ -1,10 +1,11 @@
<?php
namespace Incoviba\Repository;
namespace Incoviba\Repository\Contabilidad;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Model;
use Incoviba\Repository\Inmobiliaria;
class Nubox extends Ideal\Repository
{
@ -14,7 +15,7 @@ class Nubox extends Ideal\Repository
$this->setTable('inmobiliarias_nubox');
}
public function create(?array $data = null): Model\Nubox
public function create(?array $data = null): Model\Contabilidad\Nubox
{
$map = (new Implement\Repository\MapperParser(['usuario', 'alias']))
->register('inmobiliaria_rut', (new Implement\Repository\Mapper())
@ -24,9 +25,9 @@ class Nubox extends Ideal\Repository
}))
->register('contraseña', (new Implement\Repository\Mapper())
->setProperty('password'));
return $this->parseData(new Model\Nubox(), $data, $map);
return $this->parseData(new Model\Contabilidad\Nubox(), $data, $map);
}
public function save(Define\Model $model): Model\Nubox
public function save(Define\Model $model): Model\Contabilidad\Nubox
{
$this->saveNew(
['inmobiliaria_rut', 'alias', 'usuario', 'contraseña'],
@ -34,12 +35,12 @@ class Nubox extends Ideal\Repository
);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\Nubox
public function edit(Define\Model $model, array $new_data): Model\Contabilidad\Nubox
{
return $this->update($model, ['inmobiliaria_rut', 'alias', 'usuario', 'contraseña'], $new_data);
}
public function fetchByInmobiliaria(int $inmobiliaria_rut): Model\Nubox
public function fetchByInmobiliaria(int $inmobiliaria_rut): Model\Contabilidad\Nubox
{
$query = $this->connection->getQueryBuilder()
->select()

View File

@ -1,5 +1,5 @@
<?php
namespace Incoviba\Repository;
namespace Incoviba\Repository\Contabilidad;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
@ -15,7 +15,7 @@ class PagoCentroCosto extends Ideal\Repository
$this->setTable('pagos_centros_costos');
}
public function create(?array $data = null): Model\PagoCentroCosto
public function create(?array $data = null): Model\Contabilidad\PagoCentroCosto
{
$map = (new Implement\Repository\MapperParser())
->register('pago_id', (new Implement\Repository\Mapper())
@ -28,14 +28,14 @@ class PagoCentroCosto extends Ideal\Repository
->setFunction(function(array $data) {
return $this->centroCostoRepository->fetchById($data['centro_costo_id']);
}));
return $this->parseData(new Model\PagoCentroCosto(), $data, $map);
return $this->parseData(new Model\Contabilidad\PagoCentroCosto(), $data, $map);
}
public function save(Define\Model $model): Model\PagoCentroCosto
public function save(Define\Model $model): Model\Contabilidad\PagoCentroCosto
{
$model->id = $this->saveNew(['pago_id', 'centro_costo_id'], [$model->pago->id, $model->centroCosto->id]);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\PagoCentroCosto
public function edit(Define\Model $model, array $new_data): Model\Contabilidad\PagoCentroCosto
{
return $this->update($model, ['pago_id', 'centro_costo_id'], $new_data);
}

View File

@ -1,8 +1,9 @@
<?php
namespace Incoviba\Repository;
namespace Incoviba\Repository\Contabilidad;
use Incoviba\Common\Define;
use Incoviba\Model;
use Incoviba\Repository\Tipo;
class TipoCentro extends Tipo
{
@ -14,6 +15,6 @@ class TipoCentro extends Tipo
protected function getBlank(): Define\Model
{
return new Model\TipoCentro();
return new Model\Contabilidad\TipoCentro();
}
}

View File

@ -9,7 +9,7 @@ use Incoviba\Repository;
class Inmobiliaria extends Ideal\Repository
{
public function __construct(Define\Connection $connection, protected Repository\Banco $bancoRepository, protected Repository\Inmobiliaria\TipoSociedad $tipoSociedadRepository)
public function __construct(Define\Connection $connection, protected Contabilidad\Banco $bancoRepository, protected Repository\Inmobiliaria\TipoSociedad $tipoSociedadRepository)
{
parent::__construct($connection);
$this->setTable('inmobiliaria');
@ -20,13 +20,9 @@ class Inmobiliaria extends Ideal\Repository
return 'rut';
}
public function create(?array $data = null): Define\Model
public function create(?array $data = null): Model\Inmobiliaria
{
$map = (new Implement\Repository\MapperParser(['dv', 'razon', 'abreviacion', 'cuenta']))
->register('banco', (new Implement\Repository\Mapper())
->setFunction(function($data) {
return $this->bancoRepository->fetchById($data['banco']);
}))
$map = (new Implement\Repository\MapperParser(['dv', 'razon', 'abreviacion']))
->register('sociedad', (new Implement\Repository\Mapper())
->setProperty('tipoSociedad')
->setFunction(function($data) {
@ -34,7 +30,7 @@ class Inmobiliaria extends Ideal\Repository
}));
return $this->parseData(new Model\Inmobiliaria(), $data, $map);
}
public function save(Define\Model $model): Define\Model
public function save(Define\Model $model): Model\Inmobiliaria
{
$model->rut = $this->saveNew(
['dv', 'razon', 'abreviacion', 'cuenta', 'banco', 'sociedad'],
@ -42,7 +38,7 @@ class Inmobiliaria extends Ideal\Repository
);
return $model;
}
public function edit(Define\Model $model, array $new_data): Define\Model
public function edit(Define\Model $model, array $new_data): Model\Inmobiliaria
{
return $this->update($model, ['dv', 'razon', 'abreviacion', 'cuenta', 'banco', 'sociedad'], $new_data);
}

View File

@ -0,0 +1,47 @@
<?php
namespace Incoviba\Repository\Inmobiliaria;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Model;
use Incoviba\Repository;
class Agente extends Ideal\Repository
{
public function __construct(Define\Connection $connection, protected Repository\Direccion $direccionRepository, protected TipoAgente $tipoAgenteRepository)
{
parent::__construct($connection);
$this->setTable('agente');
}
public function create(?array $data = null): Model\Inmobiliaria\Agente
{
$map = (new Implement\Repository\MapperParser(['rut', 'descripcion', 'telefono', 'correo', 'giro', 'abreviacion']))
->register('representante', (new Implement\Repository\Mapper())
->setProperty('contacto'))
->register('direccion', (new Implement\Repository\Mapper())
->setFunction(function(?array $data) {
if ($data === null) {
return null;
}
return $this->direccionRepository->fetchById($data['direccion']);
}));
return $this->parseData(new Model\Inmobiliaria\Agente(), $data, $map);
}
public function save(Define\Model $model): Model\Inmobiliaria\Agente
{
$model->id = $this->saveNew([
'rut', 'descripcion', 'representante', 'telefono', 'correo', 'giro', 'abreviacion'
], [
$model->rut, $model->descripcion, $model->contacto, $model->telefono, $model->correo, $model->giro, $model->abreviacion
]);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\Inmobiliaria\Agente
{
return $this->update($model, [
'rut', 'descripcion', 'representante', 'telefono', 'correo', 'giro', 'abreviacion'
], $new_data);
}
}

Some files were not shown because too many files have changed in this diff Show More