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; } }