mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 14:43:49 +00:00
Merge remote-tracking branch 'origin/master' into cire16
This commit is contained in:
@@ -13,12 +13,13 @@ namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\ApiController;
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Chill\PersonBundle\Security\AuthorizedCenterOnPersonCreationInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
@@ -26,16 +27,37 @@ use function in_array;
|
||||
|
||||
class PersonApiController extends ApiController
|
||||
{
|
||||
private AuthorizationHelper $authorizationHelper;
|
||||
private AuthorizedCenterOnPersonCreationInterface $authorizedCenterOnPersonCreation;
|
||||
|
||||
private ConfigPersonAltNamesHelper $configPersonAltNameHelper;
|
||||
|
||||
private bool $showCenters;
|
||||
|
||||
public function __construct(
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
ConfigPersonAltNamesHelper $configPersonAltNameHelper
|
||||
AuthorizedCenterOnPersonCreationInterface $authorizedCenterOnPersonCreation,
|
||||
ConfigPersonAltNamesHelper $configPersonAltNameHelper,
|
||||
ParameterBagInterface $parameterBag
|
||||
) {
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->authorizedCenterOnPersonCreation = $authorizedCenterOnPersonCreation;
|
||||
$this->configPersonAltNameHelper = $configPersonAltNameHelper;
|
||||
$this->showCenters = $parameterBag->get('chill_main')['acl']['form_show_centers'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/api/1.0/person/creation/authorized-centers",
|
||||
* name="chill_person_person_creation_authorized_centers"
|
||||
* )
|
||||
*/
|
||||
public function authorizedCentersForCreation(): Response
|
||||
{
|
||||
$centers = $this->authorizedCenterOnPersonCreation->getCenters();
|
||||
|
||||
return $this->json(
|
||||
['showCenters' => $this->showCenters, 'centers' => $centers],
|
||||
Response::HTTP_OK,
|
||||
[],
|
||||
['gropus' => ['read']]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -13,6 +13,7 @@ namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||
use Chill\MainBundle\Serializer\Model\Collection;
|
||||
use Chill\PersonBundle\Entity\SocialWork\Evaluation;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@@ -39,9 +40,11 @@ class SocialWorkEvaluationApiController extends AbstractController
|
||||
*/
|
||||
public function listEvaluationBySocialAction(SocialAction $action): Response
|
||||
{
|
||||
$pagination = $this->paginatorFactory->create($action->getEvaluations()->count());
|
||||
$evaluations = $action->getEvaluations()->filter(static fn (Evaluation $eval) => $eval->isActive());
|
||||
|
||||
$evaluations = $action->getEvaluations()->slice(
|
||||
$pagination = $this->paginatorFactory->create($evaluations->count());
|
||||
|
||||
$evaluations = $evaluations->slice(
|
||||
$pagination->getCurrentPageFirstItemNumber(),
|
||||
$pagination->getItemsPerPage()
|
||||
);
|
||||
|
@@ -97,11 +97,11 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
$loader->load('services/exports_person.yaml');
|
||||
|
||||
if ($container->getParameter('chill_person.accompanying_period') !== 'hidden') {
|
||||
$loader->load('services/exports_accompanying_period.yaml');
|
||||
$loader->load('services/exports_accompanying_course.yaml');
|
||||
$loader->load('services/exports_social_actions.yaml');
|
||||
$loader->load('services/exports_evaluation.yaml');
|
||||
}
|
||||
$loader->load('services/exports_accompanying_course.yaml');
|
||||
$loader->load('services/exports_social_actions.yaml');
|
||||
$loader->load('services/exports_evaluation.yaml');
|
||||
|
||||
$loader->load('services/exports_household.yaml');
|
||||
}
|
||||
|
||||
@@ -944,10 +944,8 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
|
||||
/**
|
||||
* Add a widget "add a person" on the homepage, automatically.
|
||||
*
|
||||
* @param \Chill\PersonBundle\DependencyInjection\containerBuilder $container
|
||||
*/
|
||||
protected function prependHomepageWidget(containerBuilder $container)
|
||||
protected function prependHomepageWidget(ContainerBuilder $container)
|
||||
{
|
||||
$container->prependExtensionConfig('chill_main', [
|
||||
'widgets' => [
|
||||
|
@@ -22,6 +22,7 @@ use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodLocationHistory;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodStepHistory;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment;
|
||||
@@ -52,7 +53,7 @@ use Symfony\Component\Validator\GroupSequenceProviderInterface;
|
||||
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function in_array;
|
||||
use function array_key_exists;
|
||||
use const SORT_REGULAR;
|
||||
|
||||
/**
|
||||
@@ -129,6 +130,11 @@ class AccompanyingPeriod implements
|
||||
*/
|
||||
private ?Location $administrativeLocation = null;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Chill\CalendarBundle\Entity\Calendar", mappedBy="accompanyingPeriod")
|
||||
*/
|
||||
private Collection $calendars;
|
||||
|
||||
/**
|
||||
* @var DateTime
|
||||
*
|
||||
@@ -336,6 +342,12 @@ class AccompanyingPeriod implements
|
||||
*/
|
||||
private string $step = self::STEP_DRAFT;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=AccompanyingPeriodStepHistory::class,
|
||||
* mappedBy="period", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
*/
|
||||
private Collection $stepHistories;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime", nullable=true, options={"default": NULL})
|
||||
*/
|
||||
@@ -390,7 +402,7 @@ class AccompanyingPeriod implements
|
||||
*/
|
||||
public function __construct(?DateTime $dateOpening = null)
|
||||
{
|
||||
$this->setOpeningDate($dateOpening ?? new DateTime('now'));
|
||||
$this->calendars = new ArrayCollection(); // TODO we cannot add a dependency between AccompanyingPeriod and calendars
|
||||
$this->participations = new ArrayCollection();
|
||||
$this->scopes = new ArrayCollection();
|
||||
$this->socialIssues = new ArrayCollection();
|
||||
@@ -399,6 +411,8 @@ class AccompanyingPeriod implements
|
||||
$this->resources = new ArrayCollection();
|
||||
$this->userHistories = new ArrayCollection();
|
||||
$this->locationHistories = new ArrayCollection();
|
||||
$this->stepHistories = new ArrayCollection();
|
||||
$this->setOpeningDate($dateOpening ?? new DateTime('now'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -614,6 +628,11 @@ class AccompanyingPeriod implements
|
||||
);
|
||||
}
|
||||
|
||||
public function getCalendars(): Collection
|
||||
{
|
||||
return $this->calendars;
|
||||
}
|
||||
|
||||
public function getCenter(): ?Center
|
||||
{
|
||||
if ($this->getPersons()->count() === 0) {
|
||||
@@ -625,16 +644,18 @@ class AccompanyingPeriod implements
|
||||
|
||||
public function getCenters(): ?iterable
|
||||
{
|
||||
$centers = [];
|
||||
|
||||
foreach ($this->getPersons() as $person) {
|
||||
if (
|
||||
!in_array($person->getCenter(), $centers ?? [], true)
|
||||
&& null !== $person->getCenter()
|
||||
null !== $person->getCenter()
|
||||
&& !array_key_exists(spl_object_hash($person->getCenter()), $centers)
|
||||
) {
|
||||
$centers[] = $person->getCenter();
|
||||
$centers[spl_object_hash($person->getCenter())] = $person->getCenter();
|
||||
}
|
||||
}
|
||||
|
||||
return $centers ?? null;
|
||||
return array_values($centers);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -767,6 +788,24 @@ class AccompanyingPeriod implements
|
||||
return 'none';
|
||||
}
|
||||
|
||||
public function getNextCalendarsForPerson(Person $person, $limit = 5): Collection
|
||||
{
|
||||
$today = new DateTimeImmutable('today');
|
||||
$criteria = Criteria::create()
|
||||
->where(Criteria::expr()->gte('startDate', $today))
|
||||
//->andWhere(Criteria::expr()->memberOf('persons', $person))
|
||||
->orderBy(['startDate' => 'DESC'])
|
||||
->setMaxResults($limit * 2);
|
||||
|
||||
return $this->calendars->matching($criteria)
|
||||
->matching(
|
||||
// due to a bug, filter two times
|
||||
Criteria::create()
|
||||
->where(Criteria::expr()->memberOf('persons', $person))
|
||||
->setMaxResults($limit)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get openingDate.
|
||||
*
|
||||
@@ -966,6 +1005,11 @@ class AccompanyingPeriod implements
|
||||
return $this->step;
|
||||
}
|
||||
|
||||
public function getStepHistories(): Collection
|
||||
{
|
||||
return $this->stepHistories;
|
||||
}
|
||||
|
||||
public function getUser(): ?User
|
||||
{
|
||||
return $this->user;
|
||||
@@ -1234,7 +1278,11 @@ class AccompanyingPeriod implements
|
||||
*/
|
||||
public function setOpeningDate($openingDate)
|
||||
{
|
||||
$this->openingDate = $openingDate;
|
||||
if ($this->openingDate !== $openingDate) {
|
||||
$this->openingDate = $openingDate;
|
||||
|
||||
$this->ensureStepContinuity();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -1333,6 +1381,14 @@ class AccompanyingPeriod implements
|
||||
$this->bootPeriod();
|
||||
}
|
||||
|
||||
if (self::STEP_DRAFT !== $this->step && $previous !== $step) {
|
||||
// we create a new history
|
||||
$history = new AccompanyingPeriodStepHistory();
|
||||
$history->setStep($this->step)->setStartDate(new DateTimeImmutable('now'));
|
||||
|
||||
$this->addStepHistory($history);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -1373,6 +1429,17 @@ class AccompanyingPeriod implements
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function addStepHistory(AccompanyingPeriodStepHistory $stepHistory): self
|
||||
{
|
||||
if (!$this->stepHistories->contains($stepHistory)) {
|
||||
$this->stepHistories[] = $stepHistory;
|
||||
$stepHistory->setPeriod($this);
|
||||
$this->ensureStepContinuity();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function bootPeriod(): void
|
||||
{
|
||||
// first location history
|
||||
@@ -1384,6 +1451,43 @@ class AccompanyingPeriod implements
|
||||
$this->addLocationHistory($locationHistory);
|
||||
}
|
||||
|
||||
private function ensureStepContinuity(): void
|
||||
{
|
||||
// ensure continuity of histories
|
||||
$criteria = new Criteria();
|
||||
$criteria->orderBy(['startDate' => Criteria::ASC, 'id' => Criteria::ASC]);
|
||||
|
||||
/** @var Iterator $steps */
|
||||
$steps = $this->getStepHistories()->matching($criteria)->getIterator();
|
||||
$steps->rewind();
|
||||
|
||||
// we set the start date of the first step as the opening date, only if it is
|
||||
// not greater than the end date
|
||||
/** @var AccompanyingPeriodStepHistory $current */
|
||||
$current = $steps->current();
|
||||
|
||||
if (null === $current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->getOpeningDate()->format('Y-m-d') !== $current->getStartDate()->format('Y-m-d')
|
||||
&& ($this->getOpeningDate() <= $current->getEndDate() || null === $current->getEndDate())) {
|
||||
$current->setStartDate(DateTimeImmutable::createFromMutable($this->getOpeningDate()));
|
||||
}
|
||||
|
||||
// then we set all the end date to the start date of the next one
|
||||
do {
|
||||
/** @var AccompanyingPeriodStepHistory $current */
|
||||
$current = $steps->current();
|
||||
$steps->next();
|
||||
|
||||
if ($steps->valid()) {
|
||||
$next = $steps->current();
|
||||
$current->setEndDate($next->getStartDate());
|
||||
}
|
||||
} while ($steps->valid());
|
||||
}
|
||||
|
||||
private function setRequestorPerson(?Person $requestorPerson = null): self
|
||||
{
|
||||
$this->requestorPerson = $requestorPerson;
|
||||
|
@@ -0,0 +1,115 @@
|
||||
<?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\Entity\AccompanyingPeriod;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table("chill_person_accompanying_period_step_history")
|
||||
*/
|
||||
class AccompanyingPeriodStepHistory implements TrackCreationInterface, TrackUpdateInterface
|
||||
{
|
||||
use TrackCreationTrait;
|
||||
|
||||
use TrackUpdateTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
||||
*/
|
||||
private ?DateTimeImmutable $endDate = null;
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class)
|
||||
*/
|
||||
private AccompanyingPeriod $period;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable")
|
||||
*/
|
||||
private ?DateTimeImmutable $startDate = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", nullable=false)
|
||||
*/
|
||||
private string $step;
|
||||
|
||||
public function getEndDate(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getPeriod(): AccompanyingPeriod
|
||||
{
|
||||
return $this->period;
|
||||
}
|
||||
|
||||
public function getStartDate(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
public function getStep(): string
|
||||
{
|
||||
return $this->step;
|
||||
}
|
||||
|
||||
public function setEndDate(?DateTimeImmutable $endDate): self
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal use AccompanyingPeriod::addLocationHistory
|
||||
*/
|
||||
public function setPeriod(AccompanyingPeriod $period): self
|
||||
{
|
||||
$this->period = $period;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStartDate(?DateTimeImmutable $startDate): self
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStep(string $step): AccompanyingPeriodStepHistory
|
||||
{
|
||||
$this->step = $step;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@@ -36,7 +36,7 @@ class Comment implements TrackCreationInterface, TrackUpdateInterface
|
||||
* inversedBy="comments")
|
||||
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
|
||||
*/
|
||||
private ?AccompanyingPeriod $accompanyingPeriod;
|
||||
private ?AccompanyingPeriod $accompanyingPeriod = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text")
|
||||
|
@@ -84,7 +84,7 @@ class PersonHouseholdAddress
|
||||
|
||||
public function getHousehold(): ?Household
|
||||
{
|
||||
return $this->relation;
|
||||
return $this->household;
|
||||
}
|
||||
|
||||
public function getPerson(): ?Person
|
||||
|
@@ -27,6 +27,8 @@ use Chill\MainBundle\Validation\Constraint\PhonenumberConstraint;
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
||||
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterCurrent;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCurrentAddress;
|
||||
use Chill\PersonBundle\Entity\Person\PersonResource;
|
||||
use Chill\PersonBundle\Validator\Constraints\Household\HouseholdMembershipSequential;
|
||||
@@ -44,6 +46,7 @@ use libphonenumber\PhoneNumber;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use UnexpectedValueException;
|
||||
use function count;
|
||||
use function in_array;
|
||||
|
||||
@@ -176,13 +179,35 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
*/
|
||||
private Collection $budgetResources;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(
|
||||
* targetEntity="Chill\CalendarBundle\Entity\Calendar",
|
||||
* mappedBy="persons"
|
||||
* )
|
||||
*/
|
||||
private Collection $calendars;
|
||||
|
||||
/**
|
||||
* The person's center.
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Center")
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
private ?Center $center = null;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity=PersonCenterCurrent::class, mappedBy="person")
|
||||
*/
|
||||
private ?PersonCenterCurrent $centerCurrent = null;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=PersonCenterHistory::class, mappedBy="person", cascade={"persist"})
|
||||
*
|
||||
* @var Collection|PersonCenterHistory[]
|
||||
*/
|
||||
private Collection $centerHistory;
|
||||
|
||||
/**
|
||||
* Array where customfield's data are stored.
|
||||
*
|
||||
@@ -523,6 +548,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
$this->budgetResources = new ArrayCollection();
|
||||
$this->budgetCharges = new ArrayCollection();
|
||||
$this->resources = new ArrayCollection();
|
||||
$this->centerHistory = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -897,7 +923,33 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
|
||||
public function getCenter(): ?Center
|
||||
{
|
||||
return $this->center;
|
||||
if (null !== $this->centerCurrent) {
|
||||
return $this->centerCurrent->getCenter();
|
||||
}
|
||||
|
||||
if (null === $currentCenterHistory = $this->getCurrentCenterHistory()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $currentCenterHistory->getCenter();
|
||||
}
|
||||
|
||||
public function getCenterCurrent(): ?PersonCenterCurrent
|
||||
{
|
||||
if (null !== $this->centerCurrent) {
|
||||
return $this->centerCurrent;
|
||||
}
|
||||
|
||||
if (null === $currentCenterHistory = $this->getCurrentCenterHistory()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new PersonCenterCurrent($currentCenterHistory);
|
||||
}
|
||||
|
||||
public function getCenterHistory(): Collection
|
||||
{
|
||||
return $this->centerHistory;
|
||||
}
|
||||
|
||||
public function getCFData(): ?array
|
||||
@@ -1436,7 +1488,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
$participation = $this->participationsContainAccompanyingPeriod($accompanyingPeriod);
|
||||
|
||||
if (!null === $participation) {
|
||||
$participation->setEndDate(DateTimeImmutable::class);
|
||||
$participation->setEndDate(new DateTime());
|
||||
$this->accompanyingPeriodParticipations->removeElement($participation);
|
||||
}
|
||||
}
|
||||
@@ -1510,17 +1562,41 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCenter(Center $center): self
|
||||
/**
|
||||
* Associate the center with the person. The association start on 'now'.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCenter(?Center $center): self
|
||||
{
|
||||
$this->center = $center;
|
||||
$modification = new DateTimeImmutable('now');
|
||||
|
||||
foreach ($this->centerHistory as $centerHistory) {
|
||||
if (null === $centerHistory->getEndDate()) {
|
||||
$centerHistory->setEndDate($modification);
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $center) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->centerHistory[] = new PersonCenterHistory($this, $center, $modification);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCenterHistory(Collection $centerHistory): Person
|
||||
{
|
||||
$this->centerHistory = $centerHistory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Report
|
||||
* @return Person
|
||||
*/
|
||||
public function setCFData(?array $cFData)
|
||||
public function setCFData(?array $cFData): self
|
||||
{
|
||||
$this->cFData = $cFData;
|
||||
|
||||
@@ -1696,7 +1772,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type $spokenLanguages
|
||||
* @param Collection $spokenLanguages
|
||||
*/
|
||||
public function setSpokenLanguages($spokenLanguages): self
|
||||
{
|
||||
@@ -1719,6 +1795,34 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function getCurrentCenterHistory(): ?PersonCenterHistory
|
||||
{
|
||||
if (0 === $this->centerHistory->count()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$criteria = Criteria::create();
|
||||
$now = new DateTimeImmutable('now');
|
||||
$criteria->where(Criteria::expr()->lte('startDate', $now))
|
||||
->andWhere(Criteria::expr()->orX(
|
||||
Criteria::expr()->isNull('endDate'),
|
||||
Criteria::expr()->gt('endDate', $now)
|
||||
));
|
||||
|
||||
$histories = $this->centerHistory->matching($criteria);
|
||||
|
||||
switch ($histories->count()) {
|
||||
case 0:
|
||||
return null;
|
||||
|
||||
case 1:
|
||||
return $histories->first();
|
||||
|
||||
default:
|
||||
throw new UnexpectedValueException('It should not contains more than one center at a time');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This private function scan accompanyingPeriodParticipations Collection,
|
||||
* searching for a given AccompanyingPeriod.
|
||||
|
@@ -0,0 +1,100 @@
|
||||
<?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\Entity\Person;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* Associate a Person with the current center.
|
||||
*
|
||||
* The process of selecting the current center is done on database side,
|
||||
* using a SQL view.
|
||||
*
|
||||
* @ORM\Entity(readOnly=true)
|
||||
* @ORM\Table(name="view_chill_person_person_center_history_current")
|
||||
* @psalm-internal Chill\PersonBundle\Entity
|
||||
*/
|
||||
class PersonCenterCurrent
|
||||
{
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Center::class)
|
||||
*/
|
||||
private Center $center;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
||||
*/
|
||||
private ?DateTimeImmutable $endDate = null;
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="centerCurrent")
|
||||
*/
|
||||
private Person $person;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable", nullable=false)
|
||||
*/
|
||||
private DateTimeImmutable $startDate;
|
||||
|
||||
/**
|
||||
* Populate the properties person, center, start and end date from history.
|
||||
*
|
||||
* The creator and updatedby are not filled.
|
||||
*
|
||||
* @internal Should not be instantied, unless inside Person entity
|
||||
*/
|
||||
public function __construct(PersonCenterHistory $history)
|
||||
{
|
||||
$this->person = $history->getPerson();
|
||||
$this->center = $history->getCenter();
|
||||
$this->startDate = $history->getStartDate();
|
||||
$this->endDate = $history->getEndDate();
|
||||
$this->id = $history->getId();
|
||||
}
|
||||
|
||||
public function getCenter(): Center
|
||||
{
|
||||
return $this->center;
|
||||
}
|
||||
|
||||
public function getEndDate(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* The id will be the same as the current @see{PersonCenterHistory::class}.
|
||||
*/
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getPerson(): Person
|
||||
{
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
public function getStartDate(): DateTimeImmutable
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
<?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\Entity\Person;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* Associate a Person with a Center. The association may change on date intervals.
|
||||
*
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="chill_person_person_center_history")
|
||||
*/
|
||||
class PersonCenterHistory implements TrackCreationInterface, TrackUpdateInterface
|
||||
{
|
||||
use TrackCreationTrait;
|
||||
|
||||
use TrackUpdateTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Center::class)
|
||||
*/
|
||||
private ?Center $center = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
||||
*/
|
||||
private ?DateTimeImmutable $endDate = null;
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="centerHistory")
|
||||
*/
|
||||
private ?Person $person = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable", nullable=false)
|
||||
*/
|
||||
private ?DateTimeImmutable $startDate = null;
|
||||
|
||||
public function __construct(?Person $person = null, ?Center $center = null, ?DateTimeImmutable $startDate = null)
|
||||
{
|
||||
$this->person = $person;
|
||||
$this->center = $center;
|
||||
$this->startDate = $startDate;
|
||||
}
|
||||
|
||||
public function getCenter(): ?Center
|
||||
{
|
||||
return $this->center;
|
||||
}
|
||||
|
||||
public function getEndDate(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getPerson(): ?Person
|
||||
{
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
public function getStartDate(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
public function setCenter(?Center $center): self
|
||||
{
|
||||
$this->center = $center;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setEndDate(?DateTimeImmutable $endDate): self
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setPerson(?Person $person): self
|
||||
{
|
||||
$this->person = $person;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStartDate(?DateTimeImmutable $startDate): self
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@@ -26,6 +26,11 @@ use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
*/
|
||||
class Evaluation
|
||||
{
|
||||
/**
|
||||
* @ORM\Column(type="boolean", nullable=false, options={"default": true})
|
||||
*/
|
||||
private bool $active = true;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="dateinterval", nullable=true, options={"default": null})
|
||||
* @Serializer\Groups({"read"})
|
||||
@@ -114,6 +119,11 @@ class Evaluation
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*
|
||||
@@ -128,6 +138,13 @@ class Evaluation
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setActive(bool $active): Evaluation
|
||||
{
|
||||
$this->active = $active;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDelay(?DateInterval $delay): self
|
||||
{
|
||||
$this->delay = $delay;
|
||||
|
@@ -62,7 +62,7 @@ class SocialAction
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=SocialIssue::class, inversedBy="socialActions")
|
||||
@@ -228,6 +228,22 @@ class SocialAction
|
||||
return $descendants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection|SocialAction[] $socialActions
|
||||
*/
|
||||
public static function getDescendantsWithThisForActions($socialActions): Collection
|
||||
{
|
||||
$unique = [];
|
||||
|
||||
foreach ($socialActions as $action) {
|
||||
foreach ($action->getDescendantsWithThis() as $child) {
|
||||
$unique[spl_object_hash($child)] = $child;
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayCollection(array_values($unique));
|
||||
}
|
||||
|
||||
public function getEvaluations(): Collection
|
||||
{
|
||||
return $this->evaluations;
|
||||
@@ -274,6 +290,11 @@ class SocialAction
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function hasChildren(): bool
|
||||
{
|
||||
return 0 < $this->getChildren()->count();
|
||||
}
|
||||
|
||||
public function hasParent(): bool
|
||||
{
|
||||
return $this->getParent() instanceof self;
|
||||
@@ -369,6 +390,8 @@ class SocialAction
|
||||
{
|
||||
$this->parent = $parent;
|
||||
|
||||
$parent->addChild($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@@ -71,11 +71,17 @@ class SocialIssue
|
||||
$this->socialActions = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal use @see{SocialIssue::setParent} instead
|
||||
*
|
||||
* @param SocialIssue $child
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addChild(self $child): self
|
||||
{
|
||||
if (!$this->children->contains($child)) {
|
||||
$this->children[] = $child;
|
||||
$child->setParent($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -215,6 +221,22 @@ class SocialIssue
|
||||
return $descendants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|SocialIssue[] $socialIssues
|
||||
*/
|
||||
public static function getDescendantsWithThisForIssues(array $socialIssues): Collection
|
||||
{
|
||||
$unique = [];
|
||||
|
||||
foreach ($socialIssues as $issue) {
|
||||
foreach ($issue->getDescendantsWithThis() as $child) {
|
||||
$unique[spl_object_hash($child)] = $child;
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayCollection(array_values($unique));
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@@ -262,6 +284,11 @@ class SocialIssue
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function hasChildren(): bool
|
||||
{
|
||||
return 0 < $this->getChildren()->count();
|
||||
}
|
||||
|
||||
public function hasParent(): bool
|
||||
{
|
||||
return null !== $this->parent;
|
||||
@@ -329,6 +356,8 @@ class SocialIssue
|
||||
{
|
||||
$this->parent = $parent;
|
||||
|
||||
$parent->addChild($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@@ -25,23 +25,17 @@ class AbstractAccompanyingPeriodExportElement
|
||||
*/
|
||||
protected function addJoinAccompanyingPeriod(QueryBuilder $query): void
|
||||
{
|
||||
if (false === $this->havingAccompanyingPeriodInJoin($query)) {
|
||||
if (false === in_array('person', $query->getAllAliases(), true)) {
|
||||
throw new LogicException("the alias 'person' does not exists in "
|
||||
. 'query builder');
|
||||
}
|
||||
if (false === in_array('person', $query->getAllAliases(), true)) {
|
||||
throw new LogicException("the alias 'person' does not exists in "
|
||||
. 'query builder');
|
||||
}
|
||||
|
||||
$query->join('person.accompanyingPeriods', 'accompanying_period');
|
||||
if (!in_array('acppart', $query->getAllAliases(), true)) {
|
||||
$query->join('person.accompanyingPeriodParticipations', 'acppart');
|
||||
}
|
||||
|
||||
if (!in_array('acp', $query->getAllAliases(), true)) {
|
||||
$query->join('acppart.accompanyingPeriod', 'acp');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if "accompanying_period" alias is present in the query alises.
|
||||
*/
|
||||
protected function havingAccompanyingPeriodInJoin(QueryBuilder $query): bool
|
||||
{
|
||||
$joins = $query->getDQLPart('join') ?? [];
|
||||
|
||||
return in_array('accompanying_period', $query->getAllAliases(), true);
|
||||
}
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class AdministrativeLocationAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -32,24 +33,19 @@ class AdministrativeLocationAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acp.administrativeLocation', 'al');
|
||||
if (!in_array('acploc', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acp.administrativeLocation', 'acploc');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(acp.administrativeLocation) AS location_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('location_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('location_aggregator');
|
||||
}
|
||||
$qb->addGroupBy('location_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -69,6 +65,10 @@ class AdministrativeLocationAggregator implements AggregatorInterface
|
||||
return 'Administrative location';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$l = $this->locationRepository->find($value);
|
||||
|
||||
return $l->getName() . ' (' . $this->translatableStringHelper->localize($l->getLocationType()->getTitle()) . ')';
|
||||
|
@@ -0,0 +1,67 @@
|
||||
<?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\Aggregator\AccompanyingCourseAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ByActionNumberAggregator implements AggregatorInterface
|
||||
{
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data): void
|
||||
{
|
||||
$qb->addSelect('(SELECT COUNT(acp_by_action_action.id) FROM ' . AccompanyingPeriodWork::class . ' acp_by_action_action WHERE acp_by_action_action.accompanyingPeriod = acp) AS acp_by_action_number_aggregator')
|
||||
->addGroupBy('acp_by_action_number_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder): void
|
||||
{
|
||||
// No form needed
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return static function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.course.by_number_of_action.Number of actions';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['acp_by_action_number_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group by number of actions';
|
||||
}
|
||||
}
|
@@ -13,44 +13,34 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepositoryInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ClosingMotiveAggregator implements AggregatorInterface
|
||||
{
|
||||
private EntityManagerInterface $em;
|
||||
private ClosingMotiveRepositoryInterface $motiveRepository;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
ClosingMotiveRepositoryInterface $motiveRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->motiveRepository = $em->getRepository(ClosingMotive::class);
|
||||
$this->motiveRepository = $motiveRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acp.closingMotive', 'cm');
|
||||
|
||||
$qb->addSelect('IDENTITY(acp.closingMotive) AS closingmotive_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('closingmotive_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('closingmotive_aggregator');
|
||||
}
|
||||
$qb->addGroupBy('closingmotive_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -70,6 +60,10 @@ class ClosingMotiveAggregator implements AggregatorInterface
|
||||
return 'Closing motive';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$cm = $this->motiveRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
@@ -27,7 +28,7 @@ class ConfidentialAggregator implements AggregatorInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -35,14 +36,7 @@ class ConfidentialAggregator implements AggregatorInterface
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->addSelect('acp.confidential AS confidential_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('confidential_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('confidential_aggregator');
|
||||
}
|
||||
$qb->addGroupBy('confidential_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -72,8 +66,6 @@ class ConfidentialAggregator implements AggregatorInterface
|
||||
default:
|
||||
throw new LogicException(sprintf('The value %s is not valid', $value));
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,87 @@
|
||||
<?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\Aggregator\AccompanyingCourseAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Repository\UserJobRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class CreatorJobAggregator implements AggregatorInterface
|
||||
{
|
||||
private UserJobRepository $jobRepository;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
UserJobRepository $jobRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->jobRepository = $jobRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('acp_creator', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acp.createdBy', 'acp_creator');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(acp_creator.userJob) AS acp_creator_job_aggregator')
|
||||
->addGroupBy('acp_creator_job_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// No form needed
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.course.by_creator_job.Creator\'s job';
|
||||
}
|
||||
|
||||
if (null === $value || null === $j = $this->jobRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$j->getLabel()
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['acp_creator_job_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group by creator job';
|
||||
}
|
||||
}
|
@@ -13,21 +13,21 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Les regroupements seront un nombre de mois, arrondi à l'unité la plus proche (donc
|
||||
* - au dela de 15 jours => 1 mois,
|
||||
* - jusqu'à 45 jours => 1 mois,
|
||||
* 15 | 45 | 75
|
||||
* --+----o----+----o----+----
|
||||
* | 30 | 60 |
|
||||
* etc.).
|
||||
*/
|
||||
class DurationAggregator implements AggregatorInterface
|
||||
final class DurationAggregator implements AggregatorInterface
|
||||
{
|
||||
private const CHOICES = [
|
||||
'month',
|
||||
'week',
|
||||
'day',
|
||||
];
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
@@ -35,60 +35,38 @@ class DurationAggregator implements AggregatorInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb
|
||||
// OUI
|
||||
->addSelect(
|
||||
'
|
||||
(acp.closingDate - acp.openingDate +15) *12/365
|
||||
AS duration_aggregator'
|
||||
)
|
||||
//->addSelect('DATE_DIFF(acp.closingDate, acp.openingDate) AS duration_aggregator')
|
||||
//->addSelect('EXTRACT(month FROM acp.openingDate) AS duration_aggregator')
|
||||
//->addSelect("DATE_SUB(acp.openingDate, 6, 'day') AS duration_aggregator")
|
||||
switch ($data['precision']) {
|
||||
case 'day':
|
||||
$qb->addSelect('(COALESCE(acp.closingDate, :now) - acp.openingDate) AS duration_aggregator');
|
||||
|
||||
// TODO adapter la fonction extract pour l'utiliser avec des intervals: extract(month from interval)
|
||||
// et ajouter une fonction custom qui calcule les intervals, comme doctrineum/date-interval
|
||||
// https://packagist.org/packages/doctrineum/date-interval#3.1.0
|
||||
// (composer fait un conflit de dépendance)
|
||||
break;
|
||||
|
||||
//->addSelect("
|
||||
// EXTRACT(
|
||||
// month FROM
|
||||
// DATE_INTERVAL(acp.closingDate, acp.openingDate)
|
||||
// )
|
||||
// AS duration_aggregator")
|
||||
case 'week':
|
||||
$qb->addSelect('(COALESCE(acp.closingDate, :now) - acp.openingDate) / 7 AS duration_aggregator');
|
||||
|
||||
// NON
|
||||
//->addSelect("BETWEEN acp.openingDate AND acp.closingDate AS duration_aggregator")
|
||||
//->addSelect("EXTRACT(month FROM DATE_SUB(acp.openingDate, 6, 'day')) AS duration_aggregator")
|
||||
//->addSelect('EXTRACT(month FROM DATE_DIFF(acp.closingDate, acp.openingDate)) AS duration_aggregator')
|
||||
/*
|
||||
->addSelect('
|
||||
( CASE
|
||||
WHEN EXTRACT(day FROM DATE_DIFF(acp.closingDate, acp.openingDate)) > 15
|
||||
THEN EXTRACT(month FROM DATE_DIFF(acp.closingDate, acp.openingDate)) +1
|
||||
ELSE EXTRACT(month FROM DATE_DIFF(acp.closingDate, acp.openingDate))
|
||||
END ) AS duration_aggregator
|
||||
')
|
||||
*/
|
||||
;
|
||||
break;
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
case 'month':
|
||||
$qb->addSelect('(EXTRACT (MONTH FROM AGE(COALESCE(acp.closingDate, :now), acp.openingDate)) * 12 +
|
||||
EXTRACT (MONTH FROM AGE(COALESCE(acp.closingDate, :now), acp.openingDate))) AS duration_aggregator');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('duration_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('duration_aggregator');
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LogicException('precision not supported: ' . $data['precision']);
|
||||
}
|
||||
|
||||
$qb->orderBy('duration_aggregator');
|
||||
$qb
|
||||
->setParameter('now', new DateTimeImmutable('now'))
|
||||
->addGroupBy('duration_aggregator')
|
||||
->addOrderBy('duration_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -98,25 +76,27 @@ class DurationAggregator implements AggregatorInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// no form
|
||||
$builder->add('precision', ChoiceType::class, [
|
||||
'choices' => array_combine(self::CHOICES, self::CHOICES),
|
||||
'label' => 'export.aggregator.course.duration.Precision',
|
||||
'choice_label' => static fn (string $c) => 'export.aggregator.course.duration.' . $c,
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value): string {
|
||||
return static function ($value) use ($data) {
|
||||
if ('_header' === $value) {
|
||||
return $this->translator->trans('Rounded month duration');
|
||||
return 'export.aggregator.course.duration.' . $data['precision'];
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return $this->translator->trans('current duration'); // when closingDate is null
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 === $value) {
|
||||
return $this->translator->trans('duration 0 month');
|
||||
}
|
||||
|
||||
return '' . $value . $this->translator->trans(' months');
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
@@ -27,7 +28,7 @@ class EmergencyAggregator implements AggregatorInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -35,14 +36,7 @@ class EmergencyAggregator implements AggregatorInterface
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->addSelect('acp.emergency AS emergency_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('emergency_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('emergency_aggregator');
|
||||
}
|
||||
$qb->addGroupBy('emergency_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -72,8 +66,6 @@ class EmergencyAggregator implements AggregatorInterface
|
||||
default:
|
||||
throw new LogicException(sprintf('The value %s is not valid', $value));
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -33,7 +33,7 @@ final class EvaluationAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -41,19 +41,15 @@ final class EvaluationAggregator implements AggregatorInterface
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('acpw', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acp.works', 'acpw');
|
||||
$qb->leftJoin('acp.works', 'acpw');
|
||||
}
|
||||
$qb->join('acpw.accompanyingPeriodWorkEvaluations', 'we');
|
||||
|
||||
$qb->addSelect('IDENTITY(we.evaluation) AS evaluation_aggregator');
|
||||
|
||||
$groupby = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('evaluation_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('evaluation_aggregator');
|
||||
if (!in_array('workeval', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acpw.accompanyingPeriodWorkEvaluations', 'workeval');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(workeval.evaluation) AS evaluation_aggregator');
|
||||
$qb->addGroupBy('evaluation_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -73,6 +69,10 @@ final class EvaluationAggregator implements AggregatorInterface
|
||||
return 'Evaluation';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$e = $this->evaluationRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@@ -0,0 +1,180 @@
|
||||
<?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\Aggregator\AccompanyingCourseAggregators;
|
||||
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
use Chill\MainBundle\Entity\GeographicalUnitLayer;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use UnexpectedValueException;
|
||||
|
||||
final class GeographicalUnitStatAggregator implements AggregatorInterface
|
||||
{
|
||||
private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository;
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->geographicalUnitLayerRepository = $geographicalUnitLayerRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->leftJoin('acp.locationHistories', 'acp_geog_agg_location_history');
|
||||
|
||||
$qb->andWhere(
|
||||
$qb->expr()->andX(
|
||||
'acp_geog_agg_location_history.startDate <= :acp_geog_aggregator_date',
|
||||
$qb->expr()->orX(
|
||||
'acp_geog_agg_location_history.endDate IS NULL',
|
||||
'acp_geog_agg_location_history.endDate > :acp_geog_aggregator_date'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// link between location history and person
|
||||
$qb->leftJoin(
|
||||
PersonHouseholdAddress::class,
|
||||
'acp_geog_agg_address_person_location',
|
||||
Join::WITH,
|
||||
$qb->expr()->andX(
|
||||
'IDENTITY(acp_geog_agg_address_person_location.person) = IDENTITY(acp_geog_agg_location_history.personLocation)',
|
||||
'acp_geog_agg_address_person_location.validFrom < :acp_geog_aggregator_date',
|
||||
$qb->expr()->orX(
|
||||
'acp_geog_agg_address_person_location.validTo > :acp_geog_aggregator_date',
|
||||
$qb->expr()->isNull('acp_geog_agg_address_person_location.validTo')
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$qb->setParameter(
|
||||
'acp_geog_aggregator_date',
|
||||
$this->rollingDateConverter->convert($data['date_calc'])
|
||||
);
|
||||
|
||||
// we finally find an address
|
||||
$qb->leftJoin(
|
||||
Address::class,
|
||||
'acp_geog_agg_address',
|
||||
Join::WITH,
|
||||
'COALESCE(IDENTITY(acp_geog_agg_address_person_location.address), IDENTITY(acp_geog_agg_location_history.addressLocation)) = acp_geog_agg_address.id'
|
||||
);
|
||||
|
||||
// and we do a join with units
|
||||
$qb->leftJoin(
|
||||
'acp_geog_agg_address.geographicalUnits',
|
||||
'acp_geog_units'
|
||||
);
|
||||
|
||||
$qb->andWhere($qb->expr()->eq('acp_geog_units.layer', ':acp_geog_unit_layer'));
|
||||
|
||||
$qb->setParameter('acp_geog_unit_layer', $data['level']);
|
||||
|
||||
// we add group by
|
||||
$qb
|
||||
->addSelect('acp_geog_units.unitName AS acp_geog_agg_unitname')
|
||||
->addSelect('acp_geog_units.unitRefId AS acp_geog_agg_unitrefid')
|
||||
->addGroupBy('acp_geog_agg_unitname')
|
||||
->addGroupBy('acp_geog_agg_unitrefid');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('date_calc', PickRollingDateType::class, [
|
||||
'label' => 'Compute geographical location at date',
|
||||
'required' => true,
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
])
|
||||
->add('level', EntityType::class, [
|
||||
'label' => 'Geographical layer',
|
||||
'placeholder' => 'Select a geographical layer',
|
||||
'class' => GeographicalUnitLayer::class,
|
||||
'choices' => $this->geographicalUnitLayerRepository->findAllHavingUnits(),
|
||||
'choice_label' => function (GeographicalUnitLayer $item) {
|
||||
return $this->translatableStringHelper->localize($item->getName());
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'acp_geog_agg_unitname':
|
||||
return static function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'acp_geog_agg_unitname';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
|
||||
case 'acp_geog_agg_unitrefid':
|
||||
return static function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'acp_geog_agg_unitrefid';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
|
||||
default:
|
||||
throw new UnexpectedValueException('this value should not happens');
|
||||
}
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['acp_geog_agg_unitname', 'acp_geog_agg_unitrefid'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group by geographical unit';
|
||||
}
|
||||
}
|
@@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
@@ -27,7 +28,7 @@ class IntensityAggregator implements AggregatorInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -35,14 +36,7 @@ class IntensityAggregator implements AggregatorInterface
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->addSelect('acp.intensity AS intensity_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('intensity_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('intensity_aggregator');
|
||||
}
|
||||
$qb->addGroupBy('intensity_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
|
@@ -17,6 +17,7 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class JobAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -32,24 +33,19 @@ final class JobAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acp.job', 'j');
|
||||
if (!in_array('acpjob', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acp.job', 'acpjob');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(acp.job) AS job_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('job_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('job_aggregator');
|
||||
}
|
||||
$qb->addGroupBy('job_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -69,6 +65,10 @@ final class JobAggregator implements AggregatorInterface
|
||||
return 'Job';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$j = $this->jobRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@@ -19,6 +19,7 @@ use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class OriginAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -34,24 +35,19 @@ final class OriginAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acp.origin', 'o');
|
||||
|
||||
$qb->addSelect('o.id AS origin_aggregator');
|
||||
|
||||
$groupby = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('origin_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('origin_aggregator');
|
||||
if (!in_array('acporigin', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acp.origin', 'acporigin');
|
||||
}
|
||||
|
||||
$qb->addSelect('acporigin.id AS origin_aggregator');
|
||||
$qb->addGroupBy('origin_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -71,6 +67,10 @@ final class OriginAggregator implements AggregatorInterface
|
||||
return 'Origin';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$o = $this->repository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@@ -12,7 +12,10 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
@@ -20,36 +23,53 @@ use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
final class ReferrerAggregator implements AggregatorInterface
|
||||
{
|
||||
private const A = 'acp_ref_agg_uhistory';
|
||||
|
||||
private const P = 'acp_ref_agg_date';
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private UserRender $userRender;
|
||||
|
||||
private UserRepository $userRepository;
|
||||
|
||||
public function __construct(
|
||||
UserRepository $userRepository,
|
||||
UserRender $userRender
|
||||
UserRender $userRender,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->userRepository = $userRepository;
|
||||
$this->userRender = $userRender;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acp.user', 'u');
|
||||
|
||||
$qb->addSelect('u.id AS referrer_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('referrer_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('referrer_aggregator');
|
||||
}
|
||||
$qb
|
||||
->addSelect('IDENTITY(' . self::A . '.user) AS referrer_aggregator')
|
||||
->addGroupBy('referrer_aggregator')
|
||||
->leftJoin('acp.userHistories', self::A)
|
||||
->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull(self::A),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte(self::A . '.startDate', ':' . self::P),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull(self::A . '.endDate'),
|
||||
$qb->expr()->gt(self::A . '.endDate', ':' . self::P)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameter(
|
||||
self::P,
|
||||
$this->rollingDateConverter->convert($data['date_calc'])
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -59,7 +79,12 @@ final class ReferrerAggregator implements AggregatorInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// no form
|
||||
$builder
|
||||
->add('date_calc', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
'label' => 'export.aggregator.course.by_referrer.Computation date for referrer',
|
||||
'required' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
@@ -69,6 +94,10 @@ final class ReferrerAggregator implements AggregatorInterface
|
||||
return 'Referrer';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$r = $this->userRepository->find($value);
|
||||
|
||||
return $this->userRender->renderString($r, []);
|
||||
|
@@ -0,0 +1,127 @@
|
||||
<?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\Aggregator\AccompanyingCourseAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ReferrerScopeAggregator implements AggregatorInterface
|
||||
{
|
||||
private const SCOPE_KEY = 'acp_agg_refscope_user_history_ref_scope_name';
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private ScopeRepositoryInterface $scopeRepository;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ScopeRepositoryInterface $scopeRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$userHistory = 'acp_agg_refscope_user_history';
|
||||
$ref = 'acp_agg_refscope_user_history_ref';
|
||||
$scopeName = self::SCOPE_KEY;
|
||||
$dateCalc = 'acp_agg_refscope_user_history_date_calc';
|
||||
|
||||
$qb
|
||||
->leftJoin('acp.userHistories', $userHistory)
|
||||
->leftJoin($userHistory . '.user', $ref)
|
||||
->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull($userHistory),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte($userHistory . '.startDate', ':' . $dateCalc),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull($userHistory . '.endDate'),
|
||||
$qb->expr()->lt($userHistory . '.endDate', ':' . $dateCalc)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameter(
|
||||
$dateCalc,
|
||||
$this->rollingDateConverter->convert($data['date_calc'])
|
||||
);
|
||||
|
||||
// add groups
|
||||
$qb
|
||||
->addSelect('IDENTITY(' . $ref . '.mainScope) AS ' . $scopeName)
|
||||
->addGroupBy($scopeName);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_calc', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
'label' => 'export.aggregator.course.by_user_scope.Computation date for referrer',
|
||||
'required' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.course.by_user_scope.Referrer\'s scope';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$scope = $this->scopeRepository->find($value);
|
||||
|
||||
if (null === $scope) {
|
||||
throw new LogicException('no scope found with this id: ' . $value);
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize($scope->getName());
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return [self::SCOPE_KEY];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'export.aggregator.course.by_user_scope.Group course by referrer\'s scope';
|
||||
}
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
<?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\Aggregator\AccompanyingCourseAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use function in_array;
|
||||
|
||||
final class RequestorAggregator implements AggregatorInterface
|
||||
{
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('acppart', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acp.participations', 'acppart');
|
||||
}
|
||||
|
||||
$qb->addSelect("
|
||||
( CASE
|
||||
WHEN acp.requestorPerson IS NOT NULL
|
||||
THEN
|
||||
( CASE
|
||||
WHEN acp.requestorPerson = acppart.person
|
||||
THEN 'is person concerned'
|
||||
ELSE 'is other person'
|
||||
END )
|
||||
ELSE
|
||||
( CASE
|
||||
WHEN acp.requestorThirdParty IS NOT NULL
|
||||
THEN 'is thirdparty'
|
||||
ELSE 'no requestor'
|
||||
END )
|
||||
END ) AS requestor_aggregator
|
||||
");
|
||||
|
||||
$qb->addGroupBy('requestor_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// no form
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'Requestor';
|
||||
}
|
||||
|
||||
return $this->translator->trans($value);
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['requestor_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group by requestor';
|
||||
}
|
||||
}
|
@@ -17,6 +17,7 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class ScopeAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -32,24 +33,19 @@ final class ScopeAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acp.scopes', 's');
|
||||
|
||||
$qb->addSelect('s.id as scope_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('scope_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('scope_aggregator');
|
||||
if (!in_array('acpscope', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acp.scopes', 'acpscope');
|
||||
}
|
||||
|
||||
$qb->addSelect('acpscope.id as scope_aggregator');
|
||||
$qb->addGroupBy('scope_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -69,6 +65,10 @@ final class ScopeAggregator implements AggregatorInterface
|
||||
return 'Scope';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = $this->scopeRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
@@ -84,6 +84,6 @@ final class ScopeAggregator implements AggregatorInterface
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group by user scope';
|
||||
return 'Group course by scope';
|
||||
}
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ final class SocialActionAggregator implements AggregatorInterface
|
||||
$this->actionRepository = $actionRepository;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -41,18 +41,12 @@ final class SocialActionAggregator implements AggregatorInterface
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('acpw', $qb->getAllAliases(), true)) {
|
||||
// here, we will only see accompanying period linked with a socialAction
|
||||
$qb->join('acp.works', 'acpw');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(acpw.socialAction) AS socialaction_aggregator'); // DISTINCT ??
|
||||
|
||||
$groupby = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('socialaction_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('socialaction_aggregator');
|
||||
}
|
||||
$qb->addSelect('IDENTITY(acpw.socialAction) AS socialaction_aggregator');
|
||||
$qb->addGroupBy('socialaction_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -72,6 +66,10 @@ final class SocialActionAggregator implements AggregatorInterface
|
||||
return 'Social action';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$sa = $this->actionRepository->find($value);
|
||||
|
||||
return $this->actionRender->renderString($sa, []);
|
||||
|
@@ -17,6 +17,7 @@ use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class SocialIssueAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -32,23 +33,20 @@ final class SocialIssueAggregator implements AggregatorInterface
|
||||
$this->issueRender = $issueRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acp.socialIssues', 'si');
|
||||
$qb->addSelect('si.id as socialissue_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('socialissue_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('socialissue_aggregator');
|
||||
if (!in_array('acpsocialissue', $qb->getAllAliases(), true)) {
|
||||
// we will see accompanying period linked with social issues
|
||||
$qb->join('acp.socialIssues', 'acpsocialissue');
|
||||
}
|
||||
|
||||
$qb->addSelect('acpsocialissue.id as socialissue_aggregator');
|
||||
$qb->addGroupBy('socialissue_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
|
@@ -12,63 +12,61 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
//use Chill\MainBundle\Export\FilterInterface;
|
||||
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\Export\Declarations;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use function in_array;
|
||||
|
||||
final class StepAggregator implements AggregatorInterface //, FilterInterface
|
||||
final class StepAggregator implements AggregatorInterface
|
||||
{
|
||||
private const A = 'acpstephistories';
|
||||
|
||||
private const P = 'acp_step_agg_date';
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(
|
||||
RollingDateConverterInterface $rollingDateConverter,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->addSelect('acp.step AS step_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('step_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('step_aggregator');
|
||||
if (!in_array(self::A, $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acp.stepHistories', self::A);
|
||||
}
|
||||
|
||||
// add date in where clause
|
||||
$where = $qb->getDQLPart('where');
|
||||
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->lte('acp.openingDate', ':ondate'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gt('acp.closingDate', ':ondate'),
|
||||
$qb->expr()->isNull('acp.closingDate')
|
||||
$qb
|
||||
->addSelect(self::A . '.step AS step_aggregator')
|
||||
->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull(self::A . '.step'),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte(self::A . '.startDate', ':' . self::P),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull(self::A . '.endDate'),
|
||||
$qb->expr()->lt(self::A . '.endDate', ':' . self::P)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('ondate', $data['on_date'], Types::DATE_MUTABLE);
|
||||
->setParameter(self::P, $this->rollingDateConverter->convert($data['on_date']))
|
||||
->addGroupBy('step_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -78,8 +76,8 @@ final class StepAggregator implements AggregatorInterface //, FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('on_date', ChillDateType::class, [
|
||||
'data' => new DateTime(),
|
||||
$builder->add('on_date', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -99,8 +97,11 @@ final class StepAggregator implements AggregatorInterface //, FilterInterface
|
||||
case '_header':
|
||||
return 'Step';
|
||||
|
||||
case null:
|
||||
return '';
|
||||
|
||||
default:
|
||||
throw new LogicException(sprintf('The value %s is not valid', $value));
|
||||
return $value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -0,0 +1,106 @@
|
||||
<?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\Aggregator\EvaluationAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class ByEndDateAggregator implements AggregatorInterface
|
||||
{
|
||||
private const CHOICES = [
|
||||
'by week' => 'week',
|
||||
'by month' => 'month',
|
||||
'by year' => 'year',
|
||||
];
|
||||
|
||||
private const DEFAULT_CHOICE = 'year';
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
switch ($data['frequency']) {
|
||||
case 'week':
|
||||
$fmt = 'YYYY-IW';
|
||||
|
||||
break;
|
||||
|
||||
case 'month':
|
||||
$fmt = 'YYYY-MM';
|
||||
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
$fmt = 'YYYY';
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LogicException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
|
||||
}
|
||||
|
||||
$qb->addSelect(sprintf("TO_CHAR(workeval.endDate, '%s') AS eval_by_end_date_aggregator", $fmt));
|
||||
$qb->addGroupBy(' eval_by_end_date_aggregator');
|
||||
$qb->addOrderBy(' eval_by_end_date_aggregator', 'ASC');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::EVAL_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('frequency', ChoiceType::class, [
|
||||
'choices' => self::CHOICES,
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'empty_data' => self::DEFAULT_CHOICE,
|
||||
'data' => self::DEFAULT_CHOICE,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return static function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.eval.by_end_date.End date period';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['eval_by_end_date_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.aggregator.eval.by_end_date.Group by end date evaluations';
|
||||
}
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
<?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\Aggregator\EvaluationAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class ByMaxDateAggregator implements AggregatorInterface
|
||||
{
|
||||
private const CHOICES = [
|
||||
'by week' => 'week',
|
||||
'by month' => 'month',
|
||||
'by year' => 'year',
|
||||
];
|
||||
|
||||
private const DEFAULT_CHOICE = 'year';
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
switch ($data['frequency']) {
|
||||
case 'week':
|
||||
$fmt = 'YYYY-IW';
|
||||
|
||||
break;
|
||||
|
||||
case 'month':
|
||||
$fmt = 'YYYY-MM';
|
||||
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
$fmt = 'YYYY';
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LogicException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
|
||||
}
|
||||
|
||||
$qb->addSelect(sprintf("TO_CHAR(workeval.maxDate, '%s') AS eval_by_max_date_aggregator", $fmt));
|
||||
$qb->addGroupBy(' eval_by_max_date_aggregator');
|
||||
$qb->addOrderBy(' eval_by_max_date_aggregator', 'ASC');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::EVAL_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('frequency', ChoiceType::class, [
|
||||
'choices' => self::CHOICES,
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'empty_data' => self::DEFAULT_CHOICE,
|
||||
'data' => self::DEFAULT_CHOICE,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return static function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.eval.by_max_date.Max date';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['eval_by_max_date_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.aggregator.eval.by_max_date.Group by max date evaluations';
|
||||
}
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
<?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\Aggregator\EvaluationAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class ByStartDateAggregator implements AggregatorInterface
|
||||
{
|
||||
private const CHOICES = [
|
||||
'by week' => 'week',
|
||||
'by month' => 'month',
|
||||
'by year' => 'year',
|
||||
];
|
||||
|
||||
private const DEFAULT_CHOICE = 'year';
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
switch ($data['frequency']) {
|
||||
case 'week':
|
||||
$fmt = 'YYYY-IW';
|
||||
|
||||
break;
|
||||
|
||||
case 'month':
|
||||
$fmt = 'YYYY-MM';
|
||||
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
$fmt = 'YYYY';
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LogicException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
|
||||
}
|
||||
|
||||
$qb->addSelect(sprintf("TO_CHAR(workeval.startDate, '%s') AS eval_by_start_date_aggregator", $fmt));
|
||||
$qb->addGroupBy(' eval_by_start_date_aggregator');
|
||||
$qb->addOrderBy(' eval_by_start_date_aggregator', 'ASC');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::EVAL_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('frequency', ChoiceType::class, [
|
||||
'choices' => self::CHOICES,
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'empty_data' => self::DEFAULT_CHOICE,
|
||||
'data' => self::DEFAULT_CHOICE,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return static function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.eval.by_start_date_period.Start date period';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['eval_by_start_date_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.aggregator.eval.by_start_date_period.Group by start date evaluations';
|
||||
}
|
||||
}
|
@@ -32,22 +32,15 @@ class EvaluationTypeAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->addSelect('IDENTITY(eval.evaluation) AS evaluationtype_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('evaluationtype_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('evaluationtype_aggregator');
|
||||
}
|
||||
$qb->addSelect('IDENTITY(workeval.evaluation) AS eval_evaluationtype_aggregator');
|
||||
$qb->addGroupBy('eval_evaluationtype_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -67,6 +60,10 @@ class EvaluationTypeAggregator implements AggregatorInterface
|
||||
return 'Evaluation type';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$ev = $this->evaluationRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize($ev->getTitle());
|
||||
@@ -75,7 +72,7 @@ class EvaluationTypeAggregator implements AggregatorInterface
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['evaluationtype_aggregator'];
|
||||
return ['eval_evaluationtype_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
|
@@ -0,0 +1,81 @@
|
||||
<?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\Aggregator\EvaluationAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class HavingEndDateAggregator implements AggregatorInterface
|
||||
{
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb
|
||||
->addSelect('CASE WHEN workeval.endDate IS NULL THEN true ELSE false END AS eval_enddate_aggregator')
|
||||
->addGroupBy('eval_enddate_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::EVAL_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// No form needed
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.eval.by_end_date.Has end date ?';
|
||||
}
|
||||
|
||||
switch ($value) {
|
||||
case true:
|
||||
return $this->translator->trans('export.aggregator.eval.by_end_date.enddate is specified');
|
||||
|
||||
case false:
|
||||
return $this->translator->trans('export.aggregator.eval.by_end_date.enddate is not specified');
|
||||
|
||||
default:
|
||||
throw new LogicException(sprintf('The value %s is not valid', $value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['eval_enddate_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.aggregator.eval.by_end_date.Group evaluations having end date';
|
||||
}
|
||||
}
|
@@ -12,9 +12,11 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Aggregator\HouseholdAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
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\Export\Declarations;
|
||||
use DateTime;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
@@ -22,44 +24,44 @@ use function in_array;
|
||||
|
||||
class ChildrenNumberAggregator implements AggregatorInterface
|
||||
{
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(
|
||||
TranslatorInterface $translator
|
||||
TranslatorInterface $translator,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->translator = $translator;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('composition', $qb->getAllAliases(), true)) {
|
||||
$qb->join('household.compositions', 'composition');
|
||||
if (!in_array('composition_children', $qb->getAllAliases(), true)) {
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->lte('composition_children.startDate', ':ondate_composition_children'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gt('composition_children.endDate', ':ondate_composition_children'),
|
||||
$qb->expr()->isNull('composition_children.endDate')
|
||||
)
|
||||
);
|
||||
|
||||
$qb->leftJoin('household.compositions', 'composition_children', Expr\Join::WITH, $clause);
|
||||
}
|
||||
|
||||
$qb->addSelect('composition.numberOfChildren AS childrennumber_aggregator');
|
||||
$qb
|
||||
->addSelect('composition_children.numberOfChildren AS childrennumber_aggregator')
|
||||
->addGroupBy('childrennumber_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('childrennumber_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('childrennumber_aggregator');
|
||||
}
|
||||
|
||||
// add date in where clause
|
||||
$where = $qb->getDQLPart('where');
|
||||
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->lte('composition.startDate', ':ondate'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gt('composition.endDate', ':ondate'),
|
||||
$qb->expr()->isNull('composition.endDate')
|
||||
)
|
||||
$qb->setParameter(
|
||||
'ondate_composition_children',
|
||||
$this->rollingDateConverter->convert($data['on_date'])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,24 +72,23 @@ class ChildrenNumberAggregator implements AggregatorInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('on_date', ChillDateType::class, [
|
||||
'data' => new DateTime('now'),
|
||||
$builder->add('on_date', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value): string {
|
||||
return static function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'Number of children';
|
||||
}
|
||||
|
||||
return $this->translator->trans(
|
||||
'household_composition.numberOfChildren children in household',
|
||||
[
|
||||
'numberOfChildren' => $value,
|
||||
]
|
||||
);
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -12,71 +12,62 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Aggregator\HouseholdAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
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\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Repository\Household\HouseholdCompositionTypeRepository;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class CompositionAggregator implements AggregatorInterface
|
||||
{
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
private HouseholdCompositionTypeRepository $typeRepository;
|
||||
|
||||
public function __construct(
|
||||
HouseholdCompositionTypeRepository $typeRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->typeRepository = $typeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('composition', $qb->getAllAliases(), true)) {
|
||||
$qb->join('household.compositions', 'composition');
|
||||
if (!in_array('composition_type', $qb->getAllAliases(), true)) {
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->lte('composition_type.startDate', ':ondate_composition_type'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gt('composition_type.endDate', ':ondate_composition_type'),
|
||||
$qb->expr()->isNull('composition_type.endDate')
|
||||
)
|
||||
);
|
||||
|
||||
$qb->leftJoin('household.compositions', 'composition_type', Expr\Join::WITH, $clause);
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(composition.householdCompositionType) AS composition_aggregator');
|
||||
$qb
|
||||
->addSelect('IDENTITY(composition_type.householdCompositionType) AS composition_aggregator')
|
||||
->addGroupBy('composition_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('composition_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('composition_aggregator');
|
||||
}
|
||||
|
||||
// add date in where clause
|
||||
$where = $qb->getDQLPart('where');
|
||||
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->lte('composition.startDate', ':ondate'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gt('composition.endDate', ':ondate'),
|
||||
$qb->expr()->isNull('composition.endDate')
|
||||
)
|
||||
$qb->setParameter(
|
||||
'ondate_composition_type',
|
||||
$this->rollingDateConverter->convert($data['on_date'])
|
||||
);
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('ondate', $data['on_date'], Types::DATE_MUTABLE);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -86,8 +77,8 @@ class CompositionAggregator implements AggregatorInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('on_date', ChillDateType::class, [
|
||||
'data' => new DateTime('now'),
|
||||
$builder->add('on_date', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -98,6 +89,10 @@ class CompositionAggregator implements AggregatorInterface
|
||||
return 'Composition';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$c = $this->typeRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@@ -29,7 +29,7 @@ final class AgeAggregator implements AggregatorInterface, ExportElementValidated
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@@ -0,0 +1,129 @@
|
||||
<?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\Aggregator\PersonAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdComposition;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Repository\Household\HouseholdCompositionTypeRepositoryInterface;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ByHouseholdCompositionAggregator implements AggregatorInterface
|
||||
{
|
||||
private const PREFIX = 'acp_by_household_compo_agg';
|
||||
|
||||
private HouseholdCompositionTypeRepositoryInterface $householdCompositionTypeRepository;
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
RollingDateConverterInterface $rollingDateConverter,
|
||||
HouseholdCompositionTypeRepositoryInterface $householdCompositionTypeRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {
|
||||
$this->householdCompositionTypeRepository = $householdCompositionTypeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$p = self::PREFIX;
|
||||
|
||||
$qb
|
||||
->leftJoin(
|
||||
'person.householdParticipations',
|
||||
"{$p}_hm"
|
||||
)
|
||||
->leftJoin(
|
||||
HouseholdComposition::class,
|
||||
"{$p}_compo",
|
||||
Join::WITH,
|
||||
$qb->expr()->eq("{$p}_hm.household", "{$p}_compo.household"),
|
||||
)
|
||||
->andWhere("{$p}_hm.startDate <= :{$p}_date AND ({$p}_hm.endDate IS NULL OR {$p}_hm.endDate > :{$p}_date)")
|
||||
->andWhere("{$p}_hm.shareHousehold = 'TRUE'")
|
||||
->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull("{$p}_compo"),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte("{$p}_compo.startDate", ":{$p}_date"),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull("{$p}_compo.endDate"),
|
||||
$qb->expr()->gt("{$p}_compo.endDate", ":{$p}_date")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
->addSelect("IDENTITY({$p}_compo.householdCompositionType) AS {$p}_select")
|
||||
->setParameter(
|
||||
"{$p}_date",
|
||||
$this->rollingDateConverter->convert($data['date_calc'])
|
||||
)
|
||||
->addGroupBy("{$p}_select");
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::PERSON_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_calc', PickRollingDateType::class, [
|
||||
'label' => 'export.aggregator.person.by_household_composition.Calc date',
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.person.by_household_composition.Household composition';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (null === $o = $this->householdCompositionTypeRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize($o->getLabel());
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return [self::PREFIX . '_select'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'export.aggregator.person.by_household_composition.Group course by household composition';
|
||||
}
|
||||
}
|
@@ -23,6 +23,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use function in_array;
|
||||
|
||||
final class CountryOfBirthAggregator implements AggregatorInterface, ExportElementValidatedInterface
|
||||
{
|
||||
@@ -42,7 +43,7 @@ final class CountryOfBirthAggregator implements AggregatorInterface, ExportEleme
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -83,16 +84,12 @@ final class CountryOfBirthAggregator implements AggregatorInterface, ExportEleme
|
||||
. ' is not known.');
|
||||
}
|
||||
|
||||
$qb->leftJoin('person.countryOfBirth', 'countryOfBirth');
|
||||
if (!in_array('countryOfBirth', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('person.countryOfBirth', 'countryOfBirth');
|
||||
}
|
||||
|
||||
// add group by
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('country_of_birth_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('country_of_birth_aggregator');
|
||||
}
|
||||
$qb->addGroupBy('country_of_birth_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
|
@@ -28,7 +28,7 @@ final class GenderAggregator implements AggregatorInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -62,6 +62,9 @@ final class GenderAggregator implements AggregatorInterface
|
||||
case Person::BOTH_GENDER:
|
||||
return $this->translator->trans('both');
|
||||
|
||||
case Person::NO_INFORMATION:
|
||||
return $this->translator->trans('unknown');
|
||||
|
||||
case null:
|
||||
return $this->translator->trans('Not given');
|
||||
|
||||
|
@@ -0,0 +1,157 @@
|
||||
<?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\Aggregator\PersonAggregators;
|
||||
|
||||
use Chill\MainBundle\Entity\GeographicalUnitLayer;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class GeographicalUnitAggregator implements AggregatorInterface
|
||||
{
|
||||
private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository;
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->geographicalUnitLayerRepository = $geographicalUnitLayerRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data): void
|
||||
{
|
||||
$qb
|
||||
->leftJoin('person.householdAddresses', 'person_geog_agg_current_household_address')
|
||||
->leftJoin('person_geog_agg_current_household_address.address', 'person_geog_agg_address')
|
||||
->leftJoin('person_geog_agg_address.geographicalUnits', 'person_geog_agg_geog_unit')
|
||||
->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull('person_geog_agg_current_household_address'),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte('person_geog_agg_current_household_address.validFrom', ':person_geog_agg_date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull('person_geog_agg_current_household_address.validTo'),
|
||||
$qb->expr()->gt('person_geog_agg_current_household_address.validTo', ':person_geog_agg_date')
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull('person_geog_agg_geog_unit'),
|
||||
$qb->expr()->in('person_geog_agg_geog_unit.layer', ':person_geog_agg_layers')
|
||||
)
|
||||
)
|
||||
->setParameter(
|
||||
'person_geog_agg_date',
|
||||
$this->rollingDateConverter->convert($data['date_calc'])
|
||||
)
|
||||
->setParameter('person_geog_agg_layers', $data['level'])
|
||||
->addSelect('person_geog_agg_geog_unit.unitName AS geog_unit_name')
|
||||
->addSelect('person_geog_agg_geog_unit.unitRefId AS geog_unit_key')
|
||||
->addGroupBy('geog_unit_name')
|
||||
->addGroupBy('geog_unit_key');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::PERSON_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('date_calc', PickRollingDateType::class, [
|
||||
'label' => 'Address valid at this date',
|
||||
'required' => true,
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
])
|
||||
->add('level', EntityType::class, [
|
||||
'label' => 'Geographical layer',
|
||||
'placeholder' => 'Select a geographical layer',
|
||||
'class' => GeographicalUnitLayer::class,
|
||||
'choices' => $this->geographicalUnitLayerRepository->findAllHavingUnits(),
|
||||
'choice_label' => function (GeographicalUnitLayer $item) {
|
||||
return $this->translatableStringHelper->localize($item->getName());
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getDefaultAlias(): string
|
||||
{
|
||||
return 'person_geog_agg';
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'geog_unit_name':
|
||||
return static function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'acp_geog_agg_unitname';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
|
||||
case 'geog_unit_key':
|
||||
return static function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'acp_geog_agg_unitrefid';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
|
||||
default:
|
||||
throw new LogicException('key not supported');
|
||||
}
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return ['geog_unit_name', 'geog_unit_key'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Group people by geographical unit based on his address';
|
||||
}
|
||||
}
|
@@ -13,74 +13,84 @@ namespace Chill\PersonBundle\Export\Aggregator\PersonAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
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\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Repository\Household\PositionRepository;
|
||||
use DateTime;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use function in_array;
|
||||
|
||||
final class HouseholdPositionAggregator implements AggregatorInterface, ExportElementValidatedInterface
|
||||
{
|
||||
private PositionRepository $positionRepository;
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator, TranslatableStringHelper $translatableStringHelper, PositionRepository $positionRepository)
|
||||
{
|
||||
public function __construct(
|
||||
TranslatorInterface $translator,
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
PositionRepository $positionRepository,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->translator = $translator;
|
||||
$this->positionRepository = $positionRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->resetDQLPart('from');
|
||||
$qb->from('ChillPersonBundle:Household\HouseholdMember', 'hm');
|
||||
if (!in_array('householdmember', $qb->getAllAliases(), true)) {
|
||||
$qb->join(HouseholdMember::class, 'householdmember', Expr\Join::WITH, 'householdmember.person = person');
|
||||
}
|
||||
|
||||
$qb->join('hm.person', 'person');
|
||||
$qb->join('person.center', 'center');
|
||||
if (!in_array('center', $qb->getAllAliases(), true)) {
|
||||
$qb->join('person.center', 'center');
|
||||
}
|
||||
|
||||
$qb->andWhere($qb->expr()->andX(
|
||||
$qb->expr()->lte('hm.startDate', ':date'),
|
||||
$qb->expr()->lte('householdmember.startDate', ':date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull('hm.endDate'),
|
||||
$qb->expr()->gte('hm.endDate', ':date')
|
||||
$qb->expr()->isNull('householdmember.endDate'),
|
||||
$qb->expr()->gte('householdmember.endDate', ':date')
|
||||
)
|
||||
));
|
||||
|
||||
$qb->setParameter('date', $data['date_position']);
|
||||
$qb->setParameter(
|
||||
'date',
|
||||
$this->rollingDateConverter->convert($data['date_position'])
|
||||
);
|
||||
|
||||
$qb->addSelect('IDENTITY(hm.position) AS household_position_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('household_position_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('household_position_aggregator');
|
||||
}
|
||||
$qb->addSelect('IDENTITY(householdmember.position) AS household_position_aggregator');
|
||||
$qb->addGroupBy('household_position_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return 'person';
|
||||
return Declarations::PERSON_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_position', ChillDateType::class, [
|
||||
$builder->add('date_position', PickRollingDateType::class, [
|
||||
'label' => 'Household position in relation to this date',
|
||||
'data' => new DateTime(),
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,7 @@ use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Repository\MaritalStatusRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class MaritalStatusAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -30,23 +31,19 @@ final class MaritalStatusAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('person.maritalStatus', 'ms');
|
||||
$qb->addSelect('ms.id as marital_status_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('marital_status_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('marital_status_aggregator');
|
||||
if (!in_array('personmarital', $qb->getAllAliases(), true)) {
|
||||
$qb->join('person.maritalStatus', 'personmarital');
|
||||
}
|
||||
|
||||
$qb->addSelect('personmarital.id as marital_status_aggregator');
|
||||
$qb->addGroupBy('marital_status_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
@@ -56,6 +53,7 @@ final class MaritalStatusAggregator implements AggregatorInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// no form
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
|
@@ -41,7 +41,7 @@ final class NationalityAggregator implements AggregatorInterface, ExportElementV
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -83,15 +83,7 @@ final class NationalityAggregator implements AggregatorInterface, ExportElementV
|
||||
}
|
||||
|
||||
$qb->leftJoin('person.nationality', 'nationality');
|
||||
|
||||
// add group by
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('nationality_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('nationality_aggregator');
|
||||
}
|
||||
$qb->addGroupBy('nationality_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
|
@@ -12,41 +12,58 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
|
||||
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class ActionTypeAggregator implements AggregatorInterface
|
||||
{
|
||||
private SocialActionRender $actionRender;
|
||||
|
||||
private SocialActionRepository $socialActionRepository;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
private SocialIssueRender $socialIssueRender;
|
||||
|
||||
public function __construct(SocialActionRepository $socialActionRepository, TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
private SocialIssueRepository $socialIssueRepository;
|
||||
|
||||
public function __construct(
|
||||
SocialActionRepository $socialActionRepository,
|
||||
SocialActionRender $actionRender,
|
||||
SocialIssueRender $socialIssueRender,
|
||||
SocialIssueRepository $socialIssueRepository
|
||||
) {
|
||||
$this->socialActionRepository = $socialActionRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->actionRender = $actionRender;
|
||||
$this->socialIssueRender = $socialIssueRender;
|
||||
$this->socialIssueRepository = $socialIssueRepository;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acpw.socialAction', 'sa');
|
||||
$qb->addSelect('sa.id as action_type_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('action_type_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('action_type_aggregator');
|
||||
if (!in_array('acpwsocialaction', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acpw.socialAction', 'acpwsocialaction');
|
||||
}
|
||||
|
||||
if (!in_array('acpwsocialissue', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acpwsocialaction.issue', 'acpwsocialissue');
|
||||
}
|
||||
|
||||
$qb
|
||||
->addSelect('acpwsocialissue.id as social_action_type_aggregator')
|
||||
->addSelect('acpwsocialaction.id as action_type_aggregator')
|
||||
->addGroupBy('action_type_aggregator')
|
||||
->addGroupBy('social_action_type_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
@@ -61,21 +78,41 @@ final class ActionTypeAggregator implements AggregatorInterface
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
//TODO certain social actions have the same title as other, but are linked to different social issues, should we make a visual distinction?
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'Social Action Type';
|
||||
}
|
||||
switch ($key) {
|
||||
case 'action_type_aggregator':
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'Social Action Type';
|
||||
}
|
||||
|
||||
$sa = $this->socialActionRepository->find($value);
|
||||
if (null === $value || null === $sa = $this->socialActionRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize($sa->getTitle());
|
||||
};
|
||||
return $this->actionRender->renderString($sa, []);
|
||||
};
|
||||
|
||||
case 'social_action_type_aggregator':
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'Social Issue';
|
||||
}
|
||||
|
||||
if (null === $value || null === $si = $this->socialIssueRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->socialIssueRender->renderString($si, []);
|
||||
};
|
||||
|
||||
default:
|
||||
throw new LogicException('this key is not supported: ' . $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return ['action_type_aggregator'];
|
||||
return ['social_action_type_aggregator', 'action_type_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
|
@@ -0,0 +1,84 @@
|
||||
<?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\Aggregator\SocialWorkAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class CurrentActionAggregator implements AggregatorInterface
|
||||
{
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data): void
|
||||
{
|
||||
$qb
|
||||
->addSelect('
|
||||
(CASE WHEN acpw.endDate IS NULL THEN true ELSE false END)
|
||||
AS acpw_current_action_aggregator
|
||||
')
|
||||
->addGroupBy('acpw_current_action_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::SOCIAL_WORK_ACTION_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder): void
|
||||
{
|
||||
// No form needed
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.course_work.by_current_action.Current action ?';
|
||||
}
|
||||
|
||||
switch ($value) {
|
||||
case true:
|
||||
return $this->translator->trans('export.aggregator.course_work.by_current_action.Current action');
|
||||
|
||||
case false:
|
||||
return $this->translator->trans('export.aggregator.course_work.by_current_action.Not current action');
|
||||
|
||||
default:
|
||||
throw new LogicException(sprintf('The value %s is not valid', $value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['acpw_current_action_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.aggregator.course_work.by_current_action.Group by current actions';
|
||||
}
|
||||
}
|
@@ -17,6 +17,7 @@ use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Repository\SocialWork\GoalRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class GoalAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -30,26 +31,22 @@ final class GoalAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acpw.goals', 'g');
|
||||
$qb->addSelect('g.id as goal_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('goal_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('goal_aggregator');
|
||||
if (!in_array('goal', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acpw.goals', 'goal');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(goal.goal) as acpw_goal_aggregator');
|
||||
$qb->addGroupBy('acpw_goal_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::SOCIAL_WORK_ACTION_TYPE;
|
||||
}
|
||||
@@ -66,18 +63,24 @@ final class GoalAggregator implements AggregatorInterface
|
||||
return 'Goal Type';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$g = $this->goalRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize($g->getTitle());
|
||||
return $this->translatableStringHelper->localize(
|
||||
$g->getTitle()
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['goal_aggregator'];
|
||||
return ['acpw_goal_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group social work actions by goal';
|
||||
}
|
||||
|
@@ -0,0 +1,120 @@
|
||||
<?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\Aggregator\SocialWorkAggregators;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Repository\SocialWork\GoalRepository;
|
||||
use Chill\PersonBundle\Repository\SocialWork\ResultRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class GoalResultAggregator implements AggregatorInterface
|
||||
{
|
||||
private GoalRepository $goalRepository;
|
||||
|
||||
private ResultRepository $resultRepository;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ResultRepository $resultRepository,
|
||||
GoalRepository $goalRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->resultRepository = $resultRepository;
|
||||
$this->goalRepository = $goalRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('goal', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acpw.goals', 'goal');
|
||||
}
|
||||
|
||||
if (!in_array('goalresult', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('goal.results', 'goalresult');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(goal.goal) as goal_aggregator');
|
||||
$qb->addSelect('goalresult.id as result_aggregator');
|
||||
$qb->addGroupBy('goal_aggregator')->addGroupBy('result_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::SOCIAL_WORK_ACTION_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// no form
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value) use ($key): string {
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
switch ($key) {
|
||||
case 'goal_aggregator':
|
||||
if ('_header' === $value) {
|
||||
return 'Goal Type';
|
||||
}
|
||||
|
||||
$g = $this->goalRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$g->getTitle()
|
||||
);
|
||||
|
||||
case 'result_aggregator':
|
||||
if ('_header' === $value) {
|
||||
return 'Result Type';
|
||||
}
|
||||
|
||||
$r = $this->resultRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$r->getTitle()
|
||||
);
|
||||
|
||||
default:
|
||||
throw new LogicException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return [
|
||||
'goal_aggregator',
|
||||
'result_aggregator',
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group social work actions by goal and result';
|
||||
}
|
||||
}
|
@@ -17,6 +17,7 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class JobAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -32,24 +33,19 @@ final class JobAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acpw.referrers', 'u');
|
||||
|
||||
$qb->addSelect('IDENTITY(u.userJob) as job_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('job_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('job_aggregator');
|
||||
if (!in_array('acpwuser', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acpw.referrers', 'acpwuser');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(acpwuser.userJob) as job_aggregator')
|
||||
->addGroupBy('job_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -69,6 +65,10 @@ final class JobAggregator implements AggregatorInterface
|
||||
return 'Job';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$j = $this->jobRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@@ -17,6 +17,7 @@ use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class ReferrerAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -32,24 +33,19 @@ final class ReferrerAggregator implements AggregatorInterface
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acpw.referrers', 'u');
|
||||
|
||||
$qb->addSelect('u.id AS referrer_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('referrer_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('referrer_aggregator');
|
||||
if (!in_array('acpwuser', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acpw.referrers', 'acpwuser');
|
||||
}
|
||||
|
||||
$qb->addSelect('acpwuser.id AS referrer_aggregator');
|
||||
$qb->addGroupBy('referrer_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -69,6 +65,10 @@ final class ReferrerAggregator implements AggregatorInterface
|
||||
return 'Referrer';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$r = $this->userRepository->find($value);
|
||||
|
||||
return $this->userRender->renderString($r, []);
|
||||
|
@@ -17,6 +17,7 @@ use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Repository\SocialWork\ResultRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class ResultAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -30,28 +31,22 @@ final class ResultAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acpw.results', 'res');
|
||||
$qb->join('acpw.goals', 'g');
|
||||
$qb->join('g.results', 'gres');
|
||||
$qb->addSelect('res.id, IDENTITY(g.results) as result_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('result_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('result_aggregator');
|
||||
if (!in_array('result', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acpw.results', 'result');
|
||||
}
|
||||
|
||||
$qb->addSelect('result.id AS acpw_result_aggregator');
|
||||
$qb->addGroupBy('acpw_result_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::SOCIAL_WORK_ACTION_TYPE;
|
||||
}
|
||||
@@ -68,18 +63,24 @@ final class ResultAggregator implements AggregatorInterface
|
||||
return 'Result Type';
|
||||
}
|
||||
|
||||
$g = $this->resultRepository->find($value);
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize($g->getTitle());
|
||||
$r = $this->resultRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$r->getTitle()
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['result_aggregator'];
|
||||
return ['acpw_result_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group social work actions by result';
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final class ScopeAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -32,24 +33,19 @@ final class ScopeAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acpw.referrers', 'u');
|
||||
|
||||
$qb->addSelect('IDENTITY(u.mainScope) as scope_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('scope_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('scope_aggregator');
|
||||
if (!in_array('acpwuser', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acpw.referrers', 'acpwuser');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(acpwuser.mainScope) as scope_aggregator');
|
||||
$qb->addGroupBy('scope_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -69,6 +65,10 @@ final class ScopeAggregator implements AggregatorInterface
|
||||
return 'Scope';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = $this->scopeRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@@ -15,6 +15,7 @@ use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
@@ -23,7 +24,6 @@ use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class CountAccompanyingCourse implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
@@ -37,7 +37,7 @@ class CountAccompanyingCourse implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder): void
|
||||
{
|
||||
// TODO: Implement buildForm() method.
|
||||
// Nothing to add here
|
||||
}
|
||||
|
||||
public function getAllowedFormattersTypes(): array
|
||||
@@ -74,9 +74,9 @@ class CountAccompanyingCourse implements ExportInterface, GroupedExportInterface
|
||||
return ['export_result'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
@@ -91,22 +91,42 @@ class CountAccompanyingCourse implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = []): QueryBuilder
|
||||
{
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb = $this->repository->createQueryBuilder('acp');
|
||||
|
||||
$qb->select('COUNT(acp.id) AS export_result');
|
||||
$qb
|
||||
->andWhere('acp.step != :count_acp_step')
|
||||
->leftJoin('acp.participations', 'acppart')
|
||||
->leftJoin('acppart.person', 'person')
|
||||
->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)
|
||||
'
|
||||
)
|
||||
)
|
||||
->setParameter('count_acp_step', AccompanyingPeriod::STEP_DRAFT)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
$qb->select('COUNT(DISTINCT acp.id) AS export_result');
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): Role
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(AccompanyingPeriodVoter::STATS);
|
||||
return AccompanyingPeriodVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
{
|
||||
return [
|
||||
Declarations::ACP_TYPE,
|
||||
Declarations::PERSON_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -15,22 +15,22 @@ use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class CountEvaluation implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
private EntityRepository $repository;
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
) {
|
||||
$this->repository = $em->getRepository(AccompanyingPeriod::class);
|
||||
$this->entityManager = $em;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
@@ -72,9 +72,9 @@ class CountEvaluation implements ExportInterface, GroupedExportInterface
|
||||
return ['export_result'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
@@ -89,26 +89,45 @@ class CountEvaluation implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('acp')
|
||||
->join('acp.works', 'acpw')
|
||||
->join('acpw.accompanyingPeriodWorkEvaluations', 'eval');
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb->select('COUNT(eval.id) AS export_result');
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
|
||||
$qb
|
||||
->from(AccompanyingPeriod\AccompanyingPeriodWorkEvaluation::class, 'workeval')
|
||||
->join('workeval.accompanyingPeriodWork', 'acpw')
|
||||
->join('acpw.accompanyingPeriod', 'acp')
|
||||
->join('acp.participations', 'acppart')
|
||||
->join('acppart.person', 'person')
|
||||
->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)
|
||||
'
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
$qb->select('COUNT(DISTINCT workeval.id) AS export_result');
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole()
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(AccompanyingPeriodVoter::STATS);
|
||||
return AccompanyingPeriodVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
{
|
||||
return [
|
||||
Declarations::EVAL_TYPE,
|
||||
//Declarations::ACP_TYPE,
|
||||
//Declarations::SOCIAL_WORK_ACTION_TYPE,
|
||||
Declarations::SOCIAL_WORK_ACTION_TYPE,
|
||||
Declarations::ACP_TYPE,
|
||||
Declarations::PERSON_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -14,28 +14,42 @@ namespace Chill\PersonBundle\Export\Export;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
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\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Chill\PersonBundle\Security\Authorization\HouseholdVoter;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class CountHousehold implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
private EntityRepository $repository;
|
||||
private const TR_PREFIX = 'export.export.nb_household_with_course.';
|
||||
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
EntityManagerInterface $em,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->repository = $em->getRepository(AccompanyingPeriod::class);
|
||||
$this->entityManager = $em;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// TODO: Implement buildForm() method.
|
||||
$builder
|
||||
->add('calc_date', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
'label' => self::TR_PREFIX . 'Date of calculation of household members',
|
||||
'required' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getAllowedFormattersTypes(): array
|
||||
@@ -45,7 +59,7 @@ class CountHousehold implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Count household by various parameters.';
|
||||
return self::TR_PREFIX . 'Count household with accompanying course by various parameters.';
|
||||
}
|
||||
|
||||
public function getGroup(): string
|
||||
@@ -55,31 +69,41 @@ class CountHousehold implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ('export_result' !== $key) {
|
||||
throw new LogicException("the key {$key} is not used by this export");
|
||||
}
|
||||
return static function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
switch ($key) {
|
||||
case 'household_export_result':
|
||||
return self::TR_PREFIX . 'Count households';
|
||||
|
||||
$labels = array_combine($values, $values);
|
||||
$labels['_header'] = $this->getTitle();
|
||||
case 'acp_export_result':
|
||||
return self::TR_PREFIX . 'Count accompanying periods';
|
||||
|
||||
return static function ($value) use ($labels) {
|
||||
return $labels[$value];
|
||||
default:
|
||||
throw new LogicException('Key not supported: ' . $key);
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['export_result'];
|
||||
return ['household_export_result', 'acp_export_result'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Count households';
|
||||
return self::TR_PREFIX . 'Count households with accompanying course';
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
@@ -89,28 +113,48 @@ class CountHousehold implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('acp')
|
||||
->join('acp.participations', 'acppart')
|
||||
->join('acppart.person', 'person')
|
||||
->join('person.householdParticipations', 'householdmember')
|
||||
->join('householdmember.household', 'household');
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb->select('COUNT(DISTINCT householdmember.household) AS export_result');
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
|
||||
$qb
|
||||
->from(Household::class, 'household')
|
||||
->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']));
|
||||
|
||||
$qb
|
||||
->select('COUNT(DISTINCT household.id) AS household_export_result')
|
||||
->addSelect('COUNT(DISTINCT acp.id) AS acp_export_result');
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole()
|
||||
public function requiredRole(): string
|
||||
{
|
||||
// TODO HouseholdVoter::STATS !??
|
||||
return new Role(AccompanyingPeriodVoter::STATS);
|
||||
return HouseholdVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
{
|
||||
return [
|
||||
Declarations::HOUSEHOLD_TYPE,
|
||||
//Declarations::ACP_TYPE
|
||||
Declarations::ACP_TYPE,
|
||||
Declarations::PERSON_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Export\Export;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
@@ -21,7 +22,6 @@ use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class CountPerson implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
@@ -72,9 +72,9 @@ class CountPerson implements ExportInterface, GroupedExportInterface
|
||||
return ['export_result'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
@@ -100,17 +100,20 @@ class CountPerson implements ExportInterface, GroupedExportInterface
|
||||
|
||||
$qb = $this->personRepository->createQueryBuilder('person');
|
||||
|
||||
$qb->select('COUNT(person.id) AS export_result')
|
||||
->join('person.center', 'center')
|
||||
->andWhere('center IN (:authorized_centers)')
|
||||
$qb->select('COUNT(DISTINCT person.id) AS export_result')
|
||||
->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);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole()
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(PersonVoter::STATS);
|
||||
return PersonVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
|
@@ -15,13 +15,15 @@ use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use function in_array;
|
||||
|
||||
class CountPersonWithAccompanyingCourse implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
@@ -72,9 +74,9 @@ class CountPersonWithAccompanyingCourse implements ExportInterface, GroupedExpor
|
||||
return ['export_result'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
@@ -89,25 +91,41 @@ class CountPersonWithAccompanyingCourse implements ExportInterface, GroupedExpor
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('acp')
|
||||
->join('acp.participations', 'acppart')
|
||||
->join('acppart.person', 'person');
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb = $this->repository->createQueryBuilder('acp');
|
||||
|
||||
if (!in_array('acppart', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acp.participations', 'acppart');
|
||||
}
|
||||
|
||||
if (!in_array('partperson', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acppart.person', 'person');
|
||||
}
|
||||
|
||||
$qb->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);
|
||||
|
||||
$qb->select('COUNT(DISTINCT person.id) AS export_result');
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole()
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(AccompanyingPeriodVoter::STATS);
|
||||
return AccompanyingPeriodVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
{
|
||||
return [
|
||||
Declarations::ACP_TYPE,
|
||||
Declarations::PERSON_TYPE,
|
||||
Declarations::ACP_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -15,24 +15,23 @@ use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class CountSocialWorkActions implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
protected EntityRepository $repository;
|
||||
protected EntityManagerInterface $em;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
) {
|
||||
$this->repository = $em->getRepository(AccompanyingPeriod::class);
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder): void
|
||||
@@ -74,9 +73,9 @@ class CountSocialWorkActions implements ExportInterface, GroupedExportInterface
|
||||
return ['export_result'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
@@ -91,24 +90,43 @@ class CountSocialWorkActions implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = []): QueryBuilder
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('acp')
|
||||
->join('acp.works', 'acpw');
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb->select('COUNT(acpw.id) as export_result');
|
||||
$qb = $this->em->createQueryBuilder();
|
||||
|
||||
$qb
|
||||
->from(AccompanyingPeriod\AccompanyingPeriodWork::class, 'acpw')
|
||||
->join('acpw.accompanyingPeriod', 'acp')
|
||||
->join('acp.participations', 'acppart')
|
||||
->join('acppart.person', 'person')
|
||||
->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)
|
||||
'
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
$qb->select('COUNT(DISTINCT acpw.id) as export_result');
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): Role
|
||||
public function requiredRole(): string
|
||||
{
|
||||
//TODO change to string, but changes needed also in ExportManager and possibly other locations.
|
||||
return new Role(AccompanyingPeriodVoter::STATS);
|
||||
return AccompanyingPeriodVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
{
|
||||
return [
|
||||
Declarations::SOCIAL_WORK_ACTION_TYPE,
|
||||
Declarations::ACP_TYPE,
|
||||
Declarations::PERSON_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,416 @@
|
||||
<?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\Entity\Address;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
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\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
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\Repository\PersonRepository;
|
||||
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Chill\PersonBundle\Templating\Entity\PersonRenderInterface;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
|
||||
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
|
||||
use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\AbstractQuery;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function strlen;
|
||||
|
||||
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 SocialIssueRender $socialIssueRender;
|
||||
|
||||
private SocialIssueRepository $socialIssueRepository;
|
||||
|
||||
private ThirdPartyRender $thirdPartyRender;
|
||||
|
||||
private ThirdPartyRepository $thirdPartyRepository;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
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,
|
||||
UserHelper $userHelper
|
||||
) {
|
||||
$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->userHelper = $userHelper;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('calc_date', ChillDateType::class, [
|
||||
'input' => 'datetime_immutable',
|
||||
'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,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getAllowedFormattersTypes()
|
||||
{
|
||||
return [FormatterInterface::TYPE_LIST];
|
||||
}
|
||||
|
||||
public function getDescription()
|
||||
{
|
||||
return 'export.list.acp.Generate a list of accompanying periods, filtered on different parameters.';
|
||||
}
|
||||
|
||||
public function getGroup(): string
|
||||
{
|
||||
return 'Exports of accompanying courses';
|
||||
}
|
||||
|
||||
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));
|
||||
};
|
||||
|
||||
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)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
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)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
default:
|
||||
return static function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
return 'export.list.acp.' . $key;
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
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()
|
||||
{
|
||||
return 'export.list.acp.List of accompanying periods';
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return Declarations::PERSON_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(AccompanyingPeriod::class, 'acp')
|
||||
->andWhere('acp.step != :list_acp_step')
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
->setParameter('list_acp_step', AccompanyingPeriod::STEP_DRAFT)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
$this->addSelectClauses($qb, $data['calc_date']);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return PersonVoter::LISTS;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
{
|
||||
return [
|
||||
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')
|
||||
->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull('personAddress'),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte('personAddress.validFrom', ':calcDate'),
|
||||
$qb->expr()->orX($qb->expr()->isNull('personAddress.validTo'), $qb->expr()->gt('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);
|
||||
}
|
||||
}
|
@@ -17,22 +17,22 @@ use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||
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\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Export\Helper\ListPersonHelper;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use DateTime;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Query;
|
||||
use Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Validator\Constraints\Callback;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use function addcslashes;
|
||||
use function array_key_exists;
|
||||
@@ -40,7 +40,7 @@ use function array_keys;
|
||||
use function array_merge;
|
||||
use function count;
|
||||
use function in_array;
|
||||
use function strtolower;
|
||||
use function strlen;
|
||||
use function uniqid;
|
||||
|
||||
/**
|
||||
@@ -48,40 +48,35 @@ use function uniqid;
|
||||
*/
|
||||
class ListPerson implements ExportElementValidatedInterface, ListInterface, GroupedExportInterface
|
||||
{
|
||||
protected CustomFieldProvider $customFieldProvider;
|
||||
private ExportAddressHelper $addressHelper;
|
||||
|
||||
protected EntityManagerInterface $entityManager;
|
||||
private CustomFieldProvider $customFieldProvider;
|
||||
|
||||
protected array $fields = [
|
||||
'id', 'firstName', 'lastName', 'birthdate',
|
||||
'placeOfBirth', 'gender', 'memo', 'email', 'phonenumber',
|
||||
'mobilenumber', 'contactInfo', 'countryOfBirth', 'nationality',
|
||||
'address_street_address_1', 'address_street_address_2',
|
||||
'address_valid_from', 'address_postcode_label', 'address_postcode_code',
|
||||
'address_country_name', 'address_country_code', 'address_isnoaddress',
|
||||
];
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
protected TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
protected TranslatorInterface $translator;
|
||||
private ListPersonHelper $listPersonHelper;
|
||||
|
||||
private $slugs = [];
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ExportAddressHelper $addressHelper,
|
||||
CustomFieldProvider $customFieldProvider,
|
||||
ListPersonHelper $listPersonHelper,
|
||||
EntityManagerInterface $em,
|
||||
TranslatorInterface $translator,
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
CustomFieldProvider $customFieldProvider
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->entityManager = $em;
|
||||
$this->translator = $translator;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->addressHelper = $addressHelper;
|
||||
$this->customFieldProvider = $customFieldProvider;
|
||||
$this->listPersonHelper = $listPersonHelper;
|
||||
$this->entityManager = $em;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$choices = array_combine($this->fields, $this->fields);
|
||||
$choices = array_combine(ListPersonHelper::FIELDS, ListPersonHelper::FIELDS);
|
||||
|
||||
foreach ($this->getCustomFields() as $cf) {
|
||||
$choices[$this->translatableStringHelper->localize($cf->getName())]
|
||||
@@ -97,7 +92,7 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
||||
'label' => 'Fields to include in export',
|
||||
'choice_attr' => static function (string $val): array {
|
||||
// add a 'data-display-target' for address fields
|
||||
if (substr($val, 0, 8) === 'address_') {
|
||||
if (substr($val, 0, 7) === 'address' || 'center' === $val || 'household' === $val) {
|
||||
return ['data-display-target' => 'address_date'];
|
||||
}
|
||||
|
||||
@@ -112,17 +107,15 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
||||
}
|
||||
},
|
||||
])],
|
||||
'data' => array_values($choices),
|
||||
]);
|
||||
|
||||
// add a date field for addresses
|
||||
$builder->add('address_date', DateType::class, [
|
||||
'label' => 'Address valid at this date',
|
||||
'data' => new DateTime(),
|
||||
'attr' => ['class' => 'datepicker'],
|
||||
'widget' => 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
'required' => false,
|
||||
'block_name' => 'list_export_form_address_date',
|
||||
$builder->add('address_date', ChillDateType::class, [
|
||||
'label' => 'Data valid at this date',
|
||||
'help' => 'Data regarding center, addresses, and so on will be computed at this date',
|
||||
'data' => new DateTimeImmutable(),
|
||||
'input' => 'datetime_immutable',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -143,113 +136,35 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'birthdate':
|
||||
// for birthdate, we have to transform the string into a date
|
||||
// to format the date correctly.
|
||||
return static function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'birthdate';
|
||||
}
|
||||
|
||||
if (empty($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$date = DateTime::createFromFormat('Y-m-d', $value);
|
||||
// check that the creation could occurs.
|
||||
if (false === $date) {
|
||||
throw new Exception(sprintf('The value %s could '
|
||||
. 'not be converted to %s', $value, DateTime::class));
|
||||
}
|
||||
|
||||
return $date->format('d-m-Y');
|
||||
};
|
||||
|
||||
case 'gender':
|
||||
// for gender, we have to translate men/women statement
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'gender';
|
||||
}
|
||||
|
||||
return $this->translator->trans($value);
|
||||
};
|
||||
|
||||
case 'countryOfBirth':
|
||||
case 'nationality':
|
||||
$countryRepository = $this->entityManager
|
||||
->getRepository(\Chill\MainBundle\Entity\Country::class);
|
||||
|
||||
// load all countries in a single query
|
||||
$countryRepository->findBy(['countryCode' => $values]);
|
||||
|
||||
return function ($value) use ($key, $countryRepository) {
|
||||
if ('_header' === $value) {
|
||||
return strtolower($key);
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return $this->translator->trans('no data');
|
||||
}
|
||||
|
||||
$country = $countryRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$country->getName()
|
||||
);
|
||||
};
|
||||
|
||||
case 'address_country_name':
|
||||
return function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
return strtolower($key);
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize(json_decode($value, true));
|
||||
};
|
||||
|
||||
case 'address_isnoaddress':
|
||||
return static function (?string $value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'address.address_homeless';
|
||||
}
|
||||
|
||||
if (null !== $value) {
|
||||
return 'X';
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
default:
|
||||
// for fields which are associated with person
|
||||
if (in_array($key, $this->fields, true)) {
|
||||
return static function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
return strtolower($key);
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
return $this->getLabelForCustomField($key, $values, $data);
|
||||
if (in_array($key, $this->listPersonHelper->getAllPossibleFields(), true)) {
|
||||
return $this->listPersonHelper->getLabels($key, $values, $data);
|
||||
}
|
||||
|
||||
return $this->getLabelForCustomField($key, $values, $data);
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
$fields = [];
|
||||
|
||||
foreach ($data['fields'] as $key) {
|
||||
if (in_array($key, $this->fields, true)) {
|
||||
$fields[] = $key;
|
||||
foreach (ListPersonHelper::FIELDS as $key) {
|
||||
if (!in_array($key, $data['fields'], true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (substr($key, 0, strlen('address_fields')) === 'address_fields') {
|
||||
$fields = array_merge($fields, $this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields'));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('lifecycleUpdate' === $key) {
|
||||
$fields = array_merge($fields, ['createdAt', 'createdBy', 'updatedAt', 'updatedBy']);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$fields[] = $key;
|
||||
}
|
||||
|
||||
// add the key from slugs and return
|
||||
@@ -271,6 +186,9 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
||||
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 function ($el) {
|
||||
@@ -285,40 +203,24 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
||||
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
|
||||
foreach ($this->fields as $f) {
|
||||
if (in_array($f, $data['fields'], true)) {
|
||||
switch ($f) {
|
||||
case 'countryOfBirth':
|
||||
case 'nationality':
|
||||
$qb->addSelect(sprintf('IDENTITY(person.%s) as %s', $f, $f));
|
||||
$qb
|
||||
->from(Person::class, 'person')
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . Person\PersonCenterHistory::class . ' pch WHERE pch.person = person.id AND pch.center IN (:authorized_centers)'
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
break;
|
||||
$fields = $data['fields'];
|
||||
|
||||
case 'address_street_address_1':
|
||||
case 'address_street_address_2':
|
||||
case 'address_valid_from':
|
||||
case 'address_postcode_label':
|
||||
case 'address_postcode_code':
|
||||
case 'address_country_name':
|
||||
case 'address_country_code':
|
||||
case 'address_isnoaddress':
|
||||
$qb->addSelect(sprintf(
|
||||
'GET_PERSON_ADDRESS_%s(person.id, :address_date) AS %s',
|
||||
// get the part after address_
|
||||
strtoupper(substr($f, 8)),
|
||||
$f
|
||||
));
|
||||
$qb->setParameter('address_date', $data['address_date']);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$qb->addSelect(sprintf('person.%s as %s', $f, $f));
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->listPersonHelper->addSelect($qb, $fields, $data['address_date']);
|
||||
|
||||
foreach ($this->getCustomFields() as $cf) {
|
||||
if (!in_array($cf->getSlug(), $fields, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cfType = $this->customFieldProvider->getCustomFieldByType($cf->getType());
|
||||
|
||||
if ($cfType instanceof CustomFieldChoice && $cfType->isMultiple($cf)) {
|
||||
@@ -346,18 +248,12 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
||||
}
|
||||
}
|
||||
|
||||
$qb
|
||||
->from('ChillPersonBundle:Person', 'person')
|
||||
->join('person.center', 'center')
|
||||
->andWhere('center IN (:authorized_centers)')
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole()
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(PersonVoter::LISTS);
|
||||
return PersonVoter::LISTS;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
@@ -369,14 +265,14 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
||||
{
|
||||
// get the field starting with address_
|
||||
$addressFields = array_filter(
|
||||
$this->fields,
|
||||
ListPersonHelper::FIELDS,
|
||||
static fn (string $el): bool => substr($el, 0, 8) === 'address_'
|
||||
);
|
||||
|
||||
// check if there is one field starting with address in data
|
||||
if (count(array_intersect($data['fields'], $addressFields)) > 0) {
|
||||
// if a field address is checked, the date must not be empty
|
||||
if (empty($data['address_date'])) {
|
||||
if (!$data['address_date'] instanceof DateTimeImmutable) {
|
||||
$context
|
||||
->buildViolation('You must set this date if an address is checked')
|
||||
->atPath('address_date')
|
||||
@@ -457,7 +353,7 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
||||
. ' | ' . $label;
|
||||
}
|
||||
|
||||
if ('_other' === $slugChoice && $cfType->isChecked($cf, $choiceSlug, $decoded)) {
|
||||
if ('_other' === $slugChoice && $cfType->isChecked($cf, $slugChoice, $decoded)) {
|
||||
return $cfType->extractOtherValue($cf, $decoded);
|
||||
}
|
||||
|
||||
|
@@ -24,7 +24,6 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
@@ -121,10 +120,7 @@ class ListPersonDuplicate implements DirectExportInterface, ExportElementValidat
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create a list of duplicate people';
|
||||
}
|
||||
@@ -142,9 +138,9 @@ class ListPersonDuplicate implements DirectExportInterface, ExportElementValidat
|
||||
return 'List duplicates';
|
||||
}
|
||||
|
||||
public function requiredRole(): Role
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(PersonVoter::DUPLICATE);
|
||||
return PersonVoter::DUPLICATE;
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
|
@@ -0,0 +1,220 @@
|
||||
<?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\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
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;
|
||||
|
||||
class ListPersonWithAccompanyingPeriod implements ExportElementValidatedInterface, ListInterface, GroupedExportInterface
|
||||
{
|
||||
private ExportAddressHelper $addressHelper;
|
||||
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
private ListPersonHelper $listPersonHelper;
|
||||
|
||||
public function __construct(
|
||||
ExportAddressHelper $addressHelper,
|
||||
ListPersonHelper $listPersonHelper,
|
||||
EntityManagerInterface $em
|
||||
) {
|
||||
$this->addressHelper = $addressHelper;
|
||||
$this->listPersonHelper = $listPersonHelper;
|
||||
$this->entityManager = $em;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$choices = array_combine(ListPersonHelper::FIELDS, ListPersonHelper::FIELDS);
|
||||
|
||||
// Add a checkbox to select fields
|
||||
$builder->add('fields', ChoiceType::class, [
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'choices' => $choices,
|
||||
'label' => 'Fields to include in export',
|
||||
'choice_attr' => static function (string $val): array {
|
||||
// add a 'data-display-target' for address fields
|
||||
if (substr($val, 0, 7) === 'address' || 'center' === $val || 'household' === $val) {
|
||||
return ['data-display-target' => 'address_date'];
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
'constraints' => [new Callback([
|
||||
'callback' => static function ($selected, ExecutionContextInterface $context) {
|
||||
if (count($selected) === 0) {
|
||||
$context->buildViolation('You must select at least one element')
|
||||
->atPath('fields')
|
||||
->addViolation();
|
||||
}
|
||||
},
|
||||
])],
|
||||
'data' => array_values($choices),
|
||||
]);
|
||||
|
||||
// add a date field for addresses
|
||||
$builder->add('address_date', ChillDateType::class, [
|
||||
'label' => 'Data valid at this date',
|
||||
'help' => 'Data regarding center, addresses, and so on will be computed at this date',
|
||||
'data' => new DateTimeImmutable(),
|
||||
'input' => 'datetime_immutable',
|
||||
]);
|
||||
}
|
||||
|
||||
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, according to various filters.';
|
||||
}
|
||||
|
||||
public function getGroup(): string
|
||||
{
|
||||
return 'Exports of persons';
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return $this->listPersonHelper->getLabels($key, $values, $data);
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
$fields = [];
|
||||
|
||||
foreach (ListPersonHelper::FIELDS as $key) {
|
||||
if (!in_array($key, $data['fields'], true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (substr($key, 0, strlen('address_fields')) === 'address_fields') {
|
||||
$fields = array_merge($fields, $this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields'));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('lifecycleUpdate' === $key) {
|
||||
$fields = array_merge($fields, ['createdAt', 'createdBy', 'updatedAt', 'updatedBy']);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$fields[] = $key;
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
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 function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
// throw an error if any fields are present
|
||||
if (!array_key_exists('fields', $data)) {
|
||||
throw new \Doctrine\DBAL\Exception\InvalidArgumentException('any fields '
|
||||
. 'have been checked');
|
||||
}
|
||||
|
||||
$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);
|
||||
|
||||
$fields = $data['fields'];
|
||||
|
||||
$this->listPersonHelper->addSelect($qb, $fields, $data['address_date']);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return PersonVoter::LISTS;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
{
|
||||
return [Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN, Declarations::ACP_TYPE];
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
// get the field starting with address_
|
||||
$addressFields = array_filter(
|
||||
ListPersonHelper::FIELDS,
|
||||
static fn (string $el): bool => substr($el, 0, 8) === 'address_'
|
||||
);
|
||||
|
||||
// check if there is one field starting with address in data
|
||||
if (count(array_intersect($data['fields'], $addressFields)) > 0) {
|
||||
// if a field address is checked, the date must not be empty
|
||||
if (!$data['address_date'] instanceof DateTimeImmutable) {
|
||||
$context
|
||||
->buildViolation('You must set this date if an address is checked')
|
||||
->atPath('address_date')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,6 +16,7 @@ use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use DateTime;
|
||||
@@ -23,8 +24,8 @@ use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class StatAccompanyingCourseDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
@@ -51,7 +52,7 @@ class StatAccompanyingCourseDuration implements ExportInterface, GroupedExportIn
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create an average of accompanying courses duration according to various filters';
|
||||
return 'Create an average of accompanying courses duration of each person participation to accompanying course, according to filters on persons, accompanying course';
|
||||
}
|
||||
|
||||
public function getGroup(): string
|
||||
@@ -61,31 +62,47 @@ class StatAccompanyingCourseDuration implements ExportInterface, GroupedExportIn
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ('export_result' !== $key) {
|
||||
throw new LogicException("the key {$key} is not used by this export");
|
||||
}
|
||||
return static function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
switch ($key) {
|
||||
case 'avg_export_result':
|
||||
return 'export.export.acp_stats.avg_duration';
|
||||
|
||||
$labels = array_combine($values, $values);
|
||||
$labels['_header'] = $this->getTitle();
|
||||
case 'count_acppart_export_result':
|
||||
return 'export.export.acp_stats.count_participations';
|
||||
|
||||
return static function ($value) use ($labels) {
|
||||
return $labels[$value];
|
||||
case 'count_acp_export_result':
|
||||
return 'export.export.acp_stats.count_acps';
|
||||
|
||||
case 'count_pers_export_result':
|
||||
return 'export.export.acp_stats.count_persons';
|
||||
|
||||
default:
|
||||
throw new LogicException('key not supported: ' . $key);
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['export_result'];
|
||||
return ['avg_export_result', 'count_acp_export_result', 'count_acppart_export_result', 'count_pers_export_result'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Accompanying courses duration';
|
||||
return 'Accompanying courses participation duration and number of participations';
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
@@ -95,30 +112,48 @@ class StatAccompanyingCourseDuration implements ExportInterface, GroupedExportIn
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = []): QueryBuilder
|
||||
{
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb = $this->repository->createQueryBuilder('acp');
|
||||
|
||||
$qb
|
||||
->select('AVG(
|
||||
( CASE
|
||||
WHEN acp.closingDate IS NOT NULL
|
||||
THEN acp.closingDate
|
||||
ELSE :force_closingDate
|
||||
END ) - acp.openingDate
|
||||
) AS export_result')
|
||||
->setParameter('force_closingDate', $data['closingdate']);
|
||||
LEAST(acppart.endDate, COALESCE(acp.closingDate, :force_closingDate))
|
||||
- GREATEST(acppart.startDate, COALESCE(acp.openingDate, :force_closingDate))
|
||||
) AS avg_export_result')
|
||||
->addSelect('COUNT(DISTINCT acppart.id) AS count_acppart_export_result')
|
||||
->addSelect('COUNT(DISTINCT person.id) AS count_pers_export_result')
|
||||
->addSelect('COUNT(DISTINCT acp.id) AS count_acp_export_result')
|
||||
->setParameter('force_closingDate', $data['closingdate'])
|
||||
->leftJoin('acp.participations', 'acppart')
|
||||
->leftJoin('acppart.person', 'person')
|
||||
->andWhere('acp.step != :count_acp_step')
|
||||
->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)
|
||||
'
|
||||
)
|
||||
)
|
||||
->setParameter('count_acp_step', AccompanyingPeriod::STEP_DRAFT)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): Role
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(AccompanyingPeriodVoter::STATS);
|
||||
return AccompanyingPeriodVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
{
|
||||
return [
|
||||
Declarations::ACP_TYPE,
|
||||
Declarations::PERSON_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -12,17 +12,24 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
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\Export\Declarations;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ActiveOnDateFilter implements FilterInterface
|
||||
{
|
||||
public function addRole()
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
public function __construct(RollingDateConverterInterface $rollingDateConverter)
|
||||
{
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -46,7 +53,10 @@ class ActiveOnDateFilter implements FilterInterface
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('ondate', $data['on_date'], Types::DATE_MUTABLE);
|
||||
$qb->setParameter(
|
||||
'ondate',
|
||||
$this->rollingDateConverter->convert($data['on_date'])
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -57,15 +67,15 @@ class ActiveOnDateFilter implements FilterInterface
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('on_date', ChillDateType::class, [
|
||||
'data' => new DateTime(),
|
||||
->add('on_date', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['Filtered by actives courses: active on %ondate%', [
|
||||
'%ondate%' => $data['on_date']->format('d-m-Y'),
|
||||
'%ondate%' => $this->rollingDateConverter->convert($data['on_date'])->format('d-m-Y'),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@@ -12,43 +12,40 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
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\Export\Declarations;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ActiveOneDayBetweenDatesFilter implements FilterInterface
|
||||
{
|
||||
public function addRole()
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
public function __construct(RollingDateConverterInterface $rollingDateConverter)
|
||||
{
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = "OVERLAPSI (acp.openingDate, acp.closingDate), (:datefrom, :dateto) = 'TRUE'";
|
||||
|
||||
$clause = $qb->expr()->orX(
|
||||
$qb->expr()->lt('(acp.openingDate + 1)', ':dateto'),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lt('acp.openingDate', ':datefrom'),
|
||||
$qb->expr()->isNull('acp.closingDate')
|
||||
),
|
||||
$qb->expr()->gt('(acp.closingDate - 1)', ':datefrom')
|
||||
$qb->andWhere($clause);
|
||||
$qb->setParameter(
|
||||
'datefrom',
|
||||
$this->rollingDateConverter->convert($data['date_from'])
|
||||
);
|
||||
$qb->setParameter(
|
||||
'dateto',
|
||||
$this->rollingDateConverter->convert($data['date_to'])
|
||||
);
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('datefrom', $data['date_from'], Types::DATE_MUTABLE);
|
||||
$qb->setParameter('dateto', $data['date_to'], Types::DATE_MUTABLE);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -59,19 +56,19 @@ class ActiveOneDayBetweenDatesFilter implements FilterInterface
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('date_from', ChillDateType::class, [
|
||||
'data' => new DateTime(),
|
||||
->add('date_from', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
|
||||
])
|
||||
->add('date_to', ChillDateType::class, [
|
||||
'data' => new DateTime(),
|
||||
->add('date_to', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['Filtered by actives courses: at least one day between %datefrom% and %dateto%', [
|
||||
'%datefrom%' => $data['date_from']->format('d-m-Y'),
|
||||
'%dateto%' => $data['date_to']->format('d-m-Y'),
|
||||
'%datefrom%' => $this->rollingDateConverter->convert($data['date_from'])->format('d-m-Y'),
|
||||
'%dateto%' => $this->rollingDateConverter->convert($data['date_to'])->format('d-m-Y'),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@@ -1,99 +0,0 @@
|
||||
<?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\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
* TODO merge with ActivityTypeFilter in ChillActivity (!?).
|
||||
*/
|
||||
class ActivityTypeFilter implements FilterInterface
|
||||
{
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
// One2many between activity and accompanyingperiod is not reversed !
|
||||
// we replace indicator 'from' clause by 'act', and put 'acp' in a join
|
||||
|
||||
$qb->resetDQLPart('from');
|
||||
$qb->from('ChillActivityBundle:Activity', 'act');
|
||||
|
||||
$qb
|
||||
->join('act.accompanyingPeriod', 'acp')
|
||||
->join('act.activityType', 'aty');
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('aty.id', ':activitytypes');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('activitytypes', $data['accepted_activitytypes']);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_activitytypes', EntityType::class, [
|
||||
'class' => ActivityType::class,
|
||||
'choice_label' => function (ActivityType $aty) {
|
||||
return $this->translatableStringHelper->localize($aty->getName());
|
||||
},
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
$types = [];
|
||||
|
||||
foreach ($data['accepted_activitytypes'] as $aty) {
|
||||
$types[] = $this->translatableStringHelper->localize($aty->getName());
|
||||
}
|
||||
|
||||
return ['Filtered by activity types: only %activitytypes%', [
|
||||
'%activitytypes%' => implode(', ou ', $types),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter accompanying course by activity type';
|
||||
}
|
||||
}
|
@@ -11,13 +11,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Entity\Location;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickUserLocationType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class AdministrativeLocationFilter implements FilterInterface
|
||||
@@ -30,24 +28,17 @@ class AdministrativeLocationFilter implements FilterInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('acp.administrativeLocation', ':locations');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('locations', $data['accepted_locations']);
|
||||
$qb
|
||||
->andWhere($clause)
|
||||
->setParameter('locations', $data['accepted_locations']);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -57,13 +48,9 @@ class AdministrativeLocationFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_locations', EntityType::class, [
|
||||
'class' => Location::class,
|
||||
'choice_label' => function (Location $l) {
|
||||
return $l->getName() . ' (' . $this->translatableStringHelper->localize($l->getLocationType()->getTitle()) . ')';
|
||||
},
|
||||
$builder->add('accepted_locations', PickUserLocationType::class, [
|
||||
'label' => 'Accepted locations',
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -76,7 +63,7 @@ class AdministrativeLocationFilter implements FilterInterface
|
||||
}
|
||||
|
||||
return ['Filtered by administratives locations: only %locations%', [
|
||||
'%locations%' => implode(', ou ', $locations),
|
||||
'%locations%' => implode(', ', $locations),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@ class ClosingMotiveFilter implements FilterInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -77,7 +77,7 @@ class ClosingMotiveFilter implements FilterInterface
|
||||
|
||||
return [
|
||||
'Filtered by closingmotive: only %closingmotives%', [
|
||||
'%closingmotives%' => implode(', ou ', $motives),
|
||||
'%closingmotives%' => implode(', ', $motives),
|
||||
], ];
|
||||
}
|
||||
|
||||
|
@@ -35,7 +35,7 @@ class ConfidentialFilter implements FilterInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -73,17 +73,11 @@ class ConfidentialFilter implements FilterInterface
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
dump($data, self::CHOICES);
|
||||
|
||||
foreach (self::CHOICES as $k => $v) {
|
||||
if ($v === $data['accepted_confidentials']) {
|
||||
$choice = $k;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'Filtered by confidential: only %confidential%', [
|
||||
'%confidential%' => $this->translator->trans($choice),
|
||||
'%confidential%' => $this->translator->trans(
|
||||
$data['accepted_confidentials'] ? 'is confidential' : 'is not confidential'
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
@@ -0,0 +1,66 @@
|
||||
<?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\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class CreatorFilter implements FilterInterface
|
||||
{
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('acp_creator', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acp.createdBy', 'acp_creator');
|
||||
}
|
||||
|
||||
$qb
|
||||
->andWhere($qb->expr()->in('acp_creator', ':creators'))
|
||||
->setParameter('creators', $data['accepted_creators']);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('accepted_creators', PickUserDynamicType::class, [
|
||||
'multiple' => true,
|
||||
'label' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return [
|
||||
'Filtered by creator: only %creators%', [
|
||||
'%creators%' => implode(', ', array_map(static fn (User $u) => $u->getLabel(), $data['accepted_creators'])),
|
||||
], ];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by creator';
|
||||
}
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
<?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\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class CreatorJobFilter implements FilterInterface
|
||||
{
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
private UserJobRepositoryInterface $userJobRepository;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
UserJobRepositoryInterface $userJobRepository
|
||||
) {
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->userJobRepository = $userJobRepository;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('acp_creator', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acp.createdBy', 'acp_creator');
|
||||
}
|
||||
|
||||
$qb
|
||||
->andWhere($qb->expr()->in('acp_creator.userJob', ':creator_job'))
|
||||
->setParameter('creator_job', $data['creator_job']);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('creator_job', EntityType::class, [
|
||||
'class' => UserJob::class,
|
||||
'choices' => $this->userJobRepository->findAllActive(),
|
||||
'choice_label' => function (UserJob $j) {
|
||||
return $this->translatableStringHelper->localize(
|
||||
$j->getLabel()
|
||||
);
|
||||
},
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'label' => 'Job',
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
$creatorJobs = [];
|
||||
|
||||
foreach ($data['creator_job'] as $j) {
|
||||
$creatorJobs[] = $this->translatableStringHelper->localize(
|
||||
$j->getLabel()
|
||||
);
|
||||
}
|
||||
|
||||
return ['export.filter.course.creator_job.Filtered by creator job: only %jobs%', [
|
||||
'%jobs%' => implode(', ', $creatorJobs),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by creator job';
|
||||
}
|
||||
}
|
@@ -1,90 +0,0 @@
|
||||
<?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\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
class CurrentUserJobFilter implements FilterInterface
|
||||
{
|
||||
private Security $security;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
Security $security
|
||||
) {
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->eq('acp.job', ':userjob');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('userjob', $this->getUserJob());
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return [
|
||||
'Filtered by user job: only %job%', [
|
||||
'%job%' => $this->translatableStringHelper->localize(
|
||||
$this->getUserJob()->getLabel()
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Filter by user job';
|
||||
}
|
||||
|
||||
private function getUserJob(): UserJob
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->security->getUser();
|
||||
|
||||
return $user->getUserJob();
|
||||
}
|
||||
}
|
@@ -1,92 +0,0 @@
|
||||
<?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\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
class CurrentUserScopeFilter implements FilterInterface
|
||||
{
|
||||
private Security $security;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
Security $security
|
||||
) {
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acp.scopes', 's');
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->eq('s.id', ':userscope');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('userscope', $this->getUserMainScope());
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return [
|
||||
'Filtered by user main scope: only %scope%', [
|
||||
'%scope%' => $this->translatableStringHelper->localize(
|
||||
$this->getUserMainScope()->getName()
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Filter by user scope';
|
||||
}
|
||||
|
||||
private function getUserMainScope(): Scope
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->security->getUser();
|
||||
|
||||
return $user->getMainScope();
|
||||
}
|
||||
}
|
@@ -35,7 +35,7 @@ class EmergencyFilter implements FilterInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -73,15 +73,11 @@ class EmergencyFilter implements FilterInterface
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
foreach (self::CHOICES as $k => $v) {
|
||||
if ($v === $data['accepted_emergency']) {
|
||||
$choice = $k;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'Filtered by emergency: only %emergency%', [
|
||||
'%emergency%' => $this->translator->trans($choice),
|
||||
'%emergency%' => $this->translator->trans(
|
||||
$data['accepted_emergency'] ? 'is emergency' : 'is not emergency'
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
@@ -15,43 +15,47 @@ use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Entity\SocialWork\Evaluation;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Chill\PersonBundle\Repository\SocialWork\EvaluationRepositoryInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class EvaluationFilter implements FilterInterface
|
||||
{
|
||||
private EvaluationRepositoryInterface $evaluationRepository;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
EvaluationRepositoryInterface $evaluationRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->evaluationRepository = $evaluationRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb
|
||||
->join('acp.works', 'acpw')
|
||||
->join('acpw.accompanyingPeriodWorkEvaluations', 'we')
|
||||
->join('we.evaluation', 'ev');
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('ev.id', ':evaluations');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
if (!in_array('acpw', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acp.works', 'acpw');
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
if (!in_array('workeval', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acpw.accompanyingPeriodWorkEvaluations', 'workeval');
|
||||
}
|
||||
|
||||
if (!in_array('eval', $qb->getAllAliases(), true)) {
|
||||
$qb->join('workeval.evaluation', 'eval');
|
||||
}
|
||||
|
||||
$clause = $qb->expr()->in('eval.id', ':evaluations');
|
||||
$qb->andWhere($clause);
|
||||
$qb->setParameter('evaluations', $data['accepted_evaluations']);
|
||||
}
|
||||
|
||||
@@ -64,11 +68,13 @@ class EvaluationFilter implements FilterInterface
|
||||
{
|
||||
$builder->add('accepted_evaluations', EntityType::class, [
|
||||
'class' => Evaluation::class,
|
||||
'choices' => $this->evaluationRepository->findAllActive(),
|
||||
'choice_label' => function (Evaluation $ev) {
|
||||
return $this->translatableStringHelper->localize($ev->getTitle());
|
||||
},
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'expanded' => false,
|
||||
'attr' => ['class' => 'select2'],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -81,7 +87,7 @@ class EvaluationFilter implements FilterInterface
|
||||
}
|
||||
|
||||
return ['Filtered by evaluations: only %evals%', [
|
||||
'%evals%' => implode(', ou ', $evaluations),
|
||||
'%evals%' => implode(', ', $evaluations),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@@ -11,48 +11,82 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Entity\GeographicalUnit;
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
use Chill\MainBundle\Entity\GeographicalUnit\SimpleGeographicalUnitDTO;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface;
|
||||
use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
* e) par zone géographique.
|
||||
*
|
||||
* Paramètre:
|
||||
* * Date
|
||||
* * Choix unique entre: territoire, epci, canton, commune, secteur d'intervention
|
||||
* * une fois le premier choix effectué, l'utilisateur choisi parmi les zones (choix multiple)
|
||||
*
|
||||
* Le filtre retiendra les parcours localisé dans un des territoires cochés, à la date indiquée en paramètre.
|
||||
* Filter accompanying period by geographical zone.
|
||||
*/
|
||||
class GeographicalUnitStatFilter implements FilterInterface
|
||||
{
|
||||
public function addRole()
|
||||
private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository;
|
||||
|
||||
private GeographicalUnitRepositoryInterface $geographicalUnitRepository;
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
GeographicalUnitRepositoryInterface $geographicalUnitRepository,
|
||||
GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->geographicalUnitRepository = $geographicalUnitRepository;
|
||||
$this->geographicalUnitLayerRepository = $geographicalUnitLayerRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->eq(1, 1);
|
||||
$subQueryDql =
|
||||
'SELECT
|
||||
1
|
||||
FROM ' . AccompanyingPeriod\AccompanyingPeriodLocationHistory::class . ' acp_geog_filter_location_history
|
||||
LEFT JOIN ' . PersonHouseholdAddress::class . ' acp_geog_filter_address_person_location
|
||||
WITH IDENTITY(acp_geog_filter_location_history.personLocation) = IDENTITY(acp_geog_filter_address_person_location.person)
|
||||
LEFT JOIN ' . Address::class . ' acp_geog_filter_address
|
||||
WITH COALESCE(IDENTITY(acp_geog_filter_address_person_location.address), IDENTITY(acp_geog_filter_location_history.addressLocation)) = acp_geog_filter_address.id
|
||||
LEFT JOIN acp_geog_filter_address.geographicalUnits acp_geog_filter_units
|
||||
WHERE
|
||||
(acp_geog_filter_location_history.startDate <= :acp_geog_filter_date AND (
|
||||
acp_geog_filter_location_history.endDate IS NULL OR acp_geog_filter_location_history.endDate < :acp_geog_filter_date
|
||||
))
|
||||
AND
|
||||
(acp_geog_filter_address_person_location.validFrom < :acp_geog_filter_date AND (
|
||||
acp_geog_filter_address_person_location.validTo IS NULL OR acp_geog_filter_address_person_location.validTo < :acp_geog_filter_date
|
||||
))
|
||||
AND acp_geog_filter_units IN (:acp_geog_filter_units)
|
||||
AND acp_geog_filter_location_history.period = acp.id
|
||||
';
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('date', $data['date'], Types::DATE_MUTABLE);
|
||||
$qb->setParameter('loctype', $data['accepted_loctype']);
|
||||
$qb
|
||||
->andWhere($qb->expr()->exists($subQueryDql))
|
||||
->setParameter(
|
||||
'acp_geog_filter_date',
|
||||
$this->rollingDateConverter->convert($data['date_calc'])
|
||||
)
|
||||
->setParameter('acp_geog_filter_units', array_map(static fn (SimpleGeographicalUnitDTO $unitDTO) => $unitDTO->id, $data['units']));
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -63,23 +97,39 @@ class GeographicalUnitStatFilter implements FilterInterface
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('date', ChillDateType::class, [
|
||||
'data' => new DateTime(),
|
||||
->add('date_calc', PickRollingDateType::class, [
|
||||
'label' => 'Compute geographical location at date',
|
||||
'required' => true,
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
])
|
||||
->add('accepted_loctype', EntityType::class, [
|
||||
'class' => GeographicalUnit::class,
|
||||
'choice_label' => static function (GeographicalUnit $u) {
|
||||
return $u->getUnitName();
|
||||
->add('units', ChoiceType::class, [
|
||||
'label' => 'Geographical unit',
|
||||
'placeholder' => 'Select a geographical unit',
|
||||
'choices' => $this->geographicalUnitRepository->findAll(),
|
||||
'choice_value' => static fn (SimpleGeographicalUnitDTO $item) => $item->id,
|
||||
'choice_label' => function (SimpleGeographicalUnitDTO $item) {
|
||||
return $this->translatableStringHelper->localize($this->geographicalUnitLayerRepository->find($item->layerId)->getName()) . ' > ' . $item->unitName;
|
||||
},
|
||||
'attr' => [
|
||||
'class' => 'select2',
|
||||
],
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['Filtered by geographic unit: only %date%', [
|
||||
'%date%' => $data['date']->format('d-m-Y'),
|
||||
return ['Filtered by geographic unit: computed at %date%, only in %units%', [
|
||||
'%date%' => $this->rollingDateConverter->convert($data['date_calc'])->format('d-m-Y'),
|
||||
'%units' => implode(
|
||||
', ',
|
||||
array_map(
|
||||
function (SimpleGeographicalUnitDTO $item) {
|
||||
return $this->translatableStringHelper->localize($this->geographicalUnitLayerRepository->find($item->layerId)->getName()) . ' > ' . $item->unitName;
|
||||
},
|
||||
$data['units']
|
||||
)
|
||||
),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,51 @@
|
||||
<?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\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class HasNoActionFilter implements FilterInterface
|
||||
{
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data): void
|
||||
{
|
||||
$qb->andWhere('NOT EXISTS (SELECT 1 FROM ' . AccompanyingPeriodWork::class . ' work WHERE work.accompanyingPeriod = acp)');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder): void
|
||||
{
|
||||
// no form
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['Filtered acp which has no actions'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by which has no action';
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
<?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\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\UserHistory;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class HasNoReferrerFilter implements FilterInterface
|
||||
{
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
public function __construct(
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb
|
||||
->andWhere('
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM ' . UserHistory::class . ' uh
|
||||
WHERE uh.startDate <= :has_no_referrer_filter_date
|
||||
AND (
|
||||
uh.endDate IS NULL
|
||||
or uh.endDate > :has_no_referrer_filter_date
|
||||
)
|
||||
AND uh.accompanyingPeriod = acp
|
||||
)
|
||||
')
|
||||
->setParameter(
|
||||
'has_no_referrer_filter_date',
|
||||
$this->rollingDateConverter->convert($data['calc_date'])
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('calc_date', PickRollingDateType::class, [
|
||||
'label' => 'Has no referrer on this date',
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['Filtered acp which has no referrer on date: %date%', [
|
||||
'%date%' => $this->rollingDateConverter->convert($data['calc_date'])->format('d-m-Y'),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by which has no referrer';
|
||||
}
|
||||
}
|
@@ -0,0 +1,116 @@
|
||||
<?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\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class HasTemporaryLocationFilter implements FilterInterface
|
||||
{
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
public function __construct(
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb
|
||||
->join('acp.locationHistories', 'acp_having_temporarily_location')
|
||||
->andWhere('acp_having_temporarily_location.startDate <= :acp_having_temporarily_location_date
|
||||
AND (acp_having_temporarily_location.endDate IS NULL OR acp_having_temporarily_location.endDate > :acp_having_temporarily_location_date)')
|
||||
->setParameter(
|
||||
'acp_having_temporarily_location_date',
|
||||
$this->rollingDateConverter->convert($data['calc_date'])
|
||||
);
|
||||
|
||||
switch ($data['having_temporarily']) {
|
||||
case true:
|
||||
$qb->andWhere('acp_having_temporarily_location.addressLocation IS NOT NULL');
|
||||
|
||||
break;
|
||||
|
||||
case false:
|
||||
$qb->andWhere('acp_having_temporarily_location.personLocation IS NOT NULL');
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LogicException('value not supported');
|
||||
}
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('having_temporarily', ChoiceType::class, [
|
||||
'choices' => [
|
||||
'export.filter.course.having_temporarily.Having a temporarily location' => true,
|
||||
'export.filter.course.having_temporarily.Having a person\'s location' => false,
|
||||
],
|
||||
'choice_label' => static function ($choice) {
|
||||
switch ($choice) {
|
||||
case true:
|
||||
return 'export.filter.course.having_temporarily.Having a temporarily location';
|
||||
|
||||
case false:
|
||||
return 'export.filter.course.having_temporarily.Having a person\'s location';
|
||||
|
||||
default:
|
||||
throw new LogicException('this choice is not supported');
|
||||
}
|
||||
},
|
||||
])
|
||||
->add('calc_date', PickRollingDateType::class, [
|
||||
'label' => 'export.filter.course.having_temporarily.Calculation date',
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
switch ($data['having_temporarily']) {
|
||||
case true:
|
||||
return ['export.filter.course.having_temporarily.Having a temporarily location', []];
|
||||
|
||||
case false:
|
||||
return ['export.filter.course.having_temporarily.Having a person\'s location', []];
|
||||
|
||||
default:
|
||||
throw new LogicException('value not supported');
|
||||
}
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by temporary location';
|
||||
}
|
||||
}
|
@@ -35,7 +35,7 @@ class IntensityFilter implements FilterInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -73,15 +73,9 @@ class IntensityFilter implements FilterInterface
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
foreach (self::CHOICES as $k => $v) {
|
||||
if ($v === $data['accepted_intensities']) {
|
||||
$choice = $k;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'Filtered by intensity: only %intensity%', [
|
||||
'%intensity%' => $this->translator->trans($choice),
|
||||
'%intensity%' => $this->translator->trans($data['accepted_intensities']),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
@@ -12,39 +12,38 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
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\Export\Declarations;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class OpenBetweenDatesFilter implements FilterInterface
|
||||
{
|
||||
public function addRole()
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
public function __construct(RollingDateConverterInterface $rollingDateConverter)
|
||||
{
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->lt('acp.openingDate', ':datefrom'),
|
||||
$qb->expr()->gt('acp.closingDate', ':dateto')
|
||||
$qb->expr()->gte('acp.openingDate', ':datefrom'),
|
||||
$qb->expr()->lte('acp.openingDate', ':dateto')
|
||||
);
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('datefrom', $data['date_from'], Types::DATE_MUTABLE);
|
||||
$qb->setParameter('dateto', $data['date_to'], Types::DATE_MUTABLE);
|
||||
$qb->andWhere($clause);
|
||||
$qb->setParameter('datefrom', $this->rollingDateConverter->convert($data['date_from']), Types::DATE_IMMUTABLE);
|
||||
$qb->setParameter('dateto', $this->rollingDateConverter->convert($data['date_to']), Types::DATE_IMMUTABLE);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -55,19 +54,19 @@ class OpenBetweenDatesFilter implements FilterInterface
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('date_from', ChillDateType::class, [
|
||||
'data' => new DateTime(),
|
||||
->add('date_from', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_MONTH_PREVIOUS_START),
|
||||
])
|
||||
->add('date_to', ChillDateType::class, [
|
||||
'data' => new DateTime(),
|
||||
->add('date_to', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['Filtered by opening dates: between %datefrom% and %dateto%', [
|
||||
'%datefrom%' => $data['date_from']->format('d-m-Y'),
|
||||
'%dateto%' => $data['date_to']->format('d-m-Y'),
|
||||
'%datefrom%' => $this->rollingDateConverter->convert($data['date_from'])->format('d-m-Y'),
|
||||
'%dateto%' => $this->rollingDateConverter->convert($data['date_to'])->format('d-m-Y'),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@ class OriginFilter implements FilterInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ class OriginFilter implements FilterInterface
|
||||
}
|
||||
|
||||
return ['Filtered by origins: only %origins%', [
|
||||
'%origins%' => implode(', ou ', $origins),
|
||||
'%origins%' => implode(', ', $origins),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@@ -11,42 +11,62 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ReferrerFilter implements FilterInterface
|
||||
{
|
||||
private const A = 'acp_referrer_filter_uhistory';
|
||||
|
||||
private const P = 'acp_referrer_filter_date';
|
||||
|
||||
private const PU = 'acp_referrer_filter_users';
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private UserRender $userRender;
|
||||
|
||||
public function __construct(UserRender $userRender)
|
||||
{
|
||||
public function __construct(
|
||||
UserRender $userRender,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->userRender = $userRender;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('acp.user', ':referrers');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('referrers', $data['accepted_referrers']);
|
||||
$qb
|
||||
->join('acp.userHistories', self::A)
|
||||
->andWhere(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte(self::A . '.startDate', ':' . self::P),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull(self::A . '.endDate'),
|
||||
$qb->expr()->gt(self::A . '.endDate', ':' . self::P)
|
||||
)
|
||||
)
|
||||
)
|
||||
->andWhere(
|
||||
$qb->expr()->in(self::A . '.user', ':' . self::PU)
|
||||
)
|
||||
->setParameter(self::PU, $data['accepted_referrers'])
|
||||
->setParameter(
|
||||
self::P,
|
||||
$this->rollingDateConverter->convert($data['date_calc'])
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -56,14 +76,15 @@ class ReferrerFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_referrers', EntityType::class, [
|
||||
'class' => User::class,
|
||||
'choice_label' => function (User $u) {
|
||||
return $this->userRender->renderString($u, []);
|
||||
},
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
$builder
|
||||
->add('accepted_referrers', PickUserDynamicType::class, [
|
||||
'multiple' => true,
|
||||
])
|
||||
->add('date_calc', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
'label' => 'export.filter.course.by_referrer.Computation date for referrer',
|
||||
'required' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
@@ -76,7 +97,7 @@ class ReferrerFilter implements FilterInterface
|
||||
|
||||
return [
|
||||
'Filtered by referrer: only %referrers%', [
|
||||
'%referrers' => implode(', ou ', $users),
|
||||
'%referrers' => implode(', ', $users),
|
||||
], ];
|
||||
}
|
||||
|
||||
|
@@ -20,8 +20,9 @@ use Exception;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use function in_array;
|
||||
|
||||
class RequestorFilter implements FilterInterface
|
||||
final class RequestorFilter implements FilterInterface
|
||||
{
|
||||
private const DEFAULT_CHOICE = 'participation';
|
||||
|
||||
@@ -32,9 +33,9 @@ class RequestorFilter implements FilterInterface
|
||||
'no requestor' => 'no_requestor',
|
||||
];
|
||||
|
||||
protected EntityManagerInterface $em;
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
protected TranslatorInterface $translator;
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(
|
||||
TranslatorInterface $translator,
|
||||
@@ -44,7 +45,7 @@ class RequestorFilter implements FilterInterface
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -55,11 +56,13 @@ class RequestorFilter implements FilterInterface
|
||||
|
||||
switch ($data['accepted_choices']) {
|
||||
case 'participation':
|
||||
$qb->join('acp.participations', 'part');
|
||||
if (!in_array('acppart', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acp.participations', 'acppart');
|
||||
}
|
||||
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('acp.requestorPerson'),
|
||||
$qb->expr()->eq('acp.requestorPerson', 'part.person')
|
||||
$qb->expr()->eq('acp.requestorPerson', 'acppart.person')
|
||||
);
|
||||
|
||||
break;
|
||||
@@ -67,8 +70,6 @@ class RequestorFilter implements FilterInterface
|
||||
case 'other_person':
|
||||
$expr = $this->em->getExpressionBuilder();
|
||||
|
||||
$qb->join('acp.participations', 'part');
|
||||
|
||||
$clause = $expr->andX(
|
||||
$expr->isNotNull('acp.requestorPerson'),
|
||||
$expr->notIn(
|
||||
@@ -76,10 +77,11 @@ class RequestorFilter implements FilterInterface
|
||||
|
||||
// subquery
|
||||
$this->em->createQueryBuilder()
|
||||
->select('identity(acp2.requestorPerson)')
|
||||
->from('ChillPersonBundle:AccompanyingPeriod', 'acp2')
|
||||
->join('acp2.participations', 'part2')
|
||||
->where($expr->eq('acp2.requestorPerson', 'part2.person'))
|
||||
->join('acp2.participations', 'acppart2')
|
||||
->select('identity(acp2.requestorPerson)')
|
||||
->where($expr->eq('acp2.requestorPerson', 'acppart2.person'))
|
||||
->andWhere('acp2.id = acp.id')
|
||||
->getDQL()
|
||||
)
|
||||
);
|
||||
|
@@ -15,10 +15,9 @@ use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Form\Type\PickSocialActionType;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
@@ -36,7 +35,7 @@ class SocialActionFilter implements FilterInterface
|
||||
$this->actionRender = $actionRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -46,19 +45,18 @@ class SocialActionFilter implements FilterInterface
|
||||
if (!in_array('acpw', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acp.works', 'acpw');
|
||||
}
|
||||
$qb->join('acpw.socialAction', 'sa');
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('sa.id', ':socialactions');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
if (!in_array('acpwsocialaction', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acpw.socialAction', 'acpwsocialaction');
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('socialactions', $data['accepted_socialactions']);
|
||||
$clause = $qb->expr()->in('acpwsocialaction.id', ':socialactions');
|
||||
|
||||
$qb->andWhere($clause)
|
||||
->setParameter(
|
||||
'socialactions',
|
||||
SocialAction::getDescendantsWithThisForActions($data['accepted_socialactions'])->toArray()
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -68,26 +66,25 @@ class SocialActionFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_socialactions', EntityType::class, [
|
||||
'class' => SocialAction::class,
|
||||
'choice_label' => function (SocialAction $sa) {
|
||||
return $this->actionRender->renderString($sa, []);
|
||||
},
|
||||
$builder->add('accepted_socialactions', PickSocialActionType::class, [
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
$socialactions = [];
|
||||
$actions = [];
|
||||
|
||||
foreach ($data['accepted_socialactions'] as $sa) {
|
||||
$socialactions[] = $this->actionRender->renderString($sa, []);
|
||||
$socialactions = $data['accepted_socialactions'];
|
||||
|
||||
foreach ($socialactions as $action) {
|
||||
$actions[] = $this->actionRender->renderString($action, [
|
||||
'show_and_children' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
return ['Filtered by socialactions: only %socialactions%', [
|
||||
'%socialactions%' => implode(', ou ', $socialactions),
|
||||
'%socialactions%' => implode(', ', $actions),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@@ -12,15 +12,14 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\PersonBundle\Form\Type\PickSocialIssueType;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use function in_array;
|
||||
|
||||
class SocialIssueFilter implements FilterInterface
|
||||
{
|
||||
@@ -31,41 +30,32 @@ class SocialIssueFilter implements FilterInterface
|
||||
|
||||
private SocialIssueRender $socialIssueRender;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
TranslatorInterface $translator,
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
SocialIssueRender $socialIssueRender
|
||||
) {
|
||||
$this->translator = $translator;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->socialIssueRender = $socialIssueRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join('acp.socialIssues', 'si');
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('si.id', ':socialissues');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
if (!in_array('acpsocialissue', $qb->getAllAliases(), true)) {
|
||||
$qb->join('acp.socialIssues', 'acpsocialissue');
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter(
|
||||
'socialissues',
|
||||
$this->addParentIssues($data['accepted_socialissues'])
|
||||
);
|
||||
$clause = $qb->expr()->in('acpsocialissue.id', ':socialissues');
|
||||
|
||||
$qb->andWhere($clause)
|
||||
->setParameter(
|
||||
'socialissues',
|
||||
SocialIssue::getDescendantsWithThisForIssues($data['accepted_socialissues']->toArray())
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
@@ -75,74 +65,31 @@ class SocialIssueFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_socialissues', EntityType::class, [
|
||||
'class' => SocialIssue::class,
|
||||
'choice_label' => function ($socialIssue) {
|
||||
return $this->socialIssueRender->renderString($socialIssue, []);
|
||||
},
|
||||
$builder->add('accepted_socialissues', PickSocialIssueType::class, [
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
$issues = [];
|
||||
|
||||
$socialissues = $this->addParentIssues($data['accepted_socialissues']);
|
||||
$socialissues = $data['accepted_socialissues'];
|
||||
|
||||
foreach ($socialissues as $i) {
|
||||
if ('null' === $i) {
|
||||
$issues[] = $this->translator->trans('Not given');
|
||||
} else {
|
||||
$issues[] = $this->socialIssueRender->renderString($i, []);
|
||||
}
|
||||
foreach ($socialissues as $issue) {
|
||||
$issues[] = $this->socialIssueRender->renderString($issue, [
|
||||
'show_and_children' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
return [
|
||||
'Filtered by socialissues: only %socialissues%', [
|
||||
'%socialissues%' => implode(', ou ', $issues),
|
||||
'%socialissues%' => implode(', ', $issues),
|
||||
], ];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by social issue';
|
||||
}
|
||||
|
||||
/**
|
||||
* "Le filtre retiendra les parcours qui comportent cette problématique,
|
||||
* ou une problématique parente à celles choisies.".
|
||||
*
|
||||
* Add parent of each socialissue selected, and remove duplicates
|
||||
*
|
||||
* @param $accepted_issues
|
||||
*/
|
||||
private function addParentIssues($accepted_issues): array
|
||||
{
|
||||
$array = [];
|
||||
|
||||
foreach ($accepted_issues as $i) {
|
||||
/** @var SocialIssue $i */
|
||||
if ($i->hasParent()) {
|
||||
$array[] = $i->getParent();
|
||||
}
|
||||
$array[] = $i;
|
||||
}
|
||||
|
||||
return $this->removeDuplicate($array);
|
||||
}
|
||||
|
||||
private function removeDuplicate(array $array): array
|
||||
{
|
||||
$ids = array_map(static function ($item) {
|
||||
return $item->getId();
|
||||
}, $array);
|
||||
|
||||
$unique_ids = array_unique($ids);
|
||||
|
||||
return array_values(
|
||||
array_intersect_key($array, $unique_ids)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -12,52 +12,72 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
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\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use function in_array;
|
||||
|
||||
class StepFilter implements FilterInterface
|
||||
{
|
||||
private const A = 'acp_filter_bystep_stephistories';
|
||||
|
||||
private const DEFAULT_CHOICE = AccompanyingPeriod::STEP_CONFIRMED;
|
||||
|
||||
private const P = 'acp_step_filter_date';
|
||||
|
||||
private const STEPS = [
|
||||
'Draft' => AccompanyingPeriod::STEP_DRAFT,
|
||||
'Confirmed' => AccompanyingPeriod::STEP_CONFIRMED,
|
||||
'Closed' => AccompanyingPeriod::STEP_CLOSED,
|
||||
];
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
private $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
public function __construct(
|
||||
RollingDateConverterInterface $rollingDateConverter,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->eq('acp.step', ':step');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
if (!in_array(self::A, $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('acp.stepHistories', self::A);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('step', $data['accepted_steps']);
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte(self::A . '.startDate', ':' . self::P),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull(self::A . '.endDate'),
|
||||
$qb->expr()->lt(self::A . '.endDate', ':' . self::P)
|
||||
)
|
||||
)
|
||||
)
|
||||
->andWhere(
|
||||
$qb->expr()->in(self::A . '.step', ':acp_filter_by_step_steps')
|
||||
)
|
||||
->setParameter(self::P, $this->rollingDateConverter->convert($data['calc_date']))
|
||||
->setParameter('acp_filter_by_step_steps', $data['accepted_steps']);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
@@ -67,13 +87,18 @@ class StepFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_steps', ChoiceType::class, [
|
||||
'choices' => self::STEPS,
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'empty_data' => self::DEFAULT_CHOICE,
|
||||
'data' => self::DEFAULT_CHOICE,
|
||||
]);
|
||||
$builder
|
||||
->add('accepted_steps', ChoiceType::class, [
|
||||
'choices' => self::STEPS,
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'empty_data' => self::DEFAULT_CHOICE,
|
||||
'data' => self::DEFAULT_CHOICE,
|
||||
])
|
||||
->add('calc_date', PickRollingDateType::class, [
|
||||
'label' => 'export.acp.filter.by_step.date_calc',
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
|
@@ -0,0 +1,137 @@
|
||||
<?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\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
class UserJobFilter implements FilterInterface
|
||||
{
|
||||
private const A = 'acp_ujob_filter_uhistory';
|
||||
|
||||
private const AU = 'acp_ujob_filter_uhistory_user';
|
||||
|
||||
private const P = 'acp_ujob_filter_date';
|
||||
|
||||
private const PJ = 'acp_ujob_filter_job';
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private Security $security;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
private UserJobRepositoryInterface $userJobRepository;
|
||||
|
||||
public function __construct(
|
||||
Security $security,
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
UserJobRepositoryInterface $userJobRepository,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->security = $security;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->userJobRepository = $userJobRepository;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb
|
||||
->join('acp.userHistories', self::A)
|
||||
->andWhere(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte(self::A . '.startDate', ':' . self::P),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull(self::A . '.endDate'),
|
||||
$qb->expr()->gt(self::A . '.endDate', ':' . self::P)
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameter(
|
||||
self::P,
|
||||
$this->rollingDateConverter->convert($data['date_calc'])
|
||||
)
|
||||
->join(self::A . '.user', self::AU)
|
||||
->andWhere(
|
||||
$qb->expr()->in(self::AU . '.userJob', ':' . self::PJ)
|
||||
)
|
||||
->setParameter(self::PJ, $data['jobs']);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('jobs', EntityType::class, [
|
||||
'class' => UserJob::class,
|
||||
'choices' => $this->userJobRepository->findAllActive(),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'choice_label' => fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()),
|
||||
'label' => 'Job',
|
||||
])
|
||||
->add('date_calc', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
'label' => 'export.filter.course.by_user_scope.Computation date for referrer',
|
||||
'required' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return [
|
||||
'Filtered by user job: only %job%', [
|
||||
'%job%' => implode(
|
||||
', ',
|
||||
array_map(
|
||||
fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()),
|
||||
$data['jobs']->toArray()
|
||||
)
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Filter by user job';
|
||||
}
|
||||
|
||||
private function getUserJob(): UserJob
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->security->getUser();
|
||||
|
||||
return $user->getUserJob();
|
||||
}
|
||||
}
|
@@ -0,0 +1,136 @@
|
||||
<?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\Filter\AccompanyingCourseFilters;
|
||||
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
class UserScopeFilter implements FilterInterface
|
||||
{
|
||||
private const A = 'acp_uscope_filter_uhistory';
|
||||
|
||||
private const AU = 'acp_uscope_filter_uhistory_user';
|
||||
|
||||
private const P = 'acp_uscope_filter_date';
|
||||
|
||||
private const PS = 'acp_uscope_filter_scopes';
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private ScopeRepositoryInterface $scopeRepository;
|
||||
|
||||
private Security $security;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ScopeRepositoryInterface $scopeRepository,
|
||||
Security $security,
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
$this->security = $security;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb
|
||||
->join('acp.userHistories', self::A)
|
||||
->andWhere(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte(self::A . '.startDate', ':' . self::P),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull(self::A . '.endDate'),
|
||||
$qb->expr()->gt(self::A . '.endDate', ':' . self::P)
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameter(
|
||||
self::P,
|
||||
$this->rollingDateConverter->convert($data['date_calc'])
|
||||
)
|
||||
->join(self::A . '.user', self::AU)
|
||||
->andWhere(
|
||||
$qb->expr()->in(self::AU . '.mainScope', ':' . self::PS)
|
||||
)
|
||||
->setParameter(self::PS, $data['scopes']);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('scopes', EntityType::class, [
|
||||
'class' => Scope::class,
|
||||
'choices' => $this->scopeRepository->findAllActive(),
|
||||
'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
])
|
||||
->add('date_calc', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
'label' => 'export.filter.course.by_user_scope.Computation date for referrer',
|
||||
'required' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return [
|
||||
'Filtered by user main scope: only %scope%', [
|
||||
'%scope%' => implode(
|
||||
', ',
|
||||
array_map(
|
||||
fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
|
||||
$data['scopes']->toArray()
|
||||
)
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Filter by user scope';
|
||||
}
|
||||
|
||||
private function getUserMainScope(): Scope
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->security->getUser();
|
||||
|
||||
return $user->getMainScope();
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
<?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\Filter\EvaluationFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ByEndDateFilter implements FilterInterface
|
||||
{
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
public function __construct(RollingDateConverterInterface $rollingDateConverter)
|
||||
{
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data): void
|
||||
{
|
||||
$qb
|
||||
->andWhere('workeval.endDate BETWEEN :work_eval_by_end_date_start_date and :work_eval_by_end_date_end_date')
|
||||
->setParameter(
|
||||
'work_eval_by_end_date_start_date',
|
||||
$this->rollingDateConverter->convert($data['start_date'])
|
||||
)
|
||||
->setParameter(
|
||||
'work_eval_by_end_date_end_date',
|
||||
$this->rollingDateConverter->convert($data['end_date'])
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::EVAL_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder): void
|
||||
{
|
||||
$builder
|
||||
->add('start_date', PickRollingDateType::class, [
|
||||
'label' => 'start period date',
|
||||
'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
|
||||
])
|
||||
->add('end_date', PickRollingDateType::class, [
|
||||
'label' => 'end period date',
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['Filtered by end date: between %start_date% and %end_date%', [
|
||||
'%start_date%' => $this->rollingDateConverter->convert($data['start_date'])->format('d-m-Y'),
|
||||
'%end_date%' => $this->rollingDateConverter->convert($data['end_date'])->format('d-m-Y'),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by end date evaluations';
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
<?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\Filter\EvaluationFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ByStartDateFilter implements FilterInterface
|
||||
{
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
public function __construct(RollingDateConverterInterface $rollingDateConverter)
|
||||
{
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data): void
|
||||
{
|
||||
$qb
|
||||
->andWhere('workeval.startDate BETWEEN :work_eval_by_start_date_start_date and :work_eval_by_start_date_end_date')
|
||||
->setParameter(
|
||||
'work_eval_by_start_date_start_date',
|
||||
$this->rollingDateConverter->convert($data['start_date'])
|
||||
)
|
||||
->setParameter(
|
||||
'work_eval_by_start_date_end_date',
|
||||
$this->rollingDateConverter->convert($data['end_date'])
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::EVAL_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder): void
|
||||
{
|
||||
$builder
|
||||
->add('start_date', PickRollingDateType::class, [
|
||||
'label' => 'start period date',
|
||||
'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
|
||||
])
|
||||
->add('end_date', PickRollingDateType::class, [
|
||||
'label' => 'end period date',
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['Filtered by start date: between %start_date% and %end_date%', [
|
||||
'%start_date%' => $this->rollingDateConverter->convert($data['start_date'])->format('d-m-Y'),
|
||||
'%end_date%' => $this->rollingDateConverter->convert($data['end_date'])->format('d-m-Y'),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by start date evaluations';
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
<?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\Filter\EvaluationFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class CurrentEvaluationsFilter implements FilterInterface
|
||||
{
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data): void
|
||||
{
|
||||
$qb->andWhere('workeval.endDate IS NULL');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::EVAL_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder): void
|
||||
{
|
||||
//no form needed
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['Filtered by current evaluations'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by current evaluations';
|
||||
}
|
||||
}
|
@@ -30,7 +30,7 @@ final class EvaluationTypeFilter implements FilterInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ final class EvaluationTypeFilter implements FilterInterface
|
||||
}
|
||||
|
||||
return ['Filtered by evaluation type: only %evals%', [
|
||||
'%evals%' => implode(', ou ', $evals),
|
||||
'%evals%' => implode(', ', $evals),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@@ -13,7 +13,6 @@ namespace Chill\PersonBundle\Export\Filter\EvaluationFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@@ -22,8 +21,8 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
class MaxDateFilter implements FilterInterface
|
||||
{
|
||||
private const MAXDATE_CHOICES = [
|
||||
'is specified' => true,
|
||||
'is not specified' => false,
|
||||
'maxdate is specified' => true,
|
||||
'maxdate is not specified' => false,
|
||||
];
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
@@ -33,28 +32,20 @@ class MaxDateFilter implements FilterInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
|
||||
if (true === $data['maxdate']) {
|
||||
$clause = $qb->expr()->isNotNull('eval.maxDate');
|
||||
$clause = $qb->expr()->isNotNull('workeval.maxDate');
|
||||
} else {
|
||||
$clause = $qb->expr()->isNull('eval.maxDate');
|
||||
$clause = $qb->expr()->isNull('workeval.maxDate');
|
||||
}
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->andWhere($clause);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -73,19 +64,15 @@ class MaxDateFilter implements FilterInterface
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
foreach (self::MAXDATE_CHOICES as $k => $v) {
|
||||
if ($v === $data['maxdate']) {
|
||||
$choice = $k;
|
||||
}
|
||||
}
|
||||
|
||||
return ['Filtered by maxdate: only %choice%', [
|
||||
'%choice%' => $this->translator->trans($choice),
|
||||
'%choice%' => $this->translator->trans(
|
||||
$data['maxdate'] ? 'maxdate is specified' : 'maxdate is not specified'
|
||||
),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by maxdate';
|
||||
return 'Filter evaluations by maxdate mention';
|
||||
}
|
||||
}
|
||||
|
@@ -12,13 +12,13 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Export\Filter\HouseholdFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
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\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdCompositionType;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@@ -26,47 +26,46 @@ use function in_array;
|
||||
|
||||
class CompositionFilter implements FilterInterface
|
||||
{
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('composition', $qb->getAllAliases(), true)) {
|
||||
$qb->join('household.compositions', 'composition');
|
||||
if (!in_array('composition_type_filter', $qb->getAllAliases(), true)) {
|
||||
$clause =
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte('composition_type_filter.startDate', ':ondate_composition_type_filter'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gt('composition_type_filter.endDate', ':ondate_composition_type_filter'),
|
||||
$qb->expr()->isNull('composition_type_filter.endDate')
|
||||
)
|
||||
);
|
||||
|
||||
$qb->join('household.compositions', 'composition', Expr\Join::WITH, $clause);
|
||||
}
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
$whereClause = $qb->expr()->in('composition_type_filter.householdCompositionType', ':compositions');
|
||||
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->in('composition.householdCompositionType', ':compositions'),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte('composition.startDate', ':ondate'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gt('composition.endDate', ':ondate'),
|
||||
$qb->expr()->isNull('composition.endDate')
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->andWhere($whereClause);
|
||||
$qb->setParameter('compositions', $data['accepted_composition']);
|
||||
$qb->setParameter('ondate', $data['on_date'], Types::DATE_MUTABLE);
|
||||
$qb->setParameter(
|
||||
'ondate_composition_type_filter',
|
||||
$this->rollingDateConverter->convert($data['on_date'])
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -87,8 +86,8 @@ class CompositionFilter implements FilterInterface
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
])
|
||||
->add('on_date', ChillDateType::class, [
|
||||
'data' => new DateTime('now'),
|
||||
->add('on_date', PickRollingDateType::class, [
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -103,8 +102,8 @@ class CompositionFilter implements FilterInterface
|
||||
}
|
||||
|
||||
return ['Filtered by composition: only %compositions% on %ondate%', [
|
||||
'%compositions%' => implode(', ou ', $compositions),
|
||||
'%ondate%' => $data['on_date']->format('d-m-Y'),
|
||||
'%compositions%' => implode(', ', $compositions),
|
||||
'%ondate%' => $this->rollingDateConverter->convert($data['on_date'])->format('d-m-Y'),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@@ -1,78 +0,0 @@
|
||||
<?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\Filter\PersonFilters;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\PersonBundle\Export\AbstractAccompanyingPeriodExportElement;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class AccompanyingPeriodClosingFilter extends AbstractAccompanyingPeriodExportElement implements FilterInterface
|
||||
{
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$this->addJoinAccompanyingPeriod($qb);
|
||||
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->lte('accompanying_period.closingDate', ':date_to'),
|
||||
$qb->expr()->gte('accompanying_period.closingDate', ':date_from')
|
||||
);
|
||||
|
||||
$qb->andWhere($clause);
|
||||
$qb->setParameter('date_from', $data['date_from'], Types::DATE_MUTABLE);
|
||||
$qb->setParameter('date_to', $data['date_to'], Types::DATE_MUTABLE);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::PERSON_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_from', ChillDateType::class, [
|
||||
'label' => 'Having an accompanying period closed after this date',
|
||||
'data' => new DateTime('-1 month'),
|
||||
]);
|
||||
|
||||
$builder->add('date_to', ChillDateType::class, [
|
||||
'label' => 'Having an accompanying period closed before this date',
|
||||
'data' => new DateTime(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return [
|
||||
'Filtered by accompanying period: persons having an accompanying period'
|
||||
. ' closed between the %date_from% and %date_to%',
|
||||
[
|
||||
'%date_from%' => $data['date_from']->format('d-m-Y'),
|
||||
'%date_to%' => $data['date_to']->format('d-m-Y'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter by accompanying period: closed between two dates';
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user