Merge branch 'master' into 616_rapid-action

This commit is contained in:
2023-07-12 15:38:51 +02:00
404 changed files with 11850 additions and 1276 deletions

View File

@@ -51,7 +51,10 @@ class UserRefEventSubscriber implements EventSubscriberInterface
public function onStateEntered(EnteredEvent $enteredEvent): void
{
if ($enteredEvent->getMarking()->has(AccompanyingPeriod::STEP_CONFIRMED)) {
if (
$enteredEvent->getMarking()->has(AccompanyingPeriod::STEP_CONFIRMED)
and $enteredEvent->getTransition()->getName() === 'confirm'
) {
$this->onPeriodConfirmed($enteredEvent->getSubject());
}
}

View File

@@ -219,13 +219,13 @@ class AccompanyingPeriodController extends AbstractController
]);
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
$accompanyingPeriodsRaw = $this->accompanyingPeriodACLAwareRepository
->findByPerson($person, AccompanyingPeriodVoter::SEE);
$accompanyingPeriods = $this->accompanyingPeriodACLAwareRepository
->findByPerson($person, AccompanyingPeriodVoter::SEE, ["openingDate" => "DESC", "id" => "DESC"]);
usort($accompanyingPeriodsRaw, static fn ($a, $b) => $b->getOpeningDate() > $a->getOpeningDate());
//usort($accompanyingPeriodsRaw, static fn ($a, $b) => $b->getOpeningDate() <=> $a->getOpeningDate());
// filter visible or not visible
$accompanyingPeriods = array_filter($accompanyingPeriodsRaw, fn (AccompanyingPeriod $ap) => $this->isGranted(AccompanyingPeriodVoter::SEE, $ap));
//$accompanyingPeriods = array_filter($accompanyingPeriodsRaw, fn (AccompanyingPeriod $ap) => $this->isGranted(AccompanyingPeriodVoter::SEE, $ap));
return $this->render('@ChillPerson/AccompanyingPeriod/list.html.twig', [
'accompanying_periods' => $accompanyingPeriods,

View File

@@ -78,6 +78,7 @@ class AccompanyingPeriodRegulationListController
$form['jobs']->getData(),
$form['services']->getData(),
$form['locations']->getData(),
['openingDate' => 'DESC', 'id' => 'DESC'],
$paginator->getItemsPerPage(),
$paginator->getCurrentPageFirstItemNumber()
);

View File

@@ -20,6 +20,7 @@ use Chill\MainBundle\Repository\UserRepository;
use Chill\MainBundle\Templating\Entity\UserRender;
use Chill\PersonBundle\Repository\AccompanyingPeriodACLAwareRepositoryInterface;
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\CallbackTransformer;
@@ -30,6 +31,7 @@ use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Security;
@@ -85,8 +87,8 @@ class ReassignAccompanyingPeriodController extends AbstractController
*/
public function listAction(Request $request): Response
{
if (!$this->security->isGranted('ROLE_USER') || !$this->security->getUser() instanceof User) {
throw new AccessDeniedException();
if (!$this->security->isGranted(AccompanyingPeriodVoter::REASSIGN_BULK)) {
throw new AccessDeniedHttpException('no right to reassign bulk');
}
$form = $this->buildFilterForm();
@@ -96,7 +98,7 @@ class ReassignAccompanyingPeriodController extends AbstractController
$userFrom = $form['user']->getData();
$postalCodes = $form['postal_code']->getData() instanceof PostalCode ? [$form['postal_code']->getData()] : [];
$total = $this->accompanyingPeriodACLAwareRepository->countByUserOpenedAccompanyingPeriod($userFrom);
$total = $this->accompanyingPeriodACLAwareRepository->countByUserAndPostalCodesOpenedAccompanyingPeriod($userFrom, $postalCodes);
$paginator = $this->paginatorFactory->create($total);
$paginator->setItemsPerPage(50);
$periods = $this->accompanyingPeriodACLAwareRepository

View File

@@ -16,21 +16,19 @@ use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Serializer\Model\Collection;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use function count;
class SocialWorkSocialActionApiController extends ApiController
final class SocialWorkSocialActionApiController extends ApiController
{
private PaginatorFactory $paginator;
private SocialIssueRepository $socialIssueRepository;
public function __construct(SocialIssueRepository $socialIssueRepository, PaginatorFactory $paginator)
{
$this->socialIssueRepository = $socialIssueRepository;
$this->paginator = $paginator;
public function __construct(
private readonly SocialIssueRepository $socialIssueRepository,
private readonly PaginatorFactory $paginator,
private readonly ClockInterface $clock,
) {
}
public function listBySocialIssueApi($id, Request $request)
@@ -42,7 +40,10 @@ class SocialWorkSocialActionApiController extends ApiController
throw $this->createNotFoundException('socialIssue not found');
}
$socialActions = $socialIssue->getRecursiveSocialActions()->toArray();
$socialActions = SocialAction::filterRemoveDeactivatedActions(
$socialIssue->getRecursiveSocialActions()->toArray(),
\DateTime::createFromImmutable($this->clock->now())
);
usort($socialActions, static fn (SocialAction $sa, SocialAction $sb) => $sa->getOrdering() <=> $sb->getOrdering());

View File

@@ -12,9 +12,11 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class UserAccompanyingPeriodController extends AbstractController
@@ -32,12 +34,24 @@ class UserAccompanyingPeriodController extends AbstractController
/**
* @Route("/{_locale}/person/accompanying-periods/my", name="chill_person_accompanying_period_user")
*/
public function listAction(Request $request)
public function listAction(Request $request): Response
{
$total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => ['CONFIRMED', 'CLOSED']]);
$active = $request->query->getBoolean('active', true);
$steps = match ($active) {
true => [
AccompanyingPeriod::STEP_CONFIRMED,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
],
false => [
AccompanyingPeriod::STEP_CLOSED,
]
};
$total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => $steps]);
$pagination = $this->paginatorFactory->create($total);
$accompanyingPeriods = $this->accompanyingPeriodRepository->findBy(
['user' => $this->getUser(), 'step' => ['CONFIRMED', 'CLOSED']],
['user' => $this->getUser(), 'step' => $steps],
['openingDate' => 'DESC'],
$pagination->getItemsPerPage(),
$pagination->getCurrentPageFirstItemNumber()
@@ -46,13 +60,14 @@ class UserAccompanyingPeriodController extends AbstractController
return $this->render('@ChillPerson/AccompanyingPeriod/user_periods_list.html.twig', [
'accompanyingPeriods' => $accompanyingPeriods,
'pagination' => $pagination,
'active' => $active,
]);
}
/**
* @Route("/{_locale}/person/accompanying-periods/my/drafts", name="chill_person_accompanying_period_draft_user")
*/
public function listDraftsAction(Request $request)
public function listDraftsAction(): Response
{
$total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => 'DRAFT']);
$pagination = $this->paginatorFactory->create($total);

View File

@@ -983,11 +983,8 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
AccompanyingPeriodVoter::EDIT,
AccompanyingPeriodVoter::DELETE,
],
AccompanyingPeriodVoter::REASSIGN_BULK => [
AccompanyingPeriodVoter::CONFIDENTIAL_CRUD,
],
AccompanyingPeriodVoter::TOGGLE_CONFIDENTIAL => [
AccompanyingPeriodVoter::CONFIDENTIAL_CRUD,
AccompanyingPeriodVoter::TOGGLE_CONFIDENTIAL_ALL => [
AccompanyingPeriodVoter::SEE_CONFIDENTIAL_ALL,
],
],
]);

View File

@@ -185,7 +185,9 @@ class AccompanyingPeriod implements
* cascade={"persist", "remove"},
* orphanRemoval=true
* )
* @ORM\OrderBy({"createdAt": "DESC", "id": "DESC"})
* @Assert\NotBlank(groups={AccompanyingPeriod::STEP_DRAFT})
* @var Collection<Comment>
*/
private Collection $comments;
@@ -269,6 +271,7 @@ class AccompanyingPeriod implements
* cascade={"persist", "refresh", "remove", "merge", "detach"})
* @Groups({"read", "docgen:read"})
* @ParticipationOverlap(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED})
* @var Collection<AccompanyingPeriodParticipation>
*/
private Collection $participations;
@@ -705,10 +708,11 @@ class AccompanyingPeriod implements
->comments
->filter(
static fn (Comment $c): bool => $c !== $pinnedComment
);
)
;
}
public function getCreatedAt(): ?DateTime
public function getCreatedAt(): DateTimeInterface
{
return $this->createdAt;
}
@@ -782,7 +786,7 @@ class AccompanyingPeriod implements
}
/**
* @return Collection|AccompanyingPeriodLocationHistory[]
* @return Collection<AccompanyingPeriodLocationHistory>
*/
public function getLocationHistories(): Collection
{
@@ -793,6 +797,7 @@ class AccompanyingPeriod implements
* Get where the location is.
*
* @Groups({"read"})
* @return 'person'|'address'|'none'
*/
public function getLocationStatus(): string
{
@@ -870,6 +875,7 @@ class AccompanyingPeriod implements
/**
* Get Participations Collection.
* @return Collection<AccompanyingPeriodParticipation>
*/
public function getParticipations(): Collection
{
@@ -1204,6 +1210,7 @@ class AccompanyingPeriod implements
$this->addressLocation = $addressLocation;
if (null !== $addressLocation) {
$this->setPersonLocation(null);
$locationHistory = new AccompanyingPeriodLocationHistory();
$locationHistory
->setStartDate(new DateTimeImmutable('now'))
@@ -1322,6 +1329,7 @@ class AccompanyingPeriod implements
$this->personLocation = $person;
if (null !== $person) {
$this->setAddressLocation(null);
$locationHistory = new AccompanyingPeriodLocationHistory();
$locationHistory
->setStartDate(new DateTimeImmutable('now'))

View File

@@ -59,6 +59,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
* )
* @Serializer\Groups({"read", "docgen:read"})
* @ORM\OrderBy({"startDate": "DESC", "id": "DESC"})
* @var Collection<AccompanyingPeriodWorkEvaluation>
*
* @internal /!\ the serialization for write evaluations is handled in `AccompanyingPeriodWorkDenormalizer`
*/
@@ -278,6 +279,9 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
return $this->accompanyingPeriod;
}
/**
* @return Collection<AccompanyingPeriodWorkEvaluation>
*/
public function getAccompanyingPeriodWorkEvaluations(): Collection
{
return $this->accompanyingPeriodWorkEvaluations;

View File

@@ -79,6 +79,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
* )
* @ORM\OrderBy({"createdAt": "DESC", "id": "DESC"})
* @Serializer\Groups({"read"})
* @var Collection<AccompanyingPeriodWorkEvaluationDocument>
*/
private Collection $documents;
@@ -204,7 +205,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
}
/**
* @return Collection
* @return Collection<AccompanyingPeriodWorkEvaluationDocument>
*/
public function getDocuments()
{

View File

@@ -45,7 +45,7 @@ class PersonCenterCurrent
private ?int $id = null;
/**
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="centerCurrent")
* @ORM\OneToOne(targetEntity=Person::class, inversedBy="centerCurrent")
*/
private Person $person;

View File

@@ -15,6 +15,7 @@ use DateInterval;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ReadableCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
@@ -295,6 +296,19 @@ class SocialAction
return 0 < $this->getChildren()->count();
}
public function isDesactivated(\DateTime $atDate): bool
{
if (null !== $this->desactivationDate && $this->desactivationDate < $atDate) {
return true;
}
if ($this->hasParent()) {
return $this->parent->isDesactivated($atDate);
}
return false;
}
public function hasParent(): bool
{
return $this->getParent() instanceof self;
@@ -401,4 +415,14 @@ class SocialAction
return $this;
}
public static function filterRemoveDeactivatedActions(ReadableCollection|array $actions, \DateTime $comparisonDate): ReadableCollection|array
{
$filterFn = fn (SocialAction $socialAction) => !$socialAction->isDesactivated($comparisonDate);
return match ($actions instanceof ReadableCollection) {
true => $actions->filter($filterFn),
false => array_filter($actions, $filterFn)
};
}
}

View File

@@ -253,7 +253,7 @@ class SocialIssue
}
/**
* @return Collection|SocialAction[] All the descendant social actions of all
* @return Collection<SocialAction> All the descendant social actions of all
* the descendants of the entity
*/
public function getRecursiveSocialActions(): Collection
@@ -272,7 +272,7 @@ class SocialIssue
}
/**
* @return Collection|SocialAction[]
* @return Collection<SocialAction>
*/
public function getSocialActions(): Collection
{

View File

@@ -57,6 +57,10 @@ class AdministrativeLocationAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -39,6 +39,10 @@ class ByActionNumberAggregator implements AggregatorInterface
{
// No form needed
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -52,6 +52,10 @@ class ClosingMotiveAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -48,6 +48,10 @@ class ConfidentialAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -57,6 +57,10 @@ class CreatorJobAggregator implements AggregatorInterface
{
// No form needed
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -84,6 +84,10 @@ final class DurationAggregator implements AggregatorInterface
'expanded' => true,
]);
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -48,6 +48,10 @@ class EmergencyAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -61,6 +61,10 @@ final class EvaluationAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -121,7 +121,6 @@ final class GeographicalUnitStatAggregator implements AggregatorInterface
->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',
@@ -133,6 +132,10 @@ final class GeographicalUnitStatAggregator implements AggregatorInterface
'expanded' => true,
]);
}
public function getFormDefaultData(): array
{
return ['date_calc' => new RollingDate(RollingDate::T_TODAY)];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -48,6 +48,10 @@ class IntensityAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -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\Export\Aggregator\AccompanyingCourseAggregators;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface
{
private const COLUMN_NAME = 'user_working_on_course_job_id';
public function __construct(
private UserJobRepositoryInterface $userJobRepository,
private TranslatableStringHelperInterface $translatableStringHelper,
) {
}
public function buildForm(FormBuilderInterface $builder)
{
// nothing to add here
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data): \Closure
{
return function (int|string|null $jobId) {
if (null === $jobId || '' === $jobId) {
return '';
}
if ('_header' === $jobId) {
return 'export.aggregator.course.by_job_working.job';
}
if (null === $job = $this->userJobRepository->find((int) $jobId)) {
return '';
}
return $this->translatableStringHelper->localize($job->getLabel());
};
}
public function getQueryKeys($data)
{
return [self::COLUMN_NAME];
}
public function getTitle()
{
return 'export.aggregator.course.by_job_working.title';
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('acpinfo', $qb->getAllAliases(), true)) {
$qb->leftJoin(
AccompanyingPeriodInfo::class,
'acpinfo',
Join::WITH,
'acp.id = IDENTITY(acpinfo.accompanyingPeriod)'
);
}
if (!in_array('acpinfo_user', $qb->getAllAliases(), true)) {
$qb->leftJoin('acpinfo.user', 'acpinfo_user');
}
$qb->addSelect('IDENTITY(acpinfo_user.userJob) AS ' . self::COLUMN_NAME);
$qb->addGroupBy(self::COLUMN_NAME);
}
public function applyOn()
{
return Declarations::ACP_TYPE;
}
}

View File

@@ -59,6 +59,10 @@ final class OriginAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -81,11 +81,14 @@ final class ReferrerAggregator implements AggregatorInterface
{
$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 getFormDefaultData(): array
{
return ['date_calc' => new RollingDate(RollingDate::T_TODAY)];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -88,11 +88,14 @@ class ReferrerScopeAggregator implements AggregatorInterface
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 getFormDefaultData(): array
{
return ['date_calc' => new RollingDate(RollingDate::T_TODAY)];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -69,6 +69,10 @@ final class RequestorAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -57,6 +57,10 @@ final class ScopeAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -0,0 +1,101 @@
<?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\ScopeRepositoryInterface;
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterface
{
private const COLUMN_NAME = 'user_working_on_course_scope_id';
public function __construct(
private ScopeRepositoryInterface $scopeRepository,
private TranslatableStringHelperInterface $translatableStringHelper,
) {
}
public function buildForm(FormBuilderInterface $builder)
{
// nothing to add here
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data): \Closure
{
return function (int|string|null $scopeId) {
if (null === $scopeId || '' === $scopeId) {
return '';
}
if ('_header' === $scopeId) {
return 'export.aggregator.course.by_scope_working.scope';
}
if (null === $scope = $this->scopeRepository->find((int) $scopeId)) {
return '';
}
return $this->translatableStringHelper->localize($scope->getName());
};
}
public function getQueryKeys($data)
{
return [self::COLUMN_NAME];
}
public function getTitle()
{
return 'export.aggregator.course.by_scope_working.title';
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('acpinfo', $qb->getAllAliases(), true)) {
$qb->leftJoin(
AccompanyingPeriodInfo::class,
'acpinfo',
Join::WITH,
'acp.id = IDENTITY(acpinfo.accompanyingPeriod)'
);
}
if (!in_array('acpinfo_user', $qb->getAllAliases(), true)) {
$qb->leftJoin('acpinfo.user', 'acpinfo_user');
}
$qb->addSelect('IDENTITY(acpinfo_user.mainScope) AS ' . self::COLUMN_NAME);
$qb->addGroupBy(self::COLUMN_NAME);
}
public function applyOn()
{
return Declarations::ACP_TYPE;
}
}

View File

@@ -58,6 +58,10 @@ final class SocialActionAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -58,6 +58,10 @@ final class SocialIssueAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -76,9 +76,11 @@ final class StepAggregator implements AggregatorInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('on_date', PickRollingDateType::class, [
'data' => new RollingDate(RollingDate::T_TODAY),
]);
$builder->add('on_date', PickRollingDateType::class, []);
}
public function getFormDefaultData(): array
{
return ['on_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function getLabels($key, array $values, $data)

View File

@@ -57,6 +57,10 @@ final class UserJobAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -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\Export\Aggregator\AccompanyingCourseAggregators;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\UserRepositoryInterface;
use Chill\MainBundle\Templating\Entity\UserRender;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class UserWorkingOnCourseAggregator implements AggregatorInterface
{
private const COLUMN_NAME = 'user_working_on_course_user_id';
public function __construct(
private UserRender $userRender,
private UserRepositoryInterface $userRepository,
) {
}
public function buildForm(FormBuilderInterface $builder)
{
// nothing to add here
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data): \Closure
{
return function (int|string|null $userId) {
if (null === $userId || '' === $userId) {
return '';
}
if ('_header' === $userId) {
return 'export.aggregator.course.by_user_working.user';
}
if (null === $user = $this->userRepository->find((int) $userId)) {
return '';
}
return $this->userRender->renderString($user, []);
};
}
public function getQueryKeys($data)
{
return [self::COLUMN_NAME];
}
public function getTitle()
{
return 'export.aggregator.course.by_user_working.title';
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('acpinfo', $qb->getAllAliases(), true)) {
$qb->leftJoin(
AccompanyingPeriodInfo::class,
'acpinfo',
Join::WITH,
'acp.id = IDENTITY(acpinfo.accompanyingPeriod)'
);
}
if (!in_array('acpinfo_user', $qb->getAllAliases(), true)) {
$qb->leftJoin('acpinfo.user', 'acpinfo_user');
}
$qb->addSelect('acpinfo_user.id AS ' . self::COLUMN_NAME);
$qb->addGroupBy('acpinfo_user.id');
}
public function applyOn()
{
return Declarations::ACP_TYPE;
}
}

View File

@@ -75,9 +75,12 @@ class ByEndDateAggregator implements AggregatorInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
]);
}
public function getFormDefaultData(): array
{
return ['frequency' => self::DEFAULT_CHOICE];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -75,9 +75,12 @@ class ByMaxDateAggregator implements AggregatorInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
]);
}
public function getFormDefaultData(): array
{
return ['frequency' => self::DEFAULT_CHOICE];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -75,9 +75,12 @@ class ByStartDateAggregator implements AggregatorInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
]);
}
public function getFormDefaultData(): array
{
return ['frequency' => self::DEFAULT_CHOICE];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -52,6 +52,10 @@ class EvaluationTypeAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -48,6 +48,10 @@ class HavingEndDateAggregator implements AggregatorInterface
{
// No form needed
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -72,9 +72,11 @@ class ChildrenNumberAggregator implements AggregatorInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('on_date', PickRollingDateType::class, [
'data' => new RollingDate(RollingDate::T_TODAY),
]);
$builder->add('on_date', PickRollingDateType::class, []);
}
public function getFormDefaultData(): array
{
return ['on_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function getLabels($key, array $values, $data)

View File

@@ -77,9 +77,11 @@ class CompositionAggregator implements AggregatorInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('on_date', PickRollingDateType::class, [
'data' => new RollingDate(RollingDate::T_TODAY),
]);
$builder->add('on_date', PickRollingDateType::class, []);
}
public function getFormDefaultData(): array
{
return ['on_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function getLabels($key, array $values, $data)

View File

@@ -13,20 +13,18 @@ namespace Chill\PersonBundle\Export\Aggregator\PersonAggregators;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use DateTime;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
final class AgeAggregator implements AggregatorInterface, ExportElementValidatedInterface
final readonly class AgeAggregator implements AggregatorInterface, ExportElementValidatedInterface
{
private TranslatorInterface $translator;
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
public function __construct(
private RollingDateConverterInterface $rollingDateConverter,
) {
}
public function addRole(): ?string
@@ -37,7 +35,7 @@ final class AgeAggregator implements AggregatorInterface, ExportElementValidated
public function alterQuery(QueryBuilder $qb, $data)
{
$qb->addSelect('DATE_DIFF(:date_age_calculation, person.birthdate)/365 as person_age');
$qb->setParameter('date_age_calculation', $data['date_age_calculation']);
$qb->setParameter('date_age_calculation', $this->rollingDateConverter->convert($data['date_age_calculation']));
$qb->addGroupBy('person_age');
}
@@ -48,14 +46,14 @@ final class AgeAggregator implements AggregatorInterface, ExportElementValidated
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('date_age_calculation', DateType::class, [
$builder->add('date_age_calculation', PickRollingDateType::class, [
'label' => 'Calculate age in relation to this date',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]);
}
public function getFormDefaultData(): array
{
return ['date_age_calculation' => new RollingDate(RollingDate::T_TODAY)];
}
public function getLabels($key, array $values, $data)
{
@@ -64,11 +62,7 @@ final class AgeAggregator implements AggregatorInterface, ExportElementValidated
return 'Age';
}
if (null === $value) {
return $this->translator->trans('without data');
}
return $value;
return $value ?? '';
};
}

View File

@@ -94,9 +94,12 @@ class ByHouseholdCompositionAggregator implements AggregatorInterface
{
$builder->add('date_calc', PickRollingDateType::class, [
'label' => 'export.aggregator.person.by_household_composition.Calc date',
'data' => new RollingDate(RollingDate::T_TODAY),
]);
}
public function getFormDefaultData(): array
{
return ['date_calc' => new RollingDate(RollingDate::T_TODAY)];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -0,0 +1,103 @@
<?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\Repository\CenterRepositoryInterface;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Export\Declarations;
use Closure;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class CenterAggregator implements AggregatorInterface
{
private const COLUMN_NAME = 'person_center_aggregator';
public function __construct(
private CenterRepositoryInterface $centerRepository,
private RollingDateConverterInterface $rollingDateConverter,
) {
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('at_date', PickRollingDateType::class, [
'label' => 'export.aggregator.person.by_center.at_date',
]);
}
public function getFormDefaultData(): array
{
return [
'at_date' => new RollingDate(RollingDate::T_TODAY)
];
}
public function getLabels($key, array $values, $data): Closure
{
return function (int|string|null $value) {
if (null === $value || '' === $value) {
return '';
}
if ('_header' === $value) {
return 'export.aggregator.person.by_center.center';
}
return (string) $this->centerRepository->find((int) $value)?->getName();
};
}
public function getQueryKeys($data)
{
return [self::COLUMN_NAME];
}
public function getTitle()
{
return 'export.aggregator.person.by_center.title';
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$alias = 'pers_center_agg';
$atDate = 'pers_center_agg_at_date';
$qb->leftJoin('person.centerHistory', $alias);
$qb
->andWhere(
$qb->expr()->lte($alias.'.startDate', ':'.$atDate),
)->andWhere(
$qb->expr()->orX(
$qb->expr()->isNull($alias.'.endDate'),
$qb->expr()->gt($alias.'.endDate', ':'.$atDate)
)
);
$qb->setParameter($atDate, $this->rollingDateConverter->convert($data['at_date']));
$qb->addSelect("IDENTITY({$alias}.center) AS " . self::COLUMN_NAME);
$qb->addGroupBy(self::COLUMN_NAME);
}
public function applyOn()
{
return Declarations::PERSON_TYPE;
}
}

View File

@@ -108,6 +108,10 @@ final class CountryOfBirthAggregator implements AggregatorInterface, ExportEleme
'multiple' => false,
]);
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -48,6 +48,10 @@ final class GenderAggregator implements AggregatorInterface
public function buildForm(FormBuilderInterface $builder)
{
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -93,7 +93,6 @@ class GeographicalUnitAggregator implements AggregatorInterface
->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',
@@ -105,6 +104,10 @@ class GeographicalUnitAggregator implements AggregatorInterface
'expanded' => true,
]);
}
public function getFormDefaultData(): array
{
return ['date_calc' => new RollingDate(RollingDate::T_TODAY)];
}
public static function getDefaultAlias(): string
{

View File

@@ -90,9 +90,12 @@ final class HouseholdPositionAggregator implements AggregatorInterface, ExportEl
{
$builder->add('date_position', PickRollingDateType::class, [
'label' => 'Household position in relation to this date',
'data' => new RollingDate(RollingDate::T_TODAY),
]);
}
public function getFormDefaultData(): array
{
return ['date_position' => new RollingDate(RollingDate::T_TODAY)];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -56,6 +56,11 @@ final class MaritalStatusAggregator implements AggregatorInterface
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{
return function ($value): string {

View File

@@ -103,6 +103,13 @@ final class NationalityAggregator implements AggregatorInterface, ExportElementV
]);
}
public function getFormDefaultData(): array
{
return [
'group_by_level' => 'country',
];
}
public function getLabels($key, array $values, $data)
{
$labels = [];

View File

@@ -75,6 +75,10 @@ final class ActionTypeAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -51,6 +51,10 @@ class CurrentActionAggregator implements AggregatorInterface
{
// No form needed
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -55,6 +55,10 @@ final class GoalAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -68,6 +68,10 @@ class GoalResultAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -57,6 +57,10 @@ final class JobAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -57,6 +57,10 @@ final class ReferrerAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -55,6 +55,10 @@ final class ResultAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -57,6 +57,10 @@ final class ScopeAggregator implements AggregatorInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function getLabels($key, array $values, $data)
{

View File

@@ -39,6 +39,10 @@ class CountAccompanyingCourse implements ExportInterface, GroupedExportInterface
{
// Nothing to add here
}
public function getFormDefaultData(): array
{
return [];
}
public function getAllowedFormattersTypes(): array
{
@@ -97,7 +101,6 @@ class CountAccompanyingCourse implements ExportInterface, GroupedExportInterface
->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

View File

@@ -38,6 +38,10 @@ class CountAccompanyingPeriodWork implements ExportInterface, GroupedExportInter
{
// No form necessary?
}
public function getFormDefaultData(): array
{
return [];
}
public function getAllowedFormattersTypes(): array
{
@@ -97,7 +101,6 @@ class CountAccompanyingPeriodWork implements ExportInterface, GroupedExportInter
->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

View File

@@ -37,6 +37,10 @@ class CountEvaluation implements ExportInterface, GroupedExportInterface
{
// TODO: Implement buildForm() method.
}
public function getFormDefaultData(): array
{
return [];
}
public function getAllowedFormattersTypes(): array
{
@@ -97,7 +101,6 @@ class CountEvaluation implements ExportInterface, GroupedExportInterface
->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

View File

@@ -46,11 +46,14 @@ class CountHousehold implements ExportInterface, GroupedExportInterface
{
$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 getFormDefaultData(): array
{
return ['calc_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function getAllowedFormattersTypes(): array
{

View File

@@ -38,6 +38,11 @@ class CountPerson implements ExportInterface, GroupedExportInterface
// No form necessary
}
public function getFormDefaultData(): array
{
return [];
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_TABULAR];
@@ -115,9 +120,9 @@ class CountPerson implements ExportInterface, GroupedExportInterface
public function supportsModifiers()
{
return [
Declarations::PERSON_TYPE,
Declarations::PERSON_IMPLIED_IN,
//Declarations::ACP_TYPE
'abcde',
//Declarations::PERSON_TYPE,
//Declarations::PERSON_IMPLIED_IN,
];
}
}

View File

@@ -39,6 +39,10 @@ class CountPersonWithAccompanyingCourse implements ExportInterface, GroupedExpor
{
// TODO: Implement buildForm() method.
}
public function getFormDefaultData(): array
{
return [];
}
public function getAllowedFormattersTypes(): array
{

View File

@@ -20,6 +20,7 @@ use Chill\MainBundle\Export\Helper\ExportAddressHelper;
use Chill\MainBundle\Export\Helper\UserHelper;
use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
@@ -144,6 +145,12 @@ class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
'required' => true,
]);
}
public function getFormDefaultData(): array
{
return [
'calc_date' => new RollingDate(RollingDate::T_TODAY)
];
}
public function getAllowedFormattersTypes()
{
@@ -409,15 +416,11 @@ class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
)
)
)
->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(
PersonHouseholdAddress::class,
'personAddress',
Join::WITH,
'locationHistory.personLocation = personAddress.person AND (personAddress.validFrom <= :calcDate AND (personAddress.validTo IS NULL OR personAddress.validTo > :calcDate))'
)
->leftJoin(Address::class, 'acp_address', Join::WITH, 'COALESCE(IDENTITY(locationHistory.addressLocation), IDENTITY(personAddress.address)) = acp_address.id');

View File

@@ -135,9 +135,12 @@ class ListAccompanyingPeriodWork implements ListInterface, GroupedExportInterfac
'label' => 'export.list.acpw.Date of calculation for associated elements',
'help' => 'export.list.acpw.help_description',
'required' => true,
'data' => new RollingDate(RollingDate::T_TODAY),
]);
}
public function getFormDefaultData(): array
{
return ['calc_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function getAllowedFormattersTypes()
{

View File

@@ -123,9 +123,12 @@ class ListEvaluation implements ListInterface, GroupedExportInterface
'label' => 'export.list.eval.Date of calculation for associated elements',
'help' => 'export.list.eval.help_description',
'required' => true,
'data' => new RollingDate(RollingDate::T_TODAY),
]);
}
public function getFormDefaultData(): array
{
return ['calc_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function getAllowedFormattersTypes()
{

View File

@@ -75,10 +75,13 @@ class ListHouseholdInPeriod implements ListInterface, GroupedExportInterface
->add('calc_date', PickRollingDateType::class, [
'label' => 'export.list.household.Date of calculation for associated elements',
'help' => 'export.list.household.help_description',
'data' => new RollingDate(RollingDate::T_TODAY),
'required' => true,
]);
}
public function getFormDefaultData(): array
{
return ['calc_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function getAllowedFormattersTypes()
{

View File

@@ -107,17 +107,27 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
}
},
])],
'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 getFormDefaultData(): array
{
$choices = array_combine(ListPersonHelper::FIELDS, ListPersonHelper::FIELDS);
foreach ($this->getCustomFields() as $cf) {
$choices[$this->translatableStringHelper->localize($cf->getName())]
=
$cf->getSlug();
}
return ['fields' => array_values($choices), 'address_date' => new DateTimeImmutable()];
}
public function getAllowedFormattersTypes()
{

View File

@@ -74,9 +74,12 @@ class ListPersonDuplicate implements DirectExportInterface, ExportElementValidat
{
$builder->add('precision', NumberType::class, [
'label' => 'Precision',
'data' => self::PRECISION_DEFAULT_VALUE,
]);
}
public function getFormDefaultData(): array
{
return ['precision' => self::PRECISION_DEFAULT_VALUE];
}
public function generate(array $acl, array $data = []): Response
{

View File

@@ -57,7 +57,6 @@ class ListPersonWithAccompanyingPeriod implements ExportElementValidatedInterfac
{
$choices = array_combine(ListPersonHelper::FIELDS, ListPersonHelper::FIELDS);
// Add a checkbox to select fields
$builder->add('fields', ChoiceType::class, [
'multiple' => true,
'expanded' => true,
@@ -80,17 +79,20 @@ class ListPersonWithAccompanyingPeriod implements ExportElementValidatedInterfac
}
},
])],
'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 getFormDefaultData(): array
{
$choices = array_combine(ListPersonHelper::FIELDS, ListPersonHelper::FIELDS);
return ['fields' => array_values($choices), 'address_date' => new DateTimeImmutable()];
}
public function getAllowedFormattersTypes()
{

View File

@@ -41,9 +41,12 @@ class StatAccompanyingCourseDuration implements ExportInterface, GroupedExportIn
{
$builder->add('closingdate', ChillDateType::class, [
'label' => 'Closingdate to apply',
'data' => new DateTime('now'),
]);
}
public function getFormDefaultData(): array
{
return ['closingdate' => new DateTime('now')];
}
public function getAllowedFormattersTypes(): array
{

View File

@@ -67,9 +67,11 @@ class ActiveOnDateFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('on_date', PickRollingDateType::class, [
'data' => new RollingDate(RollingDate::T_TODAY),
]);
->add('on_date', PickRollingDateType::class, []);
}
public function getFormDefaultData(): array
{
return ['on_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string'): array

View File

@@ -56,12 +56,12 @@ class ActiveOneDayBetweenDatesFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('date_from', PickRollingDateType::class, [
'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
])
->add('date_to', PickRollingDateType::class, [
'data' => new RollingDate(RollingDate::T_TODAY),
]);
->add('date_from', PickRollingDateType::class, [])
->add('date_to', PickRollingDateType::class, []);
}
public function getFormDefaultData(): array
{
return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string'): array

View File

@@ -53,6 +53,10 @@ class AdministrativeLocationFilter implements FilterInterface
'multiple' => true,
]);
}
public function getFormDefaultData(): array
{
return [];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -64,6 +64,10 @@ class ClosingMotiveFilter implements FilterInterface
'expanded' => true,
]);
}
public function getFormDefaultData(): array
{
return [];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -22,11 +22,11 @@ use Symfony\Contracts\Translation\TranslatorInterface;
class ConfidentialFilter implements FilterInterface
{
private const CHOICES = [
'is not confidential' => false,
'is confidential' => true,
'is not confidential' => 'false',
'is confidential' => 'true',
];
private const DEFAULT_CHOICE = false;
private const DEFAULT_CHOICE = 'false';
private TranslatorInterface $translator;
@@ -67,9 +67,12 @@ class ConfidentialFilter implements FilterInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
]);
}
public function getFormDefaultData(): array
{
return ['accepted_confidentials' => self::DEFAULT_CHOICE];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -50,6 +50,10 @@ class CreatorFilter implements FilterInterface
'label' => false,
]);
}
public function getFormDefaultData(): array
{
return [];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -69,6 +69,10 @@ class CreatorJobFilter implements FilterInterface
'label' => 'Job',
]);
}
public function getFormDefaultData(): array
{
return [];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -22,11 +22,11 @@ use Symfony\Contracts\Translation\TranslatorInterface;
class EmergencyFilter implements FilterInterface
{
private const CHOICES = [
'is emergency' => true,
'is not emergency' => false,
'is emergency' => 'true',
'is not emergency' => 'false',
];
private const DEFAULT_CHOICE = false;
private const DEFAULT_CHOICE = 'false';
private TranslatorInterface $translator;
@@ -67,9 +67,12 @@ class EmergencyFilter implements FilterInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
]);
}
public function getFormDefaultData(): array
{
return ['accepted_emergency' => self::DEFAULT_CHOICE];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -75,6 +75,10 @@ class EvaluationFilter implements FilterInterface
'attr' => ['class' => 'select2'],
]);
}
public function getFormDefaultData(): array
{
return [];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -100,7 +100,6 @@ class GeographicalUnitStatFilter implements FilterInterface
->add('date_calc', PickRollingDateType::class, [
'label' => 'Compute geographical location at date',
'required' => true,
'data' => new RollingDate(RollingDate::T_TODAY),
])
->add('units', ChoiceType::class, [
'label' => 'Geographical unit',
@@ -114,6 +113,10 @@ class GeographicalUnitStatFilter implements FilterInterface
'multiple' => true,
]);
}
public function getFormDefaultData(): array
{
return ['date_calc' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -38,6 +38,10 @@ class HasNoActionFilter implements FilterInterface
{
// no form
}
public function getFormDefaultData(): array
{
return [];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -65,9 +65,12 @@ class HasNoReferrerFilter implements FilterInterface
$builder
->add('calc_date', PickRollingDateType::class, [
'label' => 'Has no referrer on this date',
'data' => new RollingDate(RollingDate::T_TODAY),
]);
}
public function getFormDefaultData(): array
{
return ['calc_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -92,9 +92,12 @@ class HasTemporaryLocationFilter implements FilterInterface
])
->add('calc_date', PickRollingDateType::class, [
'label' => 'export.filter.course.having_temporarily.Calculation date',
'data' => new RollingDate(RollingDate::T_TODAY),
]);
}
public function getFormDefaultData(): array
{
return ['calc_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -38,13 +38,14 @@ final readonly class HavingAnAccompanyingPeriodInfoWithinDatesFilter implements
$builder
->add('start_date', PickRollingDateType::class, [
'label' => 'export.filter.course.having_info_within_interval.start_date',
'data' => new RollingDate(RollingDate::T_TODAY),
])
->add('end_date', PickRollingDateType::class, [
'label' => 'export.filter.course.having_info_within_interval.end_date',
'data' => new RollingDate(RollingDate::T_TODAY),
])
;
]);
}
public function getFormDefaultData(): array
{
return ['start_date' => new RollingDate(RollingDate::T_TODAY), 'end_date' => new RollingDate(RollingDate::T_TODAY)];
}
public function getTitle(): string

View File

@@ -67,9 +67,12 @@ class IntensityFilter implements FilterInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
]);
}
public function getFormDefaultData(): array
{
return ['accepted_intensities' => self::DEFAULT_CHOICE];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -0,0 +1,130 @@
<?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\Form\Type\PickUserDynamicType;
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Templating\Entity\UserRender;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
/**
* Filter course where a user with the given job is "working" on it
*
* Makes use of AccompanyingPeriodInfo
*/
readonly class JobWorkingOnCourseFilter implements FilterInterface
{
public function __construct(
private UserJobRepositoryInterface $userJobRepository,
private RollingDateConverterInterface $rollingDateConverter,
private TranslatableStringHelperInterface $translatableStringHelper,
) {
}
public function buildForm(FormBuilderInterface $builder): void
{
$jobs = $this->userJobRepository->findAllActive();
usort($jobs, fn (UserJob $a, UserJob $b) => $this->translatableStringHelper->localize($a->getLabel()) <=> $this->translatableStringHelper->localize($b->getLabel()));
$builder
->add('jobs', EntityType::class, [
'class' => UserJob::class,
'choices' => $jobs,
'choice_label' => fn (UserJob $userJob) => $this->translatableStringHelper->localize($userJob->getLabel()),
'multiple' => true,
'expanded' => true,
])
->add('start_date', PickRollingDateType::class, [
'label' => 'export.filter.course.by_job_working.Job working after'
])
->add('end_date', PickRollingDateType::class, [
'label' => 'export.filter.course.by_job_working.Job working before'
])
;
}
public function getFormDefaultData(): array
{
return [
'jobs' => [],
'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START),
'end_date' => new RollingDate(RollingDate::T_TODAY),
];
}
public function getTitle(): string
{
return 'export.filter.course.by_job_working.title';
}
public function describeAction($data, $format = 'string'): array
{
return [
'export.filter.course.by_job_working.Filtered by job working on course: only %jobs%, between %start_date% and %end_date%', [
'%jobs%' => implode(
', ',
array_map(
fn (UserJob $userJob) => $this->translatableStringHelper->localize($userJob->getLabel()),
$data['jobs']
)
),
'%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 addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data): void
{
$ai_alias = 'jobs_working_on_course_filter_acc_info';
$ai_user_alias = 'jobs_working_on_course_filter_user';
$ai_jobs = 'jobs_working_on_course_filter_jobs';
$start = 'acp_jobs_work_on_start';
$end = 'acp_jobs_work_on_end';
$qb
->andWhere(
$qb->expr()->exists(
"SELECT 1 FROM " . AccompanyingPeriod\AccompanyingPeriodInfo::class . " {$ai_alias} JOIN {$ai_alias}.user {$ai_user_alias} " .
"WHERE IDENTITY({$ai_alias}.accompanyingPeriod) = acp.id
AND {$ai_user_alias}.userJob IN (:{$ai_jobs})
AND {$ai_alias}.infoDate >= :{$start} and {$ai_alias}.infoDate < :{$end}
"
)
)
->setParameter($ai_jobs, $data['jobs'])
->setParameter($start, $this->rollingDateConverter->convert($data['start_date']))
->setParameter($end, $this->rollingDateConverter->convert($data['end_date']))
;
}
public function applyOn(): string
{
return Declarations::ACP_TYPE;
}
}

View File

@@ -38,7 +38,7 @@ class OpenBetweenDatesFilter implements FilterInterface
{
$clause = $qb->expr()->andX(
$qb->expr()->gte('acp.openingDate', ':datefrom'),
$qb->expr()->lte('acp.openingDate', ':dateto')
$qb->expr()->lt('acp.openingDate', ':dateto')
);
$qb->andWhere($clause);
@@ -54,12 +54,12 @@ class OpenBetweenDatesFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('date_from', PickRollingDateType::class, [
'data' => new RollingDate(RollingDate::T_MONTH_PREVIOUS_START),
])
->add('date_to', PickRollingDateType::class, [
'data' => new RollingDate(RollingDate::T_TODAY),
]);
->add('date_from', PickRollingDateType::class, [])
->add('date_to', PickRollingDateType::class, []);
}
public function getFormDefaultData(): array
{
return ['date_from' => new RollingDate(RollingDate::T_MONTH_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string'): array

View File

@@ -64,6 +64,10 @@ class OriginFilter implements FilterInterface
'expanded' => true,
]);
}
public function getFormDefaultData(): array
{
return [];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -77,11 +77,14 @@ class ReferrerFilter implements FilterInterface
'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 getFormDefaultData(): array
{
return ['date_calc' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -126,9 +126,12 @@ final class RequestorFilter implements FilterInterface
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
]);
}
public function getFormDefaultData(): array
{
return ['accepted_choices' => self::DEFAULT_CHOICE];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -0,0 +1,132 @@
<?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\Entity\UserJob;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Templating\Entity\UserRender;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
/**
* Filter course where a user with the given scope is "working" on it
*
* Makes use of AccompanyingPeriodInfo
*/
readonly class ScopeWorkingOnCourseFilter implements FilterInterface
{
public function __construct(
private ScopeRepositoryInterface $scopeRepository,
private RollingDateConverterInterface $rollingDateConverter,
private TranslatableStringHelperInterface $translatableStringHelper,
) {
}
public function buildForm(FormBuilderInterface $builder): void
{
$scopes = $this->scopeRepository->findAllActive();
usort($scopes, fn (Scope $a, Scope $b) => $this->translatableStringHelper->localize($a->getName()) <=> $this->translatableStringHelper->localize($b->getName()));
$builder
->add('scopes', EntityType::class, [
'class' => Scope::class,
'choices' => $scopes,
'choice_label' => fn (Scope $scope) => $this->translatableStringHelper->localize($scope->getName()),
'multiple' => true,
'expanded' => true,
])
->add('start_date', PickRollingDateType::class, [
'label' => 'export.filter.course.by_scope_working.Scope working after'
])
->add('end_date', PickRollingDateType::class, [
'label' => 'export.filter.course.by_scope_working.Scope working before'
])
;
}
public function getFormDefaultData(): array
{
return [
'scopes' => [],
'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START),
'end_date' => new RollingDate(RollingDate::T_TODAY),
];
}
public function getTitle(): string
{
return 'export.filter.course.by_scope_working.title';
}
public function describeAction($data, $format = 'string'): array
{
return [
'export.filter.course.by_scope_working.Filtered by scope working on course: only %scopes%, between %start_date% and %end_date%', [
'%scopes%' => implode(
', ',
array_map(
fn (Scope $scope) => $this->translatableStringHelper->localize($scope->getName()),
$data['scopes']
)
),
'%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 addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data): void
{
$ai_alias = 'scopes_working_on_course_filter_acc_info';
$ai_user_alias = 'scopes_working_on_course_filter_user';
$ai_scopes = 'scopes_working_on_course_filter_scopes';
$start = 'acp_scopes_work_on_start';
$end = 'acp_scopes_work_on_end';
$qb
->andWhere(
$qb->expr()->exists(
"SELECT 1 FROM " . AccompanyingPeriod\AccompanyingPeriodInfo::class . " {$ai_alias} JOIN {$ai_alias}.user {$ai_user_alias} " .
"WHERE IDENTITY({$ai_alias}.accompanyingPeriod) = acp.id
AND {$ai_user_alias}.mainScope IN (:{$ai_scopes})
AND {$ai_alias}.infoDate >= :{$start} and {$ai_alias}.infoDate < :{$end}
"
)
)
->setParameter($ai_scopes, $data['scopes'])
->setParameter($start, $this->rollingDateConverter->convert($data['start_date']))
->setParameter($end, $this->rollingDateConverter->convert($data['end_date']))
;
}
public function applyOn(): string
{
return Declarations::ACP_TYPE;
}
}

View File

@@ -70,6 +70,10 @@ class SocialActionFilter implements FilterInterface
'multiple' => true,
]);
}
public function getFormDefaultData(): array
{
return [];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -69,6 +69,10 @@ class SocialIssueFilter implements FilterInterface
'multiple' => true,
]);
}
public function getFormDefaultData(): array
{
return [];
}
public function describeAction($data, $format = 'string'): array
{

View File

@@ -0,0 +1,125 @@
<?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;
use Chill\PersonBundle\Export\Declarations;
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 StepFilterBetweenDates implements FilterInterface
{
private const DEFAULT_CHOICE = [
AccompanyingPeriod::STEP_CONFIRMED,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
];
private const STEPS = [
'course.draft' => AccompanyingPeriod::STEP_DRAFT,
'course.confirmed' => AccompanyingPeriod::STEP_CONFIRMED,
'course.closed' => AccompanyingPeriod::STEP_CLOSED,
'course.inactive_short' => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
'course.inactive_long' => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
];
private RollingDateConverterInterface $rollingDateConverter;
private TranslatorInterface $translator;
public function __construct(
RollingDateConverterInterface $rollingDateConverter,
TranslatorInterface $translator
) {
$this->rollingDateConverter = $rollingDateConverter;
$this->translator = $translator;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$alias = 'acp_filter_by_step_between_dat_alias';
$steps = 'acp_filter_by_step_between_dat_steps';
$from = 'acp_filter_by_step_between_dat_from';
$to = 'acp_filter_by_step_between_dat_to';
$qb
->andWhere(
$qb->expr()->exists(
"SELECT 1 FROM " . AccompanyingPeriod\AccompanyingPeriodStepHistory::class . " {$alias} " .
"WHERE {$alias}.step IN (:{$steps}) AND OVERLAPSI ({$alias}.startDate, {$alias}.endDate),(:{$from}, :{$to}) = TRUE " .
"AND {$alias}.period = acp"
)
)
->setParameter($from, $this->rollingDateConverter->convert($data['date_from']))
->setParameter($to, $this->rollingDateConverter->convert($data['date_to']))
->setParameter($steps, $data['accepted_steps_multi']);
}
public function applyOn()
{
return Declarations::ACP_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('accepted_steps_multi', ChoiceType::class, [
'label' => 'export.filter.course.by_step.steps',
'choices' => self::STEPS,
'multiple' => true,
'expanded' => true,
])
->add('date_from', PickRollingDateType::class, [
'label' => 'export.filter.course.by_step.date_from',
])
->add('date_to', PickRollingDateType::class, [
'label' => 'export.filter.course.by_step.date_to',
]);
}
public function getFormDefaultData(): array
{
return [
'accepted_steps_multi' => self::DEFAULT_CHOICE,
'date_from' => new RollingDate(RollingDate::T_YEAR_CURRENT_START),
'date_to' => new RollingDate(RollingDate::T_TODAY),
];
}
public function describeAction($data, $format = 'string')
{
$steps = array_map(fn (string $step) => $this->translator->trans(array_flip(self::STEPS)[$step]), $data['accepted_steps_multi']);
return ['export.filter.course.by_step.Filtered by steps: only %step% and between %date_from% and %date_to%', [
'%step%' => implode(', ', $steps),
'%date_from%' => $this->rollingDateConverter->convert($data['date_from'])->format('d-m-Y'),
'%date_to%' => $this->rollingDateConverter->convert($data['date_to'])->format('d-m-Y'),
]];
}
public function getTitle()
{
return 'export.filter.course.by_step.Filter by step between dates';
}
}

View File

@@ -23,11 +23,15 @@ use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use function in_array;
class StepFilter implements FilterInterface
class StepFilterOnDate implements FilterInterface
{
private const A = 'acp_filter_bystep_stephistories';
private const DEFAULT_CHOICE = AccompanyingPeriod::STEP_CONFIRMED;
private const DEFAULT_CHOICE = [
AccompanyingPeriod::STEP_CONFIRMED,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
];
private const P = 'acp_step_filter_date';
@@ -79,7 +83,7 @@ class StepFilter implements FilterInterface
$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']);
->setParameter('acp_filter_by_step_steps', $data['accepted_steps_multi']);
}
public function applyOn()
@@ -90,30 +94,36 @@ class StepFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('accepted_steps', ChoiceType::class, [
->add('accepted_steps_multi', ChoiceType::class, [
'label' => 'export.filter.course.by_step.steps',
'choices' => self::STEPS,
'multiple' => false,
'multiple' => true,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
])
->add('calc_date', PickRollingDateType::class, [
'label' => 'export.filter.course.by_step.date_calc',
'data' => new RollingDate(RollingDate::T_TODAY),
]);
}
public function getFormDefaultData(): array
{
return [
'accepted_steps_multi' => self::DEFAULT_CHOICE,
'calc_date' => new RollingDate(RollingDate::T_TODAY),
];
}
public function describeAction($data, $format = 'string')
{
$step = array_flip(self::STEPS)[$data['accepted_steps']];
$steps = array_map(fn (string $step) => $this->translator->trans(array_flip(self::STEPS)[$step]), $data['accepted_steps_multi']);
return ['Filtered by steps: only %step%', [
'%step%' => $this->translator->trans($step),
'%step%' => implode(', ', $steps),
]];
}
public function getTitle()
{
return 'Filter by step';
return 'export.filter.course.by_step.Filter by step';
}
}

View File

@@ -96,11 +96,14 @@ class UserJobFilter implements FilterInterface
'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 getFormDefaultData(): array
{
return ['date_calc' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string')
{

View File

@@ -100,11 +100,14 @@ class UserScopeFilter implements FilterInterface
'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 getFormDefaultData(): array
{
return ['date_calc' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string')
{

Some files were not shown because too many files have changed in this diff Show More