process($this->ventaRepository->fetchById($venta_id)); } catch (Implement\Exception\EmptyResult $exception) { throw new Read(__CLASS__, $exception); } } public function getByProyecto(int $proyecto_id): array { $ventas = $this->ventaRepository->fetchByProyecto($proyecto_id); return array_map([$this, 'process'], $ventas); } public function getActivaByProyecto(int $proyecto_id): array { $ventas = $this->ventaRepository->fetchActivaByProyecto($proyecto_id); return array_map([$this, 'process'], $ventas); } public function getIdsByProyecto(int $proyecto_id): array { return $this->ventaRepository->fetchIdsByProyecto($proyecto_id); } public function getByProyectoAndUnidad(string $proyecto_nombre, int $unidad_descripcion): Model\Venta { $venta = $this->ventaRepository->fetchByProyectoAndUnidad($proyecto_nombre, $unidad_descripcion); return $this->process($venta); } /** * @param string $unidad * @param string $tipo * @return array * @throws Read */ public function getByUnidad(string $unidad, string $tipo): array { try { $ventas = $this->ventaRepository->fetchByUnidad($unidad, $tipo); return array_map([$this, 'process'], $ventas); } catch (Implement\Exception\EmptyResult $exception) { throw new Read(__CLASS__, $exception); } } /** * @param int $unidad_id * @return Model\Venta * @throws Read */ public function getByUnidadId(int $unidad_id): Model\Venta { try { return $this->process($this->ventaRepository->fetchByUnidadId($unidad_id)); } catch (Implement\Exception\EmptyResult $exception) { throw new Read(__CLASS__, $exception); } } public function getByPropietario(string $propietario): array { $ventas = $this->ventaRepository->fetchByPropietario($propietario); return array_map([$this, 'process'], $ventas); } public function getByPrecio(string $precio): array { $ventas = $this->ventaRepository->fetchByPrecio($precio); return array_map([$this, 'process'], $ventas); } public function getEscriturasByProyecto(int $proyecto_id): array { $ventas = $this->ventaRepository->fetchEscriturasByProyecto($proyecto_id); return array_map([$this, 'process'], $ventas); } public function getByIdForSearch(int $venta_id): array { return $this->ventaRepository->fetchByIdForSearch($venta_id); } public function getByIdForList(int $venta_id): array { return $this->ventaRepository->fetchByIdForList($venta_id); } public function getByPie(int $pie_id): Model\Venta { return $this->process($this->ventaRepository->fetchByPie($pie_id)); } public function getFacturacionById(int $venta_id): array { $venta = $this->getById($venta_id); $escritura = (in_array($venta->currentEstado()->tipoEstadoVenta->descripcion, ['escriturando', 'firmado por inmobiliaria'])) ? $venta->currentEstado()->fecha : $venta->fecha; $data = [ 'id' => $venta->id, 'fecha' => $venta->fecha->format('Y-m-d'), 'valor' => $venta->valor, 'escritura' => $escritura->format('Y-m-d'), 'unidades' => [], ]; foreach ($venta->propiedad()->unidades as $unidad) { $data['unidades'] []= [ 'id' => $unidad->id, 'tipo' => ucwords($unidad->proyectoTipoUnidad->tipoUnidad->descripcion), 'descripcion' => $unidad->descripcion, 'prorrateo' => $unidad->prorrateo, 'valor' => $unidad->valor, 'precio' => (isset($unidad->currentPrecio)) ? $unidad->currentPrecio->valor : 0 ]; } $principal = $venta->propiedad()->principal(); $data['principal'] = [ 'id' => $principal->id, 'descripcion' => $principal->descripcion ]; return $data; } protected function process(Model\Venta $venta): Model\Venta { $venta->addFactory('formaPago', (new Implement\Repository\Factory()) ->setCallable([$this->formaPagoService, 'getByVenta']) ->setArgs(['venta_id' => $venta->id])); $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; } /** * @throws Exception */ public function add(array $data): Model\Venta { $fecha = new DateTimeImmutable($data['fecha_venta']); $data['uf'] = $this->moneyService->getUF($fecha); $propietario = $this->addPropietario($data); $propiedad = $this->addPropiedad($data); $formaPago = $this->addFormaPago($data); $venta_data = [ 'propietario' => $propietario->rut, 'propiedad' => $propiedad->id, 'fecha' => $fecha->format('Y-m-d'), 'valor_uf' => $this->valorService->clean($data['valor']), 'fecha_ingreso' => (new DateTimeImmutable())->format('Y-m-d'), 'uf' => $data['uf'] ]; $map = ['pie', 'subsidio', 'credito', 'bono_pie']; foreach ($map as $field) { $name = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $field)))); if (isset($formaPago->{$name})) { $venta_data[$field] = $formaPago->{$name}->id; } } try { return $this->ventaRepository->fetchByPropietarioAndPropiedad($propietario->rut, $propiedad->id); } catch (Implement\Exception\EmptyResult) { $venta = $this->ventaRepository->create($venta_data); $venta->setFormaPago($formaPago); $venta = $this->ventaRepository->save($venta); $tipoEstado = $this->tipoEstadoVentaRepository->fetchByDescripcion('vigente'); $estado = $this->estadoVentaRepository->create([ 'venta' => $venta->id, 'estado' => $tipoEstado->id, 'fecha' => $venta->fecha->format('Y-m-d') ]); $this->estadoVentaRepository->save($estado); return $venta; } } protected function addPropietario(array $data): Model\Venta\Propietario { if (isset($data['natural_uno'])) { if (isset($data['natural_multiple'])) { return $this->addDosPropietarios($data); } return $this->addUnPropietario($data); } return $this->addSociedad($data); } protected function addUnPropietario(array $data): Model\Venta\Propietario { $fields = array_fill_keys([ 'rut', 'nombres', 'apellido_paterno', 'apellido_materno', 'calle', 'numero', 'extra', 'comuna' ], 0); $filtered_data = array_intersect_key($data, $fields); return $this->propietarioService->addPropietario($filtered_data); } protected function addDosPropietarios(array $data): Model\Venta\Propietario { $fields = array_fill_keys([ 'rut_otro', 'nombres_otro', 'apellido_paterno_otro', 'apellido_materno_otro', 'calle_otro', 'numero_otro', 'extra_otro', 'comuna_otro' ], 0); $filtered_data = array_intersect_key($data, $fields); $mapped_data = array_combine([ 'rut', 'nombres', 'apellido_paterno', 'apellido_materno', 'calle', 'numero', 'extra', 'comuna' ], $filtered_data); $otro = $this->propietarioService->addPropietario($mapped_data); $data['otro'] = $otro->rut; $fields = array_fill_keys([ 'rut', 'nombres', 'apellido_paterno', 'apellido_materno', 'calle', 'numero', 'extra', 'comuna', 'otro' ], 0); $filtered_data = array_intersect_key($data, $fields); return $this->propietarioService->addPropietario($filtered_data); } protected function addSociedad(array $data): Model\Venta\Propietario { $representante = $this->addUnPropietario($data); $data['representante'] = $representante->rut; $fields = array_fill_keys([ 'rut_sociedad', 'razon_social', 'calle_comercial', 'numero_comercial', 'extra_comercial', 'comuna_comercial', 'representante' ], 0); $filtered_data = array_intersect_key($data, $fields); $mapped_data = array_combine([ 'rut', 'razon_social', 'calle', 'numero', 'extra', 'comuna', 'representante' ], $filtered_data); return $this->propietarioService->addSociedad($mapped_data); } protected function addPropiedad(array $data): Model\Venta\Propiedad { $ids = array_filter($data, function($key) { return str_starts_with($key, 'unidad'); }, ARRAY_FILTER_USE_KEY); return $this->propiedadService->addPropiedad($ids); } protected function addFormaPago(array $data): Model\Venta\FormaPago { return $this->formaPagoService->add($data); } /** * @param Model\Venta $venta * @param array $data * @return Model\Venta * @throws Update */ public function edit(Model\Venta $venta, array $data): Model\Venta { try { $filteredData = $this->ventaRepository->filterData($data); return $this->ventaRepository->edit($venta, $filteredData); } catch (Implement\Exception\EmptyResult $exception) { throw new Update(__CLASS__, $exception); } } protected function addEstado(Model\Venta $venta, Model\Venta\TipoEstadoVenta $tipoEstadoVenta, array $data): void { try { $fecha = new DateTimeImmutable($data['fecha']); } catch (DateMalformedStringException) { $fecha = new DateTimeImmutable(); } $estadoData = [ 'venta' => $venta->id, 'estado' => $tipoEstadoVenta->id, 'fecha' => $fecha->format('Y-m-d') ]; $estado = $this->estadoVentaRepository->create($estadoData); $this->estadoVentaRepository->save($estado); } public function escriturar(Model\Venta $venta, array $data): bool { if (in_array($venta->currentEstado()->tipoEstadoVenta->descripcion, ['escriturando', 'firmado por inmobiliaria', 'archivado'])) { return true; } try { if ($this->validarData($data, ['fecha_reajuste', 'valor_reajuste'])) { $this->reajustarEscritura($venta, $data); } if ($this->validarData($data, ['fecha_pago'], ['valor_pago_pesos', 'valor_pago_ufs'])) { $this->abonoEscritura($venta, $data); } if ($this->validarData($data, ['banco_credito'], ['valor_credito'])) { $this->editCredito($venta, $data); } if ($this->validarData($data, ['valor_subsidio', 'valor_ahorro', 'fecha'])) { $this->subsidioEscritura($venta, $data); } $tipoEstado = $this->tipoEstadoVentaRepository->fetchByDescripcion('escriturando'); $this->addEstado($venta, $tipoEstado, ['fecha' => $data['fecha']]); return true; } catch (Implement\Exception\EmptyResult) { return false; } } protected function validarData(array $data, array $keys, array $optionals = []): bool { foreach ($keys as $key) { if (!isset($data[$key])) { return false; } if ($data[$key] === '') { return false; } } foreach ($optionals as $key) { if (isset($data[$key]) and $data[$key] !== '') { break; } } return true; } protected function reajustarEscritura(Model\Venta $venta, array $data): void { try { $fecha = new DateTimeImmutable($data['fecha_reajuste']); } catch (DateMalformedStringException) { $fecha = new DateTimeImmutable(); } $reajusteData = [ 'valor' => $this->valorService->clean($data['valor_reajuste']), 'fecha' => $fecha->format('Y-m-d') ]; $pie = $venta->formaPago()->pie; $this->pieService->reajustar($pie, $reajusteData); } protected function abonoEscritura(Model\Venta $venta, array $data): void { try { $fecha = new DateTimeImmutable($data['fecha_pago']); } catch (DateMalformedStringException) { $fecha = new DateTimeImmutable(); } $uf = $this->moneyService->getUF($fecha); $valor = $data['valor_pago_ufs'] !== '' ? $this->valorService->clean($data['valor_pago_ufs']) * $uf : $this->valorService->clean($data['valor_pago_pesos']); $pagoData = [ 'valor' => $valor, 'fecha' => $fecha->format('Y-m-d'), 'uf' => $uf ]; $pago = $this->pagoService->add($pagoData); $escrituraData = [ 'valor' => $valor, 'fecha' => $fecha->format('Y-m-d'), 'uf' => $uf, 'pago' => $pago->id ]; $escritura = $this->escrituraRepository->create($escrituraData); $escritura = $this->escrituraRepository->save($escritura); $this->ventaRepository->edit($venta, ['escritura' => $escritura->id]); } protected function subsidioEscritura(Model\Venta $venta, array $data): void { try { $fecha = new DateTimeImmutable($data['fecha']); } catch (DateMalformedStringException) { $fecha = new DateTimeImmutable(); } $uf = $this->moneyService->getUF($fecha); $subsidioData = [ 'fecha_venta' => $fecha->format('Y-m-d'), 'ahorro' => $this->valorService->clean($data['valor_ahorro']), 'subsidio' => $this->valorService->clean($data['valor_subsidio']), 'uf' => $uf ]; $formaPago = $this->addFormaPago($subsidioData); $this->ventaRepository->edit($venta, ['subsidio' => $formaPago->subsidio->id]); } protected function editCredito(Model\Venta $venta, array $data): void { try { $fecha = new DateTimeImmutable($data['fecha']); } catch (DateMalformedStringException) { $fecha = new DateTimeImmutable(); } $uf = $this->moneyService->getUF($fecha); $valor = $this->valorService->clean($data['valor_credito']) * $uf; if ($venta->formaPago()->credito === null) { if ($data['valor_credito'] === 0) { return; } $pagoData = [ 'valor' => $valor, 'fecha' => $fecha->format('Y-m-d'), 'uf' => $uf ]; $pago = $this->pagoService->add($pagoData); $creditoData = [ 'banco' => $data['banco_credito'], 'valor' => $valor, 'pago' => $pago->id ]; $credito = $this->creditoRepository->create($creditoData); $credito = $this->creditoRepository->save($credito); $this->ventaRepository->edit($venta, ['credito' => $credito->id]); return; } if ($data['valor_credito'] === 0) { $this->pagoRepository->remove($venta->formaPago()->credito->pago); $this->creditoRepository->remove($venta->formaPago()->credito); $this->ventaRepository->edit($venta, ['credito' => null]); return; } $this->pagoRepository->edit($venta->formaPago()->credito->pago, [ 'valor' => $valor, 'banco' => $data['banco_credito'], 'uf' => $uf ]); $this->estadoPagoRepository->edit($venta->formaPago()->credito->pago->currentEstado, [ 'fecha' => $fecha->format('Y-m-d') ]); $this->creditoRepository->edit($venta->formaPago()->credito, [ 'valor' => $valor, 'fecha' => $fecha->format('Y-m-d'), 'uf' => $uf ]); } public function desistir(Model\Venta $venta, array $data): bool { try { if ($this->validarData($data, ['fecha', 'devolucion'])) { $pago = $this->pagoService->add(['fecha' => $data['fecha'], 'valor' => $this->valorService->clean($data['devolucion'])]); $this->ventaRepository->edit($venta, ['resciliacion' => $pago->id]); } $tipoEstado = $this->tipoEstadoVentaRepository->fetchByDescripcion('desistida'); $this->addEstado($venta, $tipoEstado, ['fecha' => $data['fecha']]); return true; } catch (Implement\Exception\EmptyResult) { return false; } } public function insistir(Model\Venta $venta): bool { try { $pago = $venta->resciliacion(); $this->pagoService->delete($pago); $estado = $venta->currentEstado(); $this->estadoVentaRepository->remove($estado); $this->ventaRepository->edit($venta, ['resciliacion' => null]); return true; } catch (Implement\Exception\EmptyResult) { return false; } } }