diff --git a/.changes/unreleased/Feature-20230606-105153.yaml b/.changes/unreleased/Feature-20230606-105153.yaml deleted file mode 100644 index 00c3ab1da..000000000 --- a/.changes/unreleased/Feature-20230606-105153.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Feature -body: 'Edit saved exports options: the saved exports options (forms, filters, aggregators) - are now editable.' -time: 2023-06-06T10:51:53.331701352+02:00 -custom: - Issue: "110" diff --git a/.changes/unreleased/Feature-20230613-151546.yaml b/.changes/unreleased/Feature-20230613-151546.yaml deleted file mode 100644 index e66076aa5..000000000 --- a/.changes/unreleased/Feature-20230613-151546.yaml +++ /dev/null @@ -1,5 +0,0 @@ -kind: Feature -body: Get an unified list of document in person and accompanying period context -time: 2023-06-13T15:15:46.146899906+02:00 -custom: - Issue: "103" diff --git a/.changes/unreleased/Fixed-20230621-132851.yaml b/.changes/unreleased/Fixed-20230621-132851.yaml deleted file mode 100644 index 89fb7cdd9..000000000 --- a/.changes/unreleased/Fixed-20230621-132851.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Fixed -body: '[Accompanying period comments]: order comments from the most recent to the - oldest, in the list' -time: 2023-06-21T13:28:51.282714011+02:00 -custom: - Issue: "" diff --git a/.changes/unreleased/Fixed-20230621-135912.yaml b/.changes/unreleased/Fixed-20230621-135912.yaml deleted file mode 100644 index 676d1c21b..000000000 --- a/.changes/unreleased/Fixed-20230621-135912.yaml +++ /dev/null @@ -1,5 +0,0 @@ -kind: Fixed -body: 'Api: filter social action to keep only the currently activated' -time: 2023-06-21T13:59:12.57760217+02:00 -custom: - Issue: "" diff --git a/.changes/unreleased/Fixed-20230621-141828.yaml b/.changes/unreleased/Fixed-20230621-141828.yaml deleted file mode 100644 index 2c7f94488..000000000 --- a/.changes/unreleased/Fixed-20230621-141828.yaml +++ /dev/null @@ -1,5 +0,0 @@ -kind: Fixed -body: Fix deletion and re-creation of filiation relationship -time: 2023-06-21T14:18:28.437876316+02:00 -custom: - Issue: "82" diff --git a/.changes/v2.2.2.md b/.changes/v2.2.2.md new file mode 100644 index 000000000..61d194b6d --- /dev/null +++ b/.changes/v2.2.2.md @@ -0,0 +1,5 @@ +## v2.2.2 - 2023-06-26 +### Fixed +* [Accompanying period comments]: order comments from the most recent to the oldest, in the list +* Api: filter social action to keep only the currently activated +* ([#82](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/82)) Fix deletion and re-creation of filiation relationship diff --git a/.changes/v2.3.0.md b/.changes/v2.3.0.md new file mode 100644 index 000000000..827a338de --- /dev/null +++ b/.changes/v2.3.0.md @@ -0,0 +1,42 @@ +## v2.3.0 - 2023-06-27 +### Feature +* ([#110](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/110)) Edit saved exports options: the saved exports options (forms, filters, aggregators) are now editable. +* ([#103](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/103)) Get an unified list of document in person and accompanying period context +* [export] Set the default date of calculation of the accompanying period's list as "today" +* Force accompanying period user history to be unique for the same period and stardate/enddate [:warning: may encounter migration issue] + + If some issue is encountered during migration, use this SQL to find the line which are in conflict, examine the problem and delete some of the concerning line +* + ```sql + -- to see the line which are in conflict with another one + SELECT o.* + FROM chill_person_accompanying_period_user_history o + JOIN chill_person_accompanying_period_user_history c ON o.id < c.id AND o.accompanyingperiod_id = c.accompanyingperiod_id + WHERE tsrange(o.startdate, o.enddate, '[)') && tsrange(c.startdate, c.enddate, '[)') + ORDER BY accompanyingperiod_id; + -- to examine line in conflict for a given accompanyingperiod_id (given by the previous query) + SELECT * FROM chill_person_accompanying_period_user_history WHERE accompanyingperiod_id = IIIIDDDD order by startdate, enddate; + ``` +* Rename label of filter in French: "parcours actif" => "parcours ouvert", and "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture" + +### Traduction francophone des principaux changements + +* Les exports enregistrés sont éditables par l'utilisateur; +* L'onglet "Document" dans les parcours et les dossiers d'usager affiche désormais les documents ajoutés à différents endroits. + + Pour les parcours, il s'agit de: + + - documents ajoutés directement dans le parcours; + - documents des échanges; + - documents des rendez-vous; + - documents des évaluations; + - documents directement ajoutés dans le dossier des usagers concernés par le parcours; + + Pour les usagers, il s'agit de: + + - documents des échanges; + - documents des parcours; + - documents des rendez-vous; + - documents des actions, des échanges, des rendez-vous, des évaluations ajoutés dans les parcours. +* Dans la liste des parcours, la date de calcul des éléments associés est "aujourd'hui" par défaut. +* Dans les exports, renommage des libellés des filtres: "parcours actif" => "parcours ouvert", et "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture" diff --git a/.changie.yaml b/.changie.yaml index ba5454ce7..8a25ed695 100644 --- a/.changie.yaml +++ b/.changie.yaml @@ -5,8 +5,11 @@ changelogPath: CHANGELOG.md versionExt: md versionFormat: '## {{.Version}} - {{.Time.Format "2006-01-02"}}' kindFormat: '### {{.Kind}}' +# Note: it is possible to add a `.custom.Long` text manually into the yaml file produced by `changie new`. This will add a long description. changeFormat: >- - * {{ if not (eq .Custom.Issue "") }}([#{{ .Custom.Issue }}](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/{{ .Custom.Issue }})) {{ end }}{{.Body}} + * {{ if not (eq .Custom.Issue "") }}([#{{ .Custom.Issue }}](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/{{ .Custom.Issue }})) {{ end }}{{.Body}} {{ if not (eq .Custom.Long "") }} + + {{ .Custom.Long }}{{ end }} custom: - key: Issue label: Issue number (on chill-bundles repository) (optional) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3f1d75ed5..aa1eff8b1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,6 +34,7 @@ variables: stages: - Composer install - Tests + - Deploy build: stage: Composer install @@ -121,3 +122,14 @@ unit_tests: paths: - bin - tests/app/vendor/ + +release: + stage: Deploy + image: registry.gitlab.com/gitlab-org/release-cli:latest + rules: + - if: $CI_COMMIT_TAG + script: + - echo "running release_job" + release: + tag_name: '$CI_COMMIT_TAG' + description: "./.changes/v$CI_COMMIT_TAG.md" diff --git a/CHANGELOG.md b/CHANGELOG.md index e223fa116..93ff93556 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,55 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), and is generated by [Changie](https://github.com/miniscruff/changie). +## v2.3.0 - 2023-06-27 +### Feature +* ([#110](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/110)) Edit saved exports options: the saved exports options (forms, filters, aggregators) are now editable. +* ([#103](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/103)) Get an unified list of document in person and accompanying period context +* [export] Set the default date of calculation of the accompanying period's list as "today" +* Force accompanying period user history to be unique for the same period and stardate/enddate [:warning: may encounter migration issue] + + If some issue is encountered during migration, use this SQL to find the line which are in conflict, examine the problem and delete some of the concerning line +* + ```sql + -- to see the line which are in conflict with another one + SELECT o.* + FROM chill_person_accompanying_period_user_history o + JOIN chill_person_accompanying_period_user_history c ON o.id < c.id AND o.accompanyingperiod_id = c.accompanyingperiod_id + WHERE tsrange(o.startdate, o.enddate, '[)') && tsrange(c.startdate, c.enddate, '[)') + ORDER BY accompanyingperiod_id; + -- to examine line in conflict for a given accompanyingperiod_id (given by the previous query) + SELECT * FROM chill_person_accompanying_period_user_history WHERE accompanyingperiod_id = IIIIDDDD order by startdate, enddate; + ``` +* Rename label of filter in French: "parcours actif" => "parcours ouvert", and "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture" + +### Traduction francophone des principaux changements + +* Les exports enregistrés sont éditables par l'utilisateur; +* L'onglet "Document" dans les parcours et les dossiers d'usager affiche désormais les documents ajoutés à différents endroits. + + Pour les parcours, il s'agit de: + + - documents ajoutés directement dans le parcours; + - documents des échanges; + - documents des rendez-vous; + - documents des évaluations; + - documents directement ajoutés dans le dossier des usagers concernés par le parcours; + + Pour les usagers, il s'agit de: + + - documents des échanges; + - documents des parcours; + - documents des rendez-vous; + - documents des actions, des échanges, des rendez-vous, des évaluations ajoutés dans les parcours. +* Dans la liste des parcours, la date de calcul des éléments associés est "aujourd'hui" par défaut. +* Dans les exports, renommage des libellés des filtres: "parcours actif" => "parcours ouvert", et "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture" + +## v2.2.2 - 2023-06-26 +### Fixed +* [Accompanying period comments]: order comments from the most recent to the oldest, in the list +* Api: filter social action to keep only the currently activated +* ([#82](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/82)) Fix deletion and re-creation of filiation relationship + ## v2.2.1 - 2023-06-19 ### Fixed * ([#114](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/114)) [notification on document evaluation] fix entityId and return path when adding a notification on a document in an evaluation diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/PersonDocumentGenericDocProvider.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/PersonDocumentGenericDocProvider.php index 08a0df960..613f8d758 100644 --- a/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/PersonDocumentGenericDocProvider.php +++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/PersonDocumentGenericDocProvider.php @@ -12,14 +12,16 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\GenericDoc\Providers; use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; +use Chill\DocStoreBundle\GenericDoc\GenericDocForAccompanyingPeriodProviderInterface; use Chill\DocStoreBundle\GenericDoc\GenericDocForPersonProviderInterface; use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface; use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter; +use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; use DateTimeImmutable; use Symfony\Component\Security\Core\Security; -final readonly class PersonDocumentGenericDocProvider implements GenericDocForPersonProviderInterface +final readonly class PersonDocumentGenericDocProvider implements GenericDocForPersonProviderInterface, GenericDocForAccompanyingPeriodProviderInterface { public const KEY = 'person_document'; @@ -48,4 +50,16 @@ final readonly class PersonDocumentGenericDocProvider implements GenericDocForPe { return $this->security->isGranted(PersonDocumentVoter::SEE, $person); } + + public function buildFetchQueryForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface + { + return $this->personDocumentACLAwareRepository->buildFetchQueryForAccompanyingPeriod($accompanyingPeriod, $startDate, $endDate, $content); + } + + public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool + { + // we assume that the user is allowed to see at least one person of the course + // this will be double checked when running the query + return true; + } } diff --git a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php index 5d85541aa..26a42b894 100644 --- a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php +++ b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php @@ -22,6 +22,8 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher; use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface; use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; +use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; use Chill\PersonBundle\Entity\Person; use DateTimeImmutable; use Doctrine\DBAL\Types\Types; @@ -29,19 +31,14 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Security\Core\Security; -class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareRepositoryInterface +final readonly class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareRepositoryInterface { - private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser; - - private CenterResolverManagerInterface $centerResolverManager; - - private EntityManagerInterface $em; - - public function __construct(EntityManagerInterface $em, CenterResolverManagerInterface $centerResolverManager, AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser) - { - $this->em = $em; - $this->centerResolverManager = $centerResolverManager; - $this->authorizationHelperForCurrentUser = $authorizationHelperForCurrentUser; + public function __construct( + private EntityManagerInterface $em, + private CenterResolverManagerInterface $centerResolverManager, + private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser, + private Security $security, + ) { } public function buildQueryByPerson(Person $person): QueryBuilder @@ -63,6 +60,66 @@ class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareReposito return $this->addFetchQueryByPersonACL($query, $person); } + public function buildFetchQueryForAccompanyingPeriod(AccompanyingPeriod $period, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface + { + $personDocMetadata = $this->em->getClassMetadata(PersonDocument::class); + $participationMetadata = $this->em->getClassMetadata(AccompanyingPeriodParticipation::class); + + $query = new FetchQuery( + PersonDocumentGenericDocProvider::KEY, + sprintf('jsonb_build_object(\'id\', person_document.%s)', $personDocMetadata->getSingleIdentifierColumnName()), + sprintf('person_document.%s', $personDocMetadata->getColumnName('date')), + sprintf('%s AS person_document', $personDocMetadata->getSchemaName().'.'.$personDocMetadata->getTableName()) + ); + + $query->addJoinClause( + sprintf( + 'JOIN %s AS participation ON participation.%s = person_document.%s '. + 'AND person_document.%s BETWEEN participation.%s AND COALESCE(participation.%s, \'infinity\'::date)', + $participationMetadata->getTableName(), + $participationMetadata->getSingleAssociationJoinColumnName('person'), + $personDocMetadata->getSingleAssociationJoinColumnName('person'), + $personDocMetadata->getColumnName('date'), + $participationMetadata->getColumnName('startDate'), + $participationMetadata->getColumnName('endDate') + ) + ); + + $query->addWhereClause( + sprintf('participation.%s = ?', $participationMetadata->getSingleAssociationJoinColumnName('accompanyingPeriod')), + [$period->getId()], + [Types::INTEGER] + ); + + // can we see the document for this person ? + $orPersonId = []; + foreach ($period->getParticipations() as $participation) { + if (!$this->security->isGranted(PersonDocumentVoter::SEE, $participation->getPerson())) { + continue; + } + $orPersonId[] = $participation->getPerson()->getId(); + + } + + if ([] === $orPersonId) { + $query->addWhereClause('FALSE = TRUE'); + + return $query; + } + + $query->addWhereClause( + sprintf( + 'participation.%s IN (%s)', + $participationMetadata->getSingleAssociationJoinColumnName('person'), + implode(', ', array_fill(0, count($orPersonId), '?')) + ), + $orPersonId, + array_fill(0, count($orPersonId), Types::INTEGER) + ); + + return $this->addFilterClauses($query, $startDate, $endDate, $content); + } + public function buildBaseFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery { $personDocMetadata = $this->em->getClassMetadata(PersonDocument::class); @@ -80,6 +137,13 @@ class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareReposito [Types::INTEGER] ); + return $this->addFilterClauses($query, $startDate, $endDate, $content); + } + + private function addFilterClauses(FetchQuery $query, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery + { + $personDocMetadata = $this->em->getClassMetadata(PersonDocument::class); + if (null !== $startDate) { $query->addWhereClause( sprintf('? <= %s', $personDocMetadata->getColumnName('date')), @@ -107,7 +171,6 @@ class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareReposito [Types::STRING, Types::STRING] ); } - return $query; } diff --git a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php index 0b5e26792..f1bc70812 100644 --- a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php +++ b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\Repository; use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; +use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; interface PersonDocumentACLAwareRepositoryInterface @@ -32,4 +33,11 @@ interface PersonDocumentACLAwareRepositoryInterface ?\DateTimeImmutable $endDate = null, ?string $content = null ): FetchQueryInterface; + + public function buildFetchQueryForAccompanyingPeriod( + AccompanyingPeriod $period, + ?\DateTimeImmutable $startDate = null, + ?\DateTimeImmutable $endDate = null, + ?string $content = null + ): FetchQueryInterface; } diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/GenericDoc/accompanying_period_list.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/GenericDoc/accompanying_period_list.html.twig index f76e4b984..b22c7d00f 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/GenericDoc/accompanying_period_list.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/GenericDoc/accompanying_period_list.html.twig @@ -8,12 +8,14 @@ {% block js %} {{ parent() }} + {{ encore_entry_script_tags('mod_docgen_picktemplate') }} {{ encore_entry_script_tags('mod_entity_workflow_pick') }} {{ encore_entry_script_tags('mod_document_action_buttons_group') }} {% endblock %} {% block css %} {{ parent() }} + {{ encore_entry_script_tags('mod_docgen_picktemplate') }} {{ encore_entry_link_tags('mod_entity_workflow_pick') }} {{ encore_entry_link_tags('mod_document_action_buttons_group') }} {% endblock %} @@ -36,6 +38,8 @@ {{ chill_pagination(pagination) }} +
+ {% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_CREATE', accompanyingCourse) %}