Covivo/mobicoop

View on GitHub
api/src/Gratuity/Service/GratuityCampaignManager.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

/**
 * Copyright (c) 2023, MOBICOOP. All rights reserved.
 * This project is dual licensed under AGPL and proprietary licence.
 ***************************
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as
 *    published by the Free Software Foundation, either version 3 of the
 *    License, or (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <gnu.org/licenses>.
 ***************************
 *    Licence MOBICOOP described in the file
 *    LICENSE
 */

namespace App\Gratuity\Service;

use App\Geography\Repository\TerritoryRepository;
use App\Gratuity\Entity\GratuityCampaign as EntityGratuityCampaign;
use App\Gratuity\Entity\GratuityNotification;
use App\Gratuity\Repository\GratuityCampaignNotificationRepository;
use App\Gratuity\Repository\GratuityCampaignRepository;
use App\Gratuity\Resource\GratuityCampaign;
use App\User\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;

/**
 * @author Maxime Bardot <maxime.bardot@mobicoop.org>
 */
class GratuityCampaignManager
{
    private const GRATUITY_DISABLED = 'Gratuity disabled on this instance';
    private $_entityManager;
    private $_territoryRepository;
    private $_gratuityCampaignRepository;
    private $_gratuityCampaignNotificationRepository;

    /**
     * @var User
     */
    private $_user;
    private $_gratuityCampaignActive;

    public function __construct(
        EntityManagerInterface $entityManager,
        Security $security,
        TerritoryRepository $territoryRepository,
        GratuityCampaignRepository $gratuityCampaignRepository,
        GratuityCampaignNotificationRepository $gratuityCampaignNotificationRepository,
        bool $gratuityCampaignActive
    ) {
        $this->_entityManager = $entityManager;
        $this->_territoryRepository = $territoryRepository;
        $this->_gratuityCampaignRepository = $gratuityCampaignRepository;
        $this->_gratuityCampaignNotificationRepository = $gratuityCampaignNotificationRepository;
        $this->_user = $security->getToken()->getUser();
        $this->_gratuityCampaignActive = $gratuityCampaignActive;
    }

    public function createGratuityCampaign(GratuityCampaign $gratuityCampaign): ?GratuityCampaign
    {
        if (!$this->_isGratuityActive()) {
            throw new \LogicException(self::GRATUITY_DISABLED);
        }

        $entity = $this->_buildEntityGratuityCampaign($gratuityCampaign);
        $entity->setUser($this->_user);
        $entity->setStatus(EntityGratuityCampaign::STATUS_ACTIVE);

        $this->_entityManager->persist($entity);
        $this->_entityManager->flush();

        return $this->_buildGratuityCampaignFromEntity($entity);
    }

    public function getGratuityCampaign(int $gratuityCampaignId): ?GratuityCampaign
    {
        if (!$this->_isGratuityActive()) {
            throw new \LogicException(self::GRATUITY_DISABLED);
        }

        if ($entity = $this->_gratuityCampaignRepository->find($gratuityCampaignId)) {
            return $this->_buildGratuityCampaignFromEntity($entity);
        }

        return null;
    }

    /**
     * @return GratuityCampaign[]
     */
    public function getGratuityCampaigns(): ?array
    {
        if (!$this->_isGratuityActive()) {
            throw new \LogicException(self::GRATUITY_DISABLED);
        }

        $campaigns = [];
        if ($entities = $this->_gratuityCampaignRepository->findAll()) {
            foreach ($entities as $entity) {
                $campaigns[] = $this->_buildGratuityCampaignFromEntity($entity);
            }
        }

        return $campaigns;
    }

    public function tagAsNotified(int $campaignId): ?GratuityCampaign
    {
        if (!$this->_isGratuityActive()) {
            return null;
        }

        if ($entity = $this->_gratuityCampaignRepository->find($campaignId)) {
            $notifications = $this->_getExistingNotification($entity);
            if (count($notifications) > 0) {
                $this->_tagExistingNotificationAsSeen($notifications[0]);
            } else {
                $this->_tagNewExistingNotificationAsSeen($entity);
            }

            $gratuityCampaign = $this->_buildGratuityCampaignFromEntity($entity);
            $gratuityCampaign->setNotifiedForThisUser(true);

            return $gratuityCampaign;
        }

        return null;
    }

    private function _isGratuityActive()
    {
        return $this->_user->hasGratuity() && $this->_gratuityCampaignActive;
    }

    private function _tagNewExistingNotificationAsSeen(EntityGratuityCampaign $gratuityCampaign)
    {
        $notification = new GratuityNotification();
        $notification->setUser($this->_user);
        $notification->setGratuityCampaign($gratuityCampaign);
        $notification->setNotifiedDate(new \DateTime('now'));
        $gratuityCampaign->addGratuityNotification($notification);

        $this->_entityManager->persist($gratuityCampaign);
        $this->_entityManager->flush();
    }

    private function _tagExistingNotificationAsSeen(GratuityNotification $notification)
    {
        $notification->setNotifiedDate(new \DateTime('now'));
        $this->_entityManager->persist($notification);
        $this->_entityManager->flush();
    }

    private function _getExistingNotification(EntityGratuityCampaign $gratuityCampaign): array
    {
        return $this->_gratuityCampaignNotificationRepository->findBy(['user' => $this->_user, 'gratuityCampaign' => $gratuityCampaign]);
    }

    private function _buildEntityGratuityCampaign(GratuityCampaign $gratuityCampaign): EntityGratuityCampaign
    {
        $entity = new EntityGratuityCampaign();
        $entity->setId($gratuityCampaign->getId());
        $entity->setName($gratuityCampaign->getName());
        $entity->setUser($gratuityCampaign->getUser());
        $entity->setTemplate($gratuityCampaign->getTemplate());
        $entity->setStatus($gratuityCampaign->getStatus());
        $entity->setStartDate($gratuityCampaign->getStartDate());
        $entity->setEndDate($gratuityCampaign->getEndDate());

        foreach ($gratuityCampaign->getTerritories() as $territoryId) {
            if (is_numeric($territoryId) && $territory = $this->_territoryRepository->find($territoryId)) {
                $entity->addTerritory($territory);
            }
        }

        return $entity;
    }

    private function _buildGratuityCampaignFromEntity(EntityGratuityCampaign $entity): GratuityCampaign
    {
        $gratuityCampaign = new GratuityCampaign();
        $gratuityCampaign->setId($entity->getId());
        $gratuityCampaign->setName($entity->getName());
        $gratuityCampaign->setUser($entity->getUser());
        $gratuityCampaign->setTemplate($entity->getTemplate());
        $gratuityCampaign->setStatus($entity->getStatus());
        $gratuityCampaign->setStartDate($entity->getStartDate());
        $gratuityCampaign->setEndDate($entity->getEndDate());
        $gratuityCampaign->setCreatedDate($entity->getCreatedDate());
        $gratuityCampaign->setUpdatedDate($entity->getUpdatedDate());

        $gratuityCampaign->setTerritories([]);
        foreach ($entity->getTerritories() as $territory) {
            $gratuityCampaign->pushTerritory($territory->getId());
        }

        return $gratuityCampaign;
    }
}