Feature: Add a list export for evaluation, actions and household

This commit is contained in:
2023-01-26 14:22:30 +00:00
committed by Julien Fastré
parent 9ada19ef23
commit e54c2ca712
24 changed files with 1323 additions and 50 deletions

View File

@@ -24,7 +24,7 @@ use Doctrine\ORM\QueryBuilder;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
class CountSocialWorkActions implements ExportInterface, GroupedExportInterface
class CountAccompanyingPeriodWork implements ExportInterface, GroupedExportInterface
{
protected EntityManagerInterface $em;

View File

@@ -19,7 +19,8 @@ use Chill\MainBundle\Export\Helper\DateTimeHelper;
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
use Chill\MainBundle\Export\Helper\UserHelper;
use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
@@ -87,6 +88,8 @@ class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
private PersonRepository $personRepository;
private RollingDateConverterInterface $rollingDateConverter;
private SocialIssueRender $socialIssueRender;
private SocialIssueRepository $socialIssueRepository;
@@ -110,6 +113,7 @@ class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
SocialIssueRepository $socialIssueRepository,
SocialIssueRender $socialIssueRender,
TranslatableStringHelperInterface $translatableStringHelper,
RollingDateConverterInterface $rollingDateConverter,
UserHelper $userHelper
) {
$this->addressHelper = $addressHelper;
@@ -122,14 +126,14 @@ class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
$this->thirdPartyRender = $thirdPartyRender;
$this->thirdPartyRepository = $thirdPartyRepository;
$this->translatableStringHelper = $translatableStringHelper;
$this->rollingDateConverter = $rollingDateConverter;
$this->userHelper = $userHelper;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('calc_date', ChillDateType::class, [
'input' => 'datetime_immutable',
->add('calc_date', PickRollingDateType::class, [
'label' => 'export.list.acp.Date of calculation for associated elements',
'help' => 'export.list.acp.The associated referree, localisation, and other elements will be valid at this date',
'required' => true,
@@ -306,7 +310,7 @@ class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
->setParameter('list_acp_step', AccompanyingPeriod::STEP_DRAFT)
->setParameter('authorized_centers', $centers);
$this->addSelectClauses($qb, $data['calc_date']);
$this->addSelectClauses($qb, $this->rollingDateConverter->convert($data['calc_date']));
return $qb;
}

View File

@@ -0,0 +1,396 @@
<?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\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Export\Helper\AggregateStringHelper;
use Chill\MainBundle\Export\Helper\DateTimeHelper;
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
use Chill\MainBundle\Export\Helper\UserHelper;
use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkGoal;
use Chill\PersonBundle\Entity\AccompanyingPeriod\UserHistory;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Entity\SocialWork\Evaluation;
use Chill\PersonBundle\Entity\SocialWork\Goal;
use Chill\PersonBundle\Entity\SocialWork\Result;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper;
use DateTimeImmutable;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class ListAccompanyingPeriodWork implements ListInterface, GroupedExportInterface
{
private const FIELDS = [
'id',
'socialActionId',
'socialAction',
'socialIssue',
'acp_id',
'acp_user',
'startDate',
'endDate',
'goalsId',
'goalsTitle',
'goalResultsId',
'goalResultsTitle',
'resultsId',
'resultsTitle',
'evaluationsId',
'evaluationsTitle',
'note',
'personsId',
'personsName',
'thirdParties',
'handlingThierParty',
'referrers',
'createdAt',
'createdBy',
'updatedAt',
'updatedBy',
];
private AggregateStringHelper $aggregateStringHelper;
private DateTimeHelper $dateTimeHelper;
private EntityManagerInterface $entityManager;
private LabelPersonHelper $personHelper;
private RollingDateConverterInterface $rollingDateConverter;
private SocialActionRender $socialActionRender;
private SocialActionRepository $socialActionRepository;
private SocialIssueRender $socialIssueRender;
private SocialIssueRepository $socialIssueRepository;
private LabelThirdPartyHelper $thirdPartyHelper;
private TranslatableStringExportLabelHelper $translatableStringExportLabelHelper;
private UserHelper $userHelper;
public function __construct(
EntityManagerInterface $entityManager,
DateTimeHelper $dateTimeHelper,
UserHelper $userHelper,
LabelPersonHelper $personHelper,
LabelThirdPartyHelper $thirdPartyHelper,
TranslatableStringExportLabelHelper $translatableStringExportLabelHelper,
SocialIssueRender $socialIssueRender,
SocialIssueRepository $socialIssueRepository,
SocialActionRender $socialActionRender,
RollingDateConverterInterface $rollingDateConverter,
AggregateStringHelper $aggregateStringHelper,
SocialActionRepository $socialActionRepository
) {
$this->entityManager = $entityManager;
$this->dateTimeHelper = $dateTimeHelper;
$this->userHelper = $userHelper;
$this->personHelper = $personHelper;
$this->thirdPartyHelper = $thirdPartyHelper;
$this->translatableStringExportLabelHelper = $translatableStringExportLabelHelper;
$this->socialIssueRender = $socialIssueRender;
$this->socialIssueRepository = $socialIssueRepository;
$this->socialActionRender = $socialActionRender;
$this->rollingDateConverter = $rollingDateConverter;
$this->aggregateStringHelper = $aggregateStringHelper;
$this->socialActionRepository = $socialActionRepository;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('calc_date', PickRollingDateType::class, [
'label' => 'export.list.acpw.Date of calculation for associated elements',
'help' => 'export.list.acpw.help_description',
'required' => true,
'data' => new RollingDate(RollingDate::T_TODAY),
]);
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_LIST];
}
public function getDescription(): string
{
return 'export.list.acpw.List description';
}
public function getGroup(): string
{
return 'Exports of social work actions';
}
public function getLabels($key, array $values, $data)
{
switch ($key) {
case 'startDate':
case 'endDate':
case 'createdAt':
case 'updatedAt':
return $this->dateTimeHelper->getLabel('export.list.acpw.' . $key);
case 'socialAction':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acpw.' . $key;
}
if (null === $value) {
return '';
}
return $this->socialActionRender->renderString(
$this->socialActionRepository->find($value),
[]
);
};
case 'socialIssue':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acpw.' . $key;
}
if (null === $value) {
return '';
}
return $this->socialIssueRender->renderString(
$this->socialIssueRepository->find($value),
[]
);
};
case 'createdBy':
case 'updatedBy':
case 'acp_user':
return $this->userHelper->getLabel($key, $values, 'export.list.acpw.' . $key);
case 'referrers':
//$date = $this->rollDateConverter->convert($data['calc_date'])->format('d/m/Y');
return $this->userHelper->getLabel($key, $values, 'export.list.acpw.' . $key);
case 'personsName':
return $this->personHelper->getLabelMulti($key, $values, 'export.list.acpw.' . $key);
case 'handlingThierParty':
return $this->thirdPartyHelper->getLabel($key, $values, 'export.list.acpw.' . $key);
case 'thirdParties':
return $this->thirdPartyHelper->getLabelMulti($key, $values, 'export.list.acpw.' . $key);
case 'personsId':
case 'goalsId':
case 'goalResultsId':
case 'resultsId':
case 'evaluationsId':
return $this->aggregateStringHelper->getLabelMulti($key, $values, 'export.list.acpw.' . $key);
case 'goalsTitle':
case 'goalResultsTitle':
case 'resultsTitle':
case 'evaluationsTitle':
return $this->translatableStringExportLabelHelper->getLabelMulti($key, $values, 'export.list.acpw.' . $key);
default:
return static function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acpw.' . $key;
}
if (null === $value) {
return '';
}
return $value;
};
}
}
public function getQueryKeys($data)
{
return self::FIELDS;
}
public function getResult($query, $data)
{
return $query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR);
}
public function getTitle(): string
{
return 'export.list.acpw.List of accompanying period works';
}
public function getType(): string
{
return Declarations::SOCIAL_WORK_ACTION_TYPE;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static function ($el) {
return $el['center'];
}, $acl);
$qb = $this->entityManager->createQueryBuilder();
$qb
->from(AccompanyingPeriodWork::class, 'acpw')
->distinct()
->select('acpw.id AS id')
->join('acpw.accompanyingPeriod', 'acp')
->join('acp.participations', 'acppart')
->join('acppart.person', 'person')
// ignore participation which didn't last one day, at least
->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL')
// get participants at the given date
->andWhere('acppart.startDate <= :calc_date AND (acppart.endDate > :calc_date OR acppart.endDate IS NULL)')
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM ' . PersonCenterHistory::class . ' acl_count_person_history WHERE acl_count_person_history.person = person
AND acl_count_person_history.center IN (:authorized_centers)
'
)
)
->setParameter('authorized_centers', $centers)
->setParameter('calc_date', $this->rollingDateConverter->convert($data['calc_date']));
$this->addSelectClauses($qb, $this->rollingDateConverter->convert($data['calc_date']));
return $qb;
}
public function requiredRole(): string
{
return AccompanyingPeriodVoter::STATS;
}
public function supportsModifiers(): array
{
return [
Declarations::SOCIAL_WORK_ACTION_TYPE,
Declarations::ACP_TYPE,
Declarations::PERSON_TYPE,
];
}
private function addSelectClauses(QueryBuilder $qb, DateTimeImmutable $calcDate): void
{
// add regular fields
foreach ([
'startDate',
'endDate',
'note',
'createdAt',
'updatedAt',
] as $field) {
$qb->addSelect(sprintf('acpw.%s AS %s', $field, $field));
}
// those with identity
foreach ([
'createdBy',
'updatedBy',
'handlingThierParty',
] as $field) {
$qb->addSelect(sprintf('IDENTITY(acpw.%s) AS %s', $field, $field));
}
// join socialaction
$qb
->join('acpw.socialAction', 'sa')
->addSelect('sa.id AS socialActionId')
->addSelect('sa.id AS socialAction')
->addSelect('IDENTITY(sa.issue) AS socialIssue');
// join acp
$qb
->addSelect('acp.id AS acp_id')
->addSelect('IDENTITY(acp.user) AS acp_user');
// persons
$qb
->addSelect('(SELECT AGGREGATE(person_acpw_member.id) FROM ' . Person::class . ' person_acpw_member '
. 'WHERE person_acpw_member MEMBER OF acpw.persons) AS personsId')
->addSelect('(SELECT AGGREGATE(person1_acpw_member.id) FROM ' . Person::class . ' person1_acpw_member '
. 'WHERE person1_acpw_member MEMBER OF acpw.persons) AS personsName');
// referrers => at date XXXX
$qb
->addSelect('(SELECT IDENTITY(history.user) FROM ' . UserHistory::class . ' history ' .
'WHERE history.accompanyingPeriod = acp AND history.startDate <= :calcDate AND (history.endDate IS NULL OR history.endDate > :calcDate)) AS referrers');
// thirdparties
$qb
->addSelect('(SELECT AGGREGATE(tp.id) FROM ' . ThirdParty::class . ' tp '
. 'WHERE tp MEMBER OF acpw.thirdParties) AS thirdParties');
// goals
$qb
->addSelect('(SELECT AGGREGATE(IDENTITY(goal.goal)) FROM ' . AccompanyingPeriodWorkGoal::class . ' goal '
. 'WHERE goal MEMBER OF acpw.goals) AS goalsId')
->addSelect('(SELECT AGGREGATE(g.title) FROM ' . AccompanyingPeriodWorkGoal::class . ' goal1 '
. 'LEFT JOIN ' . Goal::class . ' g WITH goal1.goal = g.id WHERE goal1 MEMBER OF acpw.goals) AS goalsTitle');
// goals results
$qb
->addSelect('(SELECT AGGREGATE(wr.id) FROM ' . Result::class . ' wr '
. 'JOIN ' . AccompanyingPeriodWorkGoal::class . ' wg WITH wr MEMBER OF wg.results '
. 'WHERE wg MEMBER OF acpw.goals) AS goalResultsId')
->addSelect('(SELECT AGGREGATE(wr1.title) FROM ' . Result::class . ' wr1 '
. 'JOIN ' . AccompanyingPeriodWorkGoal::class . ' wg1 WITH wr1 MEMBER OF wg1.results '
. 'WHERE wg1 MEMBER OF acpw.goals) AS goalResultsTitle');
// results
$qb
->addSelect('(SELECT AGGREGATE(result.id) FROM ' . Result::class . ' result '
. 'WHERE result MEMBER OF acpw.results ) AS resultsId ')
->addSelect('(SELECT AGGREGATE (result1.title) FROM ' . Result::class . ' result1 '
. 'WHERE result1 MEMBER OF acpw.results ) AS resultsTitle ');
// evaluations
$qb
->addSelect('(SELECT AGGREGATE(IDENTITY(we.evaluation)) FROM ' . AccompanyingPeriodWorkEvaluation::class . ' we '
. 'WHERE we MEMBER OF acpw.accompanyingPeriodWorkEvaluations ) AS evaluationsId ')
->addSelect('(SELECT AGGREGATE(ev.title) FROM ' . AccompanyingPeriodWorkEvaluation::class . ' we1 '
. 'LEFT JOIN ' . Evaluation::class . ' ev WITH we1.evaluation = ev.id '
. 'WHERE we1 MEMBER OF acpw.accompanyingPeriodWorkEvaluations ) AS evaluationsTitle ');
$qb->setParameter('calcDate', $calcDate);
}
}

View File

@@ -0,0 +1,336 @@
<?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\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Export\Helper\AggregateStringHelper;
use Chill\MainBundle\Export\Helper\DateTimeHelper;
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
use Chill\MainBundle\Export\Helper\UserHelper;
use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
//use Chill\MainBundle\Service\RollingDate\RollingDateConverter;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Entity\AccompanyingPeriod\UserHistory;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use DateTimeImmutable;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class ListEvaluation implements ListInterface, GroupedExportInterface
{
private const FIELDS = [
'id',
'startDate',
'endDate',
'maxDate',
'warningInterval',
'acpw_id',
'acpw_startDate',
'acpw_endDate',
'acpw_socialaction_id',
'acpw_socialaction',
'acpw_socialissue',
'acpw_referrers',
'acpw_note',
'acpw_acp_id',
'acpw_acp_user',
'acpw_persons_id',
'acpw_persons',
'comment',
'eval_title',
'createdAt',
'updatedAt',
'createdBy',
'updatedBy',
];
private AggregateStringHelper $aggregateStringHelper;
private DateTimeHelper $dateTimeHelper;
private EntityManagerInterface $entityManager;
private LabelPersonHelper $personHelper;
private RollingDateConverterInterface $rollingDateConverter;
private SocialActionRender $socialActionRender;
private SocialActionRepository $socialActionRepository;
private SocialIssueRender $socialIssueRender;
private SocialIssueRepository $socialIssueRepository;
private TranslatableStringExportLabelHelper $translatableStringExportLabelHelper;
private UserHelper $userHelper;
public function __construct(
EntityManagerInterface $entityManager,
SocialIssueRender $socialIssueRender,
SocialIssueRepository $socialIssueRepository,
SocialActionRender $socialActionRender,
SocialActionRepository $socialActionRepository,
UserHelper $userHelper,
LabelPersonHelper $personHelper,
DateTimeHelper $dateTimeHelper,
TranslatableStringExportLabelHelper $translatableStringExportLabelHelper,
AggregateStringHelper $aggregateStringHelper,
RollingDateConverterInterface $rollingDateConverter
) {
$this->entityManager = $entityManager;
$this->socialIssueRender = $socialIssueRender;
$this->socialIssueRepository = $socialIssueRepository;
$this->socialActionRender = $socialActionRender;
$this->socialActionRepository = $socialActionRepository;
$this->userHelper = $userHelper;
$this->personHelper = $personHelper;
$this->dateTimeHelper = $dateTimeHelper;
$this->translatableStringExportLabelHelper = $translatableStringExportLabelHelper;
$this->aggregateStringHelper = $aggregateStringHelper;
$this->rollingDateConverter = $rollingDateConverter;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('calc_date', PickRollingDateType::class, [
'label' => 'export.list.eval.Date of calculation for associated elements',
'help' => 'export.list.eval.help_description',
'required' => true,
'data' => new RollingDate(RollingDate::T_TODAY),
]);
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_LIST];
}
public function getDescription(): string
{
return 'export.list.eval.Generate a list of evaluations, filtered on different parameters';
}
public function getGroup(): string
{
return 'Exports of evaluations';
}
public function getLabels($key, array $values, $data)
{
switch ($key) {
case 'startDate':
case 'endDate':
case 'maxDate':
case 'acpw_startDate':
case 'acpw_endDate':
case 'createdAt':
case 'updatedAt':
return $this->dateTimeHelper->getLabel('export.list.eval.' . $key);
case 'acpw_socialaction':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.eval.' . $key;
}
if (null === $value || '' === $value) {
return '';
}
return $this->socialActionRender->renderString(
$this->socialActionRepository->find($value),
[]
);
};
case 'acpw_socialissue':
return function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.eval.' . $key;
}
if (null === $value || '' === $value) {
return '';
}
return $this->socialIssueRender->renderString(
$this->socialIssueRepository->find($value),
[]
);
};
case 'createdBy':
case 'updatedBy':
case 'acpw_acp_user':
return $this->userHelper->getLabel($key, $values, 'export.list.eval.' . $key);
case 'acpw_referrers':
return $this->userHelper->getLabel($key, $values, 'export.list.eval.' . $key);
case 'acpw_persons_id':
return $this->aggregateStringHelper->getLabelMulti($key, $values, 'export.list.eval.' . $key);
case 'acpw_persons':
return $this->personHelper->getLabelMulti($key, $values, 'export.list.eval.' . $key);
case 'eval_title':
return $this->translatableStringExportLabelHelper
->getLabel($key, $values, 'export.list.eval.' . $key);
default:
return static function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.eval.' . $key;
}
if (null === $value) {
return '';
}
return $value;
};
}
}
public function getQueryKeys($data)
{
return self::FIELDS;
}
public function getResult($query, $data)
{
return $query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR);
}
public function getTitle(): string
{
return 'export.list.eval.List of evaluations';
}
public function getType(): string
{
return Declarations::EVAL_TYPE;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static function ($el) {
return $el['center'];
}, $acl);
$qb = $this->entityManager->createQueryBuilder();
$qb
->from(AccompanyingPeriodWorkEvaluation::class, 'workeval')
->distinct()
->select('workeval.id AS id')
->join('workeval.accompanyingPeriodWork', 'acpw')
->join('acpw.accompanyingPeriod', 'acp')
->join('acp.participations', 'acppart')
->join('acppart.person', 'person')
// ignore participation which didn't last one day, at least
->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL')
// get participants at the given date
->andWhere('acppart.startDate <= :calc_date AND (acppart.endDate > :calc_date OR acppart.endDate IS NULL)')
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM ' . PersonCenterHistory::class . ' acl_count_person_history WHERE acl_count_person_history.person = person
AND acl_count_person_history.center IN (:authorized_centers)
'
)
)
->setParameter('authorized_centers', $centers)
->setParameter('calc_date', $this->rollingDateConverter->convert($data['calc_date']));
$this->addSelectClauses($qb, $this->rollingDateConverter->convert($data['calc_date']));
return $qb;
}
public function requiredRole(): string
{
return AccompanyingPeriodVoter::STATS;
}
public function supportsModifiers(): array
{
return [
Declarations::EVAL_TYPE,
Declarations::SOCIAL_WORK_ACTION_TYPE,
Declarations::ACP_TYPE,
Declarations::PERSON_TYPE,
];
}
private function addSelectClauses(QueryBuilder $qb, DateTimeImmutable $calc_date): void
{
// add the regular fields
foreach (['startDate', 'endDate', 'maxDate', 'warningInterval', 'comment', 'createdAt', 'updatedAt'] as $field) {
$qb->addSelect(sprintf('workeval.%s AS %s', $field, $field));
}
// those with identity
foreach (['createdBy', 'updatedBy'] as $field) {
$qb->addSelect(sprintf('IDENTITY(workeval.%s) AS %s', $field, $field));
}
foreach (['id', 'startDate', 'endDate', 'note'] as $field) {
$qb->addSelect(sprintf('acpw.%s AS %s', $field, 'acpw_' . $field));
}
// join socialaction
$qb
->leftJoin('acpw.socialAction', 'sa')
->addSelect('sa.id AS acpw_socialaction_id')
->addSelect('sa.id AS acpw_socialaction')
->addSelect('IDENTITY(sa.issue) AS acpw_socialissue');
// join acp
$qb
->addSelect('acp.id AS acpw_acp_id')
->addSelect('IDENTITY(acp.user) AS acpw_acp_user');
// referrers => at date XXXX
$qb
->addSelect('(SELECT IDENTITY(history.user) FROM ' . UserHistory::class . ' history ' .
'WHERE history.accompanyingPeriod = acp AND history.startDate <= :calc_date AND (history.endDate IS NULL OR history.endDate > :calc_date)) AS acpw_referrers');
// persons
$qb
->addSelect('(SELECT AGGREGATE(person_acpw_member.id) FROM ' . Person::class . ' person_acpw_member '
. 'WHERE person_acpw_member MEMBER OF acpw.persons) AS acpw_persons_id')
->addSelect('(SELECT AGGREGATE(person1_acpw_member.id) FROM ' . Person::class . ' person1_acpw_member '
. 'WHERE person1_acpw_member MEMBER OF acpw.persons) AS acpw_persons');
// join evaluation
$qb
->leftJoin('workeval.evaluation', 'eval')
->addSelect('eval.title AS eval_title');
}
}

View File

@@ -0,0 +1,251 @@
<?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\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Export\Helper\AggregateStringHelper;
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Household\HouseholdComposition;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Security\Authorization\HouseholdVoter;
use DateTimeImmutable;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use function strlen;
class ListHouseholdInPeriod implements ListInterface, GroupedExportInterface
{
private const FIELDS = [
'id',
'membersCount',
'membersId',
'membersName',
'compositionNumberOfChildren',
'compositionComment',
'compositionType',
];
private ExportAddressHelper $addressHelper;
private AggregateStringHelper $aggregateStringHelper;
private EntityManagerInterface $entityManager;
private RollingDateConverterInterface $rollingDateConverter;
private TranslatableStringExportLabelHelper $translatableStringHelper;
public function __construct(
ExportAddressHelper $addressHelper,
AggregateStringHelper $aggregateStringHelper,
EntityManagerInterface $entityManager,
RollingDateConverterInterface $rollingDateConverter,
TranslatableStringExportLabelHelper $translatableStringHelper
) {
$this->addressHelper = $addressHelper;
$this->aggregateStringHelper = $aggregateStringHelper;
$this->entityManager = $entityManager;
$this->rollingDateConverter = $rollingDateConverter;
$this->translatableStringHelper = $translatableStringHelper;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('calc_date', PickRollingDateType::class, [
'label' => 'export.list.household.Date of calculation for associated elements',
'help' => 'export.list.household.help_description',
'data' => new RollingDate(RollingDate::T_TODAY),
'required' => true,
]);
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_LIST];
}
public function getDescription(): string
{
return 'export.list.household.List description';
}
public function getGroup(): string
{
return 'Exports of households';
}
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 'membersId':
case 'membersName':
return $this->aggregateStringHelper->getLabelMulti($key, $values, 'export.list.household.' . $key);
case 'compositionType':
//dump($values);
return $this->translatableStringHelper->getLabel($key, $values, 'export.list.household.' . $key);
default:
return static function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.household.' . $key;
}
return (string) $value;
};
}
}
public function getQueryKeys($data): array
{
return array_merge(
self::FIELDS,
$this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields')
);
}
public function getResult($query, $data)
{
return $query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR);
}
public function getTitle(): string
{
return 'export.list.household.List household associated with accompanying period title';
}
public function getType(): string
{
return Declarations::HOUSEHOLD_TYPE;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static function ($el) {
return $el['center'];
}, $acl);
$qb = $this->entityManager->createQueryBuilder();
$qb
->from(Household::class, 'household')
->distinct()
->select('household.id AS id')
->join('household.members', 'hmember')
->join('hmember.person', 'person')
->join('person.accompanyingPeriodParticipations', 'acppart')
->join('acppart.accompanyingPeriod', 'acp')
->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL')
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM ' . PersonCenterHistory::class . ' acl_count_person_history WHERE acl_count_person_history.person = person
AND acl_count_person_history.center IN (:authorized_centers)
'
)
)
->andWhere('hmember.startDate <= :count_household_at_date AND (hmember.endDate IS NULL OR hmember.endDate > :count_household_at_date)')
->setParameter('authorized_centers', $centers)
->setParameter('count_household_at_date', $this->rollingDateConverter->convert($data['calc_date']));
$this->addSelectClauses($qb, $this->rollingDateConverter->convert($data['calc_date']));
return $qb;
}
public function requiredRole(): string
{
return HouseholdVoter::STATS;
}
public function supportsModifiers(): array
{
return [
Declarations::HOUSEHOLD_TYPE,
Declarations::ACP_TYPE,
Declarations::PERSON_TYPE,
];
}
private function addSelectClauses(QueryBuilder $qb, DateTimeImmutable $calcDate): void
{
// members at date
$qb
->addSelect('(SELECT COUNT(members0) FROM ' . HouseholdMember::class . ' members0 '
. 'WHERE members0.startDate <= :calcDate AND (members0.endDate IS NULL OR members0.endDate > :calcDate) '
. 'AND members0 MEMBER OF household.members) AS membersCount')
->addSelect('(SELECT AGGREGATE(IDENTITY(members1.person)) FROM ' . HouseholdMember::class . ' members1 '
. 'WHERE members1.startDate <= :calcDate AND (members1.endDate IS NULL OR members1.endDate > :calcDate) '
. 'AND members1 MEMBER OF household.members) AS membersId')
->addSelect("(SELECT AGGREGATE(CONCAT(person2.firstName, ' ', person2.lastName)) FROM " . HouseholdMember::class . ' members2 '
. 'JOIN members2.person person2 '
. 'WHERE members2.startDate <= :calcDate AND (members2.endDate IS NULL OR members2.endDate > :calcDate) '
. 'AND members2 MEMBER OF household.members) AS membersName');
// composition at date
$qb
->addSelect('(SELECT compo.numberOfChildren FROM ' . HouseholdComposition::class . ' compo '
. 'WHERE compo.startDate <= :calcDate AND (compo.endDate IS NULL OR compo.endDate > :calcDate) '
. 'AND compo MEMBER OF household.compositions) AS compositionNumberOfChildren')
->addSelect('(SELECT compo1.comment.comment FROM ' . HouseholdComposition::class . ' compo1 '
. 'WHERE compo1.startDate <= :calcDate AND (compo1.endDate IS NULL OR compo1.endDate > :calcDate) '
. 'AND compo1 MEMBER OF household.compositions) AS compositionComment')
->addSelect('(
SELECT type2.label
FROM ' . HouseholdComposition::class . ' compo2
JOIN compo2.householdCompositionType type2
WHERE compo2.startDate <= :calcDate AND (compo2.endDate IS NULL OR compo2.endDate > :calcDate)
AND compo2 MEMBER OF household.compositions
) AS compositionType');
// address at date
$qb
->leftJoin('household.addresses', 'addresses')
->andWhere(
$qb->expr()->andX(
$qb->expr()->lte('addresses.validFrom', ':calcDate'),
$qb->expr()->orX(
$qb->expr()->isNull('addresses.validTo'),
$qb->expr()->gt('addresses.validTo', ':calcDate')
)
)
);
$this->addressHelper->addSelectClauses(
ExportAddressHelper::F_ALL,
$qb,
'addresses',
'address_fields'
);
// inject date parameter
$qb->setParameter('calcDate', $calcDate);
}
}