Cambios a modelo Reservation
This commit is contained in:
@ -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
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user