setTable('proyecto'); } public function create(?array $data = null): Define\Model { $map = (new Implement\Repository\MapperParser(['descripcion', 'corredor', 'pisos', 'subterraneos'])) ->register('inmobiliaria', (new Implement\Repository\Mapper()) ->setFactory((new Implement\Repository\Factory()) ->setCallable([$this->inmobiliariaRepository, 'fetchById']) ->setArgs([$data['inmobiliaria']]))) ->register('direccion', (new Implement\Repository\Mapper()) ->setFactory((new Implement\Repository\Factory()) ->setCallable([$this->direccionRepository, 'fetchById']) ->setArgs([$data['direccion']]))) ->register('superficie_terreno', (new Implement\Repository\Mapper()) ->setProperty('terreno') ->setFunction(function($data) { $terreno = new Model\Proyecto\Terreno(); $terreno->superficie = $data['superficie_terreno']; $terreno->valorUnitario = $data['valor_unitario_terreno'] ?? 0; $terreno->valor = 0; $terreno->fecha = null; if (isset($data['fecha_terreno']) and $data['fecha_terreno'] !== '') { $terreno->valor = $data['valor_terreno']; $terreno->fecha = new DateTimeImmutable($data['fecha_terreno']); } return $terreno; })) ->register('superficie_sobre_nivel', (new Implement\Repository\Mapper()) ->setProperty('superficie') ->setFunction(function($data) { $superficie = new Model\Proyecto\Superficie(); $superficie->sobre_nivel = $data['superficie_sobre_nivel']; $superficie->bajo_nivel = $data['superficie_bajo_nivel']; return $superficie; })); return $this->parseData(new Model\Proyecto(), $data, $map); } public function save(Define\Model $model): Define\Model { $model->id = $this->saveNew( ['inmobiliaria', 'descripcion', 'direccion', 'superficie_terreno', 'valor_terreno', 'corredor', 'superficie_sobre_nivel', 'superficie_bajo_nivel', 'pisos', 'subterraneos'], [$model->inmobiliaria()->rut, $model->descripcion, $model->direccion()->id, $model->terreno->superficie, $model->terreno->valorUnitario, $model->corredor, $model->superficie->sobre_nivel, $model->superficie->bajo_nivel, $model->pisos, $model->subterraneos] ); return $model; } public function edit(Define\Model $model, array $new_data): Define\Model { return $this->update($model, ['inmobiliaria', 'descripcion', 'direccion', 'superficie_terreno', 'valor_terreno', 'corredor', 'superficie_sobre_nivel', 'superficie_bajo_nivel', 'pisos', 'subterraneos'], $new_data); } public function fetchById(int $id): Model\Proyecto { $query = $this->connection->getQueryBuilder() ->select($this->columns()) ->from("{$this->getTable()} a") ->joined($this->joinTerreno()) ->where("a.id = ?"); return $this->fetchOne($query, [$id]); } public function fetchByName(string $name): Model\Proyecto { $query = $this->connection->getQueryBuilder() ->select($this->columns()) ->from("{$this->getTable()} a") ->joined($this->joinTerreno()) ->where("a.descripcion LIKE ?"); return $this->fetchOne($query, ["%{$name}%"]); } public function fetchAllActive(null|string|array $orderBy = null): array { $etapaProyecto = $this->etapaRepository->fetchByDescripcion('Proyecto'); $etapaTerminado = $this->etapaRepository->fetchByDescripcion('Terminado'); $query = $this->connection->getQueryBuilder() ->select($this->columns()) ->from("{$this->getTable()} a") ->joined($this->joinTerreno()) ->joined($this->joinEstado()) ->where("et.orden BETWEEN {$etapaProyecto->orden} AND ({$etapaTerminado->orden} - 1)"); if ($orderBy === null) { $query = $query->order('a.descripcion'); } else { $query = $query->order($orderBy); } return $this->fetchMany($query); } public function fetchAllEscriturando(): array { $etapaRecepcion = $this->etapaRepository->fetchByDescripcion('Recepción'); $etapaTerminado = $this->etapaRepository->fetchByDescripcion('Terminado'); $query = $this->connection->getQueryBuilder() ->select($this->columns()) ->from("{$this->getTable()} a") ->joined($this->joinTerreno()) ->joined($this->joinEstado()) ->where("et.orden BETWEEN {$etapaRecepcion->orden} AND ({$etapaTerminado->orden} - 1)") ->order('a.descripcion'); return $this->fetchMany($query); } public function editTerreno(Model\Proyecto $proyecto, array $data): Model\Proyecto { $fecha = new DateTimeImmutable($data['fecha']); try { $query = $this->connection->getQueryBuilder() ->select('valor') ->from('proyecto_terreno') ->where('proyecto_id = ? AND fecha = ?'); $result = $this->connection->execute($query, [$proyecto->id, $fecha->format('Y-m-d')])->fetch(PDO::FETCH_ASSOC); if ($result === false) { throw new Implement\Exception\EmptyResult($query); } if ($result['valor'] !== $data['valor']) { $query = $this->connection->getQueryBuilder() ->update('proyecto_terreno') ->set('valor = ?') ->where('proyecto_id = ? AND fecha = ?'); $this->connection->execute($query, [$data['valor'], $proyecto->id, $fecha->format('Y-m-d')]); $proyecto->terreno->valor = $data['valor']; } } catch (PDOException | Implement\Exception\EmptyResult) { $query = $this->connection->getQueryBuilder() ->insert() ->into('proyecto_terreno') ->columns(['proyecto_id', 'fecha', 'valor', 'tipo_moneda_id']) ->values(['?', '?', '?', '1']); try { $this->connection->execute($query, [$proyecto->id, $fecha->format('Y-m-d'), $data['valor']]); $proyecto->terreno->fecha = $fecha; $proyecto->terreno->valor = $data['valor']; } catch (PDOException $exception) { throw new Implement\Exception\EmptyResult($query); } } return $proyecto; } public function fetchByInmobiliaria(int $inmobiliaria_rut): array { $query = $this->connection->getQueryBuilder() ->select() ->from($this->getTable()) ->where('inmobiliaria = ?'); return $this->fetchMany($query, [$inmobiliaria_rut]); } /** * @param int $promotion_id * @return array * @throws Implement\Exception\EmptyResult */ public function fetchByPromotion(int $promotion_id): array { $query = $this->connection->getQueryBuilder() ->select('a.*') ->from("{$this->getTable()} a") ->joined('INNER JOIN promotion_projects pp ON pp.project_id = a.id') ->where('pp.promotion_id = :promotion_id'); return $this->fetchMany($query, ['promotion_id' => $promotion_id]); } /*public function fetchSuperficieVendido(int $proyecto_id): float { }*/ protected function columns(): string { return "a.id, a.inmobiliaria, a.descripcion, a.direccion, a.superficie_terreno, valor_terreno AS valor_unitario_terreno, COALESCE(pt.valor, '') AS valor_terreno, COALESCE(pt.fecha, '') AS fecha_terreno, a.corredor, a.superficie_sobre_nivel, a.superficie_bajo_nivel, a.pisos, a.subterraneos"; } protected function joinTerreno(): string { return "LEFT OUTER JOIN (SELECT pt1.* FROM proyecto_terreno pt1 JOIN (SELECT MAX(id) AS id, proyecto_id FROM proyecto_terreno GROUP BY proyecto_id) pt0 ON pt0.id = pt1.id) pt ON pt.proyecto_id = a.id"; } protected function joinEstado(): string { return "JOIN ( SELECT e2.* FROM `estado_proyecto` e2 JOIN ( SELECT MAX(e1.`id`) AS 'id', e1.`proyecto` FROM `estado_proyecto` e1 JOIN ( SELECT `id`, `proyecto`, MAX(`fecha`) as 'fecha' FROM `estado_proyecto` GROUP BY `proyecto`, `fecha` ) e0 ON e1.`id` = e0.`id` GROUP BY `proyecto` ) e01 ON e01.`id` = e2.`id` ) ep ON ep.`proyecto` = a.`id` JOIN `tipo_estado_proyecto` tep ON tep.`id` = ep.`estado` JOIN `etapa_proyecto` et ON et.`id` = tep.`etapa`"; } }