<?php
namespace Whater\Domain\User\Model;
use BornFree\TacticianDomainEvent\Recorder\ContainsRecordedEvents;
use BornFree\TacticianDomainEvent\Recorder\EventRecorderCapabilities;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Whater\Domain\Common\Exception\InvalidUUIDException;
use Ramsey\Uuid\Uuid;
use Whater\Domain\Product\Exception\InvalidCartOrderChangeUserException;
use Whater\Domain\Product\Model\CartOrder;
use Whater\Domain\User\Exception\IllegalOrganizationLicenseDatesException;
use Whater\Domain\User\Exception\IllegalOrganizationLicenseStatusException;
use Whater\Domain\User\Exception\InvalidLicensePlanException;
use Whater\Domain\User\Exception\InvalidLicenseScopeException;
use Whater\Domain\User\Exception\InvalidLicenseTypeException;
use Whater\Domain\Whater\Model\DistributionNetwork;
use Whater\Domain\Whater\Model\WhaterOrganization;
use Whater\Domain\Whater\Model\WhaterPoint;
use Whater\Domain\Zones\Model\Town;
/**
* Class OrganizationLicense
*
* @package Whater\Domain\User\Model
*/
class OrganizationLicense implements ContainsRecordedEvents
{
use EventRecorderCapabilities;
// *** DEPRECATED*****
public const LICENSE_DATABASE_ACCESS = 'LICENSE_DATABASE_ACCESS';
public const LICENSE_MANAGE_ORGANIZATION = 'LICENSE_MANAGE_ORGANIZATION';
public const LICENSE_MARKETPLACE = 'LICENSE_MARKETPLACE';
// *******************
public const LICENSE_STATUS_CONFIRMED = 'LICENSE_STATUS_CONFIRMED';
public const LICENSE_STATUS_REQUESTED = 'LICENSE_STATUS_REQUESTED';
public const LICENSE_STATUS_CANCELED = 'LICENSE_STATUS_CANCELED';
public const LICENSE_TYPE_BASIC = 'LICENSE_TYPE_BASIC';
public const LICENSE_TYPE_STANDARD = 'LICENSE_TYPE_STANDARD';
public const LICENSE_TYPE_PREMIUM = 'LICENSE_TYPE_PREMIUM';
public const LICENSE_PAYMENT_PLAN_MONTHLY = 'LICENSE_PAYMENT_PLAN_MONTHLY';
public const LICENSE_PAYMENT_PLAN_ANNUAL = 'LICENSE_PAYMENT_PLAN_ANNUAL';
public const LICENSE_PAYMENT_PLAN_ADMIN = 'LICENSE_PAYMENT_PLAN_ADMIN';
public const LICENSE_SCOPE_TOWNS = 'LICENSE_SCOPE_TOWNS';
public const LICENSE_SCOPE_COUNTRIES_COUNTRY_AREAS_AGRUPATIONS = 'LICENSE_SCOPE_COUNTRIES_COUNTRY_AREAS_AGRUPATIONS';
public const LICENSE_SCOPE_ESTABLISHMENTS = 'LICENSE_SCOPE_ESTABLISHMENTS';
public const LICENSE_SCOPE_PROFESSIONALS = 'LICENSE_SCOPE_PROFESSIONALS';
public const LICENSE_SCOPE_SELLERS = 'LICENSE_SCOPE_SELLERS';
/**
* @var string
*/
private $uuid;
/**
* @var string
*/
private $status;
/**
* @var \DateTime
*/
private $startDate;
/**
* @var \DateTime
*/
private $endDate;
/**
* @var \DateTime
*/
private $createdAt;
/**
* @var \DateTime
*/
private $updatedAt;
/**
* @var \Whater\Domain\Whater\Model\WhaterOrganization
*/
private $organization;
/**
* @var Collection
*/
private $countries;
/**
* @var Collection
*/
private $countryAreas;
/**
* @var Collection
*/
private $whaterpoints;
/**
* @var Collection
*/
private $agrupations;
/**
* @var Collection
*/
private $towns;
/**
* @var Collection
*/
private $establishments;
/**
* @var string
*/
private $licenseType;
/**
* @var array
*/
private $widgetAllowedDomains;
/**
* @var CartOrder
*/
private $cartOrder;
/**
* @var int
*/
private $totalPopulation;
/**
* @var string
*/
private $licenseScope;
/**
* @var float
*/
private $licenseFee;
/**
* @var string
*/
private $paymentPlan;
public function __construct(
string $userLicenseId = null,
\DateTime $startDate,
\DateTime $endDate,
WhaterOrganization $organization,
string $licenseType,
string $licenseScope,
float $licenseFee,
string $paymentPlan
) {
try {
$this->uuid = Uuid::fromString($userLicenseId ?: Uuid::uuid4())->toString();
} catch (\InvalidArgumentException $e) {
throw new InvalidUUIDException();
}
$this->status = OrganizationLicense::LICENSE_STATUS_REQUESTED;
$this->startDate = $startDate;
$this->endDate = $endDate;
if ($startDate > $endDate) {
throw new IllegalOrganizationLicenseDatesException();
}
$this->organization = $organization;
switch ($licenseType) {
case OrganizationLicense::LICENSE_TYPE_BASIC:
case OrganizationLicense::LICENSE_TYPE_STANDARD:
case OrganizationLicense::LICENSE_TYPE_PREMIUM:
$this->licenseType = $licenseType;
break;
default:
throw new InvalidLicenseTypeException();
}
switch ($licenseScope) {
case OrganizationLicense::LICENSE_SCOPE_COUNTRIES_COUNTRY_AREAS_AGRUPATIONS:
case OrganizationLicense::LICENSE_SCOPE_TOWNS:
case OrganizationLicense::LICENSE_SCOPE_ESTABLISHMENTS:
case OrganizationLicense::LICENSE_SCOPE_PROFESSIONALS:
case OrganizationLicense::LICENSE_SCOPE_SELLERS:
$this->licenseScope = $licenseScope;
break;
default:
throw new InvalidLicenseScopeException();
}
switch ($paymentPlan) {
case OrganizationLicense::LICENSE_PAYMENT_PLAN_MONTHLY:
case OrganizationLicense::LICENSE_PAYMENT_PLAN_ANNUAL:
case OrganizationLicense::LICENSE_PAYMENT_PLAN_ADMIN:
$this->paymentPlan = $paymentPlan;
break;
default:
throw new InvalidLicensePlanException();
}
$this->licenseFee = $licenseFee;
if ($this->licenseFee <= 0) {
$this->licenseFee = 0;
}
$this->countries = new ArrayCollection();
$this->countryAreas = new ArrayCollection();
$this->whaterpoints = new ArrayCollection();
$this->agrupations = new ArrayCollection();
$this->towns = new ArrayCollection();
$this->establishments = new ArrayCollection();
$this->createdAt = new \DateTime();
$this->updatedAt = new \DateTime();
}
/**
* @param \DateTime $startDate
* @param \DateTime $endDate
* @return OrganizationLicense
*/
public function editDates(
\DateTime $startDate,
\DateTime $endDate
): OrganizationLicense {
$this->startDate = $startDate;
$this->endDate = $endDate;
if ($startDate > $endDate) {
throw new IllegalOrganizationLicenseDatesException();
}
$this->updatedAt = new \DateTime();
return $this;
}
public function editStatus(string $status)
{
switch ($status) {
case OrganizationLicense::LICENSE_STATUS_CANCELED:
case OrganizationLicense::LICENSE_STATUS_CONFIRMED:
case OrganizationLicense::LICENSE_STATUS_REQUESTED:
$this->status = $status;
break;
default:
throw new IllegalOrganizationLicenseStatusException();
}
}
public function updateCountriesLicense(
Collection $countries
) {
if ($this->licenseScope() != OrganizationLicense::LICENSE_SCOPE_COUNTRIES_COUNTRY_AREAS_AGRUPATIONS) {
throw new InvalidLicenseScopeException($this->licenseScope());
}
$this->countries = $countries;
//Calculate propulation
$totalPopulation = 0;
foreach ($this->countries() as $country) {
$totalPopulation += $country->population();
}
$this->totalPopulation = $totalPopulation;
$this->countryAreas->clear();
$this->whaterpoints->clear();
$this->agrupations->clear();
$this->towns->clear();
$this->establishments->clear();
$this->updatedAt = new \DateTime();
return $this;
}
public function updateCountryAreasLicense(
Collection $countryAreas
) {
if ($this->licenseScope() != OrganizationLicense::LICENSE_SCOPE_COUNTRIES_COUNTRY_AREAS_AGRUPATIONS) {
throw new InvalidLicenseScopeException();
}
$this->countryAreas = $countryAreas;
//Calculate propulation
$totalPopulation = 0;
foreach ($this->countryAreas() as $countryArea) {
$totalPopulation += $countryArea->population();
}
$this->totalPopulation = $totalPopulation;
$this->countries->clear();
$this->whaterpoints->clear();
$this->agrupations->clear();
$this->towns->clear();
$this->establishments->clear();
$this->updatedAt = new \DateTime();
return $this;
}
public function updateAgrupationsLicense(
Collection $agrupations
) {
if ($this->licenseScope() != OrganizationLicense::LICENSE_SCOPE_COUNTRIES_COUNTRY_AREAS_AGRUPATIONS) {
throw new InvalidLicenseScopeException();
}
$this->agrupations = $agrupations;
//Calculate propulation
$totalPopulation = 0;
foreach ($this->agrupations() as $agrupation) {
foreach ($agrupation->towns() as $town) {
$totalPopulation += $town->population();
}
}
$this->totalPopulation = $totalPopulation;
$this->countries->clear();
$this->countryAreas->clear();
$this->whaterpoints->clear();
$this->towns->clear();
$this->establishments->clear();
$this->updatedAt = new \DateTime();
return $this;
}
public function updateTownsLicense(
Collection $towns
) {
if (
$this->licenseScope() == OrganizationLicense::LICENSE_SCOPE_TOWNS ||
$this->licenseScope() == OrganizationLicense::LICENSE_SCOPE_PROFESSIONALS
) {
$this->towns = $towns;
//Calculate propulation
$totalPopulation = 0;
foreach ($this->towns() as $town) {
$totalPopulation += $town->population();
}
$this->totalPopulation = $totalPopulation;
$this->countries->clear();
$this->countryAreas->clear();
$this->whaterpoints->clear();
$this->agrupations->clear();
$this->establishments->clear();
$this->updatedAt = new \DateTime();
} else {
throw new InvalidLicenseScopeException();
}
return $this;
}
public function updateEstablishmentsLicense(
Collection $establishments
) {
if ($this->licenseScope() != OrganizationLicense::LICENSE_SCOPE_ESTABLISHMENTS) {
throw new InvalidLicenseScopeException();
}
$this->establishments = $establishments;
$totalPopulation = null;
$this->totalPopulation = $totalPopulation;
$this->countries->clear();
$this->countryAreas->clear();
$this->whaterpoints->clear();
$this->agrupations->clear();
$this->towns->clear();
$this->updatedAt = new \DateTime();
return $this;
}
public function licenseScopeDescription()
{
$names = [];
switch ($this->licenseScope) {
case OrganizationLicense::LICENSE_SCOPE_COUNTRIES_COUNTRY_AREAS_AGRUPATIONS:
foreach ($this->countries() as $country) {
array_push($names, $country->name());
}
foreach ($this->countryAreas() as $countryArea) {
array_push($names, $countryArea->name());
}
foreach ($this->agrupations() as $agrupation) {
array_push($names, $agrupation->name());
}
break;
case OrganizationLicense::LICENSE_SCOPE_TOWNS:
foreach ($this->towns() as $town) {
array_push($names, $town->name());
}
break;
case OrganizationLicense::LICENSE_SCOPE_ESTABLISHMENTS:
foreach ($this->establishments() as $establishment) {
array_push($names, $establishment->name());
}
break;
case OrganizationLicense::LICENSE_SCOPE_PROFESSIONALS:
foreach ($this->towns() as $town) {
array_push($names, $town->name());
}
break;
case OrganizationLicense::LICENSE_SCOPE_SELLERS:
break;
}
return join(", ", $names);
}
public function updateWidgetAllowedDomains(array $widgetAllowedDomains)
{
$this->widgetAllowedDomains = $widgetAllowedDomains;
$this->updatedAt = new \DateTime();
}
public function setCartOrder(CartOrder $cartOrder)
{
if ($this->cartOrder == null) {
$this->cartOrder = $cartOrder;
} else {
throw new InvalidCartOrderChangeUserException();
}
$this->updatedAt = new \DateTime();
}
/**
* @return string
*/
public function id(): string
{
return $this->uuid;
}
/**
* @return string
*/
public function licenseType(): string
{
return $this->licenseType;
}
/**
* @return string
*/
public function status(): string
{
return $this->status;
}
/**
* @return array
*/
public function widgetAllowedDomains(): array
{
return $this->widgetAllowedDomains;
}
/**
* @return string
*/
public function licenseScope(): string
{
return $this->licenseScope;
}
/**
* @return float
*/
public function licenseFee(): float
{
return $this->licenseFee;
}
/**
* @return string
*/
public function paymentPlan(): string
{
return $this->paymentPlan;
}
/**
* @return int
*/
public function totalPopulation(): ?int
{
return $this->totalPopulation;
}
/**
* @return \DateTime
*/
public function endDate(): \DateTime
{
return $this->endDate;
}
/**
* @return \DateTime
*/
public function startDate(): \DateTime
{
return $this->startDate;
}
/**
* @return \DateTime
*/
public function createdAt(): \DateTime
{
return $this->createdAt;
}
/**
* @return \DateTime|null
*/
public function updatedAt()
{
return $this->updatedAt;
}
/**
* @return WhaterOrganization
*/
public function organization(): WhaterOrganization
{
return $this->organization;
}
/**
* @return CartOrder
*/
public function cartOrder(): ?CartOrder
{
return $this->cartOrder;
}
/**
* @return Collection
*/
public function countries(): Collection
{
return $this->countries;
}
/**
* @return Collection
*/
public function countryAreas(): Collection
{
return $this->countryAreas;
}
/**
* @return Collection
*/
public function whaterpoints(): Collection
{
return $this->whaterpoints;
}
/**
* @return Collection
*/
public function agrupations(): Collection
{
return $this->agrupations;
}
/**
* @return Collection
*/
public function towns(): Collection
{
return $this->towns;
}
/**
* @return Collection
*/
public function establishments(): Collection
{
return $this->establishments;
}
public function licenseSortingPosition()
{
switch ($this->licenseScope) {
case OrganizationLicense::LICENSE_SCOPE_COUNTRIES_COUNTRY_AREAS_AGRUPATIONS:
return 1;
break;
case OrganizationLicense::LICENSE_SCOPE_TOWNS:
return 2;
break;
case OrganizationLicense::LICENSE_SCOPE_ESTABLISHMENTS:
return 3;
break;
case OrganizationLicense::LICENSE_SCOPE_PROFESSIONALS:
return 4;
break;
case OrganizationLicense::LICENSE_SCOPE_SELLERS:
return 5;
break;
}
}
public function isValidForWhaterpoint(WhaterPoint $whaterPoint)
{
if ($this->status() == OrganizationLicense::LICENSE_STATUS_REQUESTED) {
return false;
} else {
$now = new \DateTime();
if ($now > $this->endDate()) {
return false;
}
if ($now < $this->startDate()) {
return false;
}
}
switch ($this->licenseScope()) {
case OrganizationLicense::LICENSE_SCOPE_SELLERS:
return false;
case OrganizationLicense::LICENSE_SCOPE_ESTABLISHMENTS:
return false;
case OrganizationLicense::LICENSE_SCOPE_TOWNS:
$whaterpointTown = $whaterPoint->town();
foreach ($this->towns() as $licenseTown) {
if ($licenseTown->equals($whaterpointTown)) {
return true;
}
}
break;
case OrganizationLicense::LICENSE_SCOPE_PROFESSIONALS:
$whaterpointTown = $whaterPoint->town();
foreach ($this->towns() as $licenseTown) {
if ($licenseTown->equals($whaterpointTown)) {
return true;
}
}
break;
case OrganizationLicense::LICENSE_SCOPE_COUNTRIES_COUNTRY_AREAS_AGRUPATIONS:
$whaterpointTown = $whaterPoint->town();
foreach ($this->countries() as $country) {
if ($country->equals($whaterpointTown->country())) {
return true;
}
}
foreach ($this->countryAreas() as $licenseCountryArea) {
if (
$whaterpointTown->countryArea() != null &&
$licenseCountryArea->equals($whaterpointTown->countryArea())
) {
return true;
}
}
foreach ($this->agrupations() as $licenseAgrupation) {
foreach ($licenseAgrupation->towns() as $licenseAgrupationTown) {
if ($whaterpointTown->equals($licenseAgrupationTown)) {
return true;
}
}
}
break;
}
return false;
}
public function isValidForDistributionNetwork(DistributionNetwork $distributionNetwork)
{
if ($this->status() == OrganizationLicense::LICENSE_STATUS_REQUESTED) {
return false;
} else {
$now = new \DateTime();
if ($now > $this->endDate()) {
return false;
}
if ($now < $this->startDate()) {
return false;
}
}
switch ($this->licenseScope()) {
case OrganizationLicense::LICENSE_SCOPE_SELLERS:
return false;
case OrganizationLicense::LICENSE_SCOPE_ESTABLISHMENTS:
return false;
case OrganizationLicense::LICENSE_SCOPE_TOWNS:
$distributionNetworkTowns = $distributionNetwork->towns();
foreach ($distributionNetworkTowns as $distributionNetworkTown) {
foreach ($this->towns() as $licenseTown) {
if ($licenseTown->equals($distributionNetworkTown)) {
return true;
}
}
}
break;
case OrganizationLicense::LICENSE_SCOPE_PROFESSIONALS:
$distributionNetworkTowns = $distributionNetwork->towns();
foreach ($distributionNetworkTowns as $distributionNetworkTown) {
foreach ($this->towns() as $licenseTown) {
if ($licenseTown->equals($distributionNetworkTown)) {
return true;
}
}
}
break;
case OrganizationLicense::LICENSE_SCOPE_COUNTRIES_COUNTRY_AREAS_AGRUPATIONS:
$distributionNetworkTowns = $distributionNetwork->towns();
foreach ($distributionNetworkTowns as $distributionNetworkTown) {
foreach ($this->countries() as $country) {
if ($country->equals($distributionNetworkTown->country())) {
return true;
}
}
foreach ($this->countryAreas() as $licenseCountryArea) {
if (
$distributionNetworkTown->countryArea() != null &&
$licenseCountryArea->equals($distributionNetworkTown->countryArea())
) {
return true;
}
}
foreach ($this->agrupations() as $licenseAgrupation) {
foreach ($licenseAgrupation->towns() as $licenseAgrupationTown) {
if ($distributionNetworkTown->equals($licenseAgrupationTown)) {
return true;
}
}
}
}
break;
}
return false;
}
public function isValidForTown(Town $town)
{
throw new \Exception('Need to refactoring!!');
// if ($this->status() != OrganizationLicense::LICENSE_STATUS_CONFIRMED) {
// return false;
// }
// foreach ($this->countries() as $country) {
// if ($town->country()->equals($country)) {
// return true;
// }
// }
// foreach ($this->countryAreas() as $countryArea) {
// if (
// $town->countryArea() != null &&
// $town->countryArea()->equals($countryArea)
// ) {
// return true;
// }
// }
// return false;
}
public function isActive(): bool
{
if ($this->status() != OrganizationLicense::LICENSE_STATUS_CONFIRMED) {
return false;
}
$now = new \DateTime();
if ($this->startDate() != null && $now < $this->startDate() ) {
return false;
}
if ($this->endDate() != null && $now > $this->endDate()) {
return false;
}
return true;
}
/**
* @return bool
*/
public function equals(OrganizationLicense $organizationLicense)
{
return $this->id() === $organizationLicense->id();
}
}