diff --git a/src/Bundle/ChillActivityBundle/Repository/ActivityRepository.php b/src/Bundle/ChillActivityBundle/Repository/ActivityRepository.php
index 5a6e16cd5..a3bfb5942 100644
--- a/src/Bundle/ChillActivityBundle/Repository/ActivityRepository.php
+++ b/src/Bundle/ChillActivityBundle/Repository/ActivityRepository.php
@@ -15,6 +15,7 @@ use Chill\ActivityBundle\Entity\Activity;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Doctrine\ORM\Query\Expr;
use Doctrine\Persistence\ManagerRegistry;
/**
diff --git a/src/Bundle/ChillActivityBundle/Repository/PersonActivityDocumentACLAwareRepository.php b/src/Bundle/ChillActivityBundle/Repository/PersonActivityDocumentACLAwareRepository.php
new file mode 100644
index 000000000..84bb08fb4
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Repository/PersonActivityDocumentACLAwareRepository.php
@@ -0,0 +1,225 @@
+em->getRepository(PersonDocument::class)->createQueryBuilder('d');
+
+ $qb
+ ->where($qb->expr()->eq('d.person', ':person'))
+ ->setParameter('person', $person);
+
+ return $qb;
+ }
+
+
+ public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface
+ {
+ $query = $this->buildBaseFetchQueryForPerson($person, $startDate, $endDate, $content);
+
+ return $this->addFetchQueryByPersonACL($query, $person);
+ }
+
+ public function buildBaseFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
+ {
+ $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
+ $activityMetadata = $this->em->getClassMetadata(Activity::class);
+
+ $query = new FetchQuery(
+ PersonDocumentGenericDocProvider::KEY,
+ sprintf('jsonb_build_object(\'id\', stored_obj.%s, \'activity_id\', activity.%s)', $storedObjectMetadata->getSingleIdentifierColumnName(), $activityMetadata->getSingleIdentifierColumnName()),
+ sprintf('stored_obj.%s', $storedObjectMetadata->getColumnName('createdAt')),
+ sprintf('%s AS stored_obj', $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName())
+ );
+
+ $query->addJoinClause(
+ 'JOIN public.activity_storedobject activity_doc ON activity_doc.storedobject_id = stored_obj.id'
+ );
+
+ $query->addJoinClause(
+ 'JOIN public.activity activity ON activity.id = activity_doc.activity_id'
+ );
+
+ // add documents of activities from parcours context
+ $or = [];
+ $orParams = [];
+ $orTypes = [];
+ foreach ($person->getAccompanyingPeriodParticipations() as $participation) {
+ if (!$this->security->isGranted(ActivityVoter::SEE, $participation->getAccompanyingPeriod())) {
+ continue;
+ }
+
+ $or[] = sprintf(
+ '(activity.%s = ? AND stored_obj.%s BETWEEN ?::date AND COALESCE(?::date, \'infinity\'::date))',
+ $activityMetadata->getSingleAssociationJoinColumnName('accompanyingPeriod'),
+ $storedObjectMetadata->getColumnName('createdAt')
+ );
+ $orParams = [...$orParams, $participation->getAccompanyingPeriod()->getId(),
+ DateTimeImmutable::createFromInterface($participation->getStartDate()),
+ null === $participation->getEndDate() ? null : DateTimeImmutable::createFromInterface($participation->getEndDate())];
+ $orTypes = [...$orTypes, Types::INTEGER, Types::DATE_IMMUTABLE, Types::DATE_IMMUTABLE];
+ }
+
+ if ([] === $or) {
+ $query->addWhereClause('TRUE = FALSE');
+
+ return $query;
+ }
+
+ $query->addWhereClause(sprintf('(%s)', implode(' OR ', $or)), $orParams, $orTypes);
+
+/* $query->addWhereClause(
+ 'activity.person_id = ?',
+ [$person->getId()],
+ [Types::INTEGER]
+ );*/
+
+ if (null !== $startDate) {
+ $query->addWhereClause(
+ sprintf('stored_obj.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$startDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $endDate) {
+ $query->addWhereClause(
+ sprintf('stored_obj.%s < ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$endDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $content) {
+ $query->addWhereClause(
+ 'stored_obj.title ilike ?',
+ ['%' . $content . '%'],
+ [Types::STRING]
+ );
+ }
+
+ return $query;
+ }
+
+ public function countByPerson(Person $person): int
+ {
+ $qb = $this->buildQueryByPerson($person)->select('COUNT(d)');
+
+ $this->addACL($qb, $person);
+
+ return $qb->getQuery()->getSingleScalarResult();
+ }
+
+ public function findByPerson(Person $person, array $orderBy = [], int $limit = 20, int $offset = 0): array
+ {
+ $qb = $this->buildQueryByPerson($person)->select('d');
+
+ $this->addACL($qb, $person);
+
+ foreach ($orderBy as $field => $order) {
+ $qb->addOrderBy('d.' . $field, $order);
+ }
+
+ $qb->setFirstResult($offset)->setMaxResults($limit);
+
+ return $qb->getQuery()->getResult();
+ }
+
+ private function addACL(QueryBuilder $qb, Person $person): void
+ {
+ $reachableScopes = [];
+
+ foreach ($this->centerResolverManager->resolveCenters($person) as $center) {
+ $reachableScopes = [
+ ...$reachableScopes,
+ ...$this->authorizationHelperForCurrentUser
+ ->getReachableScopes(
+ ActivityVoter::SEE,
+ $center
+ )
+ ];
+ }
+
+ if ([] === $reachableScopes) {
+ $qb->andWhere("'FALSE' = 'TRUE'");
+
+ return;
+ }
+
+ $qb->andWhere($qb->expr()->in('d.scope', ':scopes'))
+ ->setParameter('scopes', $reachableScopes);
+ }
+
+ private function addFetchQueryByPersonACL(FetchQuery $fetchQuery, Person $person): FetchQuery
+ {
+ $activityMetadata = $this->em->getClassMetadata(Activity::class);
+
+ $reachableScopes = [];
+
+ foreach ($this->centerResolverManager->resolveCenters($person) as $center) {
+ $reachableScopes = [
+ ...$reachableScopes,
+ ...$this->authorizationHelperForCurrentUser->getReachableScopes(ActivityVoter::SEE, $center)
+ ];
+ }
+
+ if ([] === $reachableScopes) {
+ $fetchQuery->addWhereClause('FALSE = TRUE');
+
+ return $fetchQuery;
+ }
+
+ $fetchQuery->addWhereClause(
+ sprintf(
+ 'activity.%s IN (%s)',
+ $activityMetadata->getSingleAssociationJoinColumnName('scope'),
+ implode(', ', array_fill(0, count($reachableScopes), '?'))
+ ),
+ array_map(static fn (Scope $s) => $s->getId(), $reachableScopes),
+ array_fill(0, count($reachableScopes), Types::INTEGER)
+ );
+
+ return $fetchQuery;
+ }
+}
diff --git a/src/Bundle/ChillActivityBundle/Resources/views/GenericDoc/activity_document.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/GenericDoc/activity_document.html.twig
new file mode 100644
index 000000000..11aeeeca1
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Resources/views/GenericDoc/activity_document.html.twig
@@ -0,0 +1,79 @@
+{% import "@ChillDocStore/Macro/macro.html.twig" as m %}
+{% import "@ChillDocStore/Macro/macro_mimeicon.html.twig" as mm %}
+{% import '@ChillPerson/Macro/updatedBy.html.twig' as mmm %}
+
+{% set person_id = null %}
+{% if activity.person %}
+ {% set person_id = activity.person.id %}
+{% endif %}
+
+{% set accompanying_course_id = null %}
+{% if activity.accompanyingPeriod %}
+ {% set accompanying_course_id = activity.accompanyingPeriod.id %}
+{% endif %}
+
+
+
+
+ {% if document.isPending %}
+
{{ 'docgen.Doc generation is pending'|trans }}
+ {% elseif document.isFailure %}
+
{{ 'docgen.Doc generation failed'|trans }}
+ {% endif %}
+
+ {{ document.title }}
+
+ {% if document.hasTemplate %}
+
+
{{ document.template.name|localize_translatable_string }}
+
+ {% endif %}
+
+
+
+
+
+ {{ document.createdAt|format_date('short') }}
+
+
+
+
+
+
+
+
+
+
+ {{ activity.type.name | localize_translatable_string }}
+ {% if activity.emergency %}
+ {{ 'Emergency'|trans|upper }}
+ {% endif %}
+
+
+
+
+
+
+
+ {{ mmm.createdBy(document) }}
+
+
+ {% if is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) %}
+ -
+ {{ document|chill_document_button_group(document.title, is_granted('CHILL_ACTIVITY_UPDATE', activity), {small: false}) }}
+
+ {% endif %}
+ {% if is_granted('CHILL_ACTIVITY_SEE', activity)%}
+ -
+
+
+ {% endif %}
+ {% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
+ -
+
+
+ {% endif %}
+
+
+
+
diff --git a/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/AccompanyingPeriodActivityGenericDocProvider.php b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/AccompanyingPeriodActivityGenericDocProvider.php
new file mode 100644
index 000000000..284182cfb
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/AccompanyingPeriodActivityGenericDocProvider.php
@@ -0,0 +1,98 @@
+em->getClassMetadata(StoredObject::class);
+ $activityMetadata = $this->em->getClassMetadata(Activity::class);
+
+ $query = new FetchQuery(
+ self::KEY,
+ sprintf("jsonb_build_object('id', doc_obj.%s, 'activity_id', activity.%s)", $storedObjectMetadata->getSingleIdentifierColumnName(), $activityMetadata->getSingleIdentifierColumnName()),
+ 'doc_obj.'.$storedObjectMetadata->getColumnName('createdAt'),
+ $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName().' AS doc_obj'
+ );
+
+ $query->addJoinClause(
+ 'JOIN public.activity_storedobject activity_doc ON activity_doc.storedobject_id = doc_obj.id'
+ );
+
+ $query->addJoinClause(
+ 'JOIN public.activity activity ON activity.id = activity_doc.activity_id'
+ );
+
+ $query->addWhereClause(
+ 'activity.accompanyingperiod_id = ?',
+ [$accompanyingPeriod->getId()],
+ [Types::INTEGER]
+ );
+
+ if (null !== $startDate) {
+ $query->addWhereClause(
+ sprintf('doc_obj.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$startDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $endDate) {
+ $query->addWhereClause(
+ sprintf('doc_obj.%s < ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$endDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $content) {
+ $query->addWhereClause(
+ 'doc_obj.title ilike ?',
+ ['%' . $content . '%'],
+ [Types::STRING]
+ );
+ }
+
+ return $query;
+ }
+
+ /**
+ * @param AccompanyingPeriod $accompanyingPeriod
+ * @return bool
+ */
+ public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool
+ {
+ return $this->security->isGranted(ActivityVoter::SEE, $accompanyingPeriod);
+ }
+}
diff --git a/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/PersonActivityGenericDocProvider.php b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/PersonActivityGenericDocProvider.php
new file mode 100644
index 000000000..d00a23e79
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Providers/PersonActivityGenericDocProvider.php
@@ -0,0 +1,57 @@
+security = $security;
+ $this->personActivityDocumentACLAwareRepository = $personActivityDocumentACLAwareRepository;
+ }
+
+ public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface
+ {
+ return $this->personActivityDocumentACLAwareRepository->buildFetchQueryForPerson(
+ $person,
+ $startDate,
+ $endDate,
+ $content
+ );
+ }
+
+ /**
+ * @param Person $person
+ * @return bool
+ */
+ public function isAllowedForPerson(Person $person): bool
+ {
+ return $this->security->isGranted(ActivityVoter::SEE, $person);
+ }
+}
diff --git a/src/Bundle/ChillActivityBundle/Service/GenericDoc/Renderers/AccompanyingPeriodActivityGenericDocRenderer.php b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Renderers/AccompanyingPeriodActivityGenericDocRenderer.php
new file mode 100644
index 000000000..9f9a4bec8
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Service/GenericDoc/Renderers/AccompanyingPeriodActivityGenericDocRenderer.php
@@ -0,0 +1,51 @@
+objectRepository = $storedObjectRepository;
+ $this->activityRepository = $activityRepository;
+ }
+
+ public function supports(GenericDocDTO $genericDocDTO, $options = []): bool
+ {
+ return $genericDocDTO->key === AccompanyingPeriodActivityGenericDocProvider::KEY || $genericDocDTO->key === PersonActivityGenericDocProvider::KEY;
+ }
+
+ public function getTemplate(GenericDocDTO $genericDocDTO, $options = []): string
+ {
+ return '@ChillActivity/GenericDoc/activity_document.html.twig';
+ }
+
+ public function getTemplateData(GenericDocDTO $genericDocDTO, $options = []): array
+ {
+ return [
+ 'activity' => $this->activityRepository->find($genericDocDTO->identifiers['activity_id']),
+ 'document' => $this->objectRepository->find($genericDocDTO->identifiers['id'])
+ ];
+ }
+}
+
diff --git a/src/Bundle/ChillActivityBundle/config/services.yaml b/src/Bundle/ChillActivityBundle/config/services.yaml
index d55f86d4f..18be76ec9 100644
--- a/src/Bundle/ChillActivityBundle/config/services.yaml
+++ b/src/Bundle/ChillActivityBundle/config/services.yaml
@@ -38,3 +38,6 @@ services:
Chill\ActivityBundle\Service\EntityInfo\:
resource: '../Service/EntityInfo/'
+
+ Chill\ActivityBundle\Service\GenericDoc\:
+ resource: '../Service/GenericDoc/'
diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/GenericDoc/calendar_document.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/GenericDoc/calendar_document.html.twig
new file mode 100644
index 000000000..4cd369366
--- /dev/null
+++ b/src/Bundle/ChillCalendarBundle/Resources/views/GenericDoc/calendar_document.html.twig
@@ -0,0 +1,69 @@
+{% import "@ChillDocStore/Macro/macro.html.twig" as m %}
+{% import "@ChillDocStore/Macro/macro_mimeicon.html.twig" as mm %}
+{% import '@ChillPerson/Macro/updatedBy.html.twig' as mmm %}
+
+{% set c = document.calendar %}
+
+
+
+
+ {% if document.storedObject.isPending %}
+
{{ 'docgen.Doc generation is pending'|trans }}
+ {% elseif document.storedObject.isFailure %}
+
{{ 'docgen.Doc generation failed'|trans }}
+ {% endif %}
+
+ {{ document.storedObject.title }}
+
+
+ {{ 'chill_calendar.Document'|trans }}
+
+ {% if document.storedObject.hasTemplate %}
+
+
{{ document.storedObject.template.name|localize_translatable_string }}
+
+ {% endif %}
+
+
+
+
+
+ {{ document.storedObject.createdAt|format_date('short') }}
+
+
+
+
+
+
+
+
+ {% if c.endDate.diff(c.startDate).days >= 1 %}
+ {{ c.startDate|format_datetime('short', 'short') }}
+ - {{ c.endDate|format_datetime('short', 'short') }}
+ {% else %}
+ {{ c.startDate|format_datetime('short', 'short') }}
+ - {{ c.endDate|format_datetime('none', 'short') }}
+ {% endif %}
+
+
+
+
+
+
+ {{ mmm.createdBy(document) }}
+
+
+ {% if is_granted('CHILL_CALENDAR_DOC_SEE', document) %}
+ -
+ {{ document.storedObject|chill_document_button_group(document.storedObject.title, is_granted('CHILL_CALENDAR_CALENDAR_EDIT', c)) }}
+
+ {% endif %}
+ {% if is_granted('CHILL_CALENDAR_CALENDAR_EDIT', c) %}
+ -
+
+
+ {% endif %}
+
+
+
+
diff --git a/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/AccompanyingPeriodCalendarGenericDocProvider.php b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/AccompanyingPeriodCalendarGenericDocProvider.php
new file mode 100644
index 000000000..7efc1589d
--- /dev/null
+++ b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/AccompanyingPeriodCalendarGenericDocProvider.php
@@ -0,0 +1,107 @@
+em->getClassMetadata(CalendarDoc::class);
+ $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
+ $calendarMetadata = $this->em->getClassMetadata(Calendar::class);
+
+ $query = new FetchQuery(
+ self::KEY,
+ sprintf("jsonb_build_object('id', cd.%s)", $classMetadata->getColumnName('id')),
+ 'cd.'.$storedObjectMetadata->getColumnName('createdAt'),
+ $classMetadata->getSchemaName().'.'.$classMetadata->getTableName().' AS cd'
+ );
+ $query->addJoinClause(
+ sprintf('JOIN %s doc_store ON doc_store.%s = cd.%s',
+ $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName(),
+ $storedObjectMetadata->getColumnName('id'),
+ $classMetadata->getSingleAssociationJoinColumnName('storedObject')
+ ));
+
+ $query->addJoinClause(
+ sprintf('JOIN %s calendar ON calendar.%s = cd.%s',
+ $calendarMetadata->getSchemaName().'.'.$calendarMetadata->getTableName(),
+ $calendarMetadata->getColumnName('id'),
+ $classMetadata->getSingleAssociationJoinColumnName('calendar')
+ )
+ );
+
+ $query->addWhereClause(
+ sprintf('calendar.%s = ?',
+ $calendarMetadata->getAssociationMapping('accompanyingPeriod')['joinColumns'][0]['name']),
+ [$accompanyingPeriod->getId()],
+ [Types::INTEGER]
+ );
+
+ if (null !== $startDate) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$startDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $endDate) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s < ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$endDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $content) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s ilike ?', $storedObjectMetadata->getColumnName('title')),
+ ['%' . $content . '%'],
+ [Types::STRING]
+ );
+ }
+
+ return $query;
+ }
+
+ public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool
+ {
+ return $this->security->isGranted(CalendarVoter::SEE, $accompanyingPeriod);
+ }
+
+
+}
diff --git a/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/PersonCalendarGenericDocProvider.php b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/PersonCalendarGenericDocProvider.php
new file mode 100644
index 000000000..640f0d197
--- /dev/null
+++ b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/PersonCalendarGenericDocProvider.php
@@ -0,0 +1,141 @@
+em->getClassMetadata(StoredObject::class);
+
+ if (null !== $startDate) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$startDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $endDate) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s < ?', $storedObjectMetadata->getColumnName('createdAt')),
+ [$endDate],
+ [Types::DATE_IMMUTABLE]
+ );
+ }
+
+ if (null !== $content) {
+ $query->addWhereClause(
+ sprintf('doc_store.%s ilike ?', $storedObjectMetadata->getColumnName('title')),
+ ['%' . $content . '%'],
+ [Types::STRING]
+ );
+ }
+
+ return $query;
+ }
+
+ /**
+ * @throws MappingException
+ */
+ public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface
+ {
+ $classMetadata = $this->em->getClassMetadata(CalendarDoc::class);
+ $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class);
+ $calendarMetadata = $this->em->getClassMetadata(Calendar::class);
+
+ $query = new FetchQuery(
+ self::KEY,
+ sprintf("jsonb_build_object('id', cd.%s)", $classMetadata->getColumnName('id')),
+ 'cd.'.$storedObjectMetadata->getColumnName('createdAt'),
+ $classMetadata->getSchemaName().'.'.$classMetadata->getTableName().' AS cd'
+ );
+ $query->addJoinClause(
+ sprintf('JOIN %s doc_store ON doc_store.%s = cd.%s',
+ $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName(),
+ $storedObjectMetadata->getColumnName('id'),
+ $classMetadata->getSingleAssociationJoinColumnName('storedObject')
+ ));
+
+ $query->addJoinClause(
+ sprintf('JOIN %s calendar ON calendar.%s = cd.%s',
+ $calendarMetadata->getSchemaName().'.'.$calendarMetadata->getTableName(),
+ $calendarMetadata->getColumnName('id'),
+ $classMetadata->getSingleAssociationJoinColumnName('calendar')
+ )
+ );
+
+ // get the documents associated with accompanying periods in which person participates
+ $or = [];
+ $orParams = [];
+ $orTypes = [];
+ foreach ($person->getAccompanyingPeriodParticipations() as $participation) {
+ if (!$this->security->isGranted(CalendarVoter::SEE, $participation->getAccompanyingPeriod())) {
+ continue;
+ }
+
+ $or[] = sprintf(
+ '(calendar.%s = ? AND cd.%s BETWEEN ?::date AND COALESCE(?::date, \'infinity\'::date))',
+ $calendarMetadata->getSingleAssociationJoinColumnName('accompanyingPeriod'),
+ $storedObjectMetadata->getColumnName('createdAt')
+ );
+ $orParams = [...$orParams, $participation->getAccompanyingPeriod()->getId(),
+ DateTimeImmutable::createFromInterface($participation->getStartDate()),
+ null === $participation->getEndDate() ? null : DateTimeImmutable::createFromInterface($participation->getEndDate())];
+ $orTypes = [...$orTypes, Types::INTEGER, Types::DATE_IMMUTABLE, Types::DATE_IMMUTABLE];
+ }
+
+ if ([] === $or) {
+ $query->addWhereClause('TRUE = FALSE');
+
+ return $query;
+ }
+
+// $query->addWhereClause(sprintf('(%s)', implode(' OR ', $or)), $orParams, $orTypes);
+
+ return $this->addWhereClausesToQuery($query, $startDate, $endDate, $content);
+
+ }
+
+ /**
+ * @param Person $person
+ * @return bool
+ */
+ public function isAllowedForPerson(Person $person): bool
+ {
+ return $this->security->isGranted(CalendarVoter::SEE, $person);
+ }
+}
diff --git a/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Renderers/AccompanyingPeriodCalendarGenericDocRenderer.php b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Renderers/AccompanyingPeriodCalendarGenericDocRenderer.php
new file mode 100644
index 000000000..d9636d99d
--- /dev/null
+++ b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Renderers/AccompanyingPeriodCalendarGenericDocRenderer.php
@@ -0,0 +1,45 @@
+repository = $calendarDocRepository;
+ }
+
+ public function supports(GenericDocDTO $genericDocDTO, $options = []): bool
+ {
+ return $genericDocDTO->key === AccompanyingPeriodCalendarGenericDocProvider::KEY || $genericDocDTO->key === PersonCalendarGenericDocProvider::KEY;
+ }
+
+ public function getTemplate(GenericDocDTO $genericDocDTO, $options = []): string
+ {
+ return '@ChillCalendar/GenericDoc/calendar_document.html.twig';
+ }
+
+ public function getTemplateData(GenericDocDTO $genericDocDTO, $options = []): array
+ {
+ return [
+ 'document' => $this->repository->find($genericDocDTO->identifiers['id'])
+ ];
+ }
+}
diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml
index eb02be280..99aae1082 100644
--- a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml
@@ -43,6 +43,7 @@ crud:
title_edit: Modifier le motif d'annulation
chill_calendar:
+ Document: Document d'un rendez-vous
form:
The main user is mandatory. He will organize the appointment.: L'utilisateur principal est obligatoire. Il est l'organisateur de l'événement.
Create for referrer: Créer pour le référent
@@ -65,6 +66,7 @@ chill_calendar:
Document outdated: La date et l'heure du rendez-vous ont été modifiés après la création du document
+
remote_ms_graph:
freebusy_statuses:
busy: Occupé
@@ -145,3 +147,9 @@ CHILL_CALENDAR_CALENDAR_EDIT: Modifier les rendez-vous
CHILL_CALENDAR_CALENDAR_DELETE: Supprimer les rendez-vous
CHILL_CALENDAR_CALENDAR_SEE: Voir les rendez-vous
+
+generic_doc:
+ filter:
+ keys:
+ accompanying_period_calendar_document: Document des rendez-vous
+ person_calendar_document: Document des rendez-vous de la personne
diff --git a/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php b/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php
index 8762050aa..384eeb510 100644
--- a/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php
+++ b/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php
@@ -160,7 +160,7 @@ class DocumentAccompanyingCourseController extends AbstractController
$this->addFlash('success', $this->translator->trans('The document is successfully registered'));
- return $this->redirectToRoute('accompanying_course_document_index', ['course' => $course->getId()]);
+ return $this->redirectToRoute('chill_docstore_generic-doc_by-period_index', ['id' => $course->getId()]);
}
if ($form->isSubmitted() && !$form->isValid()) {
diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
index a344ac50d..9b30e3a0b 100644
--- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
@@ -1236,3 +1236,4 @@ generic_doc:
filter:
keys:
accompanying_period_work_evaluation_document: Document des actions d'accompagnement
+ person_document: Documents de la personne