diff --git a/app/resources/routes/97_search.php b/app/resources/routes/97_search.php new file mode 100644 index 0000000..c76b639 --- /dev/null +++ b/app/resources/routes/97_search.php @@ -0,0 +1,7 @@ +group('/search', function($app) { + $app->get('[/{query}[/{tipo}[/]]]', Search::class); + $app->post('[/]', Search::class); +}); diff --git a/app/resources/routes/api/search.php b/app/resources/routes/api/search.php new file mode 100644 index 0000000..1339a42 --- /dev/null +++ b/app/resources/routes/api/search.php @@ -0,0 +1,4 @@ +post('/search', [Search::class, 'query']); diff --git a/app/resources/views/search.blade.php b/app/resources/views/search.blade.php new file mode 100644 index 0000000..d81b1d1 --- /dev/null +++ b/app/resources/views/search.blade.php @@ -0,0 +1,220 @@ +@extends('layout.base') + +@section('page_content') +
+

Búsqueda

+ +
+
+
+ +
+
+ + +
+
+
+@endsection + +@include('layout.head.styles.datatables') +@include('layout.body.scripts.datatables') + +@push('page_scripts') + +@endpush diff --git a/app/resources/views/ventas/show/forma_pago/credito.blade.php b/app/resources/views/ventas/show/forma_pago/credito.blade.php index a0fb0b5..90c3905 100644 --- a/app/resources/views/ventas/show/forma_pago/credito.blade.php +++ b/app/resources/views/ventas/show/forma_pago/credito.blade.php @@ -19,7 +19,7 @@ {{$format->pesos($credito->pago->valor)}} - + {{$credito->pago->currentEstado->fecha->format('d-m-Y')}} @if ($credito->pago->currentEstado->tipoEstadoPago->descripcion === 'no pagado') diff --git a/app/resources/views/ventas/show/propietario.blade.php b/app/resources/views/ventas/show/propietario.blade.php index 6a7ac45..62f564f 100644 --- a/app/resources/views/ventas/show/propietario.blade.php +++ b/app/resources/views/ventas/show/propietario.blade.php @@ -9,7 +9,7 @@ {{$venta->propietario()->rut()}}
- {{$venta->propietario()->datos->direccion}} + {{$venta->propietario()->datos->direccion ?? ''}}
diff --git a/app/src/Controller/Login.php b/app/src/Controller/Login.php index 70467f5..44fb96c 100644 --- a/app/src/Controller/Login.php +++ b/app/src/Controller/Login.php @@ -20,6 +20,10 @@ class Login if ($request->hasHeader('X-Redirect-URI')) { $redirect_uri = $request->getHeaderLine('X-Redirect-URI'); } + $query = $request->getQueryParams(); + if (isset($query['url'])) { + $redirect_uri = base64_decode(urldecode($query['url'])); + } return $view->render($response, 'login.form', compact('redirect_uri')); } public function login(ServerRequestInterface $request, ResponseInterface $response, Repository\User $userRepository, Service\Login $service): ResponseInterface diff --git a/app/src/Controller/Search.php b/app/src/Controller/Search.php new file mode 100644 index 0000000..94a6a6f --- /dev/null +++ b/app/src/Controller/Search.php @@ -0,0 +1,23 @@ +getParsedBody() ?? ''; + return $view->render($response, 'search', compact('post', 'query', 'tipo')); + } + public function query(ServerRequestInterface $request, ResponseInterface $response, Service\Search $service): ResponseInterface + { + $data = $request->getParsedBody(); + $results = $service->query($data['query'], $data['tipo']); + $response->getBody()->write(json_encode(compact('results'))); + return $response->withHeader('Content-Type', 'application/json'); + } +} diff --git a/app/src/Controller/Ventas.php b/app/src/Controller/Ventas.php index 153237f..3b54065 100644 --- a/app/src/Controller/Ventas.php +++ b/app/src/Controller/Ventas.php @@ -40,7 +40,7 @@ class Ventas 'total' => 0 ]; try { - $ventas = $service->fetchByProyecto($proyecto_id); + $ventas = $service->fetchActivaByProyecto($proyecto_id); $output['ventas'] = array_map(function(Model\Venta $venta) {return $venta->id;}, $ventas); $output['proyecto']['descripcion'] = $ventas[0]->proyecto()->descripcion; $output['total'] = count($ventas); diff --git a/app/src/Middleware/Authentication.php b/app/src/Middleware/Authentication.php index 32d3e9f..4b74355 100644 --- a/app/src/Middleware/Authentication.php +++ b/app/src/Middleware/Authentication.php @@ -17,7 +17,9 @@ class Authentication return $handler->handle($request); } $response = $this->responseFactory->createResponse(301, 'Not logged in'); - return $response->withHeader('Location', $this->login_url) + $uri = urlencode(base64_encode((string) $request->getUri())); + return $response->withHeader('Location', implode('?', [$this->login_url, "url={$uri}"])) + ->withHeader('Referer', (string) $request->getUri()) ->withHeader('X-Redirected-URI', (string) $request->getUri()); } diff --git a/app/src/Model/Venta.php b/app/src/Model/Venta.php index 39621d2..5e8a502 100644 --- a/app/src/Model/Venta.php +++ b/app/src/Model/Venta.php @@ -99,6 +99,7 @@ class Venta extends Ideal\Model 'fecha_ingreso' => $this->fechaIngreso->format('Y-m-d'), 'valor' => $this->valor, 'relacionado' => $this->relacionado, + 'proyecto' => $this->proyecto(), 'estados' => array_map(function(Venta\EstadoVenta $estado) {return $estado->id;}, $this->estados()), 'current_estado' => $this->currentEstado() ]); diff --git a/app/src/Model/Venta/Propietario.php b/app/src/Model/Venta/Propietario.php index 7028773..77300eb 100644 --- a/app/src/Model/Venta/Propietario.php +++ b/app/src/Model/Venta/Propietario.php @@ -12,7 +12,7 @@ class Propietario extends Model public array $apellidos; public Datos $datos; public ?Propietario $representante; - public ?Propietario $otro; + public ?bool $otro; public function rut(): string { diff --git a/app/src/Repository/Venta.php b/app/src/Repository/Venta.php index 1901cc7..3944586 100644 --- a/app/src/Repository/Venta.php +++ b/app/src/Repository/Venta.php @@ -152,6 +152,19 @@ FROM `{$this->getTable()}` a 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]); + } + public function fetchActivaByProyecto(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]); } @@ -173,4 +186,38 @@ WHERE `proyecto`.`descripcion` = ? AND `unidad`.`descripcion` = ? AND tev.`activ $query = "SELECT * FROM `{$this->getTable()}` WHERE `pie` = ?"; return $this->fetchOne($query, [$pie_id]); } + public function fetchByUnidad(string $unidad, string $tipo): array + { + $query = "SELECT a.* +FROM `{$this->getTable()}` a + JOIN `propiedad_unidad` pu ON pu.`propiedad` = a.`propiedad` + JOIN `unidad` ON `unidad`.`id` = pu.`unidad` + JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = `unidad`.`pt` + JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo` +WHERE `unidad`.`descripcion` LIKE ? AND tu.`descripcion` = ?"; + return $this->fetchMany($query, [$unidad, $tipo]); + } + public function fetchByPrecio(string $precio): array + { + $query = "SELECT * FROM `{$this->getTable()}` WHERE `valor_uf` = ?"; + return $this->fetchMany($query, [$precio]); + } + public function fetchByPropietario(string $propietario): array + { + $query = "SELECT a.* +FROM `{$this->getTable()}` a + JOIN `propietario` ON `propietario`.`rut` = a.`propietario` +WHERE CONCAT_WS('-', `propietario`.`rut`, `propietario`.`dv`) LIKE :propietario OR `propietario`.`nombres` LIKE :propietario + OR `propietario`.`apellido_paterno` LIKE :propietario OR `propietario`.`apellido_materno` LIKE :propietario + OR CONCAT_WS(' ', `propietario`.`nombres`, `propietario`.`apellido_paterno`, `propietario`.`apellido_materno`) LIKE :propietario"; + return $this->fetchMany($query, [':propietario' => "%{$propietario}%"]); + } + public function fetchByPropietarioNombreCompleto(string $propietario): array + { + $query = "SELECT a.* +FROM `{$this->getTable()}` a + JOIN `propietario` ON `propietario`.`rut` = a.`propietario` +WHERE CONCAT_WS(' ', `propietario`.`nombres`, `propietario`.`apellido_paterno`, `propietario`.`apellido_materno`) LIKE ?"; + return $this->fetchMany($query, [$propietario]); + } } diff --git a/app/src/Repository/Venta/Propietario.php b/app/src/Repository/Venta/Propietario.php index 6ed599b..5b0f5dc 100644 --- a/app/src/Repository/Venta/Propietario.php +++ b/app/src/Repository/Venta/Propietario.php @@ -52,10 +52,10 @@ class Propietario extends Ideal\Repository })) ->register('otro', (new Implement\Repository\Mapper()) ->setFunction(function($data) { - if ($data['otro'] === null or $data['otro'] === 0) { + if ($data['otro'] === null) { return null; } - return $this->fetchById($data['otro']); + return $data['otro'] !== 0; }) ->setDefault(null)); return $this->parseData(new Model\Venta\Propietario(), $data, $map); diff --git a/app/src/Repository/Venta/Unidad.php b/app/src/Repository/Venta/Unidad.php index 6f1b523..341665e 100644 --- a/app/src/Repository/Venta/Unidad.php +++ b/app/src/Repository/Venta/Unidad.php @@ -15,7 +15,7 @@ class Unidad extends Ideal\Repository $this->setTable('unidad'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta\Unidad { $map = (new Implement\Repository\MapperParser(['subtipo', 'piso', 'descripcion', 'orientacion'])) ->register('pt', (new Implement\Repository\Mapper()) @@ -25,7 +25,7 @@ class Unidad extends Ideal\Repository })); return $this->parseData(new Model\Venta\Unidad(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta\Unidad { $model->id = $this->saveNew( ['subtipo', 'piso', 'descripcion', 'orientacion', 'pt'], @@ -33,7 +33,7 @@ class Unidad 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\Venta\Unidad { return $this->update($model, ['subtipo', 'piso', 'descripcion', 'orientacion', 'pt'], $new_data); } @@ -83,4 +83,17 @@ WHERE ptu.`proyecto` = ? AND (pu.`id` IS NULL OR `venta`.`id` IS NULL OR tev.`ac ORDER BY tu.`orden`"; return $this->fetchMany($query, [$proyecto_id]); } + public function fetchDisponiblesByDescripcionAndTipo(string $descripcion, string $tipo): array + { + $query = "SELECT DISTINCT a.* +FROM `{$this->getTable()}` a + JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt` + JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo` + LEFT OUTER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id` + LEFT OUTER JOIN `venta` ON `venta`.`propiedad` = pu.`propiedad` + LEFT OUTER JOIN (SELECT ev1.* FROM `estado_venta` ev1 JOIN (SELECT MAX(`id`) as 'id', `venta` FROM `estado_venta`) ev0 ON ev0.`id` = ev1.`id`) ev ON ev.`venta` = `venta`.`id` + LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado` +WHERE a.`descripcion` LIKE ? AND tu.`descripcion` = ? AND (pu.`id` IS NULL OR `venta`.`id` IS NULL OR tev.`activa` = 0)"; + return $this->fetchMany($query, [$descripcion, $tipo]); + } } diff --git a/app/src/Service/Search.php b/app/src/Service/Search.php new file mode 100644 index 0000000..82421e8 --- /dev/null +++ b/app/src/Service/Search.php @@ -0,0 +1,186 @@ +findCualquiera($query); + } else { + $results = $this->find($query, $tipo); + } + return $this->sort($results); + } + + protected function findCualquiera(string $query): array + { + $tipos = [ + 'departamento', + 'estacionamiento', + 'bodega', + 'propietario', + 'precio_venta', + 'proyecto', + 'pago', + 'unidad' + ]; + $results = []; + foreach ($tipos as $t) { + $this->add($results, $this->find($query, $t)); + } + return $results; + } + protected function find(string $query, string $tipo): array + { + $queries = explode(' ', $query); + $tiposUnidades = $this->getTiposUnidades(); + $results = []; + foreach ($queries as $q) { + $this->add($results, $this->findVentas($q, $tipo)); + if (in_array($tipo, $tiposUnidades)) { + $this->add($results, $this->findUnidadesDisponibles($q, $tipo)); + } + } + return $results; + } + protected function findVentas(string $query, string $tipo): array + { + $tiposUnidades = $this->getTiposUnidades(); + if ($tipo === 'unidad') { + $results = []; + foreach ($tiposUnidades as $t) { + $this->add($results, $this->findVentas($query, $t)); + } + return $results; + } + if (in_array($tipo, $tiposUnidades)) { + return $this->findUnidad($query, $tipo); + } + if ($tipo === 'propietario') { + return $this->findPropietario($query); + } + if ($tipo === 'precio_venta') { + return $this->findPrecio($query); + } + if ($tipo === 'proyecto') { + return $this->findProyecto($query); + } + if ($tipo === 'pago') { + return $this->findPago($query); + } + return []; + } + protected function findUnidadesDisponibles(string $query, string $tipo): array + { + try { + return $this->unidadRepository->fetchDisponiblesByDescripcionAndTipo($query, $tipo); + } catch (EmptyResponse) { + return []; + } + } + protected function findUnidad(string $query, string $tipo): array + { + try { + return $this->ventaService->getByUnidad($query, $tipo); + } catch (EmptyResult) { + return []; + } + } + protected function findPropietario(string $query): array + { + try { + return $this->ventaService->getByPropietario($query); + } catch (EmptyResult) { + return []; + } + } + protected function findPrecio(string $query): array + { + try { + $precio = str_replace(['$', '.', ','], ['', '', '.'], $query); + return $this->ventaService->getByPrecio($precio); + } catch (EmptyResult) { + return []; + } + } + protected function findProyecto(string $query): array + { + try { + return $this->ventaService->getByProyecto($query); + } catch (EmptyResult) { + return []; + } + } + protected function findPago(string $query): array + { + return []; + } + + protected array $tipos; + protected function getTiposUnidades(): array + { + if (!isset($this->tipos)) { + $this->tipos = array_map(function(Model\Venta\TipoUnidad $tipoUnidad) { + return $tipoUnidad->descripcion; + }, $this->tipoUnidadRepository->fetchAll()); + } + return $this->tipos; + } + protected function add(array &$results, array $found): void + { + foreach ($found as $item) { + if (!$this->inResults($item, $results)) { + $results []= $item; + } + } + } + protected function inResults($item, array $results): bool + { + foreach ($results as $result) { + if (get_class($item) === get_class($result) and $item->id === $result->id) { + return true; + } + } + return false; + } + protected function sort(&$results): array + { + usort($results, function($a, $b) { + if (is_a($a, Model\Venta::class)) { + $pa = $a->proyecto()->descripcion; + $ta = $a->propiedad()->departamentos()[0]->proyectoTipoUnidad->tipoUnidad->descripcion; + $ua = $a->propiedad()->departamentos()[0]->descripcion; + } else { + $pa = $a->proyectoTipoUnidad->proyecto->descripcion; + $ta = $a->proyectoTipoUnidad->tipoUnidad->descripcion; + $ua = $a->descripcion; + } + if (is_a($b, Model\Venta::class)) { + $pb = $b->proyecto()->descripcion; + $tb = $b->propiedad()->departamentos()[0]->proyectoTipoUnidad->tipoUnidad->descripcion; + $ub = $b->propiedad()->departamentos()[0]->descripcion; + } else { + $pb = $b->proyectoTipoUnidad->proyecto->descripcion; + $tb = $b->proyectoTipoUnidad->tipoUnidad->descripcion; + $ub = $b->descripcion; + } + $p = strcmp($pa, $pb); + if ($p !== 0) { + return $p; + } + $t = strcmp($ta, $tb); + if ($t !== 0) { + return $t; + } + return strcmp($ua, $ub); + }); + return $results; + } +} diff --git a/app/src/Service/Venta.php b/app/src/Service/Venta.php index 6609518..086a2cd 100644 --- a/app/src/Service/Venta.php +++ b/app/src/Service/Venta.php @@ -23,26 +23,56 @@ class Venta public function getById(int $venta_id): Model\Venta { - return ($this->ventaRepository->fetchById($venta_id)) - ->addFactory('estados', (new Implement\Repository\Factory()) - ->setCallable([$this->estadoVentaRepository, 'fetchByVenta']) - ->setArgs([$venta_id])) - ->addFactory('currentEstado', (new Implement\Repository\Factory()) - ->setCallable([$this->estadoVentaRepository, 'fetchCurrentByVenta']) - ->setArgs([$venta_id])); + return $this->process($this->ventaRepository->fetchById($venta_id)); } public function getByProyecto(int $proyecto_id): array { $ventas = $this->ventaRepository->fetchByProyecto($proyecto_id); foreach ($ventas as &$venta) { - $venta->estados = $this->estadoVentaRepository->fetchByVenta($venta->id); - $venta->currentEstado = $this->estadoVentaRepository->fetchCurrentByVenta($venta->id); + $venta = $this->process($venta); + } + return $ventas; + } + public function getActivaByProyecto(int $proyecto_id): array + { + $ventas = $this->ventaRepository->fetchActivaByProyecto($proyecto_id); + foreach ($ventas as &$venta) { + $venta = $this->process($venta); } return $ventas; } public function getByProyectoAndUnidad(string $proyecto_nombre, int $unidad_descripcion): Model\Venta { $venta = $this->ventaRepository->fetchByProyectoAndUnidad($proyecto_nombre, $unidad_descripcion); + return $this->process($venta); + } + public function getByUnidad(string $unidad, string $tipo): array + { + $ventas = $this->ventaRepository->fetchByUnidad($unidad, $tipo); + foreach ($ventas as &$venta) { + $venta = $this->process($venta); + } + return $ventas; + } + public function getByPropietario(string $propietario): array + { + $ventas = $this->ventaRepository->fetchByPropietario($propietario); + foreach ($ventas as &$venta) { + $venta = $this->process($venta); + } + return $ventas; + } + public function getByPrecio(string $precio): array + { + $ventas = $this->ventaRepository->fetchByPrecio($precio); + foreach ($ventas as &$venta) { + $venta = $this->process($venta); + } + return $ventas; + } + + protected function process(Model\Venta $venta): Model\Venta + { $venta->addFactory('estados', (new Implement\Repository\Factory())->setCallable([$this->estadoVentaRepository, 'fetchByVenta'])->setArgs([$venta->id])); $venta->addFactory('currentEstado', (new Implement\Repository\Factory())->setCallable([$this->estadoVentaRepository, 'fetchCurrentByVenta'])->setArgs([$venta->id])); return $venta;