From 0cd357b6cb934314abe2819a442bb2a3a691dbf4 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Wed, 13 Sep 2023 18:51:46 -0300 Subject: [PATCH] 2023-09-12 --- Dockerfile | 2 +- app/common/Define/Money/Provider.php | 9 + app/common/Ideal/Model.php | 5 +- app/common/Ideal/Repository.php | 5 +- .../Implement/Exception/EmptyResponse.php | 15 ++ .../Implement/Repository/Mapper/Boolean.php | 3 +- app/composer.json | 9 +- app/resources/routes/04_ventas.php | 10 +- app/resources/routes/ventas/pies.php | 13 + .../views/layout/body/scripts.blade.php | 18 ++ .../views/layout/body/scripts/dayjs.blade.php | 1 + app/resources/views/ventas/add.blade.php | 52 ++-- .../views/ventas/cuotas/abonar.blade.php | 3 +- .../views/ventas/pies/cuotas.blade.php | 79 ++++++ .../views/ventas/pies/cuotas/add.blade.php | 142 +++++++++++ app/setup/setups/services.php | 10 +- app/src/Controller/Proyectos.php | 2 +- app/src/Controller/Ventas.php | 21 ++ app/src/Controller/Ventas/Cuotas.php | 31 +++ app/src/Controller/Ventas/Pies.php | 23 ++ app/src/Model/Venta.php | 1 + app/src/Model/Venta/Credito.php | 2 + app/src/Model/Venta/Pie.php | 1 + app/src/Model/Venta/Propietario.php | 2 +- app/src/Repository/Direccion.php | 5 + app/src/Repository/Venta.php | 31 ++- app/src/Repository/Venta/Credito.php | 8 +- app/src/Repository/Venta/Cuota.php | 19 +- app/src/Repository/Venta/EstadoPago.php | 10 +- app/src/Repository/Venta/Pago.php | 15 +- app/src/Repository/Venta/Pie.php | 8 +- app/src/Repository/Venta/Propiedad.php | 22 +- app/src/Repository/Venta/Propietario.php | 14 +- app/src/Repository/Venta/Subsidio.php | 6 +- app/src/Repository/Venta/TipoEstadoVenta.php | 12 +- app/src/Repository/Venta/TipoPago.php | 12 +- app/src/Service/Money.php | 41 ++++ app/src/Service/Money/MiIndicador.php | 39 +++ app/src/Service/Venta.php | 227 +++++++++++++++++- app/src/Service/Venta/BonoPie.php | 15 ++ app/src/Service/Venta/Credito.php | 47 ++++ app/src/Service/Venta/Cuota.php | 44 +++- app/src/Service/Venta/Pago.php | 46 +++- app/src/Service/Venta/Pie.php | 14 +- app/src/Service/Venta/Propiedad.php | 87 +++++++ app/src/Service/Venta/Propietario.php | 102 ++++++++ app/src/Service/Venta/Subsidio.php | 44 ++++ 47 files changed, 1225 insertions(+), 102 deletions(-) create mode 100644 app/common/Define/Money/Provider.php create mode 100644 app/common/Implement/Exception/EmptyResponse.php create mode 100644 app/resources/routes/ventas/pies.php create mode 100644 app/resources/views/layout/body/scripts/dayjs.blade.php create mode 100644 app/resources/views/ventas/pies/cuotas.blade.php create mode 100644 app/resources/views/ventas/pies/cuotas/add.blade.php create mode 100644 app/src/Controller/Ventas/Pies.php create mode 100644 app/src/Service/Money.php create mode 100644 app/src/Service/Money/MiIndicador.php create mode 100644 app/src/Service/Venta/BonoPie.php create mode 100644 app/src/Service/Venta/Credito.php create mode 100644 app/src/Service/Venta/Propiedad.php create mode 100644 app/src/Service/Venta/Propietario.php create mode 100644 app/src/Service/Venta/Subsidio.php diff --git a/Dockerfile b/Dockerfile index 2b3b2ee..a33a7a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM php:8.1-fpm -RUN apt-get update && apt-get install -y libzip-dev libicu-dev git libpng-dev unzip \ +RUN apt-get update && apt-get install -y libzip-dev libicu-dev git libpng-dev unzip tzdata \ && rm -r /var/lib/apt/lists/* RUN docker-php-ext-install pdo pdo_mysql zip intl gd bcmath diff --git a/app/common/Define/Money/Provider.php b/app/common/Define/Money/Provider.php new file mode 100644 index 0000000..f91e079 --- /dev/null +++ b/app/common/Define/Money/Provider.php @@ -0,0 +1,9 @@ +factories[$property]->run(); + if (isset($this->factories[$property])) { + return $this->factories[$property]->run(); + } + return null; } public function jsonSerialize(): mixed diff --git a/app/common/Ideal/Repository.php b/app/common/Ideal/Repository.php index 56a2c10..cb49210 100644 --- a/app/common/Ideal/Repository.php +++ b/app/common/Ideal/Repository.php @@ -112,14 +112,15 @@ abstract class Repository implements Define\Repository $values []= $data[$column]; } } + if (count($changes) === 0) { return $model; } $columns_string = implode(', ', array_map(function($property) {return "`{$property}` = ?";}, $changes)); $query = "UPDATE `{$this->getTable()}` SET {$columns_string} WHERE `{$this->getKey()}` = ?"; - $values []= $model->id; + $values []= $model->{$this->getKey()}; $this->connection->execute($query, $values); - return $this->fetchById($model->id); + return $this->fetchById($model->{$this->getKey()}); } protected function fetchOne(string $query, ?array $data = null): Define\Model { diff --git a/app/common/Implement/Exception/EmptyResponse.php b/app/common/Implement/Exception/EmptyResponse.php new file mode 100644 index 0000000..2d7fb7d --- /dev/null +++ b/app/common/Implement/Exception/EmptyResponse.php @@ -0,0 +1,15 @@ +setFunction(function($data) use ($column) { return $data[$column] !== 0; }); + $this->setDefault($default); if ($property !== null) { $this->setProperty($property); } diff --git a/app/composer.json b/app/composer.json index 7472f7b..096f634 100644 --- a/app/composer.json +++ b/app/composer.json @@ -2,13 +2,14 @@ "name": "incoviba/web", "type": "project", "require": { - "slim/slim": "^4.11", - "php-di/php-di": "^7.0", - "php-di/slim-bridge": "^3.4", "berrnd/slim-blade-view": "^1.0", + "guzzlehttp/guzzle": "^7.8", "monolog/monolog": "^3.4", "nyholm/psr7": "^1.8", - "nyholm/psr7-server": "^1.0" + "nyholm/psr7-server": "^1.0", + "php-di/php-di": "^7.0", + "php-di/slim-bridge": "^3.4", + "slim/slim": "^4.11" }, "require-dev": { "phpunit/phpunit": "^10.2" diff --git a/app/resources/routes/04_ventas.php b/app/resources/routes/04_ventas.php index 404feb1..dc4fc8d 100644 --- a/app/resources/routes/04_ventas.php +++ b/app/resources/routes/04_ventas.php @@ -9,7 +9,10 @@ $app->group('/ventas', function($app) { } include_once $file->getRealPath(); } - $app->get('/add', [Ventas::class, 'add']); + $app->group('/add', function($app) { + $app->post('[/]', [Ventas::class, 'doAdd']); + $app->get('[/]', [Ventas::class, 'add']); + }); $app->get('[/]', Ventas::class); }); $app->group('/venta/{proyecto_nombre:[A-za-zÑñ\+\ %0-9]+}/{unidad_descripcion:[0-9]+}', function($app) { @@ -22,6 +25,11 @@ $app->group('/venta/{venta_id:[0-9]+}', function($app) { $app->group('/propiedad', function($app) { $app->get('[/]', [Ventas::class, 'propiedad']); }); + $app->group('/pie', function($app) { + $app->group('/cuotas', function($app) { + $app->get('[/]', [Ventas::class, 'cuotas']); + }); + }); $app->get('/edit[/]', [Ventas::class, 'edit']); $app->get('[/]', [Ventas::class, 'show']); }); diff --git a/app/resources/routes/ventas/pies.php b/app/resources/routes/ventas/pies.php new file mode 100644 index 0000000..25bb08a --- /dev/null +++ b/app/resources/routes/ventas/pies.php @@ -0,0 +1,13 @@ +group('/pie/{pie_id}', function($app) { + $app->group('/cuotas', function($app) { + $app->group('/add', function($app) { + $app->get('[/]', [Cuotas::class, 'add']); + $app->post('[/]', [Cuotas::class, 'doAdd']); + }); + $app->get('[/]', [Pies::class, 'cuotas']); + }); +}); diff --git a/app/resources/views/layout/body/scripts.blade.php b/app/resources/views/layout/body/scripts.blade.php index 9b8faa6..a8010eb 100644 --- a/app/resources/views/layout/body/scripts.blade.php +++ b/app/resources/views/layout/body/scripts.blade.php @@ -1,4 +1,22 @@ + + @stack('page_scripts') diff --git a/app/resources/views/layout/body/scripts/dayjs.blade.php b/app/resources/views/layout/body/scripts/dayjs.blade.php new file mode 100644 index 0000000..00d8045 --- /dev/null +++ b/app/resources/views/layout/body/scripts/dayjs.blade.php @@ -0,0 +1 @@ + diff --git a/app/resources/views/ventas/add.blade.php b/app/resources/views/ventas/add.blade.php index 3b88f25..75bb644 100644 --- a/app/resources/views/ventas/add.blade.php +++ b/app/resources/views/ventas/add.blade.php @@ -3,7 +3,7 @@ @section('page_content')

Nueva Venta

-
+
@@ -57,7 +57,7 @@ {{--Bodega--}} -
+

FORMA DE PAGO

@@ -605,7 +605,6 @@ } } } - console.debug(data) }) } } @@ -683,12 +682,10 @@ const unidad = new Unidad({number}) this.added.push(unidad) $(this.ids.unidades).append( - $('').attr('data-number', number).append( - $('').append( + $('
').addClass('item').attr('data-number', number).append( + $('
').addClass('content').append(tipo.charAt(0).toUpperCase() + tipo.slice(1) + ' ').append( unidad.draw(this.unidades[tipo]) - ) - ).append( - $('').append( + ).append( $('').addClass('ui icon button').attr('type', 'button').attr('data-number', number).append( $('').addClass('remove icon') ).click(event => { @@ -705,7 +702,7 @@ if (index === -1) { return } - $(this.ids.unidades).find("tr[data-number='" + number + "']").remove() + $(this.ids.unidades).find("div.item[data-number='" + number + "']").remove() this.added.splice(index, 1) } reset() { @@ -737,14 +734,10 @@ }) dropdown.append(menu) dropdown.dropdown() - return $('
').addClass('inline fields').attr('data-number', this.number).append(dropdown) + return dropdown } } - const unidades = { - data: [] - } - class Payment { ids @@ -754,10 +747,10 @@ checkbox: checkbox_id } - $(this.ids.base).hide() document.getElementById(this.ids.checkbox).onchange = event => { this.toggle() } + this.toggle() } get status() { @@ -772,13 +765,12 @@ } } + function showErrors(errors) { + console.debug(errors) + } + $(document).ready(() => { - $('#fecha_venta_calendar').calendar({ - type: 'date', - formatter: { - date: 'DD-MM-YYYY' - } - }) + $('#fecha_venta_calendar').calendar(calendar_date_options) new Propietario({id: '#propietario', id_tipo: 'persona_propietario', id_cantidad: 'cantidad_propietario'}) new Proyecto({unidades_id: '#unidades', proyecto_id: '#proyecto'}) @@ -794,6 +786,24 @@ checkbox_id: 'has_' + payment }) }) + + $('#add_form').submit(event => { + event.preventDefault() + const data = new FormData(event.currentTarget) + const uri = $(event.currentTarget).attr('action') + fetch(uri, {method: 'post', body: data}).then(response => { + if (response.ok) { + return response.json() + } + }).then(data => { + if (data.status) { + window.location = '{{$urls->base}}' + return true + } + showErrors(data.errors) + }) + return false + }) }) @endpush diff --git a/app/resources/views/ventas/cuotas/abonar.blade.php b/app/resources/views/ventas/cuotas/abonar.blade.php index f4e10bd..babfa2a 100644 --- a/app/resources/views/ventas/cuotas/abonar.blade.php +++ b/app/resources/views/ventas/cuotas/abonar.blade.php @@ -79,7 +79,8 @@ columnDefs: [ { target: 6, - visible: false + visible: false, + searchable: false }, { target: 2, diff --git a/app/resources/views/ventas/pies/cuotas.blade.php b/app/resources/views/ventas/pies/cuotas.blade.php new file mode 100644 index 0000000..2bc6a4a --- /dev/null +++ b/app/resources/views/ventas/pies/cuotas.blade.php @@ -0,0 +1,79 @@ +@extends('layout.base') + +@section('page_content') +
+
+

+
+
{{$venta->proyecto()->descripcion}}
+ {{$venta->propiedad()->summary()}} +
+

+
+

Cuotas - Pie

+ + + + + + + + + + + + + @foreach ($venta->formaPago()->pie->cuotas() as $cuota) + + + + + + + + + @endforeach + +
#FechaFecha ISOBancoIdentificadorValor
{{$cuota->numero}} + {{$cuota->pago->fecha->format('d-m-Y')}} + + {{$cuota->pago->fecha->format('Y-m-d')}} + + {{$cuota->pago->banco->nombre}} + + {{$cuota->pago->identificador}} + + {{$format->pesos($cuota->pago->valor)}} +
+
+@endsection + +@include('layout.body.scripts.datatables') + +@push('page_scripts') + +@endpush diff --git a/app/resources/views/ventas/pies/cuotas/add.blade.php b/app/resources/views/ventas/pies/cuotas/add.blade.php new file mode 100644 index 0000000..22764c3 --- /dev/null +++ b/app/resources/views/ventas/pies/cuotas/add.blade.php @@ -0,0 +1,142 @@ +@extends('layout.base') + +@section('page_content') +
+
+

+
+
{{$venta->proyecto()->descripcion}}
+ {{$venta->propiedad()->summary()}} +
+

+
+

Agregar Cuotas - Pie

+ + + + + + + + + + + + + @for ($i = count($pie->cuotas()); $i < $pie->cuotas - count($pie->cuotas()); $i ++) + + + + + + + + @endfor + + + + + + +
#FechaBancoIdentificadorValor
{{$i + 1}} +
+
+
+ + +
+
+ +
+
+ + + +
+ +
+
+
+
+
$
+ +
+ +
+
+ +
+ +
+@endsection + +@include('layout.body.scripts.dayjs') + +@push('page_scripts') + +@endpush diff --git a/app/setup/setups/services.php b/app/setup/setups/services.php index 3f4906f..bc51aaa 100644 --- a/app/setup/setups/services.php +++ b/app/setup/setups/services.php @@ -10,5 +10,13 @@ return [ $container->has('COOKIE_DOMAIN') ? $container->get('COOKIE_DOMAIN') : '', $container->has('COOKIE_PATH') ? $container->get('COOKIE_PATH') : '' ); - } + }, + Incoviba\Service\Money::class => function(ContainerInterface $container) { + $mindicador = new Incoviba\Service\Money\MiIndicador(new GuzzleHttp\Client([ + 'base_uri' => 'https://mindicador.cl/api/', + 'headers' => ['Accept' => 'application/json'] + ])); + return (new Incoviba\Service\Money())->register('uf', $mindicador) + ->register('ipc', $mindicador); + }, ]; diff --git a/app/src/Controller/Proyectos.php b/app/src/Controller/Proyectos.php index d38d09f..39cc1e4 100644 --- a/app/src/Controller/Proyectos.php +++ b/app/src/Controller/Proyectos.php @@ -29,7 +29,7 @@ class Proyectos { $output = ['proyecto_id' => $proyecto_id, 'unidades' => [], 'total' => 0]; try { - $unidades = $unidadRepository->fetchByProyecto($proyecto_id); + $unidades = $unidadRepository->fetchDisponiblesByProyecto($proyecto_id); $tipos = []; foreach ($unidades as $unidad) { if (!isset($tipos[$unidad->proyectoTipoUnidad->tipoUnidad->descripcion])) { diff --git a/app/src/Controller/Ventas.php b/app/src/Controller/Ventas.php index 215bbeb..153237f 100644 --- a/app/src/Controller/Ventas.php +++ b/app/src/Controller/Ventas.php @@ -111,4 +111,25 @@ class Ventas $proyectos = $proyectoRepository->fetchAllActive(); return $view->render($response, 'ventas.add', compact('regiones', 'proyectos')); } + public function doAdd(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService): ResponseInterface + { + $data = $request->getParsedBody(); + $output = [ + 'status' => false, + 'errors' => [] + ]; + try { + $ventaService->add($data); + $output['status'] = true; + } catch (\Exception $exception) { + $output['errors'] = $exception; + } + $response->getBody()->write(json_encode($output)); + return $response->withHeader('Content-Type', 'application/json'); + } + public function cuotas(ServerRequestInterface $request, ResponseInterface $response, Service\Venta $ventaService, View $view, int $venta_id): ResponseInterface + { + $venta = $ventaService->getById($venta_id); + return $view->render($response, 'ventas.pies.cuotas', compact('venta')); + } } diff --git a/app/src/Controller/Ventas/Cuotas.php b/app/src/Controller/Ventas/Cuotas.php index 731c151..ea2b29d 100644 --- a/app/src/Controller/Ventas/Cuotas.php +++ b/app/src/Controller/Ventas/Cuotas.php @@ -8,6 +8,7 @@ use Incoviba\Common\Implement\Exception\EmptyResult; use Incoviba\Common\Alias\View; use Incoviba\Repository; use Incoviba\Service; +use Incoviba\Model; class Cuotas { @@ -72,4 +73,34 @@ class Cuotas $response->getBody()->write(json_encode($output)); return $response->withHeader('Content-Type', 'application/json'); } + public function add(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pie $pieService, Repository\Venta $ventaRepository, Repository\Banco $bancoRepository, View $view, int $pie_id): ResponseInterface + { + $pie = $pieService->getById($pie_id); + $venta = $ventaRepository->fetchByPie($pie_id); + $bancos = $bancoRepository->fetchAll(); + usort($bancos, function(Model\Banco $a, Model\Banco $b) { + return strcmp($a->nombre, $b->nombre); + }); + return $view->render($response, 'ventas.pies.cuotas.add', compact('pie', 'venta', 'bancos')); + } + public function doAdd(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pie $pieService, Repository\Venta $ventaRepository, int $pie_id): ResponseInterface + { + $body = $request->getParsedBody(); + $pie = $pieService->getById($pie_id); + $venta = $ventaRepository->fetchByPie($pie_id); + $total = $pie->cuotas - count($pie->cuotas()); + $start = count($pie->cuotas()); + for ($i = $start; $i < $total; $i ++) { + $data = [ + 'pie' => $pie->id, + 'fecha' => $body["fecha{$i}"], + 'banco' => $body["banco{$i}"], + 'identificador' => $body["identificador{$i}"], + 'valor' => str_replace(['.', ','], ['', ''], $body["valor{$i}"]), + 'numero' => $i + 1, + ]; + $pieService->addCuota($data); + } + return $response->withHeader('Location', "/venta/{$venta->id}"); + } } diff --git a/app/src/Controller/Ventas/Pies.php b/app/src/Controller/Ventas/Pies.php new file mode 100644 index 0000000..21e5fcc --- /dev/null +++ b/app/src/Controller/Ventas/Pies.php @@ -0,0 +1,23 @@ +getById($pie_id); + $venta = $ventaRepository->fetchByPie($pie_id); + $bancos = $bancoRepository->fetchAll(); + usort($bancos, function(Model\Banco $a, Model\Banco $b) { + return strcmp($a->nombre, $b->nombre); + }); + return $view->render($response, 'ventas.pies.cuotas', compact('pie', 'venta', 'bancos')); + } +} diff --git a/app/src/Model/Venta.php b/app/src/Model/Venta.php index e648c59..39621d2 100644 --- a/app/src/Model/Venta.php +++ b/app/src/Model/Venta.php @@ -15,6 +15,7 @@ class Venta extends Ideal\Model public float $valor; public bool $relacionado; protected ?Venta\Entrega $entrega; + public float $uf; public array $estados; public Venta\EstadoVenta $currentEstado; diff --git a/app/src/Model/Venta/Credito.php b/app/src/Model/Venta/Credito.php index e1f8a3a..25b4fa3 100644 --- a/app/src/Model/Venta/Credito.php +++ b/app/src/Model/Venta/Credito.php @@ -5,11 +5,13 @@ use Incoviba\Common\Ideal; class Credito extends Ideal\Model { + public ?float $valor; public Pago $pago; public function jsonSerialize(): mixed { return array_merge(parent::jsonSerialize(), [ + 'valor' => $this->valor, 'pago' => $this->pago ]); } diff --git a/app/src/Model/Venta/Pie.php b/app/src/Model/Venta/Pie.php index 0931ee9..d4a8d98 100644 --- a/app/src/Model/Venta/Pie.php +++ b/app/src/Model/Venta/Pie.php @@ -3,6 +3,7 @@ namespace Incoviba\Model\Venta; use DateTimeInterface; use Incoviba\Common\Ideal\Model; +use Incoviba\Model\Venta; class Pie extends Model { diff --git a/app/src/Model/Venta/Propietario.php b/app/src/Model/Venta/Propietario.php index 77300eb..7028773 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 ?bool $otro; + public ?Propietario $otro; public function rut(): string { diff --git a/app/src/Repository/Direccion.php b/app/src/Repository/Direccion.php index 44d3508..e2396b4 100644 --- a/app/src/Repository/Direccion.php +++ b/app/src/Repository/Direccion.php @@ -40,4 +40,9 @@ class Direccion extends Ideal\Repository $query = "SELECT * FROM `{$this->getTable()}` WHERE `calle` = ? AND `numero` = ?"; return $this->fetchMany($query, [$calle, $numero]); } + public function fetchByCalleAndNumeroAndExtra(string $calle, int $numero, string $extra): Model\Direccion + { + $query = "SELECT * FROM `{$this->getTable()}` WHERE `calle` = ? AND `numero` = ? AND `extra` = ?"; + return $this->fetchOne($query, [$calle, $numero, $extra]); + } } diff --git a/app/src/Repository/Venta.php b/app/src/Repository/Venta.php index f594e6f..1901cc7 100644 --- a/app/src/Repository/Venta.php +++ b/app/src/Repository/Venta.php @@ -27,9 +27,9 @@ class Venta extends Ideal\Repository $this->setTable('venta'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta { - $map = (new Implement\Repository\MapperParser()) + $map = (new Implement\Repository\MapperParser(['uf'])) ->register('propietario', (new Implement\Repository\Mapper()) ->setFactory((new Implement\Repository\Factory()) ->setCallable([$this->propietarioRepository, 'fetchById']) @@ -65,7 +65,7 @@ class Venta extends Ideal\Repository ] ]; foreach ($map as $column => $settings) { - if ($data[$column] !== null and $data[$column] !== 0) { + if (isset($data[$column]) and $data[$column] !== 0) { if (isset($settings['repository'])) { $fp->{$settings['property'] ?? $column} = $settings['repository']->fetchById($data[$column]); continue; @@ -89,7 +89,7 @@ class Venta extends Ideal\Repository ->setFunction(function($data) { return $data['escritura'] !== null; }))*/ - ->register('entrega', (new Implement\Repository\Mapper()) + /*->register('entrega', (new Implement\Repository\Mapper()) ->setFactory((new Implement\Repository\Factory()) ->setCallable(function($entrega_id) { if ($entrega_id !== null and $entrega_id !== 0) { @@ -97,7 +97,8 @@ class Venta extends Ideal\Repository } return null; }) - ->setArgs([$data['entrega']]))) + ->setArgs([$data['entrega']])) + ->setDefault(null))*/ /*->register('entregado', (new Implement\Repository\Mapper()) ->setFactory((new Implement\Repository\Factory()) ->setCallable(function($entrega_id) { @@ -114,28 +115,27 @@ class Venta extends Ideal\Repository ->register('fecha_ingreso', new Implement\Repository\Mapper\DateTime('fecha_ingreso', 'fechaIngreso')) //->register('avalchile') //->register('agente') - //->register('uf') ->register('relacionado', new Implement\Repository\Mapper\Boolean('relacionado')); //->register('promocion') //->register('resciliacion') //->register('devolucion'); return $this->parseData(new Model\Venta(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta { $model->id = $this->saveNew( ['propietario', 'propiedad', 'pie', 'bono_pie', 'credito', 'escritura', 'subsidio', 'escriturado', 'entrega', 'entregado', 'fecha', 'valor_uf', 'estado', 'fecha_ingreso', 'avalchile', 'agente', 'uf', 'relacionado', 'promocion', 'resciliacion', 'devolucion'], - [$model->propietario->rut, $model->propiedad()->id, $model->formaPago()->Pie?->id, $model->formaPago()->bonoPie?->id, + [$model->propietario()->rut, $model->propiedad()->id, $model->formaPago()->pie?->id, $model->formaPago()->bonoPie?->id, $model->formaPago()->credito?->id, $model->formaPago()->escritura?->id, $model->formaPago()->subsidio?->id, - $model->formaPago()->escritura !== null ? 1 : 0, null, 0, $model->fecha->format('Y-m-d'), $model->valor, - $model->currentEstado->vigente ? 1 : 0, $model->fechaIngreso->format('Y-m-d'), '', null, 0, - $model->relacionado ? 1 : 0, null, null, null] + $model->formaPago()->escritura !== null ? $model->formaPago()->escritura->pago->fecha->format('Y-m-d') : null, + null, null, $model->fecha->format('Y-m-d'), $model->valor, 1, $model->fechaIngreso->format('Y-m-d'), + null, null, $model->uf, $model->relacionado ? 1 : 0, null, null, null] ); return $model; } - public function edit(Define\Model $model, array $new_data): Define\Model + public function edit(Define\Model $model, array $new_data): Model\Venta { return $this->update($model, ['propietario', 'propiedad', 'pie', 'bono_pie', 'credito', 'escritura', 'subsidio', 'escriturado', 'entrega', 'entregado', 'fecha', 'valor_uf', 'estado', 'fecha_ingreso', 'avalchile', 'agente', 'uf', @@ -155,7 +155,7 @@ WHERE ptu.`proyecto` = ? AND tev.`activa` GROUP BY a.`id`"; return $this->fetchMany($query, [$proyecto_id]); } - public function fetchByProyectoAndUnidad(string $proyecto_nombre, int $unidad_descripcion): Define\Model + public function fetchByProyectoAndUnidad(string $proyecto_nombre, int $unidad_descripcion): Model\Venta { $query = "SELECT a.* FROM `{$this->getTable()}` a @@ -168,4 +168,9 @@ FROM `{$this->getTable()}` a WHERE `proyecto`.`descripcion` = ? AND `unidad`.`descripcion` = ? AND tev.`activa`"; return $this->fetchOne($query, [$proyecto_nombre, $unidad_descripcion]); } + public function fetchByPie(int $pie_id): Model\Venta + { + $query = "SELECT * FROM `{$this->getTable()}` WHERE `pie` = ?"; + return $this->fetchOne($query, [$pie_id]); + } } diff --git a/app/src/Repository/Venta/Credito.php b/app/src/Repository/Venta/Credito.php index b5529c7..3767461 100644 --- a/app/src/Repository/Venta/Credito.php +++ b/app/src/Repository/Venta/Credito.php @@ -15,7 +15,7 @@ class Credito extends Ideal\Repository $this->setTable('credito'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta\Credito { $map = (new Implement\Repository\MapperParser()) ->register('pago', (new Implement\Repository\Mapper()) @@ -24,15 +24,15 @@ class Credito extends Ideal\Repository })); return $this->parseData(new Model\Venta\Credito(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta\Credito { $model->id = $this->saveNew( ['banco', 'valor', 'fecha', 'uf', 'abonado', 'fecha_abono', 'pago'], - [$model->pago->banco->id, $model->pago->valor, $model->pago->fecha->format('Y-m-d'), $model->pago->uf, null, null, $model->pago->id] + [$model->pago->banco?->id, $model->valor ?? (($model->pago->uf > 0) ? $model->pago->valor / $model->pago->uf : null), $model->pago->fecha->format('Y-m-d'), $model->pago->uf, null, null, $model->pago->id] ); return $model; } - public function edit(Define\Model $model, array $new_data): Define\Model + public function edit(Define\Model $model, array $new_data): Model\Venta\Credito { return $this->update($model, ['banco', 'valor', 'fecha', 'uf', 'abonado', 'fecha_abono', 'pago'], $new_data); } diff --git a/app/src/Repository/Venta/Cuota.php b/app/src/Repository/Venta/Cuota.php index 43c1ef8..b9d87ab 100644 --- a/app/src/Repository/Venta/Cuota.php +++ b/app/src/Repository/Venta/Cuota.php @@ -23,14 +23,17 @@ class Cuota extends Ideal\Repository $this->setTable('cuota'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta\Cuota { - $map = (new Implement\Repository\MapperParser(['valor', 'uf', 'numero'])) + $map = (new Implement\Repository\MapperParser(['uf', 'numero'])) ->register('pie', (new Implement\Repository\Mapper()) ->setFunction(function($data) { return $this->pieRepository->fetchById($data['pie']); })) ->register('fecha', new Implement\Repository\Mapper\DateTime('fecha')) + ->register('valor_$', (new Implement\Repository\Mapper()) + ->setProperty('valor') + ) ->register('estado', new Implement\Repository\Mapper\Boolean('estado')) ->register('banco', (new Implement\Repository\Mapper()) ->setFunction(function($data) { @@ -55,18 +58,18 @@ class Cuota extends Ideal\Repository return $this->parseData(new Model\Venta\Cuota(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta\Cuota { $model->id = $this->saveNew( - ['pie', 'fecha', 'valor', 'estado', 'banco', 'fecha_pago', 'abonado', 'fecha_abonado', 'uf', 'pago', 'numero'], - [$model->pie->id, $model->fecha->format('Y-m-d H:i:s'), $model->valor, $model->estado ? 1 : 0, $model?->banco->id, - $model?->fechaPago->format('Y-m-d H:i:s'), $model?->abonado ? 1 : 0, $model?->fechaAbonado->format('Y-m-d H:i:s'), - $model?->uf, $model?->pago->id, $model?->numero] + ['pie', 'fecha', 'valor_$', 'estado', 'banco', 'fecha_pago', 'abonado', 'fecha_abono', 'uf', 'pago', 'numero'], + [$model->pie->id, $model->fecha->format('Y-m-d H:i:s'), $model->valor, $model->estado ? 1 : 0, $model->banco?->id, + null, null, null, + $model->uf, $model->pago->id, $model->numero] ); return $model; } - public function edit(Define\Model $model, array $new_data): Define\Model + public function edit(Define\Model $model, array $new_data): Model\Venta\Cuota { return $this->update($model, ['pie', 'fecha', 'valor', 'estado', 'banco', 'fecha_pago', 'abonado', 'fecha_abonado', 'uf', 'pago', 'numero'], $new_data); } diff --git a/app/src/Repository/Venta/EstadoPago.php b/app/src/Repository/Venta/EstadoPago.php index 8fb1c78..250eb8d 100644 --- a/app/src/Repository/Venta/EstadoPago.php +++ b/app/src/Repository/Venta/EstadoPago.php @@ -18,7 +18,7 @@ class EstadoPago extends Ideal\Repository $this->setTable('estado_pago'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta\EstadoPago { $map = (new Implement\Repository\MapperParser()) ->register('pago', (new Implement\Repository\Mapper()) @@ -34,7 +34,7 @@ class EstadoPago extends Ideal\Repository return $this->parseData(new Model\Venta\EstadoPago(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta\EstadoPago { $model->id = $this->saveNew( ['pago', 'estado', 'fecha'], @@ -43,7 +43,7 @@ class EstadoPago 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\EstadoPago { return $this->update($model, ['pago', 'estado', 'fecha'], $new_data); } @@ -53,7 +53,7 @@ class EstadoPago extends Ideal\Repository $query = "SELECT * FROM `{$this->getTable()}` WHERE `pago` = ?"; return $this->fetchMany($query, [$pago_id]); } - public function fetchCurrentByPago(int $pago_id): Define\Model + public function fetchCurrentByPago(int $pago_id): Model\Venta\EstadoPago { $query = "SELECT a.* FROM `{$this->getTable()}` a @@ -61,7 +61,7 @@ FROM `{$this->getTable()}` a WHERE a.`pago` = ?"; return $this->fetchOne($query, [$pago_id]); } - public function fetchByPagoAndEstado(int $pago_id, int $estado_id): Define\Model + public function fetchByPagoAndEstado(int $pago_id, int $estado_id): Model\Venta\EstadoPago { $query = "SELECT * FROM `{$this->getTable()}` WHERE `pago` = ? AND `estado` = ?"; return $this->fetchOne($query, [$pago_id, $estado_id]); diff --git a/app/src/Repository/Venta/Pago.php b/app/src/Repository/Venta/Pago.php index c164417..04e380b 100644 --- a/app/src/Repository/Venta/Pago.php +++ b/app/src/Repository/Venta/Pago.php @@ -1,7 +1,6 @@ setTable('pago'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta\Pago { $map = (new Implement\Repository\MapperParser(['valor', 'identificador', 'uf', 'pagador'])) ->register('banco', (new Implement\Repository\Mapper()) @@ -45,15 +48,15 @@ class Pago extends Ideal\Repository })); return $this->parseData(new Model\Venta\Pago(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta\Pago { $model->id = $this->saveNew( ['valor', 'banco', 'tipo', 'identificador', 'fecha', 'uf', 'pagador', 'asociado'], - [$model->valor, $model?->banco->id, $model?->tipoPago->id, $model?->identificador, $model?->fecha->format('Y-m-d H:i:s'), $model?->uf, $model?->pagador, $model?->asociado->id] + [$model->valor, $model->banco?->id, $model->tipoPago?->id, $model->identificador, $model->fecha?->format('Y-m-d H:i:s'), $model->uf, $model->pagador, $model->asociado?->id] ); return $model; } - public function edit(Define\Model $model, array $new_data): Define\Model + public function edit(Define\Model $model, array $new_data): Model\Venta\Pago { return $this->update($model, ['valor', 'banco', 'tipo', 'identificador', 'fecha', 'uf', 'pagador', 'asociado'], $new_data); } diff --git a/app/src/Repository/Venta/Pie.php b/app/src/Repository/Venta/Pie.php index 6d66b85..650760f 100644 --- a/app/src/Repository/Venta/Pie.php +++ b/app/src/Repository/Venta/Pie.php @@ -15,7 +15,7 @@ class Pie extends Ideal\Repository $this->setTable('pie'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta\Pie { $map = (new Implement\Repository\MapperParser(['valor', 'uf', 'cuotas'])) ->register('fecha', new Implement\Repository\Mapper\DateTime('fecha')) @@ -35,15 +35,15 @@ class Pie extends Ideal\Repository })); return $this->parseData(new Model\Venta\Pie(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta\Pie { $model->id = $this->saveNew( ['fecha', 'valor', 'uf', 'cuotas', 'asociado', 'reajuste'], - [$model->fecha->format('Y-m-d H:i:s'), $model->valor, $model?->uf, $model->cuotas, $model?->asociado->id, $model?->reajuste->id] + [$model->fecha->format('Y-m-d H:i:s'), $model->valor, $model->uf, $model->cuotas, $model->asociado?->id, $model->reajuste?->id] ); return $model; } - public function edit(Define\Model $model, array $new_data): Define\Model + public function edit(Define\Model $model, array $new_data): Model\Venta\Pie { return $this->update($model, ['fecha', 'valor', 'uf', 'cuotas', 'asociado', 'reajuste'], $new_data); } diff --git a/app/src/Repository/Venta/Propiedad.php b/app/src/Repository/Venta/Propiedad.php index 173da2e..173e810 100644 --- a/app/src/Repository/Venta/Propiedad.php +++ b/app/src/Repository/Venta/Propiedad.php @@ -15,27 +15,39 @@ class Propiedad extends Ideal\Repository $this->setTable('propiedad'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta\Propiedad { $map = (new Implement\Repository\MapperParser()) ->register('unidad_principal', (new Implement\Repository\Mapper()) ->setProperty('unidades') ->setFunction(function($data) { - return $this->unidadService->getByPropiedad($data['id']); + if (isset($data['id'])) { + return $this->unidadService->getByPropiedad($data['id']); + } + return [$this->unidadService->getById($data['unidad_principal'])]; })) ->register('estado', new Implement\Repository\Mapper\Boolean('estado')); return $this->parseData(new Model\Venta\Propiedad(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta\Propiedad { $model->id = $this->saveNew( ['unidad_principal', 'estacionamientos', 'bodegas', 'estado'], - [$model->departamentos()[0]->id, null, null, 1] + [$model->departamentos()[0]->id, + implode(',', array_map(function(Model\Venta\Unidad $unidad) {return $unidad->id;}, $model->estacionamientos())), + implode(',', array_map(function(Model\Venta\Unidad $unidad) {return $unidad->id;}, $model->bodegas())), + 1] ); return $model; } - public function edit(Define\Model $model, array $new_data): Define\Model + public function edit(Define\Model $model, array $new_data): Model\Venta\Propiedad { return $this->update($model, ['unidad_principal', 'estacionamientos', 'bodegas', 'estado'], $new_data); } + + public function fetchVigenteByUnidad(int $unidad_id): Model\Venta\Propiedad + { + $query = "SELECT * FROM `{$this->getTable()}` WHERE `unidad_principal` = ?"; + return $this->fetchOne($query, [$unidad_id]); + } } diff --git a/app/src/Repository/Venta/Propietario.php b/app/src/Repository/Venta/Propietario.php index eacc4a7..6ed599b 100644 --- a/app/src/Repository/Venta/Propietario.php +++ b/app/src/Repository/Venta/Propietario.php @@ -50,7 +50,13 @@ class Propietario extends Ideal\Repository } return $this->fetchById($data['representante']); })) - ->register('otro', (new Implement\Repository\Mapper\Boolean('otro')) + ->register('otro', (new Implement\Repository\Mapper()) + ->setFunction(function($data) { + if ($data['otro'] === null or $data['otro'] === 0) { + return null; + } + return $this->fetchById($data['otro']); + }) ->setDefault(null)); return $this->parseData(new Model\Venta\Propietario(), $data, $map); } @@ -58,14 +64,14 @@ class Propietario extends Ideal\Repository public function save(Define\Model $model): Define\Model { $model->rut = $this->saveNew( - ['dv', 'nombres', 'apellido_paterno', 'apellido_materno'], - [$model->dv, $model->nombres, $model->apellidos['paterno'], $model->apellidos['materno']] + ['dv', 'nombres', 'apellido_paterno', 'apellido_materno', 'direccion', 'otro', 'representante'], + [$model->dv, $model->nombres, $model->apellidos['paterno'], $model->apellidos['materno'], $model->datos->direccion->id, $model->otro->rut ?? 0, $model->representante->rut ?? 0] ); return $model; } public function edit(Define\Model $model, array $new_data): Define\Model { - return $this->update($model, ['dv', 'nombres', 'apellido_paterno', 'apellido_materno'], $new_data); + return $this->update($model, ['dv', 'nombres', 'apellido_paterno', 'apellido_materno', 'direccion', 'otro', 'representante'], $new_data); } } diff --git a/app/src/Repository/Venta/Subsidio.php b/app/src/Repository/Venta/Subsidio.php index 12af4e2..f79ae24 100644 --- a/app/src/Repository/Venta/Subsidio.php +++ b/app/src/Repository/Venta/Subsidio.php @@ -14,12 +14,12 @@ class Subsidio extends Ideal\Repository $this->setTable('subsidio'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta\Subsidio { $map = new Implement\Repository\MapperParser(['pago', 'subsidio']); return $this->parseData(new Model\Venta\Subsidio(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta\Subsidio { $model->id = $this->saveNew( ['pago', 'subsidio'], @@ -27,7 +27,7 @@ class Subsidio 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\Subsidio { return $this->update($model, ['pago', 'subsidio'], $new_data); } diff --git a/app/src/Repository/Venta/TipoEstadoVenta.php b/app/src/Repository/Venta/TipoEstadoVenta.php index 7b07332..5043963 100644 --- a/app/src/Repository/Venta/TipoEstadoVenta.php +++ b/app/src/Repository/Venta/TipoEstadoVenta.php @@ -14,13 +14,13 @@ class TipoEstadoVenta extends Ideal\Repository $this->setTable('tipo_estado_venta'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta\TipoEstadoVenta { $map = (new Implement\Repository\MapperParser(['descripcion'])) ->register('activa', new Implement\Repository\Mapper\Boolean('activa')); return $this->parseData(new Model\Venta\TipoEstadoVenta(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta\TipoEstadoVenta { $model->id = $this->saveNew( ['descripcion', 'activa'], @@ -28,8 +28,14 @@ class TipoEstadoVenta 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\TipoEstadoVenta { return $this->update($model, ['descripcion', 'activa'], $new_data); } + + public function fetchByDescripcion(string $descripcion): Model\Venta\TipoEstadoVenta + { + $query = "SELECT * FROM `{$this->getTable()}` WHERE `descripcion` = ?"; + return $this->fetchOne($query, [$descripcion]); + } } diff --git a/app/src/Repository/Venta/TipoPago.php b/app/src/Repository/Venta/TipoPago.php index bcb8e52..0b2f365 100644 --- a/app/src/Repository/Venta/TipoPago.php +++ b/app/src/Repository/Venta/TipoPago.php @@ -14,12 +14,12 @@ class TipoPago extends Ideal\Repository $this->setTable('tipo_pago'); } - public function create(?array $data = null): Define\Model + public function create(?array $data = null): Model\Venta\TipoPago { $map = new Implement\Repository\MapperParser(['descripcion']); return $this->parseData(new Model\Venta\TipoPago(), $data, $map); } - public function save(Define\Model $model): Define\Model + public function save(Define\Model $model): Model\Venta\TipoPago { $model->id = $this->saveNew( ['descripcion'], @@ -27,8 +27,14 @@ class TipoPago 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\TipoPago { return $this->update($model, ['descripcion'], $new_data); } + + public function fetchByDescripcion(string $descripcion): Model\Venta\TipoPago + { + $query = "SELECT * FROM `{$this->getTable()}` WHERE `descripcion` = ?"; + return $this->fetchOne($query, [$descripcion]); + } } diff --git a/app/src/Service/Money.php b/app/src/Service/Money.php new file mode 100644 index 0000000..3cb7df8 --- /dev/null +++ b/app/src/Service/Money.php @@ -0,0 +1,41 @@ +providers) and isset($this->providers[$name]) and $this->providers[$name] === $provider) { + return $this; + } + $this->providers[$name] = $provider; + return $this; + } + public function getProvider(string $name): Provider + { + return $this->providers[$name]; + } + + public function getUF(DateTimeInterface $dateTime): float + { + try { + return $this->getProvider('uf')->get(MiIndicador::UF, $dateTime); + } catch (EmptyResponse) { + return 0; + } + } + public function getIPC(DateTimeInterface $dateTime): float + { + try { + return $this->getProvider('ipc')->get(MiIndicador::IPC, $dateTime); + } catch (EmptyResponse) { + return 0; + } + } +} diff --git a/app/src/Service/Money/MiIndicador.php b/app/src/Service/Money/MiIndicador.php new file mode 100644 index 0000000..113bc30 --- /dev/null +++ b/app/src/Service/Money/MiIndicador.php @@ -0,0 +1,39 @@ +format('d-m-Y')}"; + try { + $response = $this->client->get($request_uri); + } catch (GuzzleException) { + throw new EmptyResponse($request_uri); + } + + if ((int) floor($response->getStatusCode() / 100) !== 2) { + throw new EmptyResponse($request_uri); + } + + $body = $response->getBody(); + $json = json_decode($body->getContents()); + + if ($json->codigo !== $money_symbol or count($json->serie) === 0) { + throw new EmptyResponse($request_uri); + } + return $json->serie[0]->valor; + } +} diff --git a/app/src/Service/Venta.php b/app/src/Service/Venta.php index ec6b6b9..6609518 100644 --- a/app/src/Service/Venta.php +++ b/app/src/Service/Venta.php @@ -1,6 +1,7 @@ ventaRepository->fetchByProyectoAndUnidad($proyecto_nombre, $unidad_descripcion); - $venta->addFactory('estados', ['callable' => [$this->estadoVentaRepository, 'fetchByVenta'], 'args' => [$venta->id]]); - $venta->addFactory('currentEstado', ['callable' => [$this->estadoVentaRepository, 'fetchCurrentByVenta'], 'args' => [$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; } + + public function add(array $data): void + { + $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' => $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; + } + } + $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); + } + 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); + 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); + } } diff --git a/app/src/Service/Venta/BonoPie.php b/app/src/Service/Venta/BonoPie.php new file mode 100644 index 0000000..1d0663b --- /dev/null +++ b/app/src/Service/Venta/BonoPie.php @@ -0,0 +1,15 @@ +moneyService->getUF($fecha); + $tipoPago = $this->tipoPagoRepository->fetchByDescripcion('carta de resguardo'); + $pago = $this->addPago(['fecha' => $fecha->format('Y-m-d'), 'valor' => $data['valor'] * $uf, 'uf' => $uf, 'tipo' => $tipoPago->id]); + $credito = $this->creditoRepository->create([ + 'valor' => $data['valor'], + 'fecha' => $fecha->format('Y-m-d'), + 'pago' => $pago->id + ]); + return $this->creditoRepository->save($credito); + } + protected function addPago(array $data): Model\Venta\Pago + { + $pago = $this->pagoRepository->create($data); + $pago = $this->pagoRepository->save($pago); + $tipoEstado = $this->tipoEstadoPagoRepository->fetchByDescripcion('no pagado'); + $data = [ + 'pago' => $pago->id, + 'fecha' => $pago->fecha->format('Y-m-d'), + 'estado' => $tipoEstado->id + ]; + $estado = $this->estadoPagoRepository->create($data); + $this->estadoPagoRepository->save($estado); + return $pago; + } +} diff --git a/app/src/Service/Venta/Cuota.php b/app/src/Service/Venta/Cuota.php index 1891b0a..c3cda89 100644 --- a/app/src/Service/Venta/Cuota.php +++ b/app/src/Service/Venta/Cuota.php @@ -5,10 +5,15 @@ use DateTimeImmutable; use DateInterval; use IntlDateFormatter; use Incoviba\Repository; +use Incoviba\Model; class Cuota { - public function __construct(protected Repository\Venta\Cuota $cuotaRepository) {} + public function __construct( + protected Repository\Venta\Cuota $cuotaRepository, + protected Pago $pagoService, + protected Repository\Venta\TipoPago $tipoPagoRepository + ) {} public function pendientes(): array { @@ -68,4 +73,41 @@ class Cuota } return $cuotas_depositadas; } + public function getVigenteByPie(int $pie_id): array + { + return $this->cuotaRepository->fetchVigenteByPie($pie_id); + } + + public function add(array $data): Model\Venta\Cuota + { + $tipoPago = $this->tipoPagoRepository->fetchByDescripcion('cheque'); + $fields = array_fill_keys([ + 'fecha', + 'banco', + 'valor', + 'identificador' + ], 0); + $filtered_data = array_intersect_key($data, $fields); + $pago_data = array_merge($filtered_data, ['tipo' => $tipoPago->id]); + $pago = $this->pagoService->add($pago_data); + $data['pago'] = $pago->id; + $data['estado'] = $pago->currentEstado->tipoEstadoPago->id; + $fields = array_fill_keys([ + 'pie', + 'fecha', + 'valor', + 'estado', + 'banco', + 'uf', + 'pago', + 'numero' + ], 0); + $filtered_data = array_intersect_key($data, $fields); + $mapped_data = $filtered_data; + $mapped_data['valor_$'] = $mapped_data['valor']; + unset($mapped_data['valor']); + $cuota = $this->cuotaRepository->create($mapped_data); + $this->cuotaRepository->save($cuota); + return $cuota; + } } diff --git a/app/src/Service/Venta/Pago.php b/app/src/Service/Venta/Pago.php index 0bd7041..cff2779 100644 --- a/app/src/Service/Venta/Pago.php +++ b/app/src/Service/Venta/Pago.php @@ -3,15 +3,20 @@ namespace Incoviba\Service\Venta; use DateTimeInterface; use DateTimeImmutable; +use Incoviba\Service\Money; use PDOException; use Incoviba\Repository; use Incoviba\Model; +use Incoviba\Service; class Pago { - public function __construct(protected Repository\Venta\Pago $pagoRepository, - protected Repository\Venta\EstadoPago $estadoPagoRepository, - protected Repository\Venta\TipoEstadoPago $tipoEstadoPagoRepository) {} + public function __construct( + protected Repository\Venta\Pago $pagoRepository, + protected Repository\Venta\EstadoPago $estadoPagoRepository, + protected Repository\Venta\TipoEstadoPago $tipoEstadoPagoRepository, + protected Service\Money $moneyService + ) {} public function depositar(Model\Venta\Pago $pago, DateTimeInterface $fecha): bool { @@ -66,6 +71,12 @@ class Pago $pago = $this->pagoRepository->fetchById($pago_id); $pago->estados = $this->estadoPagoRepository->fetchByPago($pago_id); $pago->currentEstado = $this->estadoPagoRepository->fetchCurrentByPago($pago_id); + if (($pago->uf === null or $pago->uf === 0.0) and $pago->fecha < new DateTimeImmutable()) { + $pago->uf = $this->moneyService->getUF($pago->fecha); + if ($pago->uf !== 0.0) { + $this->pagoRepository->edit($pago, ['uf' => $pago->uf]); + } + } return $pago; } @@ -81,4 +92,33 @@ class Pago { return []; } + + public function add(array $data): Model\Venta\Pago + { + if (!isset($data['uf'])) { + $data['uf'] = $this->moneyService->getUF(new DateTimeImmutable($data['fecha'])); + } + $fields = array_fill_keys([ + 'valor', + 'banco', + 'tipo', + 'identificador', + 'fecha', + 'uf', + 'pagador', + 'asociado' + ], 0); + $filtered_data = array_intersect_key($data, $fields); + $pago = $this->pagoRepository->create($filtered_data); + $pago = $this->pagoRepository->save($pago); + $tipoEstado = $this->tipoEstadoPagoRepository->fetchByDescripcion('no pagado'); + $estado = $this->estadoPagoRepository->create([ + 'pago' => $pago->id, + 'fecha' => $pago->fecha->format('Y-m-d'), + 'estado' => $tipoEstado->id + ]); + $estado = $this->estadoPagoRepository->save($estado); + $pago->currentEstado = $estado; + return $pago; + } } diff --git a/app/src/Service/Venta/Pie.php b/app/src/Service/Venta/Pie.php index 0455d0a..3c07a0a 100644 --- a/app/src/Service/Venta/Pie.php +++ b/app/src/Service/Venta/Pie.php @@ -8,13 +8,23 @@ class Pie { public function __construct( protected Repository\Venta\Pie $pieRepository, - protected Repository\Venta\Cuota $cuotaRepository + protected Cuota $cuotaService ) {} public function getById(int $pie_id): Model\Venta\Pie { $pie = $this->pieRepository->fetchById($pie_id); - $pie->cuotasArray = $this->cuotaRepository->fetchVigenteByPie($pie_id); + $pie->cuotasArray = $this->cuotaService->getVigenteByPie($pie_id); return $pie; } + + public function add(array $data): Model\Venta\Pie + { + $pie = $this->pieRepository->create($data); + return $this->pieRepository->save($pie); + } + public function addCuota(array $data): Model\Venta\Cuota + { + return $this->cuotaService->add($data); + } } diff --git a/app/src/Service/Venta/Propiedad.php b/app/src/Service/Venta/Propiedad.php new file mode 100644 index 0000000..7de58ba --- /dev/null +++ b/app/src/Service/Venta/Propiedad.php @@ -0,0 +1,87 @@ +unidadRepository->fetchById($unidad_id); + } + usort($unidades, function(Model\Venta\Unidad $a, Model\Venta\Unidad $b) { + $t = $a->proyectoTipoUnidad->tipoUnidad->orden - $b->proyectoTipoUnidad->tipoUnidad->orden; + if ($t === 0) { + return strcmp(str_pad($a->descripcion, 4, '0', STR_PAD_LEFT), str_pad($b->descripcion, 4, '0', STR_PAD_LEFT)); + } + return $t; + }); + try { + $propiedad = $this->propiedadRepository->fetchVigenteByUnidad($unidades[0]->id); + } catch (EmptyResult) { + $propiedad = $this->propiedadRepository->create([ + 'unidad_principal' => $unidades[0]->id, + 'estado' => 1 + ]); + $propiedad = $this->propiedadRepository->save($propiedad); + } + $this->addUnidades($propiedad, $unidades); + $this->cleanUpUnidades($propiedad, $unidades); + + return $propiedad; + } + protected function addUnidades(Model\Venta\Propiedad $propiedad, array $unidades): void + { + $query = "SELECT 1 FROM `propiedad_unidad` WHERE `propiedad` = ? AND `unidad` = ?"; + $statement = $this->connection->prepare($query); + $query2 = "INSERT INTO `propiedad_unidad` (`propiedad`, `unidad`, `principal`) VALUES (?, ?, ?)"; + $insert = $this->connection->prepare($query2); + foreach ($unidades as $ix => $unidad) { + try { + $statement->execute([$propiedad->id, $unidad->id]); + $result = $statement->fetch(PDO::FETCH_ASSOC); + if (!$result) { + throw new EmptyResult($query); + } + } catch (PDOException|EmptyResult) { + $insert->execute([$propiedad->id, $unidad->id, ($ix === 0) ? 1 : 0]); + } + } + } + protected function cleanUpUnidades(Model\Venta\Propiedad $propiedad, array $unidades): void + { + $query = "SELECT `unidad` FROM `propiedad_unidad` WHERE `propiedad` = ?"; + $statement = $this->connection->prepare($query); + $statement->execute([$propiedad->id]); + $results = $statement->fetchAll(PDO::FETCH_ASSOC); + + if (!$results) { + return; + } + + $all_ids = array_map(function($row) {return $row['unidad'];}, $results); + $new_ids = array_map(function(Model\Venta\Unidad $unidad) {return $unidad->id;}, $unidades); + $diff = array_diff($all_ids, $new_ids); + if (count($diff) === 0) { + return; + } + $query = "DELECT FROM `propiedad_unidad` WHERE `propiedad` = ? AND `unidad` = ?"; + $statement = $this->connection->prepare($query); + foreach ($diff as $id) { + $statement->execute([$propiedad->id, $id]); + } + } +} diff --git a/app/src/Service/Venta/Propietario.php b/app/src/Service/Venta/Propietario.php new file mode 100644 index 0000000..699ad70 --- /dev/null +++ b/app/src/Service/Venta/Propietario.php @@ -0,0 +1,102 @@ +addDireccion($data); + $data['direccion'] = $direccion->id; + + if (str_contains($data['rut'], '-')) { + $data['rut'] = explode('-', $data['rut'])[0]; + } + + $fields = array_fill_keys([ + 'rut', + 'nombres', + 'apellido_paterno', + 'apellido_materno', + 'direccion' + ], 0); + $filtered_data = array_intersect_key($data, $fields); + + try { + $propietario = $this->propietarioRepository->fetchById($data['rut']); + $edits = []; + if ($propietario->datos->direccion->id !== $filtered_data['direccion']) { + $edits['direccion'] = $filtered_data['direccion']; + } + $propietario = $this->propietarioRepository->edit($propietario, $edits); + } catch (EmptyResult) { + $propietario = $this->propietarioRepository->create($filtered_data); + $propietario = $this->propietarioRepository->save($propietario); + } + return $propietario; + } + public function addSociedad(array $data): Model\Venta\Propietario + { + $direccion = $this->addDireccion($data); + $data['direccion'] = $direccion->id; + + if (str_contains($data['rut'], '-')) { + $data['rut'] = explode('-', $data['rut'])[0]; + } + + $fields = array_fill_keys([ + 'rut', + 'razon_social', + 'direccion', + 'representante' + ], 0); + $filtered_data = array_intersect_key($data, $fields); + $mapped_data = array_combine([ + 'rut', + 'nombres', + 'direccion', + 'representante' + ], $filtered_data); + + try { + $sociedad = $this->propietarioRepository->fetchById($data['rut']); + $edits = []; + if ($sociedad->datos->direccion->id !== $mapped_data['direccion']) { + $edits['direccion'] = $mapped_data['direccion']; + } + if ($sociedad->representante->rut !== $mapped_data['representante']) { + $edits['representante'] = $mapped_data['representante']; + } + $sociedad = $this->propietarioRepository->edit($sociedad, $edits); + } catch (EmptyResult) { + $sociedad = $this->propietarioRepository->create($mapped_data); + $sociedad = $this->propietarioRepository->save($sociedad); + } + return $sociedad; + } + protected function addDireccion(array $data): Model\Direccion + { + $fields = array_fill_keys([ + 'calle', + 'numero', + 'extra', + 'comuna' + ], 0); + $filtered_data = array_intersect_key($data, $fields); + try { + $direccion = $this->direccionRepository->fetchByCalleAndNumeroAndExtra($filtered_data['calle'], $filtered_data['numero'], $filtered_data['extra']); + } catch (EmptyResult) { + $direccion = $this->direccionRepository->create($filtered_data); + $direccion = $this->direccionRepository->save($direccion); + } + return $direccion; + } +} diff --git a/app/src/Service/Venta/Subsidio.php b/app/src/Service/Venta/Subsidio.php new file mode 100644 index 0000000..69766e2 --- /dev/null +++ b/app/src/Service/Venta/Subsidio.php @@ -0,0 +1,44 @@ +moneyService->getUF($fecha); + $tipoPago = $this->tipoPagoRepository->fetchByDescripcion('vale vista'); + $ahorro = $this->addPago(['fecha' => $fecha->format('Y-m-d'), 'valor' => $data['ahorro'] * $uf, 'uf' => $uf, 'tipo' => $tipoPago->id]); + $subsidio = $this->addPago(['fecha' => $fecha->format('Y-m-d'), 'valor' => $data['subsidio'] * $uf, 'uf' => $uf, 'tipo' => $tipoPago->id]); + $subsidio = $this->subsidioRepository->create(['pago' => $ahorro->id, 'subsidio' => $subsidio->id]); + return $this->subsidioRepository->save($subsidio); + } + protected function addPago(array $data): Model\Venta\Pago + { + $pago = $this->pagoRepository->create($data); + $pago = $this->pagoRepository->save($pago); + $tipoEstado = $this->tipoEstadoPagoRepository->fetchByDescripcion('no pagado'); + $data = [ + 'pago' => $pago->id, + 'fecha' => $pago->fecha->format('Y-m-d'), + 'estado' => $tipoEstado->id + ]; + $estado = $this->estadoPagoRepository->create($data); + $this->estadoPagoRepository->save($estado); + return $pago; + } +}