Merge branch 'master' into 38-gestion-doublon

This commit is contained in:
2023-09-07 16:08:27 +02:00
79 changed files with 3331 additions and 749 deletions

View File

@@ -39,8 +39,10 @@ readonly class AccompanyingPeriodStepChangeCronjob implements CronJobInterface
return 'accompanying-period-step-change';
}
public function run(): void
public function run(array $lastExecutionData): null|array
{
($this->requestor)();
return null;
}
}

View File

@@ -11,45 +11,39 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\Entity\UserJob;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Templating\Listing\FilterOrderHelper;
use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class AccompanyingCourseWorkController extends AbstractController
final class AccompanyingCourseWorkController extends AbstractController
{
private LoggerInterface $chillLogger;
private PaginatorFactory $paginator;
private SerializerInterface $serializer;
private TranslatorInterface $trans;
private AccompanyingPeriodWorkRepository $workRepository;
public function __construct(
TranslatorInterface $trans,
SerializerInterface $serializer,
AccompanyingPeriodWorkRepository $workRepository,
PaginatorFactory $paginator,
LoggerInterface $chillLogger
private readonly TranslatorInterface $trans,
private readonly SerializerInterface $serializer,
private readonly AccompanyingPeriodWorkRepository $workRepository,
private readonly PaginatorFactory $paginator,
private readonly LoggerInterface $chillLogger,
private readonly TranslatableStringHelperInterface $translatableStringHelper,
private readonly FilterOrderHelperFactoryInterface $filterOrderHelperFactory
) {
$this->trans = $trans;
$this->serializer = $serializer;
$this->workRepository = $workRepository;
$this->paginator = $paginator;
$this->chillLogger = $chillLogger;
}
/**
@@ -162,11 +156,21 @@ class AccompanyingCourseWorkController extends AbstractController
{
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::SEE, $period);
$filter = $this->buildFilterOrder($period);
$filterData = [
'types' => $filter->hasEntityChoice('typesFilter') ? $filter->getEntityChoiceData('typesFilter') : [],
'before' => $filter->getDateRangeData('dateFilter')['to'],
'after' => $filter->getDateRangeData('dateFilter')['from'],
'user' => $filter->getUserPickerData('userFilter')
];
$totalItems = $this->workRepository->countByAccompanyingPeriod($period);
$paginator = $this->paginator->create($totalItems);
$works = $this->workRepository->findByAccompanyingPeriodOpenFirst(
$period,
$filterData,
$paginator->getItemsPerPage(),
$paginator->getCurrentPageFirstItemNumber()
);
@@ -175,6 +179,7 @@ class AccompanyingCourseWorkController extends AbstractController
'accompanyingCourse' => $period,
'works' => $works,
'paginator' => $paginator,
'filter' => $filter
]);
}
@@ -199,7 +204,7 @@ class AccompanyingCourseWorkController extends AbstractController
]);
}
private function createDeleteForm(int $id): Form
private function createDeleteForm(int $id): FormInterface
{
$params = [];
$params['id'] = $id;
@@ -210,4 +215,26 @@ class AccompanyingCourseWorkController extends AbstractController
->add('submit', SubmitType::class, ['label' => 'Delete'])
->getForm();
}
private function buildFilterOrder($associatedPeriod): FilterOrderHelper
{
$filterBuilder = $this->filterOrderHelperFactory->create(self::class);
$types = $this->workRepository->findActionTypeByPeriod($associatedPeriod);
$filterBuilder
->addDateRange('dateFilter', 'accompanying_course_work.date_filter');
if (1 < count($types)) {
$filterBuilder
->addEntityChoice('typesFilter', 'accompanying_course_work.types_filter', \Chill\PersonBundle\Entity\SocialWork\SocialAction::class, $types, [
'choice_label' => fn (SocialAction $sa) => $this->translatableStringHelper->localize($sa->getTitle())
]);
}
$filterBuilder
->addUserPicker('userFilter', 'accompanying_course_work.user_filter', ['required' => false])
;
return $filterBuilder->build();
}
}

View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Controller;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
class AccompanyingCourseWorkEvaluationDocumentController extends AbstractController
{
public function __construct(private Security $security)
{
}
/**
* @Route(
* "{_locale}/person/accompanying-period/work/evaluation/document/{id}/show",
* name="chill_person_accompanying_period_work_evaluation_document_show",
* methods={"GET"}
* )
*/
public function showAccompanyingCourseWork(AccompanyingPeriodWorkEvaluationDocument $document): Response
{
$work = $document->getAccompanyingPeriodWorkEvaluation()->getAccompanyingPeriodWork();
return $this->redirectToRoute(
$this->security->isGranted(AccompanyingPeriodWorkVoter::UPDATE, $work) ?
'chill_person_accompanying_period_work_edit' : 'chill_person_accompanying_period_work_show',
[
'id' => $work->getId()
]
);
}
}

View File

@@ -29,6 +29,7 @@ use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Helper\ListAccompanyingPeriodHelper;
use Chill\PersonBundle\Repository\PersonRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
@@ -45,95 +46,13 @@ use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use function strlen;
class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
final readonly class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
{
private const FIELDS = [
'id',
'step',
'stepSince',
'openingDate',
'closingDate',
'referrer',
'referrerSince',
'administrativeLocation',
'locationIsPerson',
'locationIsTemp',
'locationPersonName',
'locationPersonId',
'origin',
'closingMotive',
'confidential',
'emergency',
'intensity',
'job',
'isRequestorPerson',
'isRequestorThirdParty',
'requestorPerson',
'requestorPersonId',
'requestorThirdParty',
'requestorThirdPartyId',
'scopes',
'socialIssues',
'createdAt',
'createdBy',
'updatedAt',
'updatedBy',
];
private ExportAddressHelper $addressHelper;
private DateTimeHelper $dateTimeHelper;
private EntityManagerInterface $entityManager;
private PersonRenderInterface $personRender;
private PersonRepository $personRepository;
private RollingDateConverterInterface $rollingDateConverter;
private SocialIssueRender $socialIssueRender;
private SocialIssueRepository $socialIssueRepository;
private ThirdPartyRender $thirdPartyRender;
private ThirdPartyRepository $thirdPartyRepository;
private TranslatableStringHelperInterface $translatableStringHelper;
private TranslatorInterface $translator;
private UserHelper $userHelper;
public function __construct(
ExportAddressHelper $addressHelper,
DateTimeHelper $dateTimeHelper,
EntityManagerInterface $entityManager,
PersonRenderInterface $personRender,
PersonRepository $personRepository,
ThirdPartyRepository $thirdPartyRepository,
ThirdPartyRender $thirdPartyRender,
SocialIssueRepository $socialIssueRepository,
SocialIssueRender $socialIssueRender,
TranslatableStringHelperInterface $translatableStringHelper,
TranslatorInterface $translator,
RollingDateConverterInterface $rollingDateConverter,
UserHelper $userHelper
private EntityManagerInterface $entityManager,
private RollingDateConverterInterface $rollingDateConverter,
private ListAccompanyingPeriodHelper $listAccompanyingPeriodHelper,
) {
$this->addressHelper = $addressHelper;
$this->dateTimeHelper = $dateTimeHelper;
$this->entityManager = $entityManager;
$this->personRender = $personRender;
$this->personRepository = $personRepository;
$this->socialIssueRender = $socialIssueRender;
$this->socialIssueRepository = $socialIssueRepository;
$this->thirdPartyRender = $thirdPartyRender;
$this->thirdPartyRepository = $thirdPartyRepository;
$this->translatableStringHelper = $translatableStringHelper;
$this->translator = $translator;
$this->rollingDateConverter = $rollingDateConverter;
$this->userHelper = $userHelper;
}
public function buildForm(FormBuilderInterface $builder)
@@ -169,141 +88,12 @@ class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
public function getLabels($key, array $values, $data)
{
if (substr($key, 0, strlen('address_fields')) === 'address_fields') {
return $this->addressHelper->getLabel($key, $values, $data, 'address_fields');
}
switch ($key) {
case 'stepSince':
case 'openingDate':
case 'closingDate':
case 'referrerSince':
case 'createdAt':
case 'updatedAt':
return $this->dateTimeHelper->getLabel('export.list.acp.' . $key);
case 'origin':
case 'closingMotive':
case 'job':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value) {
return '';
}
return $this->translatableStringHelper->localize(json_decode($value, true, 512, JSON_THROW_ON_ERROR));
};
case 'locationPersonName':
case 'requestorPerson':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value || null === $person = $this->personRepository->find($value)) {
return '';
}
return $this->personRender->renderString($person, []);
};
case 'requestorThirdParty':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value || null === $thirdparty = $this->thirdPartyRepository->find($value)) {
return '';
}
return $this->thirdPartyRender->renderString($thirdparty, []);
};
case 'scopes':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value) {
return '';
}
return implode(
'|',
array_map(
fn ($s) => $this->translatableStringHelper->localize($s),
json_decode($value, true, 512, JSON_THROW_ON_ERROR)
)
);
};
case 'socialIssues':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value) {
return '';
}
return implode(
'|',
array_map(
fn ($s) => $this->socialIssueRender->renderString($this->socialIssueRepository->find($s), []),
json_decode($value, true, 512, JSON_THROW_ON_ERROR)
)
);
};
case 'step':
return fn ($value) => match ($value) {
'_header' => 'export.list.acp.step',
null => '',
AccompanyingPeriod::STEP_DRAFT => $this->translator->trans('course.draft'),
AccompanyingPeriod::STEP_CONFIRMED => $this->translator->trans('course.confirmed'),
AccompanyingPeriod::STEP_CLOSED => $this->translator->trans('course.closed'),
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT => $this->translator->trans('course.inactive_short'),
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG => $this->translator->trans('course.inactive_long'),
default => $value,
};
case 'intensity':
return fn ($value) => match ($value) {
'_header' => 'export.list.acp.intensity',
null => '',
AccompanyingPeriod::INTENSITY_OCCASIONAL => $this->translator->trans('occasional'),
AccompanyingPeriod::INTENSITY_REGULAR => $this->translator->trans('regular'),
default => $value,
};
default:
return static function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value) {
return '';
}
return $value;
};
}
return $this->listAccompanyingPeriodHelper->getLabels($key, $values, $data);
}
public function getQueryKeys($data)
{
return array_merge(
self::FIELDS,
$this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields')
);
return $this->listAccompanyingPeriodHelper->getQueryKeys($data);
}
public function getResult($query, $data)
@@ -341,7 +131,12 @@ class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
->setParameter('list_acp_step', AccompanyingPeriod::STEP_DRAFT)
->setParameter('authorized_centers', $centers);
$this->addSelectClauses($qb, $this->rollingDateConverter->convert($data['calc_date']));
$this->listAccompanyingPeriodHelper->addSelectClauses($qb, $this->rollingDateConverter->convert($data['calc_date']));
$qb
->addOrderBy('acp.openingDate')
->addOrderBy('acp.closingDate')
->addOrderBy('acp.id');
return $qb;
}
@@ -357,91 +152,4 @@ class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
Declarations::ACP_TYPE,
];
}
private function addSelectClauses(QueryBuilder $qb, DateTimeImmutable $calcDate): void
{
// add the regular fields
foreach (['id', 'openingDate', 'closingDate', 'confidential', 'emergency', 'intensity', 'createdAt', 'updatedAt'] as $field) {
$qb->addSelect(sprintf('acp.%s AS %s', $field, $field));
}
// add the field which are simple association
foreach (['origin' => 'label', 'closingMotive' => 'name', 'job' => 'label', 'createdBy' => 'label', 'updatedBy' => 'label', 'administrativeLocation' => 'name'] as $entity => $field) {
$qb
->leftJoin(sprintf('acp.%s', $entity), "{$entity}_t")
->addSelect(sprintf('%s_t.%s AS %s', $entity, $field, $entity));
}
// step at date
$qb
->addSelect('stepHistory.step AS step')
->addSelect('stepHistory.startDate AS stepSince')
->leftJoin('acp.stepHistories', 'stepHistory')
->andWhere(
$qb->expr()->andX(
$qb->expr()->lte('stepHistory.startDate', ':calcDate'),
$qb->expr()->orX($qb->expr()->isNull('stepHistory.endDate'), $qb->expr()->gt('stepHistory.endDate', ':calcDate'))
)
);
// referree at date
$qb
->addSelect('referrer_t.label AS referrer')
->addSelect('userHistory.startDate AS referrerSince')
->leftJoin('acp.userHistories', 'userHistory')
->leftJoin('userHistory.user', 'referrer_t')
->andWhere(
$qb->expr()->orX(
$qb->expr()->isNull('userHistory'),
$qb->expr()->andX(
$qb->expr()->lte('userHistory.startDate', ':calcDate'),
$qb->expr()->orX($qb->expr()->isNull('userHistory.endDate'), $qb->expr()->gt('userHistory.endDate', ':calcDate'))
)
)
);
// location of the acp
$qb
->addSelect('CASE WHEN locationHistory.personLocation IS NOT NULL THEN 1 ELSE 0 END AS locationIsPerson')
->addSelect('CASE WHEN locationHistory.personLocation IS NOT NULL THEN 0 ELSE 1 END AS locationIsTemp')
->addSelect('IDENTITY(locationHistory.personLocation) AS locationPersonName')
->addSelect('IDENTITY(locationHistory.personLocation) AS locationPersonId')
->leftJoin('acp.locationHistories', 'locationHistory')
->andWhere(
$qb->expr()->orX(
$qb->expr()->isNull('locationHistory'),
$qb->expr()->andX(
$qb->expr()->lte('locationHistory.startDate', ':calcDate'),
$qb->expr()->orX($qb->expr()->isNull('locationHistory.endDate'), $qb->expr()->gt('locationHistory.endDate', ':calcDate'))
)
)
)
->leftJoin(
PersonHouseholdAddress::class,
'personAddress',
Join::WITH,
'locationHistory.personLocation = personAddress.person AND (personAddress.validFrom <= :calcDate AND (personAddress.validTo IS NULL OR personAddress.validTo > :calcDate))'
)
->leftJoin(Address::class, 'acp_address', Join::WITH, 'COALESCE(IDENTITY(locationHistory.addressLocation), IDENTITY(personAddress.address)) = acp_address.id');
$this->addressHelper->addSelectClauses(ExportAddressHelper::F_ALL, $qb, 'acp_address', 'address_fields');
// requestor
$qb
->addSelect('CASE WHEN acp.requestorPerson IS NULL THEN 1 ELSE 0 END AS isRequestorPerson')
->addSelect('CASE WHEN acp.requestorPerson IS NULL THEN 0 ELSE 1 END AS isRequestorThirdParty')
->addSelect('IDENTITY(acp.requestorPerson) AS requestorPersonId')
->addSelect('IDENTITY(acp.requestorThirdParty) AS requestorThirdPartyId')
->addSelect('IDENTITY(acp.requestorPerson) AS requestorPerson')
->addSelect('IDENTITY(acp.requestorThirdParty) AS requestorThirdParty');
$qb
// scopes
->addSelect('(SELECT AGGREGATE(scope.name) FROM ' . Scope::class . ' scope WHERE scope MEMBER OF acp.scopes) AS scopes')
// social issues
->addSelect('(SELECT AGGREGATE(socialIssue.id) FROM ' . SocialIssue::class . ' socialIssue WHERE socialIssue MEMBER OF acp.socialIssues) AS socialIssues');
// add parameter
$qb->setParameter('calcDate', $calcDate);
}
}

View File

@@ -35,7 +35,12 @@ use function count;
use function in_array;
use function strlen;
class ListPersonWithAccompanyingPeriod implements ExportElementValidatedInterface, ListInterface, GroupedExportInterface
/**
* List the persons, having an accompanying period.
*
* Details of the accompanying period are not included
*/
class ListPersonHavingAccompanyingPeriod implements ExportElementValidatedInterface, ListInterface, GroupedExportInterface
{
private ExportAddressHelper $addressHelper;
@@ -185,6 +190,11 @@ class ListPersonWithAccompanyingPeriod implements ExportElementValidatedInterfac
$this->listPersonHelper->addSelect($qb, $fields, $data['address_date']);
$qb
->addOrderBy('person.lastName')
->addOrderBy('person.firstName')
->addOrderBy('person.id');
return $qb;
}

View File

@@ -0,0 +1,155 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Export\Export;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Helper\ListAccompanyingPeriodHelper;
use Chill\PersonBundle\Export\Helper\ListPersonHelper;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use DateTimeImmutable;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function array_key_exists;
use function count;
use function in_array;
use function strlen;
/**
* List the persons having an accompanying period, with the accompanying period details
*
*/
final readonly class ListPersonWithAccompanyingPeriodDetails implements ListInterface, GroupedExportInterface
{
public function __construct(
private ListPersonHelper $listPersonHelper,
private ListAccompanyingPeriodHelper $listAccompanyingPeriodHelper,
private EntityManagerInterface $entityManager,
private RollingDateConverterInterface $rollingDateConverter,
) {
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('address_date', PickRollingDateType::class, [
'label' => 'Data valid at this date',
'help' => 'Data regarding center, addresses, and so on will be computed at this date',
]);
}
public function getFormDefaultData(): array
{
return ['address_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_LIST];
}
public function getDescription()
{
return 'export.list.person_with_acp.Create a list of people having an accompaying periods with details of period, according to various filters.';
}
public function getGroup(): string
{
return 'Exports of persons';
}
public function getLabels($key, array $values, $data)
{
if (in_array($key, $this->listPersonHelper->getAllKeys(), true)) {
return $this->listPersonHelper->getLabels($key, $values, $data);
}
return $this->listAccompanyingPeriodHelper->getLabels($key, $values, $data);
}
public function getQueryKeys($data)
{
return array_merge(
$this->listPersonHelper->getAllKeys(),
$this->listAccompanyingPeriodHelper->getQueryKeys($data),
);
}
public function getResult($query, $data)
{
return $query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR);
}
public function getTitle()
{
return 'export.list.person_with_acp.List peoples having an accompanying period with period details';
}
public function getType()
{
return Declarations::PERSON_TYPE;
}
/**
* param array{fields: string[], address_date: DateTimeImmutable} $data.
*/
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static fn ($el) => $el['center'], $acl);
$qb = $this->entityManager->createQueryBuilder();
$qb->from(Person::class, 'person')
->join('person.accompanyingPeriodParticipations', 'acppart')
->join('acppart.accompanyingPeriod', 'acp')
->andWhere($qb->expr()->neq('acp.step', "'" . AccompanyingPeriod::STEP_DRAFT . "'"))
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM ' . PersonCenterHistory::class . ' pch WHERE pch.person = person.id AND pch.center IN (:authorized_centers)'
)
)->setParameter('authorized_centers', $centers);
$this->listPersonHelper->addSelect($qb, ListPersonHelper::FIELDS, $this->rollingDateConverter->convert($data['address_date']));
$this->listAccompanyingPeriodHelper->addSelectClauses($qb, $this->rollingDateConverter->convert($data['address_date']));
$qb
->addOrderBy('person.lastName')
->addOrderBy('person.firstName')
->addOrderBy('person.id')
->addOrderBy('acp.id');
return $qb;
}
public function requiredRole(): string
{
return PersonVoter::LISTS;
}
public function supportsModifiers()
{
return [Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN, Declarations::ACP_TYPE];
}
}

View File

@@ -0,0 +1,317 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Export\Helper;
use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Export\Helper\DateTimeHelper;
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\PersonBundle\Repository\PersonRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
use Chill\PersonBundle\Templating\Entity\PersonRenderInterface;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Contracts\Translation\TranslatorInterface;
final readonly class ListAccompanyingPeriodHelper
{
public const FIELDS = [
'acpId',
'step',
'stepSince',
'openingDate',
'closingDate',
'referrer',
'referrerSince',
'administrativeLocation',
'locationIsPerson',
'locationIsTemp',
'locationPersonName',
'locationPersonId',
'origin',
'closingMotive',
'confidential',
'emergency',
'intensity',
'job',
'isRequestorPerson',
'isRequestorThirdParty',
'requestorPerson',
'requestorPersonId',
'requestorThirdParty',
'requestorThirdPartyId',
'scopes',
'socialIssues',
'acpCreatedAt',
'acpCreatedBy',
'acpUpdatedAt',
'acpUpdatedBy',
];
public function __construct(
private ExportAddressHelper $addressHelper,
private DateTimeHelper $dateTimeHelper,
private PersonRenderInterface $personRender,
private PersonRepository $personRepository,
private ThirdPartyRepository $thirdPartyRepository,
private ThirdPartyRender $thirdPartyRender,
private SocialIssueRepository $socialIssueRepository,
private SocialIssueRender $socialIssueRender,
private TranslatableStringHelperInterface $translatableStringHelper,
private TranslatorInterface $translator,
) {
}
public function getQueryKeys($data)
{
return array_merge(
ListAccompanyingPeriodHelper::FIELDS,
$this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'acp_address_fields')
);
}
public function getLabels($key, array $values, $data)
{
if (str_starts_with($key, 'acp_address_fields')) {
return $this->addressHelper->getLabel($key, $values, $data, 'acp_address_fields');
}
switch ($key) {
case 'stepSince':
case 'openingDate':
case 'closingDate':
case 'referrerSince':
case 'acpCreatedAt':
case 'acpUpdatedAt':
return $this->dateTimeHelper->getLabel('export.list.acp.' . $key);
case 'origin':
case 'closingMotive':
case 'job':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value) {
return '';
}
return $this->translatableStringHelper->localize(json_decode($value, true, 512, JSON_THROW_ON_ERROR));
};
case 'locationPersonName':
case 'requestorPerson':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value || null === $person = $this->personRepository->find($value)) {
return '';
}
return $this->personRender->renderString($person, []);
};
case 'requestorThirdParty':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value || null === $thirdparty = $this->thirdPartyRepository->find($value)) {
return '';
}
return $this->thirdPartyRender->renderString($thirdparty, []);
};
case 'scopes':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value) {
return '';
}
return implode(
'|',
array_map(
fn ($s) => $this->translatableStringHelper->localize($s),
json_decode($value, true, 512, JSON_THROW_ON_ERROR)
)
);
};
case 'socialIssues':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value) {
return '';
}
return implode(
'|',
array_map(
fn ($s) => $this->socialIssueRender->renderString($this->socialIssueRepository->find($s), []),
json_decode($value, true, 512, JSON_THROW_ON_ERROR)
)
);
};
case 'step':
return fn ($value) => match ($value) {
'_header' => 'export.list.acp.step',
null => '',
AccompanyingPeriod::STEP_DRAFT => $this->translator->trans('course.draft'),
AccompanyingPeriod::STEP_CONFIRMED => $this->translator->trans('course.confirmed'),
AccompanyingPeriod::STEP_CLOSED => $this->translator->trans('course.closed'),
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT => $this->translator->trans('course.inactive_short'),
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG => $this->translator->trans('course.inactive_long'),
default => $value,
};
case 'intensity':
return fn ($value) => match ($value) {
'_header' => 'export.list.acp.intensity',
null => '',
AccompanyingPeriod::INTENSITY_OCCASIONAL => $this->translator->trans('occasional'),
AccompanyingPeriod::INTENSITY_REGULAR => $this->translator->trans('regular'),
default => $value,
};
default:
return static function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
}
if (null === $value) {
return '';
}
return $value;
};
}
}
public function addSelectClauses(QueryBuilder $qb, \DateTimeImmutable $calcDate): void
{
$qb->addSelect('acp.id AS acpId');
$qb->addSelect('acp.createdAt AS acpCreatedAt');
$qb->addSelect('acp.updatedAt AS acpUpdatedAt');
// add the regular fields
foreach (['openingDate', 'closingDate', 'confidential', 'emergency', 'intensity'] as $field) {
$qb->addSelect(sprintf('acp.%s AS %s', $field, $field));
}
// add the field which are simple association
$qb
->leftJoin('acp.createdBy', "acp_created_by_t")
->addSelect('acp_created_by_t.label AS acpCreatedBy');
$qb
->leftJoin('acp.updatedBy', "acp_updated_by_t")
->addSelect('acp_updated_by_t.label AS acpUpdatedBy');
foreach (['origin' => 'label', 'closingMotive' => 'name', 'job' => 'label', 'administrativeLocation' => 'name'] as $entity => $field) {
$qb
->leftJoin(sprintf('acp.%s', $entity), "{$entity}_t")
->addSelect(sprintf('%s_t.%s AS %s', $entity, $field, $entity));
}
// step at date
$qb
->addSelect('stepHistory.step AS step')
->addSelect('stepHistory.startDate AS stepSince')
->leftJoin('acp.stepHistories', 'stepHistory')
->andWhere(
$qb->expr()->andX(
$qb->expr()->lte('stepHistory.startDate', ':calcDate'),
$qb->expr()->orX($qb->expr()->isNull('stepHistory.endDate'), $qb->expr()->gt('stepHistory.endDate', ':calcDate'))
)
);
// referree at date
$qb
->addSelect('referrer_t.label AS referrer')
->addSelect('userHistory.startDate AS referrerSince')
->leftJoin('acp.userHistories', 'userHistory')
->leftJoin('userHistory.user', 'referrer_t')
->andWhere(
$qb->expr()->orX(
$qb->expr()->isNull('userHistory'),
$qb->expr()->andX(
$qb->expr()->lte('userHistory.startDate', ':calcDate'),
$qb->expr()->orX($qb->expr()->isNull('userHistory.endDate'), $qb->expr()->gt('userHistory.endDate', ':calcDate'))
)
)
);
// location of the acp
$qb
->addSelect('CASE WHEN locationHistory.personLocation IS NOT NULL THEN 1 ELSE 0 END AS locationIsPerson')
->addSelect('CASE WHEN locationHistory.personLocation IS NOT NULL THEN 0 ELSE 1 END AS locationIsTemp')
->addSelect('IDENTITY(locationHistory.personLocation) AS locationPersonName')
->addSelect('IDENTITY(locationHistory.personLocation) AS locationPersonId')
->leftJoin('acp.locationHistories', 'locationHistory')
->andWhere(
$qb->expr()->orX(
$qb->expr()->isNull('locationHistory'),
$qb->expr()->andX(
$qb->expr()->lte('locationHistory.startDate', ':calcDate'),
$qb->expr()->orX($qb->expr()->isNull('locationHistory.endDate'), $qb->expr()->gt('locationHistory.endDate', ':calcDate'))
)
)
)
->leftJoin(
PersonHouseholdAddress::class,
'acpPersonAddress',
Join::WITH,
'locationHistory.personLocation = acpPersonAddress.person AND (acpPersonAddress.validFrom <= :calcDate AND (acpPersonAddress.validTo IS NULL OR acpPersonAddress.validTo > :calcDate))'
)
->leftJoin(Address::class, 'acp_address', Join::WITH, 'COALESCE(IDENTITY(locationHistory.addressLocation), IDENTITY(acpPersonAddress.address)) = acp_address.id');
$this->addressHelper->addSelectClauses(ExportAddressHelper::F_ALL, $qb, 'acp_address', 'acp_address_fields');
// requestor
$qb
->addSelect('CASE WHEN acp.requestorPerson IS NULL THEN 1 ELSE 0 END AS isRequestorPerson')
->addSelect('CASE WHEN acp.requestorPerson IS NULL THEN 0 ELSE 1 END AS isRequestorThirdParty')
->addSelect('IDENTITY(acp.requestorPerson) AS requestorPersonId')
->addSelect('IDENTITY(acp.requestorThirdParty) AS requestorThirdPartyId')
->addSelect('IDENTITY(acp.requestorPerson) AS requestorPerson')
->addSelect('IDENTITY(acp.requestorThirdParty) AS requestorThirdParty');
$qb
// scopes
->addSelect('(SELECT AGGREGATE(scope.name) FROM ' . Scope::class . ' scope WHERE scope MEMBER OF acp.scopes) AS scopes')
// social issues
->addSelect('(SELECT AGGREGATE(socialIssue.id) FROM ' . SocialIssue::class . ' socialIssue WHERE socialIssue MEMBER OF acp.socialIssues) AS socialIssues');
// add parameter
$qb->setParameter('calcDate', $calcDate);
}
}

View File

@@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Export\Helper;
use Chill\MainBundle\Entity\Language;
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
use Chill\MainBundle\Repository\CenterRepositoryInterface;
use Chill\MainBundle\Repository\CivilityRepositoryInterface;
@@ -42,7 +43,7 @@ use function strlen;
class ListPersonHelper
{
public const FIELDS = [
'id',
'personId',
'civility',
'firstName',
'lastName',
@@ -114,7 +115,26 @@ class ListPersonHelper
}
/**
* @param array|value-of<self::FIELDS>[] $fields
* Those keys are the "direct" keys, which are created when we decide to use to list all the keys.
*
* This method must be used in `getKeys` instead of the `self::FIELDS`
*
* @return array<string>
*/
public function getAllKeys(): array
{
return [
...array_filter(
ListPersonHelper::FIELDS,
fn (string $key) => !in_array($key, ['address_fields', 'lifecycleUpdate'], true)
),
...$this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields'),
...['createdAt', 'createdBy', 'updatedAt', 'updatedBy'],
];
}
/**
* @param array<value-of<self::FIELDS>> $fields
*/
public function addSelect(QueryBuilder $qb, array $fields, DateTimeImmutable $computedDate): void
{
@@ -124,6 +144,11 @@ class ListPersonHelper
}
switch ($f) {
case 'personId':
$qb->addSelect('person.id AS personId');
break;
case 'countryOfBirth':
case 'nationality':
$qb->addSelect(sprintf('IDENTITY(person.%s) as %s', $f, $f));
@@ -138,25 +163,7 @@ class ListPersonHelper
break;
case 'spokenLanguages':
$qb
->leftJoin('person.spokenLanguages', 'spokenLanguage')
->addSelect('AGGREGATE(spokenLanguage.id) AS spokenLanguages')
->addGroupBy('person');
if (in_array('center', $fields, true)) {
$qb->addGroupBy('center');
}
if (in_array('address_fields', $fields, true)) {
$qb
->addGroupBy('address_fieldsid')
->addGroupBy('address_fieldscountry_t.id')
->addGroupBy('address_fieldspostcode_t.id');
}
if (in_array('household_id', $fields, true)) {
$qb->addGroupBy('household_id');
}
$qb->addSelect('(SELECT AGGREGATE(language.id) FROM ' . Language::class . ' language WHERE language MEMBER OF person.spokenLanguages) AS spokenLanguages');
break;

View File

@@ -95,29 +95,103 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository
* * then, closed works
*
* @return AccompanyingPeriodWork[]
* @param array{types?: list<SocialAction>, user?: list<User>, after?: null|\DateTimeImmutable, before?: null|\DateTimeImmutable} $filters
*/
public function findByAccompanyingPeriodOpenFirst(AccompanyingPeriod $period, int $limit = 10, int $offset = 0): array
public function findByAccompanyingPeriodOpenFirst(AccompanyingPeriod $period, array $filters, int $limit = 10, int $offset = 0): array
{
$rsm = new ResultSetMappingBuilder($this->em);
$rsm->addRootEntityFromClassMetadata(AccompanyingPeriodWork::class, 'w');
$sql = "SELECT {$rsm} FROM chill_person_accompanying_period_work w
WHERE accompanyingPeriod_id = :periodId
ORDER BY
CASE WHEN enddate IS NULL THEN '-infinity'::timestamp ELSE 'infinity'::timestamp END ASC,
startdate DESC,
enddate DESC,
id DESC
LIMIT :limit OFFSET :offset";
LEFT JOIN chill_person_accompanying_period_work_referrer AS rw ON accompanyingperiodwork_id = w.id
WHERE accompanyingPeriod_id = :periodId";
// implement filters
if ([] !== ($filters['types'] ?? [])) {
$sql .= " AND w.socialaction_id IN (:types)";
}
if ([] !== ($filters['user'] ?? [])) {
$sql .= " AND rw.user_id IN ("
. implode(
', ',
// we add a user_xx for each key of the 'user' list
array_map(fn (User $u, int $idx) => ':user_' . $idx, $filters['user'], array_keys($filters['user']))
)
. ")";
}
$sql .= " AND daterange(:after::date, :before::date) && daterange(w.startDate, w.endDate)";
// if the start and end date were inversed, we inverse the order to avoid an error
if (null !== ($filters['after'] ?? null) && null !== ($filters['before']) && $filters['after'] > $filters['before']) {
$before = $filters['after'];
$after = $filters['before'];
} else {
$before = $filters['before'];
$after = $filters['after'];
}
// set limit and offset
$sql .= " ORDER BY
CASE WHEN enddate IS NULL THEN '-infinity'::timestamp ELSE 'infinity'::timestamp END ASC,
startdate DESC,
enddate DESC,
id DESC";
$sql .= " LIMIT :limit OFFSET :offset";
$typeIds = [];
foreach ($filters['types'] as $type) {
$typeIds[] = $type->getId();
}
$nq = $this->em->createNativeQuery($sql, $rsm)
->setParameter('periodId', $period->getId(), Types::INTEGER)
->setParameter('types', $typeIds)
->setParameter('after', $after)
->setParameter('before', $before)
->setParameter('limit', $limit, Types::INTEGER)
->setParameter('offset', $offset, Types::INTEGER);
foreach ($filters['user'] as $key => $user) {
$nq->setParameter('user_' . $key, $user);
}
return $nq->getResult();
}
/**
* Return a list of types of social actions associated to the accompanying period
*
* @return array<SocialAction>
*/
public function findActionTypeByPeriod(AccompanyingPeriod $period): array
{
$in = $this->em->createQueryBuilder();
$in
->select('1')
->from(AccompanyingPeriodWork::class, 'apw');
$in->andWhere('apw.accompanyingPeriod = :period')->setParameter('period', $period);
// join between the embedded exist query and the main query
$in->andWhere('apw.socialAction = sa');
$qb = $this->em->createQueryBuilder()->setParameters($in->getParameters());
$qb
->select('sa')
->from(SocialAction::class, 'sa')
->where(
$qb->expr()->exists($in->getDQL())
);
return $qb->getQuery()->getResult();
}
public function findNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until, int $limit = 20, int $offset = 0): array
{
return $this->buildQueryNearEndDateByUser($user, $since, $until)

View File

@@ -68,27 +68,45 @@
<ul class="list-content fa-ul">
<li v-if="person.current_household_id">
<i class="fa fa-li fa-map-marker"></i>
<address-render-box v-if="person.current_household_address"
:address="person.current_household_address"
:isMultiline="isMultiline">
</address-render-box>
<p v-else class="chill-no-data-statement">
{{ $t('renderbox.household_without_address') }}
</p>
<address-render-box v-if="person.current_household_address" :address="person.current_household_address" :isMultiline="isMultiline"></address-render-box>
<p v-else class="chill-no-data-statement">{{ $t('renderbox.household_without_address') }}</p>
<a v-if="options.addHouseholdLink === true"
:href="getCurrentHouseholdUrl"
:title="$t('persons_associated.show_household_number', {id: person.current_household_id})">
<span class="badge rounded-pill bg-chill-beige">
<i class="fa fa-fw fa-home"></i><!--{{ $t('persons_associated.show_household') }}-->
</span>
<span class="badge rounded-pill bg-chill-beige">
<i class="fa fa-fw fa-home"></i><!--{{ $t('persons_associated.show_household') }}-->
</span>
</a>
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-map-marker"></i>
<p class="chill-no-data-statement">
{{ $t('renderbox.no_data') }}
</p>
<i class="fa fa-li fa-map-marker"></i><p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
</li>
<template v-if="this.showResidentialAddresses && (person.current_residential_addresses || []).length > 0">
<li v-for="(addr, i) in person.current_residential_addresses" :key="i">
<i class="fa fa-li fa-map-marker"></i>
<div v-if="addr.address">
<span class="item-key">{{ $t('renderbox.residential_address') }}:</span>
<div style="margin-top: -1em;">
<address-render-box :address="addr.address" :isMultiline="isMultiline"></address-render-box>
</div>
</div>
<div v-else-if="addr.hostPerson" class="mt-3">
<p>{{ $t('renderbox.located_at') }}:</p>
<span class="chill-entity entity-person badge-person">
<person-text v-if="addr.hostPerson" :person="addr.hostPerson"></person-text>
</span>
<address-render-box v-if="addr.hostPerson.address" :address="addr.hostPerson.address" :isMultiline="isMultiline"></address-render-box>
</div>
<div v-else-if="addr.hostThirdParty" class="mt-3">
<p>{{ $t('renderbox.located_at') }}:</p>
<span class="chill-entity entity-person badge-thirdparty">
<third-party-text v-if="addr.hostThirdParty" :thirdparty="addr.hostThirdParty"></third-party-text>
</span>
<address-render-box v-if="addr.hostThirdParty.address" :address="addr.hostThirdParty.address" :isMultiline="isMultiline"></address-render-box>
</div>
</li>
</template>
<li v-if="person.email">
<i class="fa fa-li fa-envelope-o"></i>
@@ -131,53 +149,6 @@
</div>
</div>
<div class="item-col mx-3"
v-if="this.showResidentialAddresses && (person.current_residential_addresses || []).length > 0">
<div class="float-button bottom">
<div class="box">
<ul class="list-content fa-ul">
<li v-for="(addr, i) in person.current_residential_addresses" :key="i">
<i class="fa fa-li fa-map-marker"></i>
<div v-if="addr.address">
<address-render-box
:address="addr.address"
:isMultiline="isMultiline">
</address-render-box>
<p>({{ $t('renderbox.residential_address') }})</p>
</div>
<div v-else-if="addr.hostPerson" class="mt-3">
<p>{{ $t('renderbox.located_at') }}:</p>
<span class="chill-entity entity-person badge-person">
<person-text
v-if="addr.hostPerson"
:person="addr.hostPerson"
></person-text>
</span>
<address-render-box v-if="addr.hostPerson.address"
:address="addr.hostPerson.address"
:isMultiline="isMultiline">
</address-render-box>
</div>
<div v-else-if="addr.hostThirdParty" class="mt-3">
<p>{{ $t('renderbox.located_at') }}:</p>
<span class="chill-entity entity-person badge-thirdparty">
<third-party-text
v-if="addr.hostThirdParty"
:thirdparty="addr.hostThirdParty"
></third-party-text>
</span>
<address-render-box v-if="addr.hostThirdParty.address"
:address="addr.hostThirdParty.address"
:isMultiline="isMultiline">
</address-render-box>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
<slot name="end-bloc"></slot>

View File

@@ -5,18 +5,23 @@
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_entity_workflow_pick') }}
{{ encore_entry_script_tags('mod_pickentity_type') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_entity_workflow_pick') }}
{{ encore_entry_link_tags('mod_pickentity_type') }}
{% endblock %}
{% block content %}
<div class="accompanying-course-work">
<h1>{{ block('title') }}</h1>
{{ filter|chill_render_filter_order_helper }}
{% if works|length == 0 %}
<p class="chill-no-data-statement">{{ 'accompanying_course_work.Any work'|trans }}</p>
{% else %}

View File

@@ -59,7 +59,7 @@
<span class=" d-block d-sm-inline-block">
{{ address|chill_entity_render_box({
'render': 'inline', 'multiline': false, 'with_picto': true, 'with_delimiter': true,
'details_button': false
'details_button': true
}) }}
</span>
{% endif %}

View File

@@ -56,13 +56,12 @@
{%- if address is not null -%}
{{ address|chill_entity_render_box({
'render': 'inline', 'multiline': false, 'with_picto': true, 'with_delimiter': true,
'details_button': false
'details_button': true
}) }}
{%- endif -%}
{% if person.getCurrentHousehold is not null %}
<a class="btn household-link text-end"
href="{{ chill_path_add_return_path('chill_person_household_summary', { 'household_id' : person.getCurrentHousehold.id } ) }}"
title="{{ 'Show household'|trans }}">
<a href="{{ chill_path_add_return_path('chill_person_household_summary', { 'household_id' : person.getCurrentHousehold.id } ) }}"
class="btn btn-sm household-link" title="{{ 'Show household'|trans }}">
<i class="fa fa-lg fa-home"></i>
</a>
{% endif %}

View File

@@ -47,8 +47,7 @@ class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInte
public function getEntityData(EntityWorkflow $entityWorkflow, array $options = []): array
{
return [
'persons' => $this->getRelatedEntity($entityWorkflow)
->getPersons(),
'persons' => $this->getRelatedEntity($entityWorkflow)?->getPersons() ?? [],
];
}

View File

@@ -4,35 +4,27 @@ services:
autowire: true
## Indicators
chill.person.export.count_person:
class: Chill\PersonBundle\Export\Export\CountPerson
autowire: true
autoconfigure: true
Chill\PersonBundle\Export\Export\CountPerson:
tags:
- { name: chill.export, alias: count_person }
chill.person.export.count_person_with_accompanying_course:
class: Chill\PersonBundle\Export\Export\CountPersonWithAccompanyingCourse
autowire: true
autoconfigure: true
Chill\PersonBundle\Export\Export\CountPersonWithAccompanyingCourse:
tags:
- { name: chill.export, alias: count_person_with_accompanying_course }
Chill\PersonBundle\Export\Export\ListPerson:
autowire: true
autoconfigure: true
tags:
- { name: chill.export, alias: list_person }
Chill\PersonBundle\Export\Export\ListPersonWithAccompanyingPeriod:
autowire: true
autoconfigure: true
Chill\PersonBundle\Export\Export\ListPersonHavingAccompanyingPeriod:
tags:
- { name: chill.export, alias: list_person_with_acp }
Chill\PersonBundle\Export\Export\ListPersonWithAccompanyingPeriodDetails:
tags:
- { name: chill.export, alias: list_person_with_acp_details }
Chill\PersonBundle\Export\Export\ListAccompanyingPeriod:
autowire: true
autoconfigure: true
tags:
- { name: chill.export, alias: list_acp }

View File

@@ -913,6 +913,9 @@ accompanying_course_work:
social_evaluation: Évaluation
private_comment: Commentaire privé
timeSpent: Temps de rédaction
date_filter: Filtrer par date
types_filter: Filtrer par type d'action
user_filter: Filtrer par intervenant
#
@@ -998,6 +1001,8 @@ notification:
Notify referrer: Notifier le référent
Notify any: Notifier d'autres utilisateurs
personId: Identifiant de l'usager
export:
export:
acp_stats:
@@ -1147,13 +1152,15 @@ export:
list:
person_with_acp:
List peoples having an accompanying period: Liste des usagers ayant un parcours d'accompagnement
List peoples having an accompanying period with period details: Liste des usagers concernés avec détail de chaque parcours
Create a list of people having an accompaying periods, according to various filters.: Génère une liste des usagers ayant un parcours d'accompagnement, selon différents critères liés au parcours ou à l'usager
Create a list of people having an accompaying periods with details of period, according to various filters.: Génère une liste des usagers ayant un parcours d'accompagnement, selon différents critères liés au parcours ou à l'usager. Ajoute les détails du parcours à la liste.
acp:
List of accompanying periods: Liste des parcours d'accompagnements
Generate a list of accompanying periods, filtered on different parameters.: Génère une liste des parcours d'accompagnement, filtrée sur différents paramètres.
Date of calculation for associated elements: Date de calcul des éléments associés
The associated referree, localisation, and other elements will be valid at this date: Les éléments associés, comme la localisation, le référent et d'autres éléments seront valides à cette date
id: Identifiant du parcours
acpId: Identifiant du parcours
openingDate: Date d'ouverture du parcours
closingDate: Date de fermeture du parcours
closingMotive: Motif de cloture
@@ -1161,14 +1168,14 @@ export:
confidential: Confidentiel
emergency: Urgent
intensity: Intensité
createdAt: Créé le
updatedAt: Dernière mise à jour le
acpCreatedAt: Créé le
acpUpdatedAt: Dernière mise à jour le
acpOrigin: Origine du parcours
origin: Origine du parcours
acpClosingMotive: Motif de fermeture
acpJob: Métier du parcours
createdBy: Créé par
updatedBy: Dernière modification par
acpCreatedBy: Créé par
acpUpdatedBy: Dernière modification par
administrativeLocation: Location administrative
step: Etape
stepSince: Dernière modification de l'étape
@@ -1176,7 +1183,7 @@ export:
referrerSince: Référent depuis le
locationIsPerson: Parcours localisé auprès d'un usager concerné
locationIsTemp: Parcours avec une localisation temporaire
acpLocationPersonName: Usager auprès duquel le parcours est localisé
locationPersonName: Usager auprès duquel le parcours est localisé
locationPersonId: Identifiant de l'usager auprès duquel le parcours est localisé
acpaddress_fieldscountry: Pays de l'adresse
isRequestorPerson: Le demandeur est-il un usager ?