diff --git a/app/common/Ideal/Model.php b/app/common/Ideal/Model.php index eade31b..c68827a 100644 --- a/app/common/Ideal/Model.php +++ b/app/common/Ideal/Model.php @@ -26,7 +26,13 @@ abstract class Model implements Define\Model public function jsonSerialize(): mixed { return [ - 'id' => $this->id + 'id' => $this->id, + ...$this->jsonComplement() ]; } + + protected function jsonComplement(): array + { + return []; + } } diff --git a/app/resources/database/migrations/20250215133405_create_broker.php b/app/resources/database/migrations/20250215133405_create_broker.php new file mode 100644 index 0000000..0d5961d --- /dev/null +++ b/app/resources/database/migrations/20250215133405_create_broker.php @@ -0,0 +1,28 @@ +table('brokers', ['id' => false, 'primary_key' => ['rut']]) + ->addColumn('rut', 'integer', ['identity' => true, 'signed' => false]) + ->addColumn('digit', 'string', ['length' => 1]) + ->addColumn('name', 'string', ['length' => 255]) + ->create(); + } +} diff --git a/app/resources/database/migrations/20250215133411_create_broker_contract.php b/app/resources/database/migrations/20250215133411_create_broker_contract.php new file mode 100644 index 0000000..ad6c681 --- /dev/null +++ b/app/resources/database/migrations/20250215133411_create_broker_contract.php @@ -0,0 +1,36 @@ +execute('SET unique_checks=0; SET foreign_key_checks=0;'); + $this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';"); + $this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';"); + + $this->table('broker_contracts') + ->addColumn('broker_rut', 'integer', ['signed' => false]) + ->addColumn('project_id', 'integer', ['signed' => false]) + ->addColumn('commission', 'decimal', ['precision' => 10, 'scale' => 2]) + ->addForeignKey('broker_rut', 'brokers', 'rut', ['delete' => 'cascade', 'update' => 'cascade']) + ->addForeignKey('project_id', 'proyecto', 'id', ['delete' => 'cascade', 'update' => 'cascade']) + ->create(); + + $this->execute('SET unique_checks=1; SET foreign_key_checks=1;'); + } +} diff --git a/app/resources/database/migrations/20250215133419_create_broker_data.php b/app/resources/database/migrations/20250215133419_create_broker_data.php new file mode 100644 index 0000000..ce6add2 --- /dev/null +++ b/app/resources/database/migrations/20250215133419_create_broker_data.php @@ -0,0 +1,36 @@ +execute('SET unique_checks=0; SET foreign_key_checks=0;'); + $this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';"); + $this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';"); + + $this->table('broker_data') + ->addColumn('broker_rut', 'integer', ['signed' => false]) + ->addColumn('representative_rut', 'integer', ['signed' => false, 'null' => true, 'default' => null]) + ->addColumn('legalName', 'string', ['length' => 255, 'default' => null, 'null' => true]) + ->addForeignKey('broker_rut', 'brokers', ['rut'], ['delete' => 'CASCADE', 'update' => 'CASCADE']) + ->addForeignKey('representative_rut', 'personas', ['rut'], ['delete' => 'CASCADE', 'update' => 'CASCADE']) + ->create(); + + $this->execute('SET unique_checks=1; SET foreign_key_checks=1;'); + } +} diff --git a/app/resources/database/migrations/20250215133429_create_promotion.php b/app/resources/database/migrations/20250215133429_create_promotion.php new file mode 100644 index 0000000..71a4f2f --- /dev/null +++ b/app/resources/database/migrations/20250215133429_create_promotion.php @@ -0,0 +1,38 @@ +execute('SET unique_checks=0; SET foreign_key_checks=0;'); + $this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';"); + $this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';"); + + $this->table('promotions') + ->addColumn('price_id', 'integer', ['signed' => false]) + ->addColumn('amount', 'decimal', ['precision' => 10, 'scale' => 2]) + ->addColumn('start_date', 'date') + ->addColumn('end_date', 'date') + ->addColumn('valid_until', 'date') + ->addColumn('state', 'integer') + ->addForeignKey('price_id', 'prices', 'id', ['delete' => 'cascade', 'update' => 'cascade']) + ->create(); + + $this->execute('SET unique_checks=1; SET foreign_key_checks=1;'); + } +} diff --git a/app/resources/database/migrations/20250215133437_create_reservation.php b/app/resources/database/migrations/20250215133437_create_reservation.php new file mode 100644 index 0000000..b7ece9f --- /dev/null +++ b/app/resources/database/migrations/20250215133437_create_reservation.php @@ -0,0 +1,34 @@ +execute('SET unique_checks=0; SET foreign_key_checks=0;'); + $this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';"); + $this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';"); + + $this->table('reservation') + ->addColumn('buyer_rut', 'integer', ['signed' => false]) + ->addColumn('date', 'date') + ->addForeignKey('buyer_rut', 'personas', 'rut', ['delete' => 'cascade', 'update' => 'cascade']) + ->create(); + + $this->execute('SET unique_checks=1; SET foreign_key_checks=1;'); + } +} diff --git a/app/resources/database/migrations/20250215133451_create_broker_contract_state.php b/app/resources/database/migrations/20250215133451_create_broker_contract_state.php new file mode 100644 index 0000000..9287a27 --- /dev/null +++ b/app/resources/database/migrations/20250215133451_create_broker_contract_state.php @@ -0,0 +1,35 @@ +execute('SET unique_checks=0; SET foreign_key_checks=0;'); + $this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';"); + $this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';"); + + $this->table('broker_contract_states') + ->addColumn('contract_id', 'integer', ['signed' => false]) + ->addColumn('date', 'date') + ->addColumn('type', 'integer') + ->addForeignKey('contract_id', 'broker_contracts', 'id', ['delete' => 'cascade', 'update' => 'cascade']) + ->create(); + + $this->execute('SET unique_checks=1; SET foreign_key_checks=1;'); + } +} diff --git a/app/resources/database/migrations/20250215135457_create_reservation_datas.php b/app/resources/database/migrations/20250215135457_create_reservation_datas.php new file mode 100644 index 0000000..08f877e --- /dev/null +++ b/app/resources/database/migrations/20250215135457_create_reservation_datas.php @@ -0,0 +1,35 @@ +execute('SET unique_checks=0; SET foreign_key_checks=0;'); + $this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';"); + $this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';"); + + $this->table('reservation_data') + ->addColumn('reservation_id', 'integer', ['signed' => false]) + ->addColumn('type', 'integer', ['length' => 1, 'signed' => false]) + ->addColumn('reference_id', 'integer', ['signed' => false]) + ->addColumn('value', 'decimal', ['precision' => 10, 'scale' => 2, 'signed' => false, 'default' => 0.00]) + ->create(); + + $this->execute('SET unique_checks=1; SET foreign_key_checks=1;'); + } +} diff --git a/app/resources/database/migrations/20250215135822_create_reservation_states.php b/app/resources/database/migrations/20250215135822_create_reservation_states.php new file mode 100644 index 0000000..4a7b439 --- /dev/null +++ b/app/resources/database/migrations/20250215135822_create_reservation_states.php @@ -0,0 +1,35 @@ +execute('SET unique_checks=0; SET foreign_key_checks=0;'); + $this->execute("ALTER DATABASE CHARACTER SET 'utf8mb4';"); + $this->execute("ALTER DATABASE COLLATE='utf8mb4_general_ci';"); + + $this->table('reservation_states') + ->addColumn('reservation_id', 'integer', ['signed' => false]) + ->addColumn('date', 'date') + ->addColumn('type', 'integer') + ->addForeignKey('reservation_id', 'reservation', 'id', ['delete' => 'cascade', 'update' => 'cascade']) + ->create(); + + $this->execute('SET unique_checks=1; SET foreign_key_checks=1;'); + } +} diff --git a/app/src/Model/Proyecto/Broker.php b/app/src/Model/Proyecto/Broker.php new file mode 100644 index 0000000..98687b2 --- /dev/null +++ b/app/src/Model/Proyecto/Broker.php @@ -0,0 +1,23 @@ + $this->rut, + 'digit' => $this->digit, + 'name' => $this->name, + 'data' => $this->data + ]; + } +} \ No newline at end of file diff --git a/app/src/Model/Proyecto/Broker/Contract.php b/app/src/Model/Proyecto/Broker/Contract.php new file mode 100644 index 0000000..e064694 --- /dev/null +++ b/app/src/Model/Proyecto/Broker/Contract.php @@ -0,0 +1,41 @@ +states)) { + $this->states = $this->runFactory('states'); + } + return $this->states; + } + + protected Contract\State $current; + public function currentState(): Contract\State + { + if (!isset($this->current)) { + $this->current = last($this->states()); + } + return $this->current; + } + + protected function jsonComplement(): array + { + return [ + 'project_id' => $this->project->id, + 'broker_rut' => $this->broker->rut, + 'commission' => $this->commission, + 'states' => $this->states(), + 'current' => $this->currentState(), + ]; + } +} \ No newline at end of file diff --git a/app/src/Model/Proyecto/Broker/Contract/State.php b/app/src/Model/Proyecto/Broker/Contract/State.php new file mode 100644 index 0000000..f684d60 --- /dev/null +++ b/app/src/Model/Proyecto/Broker/Contract/State.php @@ -0,0 +1,25 @@ + $this->contract->id, + 'date' => $this->date->format('Y-m-d'), + 'type' => [ + 'id' => $this->type, + 'description' => State\Type::name($this->type) + ] + ]; + } +} \ No newline at end of file diff --git a/app/src/Model/Proyecto/Broker/Contract/State/Type.php b/app/src/Model/Proyecto/Broker/Contract/State/Type.php new file mode 100644 index 0000000..78d9db9 --- /dev/null +++ b/app/src/Model/Proyecto/Broker/Contract/State/Type.php @@ -0,0 +1,17 @@ + 'active', + self::INACTIVE => 'inactive', + default => throw new \InvalidArgumentException('Unexpected match value') + }; + } +} \ No newline at end of file diff --git a/app/src/Model/Proyecto/Broker/Data.php b/app/src/Model/Proyecto/Broker/Data.php new file mode 100644 index 0000000..e1de89a --- /dev/null +++ b/app/src/Model/Proyecto/Broker/Data.php @@ -0,0 +1,21 @@ + $this->broker->rut, + 'representative_rut' => $this->representative?->rut, + 'legal_name' => $this->legalName + ]; + } +} \ No newline at end of file diff --git a/app/src/Model/Venta/Promotion.php b/app/src/Model/Venta/Promotion.php new file mode 100644 index 0000000..d7aa8e7 --- /dev/null +++ b/app/src/Model/Venta/Promotion.php @@ -0,0 +1,30 @@ + $this->price->id, + 'amount' => $this->amount, + 'start_date' => $this->startDate->format('Y-m-d'), + 'end_date' => $this->endDate->format('Y-m-d'), + 'valid_until' => $this->validUntil->format('Y-m-d'), + 'state' => [ + 'id' => $this->state, + 'description' => Promotion\State::name($this->state) + ] + ]; + } +} \ No newline at end of file diff --git a/app/src/Model/Venta/Promotion/State.php b/app/src/Model/Venta/Promotion/State.php new file mode 100644 index 0000000..a51e6b8 --- /dev/null +++ b/app/src/Model/Venta/Promotion/State.php @@ -0,0 +1,17 @@ + 'active', + self::INACTIVE => 'inactive', + default => throw new \InvalidArgumentException('Unexpected match value') + }; + } +} \ No newline at end of file diff --git a/app/src/Model/Venta/Reservation.php b/app/src/Model/Venta/Reservation.php new file mode 100644 index 0000000..3a94ebf --- /dev/null +++ b/app/src/Model/Venta/Reservation.php @@ -0,0 +1,83 @@ +states)) { + $this->states = $this->runFactory('states'); + } + return $this->states; + } + + protected Model\Venta\Reservation\State $currentState; + + public function currentState(): Model\Venta\Reservation\State + { + if (!isset($this->currentState)) { + $this->currentState = last($this->states()); + } + return $this->currentState; + } + + public function addUnit(Model\Venta\Unidad $unit, float $value): self + { + if (($i = $this->findUnit($unit->id)) !== null) { + $this->units[$i]['value'] = $value; + return $this; + } + $this->units[] = [ + 'unit' => $unit, + 'value' => $value, + ]; + return $this; + } + + public function removeUnit(int $unit_id): self + { + if (($i = $this->findUnit($unit_id)) === null) { + return $this; + } + unset($this->units[$i]); + $this->units = array_values($this->units); + return $this; + } + + public function findUnit(int $unit_id): ?int + { + foreach ($this->units as $idx => $unit) { + if ($unit['unit']->id == $unit_id) { + return $idx; + } + } + return null; + } + + public function hasUnit(int $unit_id): bool + { + return $this->findUnit($unit_id) !== null; + } + + protected function jsonComplement(): array + { + return [ + 'buyer_rut' => $this->buyer->rut, + 'date' => $this->date->format('Y-m-d'), + 'units' => $this->units, + 'promotions' => $this->promotions, + 'broker_rut' => $this->broker?->rut, + ]; + } +} diff --git a/app/src/Model/Venta/Reservation/State.php b/app/src/Model/Venta/Reservation/State.php new file mode 100644 index 0000000..a24771b --- /dev/null +++ b/app/src/Model/Venta/Reservation/State.php @@ -0,0 +1,25 @@ + $this->reservation->id, + 'date' => $this->date->format('Y-m-d'), + 'type' => [ + 'id' => $this->type, + 'description' => State\Type::name($this->type) + ] + ]; + } +} \ No newline at end of file diff --git a/app/src/Model/Venta/Reservation/State/Type.php b/app/src/Model/Venta/Reservation/State/Type.php new file mode 100644 index 0000000..464ec24 --- /dev/null +++ b/app/src/Model/Venta/Reservation/State/Type.php @@ -0,0 +1,19 @@ + 'active', + self::INACTIVE => 'inactive', + self::REJECTED => 'rejected', + default => throw new \InvalidArgumentException('Unexpected match value') + }; + } +} \ No newline at end of file diff --git a/app/src/Repository/Proyecto/Broker.php b/app/src/Repository/Proyecto/Broker.php new file mode 100644 index 0000000..9bdedc4 --- /dev/null +++ b/app/src/Repository/Proyecto/Broker.php @@ -0,0 +1,43 @@ +parseData(new Model\Proyecto\Broker(), $data, $map); + } + + public function save(Common\Define\Model $model): Model\Proyecto\Broker + { + $this->saveNew( + ['rut', 'digit', 'name'], + [$model->rut, $model->digit, $model->name] + ); + return $model; + } + + public function edit(Common\Define\Model $model, array $new_data): Model\Proyecto\Broker + { + return $this->update($model, ['rut', 'digit', 'name'], $new_data); + } + + public function fetchByName(string $name): ?Model\Proyecto\Broker + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('name = :name'); + return $this->fetchOne($query, ['name' => $name]); + } +} diff --git a/app/src/Repository/Proyecto/Broker/Contract.php b/app/src/Repository/Proyecto/Broker/Contract.php new file mode 100644 index 0000000..d1bb0c9 --- /dev/null +++ b/app/src/Repository/Proyecto/Broker/Contract.php @@ -0,0 +1,93 @@ +register('broker_rut', (new Common\Implement\Repository\Mapper()) + ->setProperty('broker') + ->setFunction(function($data) { + return $this->brokerRepository->fetchById($data['broker_rut']); + }) + ) + ->register('proyecto_id', (new Common\Implement\Repository\Mapper()) + ->setProperty('proyecto') + ->setFunction(function($data) { + return $this->proyectoRepository->fetchById($data['proyecto_id']); + }) + ); + return $this->parseData(new Model\Proyecto\Broker\Contract(), $data, $map); + } + public function save(Common\Define\Model $model): Model\Proyecto\Broker\Contract + { + $model->id = $this->saveNew( + ['broker_rut', 'proyecto_id', 'commission'], + [$model->broker->rut, $model->proyecto->id, $model->commission]); + return $model; + } + public function edit(Common\Define\Model $model, array $new_data): Model\Proyecto\Broker\Contract + { + return $this->update($model, ['broker_rut', 'proyecto_id', 'commission'], $new_data); + } + + public function fetchByBroker(int $brokerRut): array + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('broker_rut = :broker_rut'); + return $this->fetchMany($query, ['broker_rut' => $brokerRut]); + } + public function fetchByProject(int $proyecto_id): array + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('proyecto_id = :proyecto_id'); + return $this->fetchMany($query, ['proyecto_id' => $proyecto_id]); + } + public function fetchActiveByBroker(int $brokerRut): array + { + $query = $this->connection->getQueryBuilder() + ->select('a.*') + ->from("{$this->getTable()} a") + ->joined($this->statusJoin()) + ->where('a.broker_rut = :broker_rut AND bcs.state = :state'); + return $this->fetchMany($query, ['broker_rut' => $brokerRut, 'state' => Model\Proyecto\Broker\Contract\Type::ACTIVE]); + } + public function fetchActiveByProject(int $proyecto_id): array + { + $query = $this->connection->getQueryBuilder() + ->select('a.*') + ->from("{$this->getTable()} a") + ->joined($this->statusJoin()) + ->where('a.proyecto_id = :proyecto_id AND bcs.state = :state'); + return $this->fetchMany($query, ['proyecto_id' => $proyecto_id, 'state' => Model\Proyecto\Broker\Contract\Type::ACTIVE]); + } + public function fetchActiveByProjectAndBroker(int $proyecto_id, int $brokerRut): Model\Proyecto\Broker\Contract + { + $query = $this->connection->getQueryBuilder() + ->select('a.*') + ->from("{$this->getTable()} a") + ->joined($this->statusJoin()) + ->where('a.proyecto_id = :proyecto_id AND a.broker_rut = :broker_rut AND bcs.state = :state'); + return $this->fetchOne($query, ['proyecto_id' => $proyecto_id, 'broker_rut' => $brokerRut, 'state' => Model\Proyecto\Broker\Contract\Type::ACTIVE]); + } + + protected function statusJoin(): string + { + return 'INNER JOIN (SELECT bcs1.* FROM broker_contract_states bcs1 INNER JOIN (SELECT MAX(id) AS id, contract_id FROM broker_contract_states GROUP BY contract_id) bcs0 ON bcs0.id = bcs1.id) bcs ON bcs.contract = a.id'; + } +} \ No newline at end of file diff --git a/app/src/Repository/Proyecto/Broker/Contract/State.php b/app/src/Repository/Proyecto/Broker/Contract/State.php new file mode 100644 index 0000000..4047a4f --- /dev/null +++ b/app/src/Repository/Proyecto/Broker/Contract/State.php @@ -0,0 +1,52 @@ +register('contract_id', (new Common\Implement\Repository\Mapper()) + ->setProperty('contract') + ->setFunction(function($data) { + return $this->contractRepository->fetchById($data['contract_id']); + })) + ->register('date', new Common\Implement\Repository\Mapper\DateTime('date')); + return $this->parseData(new Model\Proyecto\Broker\Contract\State(), $data, $map); + } + public function save(Common\Define\Model $model): Model\Proyecto\Broker\Contract\State + { + $model->id = $this->saveNew(['contract_id', 'date', 'type'], [$model->contract->id, $model->date->format('Y-m-d'), $model->type]); + return $model; + } + public function edit(Common\Define\Model $model, array $new_data): Model\Proyecto\Broker\Contract\State + { + return $this->update($model, ['contract_id', 'date', 'type'], $new_data); + } + + public function fetchByContract(int $contract_id): array + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('contract_id = :contract_id'); + return $this->fetchMany($query, ['contract_id' => $contract_id]); + } + public function fetchActiveByContract(int $contract_id): Model\Proyecto\Broker\Contract\State + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('contract_id = :contract_id AND type = :type'); + return $this->fetchOne($query, ['contract_id' => $contract_id, 'type' => Model\Proyecto\Broker\Contract\State\Type::ACTIVE]); + } +} \ No newline at end of file diff --git a/app/src/Repository/Proyecto/Broker/Data.php b/app/src/Repository/Proyecto/Broker/Data.php new file mode 100644 index 0000000..51d7c02 --- /dev/null +++ b/app/src/Repository/Proyecto/Broker/Data.php @@ -0,0 +1,59 @@ +register('broker_rut', (new Common\Implement\Repository\Mapper()) + ->setProperty('broker') + ->setFunction(function($data) { + return $this->brokerRepository->fetchById($data['broker_rut']); + })) + ->register('representative_rut', (new Common\Implement\Repository\Mapper()) + ->setProperty('representative') + ->setDefault(null) + ->setFunction(function($data) { + try { + return $this->personaRepository->fetchById($data['representative_rut']); + } catch (Common\Implement\Exception\EmptyResult) { + return null; + } + })) + ->register('legalName', (new Common\Implement\Repository\Mapper()) + ->setDefault(null)); + return $this->parseData(new Model\Proyecto\Broker\Data(), $data, $map); + } + public function save(Common\Define\Model $model): Model\Proyecto\Broker\Data + { + $model->id = $this->saveNew( + ['broker_rut', 'representative_rut', 'legal_name'], + [$model->broker->rut, $model->representative?->rut, $model->legalName]); + return $model; + } + public function edit(Common\Define\Model $model, array $new_data): Model\Proyecto\Broker\Data + { + return $this->update($model, ['broker_rut', 'representative_rut', 'legal_name'], $new_data); + } + + public function fetchByBroker(int $brokerRut): Model\Proyecto\Broker\Data + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('broker_rut = :broker_rut'); + return $this->fetchOne($query, ['broker_rut' => $brokerRut]); + } +} \ No newline at end of file diff --git a/app/src/Repository/Venta/Promotion.php b/app/src/Repository/Venta/Promotion.php new file mode 100644 index 0000000..2a74f0d --- /dev/null +++ b/app/src/Repository/Venta/Promotion.php @@ -0,0 +1,57 @@ +register('price_id', (new Implement\Repository\Mapper()) + ->setProperty('price') + ->setFunction(function($data) { + return $this->precioRepository->create($data); + })) + ->register('start_date', new Implement\Repository\Mapper\DateTime('start_date', 'startDate')) + ->register('end_date', new Implement\Repository\Mapper\DateTime('end_date', 'endDate')) + ->register('valid_until', new Implement\Repository\Mapper\DateTime('valid_until', 'validUntil')); + + return $this->parseData(new Model\Venta\Promotion(), $data, $map); + } + public function save(Common\Define\Model $model): Model\Venta\Promotion + { + $model->id = $this->saveNew( + ['amount', 'type', 'start_date', 'end_date', 'valid_until', 'price_id'], + [$model->amount, $model->type, $model->startDate->format('Y-m-d'), $model->endDate->format('Y-m-d'), $model->validUntil->format('Y-m-d'), $model->price->id] + ); + return $model; + } + public function edit(Common\Define\Model $model, array $new_data): Model\Venta\Promotion + { + return $this->update($model, ['amount', 'type', 'start_date', 'end_date', 'valid_until', 'price_id'], $new_data); + } + + public function fetchByPrice(int $price_id): array + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('price_id = :price_id'); + return $this->fetchMany($query, ['price_id' => $price_id]); + } + public function fetchActiveByPrice(int $price_id): array + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('price_id = :price_id AND state = :state'); + return $this->fetchMany($query, ['price_id' => $price_id, 'state' => Model\Venta\Promotion\State::ACTIVE]); + } +} \ No newline at end of file diff --git a/app/src/Repository/Venta/Reservation.php b/app/src/Repository/Venta/Reservation.php new file mode 100644 index 0000000..32067b7 --- /dev/null +++ b/app/src/Repository/Venta/Reservation.php @@ -0,0 +1,202 @@ +register('buyer_rut', (new Common\Implement\Repository\Mapper()) + ->setProperty('buyer') + ->setFunction(function($data) use ($data) { + return $this->personaRepository->fetchById($data['buyer_rut']); + })) + ->register('date', new Common\Implement\Repository\Mapper\DateTime('date')) + ->register('broker_rut', (new Common\Implement\Repository\Mapper()) + ->setProperty('broker') + ->setDefault(null) + ->setFunction(function($data) use ($data) { + try { + return $this->brokerRepository->fetchById($data['broker_rut']); + } catch (Common\Implement\Exception\EmptyResult) { + return null; + } + })); + return $this->parseData(new Model\Venta\Reservation(), $data, $map); + } + public function save(Common\Define\Model $model): Model\Venta\Reservation + { + $model->id = $this->saveNew([ + 'buyer_rut', + 'date', + 'broker_rut' + ], [ + $model->buyer->rut, + $model->date->format('Y-m-d'), + $model->broker?->rut + ]); + $this->saveUnits($model); + $this->savePromotions($model); + return $model; + } + public function edit(Common\Define\Model $model, array $new_data): Model\Venta\Reservation + { + return $this->update($model, ['buyer_rut', 'date', 'broker_rut'], $new_data); + } + + public function load(array $data_row): Model\Venta\Reservation + { + $model = parent::load($data_row); + + $this->fetchUnits($model); + $this->fetchPromotions($model); + return $model; + } + + protected function saveUnits(Model\Venta\Reservation $reservation): void + { + if (empty($reservation->units)) { + return; + } + $queryCheck = $this->connection->getQueryBuilder() + ->select('COUNT(id) AS cnt') + ->from('reservation_data') + ->where('reservation_id = :id AND type = "Unit" AND reference_id = :unit_id'); + $statementCheck = $this->connection->prepare($queryCheck); + $queryInsert = $this->connection->getQueryBuilder() + ->insert() + ->into('reservation_data') + ->columns(['reservation_id', 'type', 'reference_id', 'value']) + ->values([':reservation_id', ':type', ':reference_id', ':value']); + $statementInsert = $this->connection->prepare($queryInsert); + foreach ($reservation->units as $unit) { + $statementCheck->execute(['id' => $reservation->id, 'unit_id' => $unit['unit']->id]); + $result = $statementCheck->fetch(PDO::FETCH_ASSOC); + if ($result['cnt'] > 0) { + continue; + } + $statementInsert->execute(['reservation_id' => $reservation->id, 'type' => 'Unit', 'reference_id' => $unit['unit']->id, 'value' => $unit['value']]); + } + } + protected function savePromotions(Model\Venta\Reservation $reservation): void + { + if (empty($reservation->promotions)) { + return; + } + $queryCheck = $this->connection->getQueryBuilder() + ->select('COUNT(id) AS cnt') + ->from('reservation_data') + ->where('reservation_id = :id AND type = "Promotion" AND reference_id = :promotion_id'); + $statementCheck = $this->connection->prepare($queryCheck); + $queryInsert = $this->connection->getQueryBuilder() + ->insert() + ->into('reservation_data') + ->columns(['reservation_id', 'type', 'reference_id']) + ->values([':reservation_id', ':type', ':reference_id']); + $statementInsert = $this->connection->prepare($queryInsert); + foreach ($reservation->promotions as $promotion) { + $statementCheck->execute(['id' => $reservation->id, 'promotion_id' => $promotion->id]); + $result = $statementCheck->fetch(PDO::FETCH_ASSOC); + if ($result['cnt'] > 0) { + continue; + } + $statementInsert->execute(['reservation_id' => $reservation->id, 'type' => 'Promotion', 'reference_id' => $promotion->id]); + } + } + protected function editUnits(Model\Venta\Reservation $reservation, array $new_data): void + { + $querySelect = $this->connection->getQueryBuilder() + ->select() + ->from('reservation_data') + ->where('reservation_id = :id AND type = "Unit" AND reference_id = :unit_id'); + $statementSelect = $this->connection->prepare($querySelect); + $queryUpdate = $this->connection->getQueryBuilder() + ->update('reservation_data') + ->set('value = :value') + ->where('reservation_id = :id AND type = "Unit" AND reference_id = :unit_id'); + $statementUpdate = $this->connection->prepare($queryUpdate); + foreach ($new_data as $unit_id => $value) { + $idx = $reservation->findUnit($unit_id); + if ($idx === null) { + $reservation->addUnit($this->unitRepository->fetchById($unit_id), $value); + continue; + } + $statementSelect->execute(['id' => $reservation->id, 'unit_id' => $unit_id]); + $result = $statementSelect->fetch(PDO::FETCH_ASSOC); + if (!$result) { + continue; + } + $statementUpdate->execute(['id' => $reservation->id, 'unit_id' => $unit_id, 'value' => $value]); + $reservation->units[$idx]['value'] = $value; + } + } + protected function editPromotions(Model\Venta\Reservation $reservation, array $new_data): void + { + $querySelect = $this->connection->getQueryBuilder() + ->select() + ->from('reservation_data') + ->where('reservation_id = :id AND type = "Promotion" AND reference_id = :promotion_id'); + $statementSelect = $this->connection->prepare($querySelect); + $queryUpdate = $this->connection->getQueryBuilder() + ->update('reservation_data') + ->set('value = :value') + ->where('reservation_id = :id AND type = "Promotion" AND reference_id = :promotion_id'); + $statementUpdate = $this->connection->prepare($queryUpdate); + foreach ($new_data as $promotion_id => $value) { + $idx = array_search($promotion_id, array_column($reservation->promotions, 'id')); + if ($idx === false) { + $reservation->promotions []= $this->promotionRepository->fetchById($promotion_id); + continue; + } + $statementSelect->execute(['id' => $reservation->id, 'promotion_id' => $promotion_id]); + $result = $statementSelect->fetch(PDO::FETCH_ASSOC); + if (!$result) { + continue; + } + $statementUpdate->execute(['id' => $reservation->id, 'promotion_id' => $promotion_id, 'value' => $value]); + $reservation->promotions[$idx] = $this->promotionRepository->fetchById($promotion_id); + } + } + protected function fetchUnits(Model\Venta\Reservation &$reservation): Model\Venta\Reservation + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from('reservation_data') + ->where('reservation_id = :id AND type = "Unit"'); + $statement = $this->connection->execute($query, ['id' => $reservation->id]); + + while ($result = $statement->fetch(PDO::FETCH_ASSOC)) { + try { + $reservation->addUnit($this->unitRepository->fetchById($result['reference_id']), $result['value']); + } catch (Common\Implement\Exception\EmptyResult) {} + } + return $reservation; + } + protected function fetchPromotions(Model\Venta\Reservation $reservation): Model\Venta\Reservation + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from('reservation_data') + ->where('type = "Promotion" AND reservation_id = :id'); + $statement = $this->connection->execute($query, ['id' => $reservation->id]); + while ($result = $statement->fetch(PDO::FETCH_ASSOC)) { + try { + $reservation->promotions []= $this->promotionRepository->fetchById($result['reference_id']); + } catch (Common\Implement\Exception\EmptyResult) {} + } + return $reservation; + } +} \ No newline at end of file