Commit c7e8f7af authored by Stephane Bouvry's avatar Stephane Bouvry
Browse files

FIX : Les projets vides sont maintenant proposés dans la recherche des projets...

FIX : Les projets vides sont maintenant proposés dans la recherche des projets dans l'écran de modification d'un projet d'une activité
FIX : L'acronyme du projet est affiché dans l'écran de selection en plus de l'intitulé
UP : Le nombre d'activité du projet est affiché dans le selecteur de projet
parent 50886ac5
Loading
Loading
Loading
Loading
Loading
+123 −88
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
 *
 * @copyright Certic (c) 2015
 */

namespace Oscar\Controller;

use BjyAuthorize\Exception\UnAuthorizedException;
@@ -82,9 +83,11 @@ class ProjectController extends AbstractOscarController

    protected function htmlProjectDetail($project)
    {
        $view = new ViewModel([
        $view = new ViewModel(
            [
                'project' => $project
        ]);
            ]
        );
        $view->setTerminal(true);
        $view->setTemplate('/oscar/project/details');

@@ -169,14 +172,9 @@ class ProjectController extends AbstractOscarController

    public function emptyAction()
    {
        $projects = $this->getProjectService()->getBaseQuery()
            ->where('g.id IS NULL');
        $orderBy = $this->params()->fromQuery('sort', 'p.dateUpdated');
        $projects->orderBy($orderBy, 'DESC');


        $projects = $this->getProjectService()->getEmptyProject();
        return array(
            'projects' => $projects->getQuery()->getResult(),
            'projects' => $projects,
            'search' => '',
        );
    }
@@ -188,7 +186,6 @@ class ProjectController extends AbstractOscarController
     */
    public function newAction()
    {

        // Récupération de/des activités à associer
        $activitiesIds = $this->params()->fromQuery('ids', null);
        $activities = [];
@@ -204,8 +201,13 @@ class ProjectController extends AbstractOscarController
            }

            foreach ($activities as $activity) {
                if( !$this->getOscarUserContextService()->hasPrivileges(Privileges::ACTIVITY_CHANGE_PROJECT, $activity) ){
                    throw new UnAuthorizedException(_("Vous n'avez les les droits suffisant pour modifier le projet de l'activité '%s'", $activity));
                if (!$this->getOscarUserContextService()->hasPrivileges(
                    Privileges::ACTIVITY_CHANGE_PROJECT,
                    $activity
                )) {
                    throw new UnAuthorizedException(
                        _("Vous n'avez les les droits suffisant pour modifier le projet de l'activité '%s'", $activity)
                    );
                }
                $activities[] = $activity;
            }
@@ -232,9 +234,15 @@ class ProjectController extends AbstractOscarController
            }

            // Liste des organisations de l'utilisateur
            $organizations = $this->getOscarUserContextService()->getCurrentUserOrganisationWithPrivilege(Privileges::PROJECT_CREATE);
            $organizations = $this->getOscarUserContextService()->getCurrentUserOrganisationWithPrivilege(
                Privileges::PROJECT_CREATE
            );

            foreach ($this->getEntityManager()->getRepository(OrganizationRole::class)->findBy(['principal' => true]) as $role) {
            foreach (
                $this->getEntityManager()->getRepository(OrganizationRole::class)->findBy(
                    ['principal' => true]
                ) as $role
            ) {
                if ($role->isPrincipal()) {
                    $organizationRoles[$role->getId()] = $role;
                }
@@ -245,11 +253,9 @@ class ProjectController extends AbstractOscarController
        /** @var Request $request */
        $request = $this->getRequest();
        if ($this->getRequest()->isPost()) {

            $form->setData($request->getPost());

            if ($form->isValid()) {

                $assoDatas = [];

                if ($organizations) {
@@ -264,9 +270,9 @@ class ProjectController extends AbstractOscarController
                        }
                    }

                    if( count($assoDatas) )
                    if (count($assoDatas)) {
                        $organizationRolesError = "";

                    }
                }

                if (!$organizationRolesError) {
@@ -303,11 +309,17 @@ class ProjectController extends AbstractOscarController
                        LogActivity::LEVEL_INCHARGE
                    );

                    $this->flashMessenger()->addSuccessMessage(sprintf("Le projet '%s' a bien été créé.",
                        $entity->log()));
                    $this->flashMessenger()->addSuccessMessage(
                        sprintf(
                            "Le projet '%s' a bien été créé.",
                            $entity->log()
                        )
                    );

                    return $this->redirect()->toRoute('project/show',
                        array('id' => $entity->getId()));
                    return $this->redirect()->toRoute(
                        'project/show',
                        array('id' => $entity->getId())
                    );
                }
            }
        }
@@ -343,13 +355,14 @@ class ProjectController extends AbstractOscarController

        $structures = $this->getEntityManager()->getRepository(OrganizationPerson::class)->createQueryBuilder('s')
            ->where('s.person = :person AND s.role IN(:roles)')
            ->setParameters([
            ->setParameters(
                [
                    'person' => $currentPerson,
                    'roles' => $roles,
            ])
                ]
            )
            ->getQuery()
            ->getResult()
        ;
            ->getResult();


        $projects = [];
@@ -365,16 +378,21 @@ class ProjectController extends AbstractOscarController
            }
            /** @var ProjectPartner $partner */
            foreach ($organizationPerson->getOrganization()->getProjects() as $partner) {
                if( in_array($partner->getRole(), $this->getOscarUserContextService()->getRolesOrganisationLeader()))
                if (in_array($partner->getRole(), $this->getOscarUserContextService()->getRolesOrganisationLeader())) {
                    $projects[$orgaId]['projects'][] = $partner->getProject();
                }
            }
            /** @var ActivityOrganization $activityPartner */
            foreach ($organizationPerson->getOrganization()->getActivities() as $activityPartner) {
                // Cas des activités sans projet
                if( $activityPartner->getActivity()->getProject() && in_array($activityPartner->getRole(), $this->getOscarUserContextService()->getRolesOrganisationLeader()) )
                if ($activityPartner->getActivity()->getProject() && in_array(
                        $activityPartner->getRole(),
                        $this->getOscarUserContextService()->getRolesOrganisationLeader()
                    )) {
                    $projects[$orgaId]['projects'][] = $activityPartner->getActivity()->getProject();
                }
            }
        }

        return [
            'email' => $currentPerson->getEmail(),
@@ -416,11 +434,13 @@ class ProjectController extends AbstractOscarController
            }
        }

        $view = new ViewModel(array(
        $view = new ViewModel(
            array(
                'id' => $id,
                'project' => $entity,
                'form' => $form,
        ));
            )
        );

        $view->setTemplate('oscar/project/new');

@@ -442,10 +462,12 @@ class ProjectController extends AbstractOscarController
            ->getRepository('Oscar\Entity\Project')
            ->getSingle($id, ['ignoreDateMember' => true]);

        $view = new ViewModel(array(
        $view = new ViewModel(
            array(
                'id' => $id,
                'project' => $project
        ));
            )
        );
        $view->setTemplate('oscar/project/managemembers');

        return $view;
@@ -499,12 +521,14 @@ class ProjectController extends AbstractOscarController
        $_SESSION['token_' . $tokenName] = $tokenValue;


        $view = new ViewModel([
        $view = new ViewModel(
            [
                'tokenName' => $tokenName,
                'tokenValue' => $tokenValue,
                'urlCancel' => $this->url()->fromRoute('project/show', ['id' => $projectId]),
                'message' => 'Cette opération va supprimer les partenaires des activités déjà présents dans le projet et déplacer dans le projet les partenaires communs à toutes les activités',
        ]);
            ]
        );
        $view->setTemplate('/oscar/prototype/confirm.phtml');
        return $view;
    }
@@ -531,12 +555,14 @@ class ProjectController extends AbstractOscarController
        $_SESSION['token_' . $tokenName] = $tokenValue;


        $view = new ViewModel([
        $view = new ViewModel(
            [
                'tokenName' => $tokenName,
                'tokenValue' => $tokenValue,
                'urlCancel' => $this->url()->fromRoute('project/show', ['id' => $projectId]),
                'message' => 'Cette opération va supprimer les membres des activités déjà présents dans le projet et déplacer dans le projet les membres communs à toutes les activités',
        ]);
            ]
        );
        $view->setTemplate('/oscar/prototype/confirm.phtml');
        return $view;
    }
@@ -576,7 +602,9 @@ class ProjectController extends AbstractOscarController
    public function searchAction()
    {
        if (!$this->getOscarUserContextService()->hasPrivileges(Privileges::ACTIVITY_CHANGE_PROJECT)) {
            if( !$this->getOscarUserContextService()->hasPrivilegeInOrganizations(Privileges::ACTIVITY_CHANGE_PROJECT) ){
            if (!$this->getOscarUserContextService()->hasPrivilegeInOrganizations(
                Privileges::ACTIVITY_CHANGE_PROJECT
            )) {
                return $this->getResponseUnauthorized("Vous n'avez pas accès à la liste des projets.");
            }
        }
@@ -591,10 +619,11 @@ class ProjectController extends AbstractOscarController
            'datas' => []
        ];

        /** @var Project $data */
        foreach ($datas as $data) {
            $json['datas'][] = [
                'id' => $data->getId(),
                'label' => $data->getLabel(),
                'label' => $data->getLabel() . " - " . count($data->getActivities()) . " activité(s)",
                'acronym' => $data->getAcronym(),
                'description' => $data->getDescription(),
            ];
@@ -627,10 +656,12 @@ class ProjectController extends AbstractOscarController

        $organisation = $qb->getQuery()->execute(array('id' => $id));

        $viewModel = new ViewModel(array(
        $viewModel = new ViewModel(
            array(
                'organization' => $organisation[0],
                'projects' => $organisation[0]->getProjects(),
        ));
            )
        );
        $viewModel->setTemplate('oscar/project/search');

        return $viewModel;
@@ -653,15 +684,19 @@ class ProjectController extends AbstractOscarController
            ->orderBy('pj.dateCreated', 'DESC')
            ->where('p.id = :id');

        $person = $qb->getQuery()->setParameter('id',
            $id)->getOneOrNullResult();
        $person = $qb->getQuery()->setParameter(
            'id',
            $id
        )->getOneOrNullResult();
        // $projects = $em->getRepository('Oscar\Entity\Project')->allByPerson($id);

        $viewModel = new ViewModel(array(
        $viewModel = new ViewModel(
            array(
                'person' => $person,
                'search' => '',
                'projects' => $person->getProjectAffectations(),
        ));
            )
        );
        $viewModel->setTemplate('oscar/project/search');

        return $viewModel;
+78 −24
Original line number Diff line number Diff line
@@ -12,13 +12,15 @@ use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\QueryBuilder;

class ProjectRepository extends EntityRepository {
    public function getUserProjects( $userId ){
class ProjectRepository extends EntityRepository
{
    public function getUserProjects($userId)
    {
        return $this->findAll();
    }

    public function getProjectByLabelOrCreate( $label ){

    public function getProjectByLabelOrCreate($label)
    {
        $projects = $this->createQueryBuilder('p')
            ->select('p')
            ->where('p.label = :label')
@@ -35,7 +37,6 @@ class ProjectRepository extends EntityRepository {
        } else {
            return $projects[0];
        }

    }

    public function getByUserEmail($userEmail, $time = 'all')
@@ -80,9 +81,54 @@ class ProjectRepository extends EntityRepository {
        return $query->getQuery()->setParameter('id', $id)->getSingleResult();
    }

    protected function applyOptions( QueryBuilder $query, array $options = null )
    /**
     * @param null $searchExp
     * @return integer[]
     */
    public function getEmptyIds($searchExp = null)
    {
        return array_map(
            'current',
            $this->getQueryBuildEmpty($searchExp)
                ->select('p.id')
                ->getQuery()
                ->getScalarResult()
        );
    }

    /**
     * @param null $searchExp
     * @return Project[]
     */
    public function getEmptyProjects($searchExp = null)
    {
        return $this->getQueryBuildEmpty($searchExp)
            ->select('p')
            ->getQuery()
            ->getResult();
    }

    /**
     * @param null $searchExp
     * @return QueryBuilder
     */
    protected function getQueryBuildEmpty($searchExp = null)
    {
        $qb = $this->createQueryBuilder('p')
            ->leftJoin('p.grants', 'g')
            ->where('g.id IS NULL');

        if ($searchExp) {
            $qb->andWhere('p.label LIKE :exp OR p.description LIKE :exp OR p.acronym LIKE :exp')
                ->setParameter('exp', "%$searchExp%");
        }

        return $qb;
    }


    protected function applyOptions(QueryBuilder $query, array $options = null)
    {
    }

    /**
@@ -96,7 +142,9 @@ class ProjectRepository extends EntityRepository {
        // ignoreDateMember: boolean
        // Filtre les personnes en fonction des dates d'affectations
        if (!(isset($options['ignoreDateMember']) && $options['ignoreDateMember'] === true)) {
            $query->andWhere('(m.dateStart <= :now OR m.dateStart IS NULL) AND (m.dateEnd IS NULL OR m.dateEnd >= :now)');
            $query->andWhere(
                '(m.dateStart <= :now OR m.dateStart IS NULL) AND (m.dateEnd IS NULL OR m.dateEnd >= :now)'
            );
            $query->setParameter('now', new \DateTime());
        }

@@ -149,18 +197,24 @@ class ProjectRepository extends EntityRepository {
    {
        return $this->baseQuery()->where(':member MEMBER OF p.partners')
            ->addOrderBy('p.dateCreated', 'DESC')
            ->getQuery()->execute(array(
            'member'    => $this->getEntityManager()->getRepository('Oscar\Entity\Organization')->find($organizationId)
        ));
            ->getQuery()->execute(
                array(
                    'member' => $this->getEntityManager()->getRepository('Oscar\Entity\Organization')->find(
                        $organizationId
                    )
                )
            );
    }

    public function allByPerson($personId)
    {
        return $this->baseQuery()->where('mp.id = :id')
            ->addOrderBy('p.dateCreated', 'DESC')
            ->getQuery()->execute(array(
            ->getQuery()->execute(
                array(
                    'id' => $personId
        ));
                )
            );
    }

    public function all()
+87 −68
Original line number Diff line number Diff line
@@ -6,13 +6,13 @@
 *
 * @copyright Certic (c) 2015
 */

namespace Oscar\Service;

use Doctrine\DBAL\Exception\ConstraintViolationException;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Query\Expr\Join;
use Monolog\Logger;
use mysql_xdevapi\Exception;
use Oscar\Entity\Activity;
use Oscar\Entity\ActivityOrganization;
use Oscar\Entity\ActivityPerson;
@@ -20,14 +20,11 @@ use Oscar\Entity\ContractDocument;
use Oscar\Entity\Project;
use Oscar\Entity\ProjectMember;
use Oscar\Entity\ProjectPartner;
use Oscar\Entity\ProjectRepository;
use Oscar\Exception\OscarException;
use Oscar\Traits\UseServiceContainer;
use Oscar\Traits\UseServiceContainerTrait;
use Oscar\Utils\UnicaenDoctrinePaginator;
use UnicaenApp\Service\EntityManagerAwareInterface;
use UnicaenApp\Service\EntityManagerAwareTrait;
use UnicaenApp\ServiceManager\ServiceLocatorAwareInterface;
use UnicaenApp\ServiceManager\ServiceLocatorAwareTrait;

/**
 * Cette classe fournit des automatismes liés à la manipulation et la
@@ -40,7 +37,8 @@ class ProjectService implements UseServiceContainer

    use UseServiceContainerTrait;

    public function getServiceLocator(){
    public function getServiceLocator()
    {
        return $this->getServiceContainer();
    }

@@ -55,28 +53,43 @@ class ProjectService implements UseServiceContainer
    /**
     * @return ProjectGrantService
     */
    public function getProjectGrantService(){
    public function getProjectGrantService()
    {
        return $this->getServiceContainer()->get(ProjectGrantService::class);
    }

    /**
     * @return EntityManager
     */
    public function getEntityManager(){
    public function getEntityManager()
    {
        return $this->getServiceContainer()->get(EntityManager::class);
    }

    /**
     * @return ProjectRepository
     */
    public function getProjectRepository()
    {
        return $this->getEntityManager()->getRepository(Project::class);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public function fixMovePartnersToActivities( Project $project, $flush =
    true )
    {
    public function fixMovePartnersToActivities(
        Project $project,
        $flush =
        true
    ) {
        foreach ($project->getActivities() as $activity) {
            /** @var ProjectMember $member */
            foreach ($project->getMembers() as $member) {
                if( !$activity->hasPerson($member->getPerson(),
                    $member->getRole(), $member->getDateStart(),
                        $member->getDateEnd(), false
                if (!$activity->hasPerson(
                    $member->getPerson(),
                    $member->getRole(),
                    $member->getDateStart(),
                    $member->getDateEnd(),
                    false
                )) {
//                    $activityPerson = new ActivityPerson();
//                    //$this->getEntityManager()->persist($activityPerson);
@@ -87,14 +100,13 @@ class ProjectService implements UseServiceContainer
//                        ->setDateEnd($member->getDateEnd());

                    $this->getLogger()->addDebug("Déplacement");

                }

            }
        }
    }

    public function fusion( Project $main, Project $fusionned ){
    public function fusion(Project $main, Project $fusionned)
    {
        echo "Fusion de " . $main->getId() . " " . $fusionned->getId() . " <br />";
        /** @var Activity $activity */
        foreach ($fusionned->getGrants() as $activity) {
@@ -142,16 +154,12 @@ class ProjectService implements UseServiceContainer

        /** @var Activity $activity */
        foreach ($project->getGrants() as $activity) {

            /** @var ActivityPerson $member */
            foreach ($activity->getPersons() as $member) {

                // Déjà présent dans le projet avec le même rôle
                if ($project->hasPerson($member->getPerson(), $member->getRole())) {
                    $this->getEntityManager()->remove($member);
                }

                // On enregistre la distribution
                } // On enregistre la distribution
                else {
                    $personId = $member->getPerson()->getId();
                    $role = $member->getRole();
@@ -205,13 +213,10 @@ class ProjectService implements UseServiceContainer
            // Liste des membres de l'activité
            /** @var ActivityOrganization $partner */
            foreach ($activity->getOrganizations() as $partner) {

                // Déjà présent dans le projet avec le même rôle
                if ($project->hasPartner($partner->getOrganization(), $partner->getRole())) {
                    $this->getEntityManager()->remove($partner);
                }

                // On enregistre la distribution
                } // On enregistre la distribution
                else {
                    $organizationId = $partner->getOrganization()->getId();
                    $role = $partner->getRole();
@@ -260,8 +265,7 @@ class ProjectService implements UseServiceContainer
            ->leftJoin('pr.organization', 'o')
            ->leftJoin('p.grants', 'g')
            ->leftJoin('g.organizations', 'go')
            ->leftJoin('g.persons', 'gp')
        ;
            ->leftJoin('g.persons', 'gp');
        return $queryBuilder;
    }

@@ -304,12 +308,24 @@ class ProjectService implements UseServiceContainer
     */
    public function search($search)
    {
        // IDS des PROJETS
        $idsProject = $this->getProjectGrantService()->searchProject($search);
        $idsProjectsEmpty = $this->getProjectRepository()->getEmptyIds($search);
        $idsProject = array_merge($idsProject, $idsProjectsEmpty);

        return $qb = $this->getBaseQuery()
            ->where('p.id IN (:ids)')
            ->setParameter('ids', $idsProject);
    }

    /**
     * @return Project[]
     */
    public function getEmptyProject()
    {
        return $this->getProjectRepository()->getEmptyProjects();
    }

    /**
     * Liste les projets où une personne est impliquée.
     *
@@ -366,13 +382,16 @@ class ProjectService implements UseServiceContainer
     * @return bool
     * @throws OscarException
     */
    public function deleteProject( Project $project ){
    public function deleteProject(Project $project)
    {
        try {
            $this->getEntityManager()->remove($project);
            $this->getEntityManager()->flush($project);
            return true;
        } catch (ConstraintViolationException $e) {
            throw new OscarException("Ce projet contient encore des activités, vous devez les retirer du projet avant pour pouvoir supprimer ce projet.");
            throw new OscarException(
                "Ce projet contient encore des activités, vous devez les retirer du projet avant pour pouvoir supprimer ce projet."
            );
        } catch (\Exception $e) {
            throw new OscarException(sprintf("Impossible de supprimer le projet %s : %s", $project, $e->getMessage()));
        }
+3 −3
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@
     * @returns {*}
     */
    formatRepoSelection = function (repo) {
        return repo.label || repo.text;
        return repo.acronym + " " + (repo.label || repo.text);
    };

    Initer.ready(function () {