Loading module/Oscar/config/module.config.php +3 −0 Original line number Diff line number Diff line Loading @@ -178,6 +178,9 @@ return array( 'estimatedSpentExport', 'spentList', 'newInStructure', 'searchGlobal', 'searchMine', 'searchOrg', 'signedDocumentSend', 'spentSynthesisActivity', 'personsAccessDeep', Loading module/Oscar/config/routes.yml +22 −6 Original line number Diff line number Diff line Loading @@ -1013,19 +1013,35 @@ contract: defaults: action: personsAccessDeep advancedsearch: search-mine: type: segment options: route: /mes-contrats defaults: action: searchMine search-org: type: segment options: route: /mes-structures defaults: action: searchOrg search-global: type: segment options: route: /advancedsearch route: /recherche defaults: action: advancedSearch action: searchGlobal advancedsearch2: advancedsearch: type: segment options: route: /advancedsearch2 route: /recherche defaults: action: advancedSearch2 action: searchGlobal api: type: segment Loading module/Oscar/src/Oscar/Controller/ProjectGrantController.php +145 −18 Original line number Diff line number Diff line Loading @@ -2755,10 +2755,130 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif return $this->applyAdvancedSearch(); } public function advancedSearch2Action(): array|ViewModel public function searchMineAction(): array|ViewModel { $projectMode = $this->params()->fromQuery('project') == '1' ?? '0'; return $this->advancedSearch2Action('mine', [ 'titleActivity' => $this->oscarText('Mes activités'), 'titleProject' => $this->oscarText('Mes projets'), 'perimeter' => 'mine' ]); } public function searchOrgAction(): array|ViewModel { $projectMode = $this->params()->fromQuery('project') == '1' ?? '0'; $perimeterOptions = $this->organizationsPerimeter = $this->getOscarUserContextService()->getOrganisationsPersonPrincipal( $this->getOscarUserContextService()->getCurrentPerson(), true ); $perimeterDetails = []; $perimeterExclude = []; $perimeterOptions = []; $perimeterDetails = $this->getCurrentPerson()->getOrganizationsAffectations(true); if( $exclude = $this->getRequest()->getQuery('exclude', null) ){ $excluded = explode(',', $exclude); foreach ($perimeterDetails as $org) { if( !in_array($org['id'], $excluded) ){ $perimeterOptions[] = $org['id']; } else { $perimeterExclude[] = $org['id']; } } } return $this->advancedSearch2Action('org', [ 'titleActivity' => $this->oscarText('Activités dans mes structures'), 'titleProject' => $this->oscarText('Projets dans mes structures'), 'perimeter' => 'org', 'perimeterOptions' => $perimeterOptions, 'perimeterDetails' => $perimeterDetails, 'perimeterExclude' => $perimeterExclude, ]); } public function searchGlobalAction(): array|ViewModel { $projectMode = $this->params()->fromQuery('project') == '1' ?? '0'; return $this->advancedSearch2Action('global', [ 'titleActivity' => $this->oscarText('Activités'), 'titleProject' => $this->oscarText('Projets'), 'perimeter' => 'global' ]); } public function advancedSearch2Action(string $perimeter, $viewOptions = []): array|ViewModel { $currentPerson = $this->getOscarUserContextService()->getCurrentPerson(); $projectMode = $this->params()->fromQuery('project') == '1' ?? '0'; $filtersOptions = [ 'perimeter' => $perimeter, ]; foreach ($viewOptions as $key => $value) { $filtersOptions[$key] = $value; } switch ($perimeter) { case 'mine': $route = 'contract/search-mine'; if ($projectMode == '1') { $restricted_ids = $this->getEntityManager()->getRepository(Project::class)->getIdsWithPerson($currentPerson->getId()); } else { $restricted_ids = $this->getProjectGrantService()->getActivityRepository()->getIdsWithPerson($currentPerson->getId()); } break; case 'org': $route = 'contract/search-org'; $organizationPerimeter = $this->getOscarUserContextService()->getOrganisationsPersonPrincipal( $currentPerson, true ); if (count($organizationPerimeter) == 0) { throw new OscarException("Vous n'êtes pas associé à une organisation"); } $include = []; foreach ($viewOptions['perimeterDetails'] as $org) { if( !in_array($org['id'], $viewOptions['perimeterExclude']) ){ $include[] = $org['id']; } } if ($projectMode == '1') { $restricted_ids = $this->getProjectGrantService() ->getProjectRepository() ->getIdsWithOrganizations($include); } else { $restricted_ids = $this->getProjectGrantService() ->getActivityRepository() ->getIdsWithOrganizations($include); } break; default: $route = 'contract/search-global'; $restricted_ids = false; break; } // Type de filtre $filters = $this->getProjectGrantService()->getFiltersAvailables($this->oscarText); $filters = $this->getProjectGrantService()->getFiltersAvailables(); $sorts = [ 'hit' => 'Pertinence de la recherche (textuelle)', Loading @@ -2784,7 +2904,8 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif 'sort' => $this->params()->fromQuery('sort', 'hit'), 'direction' => $this->params()->fromQuery('direction', 'desc'), 'filters' => $this->params()->fromQuery('f', []), 'project' => $this->params()->fromQuery('project') == '1' ?? '0', 'project' => $projectMode, 'restricted_ids' => $restricted_ids, ]; $response = new JsonModel($this->getProjectGrantService()->search2($params)); Loading @@ -2803,19 +2924,20 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif $milestonesType = $this->getProjectGrantSearchService()->getFilterOptionsMilestones(); $milestonesProgressions = ActivityDate::progressLabels(); // Données pour la vue $filtersOptions = [ 'activityTypes' => $this->getActivityTypeService()->getActivityTypesTree(true), $filtersOptions['activityTypes'] = $this->getActivityTypeService()->getActivityTypesTree(true); $filtersOptions['status'] = $this->getAdministrationConfigService()->activityStatusSelect(true, true, false); $filtersOptions['milestones'] = $milestonesType; $filtersOptions['milestonesProgressions'] = $milestonesProgressions; $filtersOptions['rolesPersons'] = $rolesPersons; $filtersOptions['rolesOrganizations'] = $rolesOrganizations; $filtersOptions['filters'] = $filters; $filtersOptions['sorts'] = $sorts; $filtersOptions['directions'] = $directions; //'activityDocumentTypes' => $this->getProjectGrantSearchService()->getFilterOptionsMilestones(), //'countries' => $this->getProjectGrantSearchService()->getFilterOptionsCountries(), 'status' => $this->getAdministrationConfigService()->activityStatusSelect(true, true, false), 'milestones' => $milestonesType, 'milestonesProgressions' => $milestonesProgressions, 'rolesPersons' => $rolesPersons, 'rolesOrganizations' => $rolesOrganizations, 'filters' => $filters, 'sorts' => $sorts, 'directions' => $directions, ]; $urlShow = $this->url()->fromRoute('contract/show', ['id' => '']); $urlShowOrganization = ""; Loading @@ -2829,13 +2951,18 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif $urlShowPerson = $this->url()->fromRoute('person/show', ['id' => '']); } return [ $view = new ViewModel([ 'filtersOptions' => $filtersOptions, 'urlEntryPoint' => $this->url()->fromRoute($route), 'urlShow' => $urlShow, 'urlShowProject' => $urlShowProject, 'urlShowOrganization' => $urlShowOrganization, 'urlShowPerson' => $urlShowPerson, ]; ]); $view->setTemplate('oscar/project-grant/advanced-search2.phtml'); return $view; } /** Loading module/Oscar/src/Oscar/Entity/ActivityRepository.php +20 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,26 @@ use Oscar\Utils\DateTimeUtils; */ class ActivityRepository extends EntityRepository { /** * Retourne la liste des IDS * @param int $personId * @return array */ public function getIdsWithPerson( int $personId) : array { $query = $this->createQueryBuilder('a'); $query->select('a.id') ->leftJoin('a.persons', 'apers') ->leftJoin('apers.person', 'pers1') ->leftJoin('a.project', 'aprj') ->leftJoin('aprj.members', 'pprs') ->leftJoin('pprs.person', 'pers2') ->where('pers1 = :person OR pers2 = :person') ->setParameter('person', $personId); $activities = $query->getQuery()->getResult(); return array_map('current', $activities); } /** * Retourne l'ID des activités qui impliquent une des numérotations données. * Loading module/Oscar/src/Oscar/Entity/Person.php +40 −0 Original line number Diff line number Diff line Loading @@ -455,6 +455,46 @@ class Person implements ResourceInterface return $this->organizations; } public function getOrganizationsAffectations(bool $principal = true) :array { $out = []; /** @var OrganizationPerson $organizationAffectation */ foreach ($this->getOrganizations() as $organizationAffectation) { if( $principal === true && !$organizationAffectation->isPrincipal() ) { continue; } $organization = $organizationAffectation->getOrganization(); $role = $organizationAffectation->getRole(); $this->getSubOrganizationsAffectations($organization, $role, $out); } return $out; } protected function getSubOrganizationsAffectations(Organization $organization, string $role, &$out) { $organizationId = $organization->getId(); $organizationCode = $organization->getCode(); $organizationFullname = $organization->getFullName(); $organizationShortName = $organization->getShortName(); if( !array_key_exists($organizationId, $out)) { $out[$organizationId] = [ 'id' => $organizationId, 'code' => $organizationCode, 'fullname' => $organizationFullname, 'shortname' => $organizationShortName, 'label' => ($organizationCode??'') . ' : ' . $organizationShortName??$organizationFullname, 'roles' => [] ]; } $out[$organizationId]['roles'][] = $role; if($organization->getChildren()){ foreach ($organization->getChildren() as $child) { $this->getSubOrganizationsAffectations($child, $role, $out); } } } /** * @param ArrayCollection $organizations */ Loading Loading
module/Oscar/config/module.config.php +3 −0 Original line number Diff line number Diff line Loading @@ -178,6 +178,9 @@ return array( 'estimatedSpentExport', 'spentList', 'newInStructure', 'searchGlobal', 'searchMine', 'searchOrg', 'signedDocumentSend', 'spentSynthesisActivity', 'personsAccessDeep', Loading
module/Oscar/config/routes.yml +22 −6 Original line number Diff line number Diff line Loading @@ -1013,19 +1013,35 @@ contract: defaults: action: personsAccessDeep advancedsearch: search-mine: type: segment options: route: /mes-contrats defaults: action: searchMine search-org: type: segment options: route: /mes-structures defaults: action: searchOrg search-global: type: segment options: route: /advancedsearch route: /recherche defaults: action: advancedSearch action: searchGlobal advancedsearch2: advancedsearch: type: segment options: route: /advancedsearch2 route: /recherche defaults: action: advancedSearch2 action: searchGlobal api: type: segment Loading
module/Oscar/src/Oscar/Controller/ProjectGrantController.php +145 −18 Original line number Diff line number Diff line Loading @@ -2755,10 +2755,130 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif return $this->applyAdvancedSearch(); } public function advancedSearch2Action(): array|ViewModel public function searchMineAction(): array|ViewModel { $projectMode = $this->params()->fromQuery('project') == '1' ?? '0'; return $this->advancedSearch2Action('mine', [ 'titleActivity' => $this->oscarText('Mes activités'), 'titleProject' => $this->oscarText('Mes projets'), 'perimeter' => 'mine' ]); } public function searchOrgAction(): array|ViewModel { $projectMode = $this->params()->fromQuery('project') == '1' ?? '0'; $perimeterOptions = $this->organizationsPerimeter = $this->getOscarUserContextService()->getOrganisationsPersonPrincipal( $this->getOscarUserContextService()->getCurrentPerson(), true ); $perimeterDetails = []; $perimeterExclude = []; $perimeterOptions = []; $perimeterDetails = $this->getCurrentPerson()->getOrganizationsAffectations(true); if( $exclude = $this->getRequest()->getQuery('exclude', null) ){ $excluded = explode(',', $exclude); foreach ($perimeterDetails as $org) { if( !in_array($org['id'], $excluded) ){ $perimeterOptions[] = $org['id']; } else { $perimeterExclude[] = $org['id']; } } } return $this->advancedSearch2Action('org', [ 'titleActivity' => $this->oscarText('Activités dans mes structures'), 'titleProject' => $this->oscarText('Projets dans mes structures'), 'perimeter' => 'org', 'perimeterOptions' => $perimeterOptions, 'perimeterDetails' => $perimeterDetails, 'perimeterExclude' => $perimeterExclude, ]); } public function searchGlobalAction(): array|ViewModel { $projectMode = $this->params()->fromQuery('project') == '1' ?? '0'; return $this->advancedSearch2Action('global', [ 'titleActivity' => $this->oscarText('Activités'), 'titleProject' => $this->oscarText('Projets'), 'perimeter' => 'global' ]); } public function advancedSearch2Action(string $perimeter, $viewOptions = []): array|ViewModel { $currentPerson = $this->getOscarUserContextService()->getCurrentPerson(); $projectMode = $this->params()->fromQuery('project') == '1' ?? '0'; $filtersOptions = [ 'perimeter' => $perimeter, ]; foreach ($viewOptions as $key => $value) { $filtersOptions[$key] = $value; } switch ($perimeter) { case 'mine': $route = 'contract/search-mine'; if ($projectMode == '1') { $restricted_ids = $this->getEntityManager()->getRepository(Project::class)->getIdsWithPerson($currentPerson->getId()); } else { $restricted_ids = $this->getProjectGrantService()->getActivityRepository()->getIdsWithPerson($currentPerson->getId()); } break; case 'org': $route = 'contract/search-org'; $organizationPerimeter = $this->getOscarUserContextService()->getOrganisationsPersonPrincipal( $currentPerson, true ); if (count($organizationPerimeter) == 0) { throw new OscarException("Vous n'êtes pas associé à une organisation"); } $include = []; foreach ($viewOptions['perimeterDetails'] as $org) { if( !in_array($org['id'], $viewOptions['perimeterExclude']) ){ $include[] = $org['id']; } } if ($projectMode == '1') { $restricted_ids = $this->getProjectGrantService() ->getProjectRepository() ->getIdsWithOrganizations($include); } else { $restricted_ids = $this->getProjectGrantService() ->getActivityRepository() ->getIdsWithOrganizations($include); } break; default: $route = 'contract/search-global'; $restricted_ids = false; break; } // Type de filtre $filters = $this->getProjectGrantService()->getFiltersAvailables($this->oscarText); $filters = $this->getProjectGrantService()->getFiltersAvailables(); $sorts = [ 'hit' => 'Pertinence de la recherche (textuelle)', Loading @@ -2784,7 +2904,8 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif 'sort' => $this->params()->fromQuery('sort', 'hit'), 'direction' => $this->params()->fromQuery('direction', 'desc'), 'filters' => $this->params()->fromQuery('f', []), 'project' => $this->params()->fromQuery('project') == '1' ?? '0', 'project' => $projectMode, 'restricted_ids' => $restricted_ids, ]; $response = new JsonModel($this->getProjectGrantService()->search2($params)); Loading @@ -2803,19 +2924,20 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif $milestonesType = $this->getProjectGrantSearchService()->getFilterOptionsMilestones(); $milestonesProgressions = ActivityDate::progressLabels(); // Données pour la vue $filtersOptions = [ 'activityTypes' => $this->getActivityTypeService()->getActivityTypesTree(true), $filtersOptions['activityTypes'] = $this->getActivityTypeService()->getActivityTypesTree(true); $filtersOptions['status'] = $this->getAdministrationConfigService()->activityStatusSelect(true, true, false); $filtersOptions['milestones'] = $milestonesType; $filtersOptions['milestonesProgressions'] = $milestonesProgressions; $filtersOptions['rolesPersons'] = $rolesPersons; $filtersOptions['rolesOrganizations'] = $rolesOrganizations; $filtersOptions['filters'] = $filters; $filtersOptions['sorts'] = $sorts; $filtersOptions['directions'] = $directions; //'activityDocumentTypes' => $this->getProjectGrantSearchService()->getFilterOptionsMilestones(), //'countries' => $this->getProjectGrantSearchService()->getFilterOptionsCountries(), 'status' => $this->getAdministrationConfigService()->activityStatusSelect(true, true, false), 'milestones' => $milestonesType, 'milestonesProgressions' => $milestonesProgressions, 'rolesPersons' => $rolesPersons, 'rolesOrganizations' => $rolesOrganizations, 'filters' => $filters, 'sorts' => $sorts, 'directions' => $directions, ]; $urlShow = $this->url()->fromRoute('contract/show', ['id' => '']); $urlShowOrganization = ""; Loading @@ -2829,13 +2951,18 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif $urlShowPerson = $this->url()->fromRoute('person/show', ['id' => '']); } return [ $view = new ViewModel([ 'filtersOptions' => $filtersOptions, 'urlEntryPoint' => $this->url()->fromRoute($route), 'urlShow' => $urlShow, 'urlShowProject' => $urlShowProject, 'urlShowOrganization' => $urlShowOrganization, 'urlShowPerson' => $urlShowPerson, ]; ]); $view->setTemplate('oscar/project-grant/advanced-search2.phtml'); return $view; } /** Loading
module/Oscar/src/Oscar/Entity/ActivityRepository.php +20 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,26 @@ use Oscar\Utils\DateTimeUtils; */ class ActivityRepository extends EntityRepository { /** * Retourne la liste des IDS * @param int $personId * @return array */ public function getIdsWithPerson( int $personId) : array { $query = $this->createQueryBuilder('a'); $query->select('a.id') ->leftJoin('a.persons', 'apers') ->leftJoin('apers.person', 'pers1') ->leftJoin('a.project', 'aprj') ->leftJoin('aprj.members', 'pprs') ->leftJoin('pprs.person', 'pers2') ->where('pers1 = :person OR pers2 = :person') ->setParameter('person', $personId); $activities = $query->getQuery()->getResult(); return array_map('current', $activities); } /** * Retourne l'ID des activités qui impliquent une des numérotations données. * Loading
module/Oscar/src/Oscar/Entity/Person.php +40 −0 Original line number Diff line number Diff line Loading @@ -455,6 +455,46 @@ class Person implements ResourceInterface return $this->organizations; } public function getOrganizationsAffectations(bool $principal = true) :array { $out = []; /** @var OrganizationPerson $organizationAffectation */ foreach ($this->getOrganizations() as $organizationAffectation) { if( $principal === true && !$organizationAffectation->isPrincipal() ) { continue; } $organization = $organizationAffectation->getOrganization(); $role = $organizationAffectation->getRole(); $this->getSubOrganizationsAffectations($organization, $role, $out); } return $out; } protected function getSubOrganizationsAffectations(Organization $organization, string $role, &$out) { $organizationId = $organization->getId(); $organizationCode = $organization->getCode(); $organizationFullname = $organization->getFullName(); $organizationShortName = $organization->getShortName(); if( !array_key_exists($organizationId, $out)) { $out[$organizationId] = [ 'id' => $organizationId, 'code' => $organizationCode, 'fullname' => $organizationFullname, 'shortname' => $organizationShortName, 'label' => ($organizationCode??'') . ' : ' . $organizationShortName??$organizationFullname, 'roles' => [] ]; } $out[$organizationId]['roles'][] = $role; if($organization->getChildren()){ foreach ($organization->getChildren() as $child) { $this->getSubOrganizationsAffectations($child, $role, $out); } } } /** * @param ArrayCollection $organizations */ Loading