<?php
namespace App\Entity\Gauge;
use App\Entity\Extension\GaugeUnitInterface;
use App\Entity\Extension\ItemsWithHistoryTrait;
use App\Utils\GaugeType;
use App\Utils\Period;
use App\Utils\Segment;
use App\Utils\Units;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity()
* @ORM\Table(name="gauge_purpose")
*/
class GaugePurpose
{
public const PURPOSE_CONSUMPTION = 1; // spotřeba
public const PURPOSE_PRODUCTION = 2; // výroba
public const PURPOSE_DELIVERY = 3; // dodávka (přetoky)
public const PURPOSE_RAINFALL = 4; // srážky
public const PURPOSE_TEMPERATURE = 5; // teplota
public const PURPOSE_HUMIDITY = 6; // vlhkost
public const PURPOSE_CO2 = 7; // koncentrace CO2
public static array $all = [
self::PURPOSE_CONSUMPTION,
self::PURPOSE_PRODUCTION,
self::PURPOSE_DELIVERY,
self::PURPOSE_TEMPERATURE,
self::PURPOSE_HUMIDITY,
self::PURPOSE_CO2,
];
/**
* @var int|null
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private ?int $id = null;
/**
* @var Gauge $gauge
* @ORM\ManyToOne(targetEntity="App\Entity\Gauge\Gauge", inversedBy="purposes")
* @ORM\JoinColumn(name="gauge_id", referencedColumnName="id", nullable=false)
*/
private Gauge $gauge;
/**
* values defined above GaugePurpose::PURPOSE_...
* @var int
* @ORM\Column(type="smallint")
*/
private int $purpose;
/**
* TODO can be deleted after sql/EM-442.sql on production
* @var int|null
* @ORM\Column(type="smallint", nullable=true)
*/
private ?int $primaryMode = GaugeType::MODE_MANUAL;
/**
* TODO can be deleted after sql/EM-442.sql on production
* @var int|null
* @ORM\Column(type="smallint", nullable=true)
*/
private ?int $secondaryMode = GaugeType::MODE_NONE;
/**
* @var Collection|GaugeVolumeRatio[]
* @ORM\OneToMany(targetEntity="App\Entity\Gauge\GaugeVolumeRatio", mappedBy="gaugePurpose", cascade={"all"})
*/
private $volumeRatio;
/**
* @var Collection|GaugeRemoteVolumeRatio[]
* @ORM\OneToMany(targetEntity="App\Entity\Gauge\GaugeRemoteVolumeRatio", mappedBy="gaugePurpose", cascade={"all"})
*/
private $remoteVolumeRatio;
/**
* @var Collection|GaugeConsumptionUsage[]
* @ORM\OneToMany(targetEntity="App\Entity\Gauge\GaugeConsumptionUsage", mappedBy="gaugePurpose", cascade={"all"})
*/
private $consumptionUsage;
/**
* @var int|null
* @ORM\Column(type="smallint", nullable=true)
*/
private ?int $readingsPeriod = Period::MONTH;
/**
* @var bool
* @ORM\Column(type="boolean")
*/
private bool $readingsPeriodControl = true;
/**
* values are defined in App\Utils\Period
* @var int|null
* @ORM\Column(type="smallint", nullable=true)
*/
private ?int $secondaryReadingsPeriod = null;
/**
* @var bool
* @ORM\Column(type="boolean")
*/
private bool $secondaryReadingsPeriodControl = true;
/**
* values are defined in App\Utils\Period
* @var int|null
* @ORM\Column(type="smallint", nullable=true)
*/
private ?int $remoteReadingsPeriod = null;
/**
* @var int|null
* @ORM\Column(type="integer", nullable=true)
*/
private ?int $remoteReadingsMinuteFrequency = null;
/**
* @var Collection|GaugeUnit[]
* @ORM\OneToMany(targetEntity="App\Entity\Gauge\GaugeUnit", mappedBy="gaugePurpose", cascade={"all"})
*/
private $units;
/**
* @var Collection|GaugeRemoteUnit[]
* @ORM\OneToMany(targetEntity="App\Entity\Gauge\GaugeRemoteUnit", mappedBy="gaugePurpose", cascade={"all"})
*/
private $remoteUnits;
use ItemsWithHistoryTrait;
public function __construct()
{
$this->consumptionUsage = new ArrayCollection();
$this->volumeRatio = new ArrayCollection();
$this->remoteVolumeRatio = new ArrayCollection();
$this->units = new ArrayCollection();
$this->remoteUnits = new ArrayCollection();
}
/**
* @return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @param int|null $id
* @return GaugePurpose
*/
public function setId(?int $id): GaugePurpose
{
$this->id = $id;
return $this;
}
/**
* @return Gauge
*/
public function getGauge(): Gauge
{
return $this->gauge;
}
/**
* @param Gauge $gauge
* @return GaugePurpose
*/
public function setGauge(Gauge $gauge): GaugePurpose
{
$this->gauge = $gauge;
return $this;
}
/**
* @return GaugeVolumeRatio[]|Collection
*/
public function getVolumeRatio()
{
return $this->volumeRatio;
}
/**
* @param GaugeVolumeRatio[]|Collection $volumeRatio
* @return GaugePurpose
*/
public function setVolumeRatio($volumeRatio)
{
$this->volumeRatio = $volumeRatio;
return $this;
}
/**
* @return GaugeRemoteVolumeRatio[]|Collection
*/
public function getRemoteVolumeRatio()
{
return $this->remoteVolumeRatio;
}
/**
* @param GaugeRemoteVolumeRatio[]|Collection $remoteVolumeRatio
* @return GaugePurpose
*/
public function setRemoteVolumeRatio($remoteVolumeRatio)
{
$this->remoteVolumeRatio = $remoteVolumeRatio;
return $this;
}
/**
* @return GaugeConsumptionUsage[]|Collection
*/
public function getConsumptionUsage()
{
return $this->consumptionUsage;
}
/**
* @param GaugeConsumptionUsage[]|Collection $consumptionUsage
* @return GaugePurpose
*/
public function setConsumptionUsage($consumptionUsage)
{
$this->consumptionUsage = $consumptionUsage;
return $this;
}
/**
* @param float $volumeRatio
* @return $this
*/
public function addVolumeRatio(float $volumeRatio): self
{
$volumeRatioObj = (new GaugeVolumeRatio())
->setRatio($volumeRatio)
->setValidFrom(new \DateTime());
$volumeRatioObj->setGaugePurpose($this);
$this->volumeRatio->add($volumeRatioObj);
return $this;
}
/**
* @param GaugeConsumptionUsage $consumptionUsage
* @return self
*/
public function addConsumptionUsage(GaugeConsumptionUsage $consumptionUsage): self
{
$consumptionUsage->setGaugePurpose($this);
$this->consumptionUsage->add($consumptionUsage);
return $this;
}
/**
* @param float $volumeRatio
* @return $this
*/
public function addRemoteVolumeRatio(float $volumeRatio): self
{
$remoteVolumeRatioObj = (new GaugeRemoteVolumeRatio())
->setRatio($volumeRatio)
->setValidFrom(new \DateTime());
$remoteVolumeRatioObj->setGaugePurpose($this);
$this->remoteVolumeRatio->add($remoteVolumeRatioObj);
return $this;
}
/**
* @return int
*/
public function getPurpose(): int
{
return $this->purpose;
}
/**
* @param int $purpose
* @return GaugePurpose
*/
public function setPurpose(int $purpose): GaugePurpose
{
$this->purpose = $purpose;
return $this;
}
/**
* @return int|null
*/
public function getReadingsPeriod(): ?int
{
return $this->readingsPeriod;
}
/**
* @param int|null $readingsPeriod
* @return GaugePurpose
*/
public function setReadingsPeriod(?int $readingsPeriod): GaugePurpose
{
$this->readingsPeriod = $readingsPeriod;
return $this;
}
/**
* @return bool
*/
public function isReadingsPeriodControl(): bool
{
return $this->readingsPeriodControl;
}
/**
* @param bool $readingsPeriodControl
* @return GaugePurpose
*/
public function setReadingsPeriodControl(bool $readingsPeriodControl): GaugePurpose
{
$this->readingsPeriodControl = $readingsPeriodControl;
return $this;
}
/**
* @return int|null
*/
public function getSecondaryReadingsPeriod(): ?int
{
return $this->secondaryReadingsPeriod;
}
/**
* @param int|null $secondaryReadingsPeriod
* @return GaugePurpose
*/
public function setSecondaryReadingsPeriod(?int $secondaryReadingsPeriod): GaugePurpose
{
$this->secondaryReadingsPeriod = $secondaryReadingsPeriod;
return $this;
}
/**
* @return bool
*/
public function isSecondaryReadingsPeriodControl(): bool
{
return $this->secondaryReadingsPeriodControl;
}
/**
* @param bool $secondaryReadingsPeriodControl
* @return GaugePurpose
*/
public function setSecondaryReadingsPeriodControl(bool $secondaryReadingsPeriodControl): GaugePurpose
{
$this->secondaryReadingsPeriodControl = $secondaryReadingsPeriodControl;
return $this;
}
/**
* TODO možná přidat jako argument datetime aby bylo možno se ptát i historicky na počet segmentů např podle sazby elektroměru
* @return array
*/
public function getSegments(): array
{
$gauge = $this->getGauge();
if ($gauge->getLevel() !== GaugeType::LEVEL_MAIN && $gauge->getParent() !== null) {
foreach ($gauge->getParent()->getPurposes() as $parentPurpose) {
if ($parentPurpose->getPurpose() === $this->getPurpose()) {
return $parentPurpose->getSegments();
}
}
// EM-959: when purposes don't match (FVE case: CONSUMPTION sub-gauge under
// PRODUCTION parent), fall through to own segment logic below instead of
// returning []. The original commit 24553f76 commented out the entire block,
// which broke ~130 ordinary CONSUMPTION → CONSUMPTION sub-gauges.
}
if ($gauge->getType() === GaugeType::TYPE_ELECTRICITY_METER && $this->getPurpose() === self::PURPOSE_CONSUMPTION) {
$segments = [];
if ($gauge->isElectricityWholesale()) {
$segments[Segment::SEGMENT_HIGH_TARIFF] = Segment::SEGMENT_HIGH_TARIFF;
if ($gauge->isForceLowTariff()) {
$segments[Segment::SEGMENT_LOW_TARIFF] = Segment::SEGMENT_LOW_TARIFF;
}
if ($gauge->isForceSpecialTariff()) {
$segments[Segment::SEGMENT_SPECIAL_TARIFF] = Segment::SEGMENT_SPECIAL_TARIFF;
}
return $segments;
}
$currentRate = $this->getCurrent('rate', null, $gauge->getRates());
if ($currentRate instanceof GaugeRate) {
$rate = $currentRate->getRate();
if ($rate->isHighTariff() === true) {
$segments[Segment::SEGMENT_HIGH_TARIFF] = Segment::SEGMENT_HIGH_TARIFF;
}
if ($rate->isLowTariff() === true) {
$segments[Segment::SEGMENT_LOW_TARIFF] = Segment::SEGMENT_LOW_TARIFF;
}
} else {
$segments[Segment::SEGMENT_HIGH_TARIFF] = Segment::SEGMENT_HIGH_TARIFF;
}
return $segments;
}
if ($this->getPurpose() === self::PURPOSE_PRODUCTION) {
return [Segment::SEGMENT_PRODUCTION => Segment::SEGMENT_PRODUCTION];
}
if ($this->getPurpose() === self::PURPOSE_DELIVERY) {
return [Segment::SEGMENT_ENERGY_DELIVERY => Segment::SEGMENT_ENERGY_DELIVERY];
}
return Segment::getSegmentsByPurpose($this->getPurpose());
}
/**
* @param bool $primary
* @return GaugeVolumeRatio|GaugeRemoteVolumeRatio|null
*/
public function getCurrentVolumeRatio(bool $primary)
{
if ($primary) {
if ($this->gauge->getPrimaryMode() === GaugeType::MODE_MANUAL) {
// primary is manual return volumeRatio
return $this->getCurrent('volumeRatio', null, $this->getVolumeRatio());
}
// primary is remote return remoteVolumeRatio
return $this->getCurrent('remoteVolumeRatio', null, $this->getRemoteVolumeRatio());
}
// secondary is manual return volumeRatio
if ($this->gauge->getSecondaryMode() === GaugeType::MODE_MANUAL) {
return $this->getCurrent('volumeRatio', null, $this->getVolumeRatio());
}
// secondary is remote return remoteVolumeRatio
return $this->getCurrent('remoteVolumeRatio', null, $this->getRemoteVolumeRatio());
}
/**
* @return GaugeUnit[]|Collection
*/
public function getUnits()
{
return $this->units;
}
/**
* @return GaugeRemoteUnit[]|Collection
*/
public function getRemoteUnits()
{
return $this->remoteUnits;
}
/**
* @param \DateTime|null $date
* @return int
*/
public function getCurrentUnit(?\DateTime $date = null): int
{
$gUnit = $this->getCurrent('units', $date, $this->units);
if ($gUnit instanceof GaugeUnitInterface) {
return $gUnit->getUnit();
}
// return default unit by gauge type
return Units::getDefaultUnitByGaugeType($this->gauge->getType());
}
/**
* @param \DateTime|null $date
* @return int
*/
public function getCurrentRemoteUnit(?\DateTime $date = null): int
{
$gUnit = $this->getCurrent('remoteUnits', $date, $this->remoteUnits);
if ($gUnit instanceof GaugeUnitInterface) {
return $gUnit->getUnit();
}
// return default unit by gauge type
return Units::getDefaultUnitByGaugeType($this->gauge->getType());
}
/**
* @param int $remoteUnit
* @return $this
*/
public function newRemoteUnit(int $remoteUnit):self
{
$gru = (new GaugeRemoteUnit())->setUnit($remoteUnit)->setValidFrom(new \DateTime());
$gru->setGaugePurpose($this);
$this->remoteUnits->add($gru);
return $this;
}
/**
* @param int $unit
* @return $this
*/
public function newUnit(int $unit):self
{
$gru = (new GaugeUnit())->setUnit($unit)->setValidFrom(new \DateTime());
$gru->setGaugePurpose($this);
$this->units->add($gru);
return $this;
}
public function getRemoteReadingsPeriod(): ?int
{
return $this->remoteReadingsPeriod;
}
public function setRemoteReadingsPeriod(?int $remoteReadingsPeriod): GaugePurpose
{
$this->remoteReadingsPeriod = $remoteReadingsPeriod;
return $this;
}
public function getRemoteReadingsMinuteFrequency(): ?int
{
return $this->remoteReadingsMinuteFrequency;
}
public function setRemoteReadingsMinuteFrequency(?int $remoteReadingsMinuteFrequency): GaugePurpose
{
$this->remoteReadingsMinuteFrequency = $remoteReadingsMinuteFrequency;
return $this;
}
}