process($this->ventaRepository->fetchById($venta_id)); } 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 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); return array_map([$this, 'process'], $ventas); } public function getByUnidadId(int $unidad_id): Model\Venta { return $this->process($this->ventaRepository->fetchByUnidadId($unidad_id)); } 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); } 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; } 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); $forma_pago = $this->addFormaPago($data); $venta_data = [ 'propietario' => $propietario->rut, 'propiedad' => $propiedad->id, 'fecha' => $fecha->format('Y-m-d'), 'valor_uf' => $this->cleanValue($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($forma_pago->{$name})) { $venta_data[$field] = $forma_pago->{$name}->id; } } try { return $this->ventaRepository->fetchByPropietarioAndPropiedad($propietario->rut, $propiedad->id); } catch (Implement\Exception\EmptyResult) { $venta = $this->ventaRepository->create($venta_data); $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_contains($key, 'unidad'); }, ARRAY_FILTER_USE_KEY); return $this->propiedadService->addPropiedad($ids); } protected function addFormaPago(array $data): Model\Venta\FormaPago { $fields = [ 'pie', 'subsidio', 'credito', 'bono_pie' ]; $forma_pago = new Model\Venta\FormaPago(); foreach ($fields as $name) { if (isset($data["has_{$name}"])) { $method = 'add' . str_replace(' ', '', ucwords(str_replace('_', ' ', $name))); $obj = $this->{$method}($data); $forma_pago->{$name} = $obj; } } return $forma_pago; } protected function addPie(array $data): Model\Venta\Pie { $fields = array_fill_keys([ 'fecha_venta', 'pie', 'cuotas', 'uf' ], 0); $filtered_data = array_intersect_key($data, $fields); $mapped_data = array_combine([ 'fecha', 'valor', 'cuotas', 'uf' ], $filtered_data); $mapped_data['valor'] = $this->cleanValue($mapped_data['valor']); return $this->pieService->add($mapped_data); } protected function addSubsidio(array $data): Model\Venta\Subsidio { $fields = array_fill_keys([ 'fecha_venta', 'ahorro', 'subsidio', 'uf' ], 0); $filtered_data = array_intersect_key($data, $fields); $mapped_data = array_combine([ 'fecha', 'ahorro', 'subsidio', 'uf' ], $filtered_data); return $this->subsidioService->add($mapped_data); } protected function addCredito(array $data): Model\Venta\Credito { $fields = array_fill_keys([ 'fecha_venta', 'credito', 'uf' ], 0); $filtered_data = array_intersect_key($data, $fields); $mapped_data = array_combine([ 'fecha', 'valor', 'uf' ], $filtered_data); return $this->creditoService->add($mapped_data); } protected function addBonoPie(array $data): Model\Venta\BonoPie { $fields = array_fill_keys([ 'fecha_venta', 'bono_pie' ], 0); $filtered_data = array_intersect_key($data, $fields); $mapped_data = array_combine([ 'fecha', 'valor' ], $filtered_data); return $this->bonoPieService->add($mapped_data); } protected function addEstado(Model\Venta $venta, Model\Venta\TipoEstadoVenta $tipoEstadoVenta, array $data): void { $fecha = new DateTimeImmutable($data['fecha']); $estadoData = [ 'venta' => $venta->id, 'estado' => $tipoEstadoVenta->id, 'fecha' => $fecha->format('Y-m-d') ]; $estado = $this->estadoVentaRepository->create($estadoData); $this->estadoVentaRepository->save($estado); } protected function cleanValue($value): float { if ((float) $value == $value) { return (float) $value; } return (float) str_replace(['.', ','], ['', '.'], $value); } 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 { $fecha = new DateTimeImmutable($data['fecha_reajuste']); $reajusteData = [ 'valor' => $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 { $fecha = new DateTimeImmutable($data['fecha_pago']); $uf = $this->moneyService->getUF($fecha); $valor = $data['valor_pago_ufs'] !== '' ? $data['valor_pago_ufs'] * $uf : $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 { $fecha = new DateTimeImmutable($data['fecha']); $uf = $this->moneyService->getUF($fecha); $subsidioData = [ 'fecha_venta' => $fecha->format('Y-m-d'), 'ahorro' => $data['valor_ahorro'], 'subsidio' => $data['valor_subsidio'], 'uf' => $uf ]; $subsidio = $this->addSubsidio($subsidioData); $this->ventaRepository->edit($venta, ['subsidio' => $subsidio->id]); } protected function editCredito(Model\Venta $venta, array $data): void { $fecha = new DateTimeImmutable($data['fecha']); $uf = $this->moneyService->getUF($fecha); $valor = $data['valor_credito'] * $uf; if ($venta->formaPago()->credito === null) { $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; } $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' => str_replace(['.', ','], ['', '.'], $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; } } }