Commit 1087aca8 authored by Stephane Bouvry's avatar Stephane Bouvry
Browse files

Fix : les notifications pour les versements se caclulent correctement (les...

Fix : les notifications pour les versements se caclulent correctement (les personnes n'étaient pas inscrites)
parent 57cf6e2b
Loading
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -48,11 +48,22 @@ class ActivityPayment implements ITrackable
            self::getStatusPayments()[$this->getStatus()] : '';
    }

    public function getDateRef()
    {
        if( $this->getStatus() == self::STATUS_PREVISIONNEL ){
            return $this->getDatePredicted() ? $this->getDatePredicted()->format('Y-m-d') : 'No Date';
        }
        if( $this->getStatus() == self::STATUS_REALISE ){
            return $this->getDatePayment() ? $this->getDatePayment()->format('Y-m-d') : 'No Date';
        }
        return '???';
    }

    public function __toString()
    {
        return sprintf("Versement %s de %s%s",
        return sprintf("Versement %s de %s %s (%s)",
            self::getStatusPayments()[$this->getStatus()],
            $this->getAmount(), $this->getCurrency()
            $this->getAmount(), $this->getCurrency(), $this->getDateRef()
            );
    }

@@ -283,6 +294,11 @@ class ActivityPayment implements ITrackable
        return $this->getStatus() == self::STATUS_PREVISIONNEL && $this->getDatePredicted() < new \DateTime();
    }

    public function isDone() :bool
    {
        return $this->getStatus() == self::STATUS_REALISE;
    }

    function __construct()
    {
        $this->datePayment = new \DateTime();
+45 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ class Notification
    const OBJECT_ACTIVITY = 'activity';
    const OBJECT_APPLICATION = 'application';
    const OBJECT_TIMESHEET = 'timesheet';
    const OBJECT_PAYMENT = 'payment';
    const OBJECT_MILESTONE = 'milestone';

    // Valeurs par défaut
    const DEFAULT_LEVEL = self::LEVEL_INFO;
@@ -285,12 +287,55 @@ class Notification
        return $this->context;
    }

    private ?string $_contextKey = null;
    private ?int $_contextId = null;

    private function getContextDatas() :array
    {
        if( $this->_contextKey === null ){
            $contextData = explode(":", $this->getContext());
            $this->_contextKey = $contextData[0];
            if( count($contextData) > 1 ){
                $this->_contextId = $contextData[1];
            } else {
                $this->_contextId = null;
            }
        }
        return [
            'key' => $this->_contextKey,
            'id' =>$this->_contextId
        ];
    }

    public function getContextKey() :string
    {
        return $this->getContextDatas()['key'];
    }

    public function getContextId() :?int
    {
        return $this->getContextDatas()['id'];
    }

    public function isPayement() :bool
    {
        return $this->getContextKey() == self::OBJECT_PAYMENT;
    }


    public function getSubscribersIds() :array
    {
        return array_map(function($p) { return $p->getPerson()->getId(); }, $this->getPersons()->toArray());
    }


    /**
     * @param mixed $context
     */
    public function setContext($context)
    {
        $this->context = $context;
        $this->_contextKey = null;

        return $this;
    }
+13 −0
Original line number Diff line number Diff line
@@ -33,6 +33,19 @@ class NotificationRepository extends EntityRepository
        return $qb->getQuery()->getResult();
    }

    public function removeNotificationPersons( int $notificationId, array $personsIds ) :void
    {
        /** @var Notification $notification */
        $notification = $this->getEntityManager()->find(Notification::class, $notificationId);

        /** @var NotificationPerson $notificationPerson */
        foreach ($notification->getPersons() as $notificationPerson) {
            if( in_array($notificationPerson->getPerson()->getId(), $personsIds) ){
                $this->getEntityManager()->remove($notificationPerson);
            }
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// NotificationPerson

+146 −25
Original line number Diff line number Diff line
@@ -243,16 +243,62 @@ class NotificationService implements UseServiceContainer
     * @return mixed
     * @throws OscarException
     */
    public function getRolesIdsWithPersonsIds(Activity $activity)
    public function getRolesIdsWithPersonsIds(Activity $activity): array
    {
        $activityId = $activity->getId();
        $personsService = $this->getPersonService();
        /** @var Person[] $persons Liste des personnes impliquées dans une activité avec leurs rôles cherche en profondeur */
        $persons = $personsService->getAllPersonsWithRolesInActivity($activity);
        $this->_object_roles_persons[$activityId] = $persons;
        if (!array_key_exists($activityId, $this->_object_roles_persons)) {
            $this->_object_roles_persons[$activityId] = $this->getPersonService()->getAllPersonsWithRolesInActivity(
                $activity
            );
        }
        return $this->_object_roles_persons[$activityId];
    }

    /**
     * Retourne la liste des IDS des rôles qui peuvent voir les payements.
     *
     * @return array
     * @throws OscarException
     */
    public function getRolesIdConcernedByPayments(): array
    {
        $rolesAllowPayments = $this->getOscarUserContextService()->getRolesWithPrivileges(
            Privileges::ACTIVITY_PAYMENT_SHOW
        );
        return array_map(
            function ($r) {
                return $r->getId();
            },
            $rolesAllowPayments
        );
    }

    private array $_cacheActivityPayementPersons = [];

    /**
     * Retourne les identifiants des personnes concernées par les payments d'une activité.
     *
     * @param Activity $activity
     * @return array
     * @throws OscarException
     */
    protected function getPersonsIdsConcernedByPaymentInActivity(Activity $activity): array
    {
        $activityId = $activity->getId();
        if (!array_key_exists($activityId, $this->_cacheActivityPayementPersons)) {
            $output = [];
            $idsPersonsRoles = $this->getRolesIdsWithPersonsIds($activity);
            $idsRolesConcerned = $this->getRolesIdConcernedByPayments();
            foreach ($idsPersonsRoles as $roleId => $personsIds) {
                if (in_array($roleId, $idsRolesConcerned)) {
                    $output = array_merge($output, $idsPersonsRoles[$roleId]);
                }
            }
            $this->_cacheActivityPayementPersons[$activityId] = array_unique($output);
        }
        return $this->_cacheActivityPayementPersons[$activityId];
    }


    /**
     * Déclenche l'envoi d'un document lors de l'upload.
@@ -592,6 +638,7 @@ class NotificationService implements UseServiceContainer
    public function updateNotificationsActivity(Activity $activity)
    {
        $this->updateNotificationCore($activity);
        $this->updateNotificationCorePayment($activity);
        $this->updateNotificationsMilestonePersonActivity($activity);
    }

@@ -602,6 +649,65 @@ class NotificationService implements UseServiceContainer
        }
    }

    public function updateNotificationsPayment(Notification $notification): void
    {
        /** @var ActivityPayment $payment */
        $payment = $this->getEntityManager()->getRepository(ActivityPayment::class)->find(
            $notification->getContextId()
        );

        if (!$payment) {
            $this->getLoggerService()->alert("Impossible de mettre à jour les notifications pour le payment ($notification)");
            return;
        }

        if( $payment->isDone() ){
            return;
        }

        // TODO calculer si le payment est eligible aux notifications (date passée, fait, en retard, etc...)


        $haveToSub = $this->getPersonsIdsConcernedByPaymentInActivity($payment->getActivity());
        $this->updateSubscribersToNotification($notification, $haveToSub);
    }


    /**
     * Mise à jour des inscriptions des personnes à la notification.
     *
     * @param Notification $notification
     * @param array $expectedSubscribersIds ID des personnes à inscrire
     */
    protected function updateSubscribersToNotification(Notification $notification, array $expectedSubscribersIds): void
    {
        // identifiants des personnes déjà inscrites
        $alreadySub = $notification->getSubscribersIds();

        // Personnes à retirer
        $subscribeToRemove = array_diff($alreadySub, $expectedSubscribersIds);

        // Personnes à ajouter
        $subscribeToDo = array_diff($expectedSubscribersIds, $alreadySub);

        try {
            foreach ($subscribeToDo as $idPerson) {
                $person = $this->getEntityManager()->getRepository(Person::class)->find($idPerson);
                if (!$person) {
                    continue;
                }
                $subscribe = new NotificationPerson();
                $this->getEntityManager()->persist($subscribe);
                $subscribe->setNotification($notification)->setPerson($person);
            }
            $this->getNotificationRepository()->removeNotificationPersons($notification->getId(), $subscribeToRemove);
            $this->getEntityManager()->flush();
        } catch (\Exception $e) {
            $this->getLoggerService()->alert("Impossible de mettre à jour les notifications dans '$notification'");
        }
    }


    /**
     * @param Activity $activity
     * @param $ignorePast
@@ -618,15 +724,10 @@ class NotificationService implements UseServiceContainer
        // Personnes devant être inscrites
        $idsPersonsRoles = $this->getRolesIdsWithPersonsIds($activity);

        $this->getLoggerService()->debug("Rôles concernées : ");
        foreach ($idsPersonsRoles as $roleId => $personsIds) {
            $this->getLoggerService()->debug(" - rôle '$roleId' : : " . count($personsIds) . " personne(s)");
        }


        $now = (new \DateTime('now'))->modify('-1 month');

        //$na = notification
        /** @var Notification $na */
        foreach ($notificationsActivity as $na) {
            $contextNotification = explode(":", $na->getContext());

@@ -634,11 +735,31 @@ class NotificationService implements UseServiceContainer
                continue;
            }
            //ActivityDate = Jalon donc Milestone (ancienne nomenclature, terminologie métier)
            $idActivityDate = $contextNotification[1];
            $context = $na->getContextKey();
            $contextId = $na->getContextId();

            if ($context == 'payment') {
                try {
                    $this->updateNotificationsPayment($na);
                } catch (\Exception $e) {
                    $this->getLoggerService()->alert(
                        "Un problème est survenu lors de la génération des notifications pour le payment $contextId"
                    );
                }
                continue;
            }

            if ($context != Notification::OBJECT_MILESTONE) {
                continue;
            }

            try {
                $activityDate = $this->getEntityManager()->getRepository(ActivityDate::class)->findOneBy(["id"=>$idActivityDate]);
                $activityDate = $this->getEntityManager()->getRepository(ActivityDate::class)->findOneBy(
                    ["id" => $contextId]
                );
            } catch (\Exception $e) {
                die("idActivityDate : $idActivityDate --- " . $na->getContext());
                $this->getLoggerService()->alert("Problème de génération de notification pour $na : " . $e->getMessage());
                continue;
            }

            if (!$activityDate) {
@@ -650,9 +771,9 @@ class NotificationService implements UseServiceContainer

            // Si pas de rôles on passe directement, pas de calcul de notifications
            if (count($rolesActivityDate) == 0) {
                $this->getLoggerService()->debug(" > Skip (pas de rôles)");
                continue;
            }

            // Si finishable et pas fait
            // TODO
//            if (!$activityDate->isLate()){