0.1.0
This commit is contained in:
@ -7,6 +7,6 @@ RUN docker-php-ext-install zip
|
|||||||
RUN pecl install xdebug-3.1.1 \
|
RUN pecl install xdebug-3.1.1 \
|
||||||
&& docker-php-ext-enable xdebug
|
&& docker-php-ext-enable xdebug
|
||||||
|
|
||||||
WORKDIR /code
|
WORKDIR /app/ui
|
||||||
|
|
||||||
COPY --from=composer /usr/bin/composer /usr/bin/composer
|
COPY --from=composer /usr/bin/composer /usr/bin/composer
|
||||||
|
14
common/Controller/Precios.php
Normal file
14
common/Controller/Precios.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\UI\Common\Controller;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Slim\Views\Blade as View;
|
||||||
|
|
||||||
|
class Precios
|
||||||
|
{
|
||||||
|
public function proyectos(ServerRequestInterface $request, ResponseInterface $response, View $view): ResponseInterface
|
||||||
|
{
|
||||||
|
return $view->render($response, 'ventas.precios.proyectos');
|
||||||
|
}
|
||||||
|
}
|
14
common/Controller/Proyectos.php
Normal file
14
common/Controller/Proyectos.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\UI\Common\Controller;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Slim\Views\Blade as View;
|
||||||
|
|
||||||
|
class Proyectos
|
||||||
|
{
|
||||||
|
public function precios(ServerRequestInterface $request, ResponseInterface $response, View $view, $proyecto_id): ResponseInterface
|
||||||
|
{
|
||||||
|
return $view->render($response, 'ventas.precios.list', compact('proyecto_id'));
|
||||||
|
}
|
||||||
|
}
|
18
common/Controller/Ventas.php
Normal file
18
common/Controller/Ventas.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\UI\Common\Controller;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Slim\Views\Blade as View;
|
||||||
|
|
||||||
|
class Ventas
|
||||||
|
{
|
||||||
|
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, View $view): ResponseInterface
|
||||||
|
{
|
||||||
|
return $view->render($response, 'ventas.proyectos');
|
||||||
|
}
|
||||||
|
public function get(ServerRequestInterface $request, ResponseInterface $response, View $view, $proyecto_id): ResponseInterface
|
||||||
|
{
|
||||||
|
return $view->render($response, 'ventas.list', compact('proyecto_id'));
|
||||||
|
}
|
||||||
|
}
|
@ -85,9 +85,10 @@ class Auth {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($response->getStatusCode() != 200) {
|
if ($response->getStatusCode() != 200) {
|
||||||
|
error_log(var_export($response, true));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$data = json_decode($response->getBody());
|
$data = json_decode($response->getBody()->getContents());
|
||||||
if (!$data->login) {
|
if (!$data->login) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,9 @@
|
|||||||
"zeuxisoo/slim-whoops": "^0.7.3",
|
"zeuxisoo/slim-whoops": "^0.7.3",
|
||||||
"nyholm/psr7": "^1.4",
|
"nyholm/psr7": "^1.4",
|
||||||
"nyholm/psr7-server": "^1.0",
|
"nyholm/psr7-server": "^1.0",
|
||||||
"rubellum/slim-blade-view": "^0.1.1",
|
|
||||||
"nesbot/carbon": "^2.54",
|
"nesbot/carbon": "^2.54",
|
||||||
"guzzlehttp/guzzle": "^7.4"
|
"guzzlehttp/guzzle": "^7.4",
|
||||||
|
"berrnd/slim-blade-view": "^1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^9.5",
|
"phpunit/phpunit": "^9.5",
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name api;
|
server_name ui;
|
||||||
index index.php;
|
index index.php;
|
||||||
error_log /code/logs/error.log;
|
error_log /var/log/nginx/ui.error.log;
|
||||||
access_log /code/logs/access.log;
|
access_log /var/log/nginx/ui.access.log;
|
||||||
root /code/public;
|
root /app/ui/public;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri /index.php$is_args$args;
|
try_files $uri /index.php$is_args$args;
|
||||||
|
170
public/js/ventas/list.js
Normal file
170
public/js/ventas/list.js
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
const ventas = {
|
||||||
|
url: '',
|
||||||
|
id_proyecto: '',
|
||||||
|
id_ventas: '',
|
||||||
|
setup: function() {
|
||||||
|
sendGet(this.url).then(response => {
|
||||||
|
const formatters = {
|
||||||
|
pesos: Intl.NumberFormat('es-CL', {style: 'decimal', useGrouping: true}),
|
||||||
|
uf: Intl.NumberFormat('es-CL', {style: 'decimal', useGrouping: true, minimumFractionDigits: 2, maximumFractionDigits: 2})
|
||||||
|
}
|
||||||
|
const p = new Proyecto(response.proyecto)
|
||||||
|
p.set().formatters(formatters)
|
||||||
|
p.draw().title($(this.id_proyecto))
|
||||||
|
p.draw().ventas($(this.id_ventas))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Proyecto {
|
||||||
|
constructor({id, descripcion, ventas}) {
|
||||||
|
this.id = id
|
||||||
|
this.descripcion = descripcion
|
||||||
|
this.set().ventas(ventas)
|
||||||
|
this.formatters = {
|
||||||
|
uf: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set() {
|
||||||
|
return {
|
||||||
|
ventas: ventas => {
|
||||||
|
this.ventas = ventas.map(el => {
|
||||||
|
return new Venta(el)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
formatters: formatters => {
|
||||||
|
this.formatters = formatters
|
||||||
|
this.ventas.forEach(v => {
|
||||||
|
v.set().formatters(formatters)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw() {
|
||||||
|
return {
|
||||||
|
title: parent => {
|
||||||
|
parent.append(
|
||||||
|
$('<a></a>').attr('href', _urls.base + '/proyecto/' + this.id).html(this.descripcion + ' [' + this.ventas.length + ']')
|
||||||
|
)
|
||||||
|
},
|
||||||
|
ventas: tbody => {
|
||||||
|
this.ventas.forEach(venta => {
|
||||||
|
venta.draw().row(tbody)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Venta {
|
||||||
|
constructor({id, propiedad, propietario, fecha, valor, estado}) {
|
||||||
|
this.id = id
|
||||||
|
this.unidades = ''
|
||||||
|
this.set().unidades(propiedad)
|
||||||
|
this.propiedad = propiedad
|
||||||
|
this.superficie = 0
|
||||||
|
this.set().superficie(propiedad)
|
||||||
|
this.tipologia = ''
|
||||||
|
this.set().tipologia(propiedad)
|
||||||
|
this.propietario = ''
|
||||||
|
this.set().propietario(propietario)
|
||||||
|
this.fecha = fecha
|
||||||
|
this.valor = valor
|
||||||
|
this.estado = ''
|
||||||
|
this.set().estado(estado)
|
||||||
|
this.formatters = {
|
||||||
|
uf: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set() {
|
||||||
|
return {
|
||||||
|
unidades: propiedad => {
|
||||||
|
const departamentos = propiedad.unidades.filter(u => {
|
||||||
|
return (u.tipo.descripcion === 'departamento')
|
||||||
|
}).map(u => {
|
||||||
|
return u.descripcion
|
||||||
|
}).join('-')
|
||||||
|
let bodegas = []
|
||||||
|
let estacionamientos = propiedad.unidades.filter(u => {
|
||||||
|
return (u.tipo.descripcion === 'estacionamiento')
|
||||||
|
}).map(u => {
|
||||||
|
if (u.descripcion.includes('B')) {
|
||||||
|
const e = u.descripcion.split('B')
|
||||||
|
while (e.length > 1) {
|
||||||
|
bodegas.push(e.pop().replace(' ', '').replace('-', ','))
|
||||||
|
}
|
||||||
|
return e[0].replace(' ', '').replace(',', '').replace('-', ',')
|
||||||
|
}
|
||||||
|
return u.descripcion.replace(' ', '').replace('-', ',').replace('y ', ',')
|
||||||
|
}).sort((a, b) => {
|
||||||
|
return parseInt(a) - parseInt(b)
|
||||||
|
})
|
||||||
|
if (estacionamientos.length > 0) {
|
||||||
|
estacionamientos = ' - E' + estacionamientos.join(',').replace(/(,\s)*$/g, '')
|
||||||
|
} else {
|
||||||
|
estacionamientos = ''
|
||||||
|
}
|
||||||
|
bodegas = [...(bodegas.filter(el => el !== '')), ...(propiedad.unidades.filter(u => {
|
||||||
|
return (u.tipo.descripcion === 'bodega')
|
||||||
|
}).map(u => {
|
||||||
|
return u.descripcion.replace(' ', '').replace('-', ',')
|
||||||
|
}))].sort((a, b) => {
|
||||||
|
return parseInt(a) - parseInt(b)
|
||||||
|
}).filter(el => el !== '')
|
||||||
|
if (bodegas.length > 0) {
|
||||||
|
bodegas = ' - B' + bodegas.join(',').replace(/(,\s)*$/g, '')
|
||||||
|
} else {
|
||||||
|
bodegas = ''
|
||||||
|
}
|
||||||
|
this.unidades = departamentos + estacionamientos + bodegas
|
||||||
|
},
|
||||||
|
superficie: propiedad => {
|
||||||
|
const unidad = propiedad.unidades[0]
|
||||||
|
this.superficie = unidad.proyectoTipoUnidad.superficie.vendible
|
||||||
|
},
|
||||||
|
tipologia: propiedad => {
|
||||||
|
const unidad = propiedad.unidades[0]
|
||||||
|
this.tipologia = unidad.proyectoTipoUnidad.tipologia.abreviacion
|
||||||
|
},
|
||||||
|
propietario: propietario => {
|
||||||
|
this.propietario = propietario.nombreCompleto
|
||||||
|
},
|
||||||
|
estado: estado => {
|
||||||
|
this.estado = estado.estado.descripcion.replace(/\w\S*/g, function(txt) { return txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase(); })
|
||||||
|
},
|
||||||
|
formatters: formatters => {
|
||||||
|
this.formatters = formatters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw() {
|
||||||
|
return {
|
||||||
|
row: parent => {
|
||||||
|
parent.append(
|
||||||
|
$('<tr></tr>').append(
|
||||||
|
$('<td></td>').append(
|
||||||
|
$('<a></a>')
|
||||||
|
.attr('href', _urls.base + '/venta/' + this.id)
|
||||||
|
.html(this.unidades)
|
||||||
|
.append('<span class="glyphicon glyphicon-chevron-right small"></span>')
|
||||||
|
)
|
||||||
|
).append(
|
||||||
|
$('<td></td>').append(
|
||||||
|
$('<a></a>')
|
||||||
|
.attr('href', _urls.base + '/search/' + encodeURIComponent(this.propietario))
|
||||||
|
.html(this.propietario + ' <span class="glyphicon glyphicon-search small"></span>')
|
||||||
|
)
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(this.formatters.uf.format(this.valor) + ' UF')
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(this.tipologia + ' (' + this.formatters.uf.format(this.superficie) + ' m²)')
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(this.formatters.uf.format(this.valor / this.superficie) + ' UF/m²')
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(new Date(this.fecha.date).toLocaleDateString('es-CL'))
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(this.estado)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
resources/routes/04_proyectos.php
Normal file
10
resources/routes/04_proyectos.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
$app->group('/proyectos', function($app) {
|
||||||
|
$app->get('[/]', \Incoviba\UI\Common\Controller\Proyectos::class);
|
||||||
|
});
|
||||||
|
$app->group('/proyecto/{proyecto_id}', function($app) {
|
||||||
|
$app->group('/precios', function($app) {
|
||||||
|
$app->get('/add', [\Incoviba\UI\Common\Controller\Precios::class, 'add']);
|
||||||
|
$app->get('[/]', [\Incoviba\UI\Common\Controller\Proyectos::class, 'precios']);
|
||||||
|
});
|
||||||
|
});
|
6
resources/routes/05_ventas.php
Normal file
6
resources/routes/05_ventas.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
$app->group('/ventas', function($app) {
|
||||||
|
$app->get('/{proyecto_id}', [\Incoviba\UI\Common\Controller\Ventas::class, 'get']);
|
||||||
|
$app->get('[/]', \Incoviba\UI\Common\Controller\Ventas::class);
|
||||||
|
});
|
||||||
|
$app->get('/precios', [\Incoviba\UI\Common\Controller\Precios::class, 'proyectos']);
|
@ -20,7 +20,7 @@
|
|||||||
<script type="text/javascript" src="{{$urls->scripts}}/home.js"></script>
|
<script type="text/javascript" src="{{$urls->scripts}}/home.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
home.token = '{{$_COOKIE['rememberMe']}}'
|
home.token = '{{$_COOKIE['rememberMe'] ?? ''}}'
|
||||||
home.setup()
|
home.setup()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="{{$urls->styles}}/app.css" />
|
<link rel="stylesheet" type="text/css" href="{{$urls->styles}}/app.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="{{$urls->styles}}/custom.css" />
|
<link rel="stylesheet" type="text/css" href="{{$urls->styles}}/custom.css" />
|
||||||
<link rel="icon" type="image/png" href="{{$urls->images}}/Isotipo 32.png" />
|
<link rel="icon" type="image/png" href="{{$urls->images}}/Isotipo 32.png" />
|
||||||
<script type="text/javascript" src="{{$urls->scripts}}/app.js"></script>
|
|
||||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.7.8/semantic.min.js"></script>
|
|
||||||
|
|
||||||
@stack('styles')
|
@stack('styles')
|
||||||
</head>
|
</head>
|
||||||
@ -29,6 +27,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@include('layout.footer')
|
@include('layout.footer')
|
||||||
|
<script type="text/javascript" src="{{$urls->scripts}}/app.js"></script>
|
||||||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.7.8/semantic.min.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
const API_KEY = '{{$api_key}}'
|
const API_KEY = '{{$api_key}}'
|
||||||
const _urls = {
|
const _urls = {
|
||||||
|
@ -1,42 +1,33 @@
|
|||||||
@extends('layout.base')
|
@extends('layout.base')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="row page-heading">
|
<div class="row page-heading">
|
||||||
<h3>Ventas de <a href="{{url('', ['p' => 'proyectos', 'a' => 'show', 'proyecto' => $proyecto->id])}}">{{$proyecto->descripcion}}</a> [{{count($ventas)}}]</h3>
|
<h3>Ventas de <span id="proyecto"></span></h3>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="section-heading">
|
<tr class="section-heading">
|
||||||
<th>@include('ventas.sort_title', ['title' => 'Departamento'])</th>
|
<th>Departamento</th>
|
||||||
<th>@include('ventas.sort_title', ['title' => 'Propietario'])</th>
|
<th>Propietario</th>
|
||||||
<th>@include('ventas.sort_title', ['title' => 'Valor [UF]'])</th>
|
<th>Valor [UF]</th>
|
||||||
<th>@include('ventas.sort_title', ['title' => 'Tipología'])</th>
|
<th>Tipología</th>
|
||||||
<th>@include('ventas.sort_title', ['title' => 'UF/m²'])</th>
|
<th>UF/m²</th>
|
||||||
<th>@include('ventas.sort_title', ['title' => 'Fecha Venta'])</th>
|
<th>Fecha Venta</th>
|
||||||
<th>@include('ventas.sort_title', ['title' => 'Estado'])</th>
|
<th>Estado</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody id="ventas"></tbody>
|
||||||
@foreach ($ventas as $venta)
|
</table>
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<a href="?p=ventas&a=show&venta={{$venta->id}}">
|
|
||||||
{{trim(array_reduce($venta->propiedad()->departamentos(), function($carry, $item) {
|
|
||||||
return implode(' - ', [$carry, $item->descripcion]);
|
|
||||||
}), ' -')}}
|
|
||||||
{{(count($venta->propiedad()->estacionamientos('array')) > 0) ? ' - E' . implode(', ', $venta->propiedad()->estacionamientos('array')) : ''}}
|
|
||||||
{{(count($venta->propiedad()->bodegas('array')) > 0) ? ' - B' . implode(', ', $venta->propiedad()->bodegas('array')) : ''}}
|
|
||||||
<span class="glyphicon glyphicon-chevron-right small"></span>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td><a href="?p=search&q={{urlencode('"' . $venta->propietario()->nombreCompleto() . '"')}}">{{$venta->propietario()->nombreCompleto()}} <span class="glyphicon glyphicon-search small"></span></a></td>
|
|
||||||
<td>{{$format->ufs($venta->valor_uf)}}</td>
|
|
||||||
<td>{{$venta->propiedad()->unidad()->tipologia()->tipologia()->descripcion}} ({{format('m2', $venta->propiedad()->unidad()->tipologia()->m2())}} m²)</td>
|
|
||||||
<td>{{$format->ufs($venta->uf_m2())}}</td>
|
|
||||||
<td>{{$venta->fecha()->format('d-m-Y')}}</td>
|
|
||||||
<td>{{ucwords($venta->estado()->tipo()->descripcion)}}</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script type="text/javascript" src="{{$urls->scripts}}/ventas/list.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(() => {
|
||||||
|
ventas.url = '/proyecto/{{$proyecto_id}}/ventas'
|
||||||
|
ventas.id_proyecto = '#proyecto'
|
||||||
|
ventas.id_ventas = '#ventas'
|
||||||
|
ventas.setup()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
@ -5,9 +5,13 @@
|
|||||||
<h3>
|
<h3>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
Precios - {{$proyecto->descripcion}}
|
Precios - <span id="proyecto"></span>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 text-right">
|
||||||
|
<a href="{{$urls->base}}/proyecto/{{$proyecto_id}}/precios/add">
|
||||||
|
<span class="glyphicon glyphicon-plus"></span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 text-right"><a href="{{nUrl('precios', 'add', ['proyecto' => $proyecto->id])}}"><span class="glyphicon glyphicon-plus"></span></a></div>
|
|
||||||
</div>
|
</div>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
@ -25,110 +29,323 @@
|
|||||||
<th>UF/m²</th>
|
<th>UF/m²</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody id="tipos"></tbody>
|
||||||
@foreach ($proyecto->ProyectoTipoUnidades() as $tipo)
|
|
||||||
<tr class="show-unidades" data-status="closed" data-id="{{$tipo->id}}">
|
|
||||||
<td>{{ucwords($tipo->tipo()->descripcion)}}</td>
|
|
||||||
<td>{{$tipo->nombre}}</td>
|
|
||||||
<td>
|
|
||||||
@if ($tipo->tipologia())
|
|
||||||
{{$tipo->tipologia()->descripcion}}
|
|
||||||
@else
|
|
||||||
{{$tipo->abreviacion}}
|
|
||||||
@endif
|
|
||||||
</td>
|
|
||||||
<td>{{$tipo->lineas()}}</td>
|
|
||||||
<td>{{$tipo->m2()}}</td>
|
|
||||||
<td>{{count($tipo->unidades())}}</td>
|
|
||||||
<td>{{format('ufs', $tipo->precio(), true)}}</td>
|
|
||||||
<th>
|
|
||||||
@if ($tipo->m2() > 0)
|
|
||||||
{{format('ufs', $tipo->precio() / $tipo->m2(), true)}}/m²
|
|
||||||
@else
|
|
||||||
-
|
|
||||||
@endif
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr class="unidades" data-tipo="{{$tipo->id}}">
|
|
||||||
<td></td>
|
|
||||||
<td colspan="7">
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Unidad</th>
|
|
||||||
<th>Desde</th>
|
|
||||||
<th>Precio</th>
|
|
||||||
<th>UF/m²</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $subtipo = ''; ?>
|
|
||||||
@foreach ($tipo->unidades() as $unidad)
|
|
||||||
@if ($subtipo != $unidad->subtipo)
|
|
||||||
<?php $subtipo = $unidad->subtipo; ?>
|
|
||||||
<tr data-id="{{$subtipo}}" data-status="closed" class="subtipo">
|
|
||||||
<th>Línea {{$subtipo}}</th>
|
|
||||||
<th></th>
|
|
||||||
<th>{{format('ufs', $tipo->precioSubtipo($subtipo), null, true)}}</th>
|
|
||||||
<th>{{format('ufs', $tipo->precioSubtipo($subtipo) / $tipo->m2(), null, true)}}/m²</th>
|
|
||||||
</tr>
|
|
||||||
@endif
|
|
||||||
<tr>
|
|
||||||
<td>{{$unidad->descripcion}}</td>
|
|
||||||
@if ($unidad->precio())
|
|
||||||
<td>{{format('shortDate', $unidad->precio()->estado()->fecha)}}</td>
|
|
||||||
<td>{{format('ufs', $unidad->precio()->valor, null, true)}}</td>
|
|
||||||
<td>
|
|
||||||
@if ($unidad->m2('vendible') > 0)
|
|
||||||
{{format('ufs', $unidad->precio()->valor / $unidad->m2('vendible'), null, true)}}/m²
|
|
||||||
@else
|
|
||||||
-
|
|
||||||
@endif
|
|
||||||
</td>
|
|
||||||
@else
|
|
||||||
<td colspan="3">--</td>
|
|
||||||
@endif
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
class Proyecto {
|
||||||
$('.unidades').hide()
|
constructor({id, inmobiliaria, descripcion, direccion, valor_terreno, superficie, corredor, pisos, subterraneos, tipos}) {
|
||||||
$('.show-unidades').css('cursor', 'pointer').click(function(e) {
|
this.id = id
|
||||||
var id = $(this).attr('data-id')
|
this.inmobiliaria = inmobiliaria
|
||||||
var status = $(this).attr('data-status')
|
this.descripcion = descripcion
|
||||||
if (status == 'open') {
|
this.tipos = tipos.map(t => {
|
||||||
$(".unidades[data-tipo='" + id + "']").hide()
|
return new Tipo(t)
|
||||||
$(this).attr('data-status', 'closed')
|
})
|
||||||
} else {
|
this.formatters = {pesos: null, uf: null}
|
||||||
$(".unidades[data-tipo='" + id + "']").show()
|
}
|
||||||
if ($(".unidades[data-tipo='" + id + "']").find('.subtipo').length > 0) {
|
draw() {
|
||||||
$(".unidades[data-tipo='" + id + "']").find('tbody tr').hide()
|
$('#proyecto').html(this.descripcion)
|
||||||
$(".unidades[data-tipo='" + id + "']").find('.subtipo').show()
|
const p = $('#tipos')
|
||||||
|
this.tipos.forEach(t => {
|
||||||
|
t.draw(p)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
set() {
|
||||||
|
return {
|
||||||
|
formatters: formatters => {
|
||||||
|
this.formatters = formatters
|
||||||
|
this.tipos.forEach(t => {
|
||||||
|
t.set().formatters(formatters)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
$(this).attr('data-status', 'open')
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
$('.subtipo').css('cursor', 'pointer').click(function(e) {
|
setup(formatters) {
|
||||||
var id = $(this).attr('data-id')
|
this.set().formatters(formatters)
|
||||||
var status = $(this).attr('data-status')
|
this.draw()
|
||||||
if (status == 'open') {
|
$('.unidades').hide()
|
||||||
$(this).nextUntil('.subtipo').hide()
|
$('.show-unidades').css('cursor', 'pointer').click(function(e) {
|
||||||
$(this).attr('data-status', 'closed')
|
var id = $(this).attr('data-id')
|
||||||
|
var status = $(this).attr('data-status')
|
||||||
|
if (status == 'open') {
|
||||||
|
$(".unidades[data-tipo='" + id + "']").hide()
|
||||||
|
$(this).attr('data-status', 'closed')
|
||||||
|
} else {
|
||||||
|
$(".unidades[data-tipo='" + id + "']").show()
|
||||||
|
if ($(".unidades[data-tipo='" + id + "']").find('.subtipo').length > 0) {
|
||||||
|
$(".unidades[data-tipo='" + id + "']").find('tbody tr').hide()
|
||||||
|
$(".unidades[data-tipo='" + id + "']").find('.subtipo').show()
|
||||||
|
}
|
||||||
|
$(this).attr('data-status', 'open')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$('.subtipo').css('cursor', 'pointer').click(function(e) {
|
||||||
|
var id = $(this).attr('data-id')
|
||||||
|
var status = $(this).attr('data-status')
|
||||||
|
if (status == 'open') {
|
||||||
|
$(this).nextUntil('.subtipo').hide()
|
||||||
|
$(this).attr('data-status', 'closed')
|
||||||
|
} else {
|
||||||
|
$(this).nextUntil('.subtipo').show()
|
||||||
|
$(this).attr('data-status', 'open')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Tipo {
|
||||||
|
constructor({id, tipo, nombre, abreviacion, tipologia, superficie, unidades, precio}) {
|
||||||
|
this.id = id
|
||||||
|
this.tipo = tipo
|
||||||
|
this.nombre = nombre
|
||||||
|
this.abreviacion = abreviacion
|
||||||
|
this.tipologia = tipologia
|
||||||
|
this.superficie = superficie
|
||||||
|
this.unidades = unidades.map(u => {
|
||||||
|
return new Unidad(u)
|
||||||
|
})
|
||||||
|
this.precio = precio
|
||||||
|
this.formatters = {pesos: null, uf: null}
|
||||||
|
this.subtipos = []
|
||||||
|
}
|
||||||
|
draw(parent) {
|
||||||
|
let tr = $('<tr></tr>').attr('class', 'show-unidades').attr('data-status', 'closed')
|
||||||
|
.attr('data-id', this.id).append(
|
||||||
|
$('<td></td>').html(this.tipo.descripcion.replace(/\w\S*/g, function(txt) { return txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase(); }))
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(this.nombre)
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(this.abreviacion)
|
||||||
|
).append(
|
||||||
|
$('<td></td>').attr('class', 'lineas')
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(this.superficie.vendible > 0 ? this.formatters.uf.format(this.superficie.vendible) + ' m²' : '-')
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(this.unidades.length)
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(this.get().precio().formateado + ' UF')
|
||||||
|
)
|
||||||
|
if ((this.get().precio().total / this.superficie.vendible) < Infinity) {
|
||||||
|
tr.append(
|
||||||
|
$('<th></th>').html(this.formatters.uf.format(this.get().precio().total / this.superficie.vendible) + ' UF/m²')
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
$(this).nextUntil('.subtipo').show()
|
tr.append(
|
||||||
$(this).attr('data-status', 'open')
|
$('<th></th>')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
parent.append(tr)
|
||||||
|
const table = $('<table></table>').attr('class', 'table table-striped').append(
|
||||||
|
$('<thead></thead>').append(
|
||||||
|
$('<tr></tr>').append(
|
||||||
|
$('<th></th>').html('Unidad')
|
||||||
|
).append(
|
||||||
|
$('<th></th>').html('Desde')
|
||||||
|
).append(
|
||||||
|
$('<th></th>').html('Precio')
|
||||||
|
).append(
|
||||||
|
$('<th></th>').html('UF/m²')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).append(
|
||||||
|
$('<tbody></tbody>')
|
||||||
|
)
|
||||||
|
tr = $('<tr></tr>').attr('class', 'unidades').attr('data-tipo', this.id).append(
|
||||||
|
$('<td></td>')
|
||||||
|
).append(
|
||||||
|
$('<td></td>').attr('colspan', 7).append(table)
|
||||||
|
)
|
||||||
|
parent.append(tr)
|
||||||
|
let subtipo = null
|
||||||
|
this.unidades.forEach(el => {
|
||||||
|
subtipo = el.draw(table.find('tbody'), subtipo)
|
||||||
|
this.add().subtipo(subtipo)
|
||||||
|
})
|
||||||
|
subtipo.draw().precio(parent)
|
||||||
|
parent.find("[data-id='" + this.id + "']").find('.lineas').html(this.get().lineas())
|
||||||
|
}
|
||||||
|
get() {
|
||||||
|
return {
|
||||||
|
precio: () => {
|
||||||
|
let precio = 0
|
||||||
|
this.unidades.forEach(u => {
|
||||||
|
precio += u.precio.valor
|
||||||
|
})
|
||||||
|
const total = precio
|
||||||
|
precio /= this.unidades.length
|
||||||
|
return {
|
||||||
|
valor: precio,
|
||||||
|
total,
|
||||||
|
formateado: this.formatters.uf.format(precio)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lineas: () => {
|
||||||
|
let lineas = []
|
||||||
|
this.subtipos.forEach(s => {
|
||||||
|
lineas.push(s.nombre)
|
||||||
|
})
|
||||||
|
return lineas.join(' - ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set() {
|
||||||
|
return {
|
||||||
|
formatters: formatters => {
|
||||||
|
this.formatters = formatters
|
||||||
|
this.unidades.forEach(u => {
|
||||||
|
u.set().formatters(formatters)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add() {
|
||||||
|
return {
|
||||||
|
subtipo: subtipo => {
|
||||||
|
if (this.subtipos.indexOf(subtipo) === -1) {
|
||||||
|
this.subtipos.push(subtipo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Subtipo {
|
||||||
|
constructor({nombre}) {
|
||||||
|
this.nombre = nombre
|
||||||
|
this.unidades = []
|
||||||
|
this.formatters = {pesos: null, uf: null}
|
||||||
|
}
|
||||||
|
add() {
|
||||||
|
return {
|
||||||
|
unidad: unidad => {
|
||||||
|
this.unidades.push(unidad)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get() {
|
||||||
|
return {
|
||||||
|
precio: () => {
|
||||||
|
let precio = 0
|
||||||
|
this.unidades.forEach(un => {
|
||||||
|
precio += un.precio.valor
|
||||||
|
})
|
||||||
|
const total = precio
|
||||||
|
precio /= this.unidades.length
|
||||||
|
return {
|
||||||
|
precio,
|
||||||
|
total
|
||||||
|
}
|
||||||
|
},
|
||||||
|
superficie: () => {
|
||||||
|
let superficie = 0
|
||||||
|
this.unidades.forEach(un => {
|
||||||
|
superficie += un.superficie.vendible
|
||||||
|
})
|
||||||
|
return superficie
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set() {
|
||||||
|
return {
|
||||||
|
formatters: formatters => {
|
||||||
|
this.formatters = formatters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw() {
|
||||||
|
return {
|
||||||
|
precio: parent => {
|
||||||
|
const tr = parent.find("[data-id='" + this.nombre + "']")
|
||||||
|
tr.find('.precio').html(this.formatters.uf.format(this.get().precio().precio) + ' UF')
|
||||||
|
if (this.get().precio().total / this.get().superficie() < Infinity) {
|
||||||
|
tr.find('.uf_m2').html(this.formatters.uf.format(this.get().precio().total / this.get().superficie()) + ' UF/m²')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Unidad {
|
||||||
|
constructor({id, subtipo, descripcion, precio, fecha, superficie}) {
|
||||||
|
this.id = id
|
||||||
|
this.subtipo = subtipo
|
||||||
|
this.descripcion = descripcion
|
||||||
|
this.precio = precio
|
||||||
|
this.fecha = fecha
|
||||||
|
this.superficie = superficie
|
||||||
|
this.formatters = {pesos: null, uf: null}
|
||||||
|
}
|
||||||
|
build() {
|
||||||
|
return {
|
||||||
|
subtipo: (parent, nombre) => {
|
||||||
|
const subtipo = new Subtipo({nombre})
|
||||||
|
subtipo.set().formatters(this.formatters)
|
||||||
|
parent.append(
|
||||||
|
$('<tr></tr>').attr('data-id', subtipo.nombre).attr('data-status', 'closed').attr('class', 'subtipo').append(
|
||||||
|
$('<th></th>').html('Línea ' + subtipo.nombre)
|
||||||
|
).append(
|
||||||
|
$('<th></th>')
|
||||||
|
).append(
|
||||||
|
$('<th></th>').attr('class', 'precio')
|
||||||
|
).append(
|
||||||
|
$('<th></th>').attr('class', 'uf_m2')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return subtipo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw(parent, subtipo) {
|
||||||
|
if (typeof subtipo === 'undefined' || subtipo === null) {
|
||||||
|
subtipo = this.build().subtipo(parent, this.subtipo)
|
||||||
|
} else if (subtipo.nombre !== this.subtipo) {
|
||||||
|
subtipo.draw().precio(parent)
|
||||||
|
subtipo = this.build().subtipo(parent, this.subtipo)
|
||||||
|
}
|
||||||
|
subtipo.add().unidad(this)
|
||||||
|
const tr = $('<tr></tr>').append(
|
||||||
|
$('<td></td>').html(this.descripcion)
|
||||||
|
)
|
||||||
|
if (this.precio.valor) {
|
||||||
|
tr.append(
|
||||||
|
$('<td></td>').html(new Date(this.precio.estado.fecha.date).toLocaleDateString('es-CL'))
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html(this.formatters.uf.format(this.precio.valor) + ' UF')
|
||||||
|
).append(
|
||||||
|
$('<td></td>').html((this.superficie.vendible > 0) ? this.formatters.uf.format(this.get().ufM2()) + ' UF/m²' : '-')
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
tr.append(
|
||||||
|
$('<td></td>').attr('colspan', 3).html('--')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
parent.append(tr)
|
||||||
|
return subtipo
|
||||||
|
}
|
||||||
|
get() {
|
||||||
|
return {
|
||||||
|
ufM2: () => {
|
||||||
|
return this.precio.valor / this.superficie.vendible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set() {
|
||||||
|
return {
|
||||||
|
formatters: formatters => {
|
||||||
|
this.formatters = formatters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$(document).ready(function() {
|
||||||
|
sendGet('/proyecto/' + {{$proyecto_id}} + '/precios').then(response => {
|
||||||
|
const formatters = {
|
||||||
|
pesos: Intl.NumberFormat('es-CL', {style: 'decimal', useGrouping: true}),
|
||||||
|
uf: Intl.NumberFormat('es-CL', {style: 'decimal', useGrouping: true, minimumFractionDigits: 2, maximumFractionDigits: 2})
|
||||||
|
}
|
||||||
|
const proyecto = new Proyecto(response.proyecto)
|
||||||
|
proyecto.setup(formatters)
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
|
@ -5,10 +5,24 @@
|
|||||||
<h3>Precios</h3>
|
<h3>Precios</h3>
|
||||||
</div>
|
</div>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
@foreach ($proyectos as $proyecto)
|
<tbody id="proyectos"></tbody>
|
||||||
<tr>
|
|
||||||
<td><a href="{{nUrl('precios', 'list', ['proyecto' => $proyecto->id])}}">{{$proyecto->descripcion}}</a>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</table>
|
</table>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(() => {
|
||||||
|
sendGet('/proyectos').then(response => {
|
||||||
|
response.proyectos.forEach(el => {
|
||||||
|
$('#proyectos').append(
|
||||||
|
$('<tr></tr>').append(
|
||||||
|
$('<td></td>').append(
|
||||||
|
$('<a></a>').attr('href', '{{$urls->base}}/proyecto/' + el.id + '/precios').html(el.descripcion)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
@ -7,12 +7,29 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
@foreach ($proyectos as $proyecto)
|
<tbody id="proyectos"></tbody>
|
||||||
<tr>
|
|
||||||
<td><a href="{{url('', ['p' => 'ventas', 'a' => 'list', 'proyecto' => $proyecto->id])}}">{{$proyecto->descripcion}}</a></td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(() => {
|
||||||
|
sendGet('/proyectos').then(response => {
|
||||||
|
response.proyectos.forEach(proyecto => {
|
||||||
|
if (!proyecto.ventas) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$('#proyectos').append(
|
||||||
|
$('<tr></tr>').append(
|
||||||
|
$('<td></td>').append(
|
||||||
|
$('<a></a>').attr('href', '{{$urls->base}}/ventas/' + proyecto.id).html(proyecto.descripcion + ' (' + proyecto.ventas + ')')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
Reference in New Issue
Block a user