Cambios a modelo Reservation
This commit is contained in:
@ -1,7 +1,10 @@
|
||||
<?php
|
||||
namespace Incoviba\Model\Proyecto;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use Incoviba\Common;
|
||||
use Incoviba\Model\Proyecto;
|
||||
|
||||
class Broker extends Common\Ideal\Model
|
||||
{
|
||||
@ -26,6 +29,36 @@ class Broker extends Common\Ideal\Model
|
||||
}
|
||||
return $this->contracts;
|
||||
}
|
||||
public function getContract(Proyecto $proyecto, ?DateTimeInterface $date = null): ?Proyecto\Broker\Contract
|
||||
{
|
||||
if ($date === null) {
|
||||
$date = new DateTimeImmutable();
|
||||
}
|
||||
$contracts = $this->contracts();
|
||||
$valid = array_filter($contracts, fn(Proyecto\Broker\Contract $contract) => $contract->project->id === $proyecto->id);
|
||||
$valid = array_filter($valid, fn(Proyecto\Broker\Contract $contract) => $contract->wasActive($date));
|
||||
if (count($valid) === 0) {
|
||||
return null;
|
||||
}
|
||||
return last($valid);
|
||||
}
|
||||
|
||||
public function applyCommission(Proyecto $proyecto, float $price, ?DateTimeInterface $date = null): float
|
||||
{
|
||||
$contract = $this->getContract($proyecto, $date);
|
||||
if ($contract === null) {
|
||||
return $price;
|
||||
}
|
||||
return $contract->activate()->apply($proyecto, $price);
|
||||
}
|
||||
public function reverseCommission(Proyecto $proyecto, float $price, ?DateTimeInterface $date = null): float
|
||||
{
|
||||
$contract = $this->getContract($proyecto, $date);
|
||||
if ($contract === null) {
|
||||
return $price;
|
||||
}
|
||||
return $contract->activate()->reverse($proyecto, $price);
|
||||
}
|
||||
|
||||
public function rutFull(): string
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Incoviba\Model\Proyecto\Broker;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Incoviba\Common;
|
||||
use Incoviba\Model;
|
||||
|
||||
@ -41,6 +42,51 @@ class Contract extends Common\Ideal\Model
|
||||
return $this->promotions;
|
||||
}
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
$state = $this->current();
|
||||
return $state !== null and $state->isActive();
|
||||
}
|
||||
public function activate(): self
|
||||
{
|
||||
$this->current()->activate();
|
||||
return $this;
|
||||
}
|
||||
public function wasActive(DateTimeInterface $date): bool
|
||||
{
|
||||
$states = $this->states();
|
||||
return array_any($states, fn($state) => $state->date <= $date);
|
||||
}
|
||||
|
||||
public function value(float $price): float
|
||||
{
|
||||
if (!$this->isActive()) {
|
||||
return $price;
|
||||
}
|
||||
return $price * (1 + $this->commission);
|
||||
}
|
||||
public function inverse(float $price): float
|
||||
{
|
||||
if (!$this->isActive()) {
|
||||
return $price;
|
||||
}
|
||||
return $price / (1 + $this->commission);
|
||||
}
|
||||
public function apply(Model\Proyecto $project, float $price): float
|
||||
{
|
||||
if (!$this->isActive() or $this->project->id !== $project->id) {
|
||||
return $price;
|
||||
}
|
||||
return $this->value($price);
|
||||
}
|
||||
public function reverse(Model\Proyecto $project, float $price): float
|
||||
{
|
||||
if (!$this->isActive() or $this->project->id !== $project->id) {
|
||||
return $price;
|
||||
}
|
||||
return $this->inverse($price);
|
||||
}
|
||||
|
||||
protected function jsonComplement(): array
|
||||
{
|
||||
return [
|
||||
|
@ -11,6 +11,16 @@ class State extends Common\Ideal\Model
|
||||
public DateTimeInterface $date;
|
||||
public State\Type $type;
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->type === State\Type::ACTIVE;
|
||||
}
|
||||
public function activate(): self
|
||||
{
|
||||
$this->type = State\Type::ACTIVE;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function jsonComplement(): array
|
||||
{
|
||||
return [
|
||||
|
@ -3,6 +3,7 @@ namespace Incoviba\Model\Venta;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Incoviba\Common;
|
||||
use Incoviba\Model\Proyecto;
|
||||
use Incoviba\Model\Proyecto\Broker;
|
||||
use Incoviba\Model\Venta\Promotion\State;
|
||||
use Incoviba\Model\Venta\Promotion\Type;
|
||||
@ -61,13 +62,95 @@ class Promotion extends Common\Ideal\Model
|
||||
return $this->units;
|
||||
}
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->state === State::ACTIVE;
|
||||
}
|
||||
public function activate(): self
|
||||
{
|
||||
$this->state = State::ACTIVE;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function value(float $price): float
|
||||
{
|
||||
if (!$this->isActive()) {
|
||||
return $price;
|
||||
}
|
||||
if ($this->type === Type::FIXED) {
|
||||
return $price + $this->amount;
|
||||
}
|
||||
return $price / (1 - $this->amount);
|
||||
}
|
||||
public function inverse(float $price): float
|
||||
{
|
||||
if (!$this->isActive()) {
|
||||
return $price;
|
||||
}
|
||||
if ($this->type === Type::FIXED) {
|
||||
return $price - $this->amount;
|
||||
}
|
||||
return $price * (1 - $this->amount);
|
||||
}
|
||||
|
||||
public function apply(Unidad $unit, float $price, ?Broker $broker = null): float
|
||||
{
|
||||
if (!$this->isActive()) {
|
||||
return $price;
|
||||
}
|
||||
$projectIds = array_map(fn(Proyecto $proyecto) => $proyecto->id, $this->projects());
|
||||
if (in_array($unit->proyectoTipoUnidad->proyecto->id, $projectIds)) {
|
||||
return $this->value($price);
|
||||
}
|
||||
if ($broker !== null) {
|
||||
$brokerIds = array_map(fn(Broker $broker) => $broker->id, $this->brokers());
|
||||
if (in_array($broker->id, $brokerIds)) {
|
||||
return $this->value($price);
|
||||
}
|
||||
}
|
||||
$typeIds = array_map(fn(Proyecto\TipoUnidad $type) => $type->id, $this->unitTypes());
|
||||
if (in_array($unit->proyectoTipoUnidad->tipoUnidad->id, $typeIds)) {
|
||||
return $this->value($price);
|
||||
}
|
||||
$lineIds = array_map(fn(Proyecto\ProyectoTipoUnidad $line) => $line->id, $this->unitLines());
|
||||
if (in_array($unit->proyectoTipoUnidad->id, $lineIds)) {
|
||||
return $this->value($price);
|
||||
}
|
||||
$unitIds = array_map(fn(Unidad $unit) => $unit->id, $this->units());
|
||||
if (in_array($unit->id, $unitIds)) {
|
||||
return $this->value($price);
|
||||
}
|
||||
return $price;
|
||||
}
|
||||
public function reverse(Unidad $unit, float $price, ?Broker $broker = null): float
|
||||
{
|
||||
if (!$this->isActive()) {
|
||||
return $price;
|
||||
}
|
||||
$projectIds = array_map(fn(Proyecto $proyecto) => $proyecto->id, $this->projects());
|
||||
if (in_array($unit->proyectoTipoUnidad->proyecto->id, $projectIds)) {
|
||||
return $this->inverse($price);
|
||||
}
|
||||
if ($broker !== null) {
|
||||
$brokerIds = array_map(fn(Broker $broker) => $broker->id, $this->brokers());
|
||||
if (in_array($broker->id, $brokerIds)) {
|
||||
return $this->inverse($price);
|
||||
}
|
||||
}
|
||||
$typeIds = array_map(fn(Proyecto\TipoUnidad $type) => $type->id, $this->unitTypes());
|
||||
if (in_array($unit->proyectoTipoUnidad->tipoUnidad->id, $typeIds)) {
|
||||
return $this->inverse($price);
|
||||
}
|
||||
$lineIds = array_map(fn(Proyecto\ProyectoTipoUnidad $line) => $line->id, $this->unitLines());
|
||||
if (in_array($unit->proyectoTipoUnidad->id, $lineIds)) {
|
||||
return $this->inverse($price);
|
||||
}
|
||||
$unitIds = array_map(fn(Unidad $unit) => $unit->id, $this->units());
|
||||
if (in_array($unit->id, $unitIds)) {
|
||||
return $this->inverse($price);
|
||||
}
|
||||
return $price;
|
||||
}
|
||||
|
||||
protected function jsonComplement(): array
|
||||
{
|
||||
|
@ -7,11 +7,44 @@ use Incoviba\Model;
|
||||
|
||||
class Reservation extends Common\Ideal\Model
|
||||
{
|
||||
public Model\Proyecto $project;
|
||||
public Model\Persona $buyer;
|
||||
public DateTimeInterface $date;
|
||||
public array $units = [];
|
||||
public array $promotions = [];
|
||||
public ?Model\Proyecto\Broker $broker = null;
|
||||
|
||||
public function offer(): float
|
||||
{
|
||||
return array_sum(array_column($this->units, 'value'));
|
||||
}
|
||||
public function withCommission(): float
|
||||
{
|
||||
$base = 0;
|
||||
foreach ($this->units as $unit) {
|
||||
foreach ($this->promotions as $promotion) {
|
||||
$base += $promotion->activate()->reverse($unit['unit'], $unit['value'], $this->broker);
|
||||
}
|
||||
}
|
||||
return $base;
|
||||
}
|
||||
public function base(): float
|
||||
{
|
||||
$base = $this->withCommission();
|
||||
if ($this->broker !== null) {
|
||||
$base = $this->broker->reverseCommission($this->project, $base, $this->date);
|
||||
}
|
||||
return $base;
|
||||
}
|
||||
public function price(): float
|
||||
{
|
||||
$price = 0;
|
||||
foreach ($this->units as $unit) {
|
||||
$price += $unit->unit->precio($this->date);
|
||||
}
|
||||
return $price;
|
||||
}
|
||||
|
||||
protected array $states = [];
|
||||
|
||||
public function states(): array
|
||||
@ -38,13 +71,12 @@ class Reservation extends Common\Ideal\Model
|
||||
$this->units[$i]['value'] = $value;
|
||||
return $this;
|
||||
}
|
||||
$this->units[] = [
|
||||
$this->units[] = (object) [
|
||||
'unit' => $unit,
|
||||
'value' => $value,
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeUnit(int $unit_id): self
|
||||
{
|
||||
if (($i = $this->findUnit($unit_id)) === null) {
|
||||
@ -54,7 +86,6 @@ class Reservation extends Common\Ideal\Model
|
||||
$this->units = array_values($this->units);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function findUnit(int $unit_id): ?int
|
||||
{
|
||||
foreach ($this->units as $idx => $unit) {
|
||||
@ -64,20 +95,43 @@ class Reservation extends Common\Ideal\Model
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function hasUnit(int $unit_id): bool
|
||||
{
|
||||
return $this->findUnit($unit_id) !== null;
|
||||
}
|
||||
|
||||
public function summary(): string
|
||||
{
|
||||
$unitSummary = array_map(function($unit) {
|
||||
$type = $unit->unit->proyectoTipoUnidad->tipoUnidad->descripcion;
|
||||
$cap = strtoupper(strstr($type, 0, 1));
|
||||
return "{$cap}{$unit->unit->descripcion}";
|
||||
}, $this->units);
|
||||
return implode('', $unitSummary);
|
||||
}
|
||||
|
||||
public function valid(): bool
|
||||
{
|
||||
$base = $this->base();
|
||||
$price = $this->price();
|
||||
return $base >= $price;
|
||||
}
|
||||
|
||||
protected function jsonComplement(): array
|
||||
{
|
||||
return [
|
||||
'buyer_rut' => $this->buyer->rut,
|
||||
'project_id' => $this->project->id,
|
||||
'buyer' => $this->buyer,
|
||||
'date' => $this->date->format('Y-m-d'),
|
||||
'units' => $this->units,
|
||||
'promotions' => $this->promotions,
|
||||
'broker_rut' => $this->broker?->rut,
|
||||
'broker' => $this->broker,
|
||||
'offer' => $this->offer(),
|
||||
'with_commission' => $this->withCommission(),
|
||||
'base' => $this->base(),
|
||||
'price' => $this->price(),
|
||||
'valid' => $this->valid(),
|
||||
'summary' => $this->summary()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
17
app/src/Model/Venta/Reservation/Detail/Type.php
Normal file
17
app/src/Model/Venta/Reservation/Detail/Type.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace Incoviba\Model\Venta\Reservation\Detail;
|
||||
|
||||
enum Type: int
|
||||
{
|
||||
case Unit = 1;
|
||||
case Promotion = 2;
|
||||
case Broker = 3;
|
||||
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->value,
|
||||
'description' => $this->name
|
||||
];
|
||||
}
|
||||
}
|
@ -9,17 +9,14 @@ class State extends Common\Ideal\Model
|
||||
{
|
||||
public Model\Venta\Reservation $reservation;
|
||||
public DateTimeInterface $date;
|
||||
public int $type;
|
||||
public Model\Venta\Reservation\State\Type $type;
|
||||
|
||||
protected function jsonComplement(): array
|
||||
{
|
||||
return [
|
||||
'reservation_id' => $this->reservation->id,
|
||||
'date' => $this->date->format('Y-m-d'),
|
||||
'type' => [
|
||||
'id' => $this->type,
|
||||
'description' => State\Type::name($this->type)
|
||||
]
|
||||
'type' => $this->type
|
||||
];
|
||||
}
|
||||
}
|
@ -7,13 +7,11 @@ enum Type: int
|
||||
case INACTIVE = 0;
|
||||
case REJECTED = -1;
|
||||
|
||||
public static function name(int $type): string
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return match ($type) {
|
||||
self::ACTIVE => 'active',
|
||||
self::INACTIVE => 'inactive',
|
||||
self::REJECTED => 'rejected',
|
||||
default => throw new \InvalidArgumentException('Unexpected match value')
|
||||
};
|
||||
return [
|
||||
'id' => $this->value,
|
||||
'description' => $this->name
|
||||
];
|
||||
}
|
||||
}
|
@ -3,14 +3,18 @@ namespace Incoviba\Repository\Venta;
|
||||
|
||||
use DateTimeInterface;
|
||||
use DateInterval;
|
||||
use Incoviba\Common\Define;
|
||||
use PDO;
|
||||
use Incoviba\Common;
|
||||
use Incoviba\Model;
|
||||
use Incoviba\Repository;
|
||||
use PDOException;
|
||||
|
||||
class Reservation extends Common\Ideal\Repository
|
||||
{
|
||||
public function __construct(Common\Define\Connection $connection, protected Repository\Persona $personaRepository,
|
||||
public function __construct(Common\Define\Connection $connection,
|
||||
protected Repository\Proyecto $proyectoRepository,
|
||||
protected Repository\Persona $personaRepository,
|
||||
protected Repository\Proyecto\Broker $brokerRepository,
|
||||
protected Unidad $unitRepository, protected Promotion $promotionRepository)
|
||||
{
|
||||
@ -25,37 +29,33 @@ class Reservation extends Common\Ideal\Repository
|
||||
public function create(?array $data = null): Model\Venta\Reservation
|
||||
{
|
||||
$map = (new Common\Implement\Repository\MapperParser())
|
||||
->register('project_id', (new Common\Implement\Repository\Mapper())
|
||||
->setProperty('project')
|
||||
->setFunction(function($data) use ($data) {
|
||||
return $this->proyectoRepository->fetchById($data['project_id']);
|
||||
}))
|
||||
->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;
|
||||
}
|
||||
}));
|
||||
->register('date', new Common\Implement\Repository\Mapper\DateTime('date'));
|
||||
return $this->parseData(new Model\Venta\Reservation(), $data, $map);
|
||||
}
|
||||
public function save(Common\Define\Model $model): Model\Venta\Reservation
|
||||
{
|
||||
$model->id = $this->saveNew([
|
||||
'project_id',
|
||||
'buyer_rut',
|
||||
'date',
|
||||
'broker_rut'
|
||||
'date'
|
||||
], [
|
||||
$model->project->id,
|
||||
$model->buyer->rut,
|
||||
$model->date->format('Y-m-d'),
|
||||
$model->broker?->rut
|
||||
$model->date->format('Y-m-d')
|
||||
]);
|
||||
$this->saveUnits($model);
|
||||
$this->savePromotions($model);
|
||||
$this->saveBroker($model);
|
||||
return $model;
|
||||
}
|
||||
|
||||
@ -67,15 +67,20 @@ class Reservation extends Common\Ideal\Repository
|
||||
*/
|
||||
public function edit(Common\Define\Model $model, array $new_data): Model\Venta\Reservation
|
||||
{
|
||||
return $this->update($model, ['buyer_rut', 'date', 'broker_rut'], $new_data);
|
||||
$model = $this->update($model, ['project_id', 'buyer_rut', 'date'], $new_data);
|
||||
$this->editUnits($model, $new_data);
|
||||
$this->editPromotions($model, $new_data);
|
||||
$this->editBroker($model, $new_data);
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function load(array $data_row): Model\Venta\Reservation
|
||||
{
|
||||
$model = parent::load($data_row);
|
||||
|
||||
$this->fetchUnits($model);
|
||||
$this->fetchPromotions($model);
|
||||
$this->fetchUnits($model, $data_row);
|
||||
$this->fetchBroker($model, $data_row);
|
||||
$this->fetchPromotions($model, $data_row);
|
||||
return $model;
|
||||
}
|
||||
|
||||
@ -101,22 +106,71 @@ class Reservation extends Common\Ideal\Repository
|
||||
}
|
||||
$queryCheck = $this->connection->getQueryBuilder()
|
||||
->select('COUNT(id) AS cnt')
|
||||
->from('reservation_data')
|
||||
->where('reservation_id = :id AND type = "Unit" AND reference_id = :unit_id');
|
||||
->from('reservation_details')
|
||||
->where('reservation_id = :id AND type = :type AND reference_id = :unit_id');
|
||||
$statementCheck = $this->connection->prepare($queryCheck);
|
||||
$queryInsert = $this->connection->getQueryBuilder()
|
||||
->insert()
|
||||
->into('reservation_data')
|
||||
->into('reservation_details')
|
||||
->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]);
|
||||
$statementCheck->execute([
|
||||
'id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Unit->value,
|
||||
'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']]);
|
||||
$statementInsert->execute([
|
||||
'reservation_id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Unit->value,
|
||||
'reference_id' => $unit->unit->id,
|
||||
'value' => $unit->value
|
||||
]);
|
||||
}
|
||||
|
||||
$this->cleanUpUnits($reservation);
|
||||
}
|
||||
protected function cleanUpUnits(Model\Venta\Reservation $reservation): void
|
||||
{
|
||||
$this->cleanUpDetails($reservation,
|
||||
Model\Venta\Reservation\Detail\Type::Unit->value,
|
||||
array_map(fn($unit) => $unit->unit->id, $reservation->units));
|
||||
}
|
||||
protected function saveBroker(Model\Venta\Reservation &$reservation): void
|
||||
{
|
||||
if ($reservation->broker === null) {
|
||||
$this->removeBroker($reservation);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$queryCheck = $this->connection->getQueryBuilder()
|
||||
->select('id')
|
||||
->from('reservation_details')
|
||||
->where('reservation_id = :id AND type = :type');
|
||||
$statementCheck = $this->connection->execute($queryCheck, [
|
||||
'id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Broker->value
|
||||
]);
|
||||
$result = $statementCheck->fetch(PDO::FETCH_ASSOC);
|
||||
$new_id = $reservation->broker->id;
|
||||
$reservation->broker = $this->brokerRepository->fetchById($result['id']);
|
||||
$this->editBroker($reservation, ['broker_id' => $new_id]);
|
||||
} catch (PDOException) {
|
||||
$queryInsert = $this->connection->getQueryBuilder()
|
||||
->insert()
|
||||
->into('reservation_details')
|
||||
->columns(['reservation_id', 'type', 'reference_id'])
|
||||
->values([':reservation_id', ':type', ':reference_id']);
|
||||
$this->connection->execute($queryInsert, [
|
||||
'reservation_id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Broker->value,
|
||||
'reference_id' => $reservation->broker->id
|
||||
]);
|
||||
}
|
||||
}
|
||||
protected function savePromotions(Model\Venta\Reservation $reservation): void
|
||||
@ -126,60 +180,152 @@ class Reservation extends Common\Ideal\Repository
|
||||
}
|
||||
$queryCheck = $this->connection->getQueryBuilder()
|
||||
->select('COUNT(id) AS cnt')
|
||||
->from('reservation_data')
|
||||
->where('reservation_id = :id AND type = "Promotion" AND reference_id = :promotion_id');
|
||||
->from('reservation_details')
|
||||
->where('reservation_id = :id AND type = :type AND reference_id = :promotion_id');
|
||||
$statementCheck = $this->connection->prepare($queryCheck);
|
||||
$queryInsert = $this->connection->getQueryBuilder()
|
||||
->insert()
|
||||
->into('reservation_data')
|
||||
->into('reservation_details')
|
||||
->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]);
|
||||
$statementCheck->execute([
|
||||
'id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Promotion->value,
|
||||
'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]);
|
||||
$statementInsert->execute([
|
||||
'reservation_id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Promotion->value,
|
||||
'reference_id' => $promotion->id
|
||||
]);
|
||||
}
|
||||
|
||||
$this->cleanUpPromotions($reservation);
|
||||
}
|
||||
protected function editUnits(Model\Venta\Reservation $reservation, array $new_data): void
|
||||
protected function cleanUpPromotions(Model\Venta\Reservation $reservation): void
|
||||
{
|
||||
$this->cleanUpDetails($reservation,
|
||||
Model\Venta\Reservation\Detail\Type::Promotion->value,
|
||||
array_map(fn($promotion) => $promotion->id, $reservation->promotions));
|
||||
}
|
||||
protected function cleanUpDetails(Model\Venta\Reservation $reservation, int $type_id, array $currentIds): void
|
||||
{
|
||||
$queryCheck = $this->connection->getQueryBuilder()
|
||||
->select('COUNT(id) AS cnt')
|
||||
->from('reservation_details')
|
||||
->where('reservation_id = :id AND type = :type');
|
||||
$statementCheck = $this->connection->prepare($queryCheck);
|
||||
$deleteParam = implode(', ', array_map(fn($id) => ":id$id", $currentIds));
|
||||
$queryDelete = $this->connection->getQueryBuilder()
|
||||
->delete()
|
||||
->from('reservation_details')
|
||||
->where("reservation_id = :id AND type = :type AND reference_id NOT IN ({$deleteParam})");
|
||||
$statementDelete = $this->connection->prepare($queryDelete);
|
||||
|
||||
try {
|
||||
$statementCheck->execute([
|
||||
'id' => $reservation->id,
|
||||
'type' => $type_id
|
||||
]);
|
||||
$result = $statementCheck->fetch(PDO::FETCH_ASSOC);
|
||||
if ($result['cnt'] <= count($currentIds)) {
|
||||
return;
|
||||
}
|
||||
$deleteIdValues = array_combine(array_map(fn($id) => "id$id", $currentIds), $currentIds);
|
||||
$statementDelete->execute(array_merge(
|
||||
['id' => $reservation->id, 'type' => $type_id],
|
||||
$deleteIdValues));
|
||||
} catch (PDOException) {}
|
||||
}
|
||||
|
||||
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');
|
||||
->from('reservation_details')
|
||||
->where('reservation_id = :id AND type = :type AND reference_id = :unit_id');
|
||||
$statementSelect = $this->connection->prepare($querySelect);
|
||||
$queryUpdate = $this->connection->getQueryBuilder()
|
||||
->update('reservation_data')
|
||||
->update('reservation_details')
|
||||
->set('value = :value')
|
||||
->where('reservation_id = :id AND type = "Unit" AND reference_id = :unit_id');
|
||||
->where('reservation_id = :id AND type = :type AND reference_id = :unit_id');
|
||||
$statementUpdate = $this->connection->prepare($queryUpdate);
|
||||
foreach ($new_data as $unit_id => $value) {
|
||||
$idx = $reservation->findUnit($unit_id);
|
||||
$queryInsert = $this->connection->getQueryBuilder()
|
||||
->insert()
|
||||
->into('reservation_details')
|
||||
->columns(['reservation_id', 'type', 'reference_id', 'value'])
|
||||
->values([':reservation_id', ':type', ':reference_id', ':value']);
|
||||
$statementInsert = $this->connection->prepare($queryInsert);
|
||||
foreach ($new_data['units'] as $unit) {
|
||||
$idx = $reservation->findUnit($unit['unit_id']);
|
||||
if ($idx === null) {
|
||||
$reservation->addUnit($this->unitRepository->fetchById($unit_id), $value);
|
||||
$reservation->addUnit($this->unitRepository->fetchById($unit['unit_id']), $unit['value']);
|
||||
$statementInsert->execute([
|
||||
'reservation_id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Unit->value,
|
||||
'reference_id' => $unit['unit_id'],
|
||||
'value' => $unit['value']
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
$statementSelect->execute(['id' => $reservation->id, 'unit_id' => $unit_id]);
|
||||
$statementSelect->execute([
|
||||
'id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Unit->value,
|
||||
'unit_id' => $unit['unit_id']
|
||||
]);
|
||||
$result = $statementSelect->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$result) {
|
||||
$reservation->addUnit($this->unitRepository->fetchById($unit['unit_id']), $unit['value']);
|
||||
$statementInsert->execute([
|
||||
'reservation_id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Unit->value,
|
||||
'reference_id' => $unit['unit_id'],
|
||||
'value' => $unit['value']
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
$statementUpdate->execute(['id' => $reservation->id, 'unit_id' => $unit_id, 'value' => $value]);
|
||||
$reservation->units[$idx]['value'] = $value;
|
||||
$statementUpdate->execute([
|
||||
'id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Unit->value,
|
||||
'unit_id' => $unit['unit_id'],
|
||||
'value' => $unit['value']
|
||||
]);
|
||||
$reservation->units[$idx]['value'] = $unit['value'];
|
||||
}
|
||||
}
|
||||
protected function editPromotions(Model\Venta\Reservation $reservation, array $new_data): void
|
||||
protected function editBroker(Model\Venta\Reservation &$reservation, array $new_data): void
|
||||
{
|
||||
if (!array_key_exists('broker_id', $new_data) or $new_data['broker_id'] === $reservation->broker->id) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$query = $this->connection->getQueryBuilder()
|
||||
->update('reservation_details')
|
||||
->set('reference_id = :broker_id')
|
||||
->where('reservation_id = :id AND type = :type');
|
||||
$this->connection->execute($query, [
|
||||
'id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Broker->value,
|
||||
'broker_id' => $new_data['broker_id']
|
||||
]);
|
||||
$reservation->broker = $this->brokerRepository->fetchById($new_data['broker_id']);
|
||||
} catch (PDOException) {}
|
||||
}
|
||||
protected function editPromotions(Model\Venta\Reservation &$reservation, array $new_data): void
|
||||
{
|
||||
$querySelect = $this->connection->getQueryBuilder()
|
||||
->select()
|
||||
->from('reservation_data')
|
||||
->from('reservation_details')
|
||||
->where('reservation_id = :id AND type = "Promotion" AND reference_id = :promotion_id');
|
||||
$statementSelect = $this->connection->prepare($querySelect);
|
||||
$queryUpdate = $this->connection->getQueryBuilder()
|
||||
->update('reservation_data')
|
||||
->update('reservation_details')
|
||||
->set('value = :value')
|
||||
->where('reservation_id = :id AND type = "Promotion" AND reference_id = :promotion_id');
|
||||
$statementUpdate = $this->connection->prepare($queryUpdate);
|
||||
@ -198,13 +344,26 @@ class Reservation extends Common\Ideal\Repository
|
||||
$reservation->promotions[$idx] = $this->promotionRepository->fetchById($promotion_id);
|
||||
}
|
||||
}
|
||||
protected function fetchUnits(Model\Venta\Reservation &$reservation): Model\Venta\Reservation
|
||||
|
||||
protected function fetchUnits(Model\Venta\Reservation &$reservation, array $new_data): Model\Venta\Reservation
|
||||
{
|
||||
$this->fetchSavedUnits($reservation);
|
||||
|
||||
if (array_key_exists('units', $new_data) and count($new_data['units']) > 0) {
|
||||
$this->fetchUnsavedUnits($reservation, $new_data);
|
||||
}
|
||||
return $reservation;
|
||||
}
|
||||
protected function fetchSavedUnits(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]);
|
||||
->from('reservation_details')
|
||||
->where('reservation_id = :id AND type = ?');
|
||||
$statement = $this->connection->execute($query, [
|
||||
'id' => $reservation->id,
|
||||
Model\Venta\Reservation\Detail\Type::Unit->value
|
||||
]);
|
||||
|
||||
while ($result = $statement->fetch(PDO::FETCH_ASSOC)) {
|
||||
try {
|
||||
@ -213,13 +372,69 @@ class Reservation extends Common\Ideal\Repository
|
||||
}
|
||||
return $reservation;
|
||||
}
|
||||
protected function fetchPromotions(Model\Venta\Reservation $reservation): Model\Venta\Reservation
|
||||
protected function fetchUnsavedUnits(Model\Venta\Reservation &$reservation, array $new_data): Model\Venta\Reservation
|
||||
{
|
||||
if (!array_key_exists('units', $new_data) or count($new_data['units']) > 0) {
|
||||
return $reservation;
|
||||
}
|
||||
$queryCheck = $this->connection->getQueryBuilder()
|
||||
->select('COUNT(id) AS cnt')
|
||||
->from('reservation_details')
|
||||
->where('reservation_id = :id AND type = :type AND reference_id = :unit_id');
|
||||
$statementCheck = $this->connection->prepare($queryCheck);
|
||||
foreach ($new_data['units'] as $unit) {
|
||||
$statementCheck->execute([
|
||||
'id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Unit->value,
|
||||
'unit_id' => $unit['unit_id']
|
||||
]);
|
||||
$result = $statementCheck->fetch(PDO::FETCH_ASSOC);
|
||||
if ($result['cnt'] > 0) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$reservation->addUnit($this->unitRepository->fetchById($unit['unit_id']), $unit['value']);
|
||||
} catch (Common\Implement\Exception\EmptyResult) {}
|
||||
}
|
||||
return $reservation;
|
||||
}
|
||||
protected function fetchBroker(Model\Venta\Reservation &$reservation, array $new_data): Model\Venta\Reservation
|
||||
{
|
||||
if (!array_key_exists('broker_id', $new_data)) {
|
||||
$query = $this->connection->getQueryBuilder()
|
||||
->select('reference_id')
|
||||
->from('reservation_details')
|
||||
->where('reservation_id = :id AND type = :type');
|
||||
try {
|
||||
$statement =$this->connection->execute($query, [
|
||||
'id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Broker->value
|
||||
]);
|
||||
$result = $statement->fetch(PDO::FETCH_ASSOC);
|
||||
$reservation->broker = $this->brokerRepository->fetchById($result['reference_id']);
|
||||
} catch (PDOException) {}
|
||||
|
||||
return $reservation;
|
||||
}
|
||||
try {
|
||||
$reservation->broker = $this->brokerRepository->fetchById($new_data['broker_id']);
|
||||
} catch (Common\Implement\Exception\EmptyResult) {}
|
||||
return $reservation;
|
||||
}
|
||||
protected function fetchPromotions(Model\Venta\Reservation &$reservation, array $new_data): Model\Venta\Reservation
|
||||
{
|
||||
$this->fetchSavedPromotions($reservation);
|
||||
$this->fetchUnsavedPromotions($reservation, $new_data);
|
||||
return $reservation;
|
||||
}
|
||||
protected function fetchSavedPromotions(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]);
|
||||
->from('reservation_details')
|
||||
->where('type = :type AND reservation_id = :id');
|
||||
$statement = $this->connection->execute($query,
|
||||
['id' => $reservation->id, 'type' => Model\Venta\Reservation\Detail\Type::Promotion->value]);
|
||||
while ($result = $statement->fetch(PDO::FETCH_ASSOC)) {
|
||||
try {
|
||||
$reservation->promotions []= $this->promotionRepository->fetchById($result['reference_id']);
|
||||
@ -227,4 +442,43 @@ class Reservation extends Common\Ideal\Repository
|
||||
}
|
||||
return $reservation;
|
||||
}
|
||||
protected function fetchUnsavedPromotions(Model\Venta\Reservation &$reservation, array $new_data): Model\Venta\Reservation
|
||||
{
|
||||
if (!array_key_exists('promotions', $new_data) or count($new_data['promotions']) > 0) {
|
||||
return $reservation;
|
||||
}
|
||||
$queryCheck = $this->connection->getQueryBuilder()
|
||||
->select('COUNT(id) AS cnt')
|
||||
->from('reservation_details')
|
||||
->where('type = :type AND reservation_id = :id AND reference_id = :promotion_id');
|
||||
$statementCheck = $this->connection->prepare($queryCheck);
|
||||
foreach ($new_data['promotions'] as $promotion) {
|
||||
$statementCheck->execute([
|
||||
'id' => $reservation->id,
|
||||
'promotion_id' => $promotion
|
||||
]);
|
||||
$result = $statementCheck->fetch(PDO::FETCH_ASSOC);
|
||||
if ($result['cnt'] > 0) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$reservation->promotions []= $this->promotionRepository->fetchById($promotion);
|
||||
} catch (Common\Implement\Exception\EmptyResult) {}
|
||||
}
|
||||
return $reservation;
|
||||
}
|
||||
protected function removeBroker(Model\Venta\Reservation &$reservation): void
|
||||
{
|
||||
try {
|
||||
$query = $this->connection->getQueryBuilder()
|
||||
->delete()
|
||||
->from('reservation_details')
|
||||
->where('reservation_id = :id AND type = :type');
|
||||
$this->connection->execute($query, [
|
||||
'id' => $reservation->id,
|
||||
'type' => Model\Venta\Reservation\Detail\Type::Broker->value
|
||||
]);
|
||||
$reservation->broker = null;
|
||||
} catch (PDOException) {}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,9 @@ use Incoviba\Repository;
|
||||
|
||||
class Reservation extends Ideal\Service\API
|
||||
{
|
||||
public function __construct(LoggerInterface $logger, protected Repository\Venta\Reservation $reservationRepository)
|
||||
public function __construct(LoggerInterface $logger,
|
||||
protected Repository\Venta\Reservation $reservationRepository,
|
||||
protected Repository\Venta\Reservation\State $stateRepository)
|
||||
{
|
||||
parent::__construct($logger);
|
||||
}
|
||||
@ -22,7 +24,7 @@ class Reservation extends Ideal\Service\API
|
||||
public function getAll(null|string|array $order = null): array
|
||||
{
|
||||
try {
|
||||
return $this->reservationRepository->fetchAll($order);
|
||||
return array_map([$this, 'process'], $this->reservationRepository->fetchAll($order));
|
||||
} catch (Implement\Exception\EmptyResult) {
|
||||
return [];
|
||||
}
|
||||
@ -76,6 +78,12 @@ class Reservation extends Ideal\Service\API
|
||||
}
|
||||
protected function process(Define\Model $model): Model\Venta\Reservation
|
||||
{
|
||||
$model->addFactory('states', new Implement\Repository\Factory()
|
||||
->setArgs(['reservation_id' => $model->id])
|
||||
->setCallable(function(int $reservation_id) {
|
||||
return $this->stateRepository->fetchByReservation($reservation_id);
|
||||
})
|
||||
);
|
||||
return $model;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user