diff --git a/app/src/Controller/API/Proyectos/Brokers/Contracts.php b/app/src/Controller/API/Proyectos/Brokers/Contracts.php index 4911d48..7680810 100644 --- a/app/src/Controller/API/Proyectos/Brokers/Contracts.php +++ b/app/src/Controller/API/Proyectos/Brokers/Contracts.php @@ -168,18 +168,10 @@ class Contracts if (is_string($unit_ids)) { $unit_ids = json_decode($input['unidad_ids'], true); } - foreach ($unit_ids as $unit_id) { - try { - $unit = $unitRepository->fetchById($unit_id); - $contractService->getById($contract_id); - $promotions = $promotionRepository->fetchByContractAndUnit($contract_id, $unit->id); - $output['unidades'] []= [ - 'id' => $unit->id, - 'promotions' => $promotions - ]; - } catch (ServiceAction\Read | Implement\Exception\EmptyResult $exception) { - $logger->debug($exception); - } + try { + $output['unidades'] = $promotionRepository->fetchByContractAndUnits($contract_id, $unit_ids); + } catch (Implement\Exception\EmptyResult $exception) { + $logger->debug($exception); } return $this->withJson($response, $output); } diff --git a/app/src/Controller/API/Proyectos/Unidades.php b/app/src/Controller/API/Proyectos/Unidades.php index 92d5479..d49792c 100644 --- a/app/src/Controller/API/Proyectos/Unidades.php +++ b/app/src/Controller/API/Proyectos/Unidades.php @@ -34,14 +34,7 @@ class Unidades extends Ideal\Controller } try { $proyecto = $proyectoService->getById($proyecto_id); - foreach ($unidad_ids as $unidad_id) { - try { - $output['precios'][] = [ - 'id' => $unidad_id, - 'precio' => $precioRepository->fetchVigenteByUnidad((int) $unidad_id) - ]; - } catch (Implement\Exception\EmptyResult) {} - } + $output['precios'] = $precioRepository->fetchVigentesByUnidades($unidad_ids); } catch (Implement\Exception\EmptyResult) {} return $this->withJson($response, $output); } @@ -62,21 +55,7 @@ class Unidades extends Ideal\Controller } try { $proyecto = $proyectoService->getById($proyecto_id); - foreach ($unidad_ids as $unidad_id) { - $output['estados'][] = [ - 'id' => $unidad_id, - 'sold' => false - ]; - try { - $unidad = $unidadRepository->fetchById($unidad_id); - try { - $output['estados'][] = [ - 'id' => $unidad_id, - 'sold' => $unidadRepository->fetchSoldByUnidad($unidad->id) - ]; - } catch (Implement\Exception\EmptyResult) {} - } catch (Implement\Exception\EmptyResult) {} - } + $output['estados'] = $unidadRepository->fetchSoldByUnidades($unidad_ids); } catch (Implement\Exception\EmptyResult) {} return $this->withJson($response, $output); } diff --git a/app/src/Controller/API/Ventas.php b/app/src/Controller/API/Ventas.php index e6031bc..e589962 100644 --- a/app/src/Controller/API/Ventas.php +++ b/app/src/Controller/API/Ventas.php @@ -377,15 +377,9 @@ class Ventas extends Controller 'input' => $input, 'ventas' => [] ]; - foreach ($input['unidad_ids'] as $unidad_id) { - try { - $venta = $ventaService->getByUnidadId($unidad_id); - $output['ventas'][] = [ - 'unidad_id' => $unidad_id, - 'venta' => $venta - ]; - } catch (Read) {} - } + try { + $output['ventas'] = $ventaService->getActiveByUnidadIds($input['unidad_ids']); + } catch (Read) {} return $this->withJson($response, $output); } } diff --git a/app/src/Repository/Venta.php b/app/src/Repository/Venta.php index 11b04b3..6af241e 100644 --- a/app/src/Repository/Venta.php +++ b/app/src/Repository/Venta.php @@ -296,16 +296,65 @@ class Venta extends Ideal\Repository * @return Model\Venta * @throws Implement\Exception\EmptyResult */ - public function fetchByUnidadId(int $unidad_id): Model\Venta + public function fetchActiveByUnidadId(int $unidad_id): Model\Venta { + $subSubQuery = $this->connection->getQueryBuilder() + ->select('MAX(`id`) AS `id`, `venta`') + ->from('`estado_venta`') + ->group('`venta`'); + $subQuery = $this->connection->getQueryBuilder() + ->select('e1.*') + ->from('`estado_venta` e1') + ->joined("INNER JOIN ({$subSubQuery}) e0 ON e0.`id` = e1.`id`"); $query = $this->connection->getQueryBuilder() ->select('a.*') ->from("{$this->getTable()} a") - ->joined('JOIN propiedad_unidad pu ON pu.propiedad = a.propiedad') - ->where('pu.unidad = ?'); + ->joined('INNER JOIN propiedad_unidad pu ON pu.propiedad = a.propiedad') + ->joined("INNER JOIN ({$subQuery}) ev ON ev.`venta` = a.`id`") + ->joined('INNER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`') + ->where('pu.unidad = ? AND tev.activa = 1'); return $this->fetchOne($query, [$unidad_id]); } + /** + * @param array $unidad_ids + * @return array + * @throws Implement\Exception\EmptyResult + */ + public function fetchActiveByUnidadIds(array $unidad_ids): array + { + $subSubQuery = $this->connection->getQueryBuilder() + ->select('MAX(`id`) AS `id`, `venta`') + ->from('`estado_venta`') + ->group('`venta`'); + $subQuery = $this->connection->getQueryBuilder() + ->select('e1.*') + ->from('`estado_venta` e1') + ->joined("INNER JOIN ({$subSubQuery}) e0 ON e0.`id` = e1.`id`"); + $interrogations = implode(',', array_fill(0, count($unidad_ids), '?')); + $query = $this->connection->getQueryBuilder() + ->select('a.*, pu.unidad') + ->from("{$this->getTable()} a") + ->joined('INNER JOIN propiedad_unidad pu ON pu.propiedad = a.propiedad') + ->joined("INNER JOIN ({$subQuery}) ev ON ev.`venta` = a.`id`") + ->joined('INNER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`') + ->where("pu.unidad IN ({$interrogations}) AND tev.activa = 1"); + try { + $results = $this->connection->execute($query, $unidad_ids)->fetchAll(PDO::FETCH_ASSOC); + if (empty($results)) { + throw new Implement\Exception\EmptyResult($query); + } + return array_map(function($result) { + return [ + 'unidad_id' => $result['unidad'], + 'venta' => $this->load($result) + ]; + }, $results); + } catch (PDOException $exception) { + throw new Implement\Exception\EmptyResult($query, $exception); + } + } + /** * @param string $unidad * @param string $tipo diff --git a/app/src/Repository/Venta/Precio.php b/app/src/Repository/Venta/Precio.php index e414d69..04073e0 100644 --- a/app/src/Repository/Venta/Precio.php +++ b/app/src/Repository/Venta/Precio.php @@ -1,6 +1,8 @@ fetchOne($query, [$unidad_id]); } + /** + * @param array $unidad_ids + * @return array + * @throws Implement\Exception\EmptyResult + */ + public function fetchVigentesByUnidades(array $unidad_ids): array + { + $interrogations = implode(',', array_fill(0, count($unidad_ids), '?')); + $query = $this->connection->getQueryBuilder() + ->select('a.*, unidad') + ->from("{$this->getTable()} a") + ->joined($this->joinEstado()) + ->joined('INNER JOIN tipo_estado_precio tep ON tep.`id` = ep.`estado`') + ->where("`unidad` IN ({$interrogations}) AND tep.`descripcion` = \"vigente\""); + try { + $results = $this->connection->execute($query, $unidad_ids)->fetchAll(PDO::FETCH_ASSOC); + if (empty($results)) { + throw new Implement\Exception\EmptyResult($query); + } + return array_map(function($result) { + return [ + 'id' => $result['unidad'], + 'precio' => $this->load($result) + ]; + }, $results); + } catch (PDOException $exception) { + throw new Implement\Exception\EmptyResult($query, $exception); + } + } + /** * @param int $unidad_id * @param string $date_time diff --git a/app/src/Repository/Venta/Promotion.php b/app/src/Repository/Venta/Promotion.php index bb63202..136b4aa 100644 --- a/app/src/Repository/Venta/Promotion.php +++ b/app/src/Repository/Venta/Promotion.php @@ -243,6 +243,72 @@ class Promotion extends Common\Ideal\Repository return $this->fetchMany($query, ['contract_id' => $contract_id, 'unit_id' => $unit_id]); } + /** + * @param int $contract_id + * @param array $unit_ids + * @return array + * @throws Common\Implement\Exception\EmptyResult + */ + public function fetchByContractAndUnits(int $contract_id, array $unit_ids): array + { + $interrogations = implode(',', array_map(fn($k) => ":id{$k}", array_keys($unit_ids))); + $query = $this->connection->getQueryBuilder() + ->select('DISTINCT a.*, GROUP_CONCAT(COALESCE(pu.unit_id, u1.id, u2.id, u3.id) SEPARATOR "|") as unit_id') + ->from("{$this->getTable()} a") + ->joined('LEFT OUTER JOIN promotion_brokers pb ON pb.promotion_id = a.id') + ->joined('LEFT OUTER JOIN broker_contracts bc ON bc.broker_rut = pb.broker_rut') + ->joined('LEFT OUTER JOIN promotion_units pu ON pu.promotion_id = a.id') + ->joined('LEFT OUTER JOIN promotion_projects pp ON pp.promotion_id = a.id') + ->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu1 ON ptu1.proyecto = pp.project_id') + ->joined('LEFT OUTER JOIN unidad u1 ON u1.pt = ptu1.id') + ->joined('LEFT OUTER JOIN promotion_unit_types put ON put.promotion_id = a.id') + ->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu2 ON ptu2.tipo = put.unit_type_id AND ptu2.proyecto = put.project_id') + ->joined('LEFT OUTER JOIN unidad u2 ON u2.pt = ptu2.id') + ->joined('LEFT OUTER JOIN promotion_unit_lines pul ON pul.promotion_id = a.id') + ->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu3 ON ptu3.id = pul.unit_line_id') + ->joined('LEFT OUTER JOIN unidad u3 ON u3.pt = ptu3.id') + ->where("bc.id = :contract_id OR pu.unit_id IN ({$interrogations}) OR u1.id IN ({$interrogations}) OR u2.id IN ({$interrogations}) OR u3.id IN ({$interrogations})") + ->group('a.id'); + $unitParams = array_combine(array_map(fn($k) => "id{$k}", array_keys($unit_ids)), $unit_ids); + try { + $results = $this->connection->execute($query, array_merge(['contract_id' => $contract_id], $unitParams))->fetchAll(PDO::FETCH_ASSOC); + if (empty($results)) { + throw new Common\Implement\Exception\EmptyResult($query); + } + $temp = new class() + { + protected array $promotions = []; + public function addItem(int $id, Model\Venta\Promotion $promotion): void + { + if (!array_key_exists($id, $this->promotions)) { + $this->promotions[$id] = [ + 'id' => $id, + 'promotions' => [] + ]; + } + $this->promotions[$id]['promotions'] []= $promotion; + } + public function toArray(): array + { + return array_values($this->promotions); + } + }; + foreach ($results as $result) { + if (str_contains($result['unit_id'], '|')) { + $ids = explode('|', $result['unit_id']); + foreach ($ids as $id) { + $temp->addItem((int) $id, $this->load($result)); + } + continue; + } + $temp->addItem((int) $result['unit_id'], $this->load($result)); + } + return $temp->toArray(); + } catch (PDOException $exception) { + throw new Common\Implement\Exception\EmptyResult($query, $exception); + } + } + /** * @param Model\Venta\Promotion $promotion * @param int $project_id diff --git a/app/src/Repository/Venta/Unidad.php b/app/src/Repository/Venta/Unidad.php index 5486ea7..c03c866 100644 --- a/app/src/Repository/Venta/Unidad.php +++ b/app/src/Repository/Venta/Unidad.php @@ -204,6 +204,44 @@ class Unidad extends Ideal\Repository } } + /** + * @param array $unidad_ids + * @return array + * @throws Implement\Exception\EmptyResult + */ + public function fetchSoldByUnidades(array $unidad_ids): array + { + $interrogations = implode(',', array_fill(0, count($unidad_ids), '?')); + $query = $this->connection->getQueryBuilder() + ->select('a.id') + ->from("{$this->getTable()} a") + ->joined('INNER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`') + ->joined('INNER JOIN `venta` ON `venta`.`propiedad` = `pu`.`propiedad`') + ->joined($this->joinEstadoVenta(true)) + ->joined('INNER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`') + ->where("a.id IN ({$interrogations}) AND tev.activa = 1"); + try { + $results = $this->connection->execute($query, $unidad_ids)->fetchAll(PDO::FETCH_ASSOC); + if (empty($results)) { + throw new Implement\Exception\EmptyResult($query); + } + $missing = array_diff(array_map(fn($id) => (int) $id, $unidad_ids), array_column($results, 'id')); + return [...array_map(function($result) { + return [ + 'id' => $result['id'], + 'sold' => true + ]; + }, $results), ...array_map(function($id) { + return [ + 'id' => $id, + 'sold' => false + ]; + }, $missing)]; + } catch (PDOException $exception) { + throw new Implement\Exception\EmptyResult($query, $exception); + } + } + /** * @param int $promotion_id * @return array @@ -239,16 +277,17 @@ class Unidad extends Ideal\Repository { return "LEFT OUTER JOIN unidad_prorrateo up ON up.unidad_id = a.id"; } - protected function joinEstadoVenta(): string + protected function joinEstadoVenta(bool $inner = false): string { $subSubQuery = $this->connection->getQueryBuilder() ->select('MAX(id) AS id, venta') ->from('estado_venta') ->group('venta'); + $join = $inner ? 'INNER' : 'LEFT OUTER'; $subQuery = $this->connection->getQueryBuilder() ->select('ev1.*') ->from('estado_venta ev1') - ->joined("LEFT OUTER JOIN ($subSubQuery) ev0 ON ev0.id = ev1.id"); - return "LEFT OUTER JOIN ({$subQuery}) ev ON ev.`venta` = `venta`.`id`"; + ->joined("{$join} JOIN ($subSubQuery) ev0 ON ev0.id = ev1.id"); + return "{$join} JOIN ({$subQuery}) ev ON ev.`venta` = `venta`.`id`"; } } diff --git a/app/src/Service/Venta.php b/app/src/Service/Venta.php index 468024b..f7f9985 100644 --- a/app/src/Service/Venta.php +++ b/app/src/Service/Venta.php @@ -91,10 +91,30 @@ class Venta extends Service * @return Model\Venta * @throws Read */ - public function getByUnidadId(int $unidad_id): Model\Venta + public function getActiveByUnidadId(int $unidad_id): Model\Venta { try { - return $this->process($this->ventaRepository->fetchByUnidadId($unidad_id)); + return $this->process($this->ventaRepository->fetchActiveByUnidadId($unidad_id)); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Read(__CLASS__, $exception); + } + } + + /** + * @param array $unidad_ids + * @return array + * @throws Read + */ + public function getActiveByUnidadIds(array $unidad_ids): array + { + try { + $ventas = $this->ventaRepository->fetchActiveByUnidadIds($unidad_ids); + return array_map(function($data) { + return [ + 'unidad_id' => $data['unidad_id'], + 'venta' => $this->process($data['venta']) + ]; + }, $ventas); } catch (Implement\Exception\EmptyResult $exception) { throw new Read(__CLASS__, $exception); }