src/Entity/Account.php line 25

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use AdScore\Common\Crypt\Idfuscator;
  4. use AdScore\Common\Gearboy\InvokerFactory;
  5. use App\Component\Serializer\Normalizer\ProxyAwareObjectNormalizer;
  6. use App\Entity\Exception\TransactionAmountException;
  7. use App\HelperFunctions;
  8. use DateTime;
  9. use DateTimeInterface;
  10. use Doctrine\Common\Collections\ArrayCollection;
  11. use Doctrine\Common\Collections\Collection;
  12. use Doctrine\Common\Collections\Criteria;
  13. use Doctrine\ORM\Mapping as ORM;
  14. use Exception;
  15. use Symfony\Component\Serializer\Annotation as SA;
  16. /**
  17.  * Account
  18.  *
  19.  * @ORM\Table(name="accounts", indexes={@ORM\Index(name="verified", columns={"verified"})})
  20.  * @ORM\Entity(repositoryClass="App\Repository\AccountRepository")
  21.  */
  22. class Account extends Entity
  23. {
  24.     public const BADGE_INFO_DEFAULTS = [
  25.         'enabled' => false,
  26.         'name' => null,
  27.         'email' => null,
  28.         'phone_number' => null,
  29.         'address' => null,
  30.         'website' => null
  31.     ];
  32.     public const SERIALIZATION_CONTEXT = [
  33.         'general' => ['groups' => ['account_general']],
  34.         'details' => ['groups' => ['account_general''account_details']],
  35.         'badge' => ['groups' => ['badge']],
  36.         'search' => ['groups' => ['account_general''account_search'], ProxyAwareObjectNormalizer::RESOLVE_PROXY_CLASSES => [Role::class, Account::class, UserInteractive::class]],
  37.         'admin_details' => ['groups' => ['account_general''account_details''account_search''account_admin_details'],
  38.             ProxyAwareObjectNormalizer::RESOLVE_PROXY_CLASSES => [Role::class, Account::class, UserInteractive::class, Transaction::class, Zone::class]
  39.         ],
  40.     ];
  41.     public const RUNOUT_LOCK_TIME 60 60 24 7;
  42.     const RUNOUT_LOCK = [
  43.         'dashboard' => 'dashboard',
  44.         'account' => 'account'
  45.     ];
  46.     /**
  47.      * @var int
  48.      *
  49.      * @ORM\Column(name="id", type="bigint", nullable=false, options={"unsigned"=true})
  50.      * @ORM\Id
  51.      * @ORM\GeneratedValue(strategy="IDENTITY")
  52.      * @SA\Groups({"account_general", "user_search"})
  53.      */
  54.     private $id;
  55.     /**
  56.      * @var string
  57.      *
  58.      * @ORM\Column(name="name", type="string", length=255, nullable=false, options={"comment"="Company or entity name"})
  59.      * @SA\Groups({"account_general", "badge", "user_search"})
  60.      */
  61.     private $name;
  62.     /**
  63.      * @var DateTime
  64.      *
  65.      * @ORM\Column(name="created", type="datetime", nullable=false, options={"default"="CURRENT_TIMESTAMP"})
  66.      * @SA\Groups({"account_general", "badge"})
  67.      */
  68.     private $created null;
  69.     /**
  70.      * @var string
  71.      *
  72.      * @ORM\Column(name="status", type="string", length=0, nullable=false, options={"default"="inactive"})
  73.      * @SA\Groups({"account_general", "badge"})
  74.      */
  75.     private $status 'inactive';
  76.     /**
  77.      * @var string
  78.      *
  79.      * @ORM\Column(name="time_zone", type="string", length=64, nullable=false, options={"default"="UTC"})
  80.      * @SA\Groups({"account_details"})
  81.      */
  82.     private $timeZone 'UTC';
  83.     /**
  84.      * @var string
  85.      *
  86.      * @ORM\Column(name="fdow", type="string", length=0, nullable=false, options={"default"="monday"})
  87.      * @SA\Groups({"account_details"})
  88.      */
  89.     private $fdow 'monday';
  90.     /**
  91.      * @var string
  92.      *
  93.      * @ORM\Column(name="billing_method", type="string", length=0, nullable=false, options={"default"="prepaid"})
  94.      * @SA\Groups({"account_details"})
  95.      */
  96.     private $billingMethod 'prepaid';
  97.     /**
  98.      * @var string|null
  99.      *
  100.      * @ORM\Column(name="billing_details", type="text", length=65535, nullable=true)
  101.      * @SA\Groups({"account_details"})
  102.      */
  103.     private $billingDetails;
  104.     /**
  105.      * @var string|null
  106.      *
  107.      * @ORM\Column(name="price", type="decimal", precision=8, scale=6, nullable=true, options={"default"=0.000150})
  108.      * @SA\Groups({"account_details"})
  109.      */
  110.     private $price 0.000150;
  111.     /**
  112.      * @var string|null
  113.      *
  114.      * @ORM\Column(name="external_sub_id_url", type="string", length=255, nullable=true)
  115.      * @SA\Groups({"account_details"})
  116.      */
  117.     private $externalSubIdUrl null;
  118.     /**
  119.      * @var object|null
  120.      *
  121.      * @ORM\Column(name="meta", type="json", nullable=true)
  122.      */
  123.     private $meta;
  124.     /**
  125.      * @var int
  126.      *
  127.      * @ORM\Column(name="verified", type="bigint", nullable=false, options={"unsigned"=true})
  128.      * @SA\Groups({"account_general"})
  129.      */
  130.     private $verified '0';
  131.     /**
  132.      * @var object|null
  133.      *
  134.      * @ORM\Column(name="badge_info", type="json", nullable=true)
  135.      */
  136.     private $badgeInfo;
  137.     /**
  138.      * @var ArrayCollection|Role[]
  139.      *
  140.      * @SA\SerializedName("role")
  141.      * @ORM\OneToMany(targetEntity="Role", mappedBy="account")
  142.      * @SA\Ignore
  143.      */
  144.     private $roles;
  145.     /**
  146.      * @var ArrayCollection|Zone[]
  147.      *
  148.      * @SA\Groups({"account_admin_details"})
  149.      * @ORM\OneToMany(targetEntity="Zone", mappedBy="account")
  150.      */
  151.     private $zones;
  152.     /**
  153.      * @var ArrayCollection|GwocDomain[]
  154.      *
  155.      * @SA\Ignore
  156.      * @ORM\OneToMany(targetEntity="GwocDomain", mappedBy="account")
  157.      */
  158.     private $gwocDomains;
  159.     /**
  160.      * @var ArrayCollection|User[]
  161.      *
  162.      * @ORM\ManyToMany(targetEntity="User", fetch="EAGER")
  163.      * @ORM\JoinTable(name="roles",
  164.      *     joinColumns={@ORM\JoinColumn(name="account_id", referencedColumnName="id")},
  165.      *     inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}
  166.      * )
  167.      * @SA\Ignore
  168.      */
  169.     private $users;
  170.     /**
  171.      * @var AccountRunout
  172.      *
  173.      * @ORM\OneToOne(targetEntity="AccountRunout", fetch="EAGER")
  174.      * @ORM\JoinColumns({
  175.      *   @ORM\JoinColumn(name="id", referencedColumnName="id")
  176.      * })
  177.      */
  178.     private $runout;
  179.     /**
  180.      * @var ArrayCollection|Transaction[]
  181.      *
  182.      * @ORM\OneToMany(targetEntity="Transaction", mappedBy="account")
  183.      * @SA\Groups({"account_admin_details"})
  184.      */
  185.     private $transactions;
  186.     private $transactionAmount;
  187.     /**
  188.      * @var array|null
  189.      */
  190.     private $trafficData null;
  191.     /**
  192.      * @var float
  193.      */
  194.     private $trafficAmount null;
  195.     /**
  196.      * @var float
  197.      */
  198.     private $balance null;
  199.     /**
  200.      * @var bool
  201.      */
  202.     private $hasTraffic false;
  203.     /**
  204.      * @var int
  205.      */
  206.     private $ownerId;
  207.     /**
  208.      * @internal Tthis is not being called for records returned from a database!
  209.      */
  210.     public function __construct()
  211.     {
  212.         $this->roles = new ArrayCollection();
  213.         $this->zones = new ArrayCollection();
  214.         $this->users = new ArrayCollection();
  215.         $this->gwocDomains = new ArrayCollection();
  216.         $this->transactions = new ArrayCollection();
  217.         $this->created = new DateTime();
  218.     }
  219.     public function getId(): ?int
  220.     {
  221.         return $this->id;
  222.     }
  223.     public function getName(): ?string
  224.     {
  225.         return $this->name;
  226.     }
  227.     public function setName(string $name): self
  228.     {
  229.         $this->name $name;
  230.         return $this;
  231.     }
  232.     public function getCreated(): ?DateTimeInterface
  233.     {
  234.         return $this->created;
  235.     }
  236.     public function setCreated(DateTimeInterface $created): self
  237.     {
  238.         $this->created $created;
  239.         return $this;
  240.     }
  241.     public function getStatus(): ?string
  242.     {
  243.         return $this->status;
  244.     }
  245.     public function setStatus(string $status): self
  246.     {
  247.         $this->status $status;
  248.         return $this;
  249.     }
  250.     public function getTimeZone(): ?string
  251.     {
  252.         return $this->timeZone;
  253.     }
  254.     public function setTimeZone(string $timeZone): self
  255.     {
  256.         $this->timeZone $timeZone;
  257.         return $this;
  258.     }
  259.     public function getFdow(): ?string
  260.     {
  261.         return $this->fdow;
  262.     }
  263.     public function setFdow(string $fdow): self
  264.     {
  265.         $this->fdow $fdow;
  266.         return $this;
  267.     }
  268.     public function getBillingDetails(): ?string
  269.     {
  270.         return is_null($this->billingDetails) ? null trim($this->billingDetails);
  271.     }
  272.     public function setBillingDetails(?string $billingDetails): self
  273.     {
  274.         if (!is_null($billingDetails)) {
  275.             $this->billingDetails trim($billingDetails);
  276.         } else {
  277.             $this->billingDetails null;
  278.         }
  279.         return $this;
  280.     }
  281.     public function getBillingMethod(): ?string
  282.     {
  283.         return $this->billingMethod;
  284.     }
  285.     public function setBillingMethod(string $billingMethod): self
  286.     {
  287.         $this->billingMethod $billingMethod;
  288.         return $this;
  289.     }
  290.     public function getPrice(): ?float
  291.     {
  292.         return $this->price;
  293.     }
  294.     public function setPrice(?float $price): self
  295.     {
  296.         $this->price $price;
  297.         return $this;
  298.     }
  299.     public function getExternalSubIdUrl(): ?string
  300.     {
  301.         return $this->externalSubIdUrl;
  302.     }
  303.     public function setExternalSubIdUrl(?string $externalSubIdUrl): self
  304.     {
  305.         if (empty(trim($externalSubIdUrl))) {
  306.             $this->externalSubIdUrl null;
  307.         } else {
  308.             $this->externalSubIdUrl $externalSubIdUrl;
  309.         }
  310.         return $this;
  311.     }
  312.     /**
  313.      * @return object
  314.      * @SA\Groups({"account_details"})
  315.      */
  316.     public function getMeta(): ?object
  317.     {
  318.         return $this->meta;
  319.     }
  320.     public function setMeta(?object $meta): self
  321.     {
  322.         $this->meta $meta;
  323.         return $this;
  324.     }
  325.     public function isVerified(): bool
  326.     {
  327.         return (bool)$this->verified;
  328.     }
  329.     public function setVerified(string $verified): self
  330.     {
  331.         $this->verified $verified;
  332.         return $this;
  333.     }
  334.     /**
  335.      * @return object
  336.      * @throws Exception
  337.      * @SA\Groups({"account_details", "badge"})
  338.      */
  339.     public function getBadgeInfo(): object
  340.     {
  341.         return HelperFunctions::setStdDefaults((object)$this->badgeInfoself::BADGE_INFO_DEFAULTS);
  342.     }
  343.     /**
  344.      * @param object|null $badgeInfo
  345.      * @return $this
  346.      * @throws Exception
  347.      */
  348.     public function setBadgeInfo(?object $badgeInfo): self
  349.     {
  350.         $this->badgeInfo HelperFunctions::setStdDefaults((object)$badgeInfo, (array) $this->getBadgeInfo());
  351.         return $this;
  352.     }
  353.     /**
  354.      * @return ArrayCollection<int, Role>|Role[]
  355.      */
  356.     public function getRoles(): Collection
  357.     {
  358.         return $this->roles;
  359.     }
  360.     public function addRole(Role $role): self
  361.     {
  362.         if (!$this->roles->contains($role)) {
  363.             $this->roles[] = $role;
  364.             $role->setAccount($this);
  365.         }
  366.         return $this;
  367.     }
  368.     public function removeRole(Role $role): self
  369.     {
  370.         if ($this->roles->removeElement($role)) {
  371.             // set the owning side to null (unless already changed)
  372.             if ($role->getAccount() === $this) {
  373.                 $role->setAccount(null);
  374.             }
  375.         }
  376.         return $this;
  377.     }
  378.     /**
  379.      * @return Collection<int, Zone>
  380.      */
  381.     public function getZones(): Collection
  382.     {
  383.         return $this->zones;
  384.     }
  385.     public function addZone(Zone $zone): self
  386.     {
  387.         if (!$this->zones->contains($zone)) {
  388.             $this->zones[] = $zone;
  389.             $zone->setAccount($this);
  390.         }
  391.         return $this;
  392.     }
  393.     public function removeZone(Zone $zone): self
  394.     {
  395.         if ($this->zones->removeElement($zone)) {
  396.             // set the owning side to null (unless already changed)
  397.             if ($zone->getAccount() === $this) {
  398.                 $zone->setAccount(null);
  399.             }
  400.         }
  401.         return $this;
  402.     }
  403.     /**
  404.      * @return Collection<int, GwocDomain>
  405.      */
  406.     public function getGwocDomains(): Collection
  407.     {
  408.         return $this->gwocDomains;
  409.     }
  410.     public function addGwocDomain(GwocDomain $gwocDomain): self
  411.     {
  412.         if (!$this->gwocDomains->contains($gwocDomain)) {
  413.             $this->gwocDomains[] = $gwocDomain;
  414.             $gwocDomain->setAccount($this);
  415.         }
  416.         return $this;
  417.     }
  418.     public function removeGwocDomain(GwocDomain $gwocDomain): self
  419.     {
  420.         if ($this->gwocDomains->removeElement($gwocDomain)) {
  421.             // set the owning side to null (unless already changed)
  422.             if ($gwocDomain->getAccount() === $this) {
  423.                 $gwocDomain->setAccount(null);
  424.             }
  425.         }
  426.         return $this;
  427.     }
  428.     public function getUsers(?string $type null): array
  429.     {
  430.         if (empty($type) || !in_array($typeUser::TYPE)) {
  431.             $criteria Criteria::expr()->eq('status'self::STATUS['active']);
  432.         } else {
  433.             $criteria Criteria::expr()->andX(
  434.                 Criteria::expr()->eq('type'$type),
  435.                 Criteria::expr()->eq('status'self::STATUS['active'])
  436.             );
  437.         }
  438.         return array_values($this->users->matching(Criteria::create()->where($criteria))->toArray());
  439.     }
  440.     /**
  441.      * @SA\SerializedName("users")
  442.      * @SA\Groups({"account_search"})
  443.      */
  444.     public function getInteractiveUsers(): array
  445.     {
  446.         return $this->getUsers(User::TYPE['interactive']);
  447.     }
  448.     /**
  449.      * @SA\Groups({"account_general"})
  450.      * @return string|null
  451.      * @throws Exception
  452.      */
  453.     public function getBadgeHash(): ?string
  454.     {
  455.         if (!$this->getBadgeInfo()->enabled) {
  456.             return null;
  457.         }
  458.         $encoder = new Idfuscator('account_badge');
  459.         return $encoder->encode($this->getId(), 0);
  460.     }
  461.     /**
  462.      * @return DateTimeInterface|null
  463.      * @SA\Groups({"account_details"})
  464.      */
  465.     public function getRunoutCreated(): ?DateTimeInterface
  466.     {
  467.         return is_object($this->runout) ? $this->runout->getCreated() : null;
  468.     }
  469.     /**
  470.      * @return float|null
  471.      * @SA\Groups({"account_details"})
  472.      */
  473.     public function getRunoutBalance(): ?float
  474.     {
  475.         return is_object($this->runout) ? $this->runout->getRunout() : null;
  476.     }
  477.     /**
  478.      * @return string|null
  479.      * @SA\Groups({"account_details"})
  480.      */
  481.     public function getRunoutLock(): ?string
  482.     {
  483.         if (is_null($this->runout)) {
  484.             return null;
  485.         }
  486.         $runoutTime $this->runout->getCreated()->getTimestamp() + self::RUNOUT_LOCK_TIME;
  487.         if ($runoutTime time()) {
  488.             return self::RUNOUT_LOCK['account'];
  489.         }
  490.         return self::RUNOUT_LOCK['dashboard'];
  491.     }
  492.     /**
  493.      * @return mixed
  494.      * @SA\Groups({"account_details"})
  495.      */
  496.     public function getTransactionAmount(): ?float
  497.     {
  498.         return round($this->transactionAmount6);
  499.     }
  500.     /**
  501.      * @param mixed $transactionAmount
  502.      */
  503.     public function setTransactionAmount(?float $transactionAmount): self
  504.     {
  505.         $this->transactionAmount $transactionAmount;
  506.         return $this;
  507.     }
  508.     /**
  509.      * @return Transaction[]|ArrayCollection
  510.      */
  511.     public function getTransactions(): Collection
  512.     {
  513.         return $this->transactions;
  514.     }
  515.     /**
  516.      * @param Transaction[]|ArrayCollection $transactions
  517.      * @return Account
  518.      */
  519.     public function setTransactions(Collection $transactions)
  520.     {
  521.         $this->transactions $transactions;
  522.         return $this;
  523.     }
  524.     /**
  525.      * @return float
  526.      * @SA\Groups({"account_details"})
  527.      */
  528.     public function getTrafficAmount(): ?float
  529.     {
  530.         return $this->trafficAmount;
  531.     }
  532.     /**
  533.      * @return float
  534.      * @SA\Groups({"account_details"})
  535.      */
  536.     public function getBalance(): ?float
  537.     {
  538.         return $this->balance;
  539.     }
  540.     /**
  541.      * @return bool
  542.      * @SA\Groups({"account_details"})
  543.      * @SA\SerializedName("has_traffic")
  544.      */
  545.     public function hasTraffic(): bool
  546.     {
  547.         return isset($this->trafficData[0]['cost']);
  548.     }
  549.     public function fetchTrafficData(): void
  550.     {
  551.         if (is_null($this->id)) {
  552.             throw new RuntimeException('Cannot fetch traffic data for non-existent account');
  553.         }
  554.         $invoker InvokerFactory::get('traffic_local_copy');
  555.         $this->trafficData $invoker->query('SELECT account_id, sumMerge(cost) AS cost FROM cluster_account_balance WHERE account_id = :account_id GROUP BY account_id', ['account_id' => $this->id]);
  556.         $this->trafficAmount round(($this->trafficData[0]['cost'] ?? 0) / 10000006);
  557.         if (is_null($this->transactionAmount)) {
  558.             throw new TransactionAmountException();
  559.         }
  560.         $this->balance $this->transactionAmount $this->trafficAmount;
  561.         $this->hasTraffic true;
  562.     }
  563.     public function setOwnerId(int $ownerId)
  564.     {
  565.         $this->ownerId $ownerId;
  566.     }
  567.     /**
  568.      * @return int
  569.      * @SA\Groups({"account_details"})
  570.      */
  571.     public function getOwnerId(): int
  572.     {
  573.         return $this->ownerId;
  574.     }
  575. }