From b191a01313d18d2a2dd6f3fe1fe825a39ffc5824 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Tue, 25 Mar 2025 19:22:38 -0300 Subject: [PATCH] Promociones --- ...250318231051_create_promotion_projects.php | 29 +++++++ ...233223_create_promotion_contract_units.php | 31 +++++++ app/resources/routes/ventas/promotions.php | 3 + .../views/ventas/promotions/base.blade.php | 14 +++- .../views/ventas/promotions/show.blade.php | 84 +++++++++++++++++++ .../promotions/show/add_modal.blade.php | 2 + app/setup/setups/logs.php | 14 +++- app/src/Controller/Ventas/Promotions.php | 12 ++- app/src/Model/Venta/Promotion.php | 19 +++++ app/src/Repository/Proyecto.php | 15 ++++ app/src/Repository/Venta/Promotion.php | 27 ++++++ app/src/Service/Venta/Promotion.php | 44 +++++++++- 12 files changed, 286 insertions(+), 8 deletions(-) create mode 100644 app/resources/database/migrations/20250318231051_create_promotion_projects.php create mode 100644 app/resources/database/migrations/20250318233223_create_promotion_contract_units.php create mode 100644 app/resources/views/ventas/promotions/show.blade.php create mode 100644 app/resources/views/ventas/promotions/show/add_modal.blade.php diff --git a/app/resources/database/migrations/20250318231051_create_promotion_projects.php b/app/resources/database/migrations/20250318231051_create_promotion_projects.php new file mode 100644 index 0000000..0381c5f --- /dev/null +++ b/app/resources/database/migrations/20250318231051_create_promotion_projects.php @@ -0,0 +1,29 @@ +table('promotion_tables') + ->addColumn('promotion_id', 'integer', ['signed' => false, 'null' => false]) + ->addColumn('project_id', 'integer', ['signed' => false, 'null' => false]) + ->addForeignKey('promotion_id', 'promotions', 'id', ['delete' => 'cascade', 'update' => 'cascade']) + ->addForeignKey('project_id', 'proyecto', 'id', ['delete' => 'cascade', 'update' => 'cascade']) + ->create(); + } +} diff --git a/app/resources/database/migrations/20250318233223_create_promotion_contract_units.php b/app/resources/database/migrations/20250318233223_create_promotion_contract_units.php new file mode 100644 index 0000000..a6c52c0 --- /dev/null +++ b/app/resources/database/migrations/20250318233223_create_promotion_contract_units.php @@ -0,0 +1,31 @@ +table('promotion_contract_units') + ->addColumn('promotion_id', 'integer', ['signed' => false, 'null' => false]) + ->addColumn('contract_id', 'integer', ['signed' => false, 'null' => false]) + ->addColumn('unit_id', 'integer', ['signed' => false, 'null' => false]) + ->addForeignKey('promotion_id', 'promotions', 'id', ['delete' => 'cascade', 'update' => 'cascade']) + ->addForeignKey('contract_id', 'broker_contracts', 'id', ['delete' => 'cascade', 'update' => 'cascade']) + ->addForeignKey('unit_id', 'unidad', 'id', ['delete' => 'cascade', 'update' => 'cascade']) + ->create(); + } +} diff --git a/app/resources/routes/ventas/promotions.php b/app/resources/routes/ventas/promotions.php index 43ddf79..bad3850 100644 --- a/app/resources/routes/ventas/promotions.php +++ b/app/resources/routes/ventas/promotions.php @@ -4,3 +4,6 @@ use Incoviba\Controller\Ventas\Promotions; $app->group('/promotions', function($app) { $app->get('[/]', Promotions::class); }); +$app->group('/promotion/{promotion_id}', function($app) { + $app->get('[/]', [Promotions::class, 'show']); +}); diff --git a/app/resources/views/ventas/promotions/base.blade.php b/app/resources/views/ventas/promotions/base.blade.php index 0382e20..5901b96 100644 --- a/app/resources/views/ventas/promotions/base.blade.php +++ b/app/resources/views/ventas/promotions/base.blade.php @@ -1,9 +1,21 @@ @extends('layout.base') +@section('page_title') + @hasSection('promotions_title') + Promoción - @yield('promotions_title') + @else + Promociones + @endif +@endsection + @section('page_content')

- Promociones + @hasSection('promotions_header') + Promoción - @yield('promotions_header') + @else + Promociones + @endif

@yield('promotions_content')
diff --git a/app/resources/views/ventas/promotions/show.blade.php b/app/resources/views/ventas/promotions/show.blade.php new file mode 100644 index 0000000..0bb81e2 --- /dev/null +++ b/app/resources/views/ventas/promotions/show.blade.php @@ -0,0 +1,84 @@ +@extends('ventas.promotions.base') + +@section('promotions_title') + {{ $promotion->description }} +@endsection + +@section('promotions_header') + {{ $promotion->description }} +@endsection + +@section('promotions_content') +
+
+
+

+ {{ ucwords($promotion->type->name()) }} {{ ($promotion->type === Incoviba\Model\Venta\Promotion\Type::FIXED) ? $format->ufs($promotion->amount) : $format->percent($promotion->amount, 2, true) }} +

+

+ {{ $promotion->startDate->format('d-m-Y') }} -> {!! $promotion->endDate?->format('d-m-Y') ?? '∞' !!} +

+

Válido hasta: {!! $promotion->validUntil?->format('d-m-Y') ?? '∞' !!}

+
+
+
+ + + + + + + + + + + + + + + + @if (count($promotion->projects()) > 0) + @foreach ($promotion->projects() as $project) + + + + + + @endforeach + @endif + @if (count($promotion->contracts()) > 0) + @foreach($promotion->contracts() as $contract) + + + + + + @endforeach + @endif + @if (count($promotion->units()) > 0) + @foreach($promotion->units() as $unit) + + + + + + + @endforeach + @endif + @if (count($promotion->contractUnits()) > 0) + @foreach($promotion->contractUnits() as $contractUnit) + + + + + + + @endforeach + @endif + +
ProyectoOperadorUnidad + +
Tipo
{{ $project->descripcion }}Todos los OperadoresTodas las Unidades
{{ $contract->project->descripcion }}{{ $contract->broker->name }}Todas las Unidades
{{ $unit->project->descripcion }}Todos los Operadores{{ $unit->proyectoTipoUnidad->tipoUnidad->descripcion }}{{ $unit->descripcion }}
{{ $contractUnit->contract->project->descripcion }}{{ $contractUnit->contract->broker->name }}{{ $contractUnit->unidad->proyectoTipoUnidad->tipoUnidad->descripcion }}{{ $contractUnit->unidad->descripcion }}
+@endsection diff --git a/app/resources/views/ventas/promotions/show/add_modal.blade.php b/app/resources/views/ventas/promotions/show/add_modal.blade.php new file mode 100644 index 0000000..86d4bef --- /dev/null +++ b/app/resources/views/ventas/promotions/show/add_modal.blade.php @@ -0,0 +1,2 @@ + diff --git a/app/setup/setups/logs.php b/app/setup/setups/logs.php index 217d91c..d0f7e64 100644 --- a/app/setup/setups/logs.php +++ b/app/setup/setups/logs.php @@ -9,19 +9,25 @@ return [ Psr\Log\LoggerInterface::class => function(ContainerInterface $container) { return new Monolog\Logger('incoviba', [ new Monolog\Handler\FilterHandler( - (new Monolog\Handler\RotatingFileHandler('/logs/error.log', 10)) + ($container->has('ENVIRONMENT') and $container->get('ENVIRONMENT') === 'development') + ? (new Monolog\Handler\StreamHandler('/logs/error.log')) + ->setFormatter($container->get(Monolog\Formatter\LineFormatter::class)) + : (new Monolog\Handler\RotatingFileHandler('/logs/error.log', 10)) ->setFormatter($container->get(Monolog\Formatter\LineFormatter::class)), Monolog\Level::Error, Monolog\Level::Error ), new Monolog\Handler\FilterHandler( - (new Monolog\Handler\RotatingFileHandler('/logs/critical.log', 10)) + ($container->has('ENVIRONMENT') and $container->get('ENVIRONMENT') === 'development') + ? (new Monolog\Handler\StreamHandler('/logs/critical.log')) + ->setFormatter($container->get(Monolog\Formatter\LineFormatter::class)) + : (new Monolog\Handler\RotatingFileHandler('/logs/critical.log', 10)) ->setFormatter($container->get(Monolog\Formatter\LineFormatter::class)), Monolog\Level::Critical ), new Monolog\Handler\FilterHandler( ($container->has('ENVIRONMENT') and $container->get('ENVIRONMENT') === 'development') - ? (new Monolog\Handler\RotatingFileHandler('/logs/debug.log', 10)) + ? (new Monolog\Handler\StreamHandler('/logs/debug.log')) ->setFormatter($container->get(Monolog\Formatter\LineFormatter::class)) : new Monolog\Handler\RedisHandler($container->get(Predis\ClientInterface::class), 'logs:notices'), Monolog\Level::Debug, @@ -29,7 +35,7 @@ return [ ), new Monolog\Handler\FilterHandler( ($container->has('ENVIRONMENT') and $container->get('ENVIRONMENT') === 'development') - ? (new Monolog\Handler\RotatingFileHandler('/logs/notices.log', 10)) + ? (new Monolog\Handler\StreamHandler('/logs/notices.log')) ->setFormatter($container->get(Monolog\Formatter\LineFormatter::class)) : (new Incoviba\Common\Implement\Log\MySQLHandler($container->get(Incoviba\Common\Define\Connection::class))) ->setFormatter(new Incoviba\Common\Implement\Log\PDOFormatter()), diff --git a/app/src/Controller/Ventas/Promotions.php b/app/src/Controller/Ventas/Promotions.php index f3651a1..b458650 100644 --- a/app/src/Controller/Ventas/Promotions.php +++ b/app/src/Controller/Ventas/Promotions.php @@ -10,10 +10,20 @@ use Incoviba\Service; class Promotions extends Ideal\Controller { - public function __invoke(ServerRequestInterface $request, ResponseInterface $response, View $view, Service\Venta\Promotion $promotionService): ResponseInterface + public function __invoke(ServerRequestInterface $request, ResponseInterface $response, View $view, + Service\Venta\Promotion $promotionService): ResponseInterface { $promotions = $promotionService->getAll('description'); return $view->render($response, 'ventas.promotions', ['promotions' => $promotions]); } + public function show(ServerRequestInterface $request, ResponseInterface $response, View $view, + Service\Venta\Promotion $promotionService, int $promotion_id): ResponseInterface + { + $promotion = null; + try { + $promotion = $promotionService->getById($promotion_id); + } catch (ServiceAction\Read) {} + return $view->render($response, 'ventas.promotions.show', ['promotion' => $promotion]); + } } diff --git a/app/src/Model/Venta/Promotion.php b/app/src/Model/Venta/Promotion.php index dc1660e..f987256 100644 --- a/app/src/Model/Venta/Promotion.php +++ b/app/src/Model/Venta/Promotion.php @@ -17,6 +17,15 @@ class Promotion extends Common\Ideal\Model public Type $type; public State $state = State::ACTIVE; + protected array $projects; + public function projects(): array + { + if (empty($this->projects)) { + $this->projects = $this->runFactory('projects'); + } + return $this->projects; + } + protected array $contracts; public function contracts(): array { @@ -35,6 +44,15 @@ class Promotion extends Common\Ideal\Model return $this->units; } + protected array $contractUnits; + public function contractUnits(): array + { + if (empty($this->contractUnits)) { + $this->contractUnits = $this->runFactory('contractUnits'); + } + return $this->contractUnits; + } + public function value(float $price): float { if ($this->type === Type::FIXED) { @@ -53,6 +71,7 @@ class Promotion extends Common\Ideal\Model 'valid_until' => $this->validUntil?->format('Y-m-d'), 'type' => $this->type, 'state' => $this->state, + 'projects' => $this->projects() ?? [], 'contracts' => $this->contracts() ?? [], 'units' => $this->units() ?? [] ]; diff --git a/app/src/Repository/Proyecto.php b/app/src/Repository/Proyecto.php index 561868c..6bf6364 100644 --- a/app/src/Repository/Proyecto.php +++ b/app/src/Repository/Proyecto.php @@ -164,6 +164,21 @@ class Proyecto extends Ideal\Repository ->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 { diff --git a/app/src/Repository/Venta/Promotion.php b/app/src/Repository/Venta/Promotion.php index 8517d08..fdedcbe 100644 --- a/app/src/Repository/Venta/Promotion.php +++ b/app/src/Repository/Venta/Promotion.php @@ -1,6 +1,8 @@ where('pc.contract_id = :contract_id AND pu.unit_id = :unit_id'); return $this->fetchOne($query, ['contract_id' => $contract_id, 'unit_id' => $unit_id]); } + + /** + * @param int $promotion_id + * @return array + * @throws Common\Implement\Exception\EmptyResult + */ + public function fetchContractUnitsByPromotion(int $promotion_id): array + { + $query = $this->connection->getQueryBuilder() + ->select('contracts.id, unidad.id') + ->from("{$this->getTable()} a") + ->joined('INNER JOIN promotion_contract_units pcu ON pcu.promotion_id = a.id') + ->joined('INNER JOIN unidad ON unidad.id = pcu.unit_id') + ->joined('INNER JOIN contracts ON contracts.id = pcu.contract_id') + ->where('a.id = :promotion_id'); + try { + $result = $this->connection->execute($query, ['promotion_id' => $promotion_id])->fetchAll(PDO::FETCH_ASSOC); + if (empty($result)) { + throw new Common\Implement\Exception\EmptyResult($query); + } + return $result; + } catch (PDOException $exception) { + throw new Common\Implement\Exception\EmptyResult($query, $exception); + } + } } diff --git a/app/src/Service/Venta/Promotion.php b/app/src/Service/Venta/Promotion.php index 6e18bfa..efc726c 100644 --- a/app/src/Service/Venta/Promotion.php +++ b/app/src/Service/Venta/Promotion.php @@ -15,6 +15,7 @@ class Promotion extends Ideal\Service { public function __construct(LoggerInterface $logger, protected Repository\Venta\Promotion $promotionRepository, + protected Repository\Proyecto $projectRepository, protected Repository\Proyecto\Broker\Contract $contractRepository, protected Repository\Venta\Unidad $unidadRepository) { @@ -135,11 +136,50 @@ class Promotion extends Ideal\Service protected function process(Model\Venta\Promotion $model): Model\Venta\Promotion { + $model->addFactory('projects', (new Implement\Repository\Factory()) + ->setCallable(function($promotion_id) { + try { + return $this->projectRepository->fetchByPromotion($promotion_id); + } catch (Implement\Exception\EmptyResult) { + return []; + } + }) + ->setArgs(['promotion_id' => $model->id])); $model->addFactory('contracts', (new Implement\Repository\Factory()) - ->setCallable([$this->contractRepository, 'fetchByPromotion']) + ->setCallable(function($promotion_id) { + try { + return $this->contractRepository->fetchByPromotion($promotion_id); + } catch (Implement\Exception\EmptyResult) { + return []; + } + }) ->setArgs(['promotion_id' => $model->id])); $model->addFactory('units', (new Implement\Repository\Factory()) - ->setCallable([$this->unidadRepository, 'fetchByPromotion']) + ->setCallable(function($promotion_id) { + try { + return $this->unidadRepository->fetchByPromotion($promotion_id); + } catch (Implement\Exception\EmptyResult) { + return []; + } + }) + ->setArgs(['promotion_id' => $model->id])); + $model->addFactory('contractUnits', (new Implement\Repository\Factory()) + ->setCallable(function($promotion_id) { + try { + $ids = $this->promotionRepository->fetchContractUnitsByPromotion($promotion_id); + $contractUnits = []; + foreach ($ids as $id) { + try { + $contract = $this->contractRepository->fetchById($id['contract_id']); + $unidad = $this->unidadRepository->fetchById($id['unidad_id']); + $contractUnits[]= (object) ['contract' => $contract, 'unit' => $unidad]; + } catch (Implement\Exception\EmptyResult) {} + } + return $contractUnits; + } catch (Implement\Exception\EmptyResult) { + return []; + } + }) ->setArgs(['promotion_id' => $model->id])); return $model; }