diff --git a/app/common/Implement/Database/Query/Insert.php b/app/common/Implement/Database/Query/Insert.php index 6c9b7cf..f8fe6a7 100644 --- a/app/common/Implement/Database/Query/Insert.php +++ b/app/common/Implement/Database/Query/Insert.php @@ -81,6 +81,9 @@ class Insert extends Ideal\Query implements Define\Query\Insert if ($value === (int) $value) { return $value; } + if (str_starts_with($value, ':')) { + return $value; + } return "'{$value}'"; }, $this->values)) . ')'; } diff --git a/app/resources/routes/api/ventas/promotions.php b/app/resources/routes/api/ventas/promotions.php index f69303f..14fdb1e 100644 --- a/app/resources/routes/api/ventas/promotions.php +++ b/app/resources/routes/api/ventas/promotions.php @@ -7,4 +7,22 @@ $app->group('/promotions', function($app) { }); $app->group('/promotion/{promotion_id}', function($app) { $app->delete('/remove[/]', [Promotions::class, 'remove']); + $app->group('/connections', function($app) { + $app->post('/add[/]', [Promotions::class, 'addConnections']); + $app->group('/project/{project_id}', function($app) { + $app->delete('[/]', [Promotions::class, 'removeProject']); + }); + $app->group('/contract/{contract_id}', function($app) { + $app->delete('[/]', [Promotions::class, 'removeContract']); + }); + $app->group('/unit-type/{unit_type_id}', function($app) { + $app->delete('[/]', [Promotions::class, 'removeUnitType']); + }); + $app->group('/unit-line/{unit_line_id}', function($app) { + $app->delete('[/]', [Promotions::class, 'removeUnitLine']); + }); + $app->group('/unit/{unit_id}', function($app) { + $app->delete('[/]', [Promotions::class, 'removeUnit']); + }); + }); }); diff --git a/app/resources/views/ventas/promotions/show.blade.php b/app/resources/views/ventas/promotions/show.blade.php index 0bb81e2..a21ef7d 100644 --- a/app/resources/views/ventas/promotions/show.blade.php +++ b/app/resources/views/ventas/promotions/show.blade.php @@ -18,67 +18,293 @@

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

-

Válido hasta: {!! $promotion->validUntil?->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 }}
+
+ +
+ +
+
+
+
+
+ @include('ventas.promotions.show.add_modal') @endsection + +@push('page_scripts') + +@endpush diff --git a/app/resources/views/ventas/promotions/show/add_modal.blade.php b/app/resources/views/ventas/promotions/show/add_modal.blade.php index 86d4bef..c1b42a6 100644 --- a/app/resources/views/ventas/promotions/show/add_modal.blade.php +++ b/app/resources/views/ventas/promotions/show/add_modal.blade.php @@ -1,2 +1,288 @@ + +@push('page_scripts') + +@endpush diff --git a/app/src/Controller/API/Ventas/Promotions.php b/app/src/Controller/API/Ventas/Promotions.php index c144a63..19491b4 100644 --- a/app/src/Controller/API/Ventas/Promotions.php +++ b/app/src/Controller/API/Ventas/Promotions.php @@ -3,6 +3,7 @@ namespace Incoviba\Controller\API\Ventas; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Log\LoggerInterface; use Incoviba\Controller\API\withJson; use Incoviba\Exception\ServiceAction; use Incoviba\Service; @@ -11,7 +12,8 @@ class Promotions { use withJson; - public function add(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Promotion $promotionService): ResponseInterface + public function add(ServerRequestInterface $request, ResponseInterface $response, + Service\Venta\Promotion $promotionService): ResponseInterface { $input = $request->getParsedBody(); $output = [ @@ -43,7 +45,8 @@ class Promotions return $this->withJson($response, $output); } - public function edit(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Promotion $promotionService): ResponseInterface + public function edit(ServerRequestInterface $request, ResponseInterface $response, + Service\Venta\Promotion $promotionService): ResponseInterface { $input = $request->getParsedBody(); $output = [ @@ -77,7 +80,8 @@ class Promotions return $this->withJson($response, $output); } - public function remove(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Promotion $promotionService, int $promotion_id): ResponseInterface + public function remove(ServerRequestInterface $request, ResponseInterface $response, + Service\Venta\Promotion $promotionService, int $promotion_id): ResponseInterface { $output = [ 'promotion_id' => $promotion_id, @@ -94,4 +98,122 @@ class Promotions return $this->withJson($response, $output); } + public function addConnections(ServerRequestInterface $request, ResponseInterface $response, + LoggerInterface $logger, + Service\Venta\Promotion $promotionService, int $promotion_id): ResponseInterface + { + $input = $request->getParsedBody(); + $output = [ + 'promotion_id' => $promotion_id, + 'input' => $input, + 'connections' => [], + 'success' => false, + 'partial' => false + ]; + $total = 0; + if (count($input['project']) > 0 and $input['project'][0] !== '') { + $project_ids = array_filter($input['project'], function($project_id) { return $project_id !== ''; }); + $total += count($project_ids); + foreach ($project_ids as $project_id) { + try { + $promotionService->addProject($promotion_id, $project_id); + $output['connections'] []= [ + 'project_id' => $project_id, + 'success' => true, + ]; + $output['partial'] = true; + } catch (ServiceAction\Create $exception) { + $logger->error($exception); + } + } + } + if (count($input['operator']) > 0 and $input['operator'][0] !== '') { + $contract_ids = array_filter($input['operator'], function($operator_id) { return $operator_id !== ''; }); + $total += count($contract_ids); + foreach ($contract_ids as $contract_id) { + try { + $promotionService->addContract($promotion_id, $contract_id); + $output['connections'] []= [ + 'operator_id' => $contract_id, + 'success' => true, + ]; + $output['partial'] = true; + } catch (ServiceAction\Create $exception) { + $logger->error($exception); + } + } + } + if (count($input['unit_type']) > 0 and $input['unit_type'][0] !== '') { + $unit_type_ids = array_filter($input['unit_type'], function($unit_type_id) { return $unit_type_id !== ''; }); + $total += count($unit_type_ids); + foreach ($unit_type_ids as $unit_type_id) { + try { + $promotionService->addUnitType($promotion_id, $input['type_project'], $unit_type_id); + $output['connections'] []= [ + 'unit_type_id' => $unit_type_id, + 'success' => true, + ]; + $output['partial'] = true; + } catch (ServiceAction\Create $exception) { + $logger->error($exception); + } + } + } + if (count($input['line']) > 0 and $input['line'][0] !== '') { + $line_ids = array_filter($input['line'], function($line_id) { return $line_id !== ''; }); + $total += count($line_ids); + foreach ($line_ids as $line_id) { + try { + $promotionService->addUnitLine($promotion_id, $line_id); + $output['connections'] []= [ + 'line_id' => $line_id, + 'success' => true, + ]; + $output['partial'] = true; + } catch (ServiceAction\Create $exception) { + $logger->error($exception); + } + } + } + if (count($input['unit']) > 0 and $input['unit'][0] !== '') { + $unit_ids = array_filter($input['unit'], function($unit_id) { return $unit_id !== ''; }); + $total += count($unit_ids); + foreach ($unit_ids as $unit_id) { + try { + $promotionService->addUnit($promotion_id, $unit_id); + $output['connections'] []= [ + 'unit_id' => $unit_id, + 'success' => true, + ]; + $output['partial'] = true; + } catch (ServiceAction\Create $exception) { + $logger->error($exception); + } + } + } + + if (count($output['connections']) === $total) { + $output['success'] = true; + } + + return $this->withJson($response, $output); + } + public function removeProject(ServerRequestInterface $request, ResponseInterface $response, + Service\Venta\Promotion $promotionService, + int $promotion_id, int $project_id): ResponseInterface + { + $output = [ + 'promotion_id' => $promotion_id, + 'project_id' => $project_id, + 'connection' => null, + 'success' => false, + ]; + try { + $output['connection'] = $promotionService->removeProject($promotion_id, $project_id); + $output['success'] = true; + } catch (ServiceAction\Delete $exception) { + return $this->withError($response, $exception); + } + return $this->withJson($response, $output); + } } diff --git a/app/src/Controller/Ventas/Promotions.php b/app/src/Controller/Ventas/Promotions.php index b458650..bcd0021 100644 --- a/app/src/Controller/Ventas/Promotions.php +++ b/app/src/Controller/Ventas/Promotions.php @@ -18,12 +18,18 @@ class Promotions extends Ideal\Controller 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 + Service\Venta\Promotion $promotionService, Service\Proyecto $proyectoService, + Service\Proyecto\Broker $brokerService, Service\Proyecto\Broker\Contract $contractService, + int $promotion_id): ResponseInterface { $promotion = null; try { $promotion = $promotionService->getById($promotion_id); } catch (ServiceAction\Read) {} - return $view->render($response, 'ventas.promotions.show', ['promotion' => $promotion]); + $projects = $proyectoService->getVendibles('descripcion'); + $contracts = $contractService->getAll(); + $brokers = $brokerService->getAll('name'); + return $view->render($response, 'ventas.promotions.show', ['promotion' => $promotion, + 'projects' => $projects, 'contracts' => $contracts, 'brokers' => $brokers]); } } diff --git a/app/src/Exception/AggregateException.php b/app/src/Exception/AggregateException.php new file mode 100644 index 0000000..50738a0 --- /dev/null +++ b/app/src/Exception/AggregateException.php @@ -0,0 +1,22 @@ +previous = $previous; + foreach ($temp_arr as $exception) { + $exception->previous = $current; + $current = $exception; + } + $message = "Aggregate Exception"; + parent::__construct($message, $code, $current); + } +} diff --git a/app/src/Model/Proyecto/ProyectoTipoUnidad.php b/app/src/Model/Proyecto/ProyectoTipoUnidad.php index 8c7a6bf..fb7e983 100644 --- a/app/src/Model/Proyecto/ProyectoTipoUnidad.php +++ b/app/src/Model/Proyecto/ProyectoTipoUnidad.php @@ -43,6 +43,15 @@ class ProyectoTipoUnidad extends Ideal\Model return $this->abreviacion; } + protected array $unidades; + public function unidades(): array + { + if (!isset($this->unidades)) { + $this->unidades = $this->runFactory('unidades'); + } + return $this->unidades; + } + public function jsonSerialize(): mixed { return array_merge(parent::jsonSerialize(), [ diff --git a/app/src/Model/Venta/Promotion.php b/app/src/Model/Venta/Promotion.php index f987256..888ecdb 100644 --- a/app/src/Model/Venta/Promotion.php +++ b/app/src/Model/Venta/Promotion.php @@ -21,7 +21,7 @@ class Promotion extends Common\Ideal\Model public function projects(): array { if (empty($this->projects)) { - $this->projects = $this->runFactory('projects'); + $this->projects = $this->runFactory('projects') ?? []; } return $this->projects; } @@ -30,16 +30,33 @@ class Promotion extends Common\Ideal\Model public function contracts(): array { if (empty($this->contracts)) { - $this->contracts = $this->runFactory('contracts'); + $this->contracts = $this->runFactory('contracts') ?? []; } return $this->contracts; } + protected array $unitTypes; + public function unitTypes(): array + { + if (empty($this->unitTypes)) { + $this->unitTypes = $this->runFactory('unitTypes') ?? []; + } + return $this->unitTypes; + } + protected array $unitLines; + public function unitLines(): array + { + if (empty($this->unitLines)) { + $this->unitLines = $this->runFactory('unitLines') ?? []; + } + return $this->unitLines; + } + protected array $units; public function units(): array { if (empty($this->units)) { - $this->units = $this->runFactory('units'); + $this->units = $this->runFactory('units') ?? []; } return $this->units; } diff --git a/app/src/Repository/Proyecto.php b/app/src/Repository/Proyecto.php index 6bf6364..5349416 100644 --- a/app/src/Repository/Proyecto.php +++ b/app/src/Repository/Proyecto.php @@ -94,7 +94,7 @@ class Proyecto extends Ideal\Repository ->where("a.descripcion LIKE ?"); return $this->fetchOne($query, ["%{$name}%"]); } - public function fetchAllActive(): array + public function fetchAllActive(null|string|array $orderBy = null): array { $etapaProyecto = $this->etapaRepository->fetchByDescripcion('Proyecto'); $etapaTerminado = $this->etapaRepository->fetchByDescripcion('Terminado'); @@ -103,8 +103,12 @@ class Proyecto extends Ideal\Repository ->from("{$this->getTable()} a") ->joined($this->joinTerreno()) ->joined($this->joinEstado()) - ->where("et.orden BETWEEN {$etapaProyecto->orden} AND ({$etapaTerminado->orden} - 1)") - ->order('a.descripcion'); + ->where("et.orden BETWEEN {$etapaProyecto->orden} AND ({$etapaTerminado->orden} - 1)"); + if ($orderBy === null) { + $query = $query->order('a.descripcion'); + } else { + $query = $query->order($orderBy); + } return $this->fetchMany($query); } public function fetchAllEscriturando(): array @@ -175,8 +179,14 @@ class Proyecto extends Ideal\Repository $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'); + ->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu ON ptu.proyecto = a.id') + ->joined('LEFT OUTER JOIN unidad ON unidad.pt = ptu.id') + ->joined('LEFT OUTER JOIN promotion_units pu ON pu.unit_id = unidad.id') + ->joined('LEFT OUTER JOIN broker_contracts bc ON bc.project_id = a.id') + ->joined('LEFT OUTER JOIN promotion_contracts pc ON pc.contract_id = bc.id') + ->where('pu.promotion_id = :promotion_id OR pc.promotion_id = :promotion_id') + ->group('a.id'); + trigger_error($query . ' ' . json_encode(['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/Proyecto/ProyectoTipoUnidad.php b/app/src/Repository/Proyecto/ProyectoTipoUnidad.php index 737f767..d4c13ac 100644 --- a/app/src/Repository/Proyecto/ProyectoTipoUnidad.php +++ b/app/src/Repository/Proyecto/ProyectoTipoUnidad.php @@ -43,4 +43,21 @@ class ProyectoTipoUnidad extends Ideal\Repository { return $this->update($model, ['proyecto', 'tipo', 'nombre', 'abreviacion', 'util', 'logia', 'terraza', 'descripcion'], $new_data); } + + /** + * @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 unidad ON unidad.`pt` = a.`id`') + ->joined('INNER JOIN `promotion_units` pu ON pu.`unit_id` = unidad.`id`') + ->where('pu.`promotion_id` = :promotion_id') + ->group('a.id'); + return $this->fetchMany($query, ['promotion_id' => $promotion_id]); + } } diff --git a/app/src/Repository/Proyecto/TipoUnidad.php b/app/src/Repository/Proyecto/TipoUnidad.php index 8a2788a..ee3b9b3 100644 --- a/app/src/Repository/Proyecto/TipoUnidad.php +++ b/app/src/Repository/Proyecto/TipoUnidad.php @@ -1,6 +1,8 @@ update($model, ['descripcion', 'orden'], $new_data); } + /** + * @param int $proyecto_id + * @return array + * @throws Implement\Exception\EmptyResult + */ public function fetchByProyecto(int $proyecto_id): array { $query = $this->connection->getQueryBuilder() @@ -43,6 +50,31 @@ class TipoUnidad extends Ideal\Repository ->order('a.orden'); return $this->fetchMany($query, [$proyecto_id]); } + + /** + * @param int $promotion_id + * @return array + * @throws Implement\Exception\EmptyResult + */ + public function fetchByPromotion(int $promotion_id): array + { + $query = $this->connection->getQueryBuilder() + ->select('a.id, ptu.proyecto AS project_id') + ->from("{$this->getTable()} a") + ->joined('INNER JOIN proyecto_tipo_unidad ptu ON ptu.`tipo` = a.`id`') + ->joined('INNER JOIN unidad ON unidad.`pt` = ptu.`id`') + ->joined('INNER JOIN `promotion_units` pu ON pu.`unit_id` = unidad.`id`') + ->where('pu.`promotion_id` = :promotion_id') + ->group('a.id'); + try { + $result = $this->connection->execute($query, ['promotion_id' => $promotion_id])->fetchAll(PDO::FETCH_ASSOC); + if (empty($result)) { + throw new Implement\Exception\EmptyResult($query); + } + return $result; + } catch (PDOException $exception) { + throw new Implement\Exception\EmptyResult($query, $exception); + } + return $this->fetchMany($query, ['promotion_id' => $promotion_id]); + } } - - diff --git a/app/src/Repository/Venta/Promotion.php b/app/src/Repository/Venta/Promotion.php index fdedcbe..5413c9b 100644 --- a/app/src/Repository/Venta/Promotion.php +++ b/app/src/Repository/Venta/Promotion.php @@ -204,4 +204,45 @@ class Promotion extends Common\Ideal\Repository throw new Common\Implement\Exception\EmptyResult($query, $exception); } } + + /** + * @param Model\Venta\Promotion $promotion + * @param int $project_id + * @return void + * @throws PDOException + */ + public function insertProjectForPromotion(Model\Venta\Promotion $promotion, int $project_id): void + { + $query = $this->connection->getQueryBuilder() + ->insert() + ->into('promotion_projects') + ->columns(['promotion_id', 'project_id']) + ->values([':promotion_id', ':project_id']); + $this->connection->execute($query, ['promotion_id' => $promotion->id, 'project_id' => $project_id]); + } + + /** + * @param Model\Venta\Promotion $promotion + * @param int $contract_id + * @return void + * @throws PDOException + */ + public function insertContractForPromotion(Model\Venta\Promotion $promotion, int $contract_id): void + { + $query = $this->connection->getQueryBuilder() + ->insert() + ->into('promotion_contracts') + ->columns(['promotion_id', 'contract_id']) + ->values([':promotion_id', ':contract_id']); + $this->connection->execute($query, ['promotion_id' => $promotion->id, 'contract_id' => $contract_id]); + } + public function insertUnitForPromotion(Model\Venta\Promotion $promotion, int $unit_id): void + { + $query = $this->connection->getQueryBuilder() + ->insert() + ->into('promotion_units') + ->columns(['promotion_id', 'unit_id']) + ->values([':promotion_id', ':unit_id']); + $this->connection->execute($query, ['promotion_id' => $promotion->id, 'unit_id' => $unit_id]); + } } diff --git a/app/src/Repository/Venta/Unidad.php b/app/src/Repository/Venta/Unidad.php index 1cf698e..74bf1cb 100644 --- a/app/src/Repository/Venta/Unidad.php +++ b/app/src/Repository/Venta/Unidad.php @@ -200,6 +200,22 @@ class Unidad extends Ideal\Repository return $this->fetchMany($query, ['promotion_id' => $promotion_id]); } + /** + * @param int $proyecto_id + * @param int $tipo_id + * @return array + * @throws Implement\Exception\EmptyResult + */ + public function fetchByProyectoAndTipo(int $proyecto_id, int $tipo_id): array + { + $query = $this->connection->getQueryBuilder() + ->select('a.*') + ->from("{$this->getTable()} a") + ->joined('INNER JOIN proyecto_tipo_unidad ptu ON a.pt = ptu.id') + ->where('ptu.`proyecto` = :proyecto_id AND ptu.`tipo` = :tipo_id'); + return $this->fetchMany($query, ['proyecto_id' => $proyecto_id, 'tipo_id' => $tipo_id]); + } + protected function joinProrrateo(): string { return "LEFT OUTER JOIN unidad_prorrateo up ON up.unidad_id = a.id"; diff --git a/app/src/Service/Proyecto.php b/app/src/Service/Proyecto.php index cfe2f85..c089285 100644 --- a/app/src/Service/Proyecto.php +++ b/app/src/Service/Proyecto.php @@ -11,9 +11,22 @@ class Proyecto protected Repository\Proyecto $proyectoRepository, protected Repository\Proyecto\EstadoProyecto $estadoProyecto ) {} - public function getVendibles(): array + + /** + * @param string|array|null $orderBy + * @return array + */ + public function getAll(null|string|array $orderBy = null): array { - return $this->proyectoRepository->fetchAllActive(); + try { + return array_map([$this, 'process'], $this->proyectoRepository->fetchAll($orderBy)); + } catch (Implement\Exception\EmptyResult) { + return []; + } + } + public function getVendibles(null|string|array $orderBy = null): array + { + return $this->proyectoRepository->fetchAllActive($orderBy); } public function getEscriturando(): array { diff --git a/app/src/Service/Proyecto/Broker.php b/app/src/Service/Proyecto/Broker.php index bc44482..1d7354f 100644 --- a/app/src/Service/Proyecto/Broker.php +++ b/app/src/Service/Proyecto/Broker.php @@ -58,12 +58,13 @@ class Broker extends Ideal\Service } } /** + * @param null|string|array $orderBy * @return array */ - public function getAll(): array + public function getAll(null|string|array $orderBy = null): array { try { - return array_map([$this, 'process'], $this->brokerRepository->fetchAll()); + return array_map([$this, 'process'], $this->brokerRepository->fetchAll($orderBy)); } catch (EmptyResult) { return []; } diff --git a/app/src/Service/Venta/Promotion.php b/app/src/Service/Venta/Promotion.php index efc726c..923c4c8 100644 --- a/app/src/Service/Venta/Promotion.php +++ b/app/src/Service/Venta/Promotion.php @@ -17,6 +17,8 @@ class Promotion extends Ideal\Service protected Repository\Venta\Promotion $promotionRepository, protected Repository\Proyecto $projectRepository, protected Repository\Proyecto\Broker\Contract $contractRepository, + protected Repository\Proyecto\TipoUnidad $tipoUnidadRepository, + protected Repository\Proyecto\ProyectoTipoUnidad $proyectoTipoUnidadRepository, protected Repository\Venta\Unidad $unidadRepository) { parent::__construct($logger); @@ -133,6 +135,205 @@ class Promotion extends Ideal\Service } } + /** + * @param int $promotion_id + * @param int $project_id + * @return Model\Venta\Promotion + * @throws Exception\ServiceAction\Create + */ + public function addProject(int $promotion_id, int $project_id): Model\Venta\Promotion + { + try { + $promotion = $this->promotionRepository->fetchById($promotion_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + try { + $project = $this->projectRepository->fetchById($project_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + if (in_array($project, $promotion->projects())) { + return $this->process($promotion); + } + try { + $this->promotionRepository->insertProjectForPromotion($promotion, $project->id); + return $this->process($promotion); + } catch (PDOException $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + } + + /** + * @param int $promotion_id + * @param int $contract_id + * @return Model\Venta\Promotion + * @throws Exception\ServiceAction\Create + */ + public function addContract(int $promotion_id, int $contract_id): Model\Venta\Promotion + { + try { + $promotion = $this->promotionRepository->fetchById($promotion_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + try { + $contract = $this->contractRepository->fetchById($contract_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + if (in_array($contract, $promotion->contracts())) { + return $this->process($promotion); + } + try { + $this->promotionRepository->insertContractForPromotion($promotion, $contract->id); + return $this->process($promotion); + } catch (PDOException $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + } + + /** + * @param int $promotion_id + * @param int $project_id + * @param int $unitType_id + * @return Model\Venta\Promotion + * @throws Exception\ServiceAction\Create + */ + public function addUnitType(int $promotion_id, int $project_id, int $unitType_id): Model\Venta\Promotion + { + try { + $promotion = $this->promotionRepository->fetchById($promotion_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + try { + $project = $this->projectRepository->fetchById($project_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + try { + $unitType = $this->tipoUnidadRepository->fetchById($unitType_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + if (in_array(['project' => $project, 'unitType' => $unitType], $promotion->unitTypes())) { + return $this->process($promotion); + } + try { + $units = $this->unidadRepository->fetchByProyectoAndTipo($project->id, $unitType->id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + return $this->insertUnits($promotion, $units); + } + + /** + * @param int $promotion_id + * @param int $unit_line_id + * @return Model\Venta\Promotion + * @throws Exception\ServiceAction\Create + */ + public function addUnitLine(int $promotion_id, int $unit_line_id): Model\Venta\Promotion + { + try { + $promotion = $this->promotionRepository->fetchById($promotion_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + try { + $unitLine = $this->proyectoTipoUnidadRepository->fetchById($unit_line_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + if (in_array($unitLine, $promotion->unitLines())) { + return $this->process($promotion); + } + try { + $units = $this->unidadRepository->fetchByProyectoTipoUnidad($unitLine->id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + return $this->insertUnits($promotion, $units); + } + + /** + * @param int $promotion_id + * @param int $unit_id + * @return Model\Venta\Promotion + * @throws Exception\ServiceAction\Create + */ + public function addUnit(int $promotion_id, int $unit_id): Model\Venta\Promotion + { + try { + $promotion = $this->promotionRepository->fetchById($promotion_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + try { + $unit = $this->unidadRepository->fetchById($unit_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + if (in_array($unit, $promotion->units())) { + return $this->process($promotion); + } + try { + $this->promotionRepository->insertUnitForPromotion($promotion, $unit->id); + return $this->process($promotion); + } catch (PDOException $exception) { + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + } + + public function removeProject(int $promotion_id, int $project_id): array + { + try { + $promotion = $this->promotionRepository->fetchById($promotion_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Delete(__CLASS__, $exception); + } + try { + $project = $this->projectRepository->fetchById($project_id); + } catch (Implement\Exception\EmptyResult $exception) { + throw new Exception\ServiceAction\Delete(__CLASS__, $exception); + } + try { + $this->promotionRepository->removeProjectForPromotion($promotion, $project->id); + return [ + 'id' => '', + 'promotion_id' => $promotion_id, + 'project_id' => $project_id, + + ]; + } catch (PDOException $exception) { + throw new Exception\ServiceAction\Delete(__CLASS__, $exception); + } + } + + /** + * @param Model\Venta\Promotion $promotion + * @param array $units + * @return Model\Venta\Promotion + * @throws Exception\ServiceAction\Create + */ + protected function insertUnits(Model\Venta\Promotion $promotion, array $units): Model\Venta\Promotion + { + $errors = []; + foreach ($units as $unit) { + try { + $this->promotionRepository->insertUnitForPromotion($promotion, $unit->id); + } catch (PDOException | \Throwable $exception) { + $this->logger->debug($exception); + $errors []= $exception; + } + } + if (count($errors) > 0) { + $exception = new Exception\AggregateException($errors); + throw new Exception\ServiceAction\Create(__CLASS__, $exception); + } + return $this->process($promotion); + } protected function process(Model\Venta\Promotion $model): Model\Venta\Promotion { @@ -154,6 +355,31 @@ class Promotion extends Ideal\Service } }) ->setArgs(['promotion_id' => $model->id])); + $model->addFactory('unitTypes', (new Implement\Repository\Factory()) + ->setCallable(function($promotion_id) { + try { + return array_map(function(array $ids) { + return [ + 'project' => $this->projectRepository->fetchById($ids['project_id']), + 'unitType' => $this->tipoUnidadRepository->fetchById($ids['id']) + ]; + }, $this->tipoUnidadRepository->fetchByPromotion($promotion_id)); + } catch (Implement\Exception\EmptyResult) { + return []; + } + }) + ->setArgs(['promotion_id' => $model->id]) + ); + $model->addFactory('unitLines', (new Implement\Repository\Factory()) + ->setCallable(function($promotion_id) { + try { + return $this->proyectoTipoUnidadRepository->fetchByPromotion($promotion_id); + } catch (Implement\Exception\EmptyResult) { + return []; + } + }) + ->setArgs(['promotion_id' => $model->id]) + ); $model->addFactory('units', (new Implement\Repository\Factory()) ->setCallable(function($promotion_id) { try {