From ef30ae67d21ed14ab9c739dfcad56dca353ec07f Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Fri, 28 Jul 2023 16:22:20 -0400 Subject: [PATCH] Ventas->Listado->Ventas --- app/public/index.php | 8 +- app/resources/routes/04_ventas.php | 3 + app/resources/routes/api/ventas.php | 3 + app/resources/routes/api/ventas/precios.php | 5 + app/resources/routes/ventas/cierres.php | 3 + app/resources/views/not_found.blade.php | 14 + .../views/ventas/cierres/list.blade.php | 2 +- .../views/ventas/cierres/show.blade.php | 141 +++++++++ app/resources/views/ventas/list.blade.php | 274 ++++++++++++++++++ .../views/ventas/precios/list.blade.php | 8 +- app/setup/middlewares/97_not_found.php | 2 + app/setup/setups/psr7.php | 8 + app/src/Controller/Ventas.php | 26 ++ app/src/Controller/Ventas/Cierres.php | 6 + app/src/Controller/Ventas/Precios.php | 14 +- app/src/Middleware/NotFound.php | 25 ++ app/src/Model/Comuna.php | 4 + app/src/Model/Direccion.php | 14 + app/src/Model/Provincia.php | 4 + app/src/Model/Proyecto.php | 10 +- app/src/Model/Region.php | 4 + app/src/Model/Venta.php | 34 +++ app/src/Model/Venta/BonoPie.php | 8 + app/src/Model/Venta/Cierre.php | 26 +- app/src/Model/Venta/Credito.php | 7 + app/src/Model/Venta/Entrega.php | 21 ++ app/src/Model/Venta/Escritura.php | 7 + app/src/Model/Venta/EstadoVenta.php | 22 ++ app/src/Model/Venta/FormaPago.php | 24 ++ app/src/Model/Venta/Propiedad.php | 47 +++ app/src/Model/Venta/Subsidio.php | 18 ++ app/src/Model/Venta/TipoEstadoVenta.php | 16 + app/src/Model/Venta/TipoValorCierre.php | 7 + app/src/Model/Venta/Unidad.php | 3 + app/src/Model/Venta/ValorCierre.php | 20 ++ app/src/Repository/Venta.php | 155 ++++++++++ app/src/Repository/Venta/BonoPie.php | 39 +++ app/src/Repository/Venta/Credito.php | 39 +++ app/src/Repository/Venta/Entrega.php | 38 +++ app/src/Repository/Venta/Escritura.php | 39 +++ app/src/Repository/Venta/EstadoVenta.php | 67 +++++ app/src/Repository/Venta/Precio.php | 19 ++ app/src/Repository/Venta/Propiedad.php | 45 +++ app/src/Repository/Venta/Subsidio.php | 33 +++ app/src/Repository/Venta/TipoEstadoVenta.php | 40 +++ app/src/Repository/Venta/TipoValorCierre.php | 35 +++ app/src/Repository/Venta/Unidad.php | 10 + app/src/Repository/Venta/ValorCierre.php | 55 ++++ app/src/Service/Proyecto.php | 13 + app/src/Service/Venta.php | 22 ++ app/src/Service/Ventas/Cierre.php | 18 +- app/src/Service/Ventas/Precio.php | 8 + 52 files changed, 1496 insertions(+), 17 deletions(-) create mode 100644 app/resources/views/not_found.blade.php create mode 100644 app/resources/views/ventas/cierres/show.blade.php create mode 100644 app/resources/views/ventas/list.blade.php create mode 100644 app/setup/middlewares/97_not_found.php create mode 100644 app/setup/setups/psr7.php create mode 100644 app/src/Controller/Ventas.php create mode 100644 app/src/Middleware/NotFound.php create mode 100644 app/src/Model/Venta.php create mode 100644 app/src/Model/Venta/BonoPie.php create mode 100644 app/src/Model/Venta/Credito.php create mode 100644 app/src/Model/Venta/Entrega.php create mode 100644 app/src/Model/Venta/Escritura.php create mode 100644 app/src/Model/Venta/EstadoVenta.php create mode 100644 app/src/Model/Venta/FormaPago.php create mode 100644 app/src/Model/Venta/Propiedad.php create mode 100644 app/src/Model/Venta/Subsidio.php create mode 100644 app/src/Model/Venta/TipoEstadoVenta.php create mode 100644 app/src/Model/Venta/TipoValorCierre.php create mode 100644 app/src/Model/Venta/ValorCierre.php create mode 100644 app/src/Repository/Venta.php create mode 100644 app/src/Repository/Venta/BonoPie.php create mode 100644 app/src/Repository/Venta/Credito.php create mode 100644 app/src/Repository/Venta/Entrega.php create mode 100644 app/src/Repository/Venta/Escritura.php create mode 100644 app/src/Repository/Venta/EstadoVenta.php create mode 100644 app/src/Repository/Venta/Propiedad.php create mode 100644 app/src/Repository/Venta/Subsidio.php create mode 100644 app/src/Repository/Venta/TipoEstadoVenta.php create mode 100644 app/src/Repository/Venta/TipoValorCierre.php create mode 100644 app/src/Repository/Venta/ValorCierre.php create mode 100644 app/src/Service/Proyecto.php create mode 100644 app/src/Service/Venta.php diff --git a/app/public/index.php b/app/public/index.php index 0606ece..9e47d85 100644 --- a/app/public/index.php +++ b/app/public/index.php @@ -4,4 +4,10 @@ $app = require_once implode(DIRECTORY_SEPARATOR, [ 'setup', 'app.php' ]); -$app->run(); +try { + $app->run(); +} catch (Error $error) { + $app->getContainer()->get(Psr\Log\LoggerInterface::class)->error($error); +} catch (Exception $exception) { + $app->getContainer()->get(Psr\Log\LoggerInterface::class)->notice($exception); +} diff --git a/app/resources/routes/04_ventas.php b/app/resources/routes/04_ventas.php index 93a94c7..d3eeeea 100644 --- a/app/resources/routes/04_ventas.php +++ b/app/resources/routes/04_ventas.php @@ -1,4 +1,6 @@ group('/ventas', function($app) { $files = new FilesystemIterator(implode(DIRECTORY_SEPARATOR, [__DIR__, 'ventas'])); foreach ($files as $file) { @@ -7,4 +9,5 @@ $app->group('/ventas', function($app) { } include_once $file->getRealPath(); } + $app->get('[/]', Ventas::class); }); diff --git a/app/resources/routes/api/ventas.php b/app/resources/routes/api/ventas.php index 361f498..90ba335 100644 --- a/app/resources/routes/api/ventas.php +++ b/app/resources/routes/api/ventas.php @@ -1,4 +1,6 @@ group('/ventas', function($app) { $folder = implode(DIRECTORY_SEPARATOR, [__DIR__, 'ventas']); if (file_exists($folder)) { @@ -10,4 +12,5 @@ $app->group('/ventas', function($app) { include_once $file->getRealPath(); } } + $app->post('[/]', [Ventas::class, 'proyecto']); }); diff --git a/app/resources/routes/api/ventas/precios.php b/app/resources/routes/api/ventas/precios.php index 0ad9ba4..2f04166 100644 --- a/app/resources/routes/api/ventas/precios.php +++ b/app/resources/routes/api/ventas/precios.php @@ -4,3 +4,8 @@ use Incoviba\Controller\Ventas\Precios; $app->group('/precios', function($app) { $app->post('[/]', [Precios::class, 'proyecto']); }); +$app->group('/precio', function($app) { + $app->group('/unidad/{unidad_id}', function($app) { + $app->get('[/]', [Precios::class, 'unidad']); + }); +}); diff --git a/app/resources/routes/ventas/cierres.php b/app/resources/routes/ventas/cierres.php index 52c0e2d..62e3084 100644 --- a/app/resources/routes/ventas/cierres.php +++ b/app/resources/routes/ventas/cierres.php @@ -4,3 +4,6 @@ use Incoviba\Controller\Ventas\Cierres; $app->group('/cierres', function($app) { $app->get('[/]', Cierres::class); }); +$app->group('/cierre/{cierre_id}', function($app) { + $app->get('[/]', [Cierres::class, 'show']); +}); diff --git a/app/resources/views/not_found.blade.php b/app/resources/views/not_found.blade.php new file mode 100644 index 0000000..9169f01 --- /dev/null +++ b/app/resources/views/not_found.blade.php @@ -0,0 +1,14 @@ +@extends('layout.base') + +@section('page_title') + 404 - No Encontrado +@endsection + +@section('page_content') +
+
+ + No se ha encontrado la página solicitada +
+
+@endsection diff --git a/app/resources/views/ventas/cierres/list.blade.php b/app/resources/views/ventas/cierres/list.blade.php index 859ca54..fb3827b 100644 --- a/app/resources/views/ventas/cierres/list.blade.php +++ b/app/resources/views/ventas/cierres/list.blade.php @@ -124,7 +124,7 @@ ).append( $('
').addClass('content').append(table) ) - const dt = new DataTable(table, { + new DataTable(table, { order: [[1, 'desc'], [0, 'asc']] }) } diff --git a/app/resources/views/ventas/cierres/show.blade.php b/app/resources/views/ventas/cierres/show.blade.php new file mode 100644 index 0000000..d778fad --- /dev/null +++ b/app/resources/views/ventas/cierres/show.blade.php @@ -0,0 +1,141 @@ +@extends('layout.base') + +@section('page_title') + Cierre - Detalle +@endsection + +@section('page_content') +
+
+

Cierre {{$cierre->principal()->descripcion}} - {{$cierre->proyecto->descripcion}}

+
+
+
+ Fecha +
+
+ {{$cierre->dateTime->format('d-m-Y')}} +
+
+
PROPIETARIO
+
+
+
+ {{$cierre->propietario->rut()}} +
+
+ {{$cierre->propietario->nombreCompleto()}} +
+
+
+
+
+ {{$cierre->propietario->datos->direccion}} +
+
+
+
PROPIEDAD
+
+ + + @foreach ($cierre->unidades as $unidad) + + + + + + + + + + @endforeach + +
{{ucwords($unidad->proyectoTipoUnidad->tipoUnidad->descripcion)}}{{$unidad->descripcion}}{{$unidad->proyectoTipoUnidad->nombre}}{{$unidad->proyectoTipoUnidad->abreviacion}}{{number_format($unidad->proyectoTipoUnidad->vendible(), 2, ',', '.')}} m²{{number_format($unidad->currentPrecio->valor, 2, ',', '.')}} UF{{number_format($unidad->currentPrecio->valor / $unidad->proyectoTipoUnidad->vendible(), 2, ',', '.')}} UF/m²
+
+
OFERTA
+
+
+ Precio +
+
+ {{number_format($cierre->precio, 2, ',', '.')}} UF +
+
+
+ + Neto + + + {{number_format($cierre->neto(), 2, ',', '.')}} UF + + + {{number_format($cierre->neto() / $cierre->principal()->vendible, 2, ',', '.')}} UF/m² + +
+ @if ($cierre->neto() / $cierre->principal()->vendible > $cierre->principal()->precio / $cierre->principal()->vendible) + + @else + + @endif +
+
+ @foreach($cierre->valoresCierre as $valorCierre) +
+
{{ucwords($valorCierre->tipoValorCierre->descripcion)}}
+
{{number_format($valorCierre->valor, 2, ',', '.')}} UF
+
{{number_format($valorCierre->valor / $cierre->precio * 100, 2, ',', '.')}}%
+
+ @endforeach +
DIFERENCIA
+
+
Neto
+
+ {{number_format($cierre->neto() - $cierre->principal()->precio, 2, ',', '.')}} UF +
+
+
ESTADO
+
+
+
+ {{ucwords($cierre->current->tipoEstadoCierre->descripcion)}} +
+
+ {{$cierre->current->fecha->format('d-m-Y')}} +
+
+ @if ($cierre->current->tipoEstadoCierre->descripcion === 'aprobado') + + + @endif +
+
+
+
+
+
+@endsection + +@push('page_scripts') + +@endpush diff --git a/app/resources/views/ventas/list.blade.php b/app/resources/views/ventas/list.blade.php new file mode 100644 index 0000000..d92a732 --- /dev/null +++ b/app/resources/views/ventas/list.blade.php @@ -0,0 +1,274 @@ +@extends('layout.base') + +@section('page_title') + Ventas +@endsection + +@section('page_content') +
+

Listado de Ventas

+

+
+
Proyectos
+
+
+ + +
+
+
+

+ +
+
+@endsection + +@include('layout.head.styles.datatables') +@include('layout.body.scripts.datatables') + +@push('page_scripts') + +@endpush diff --git a/app/resources/views/ventas/precios/list.blade.php b/app/resources/views/ventas/precios/list.blade.php index 101e4de..5820b22 100644 --- a/app/resources/views/ventas/precios/list.blade.php +++ b/app/resources/views/ventas/precios/list.blade.php @@ -321,7 +321,7 @@ data: { id: 0, proyecto: '', - proyectos: [], + proyectos: JSON.parse('{!! json_encode($proyectos) !!}'), precios: [] }, table: null, @@ -524,14 +524,14 @@ } }, up: event => { - this.get().proyectos() + this.draw().proyectos() }, refresh: event => { const list = $(this.ids.proyectos) if (list.is(':hidden')) { this.get().precios(this.data.id) } else { - this.get().proyectos() + this.draw().proyectos() } }, add: () => { @@ -581,7 +581,7 @@ $(this.ids.buttons.refresh).click(this.actions().refresh) $(this.ids.buttons.add).click(this.actions().add().list) - this.get().proyectos() + this.draw().proyectos() } } diff --git a/app/setup/middlewares/97_not_found.php b/app/setup/middlewares/97_not_found.php new file mode 100644 index 0000000..9a61f5f --- /dev/null +++ b/app/setup/middlewares/97_not_found.php @@ -0,0 +1,2 @@ +add($app->getContainer()->get(Incoviba\Middleware\NotFound::class)); diff --git a/app/setup/setups/psr7.php b/app/setup/setups/psr7.php new file mode 100644 index 0000000..af7ff76 --- /dev/null +++ b/app/setup/setups/psr7.php @@ -0,0 +1,8 @@ + function(ContainerInterface $container) { + return $container->get(Nyholm\Psr7\Factory\Psr17Factory::class); + } +]; diff --git a/app/src/Controller/Ventas.php b/app/src/Controller/Ventas.php new file mode 100644 index 0000000..6a2d55b --- /dev/null +++ b/app/src/Controller/Ventas.php @@ -0,0 +1,26 @@ + $proyecto->id, 'descripcion' => $proyecto->descripcion];}, $proyectoService->getVendibles()); + return $view->render($response, 'ventas.list', compact('proyectos')); + } + public function proyecto(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $service): ResponseInterface + { + $body = $request->getBody(); + $json = json_decode($body->getContents()); + $proyecto_id = $json->proyecto_id; + $ventas = $service->getByProyecto($proyecto_id); + $response->getBody()->write(json_encode(['ventas' => $ventas, 'total' => count($ventas)])); + return $response->withHeader('Content-Type', 'application/json'); + } +} diff --git a/app/src/Controller/Ventas/Cierres.php b/app/src/Controller/Ventas/Cierres.php index 7c4d325..8cfde24 100644 --- a/app/src/Controller/Ventas/Cierres.php +++ b/app/src/Controller/Ventas/Cierres.php @@ -12,6 +12,12 @@ class Cierres { return $view->render($response, 'ventas.cierres.list'); } + public function show(ServerRequestInterface $request, ResponseInterface $response, View $view, Service\Ventas\Cierre $service, int $cierre_id): ResponseInterface + { + $cierre = $service->getById($cierre_id); + return $view->render($response, 'ventas.cierres.show', compact('cierre')); + } + public function proyecto(ServerRequestInterface $request, ResponseInterface $response, Service\Ventas\Cierre $service): ResponseInterface { $body = $request->getBody(); diff --git a/app/src/Controller/Ventas/Precios.php b/app/src/Controller/Ventas/Precios.php index c4ef615..56c4416 100644 --- a/app/src/Controller/Ventas/Precios.php +++ b/app/src/Controller/Ventas/Precios.php @@ -1,16 +1,18 @@ render($response, 'ventas.precios.list'); + $proyectos = array_map(function(Model\Proyecto $proyecto) {return ['id' => $proyecto->id, 'descripcion' => $proyecto->descripcion];}, $proyectoService->getVendibles()); + return $view->render($response, 'ventas.precios.list', compact('proyectos')); } public function proyecto(ServerRequestInterface $request, ResponseInterface $response, Service\Ventas\Precio $precioService): ResponseInterface { @@ -21,4 +23,10 @@ class Precios $response->getBody()->write(json_encode(['precios' => $precios, 'total' => count($precios)])); return $response->withHeader('Content-Type', 'application/json'); } + public function unidad(ServerRequestInterface $request, ResponseInterface $response, Service\Ventas\Precio $precioService, int $unidad_id): ResponseInterface + { + $precio = $precioService->getByUnidad($unidad_id); + $response->getBody()->write(json_encode(['precio' => $precio])); + return $response->withHeader('Content-Type', 'application/json'); + } } diff --git a/app/src/Middleware/NotFound.php b/app/src/Middleware/NotFound.php new file mode 100644 index 0000000..8896854 --- /dev/null +++ b/app/src/Middleware/NotFound.php @@ -0,0 +1,25 @@ +handle($request); + } catch (HttpNotFoundException $exception) { + $this->logger->warning($exception); + $response = $this->responseFactory->createResponse(404); + return $this->view->render($response, 'not_found'); + } + } +} diff --git a/app/src/Model/Comuna.php b/app/src/Model/Comuna.php index 3bf746d..6739cb7 100644 --- a/app/src/Model/Comuna.php +++ b/app/src/Model/Comuna.php @@ -15,4 +15,8 @@ class Comuna extends Model 'provincia' => $this->provincia ]); } + public function __toString(): string + { + return implode(', ', [$this->descripcion, '' . $this->provincia]); + } } diff --git a/app/src/Model/Direccion.php b/app/src/Model/Direccion.php index 7795ad5..6ed67af 100644 --- a/app/src/Model/Direccion.php +++ b/app/src/Model/Direccion.php @@ -19,4 +19,18 @@ class Direccion extends Model 'comuna' => $this->comuna ]); } + public function __toString(): string + { + $array = [ + implode(' ', [ + $this->calle, + $this->numero + ]) + ]; + if ($this->extra !== '') { + $array[]= $this->extra; + } + $array []= '' . $this->comuna; + return implode(', ', $array); + } } diff --git a/app/src/Model/Provincia.php b/app/src/Model/Provincia.php index 1f2f387..652e3ce 100644 --- a/app/src/Model/Provincia.php +++ b/app/src/Model/Provincia.php @@ -15,4 +15,8 @@ class Provincia extends Model 'region' => $this->region ]); } + public function __toString(): string + { + return implode(', ', [$this->descripcion, '' . $this->region]); + } } diff --git a/app/src/Model/Proyecto.php b/app/src/Model/Proyecto.php index f9f21d2..3b1d12a 100644 --- a/app/src/Model/Proyecto.php +++ b/app/src/Model/Proyecto.php @@ -1,17 +1,15 @@ $this->numeracion ?? 0 ]); } + public function __toString(): string + { + return $this->descripcion; + } } diff --git a/app/src/Model/Venta.php b/app/src/Model/Venta.php new file mode 100644 index 0000000..ea9ec91 --- /dev/null +++ b/app/src/Model/Venta.php @@ -0,0 +1,34 @@ + $this->propietario, + 'propiedad' => $this->propiedad, + 'forma_pago' => $this->formaPago, + 'fecha' => $this->fecha->format('Y-m-d'), + 'fecha_ingreso' => $this->fechaIngreso->format('Y-m-d'), + 'valor' => $this->valor, + 'relacionado' => $this->relacionado, + 'estados' => $this->estados, + 'current_estado' => $this->currentEstado + ]); + } +} diff --git a/app/src/Model/Venta/BonoPie.php b/app/src/Model/Venta/BonoPie.php new file mode 100644 index 0000000..a94d24f --- /dev/null +++ b/app/src/Model/Venta/BonoPie.php @@ -0,0 +1,8 @@ +precio; + $bonos = array_filter($this->valoresCierre, function(ValorCierre $valorCierre) {return $valorCierre->tipoValorCierre->descripcion === 'bono pie';}); + $sum -= array_reduce($bonos, function($sum, ValorCierre $bono) {return $sum + $bono->valor;}, 0); + $unidades = array_filter($this->unidades, function(Unidad $unidad) {return $unidad->proyectoTipoUnidad->tipoUnidad->descripcion !== 'departamento';}); + $sum -= array_reduce($unidades, function($sum, Unidad $unidad) {return $sum + ($unidad->currentPrecio->valor ?? 0);}); + return $sum; + } + + public function principal(): stdClass + { + $unidades = array_filter($this->unidades, function(Unidad $unidad) {return $unidad->proyectoTipoUnidad->tipoUnidad->descripcion === 'departamento';}); + $output = [ + 'descripcion' => implode(' - ', array_map(function(Unidad $unidad) {return $unidad->descripcion;}, $unidades)), + 'vendible' => array_reduce($unidades, function($sum, Unidad $unidad) {return $sum + $unidad->proyectoTipoUnidad->vendible();}, 0), + 'precio' => array_reduce($unidades, function($sum, Unidad $unidad) {return $sum + $unidad->currentPrecio->valor;}, 0) + ]; + return (object) $output; + } public function jsonSerialize(): mixed { @@ -28,7 +51,8 @@ class Cierre extends Ideal\Model 'propietario' => $this->propietario->rut, 'estados' => $this->estados, 'estado_cierre' => $this->current, - 'unidades' => $this->unidades + 'unidades' => $this->unidades, + 'valores_cierre' => $this->valoresCierre ]); } } diff --git a/app/src/Model/Venta/Credito.php b/app/src/Model/Venta/Credito.php new file mode 100644 index 0000000..8dea8ef --- /dev/null +++ b/app/src/Model/Venta/Credito.php @@ -0,0 +1,7 @@ + $this->fecha->format('Y-m-d'), + 'operacion' => $this->operacion, + 'reserva' => $this->reserva + ]); + } +} diff --git a/app/src/Model/Venta/Escritura.php b/app/src/Model/Venta/Escritura.php new file mode 100644 index 0000000..56b0a48 --- /dev/null +++ b/app/src/Model/Venta/Escritura.php @@ -0,0 +1,7 @@ + $this->venta->id, + 'tipo_estado_venta' => $this->tipoEstadoVenta, + 'fecha' => $this->fecha->format('Y-m-d') + ]); + } +} diff --git a/app/src/Model/Venta/FormaPago.php b/app/src/Model/Venta/FormaPago.php new file mode 100644 index 0000000..0c44d2d --- /dev/null +++ b/app/src/Model/Venta/FormaPago.php @@ -0,0 +1,24 @@ + $this->pie ?? null, + 'bono_pie' => $this->bonoPie ?? null, + 'credito' => $this->credito ?? null, + 'escritura' => $this->escritura ?? null, + 'subsidio' => $this->subsidio ?? null + ]; + } +} diff --git a/app/src/Model/Venta/Propiedad.php b/app/src/Model/Venta/Propiedad.php new file mode 100644 index 0000000..c5c6eef --- /dev/null +++ b/app/src/Model/Venta/Propiedad.php @@ -0,0 +1,47 @@ +unidades, function(Unidad $unidad) {return $unidad->proyectoTipoUnidad->tipoUnidad->descripcion === 'departamento';}); + } + public function estacionamientos(): array + { + return array_filter($this->unidades, function(Unidad $unidad) {return $unidad->proyectoTipoUnidad->tipoUnidad->descripcion === 'estacionamiento';}); + } + public function bodegas(): array + { + return array_filter($this->unidades, function(Unidad $unidad) {return $unidad->proyectoTipoUnidad->tipoUnidad->descripcion === 'bodega';}); + } + + public function summary(): string + { + return implode(' - ', array_merge( + array_map(function(Unidad $unidad) { + return $unidad->descripcion; + }, $this->departamentos()), + array_map(function(Unidad $unidad) { + return "E{$unidad->descripcion}"; + }, $this->estacionamientos()), + array_map(function(Unidad $unidad) { + return "B{$unidad->descripcion}"; + }, $this->bodegas()) + )); + } + + public function jsonSerialize(): mixed + { + return [ + 'departamentos' => $this->departamentos(), + 'estacionamientos' => $this->estacionamientos(), + 'bodegas' => $this->bodegas(), + 'summary' => $this->summary() + ]; + } +} diff --git a/app/src/Model/Venta/Subsidio.php b/app/src/Model/Venta/Subsidio.php new file mode 100644 index 0000000..3fc384b --- /dev/null +++ b/app/src/Model/Venta/Subsidio.php @@ -0,0 +1,18 @@ + $this->ahorro, + 'subsidio' => $this->subsidio + ]); + } +} diff --git a/app/src/Model/Venta/TipoEstadoVenta.php b/app/src/Model/Venta/TipoEstadoVenta.php new file mode 100644 index 0000000..f381e80 --- /dev/null +++ b/app/src/Model/Venta/TipoEstadoVenta.php @@ -0,0 +1,16 @@ + $this->activa + ]); + } +} diff --git a/app/src/Model/Venta/TipoValorCierre.php b/app/src/Model/Venta/TipoValorCierre.php new file mode 100644 index 0000000..71b7927 --- /dev/null +++ b/app/src/Model/Venta/TipoValorCierre.php @@ -0,0 +1,7 @@ + $this->cierre->id, + 'tipo_valor_cierre' => $this->tipoValorCierre, + 'valor' => $this->valor + ]); + } +} diff --git a/app/src/Repository/Venta.php b/app/src/Repository/Venta.php new file mode 100644 index 0000000..36338d0 --- /dev/null +++ b/app/src/Repository/Venta.php @@ -0,0 +1,155 @@ +setTable('venta'); + } + + public function create(?array $data = null): Define\Model + { + $map = [ + 'propietario' => [ + 'function' => function($data) { + return $this->propietarioRepository->fetchById($data['propietario']); + } + ], + 'propiedad' => [ + 'function' => function($data) { + return $this->propiedadRepository->fetchById($data['propiedad']); + } + ], + 'pie' => [ + 'property' => 'formaPago', + 'function' => function($data) { + $fp = new Model\Venta\FormaPago(); + $map = [ + 'pie' => [ + 'repository' => $this->pieRepository + ], + 'bono_pie' => [ + 'property' => 'bonoPie', + 'repository' => $this->bonoPieRepository + ], + 'credito' => [ + 'repository' => $this->creditoRepository + ], + 'escritura' => [ + 'repository' => $this->escrituraRepository + ], + 'subsidio' => [ + 'repository' => $this->subsidioRepository + ] + ]; + foreach ($map as $column => $settings) { + if ($data[$column] !== null and $data[$column] !== 0) { + $fp->{$settings['property'] ?? $column} = $settings['repository']->fetchById($data[$column]); + } + } + return $fp; + } + ], + 'escriturado' => [ + 'function' => function($data) { + return $data['escritura'] !== null; + } + ], + 'entrega' => [ + 'function' => function($data) { + if ($data['entrega'] !== null and $data['entrega'] !== 0) { + return $this->entregaRepository->fetchById($data['entrega']); + } + } + ], + 'entregado' => [ + 'function' => function($data) { + if ($data['entrega'] !== null and $data['entrega'] !== 0) { + return $data['entrega'] !== null; + } + } + ], + 'fecha' => [ + 'function' => function($data) { + return new DateTimeImmutable($data['fecha']); + } + ], + 'valor_uf' => [ + 'property' => 'valor' + ], + //'estado' => [], + 'fecha_ingreso' => [ + 'property' => 'fechaIngreso', + 'function' => function($data) { + return new DateTimeImmutable($data['fecha_ingreso']); + } + ], + /*'avalchile' => [ + + ],*/ + //'agente', + //'uf', + 'relacionado' => [ + 'function' => function($data) { + return $data['relacionado'] !== 0; + } + ], + //'promocion', + //'resciliacion', + //'devolucion' + ]; + return $this->parseData(new Model\Venta(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['propietario', 'propiedad', 'pie', 'bono_pie', 'credito', 'escritura', 'subsidio', 'escriturado', + 'entrega', 'entregado', 'fecha', 'valor_uf', 'estado', 'fecha_ingreso', 'avalchile', 'agente', 'uf', + 'relacionado', 'promocion', 'resciliacion', 'devolucion'], + [$model->propietario->rut, $model->propiedad->id, $model->formaPago->Pie?->id, $model->formaPago->bonoPie?->id, + $model->formaPago->credito?->id, $model->formaPago->escritura?->id, $model->formaPago->subsidio?->id, + $model->formaPago->escritura !== null ? 1 : 0, null, 0, $model->fecha->format('Y-m-d'), $model->valor, + $model->currentEstado->vigente ? 1 : 0, $model->fechaIngreso->format('Y-m-d'), '', null, 0, + $model->relacionado ? 1 : 0, null, null, null] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['propietario', 'propiedad', 'pie', 'bono_pie', 'credito', 'escritura', 'subsidio', 'escriturado', + 'entrega', 'entregado', 'fecha', 'valor_uf', 'estado', 'fecha_ingreso', 'avalchile', 'agente', 'uf', + 'relacionado', 'promocion', 'resciliacion', 'devolucion'], $new_data); + } + + public function fetchByProyecto(int $proyecto_id): array + { + $query = "SELECT a.* +FROM `{$this->getTable()}` a + JOIN `propiedad_unidad` pu ON pu.`propiedad` = a.`propiedad` + JOIN `unidad` ON `unidad`.`id` = pu.`unidad` AND pu.`principal` = 1 + JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = `unidad`.`pt` + JOIN (SELECT e1.* FROM `estado_venta` e1 JOIN (SELECT MAX(`id`) AS 'id', `venta` FROM `estado_venta` GROUP BY `venta`) e0 ON e0.`id` = e1.`id`) ev ON ev.`venta` = a.`id` + JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado` +WHERE ptu.`proyecto` = ? AND tev.`activa` +GROUP BY a.`id`"; + return $this->fetchMany($query, [$proyecto_id]); + } +} diff --git a/app/src/Repository/Venta/BonoPie.php b/app/src/Repository/Venta/BonoPie.php new file mode 100644 index 0000000..4f5a9bd --- /dev/null +++ b/app/src/Repository/Venta/BonoPie.php @@ -0,0 +1,39 @@ +setTable('bono_pie'); + } + + public function create(?array $data = null): Define\Model + { + $map = [ + 'pago' => [ + 'function' => function($data) { + return $this->pagoRepository->fetchById($data['pago']); + } + ] + ]; + return $this->parseData(new Model\Venta\BonoPie(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['valor', 'pago'], + [$model->pago->valor, $model->pago->id] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['valor', 'pago'], $new_data); + } +} diff --git a/app/src/Repository/Venta/Credito.php b/app/src/Repository/Venta/Credito.php new file mode 100644 index 0000000..ed3cd9d --- /dev/null +++ b/app/src/Repository/Venta/Credito.php @@ -0,0 +1,39 @@ +setTable('credito'); + } + + public function create(?array $data = null): Define\Model + { + $map = [ + 'pago' => [ + 'function' => function($data) { + return $this->pagoRepository->fetchById($data['pago']); + } + ] + ]; + return $this->parseData(new Model\Venta\Credito(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['banco', 'valor', 'fecha', 'uf', 'abonado', 'fecha_abono', 'pago'], + [$model->pago->banco->id, $model->pago->valor, $model->pago->fecha->format('Y-m-d'), $model->pago->uf, null, null, $model->pago->id] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['banco', 'valor', 'fecha', 'uf', 'abonado', 'fecha_abono', 'pago'], $new_data); + } +} diff --git a/app/src/Repository/Venta/Entrega.php b/app/src/Repository/Venta/Entrega.php new file mode 100644 index 0000000..e91935f --- /dev/null +++ b/app/src/Repository/Venta/Entrega.php @@ -0,0 +1,38 @@ +setTable('entrega'); + } + + public function create(?array $data = null): Define\Model + { + $map = ['fecha', 'fondo_operacion', 'fondo_reserva', 'fecha_fondo_operacion', 'fecha_fondo_reserva', + 'pago_operacion', 'pago_reserva']; + return $this->parseData(new Model\Venta\Entrega(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['fecha', 'fondo_operacion', 'fondo_reserva', 'fecha_fondo_operacion', 'fecha_fondo_reserva', + 'pago_operacion', 'pago_reserva'], + [$model->fecha->format('Y-m-d'), $model->operacion->valor, $model->reserva->valor, + $model->operacion->fecha('Y-m-d'), $model->reserva->fecha('Y-m-d'), $model->operacion->id, + $model->reserva->id] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['fecha', 'fondo_operacion', 'fondo_reserva', 'fecha_fondo_operacion', + 'fecha_fondo_reserva', 'pago_operacion', 'pago_reserva'], $new_data); + } +} diff --git a/app/src/Repository/Venta/Escritura.php b/app/src/Repository/Venta/Escritura.php new file mode 100644 index 0000000..730a991 --- /dev/null +++ b/app/src/Repository/Venta/Escritura.php @@ -0,0 +1,39 @@ +setTable('escritura'); + } + + public function create(?array $data = null): Define\Model + { + $map = [ + 'pago' => [ + 'function' => function($data) { + return $this->pagoRepository->fetchById($data['pago']); + } + ] + ]; + return $this->parseData(new Model\Venta\Escritura(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['valor', 'fecha', 'uf', 'abonado', 'fecha_abono', 'pago'], + [$model->pago->valor, $model->pago->fecha->format('Y-m-d'), $model->pago->uf, null, null, $model->pago->id] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['valor', 'fecha', 'uf', 'abonado', 'fecha_abono', 'pago'], $new_data); + } +} diff --git a/app/src/Repository/Venta/EstadoVenta.php b/app/src/Repository/Venta/EstadoVenta.php new file mode 100644 index 0000000..15143d3 --- /dev/null +++ b/app/src/Repository/Venta/EstadoVenta.php @@ -0,0 +1,67 @@ +setTable('estado_venta'); + } + + public function create(?array $data = null): Define\Model + { + $map = [ + 'venta' => [ + 'function' => function($data) { + return $this->ventaRepository->fetchById($data['venta']); + } + ], + 'estado' => [ + 'property' => 'tipoEstadoVenta', + 'function' => function($data) { + return $this->tipoEstadoVentaRepository->fetchById($data['estado']); + } + ], + 'fecha' => [ + 'function' => function($data) { + return new DateTimeImmutable($data['fecha']); + } + ] + ]; + return $this->parseData(new Model\Venta\EstadoVenta(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['venta', 'estado', 'fecha'], + [$model->venta->id, $model->tipoEstadoVenta->id, $model->fecha->format('Y-m-d')] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['venta', 'estado', 'fecha'], $new_data); + } + + public function fetchByVenta(int $venta_id): array + { + $query = "SELECT * FROM `{$this->getTable()}` WHERE `venta` = ?"; + return $this->fetchMany($query, [$venta_id]); + } + public function fetchCurrentByVenta(int $venta_id): Define\Model + { + $query = "SELECT a.* +FROM `{$this->getTable()}` a + JOIN (SELECT MAX(`id`) AS 'id', `venta` FROM `{$this->getTable()}` GROUP BY `venta`) e0 ON e0.`id` = a.`id` +WHERE a.`venta` = ?"; + return $this->fetchOne($query, [$venta_id]); + } +} diff --git a/app/src/Repository/Venta/Precio.php b/app/src/Repository/Venta/Precio.php index f7bb16d..3373c84 100644 --- a/app/src/Repository/Venta/Precio.php +++ b/app/src/Repository/Venta/Precio.php @@ -1,6 +1,7 @@ fetchMany($query, [$proyecto_id]); } + public function fetchByUnidad(int $unidad_id): Define\Model + { + $query = "SELECT a.* +FROM `{$this->getTable()}` a + JOIN (SELECT e1.* FROM `estado_precio` e1 JOIN (SELECT MAX(`id`) AS 'id', `precio` FROM `estado_precio` GROUP BY `precio`) e0 ON e0.`id` = e1.`id`) ep ON ep.`precio` = a.`id` + JOIN `tipo_estado_precio` tep ON tep.`id` = ep.`estado` +WHERE `unidad` = ? AND tep.`descripcion` = 'vigente'"; + return $this->fetchOne($query, [$unidad_id]); + } + public function fetchByUnidadAndDate(int $unidad_id, string $date_time): Define\Model + { + $query = "SELECT a.* +FROM `{$this->getTable()}` a + JOIN (SELECT e1.* FROM `estado_precio` e1 JOIN (SELECT MAX(`id`) AS 'id', `precio` FROM `estado_precio` GROUP BY `precio`) e0 ON e0.`id` = e1.`id`) ep ON ep.`precio` = a.`id` + JOIN `tipo_estado_precio` tep ON tep.`id` = ep.`estado` +WHERE `unidad` = ? AND ep.`fecha` <= ? AND tep.`descripcion` = 'vigente'"; + return $this->fetchOne($query, [$unidad_id, $date_time]); + } } diff --git a/app/src/Repository/Venta/Propiedad.php b/app/src/Repository/Venta/Propiedad.php new file mode 100644 index 0000000..36baa7e --- /dev/null +++ b/app/src/Repository/Venta/Propiedad.php @@ -0,0 +1,45 @@ +setTable('propiedad'); + } + + public function create(?array $data = null): Define\Model + { + $map = [ + 'unidad_principal' => [ + 'property' => 'unidades', + 'function' => function($data) { + return $this->unidadRepository->fetchByPropiedad($data['id']); + } + ], + 'estado' => [ + 'function' => function($data) { + return true; + } + ] + ]; + return $this->parseData(new Model\Venta\Propiedad(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['unidad_principal', 'estacionamientos', 'bodegas', 'estado'], + [$model->departamentos()[0]->id, null, null, 1] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['unidad_principal', 'estacionamientos', 'bodegas', 'estado'], $new_data); + } +} diff --git a/app/src/Repository/Venta/Subsidio.php b/app/src/Repository/Venta/Subsidio.php new file mode 100644 index 0000000..60e0b88 --- /dev/null +++ b/app/src/Repository/Venta/Subsidio.php @@ -0,0 +1,33 @@ +setTable('subsidio'); + } + + public function create(?array $data = null): Define\Model + { + $map = ['pago', 'subsidio']; + return $this->parseData(new Model\Venta\Subsidio(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['pago', 'subsidio'], + [$model->ahorro->id, $model->subsidio->id] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['pago', 'subsidio'], $new_data); + } +} diff --git a/app/src/Repository/Venta/TipoEstadoVenta.php b/app/src/Repository/Venta/TipoEstadoVenta.php new file mode 100644 index 0000000..5433978 --- /dev/null +++ b/app/src/Repository/Venta/TipoEstadoVenta.php @@ -0,0 +1,40 @@ +setTable('tipo_estado_venta'); + } + + public function create(?array $data = null): Define\Model + { + $map = [ + 'descripcion' => [], + 'activa' => [ + 'function' => function($data) { + return $data['activa'] !== 0; + } + ] + ]; + return $this->parseData(new Model\Venta\TipoEstadoVenta(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['descripcion', 'activa'], + [$model->descripcion, $model->activa ? 1 : 0] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['descripcion', 'activa'], $new_data); + } +} diff --git a/app/src/Repository/Venta/TipoValorCierre.php b/app/src/Repository/Venta/TipoValorCierre.php new file mode 100644 index 0000000..0f6cef0 --- /dev/null +++ b/app/src/Repository/Venta/TipoValorCierre.php @@ -0,0 +1,35 @@ +setTable('tipo_valor_cierre'); + } + + public function create(?array $data = null): Define\Model + { + $map = [ + 'descripcion' => [] + ]; + return $this->parseData(new Model\Venta\TipoValorCierre(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['descripcion'], + [$model->descripcion] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['descripcion'], $new_data); + } +} diff --git a/app/src/Repository/Venta/Unidad.php b/app/src/Repository/Venta/Unidad.php index 271997f..d76f07f 100644 --- a/app/src/Repository/Venta/Unidad.php +++ b/app/src/Repository/Venta/Unidad.php @@ -43,6 +43,15 @@ class Unidad extends Ideal\Repository return $this->update($model, ['subtipo', 'piso', 'descripcion', 'orientacion', 'pt'], $new_data); } + public function fetchByPropiedad(int $propiedad_id): array + { + $query = "SELECT a.* +FROM `{$this->getTable()}` a + JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id` +WHERE pu.`propiedad` = ? +GROUP BY a.`id`"; + return $this->fetchMany($query, [$propiedad_id]); + } public function fetchByCierre(int $cierre_id): array { $query = "SELECT a.* @@ -51,6 +60,7 @@ FROM `{$this->getTable()}` a JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt` JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo` WHERE uc.`cierre` = ? +GROUP BY a.`id` ORDER BY tu.`orden`, LPAD(a.`descripcion`, 4, '0')"; return $this->fetchMany($query, [$cierre_id]); } diff --git a/app/src/Repository/Venta/ValorCierre.php b/app/src/Repository/Venta/ValorCierre.php new file mode 100644 index 0000000..801431c --- /dev/null +++ b/app/src/Repository/Venta/ValorCierre.php @@ -0,0 +1,55 @@ +setTable('valor_cierre'); + } + + public function create(?array $data = null): Define\Model + { + $map = [ + 'cierre' => [ + 'function' => function($data) { + return $this->cierreRepository->fetchById($data['cierre']); + } + ], + 'tipo' => [ + 'property' => 'tipoValorCierre', + 'function' => function($data) { + return $this->tipoValorCierreRepository->fetchById($data['tipo']); + } + ], + 'valor' => [] + ]; + return $this->parseData(new Model\Venta\ValorCierre(), $data, $map); + } + public function save(Define\Model $model): Define\Model + { + $model->id = $this->saveNew( + ['cierre', 'tipo', 'valor'], + [$model->cierre->id, $model->tipoValorCierre->id, $model->valor] + ); + return $model; + } + public function edit(Define\Model $model, array $new_data): Define\Model + { + return $this->update($model, ['cierre', 'tipo', 'valor'], $new_data); + } + + public function fetchByCierre(int $cierre_id): array + { + $query = "SELECT * FROM `{$this->getTable()}` WHERE `cierre` = ?"; + return $this->fetchMany($query, [$cierre_id]); + } +} diff --git a/app/src/Service/Proyecto.php b/app/src/Service/Proyecto.php new file mode 100644 index 0000000..eb2f1b2 --- /dev/null +++ b/app/src/Service/Proyecto.php @@ -0,0 +1,13 @@ +proyectoRepository->fetchAllActive(); + } +} diff --git a/app/src/Service/Venta.php b/app/src/Service/Venta.php new file mode 100644 index 0000000..886804c --- /dev/null +++ b/app/src/Service/Venta.php @@ -0,0 +1,22 @@ +ventaRepository->fetchByProyecto($proyecto_id); + foreach ($ventas as &$venta) { + $venta->estados = $this->estadoVentaRepository->fetchByVenta($venta->id); + $venta->currentEstado = $this->estadoVentaRepository->fetchCurrentByVenta($venta->id); + } + return $ventas; + } +} diff --git a/app/src/Service/Ventas/Cierre.php b/app/src/Service/Ventas/Cierre.php index c066022..fbe750e 100644 --- a/app/src/Service/Ventas/Cierre.php +++ b/app/src/Service/Ventas/Cierre.php @@ -2,13 +2,17 @@ namespace Incoviba\Service\Ventas; use Incoviba\Repository; +use Incoviba\Model; class Cierre { public function __construct( protected Repository\Venta\Cierre $cierreRepository, protected Repository\Venta\EstadoCierre $estadoCierreRepository, - protected Repository\Venta\Unidad $unidadRepository) {} + protected Repository\Venta\Unidad $unidadRepository, + protected Repository\Venta\ValorCierre $valorCierreRepository, + protected Repository\Venta\Precio $precioRepository + ) {} public function getByProyecto(int $proyecto_id): array { @@ -20,4 +24,16 @@ class Cierre } return $cierres; } + public function getById(int $cierre_id): Model\Venta\Cierre + { + $cierre = $this->cierreRepository->fetchById($cierre_id); + $cierre->estados = $this->estadoCierreRepository->fetchByCierre($cierre_id); + $cierre->current = $this->estadoCierreRepository->fetchCurrentByCierre($cierre_id); + $cierre->unidades = $this->unidadRepository->fetchByCierre($cierre_id); + foreach ($cierre->unidades as &$unidad) { + $unidad->currentPrecio = $this->precioRepository->fetchByUnidadAndDate($unidad->id, $cierre->dateTime->format('Y-m-d')); + } + $cierre->valoresCierre = $this->valorCierreRepository->fetchByCierre($cierre_id); + return $cierre; + } } diff --git a/app/src/Service/Ventas/Precio.php b/app/src/Service/Ventas/Precio.php index b03174a..34c2ebc 100644 --- a/app/src/Service/Ventas/Precio.php +++ b/app/src/Service/Ventas/Precio.php @@ -2,6 +2,7 @@ namespace Incoviba\Service\Ventas; use Incoviba\Repository; +use Incoviba\Model; class Precio { @@ -16,4 +17,11 @@ class Precio } return $precios; } + public function getByUnidad(int $unidad_id): Model\Venta\Precio + { + $precio = $this->precioRepository->fetchByUnidad($unidad_id); + $precio->estados = $this->estadoPrecioRepository->fetchByPrecio($precio->id); + $precio->current = $this->estadoPrecioRepository->fetchCurrentByPrecio($precio->id); + return $precio; + } }