mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch '244-record-closing-motive-on-acc-period-closing' into 'master'
[Export] Ajout de la comptabilisation du nombre de changements de statuts du parcours Closes #244 See merge request Chill-Projet/chill-bundles!650
This commit is contained in:
commit
8be9fb6553
5
.changes/unreleased/Feature-20240129-133319.yaml
Normal file
5
.changes/unreleased/Feature-20240129-133319.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
kind: Feature
|
||||||
|
body: 'Add capability to generate export about change of steps of accompanying period, and generate exports for this'
|
||||||
|
time: 2024-01-29T13:33:19.190365565+01:00
|
||||||
|
custom:
|
||||||
|
Issue: "244"
|
@ -5,72 +5,74 @@ Add condition with distinct alias on each export join clauses (Indicators + Filt
|
|||||||
|
|
||||||
These are alias conventions :
|
These are alias conventions :
|
||||||
|
|
||||||
| Entity | Join | Attribute | Alias |
|
| Entity | Join | Attribute | Alias |
|
||||||
|:----------------------------------------|:----------------------------------------|:-------------------------------------------|:---------------------------------------|
|
|:----------------------------------------|:----------------------------------------|:-------------------------------------------|:-------------------------------------------|
|
||||||
| AccompanyingPeriod::class | | | acp |
|
| AccompanyingPeriodStepHistory::class | | | acpstephistory (contexte ACP_STEP_HISTORY) |
|
||||||
| | AccompanyingPeriodWork::class | acp.works | acpw |
|
| | AccompanyingPeriod::class | acpstephistory.period | acp |
|
||||||
| | AccompanyingPeriodParticipation::class | acp.participations | acppart |
|
| AccompanyingPeriod::class | | | acp |
|
||||||
| | Location::class | acp.administrativeLocation | acploc |
|
| | AccompanyingPeriodWork::class | acp.works | acpw |
|
||||||
| | ClosingMotive::class | acp.closingMotive | acpmotive |
|
| | AccompanyingPeriodParticipation::class | acp.participations | acppart |
|
||||||
| | UserJob::class | acp.job | acpjob |
|
| | Location::class | acp.administrativeLocation | acploc |
|
||||||
| | Origin::class | acp.origin | acporigin |
|
| | ClosingMotive::class | acp.closingMotive | acpmotive |
|
||||||
| | Scope::class | acp.scopes | acpscope |
|
| | UserJob::class | acp.job | acpjob |
|
||||||
| | SocialIssue::class | acp.socialIssues | acpsocialissue |
|
| | Origin::class | acp.origin | acporigin |
|
||||||
| | User::class | acp.user | acpuser |
|
| | Scope::class | acp.scopes | acpscope |
|
||||||
| | AccompanyingPeriopStepHistory::class | acp.stepHistories | acpstephistories |
|
| | SocialIssue::class | acp.socialIssues | acpsocialissue |
|
||||||
| | AccompanyingPeriodInfo::class | not existing (using custom WITH clause) | acpinfo |
|
| | User::class | acp.user | acpuser |
|
||||||
| AccompanyingPeriodWork::class | | | acpw |
|
| | AccompanyingPeriopStepHistory::class | acp.stepHistories | acpstephistories |
|
||||||
| | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations | workeval |
|
| | AccompanyingPeriodInfo::class | not existing (using custom WITH clause) | acpinfo |
|
||||||
| | SocialAction::class | acpw.socialAction | acpwsocialaction |
|
| AccompanyingPeriodWork::class | | | acpw |
|
||||||
| | Goal::class | acpw.goals | goal |
|
| | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations | workeval |
|
||||||
| | Result::class | acpw.results | result |
|
| | SocialAction::class | acpw.socialAction | acpwsocialaction |
|
||||||
| AccompanyingPeriodParticipation::class | | | acppart |
|
| | Goal::class | acpw.goals | goal |
|
||||||
| | Person::class | acppart.person | partperson |
|
| | Result::class | acpw.results | result |
|
||||||
| AccompanyingPeriodWorkEvaluation::class | | | workeval |
|
| AccompanyingPeriodParticipation::class | | | acppart |
|
||||||
| | Evaluation::class | workeval.evaluation | eval |
|
| | Person::class | acppart.person | partperson |
|
||||||
| AccompanyingPeriodInfo::class | | | acpinfo |
|
| AccompanyingPeriodWorkEvaluation::class | | | workeval |
|
||||||
| | User::class | acpinfo.user | acpinfo_user |
|
| | Evaluation::class | workeval.evaluation | eval |
|
||||||
| Goal::class | | | goal |
|
| AccompanyingPeriodInfo::class | | | acpinfo |
|
||||||
| | Result::class | goal.results | goalresult |
|
| | User::class | acpinfo.user | acpinfo_user |
|
||||||
| Person::class | | | person |
|
| Goal::class | | | goal |
|
||||||
| | Center::class | person.center | center |
|
| | Result::class | goal.results | goalresult |
|
||||||
| | HouseholdMember::class | partperson.householdParticipations | householdmember |
|
| Person::class | | | person |
|
||||||
| | MaritalStatus::class | person.maritalStatus | personmarital |
|
| | Center::class | person.center | center |
|
||||||
| | VendeePerson::class | | vp |
|
| | HouseholdMember::class | partperson.householdParticipations | householdmember |
|
||||||
| | VendeePersonMineur::class | | vpm |
|
| | MaritalStatus::class | person.maritalStatus | personmarital |
|
||||||
| | CurrentPersonAddress::class | person.currentPersonAddress | currentPersonAddress (on a given date) |
|
| | VendeePerson::class | | vp |
|
||||||
| ResidentialAddress::class | | | resaddr |
|
| | VendeePersonMineur::class | | vpm |
|
||||||
| | ThirdParty::class | resaddr.hostThirdParty | tparty |
|
| | CurrentPersonAddress::class | person.currentPersonAddress | currentPersonAddress (on a given date) |
|
||||||
| ThirdParty::class | | | tparty |
|
| ResidentialAddress::class | | | resaddr |
|
||||||
| | ThirdPartyCategory::class | tparty.categories | tpartycat |
|
| | ThirdParty::class | resaddr.hostThirdParty | tparty |
|
||||||
| HouseholdMember::class | | | householdmember |
|
| ThirdParty::class | | | tparty |
|
||||||
| | Household::class | householdmember.household | household |
|
| | ThirdPartyCategory::class | tparty.categories | tpartycat |
|
||||||
| | Person::class | householdmember.person | memberperson |
|
| HouseholdMember::class | | | householdmember |
|
||||||
| | | memberperson.center | membercenter |
|
| | Household::class | householdmember.household | household |
|
||||||
| Household::class | | | household |
|
| | Person::class | householdmember.person | memberperson |
|
||||||
| | HouseholdComposition::class | household.compositions | composition |
|
| | | memberperson.center | membercenter |
|
||||||
| Activity::class | | | activity |
|
| Household::class | | | household |
|
||||||
| | Person::class | activity.person | actperson |
|
| | HouseholdComposition::class | household.compositions | composition |
|
||||||
| | AccompanyingPeriod::class | activity.accompanyingPeriod | acp |
|
| Activity::class | | | activity |
|
||||||
| | Person::class | activity\_person\_having\_activity.person | person\_person\_having\_activity |
|
| | Person::class | activity.person | actperson |
|
||||||
| | ActivityReason::class | activity\_person\_having\_activity.reasons | reasons\_person\_having\_activity |
|
| | AccompanyingPeriod::class | activity.accompanyingPeriod | acp |
|
||||||
| | ActivityType::class | activity.activityType | acttype |
|
| | Person::class | activity\_person\_having\_activity.person | person\_person\_having\_activity |
|
||||||
| | Location::class | activity.location | actloc |
|
| | ActivityReason::class | activity\_person\_having\_activity.reasons | reasons\_person\_having\_activity |
|
||||||
| | SocialAction::class | activity.socialActions | actsocialaction |
|
| | ActivityType::class | activity.activityType | acttype |
|
||||||
| | SocialIssue::class | activity.socialIssues | actsocialssue |
|
| | Location::class | activity.location | actloc |
|
||||||
| | ThirdParty::class | activity.thirdParties | acttparty |
|
| | SocialAction::class | activity.socialActions | actsocialaction |
|
||||||
| | User::class | activity.user | actuser |
|
| | SocialIssue::class | activity.socialIssues | actsocialssue |
|
||||||
| | User::class | activity.users | actusers |
|
| | ThirdParty::class | activity.thirdParties | acttparty |
|
||||||
| | ActivityReason::class | activity.reasons | actreasons |
|
| | User::class | activity.user | actuser |
|
||||||
| | Center::class | actperson.center | actcenter |
|
| | User::class | activity.users | actusers |
|
||||||
| | Person::class | activity.createdBy | actcreator |
|
| | ActivityReason::class | activity.reasons | actreasons |
|
||||||
| ActivityReason::class | | | actreasons |
|
| | Center::class | actperson.center | actcenter |
|
||||||
| | ActivityReasonCategory::class | actreason.category | actreasoncat |
|
| | Person::class | activity.createdBy | actcreator |
|
||||||
| Calendar::class | | | cal |
|
| ActivityReason::class | | | actreasons |
|
||||||
| | CancelReason::class | cal.cancelReason | calcancel |
|
| | ActivityReasonCategory::class | actreason.category | actreasoncat |
|
||||||
| | Location::class | cal.location | calloc |
|
| Calendar::class | | | cal |
|
||||||
| | User::class | cal.user | caluser |
|
| | CancelReason::class | cal.cancelReason | calcancel |
|
||||||
| VendeePerson::class | | | vp |
|
| | Location::class | cal.location | calloc |
|
||||||
| | SituationProfessionelle::class | vp.situationProfessionelle | vpprof |
|
| | User::class | cal.user | caluser |
|
||||||
| | StatutLogement::class | vp.statutLogement | vplog |
|
| VendeePerson::class | | | vp |
|
||||||
| | TempsDeTravail::class | vp.tempsDeTravail | vptt |
|
| | SituationProfessionelle::class | vp.situationProfessionelle | vpprof |
|
||||||
|
| | StatutLogement::class | vp.statutLogement | vplog |
|
||||||
|
| | TempsDeTravail::class | vp.tempsDeTravail | vptt |
|
||||||
|
@ -62,7 +62,7 @@ class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle\Contr
|
|||||||
$workflow = $this->registry->get($accompanyingCourse);
|
$workflow = $this->registry->get($accompanyingCourse);
|
||||||
|
|
||||||
if ($workflow->can($accompanyingCourse, 'close')) {
|
if ($workflow->can($accompanyingCourse, 'close')) {
|
||||||
$workflow->apply($accompanyingCourse, 'close');
|
$workflow->apply($accompanyingCourse, 'close', ['closing_motive' => $form['closingMotive']->getData()]);
|
||||||
|
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
|
||||||
|
@ -98,6 +98,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
|||||||
$loader->load('services/exports_accompanying_course.yaml');
|
$loader->load('services/exports_accompanying_course.yaml');
|
||||||
$loader->load('services/exports_social_actions.yaml');
|
$loader->load('services/exports_social_actions.yaml');
|
||||||
$loader->load('services/exports_evaluation.yaml');
|
$loader->load('services/exports_evaluation.yaml');
|
||||||
|
$loader->load('services/exports_accompanying_period_step_history.yaml');
|
||||||
}
|
}
|
||||||
|
|
||||||
$loader->load('services/exports_household.yaml');
|
$loader->load('services/exports_household.yaml');
|
||||||
|
@ -1449,7 +1449,7 @@ class AccompanyingPeriod implements
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setStep(string $step): self
|
public function setStep(string $step, array $context = []): self
|
||||||
{
|
{
|
||||||
$previous = $this->step;
|
$previous = $this->step;
|
||||||
|
|
||||||
@ -1464,7 +1464,7 @@ class AccompanyingPeriod implements
|
|||||||
$history = new AccompanyingPeriodStepHistory();
|
$history = new AccompanyingPeriodStepHistory();
|
||||||
$history->setStep($this->step)->setStartDate(new \DateTimeImmutable('now'));
|
$history->setStep($this->step)->setStartDate(new \DateTimeImmutable('now'));
|
||||||
|
|
||||||
$this->addStepHistory($history);
|
$this->addStepHistory($history, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -1507,11 +1507,14 @@ class AccompanyingPeriod implements
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function addStepHistory(AccompanyingPeriodStepHistory $stepHistory): self
|
private function addStepHistory(AccompanyingPeriodStepHistory $stepHistory, array $context = []): self
|
||||||
{
|
{
|
||||||
if (!$this->stepHistories->contains($stepHistory)) {
|
if (!$this->stepHistories->contains($stepHistory)) {
|
||||||
$this->stepHistories[] = $stepHistory;
|
$this->stepHistories[] = $stepHistory;
|
||||||
$stepHistory->setPeriod($this);
|
$stepHistory->setPeriod($this);
|
||||||
|
if (($context['closing_motive'] ?? null) instanceof ClosingMotive) {
|
||||||
|
$stepHistory->setClosingMotive($context['closing_motive']);
|
||||||
|
}
|
||||||
$this->ensureStepContinuity();
|
$this->ensureStepContinuity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,13 @@ class AccompanyingPeriodStepHistory implements TrackCreationInterface, TrackUpda
|
|||||||
*/
|
*/
|
||||||
private string $step;
|
private string $step;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity=ClosingMotive::class)
|
||||||
|
*
|
||||||
|
* @ORM\JoinColumn(nullable=true)
|
||||||
|
*/
|
||||||
|
private ?ClosingMotive $closingMotive = null;
|
||||||
|
|
||||||
public function getEndDate(): ?\DateTimeImmutable
|
public function getEndDate(): ?\DateTimeImmutable
|
||||||
{
|
{
|
||||||
return $this->endDate;
|
return $this->endDate;
|
||||||
@ -114,4 +121,16 @@ class AccompanyingPeriodStepHistory implements TrackCreationInterface, TrackUpda
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getClosingMotive(): ?ClosingMotive
|
||||||
|
{
|
||||||
|
return $this->closingMotive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setClosingMotive(?ClosingMotive $closingMotive): self
|
||||||
|
{
|
||||||
|
$this->closingMotive = $closingMotive;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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\AccompanyingPeriodStepHistoryAggregators;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Export\AggregatorInterface;
|
||||||
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
|
use Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepositoryInterface;
|
||||||
|
use Chill\PersonBundle\Templating\Entity\ClosingMotiveRender;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
final readonly class ByClosingMotiveAggregator implements AggregatorInterface
|
||||||
|
{
|
||||||
|
private const KEY = 'acpstephistory_by_closing_motive_agg';
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private ClosingMotiveRepositoryInterface $closingMotiveRepository,
|
||||||
|
private ClosingMotiveRender $closingMotiveRender,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
|
{
|
||||||
|
// nothing to add here
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormDefaultData(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLabels($key, array $values, mixed $data)
|
||||||
|
{
|
||||||
|
return function (int|string|null $value): string {
|
||||||
|
if ('_header' === $value) {
|
||||||
|
return 'export.aggregator.step_history.by_closing_motive.header';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $value || '' === $value || null === $closingMotive = $this->closingMotiveRepository->find((int) $value)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->closingMotiveRender->renderString($closingMotive, []);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryKeys($data)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
self::KEY,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return 'export.aggregator.step_history.by_closing_motive.title';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addRole(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
|
{
|
||||||
|
$qb
|
||||||
|
->addSelect('IDENTITY(acpstephistory.closingMotive) AS '.self::KEY)
|
||||||
|
->addGroupBy(self::KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyOn()
|
||||||
|
{
|
||||||
|
return Declarations::ACP_STEP_HISTORY;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
<?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\AccompanyingPeriodStepHistoryAggregators;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Export\AggregatorInterface;
|
||||||
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
|
use Chill\PersonBundle\Export\Enum\DateGroupingChoiceEnum;
|
||||||
|
use Chill\PersonBundle\Tests\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators\ByDateAggregatorTest;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ByDateAggregatorTest
|
||||||
|
*/
|
||||||
|
final readonly class ByDateAggregator implements AggregatorInterface
|
||||||
|
{
|
||||||
|
private const KEY = 'acpstephistory_by_date_agg';
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
|
{
|
||||||
|
$builder->add('frequency', ChoiceType::class, [
|
||||||
|
'choices' => array_combine(
|
||||||
|
array_map(fn (DateGroupingChoiceEnum $c) => 'export.enum.frequency.'.$c->value, DateGroupingChoiceEnum::cases()),
|
||||||
|
array_map(fn (DateGroupingChoiceEnum $c) => $c->value, DateGroupingChoiceEnum::cases()),
|
||||||
|
),
|
||||||
|
'label' => 'export.aggregator.course.by_opening_date.frequency',
|
||||||
|
'multiple' => false,
|
||||||
|
'expanded' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormDefaultData(): array
|
||||||
|
{
|
||||||
|
return ['frequency' => DateGroupingChoiceEnum::YEAR->value];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLabels($key, array $values, mixed $data)
|
||||||
|
{
|
||||||
|
return function (?string $value): string {
|
||||||
|
if ('_header' === $value) {
|
||||||
|
return 'export.aggregator.step_history.by_date.header';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $value || '' === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryKeys($data)
|
||||||
|
{
|
||||||
|
return [self::KEY];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return 'export.aggregator.step_history.by_date.title';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addRole(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
|
{
|
||||||
|
$p = self::KEY;
|
||||||
|
|
||||||
|
$qb->addSelect(sprintf("TO_CHAR(acpstephistory.startDate, '%s') AS {$p}", $data['frequency']));
|
||||||
|
$qb->addGroupBy($p);
|
||||||
|
$qb->addOrderBy($p, 'DESC');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyOn()
|
||||||
|
{
|
||||||
|
return Declarations::ACP_STEP_HISTORY;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
<?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\AccompanyingPeriodStepHistoryAggregators;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Export\AggregatorInterface;
|
||||||
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
|
use Chill\PersonBundle\Tests\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators\ByStepAggregatorTest;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ByStepAggregatorTest
|
||||||
|
*/
|
||||||
|
final readonly class ByStepAggregator implements AggregatorInterface
|
||||||
|
{
|
||||||
|
private const KEY = 'acpstephistory_step_agg';
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private TranslatorInterface $translator
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
|
{
|
||||||
|
// nothing in this form
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormDefaultData(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLabels($key, array $values, mixed $data)
|
||||||
|
{
|
||||||
|
return function (?string $step): string {
|
||||||
|
if ('_header' === $step) {
|
||||||
|
return 'export.aggregator.step_history.by_step.header';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $step || '' === $step) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->translator->trans('accompanying_period.'.$step);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryKeys($data)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
self::KEY,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return 'export.aggregator.step_history.by_step.title';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addRole(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
|
{
|
||||||
|
$qb
|
||||||
|
->addSelect('acpstephistory.step AS '.self::KEY)
|
||||||
|
->addGroupBy(self::KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyOn()
|
||||||
|
{
|
||||||
|
return Declarations::ACP_STEP_HISTORY;
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,8 @@ abstract class Declarations
|
|||||||
{
|
{
|
||||||
final public const ACP_TYPE = 'accompanying_period';
|
final public const ACP_TYPE = 'accompanying_period';
|
||||||
|
|
||||||
|
final public const ACP_STEP_HISTORY = 'accompanying_period_step_history';
|
||||||
|
|
||||||
final public const EVAL_TYPE = 'evaluation';
|
final public const EVAL_TYPE = 'evaluation';
|
||||||
|
|
||||||
final public const HOUSEHOLD_TYPE = 'household';
|
final public const HOUSEHOLD_TYPE = 'household';
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
<?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\AccompanyingCourseExportHelper;
|
||||||
|
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 Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
class CountAccompanyingCourseStepHistory implements ExportInterface, GroupedExportInterface
|
||||||
|
{
|
||||||
|
protected EntityRepository $repository;
|
||||||
|
private readonly bool $filterStatsByCenters;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private readonly EntityManagerInterface $em,
|
||||||
|
ParameterBagInterface $parameterBag,
|
||||||
|
) {
|
||||||
|
$this->repository = $em->getRepository(AccompanyingPeriod::class);
|
||||||
|
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder): void
|
||||||
|
{
|
||||||
|
// Nothing to add here
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormDefaultData(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAllowedFormattersTypes(): array
|
||||||
|
{
|
||||||
|
return [FormatterInterface::TYPE_TABULAR];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'export.export.acp_closing.description';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroup(): string
|
||||||
|
{
|
||||||
|
return 'Exports of accompanying courses';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLabels($key, array $values, $data)
|
||||||
|
{
|
||||||
|
if ('export_result' !== $key) {
|
||||||
|
throw new \LogicException("the key {$key} is not used by this export");
|
||||||
|
}
|
||||||
|
|
||||||
|
return fn ($value) => '_header' === $value ? $this->getTitle() : $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryKeys($data): array
|
||||||
|
{
|
||||||
|
return ['export_result'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getResult($query, $data)
|
||||||
|
{
|
||||||
|
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle(): string
|
||||||
|
{
|
||||||
|
return 'export.export.acp_closing.title';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getType(): string
|
||||||
|
{
|
||||||
|
return Declarations::ACP_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function initiateQuery(array $requiredModifiers, array $acl, array $data = []): QueryBuilder
|
||||||
|
{
|
||||||
|
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
||||||
|
|
||||||
|
$qb = $this->em->createQueryBuilder()
|
||||||
|
->select('COUNT(DISTINCT acpstephistory.id) As export_result')
|
||||||
|
->from(AccompanyingPeriod\AccompanyingPeriodStepHistory::class, 'acpstephistory')
|
||||||
|
->join('acpstephistory.period', 'acp');
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->leftJoin('acp.participations', 'acppart')
|
||||||
|
->leftJoin('acppart.person', 'person');
|
||||||
|
|
||||||
|
if ($this->filterStatsByCenters) {
|
||||||
|
$qb
|
||||||
|
->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);
|
||||||
|
}
|
||||||
|
|
||||||
|
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
||||||
|
|
||||||
|
return $qb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function requiredRole(): string
|
||||||
|
{
|
||||||
|
return AccompanyingPeriodVoter::STATS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsModifiers(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Declarations::ACP_TYPE,
|
||||||
|
Declarations::PERSON_TYPE,
|
||||||
|
Declarations::ACP_STEP_HISTORY,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
<?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\AccompanyingPeriodStepHistoryFilters;
|
||||||
|
|
||||||
|
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 src\Bundle\ChillPersonBundle\Tests\Export\Filter\AccompanyingPeriodStepHistoryFilters\ByDateFilterTest;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ByDateFilter
|
||||||
|
* Implements the FilterInterface.
|
||||||
|
*
|
||||||
|
* This class represents a filter that filters data based on a date range on the start date.
|
||||||
|
* It allows the user to select a start date and an end date to filter the data.
|
||||||
|
*
|
||||||
|
* @see ByDateFilterTest
|
||||||
|
*/
|
||||||
|
final readonly class ByDateFilter implements FilterInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private RollingDateConverterInterface $rollingDateConverter
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return 'export.filter.step_history.by_date.title';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('start_date', PickRollingDateType::class, [
|
||||||
|
'label' => 'export.filter.step_history.by_date.start_date_label',
|
||||||
|
])
|
||||||
|
->add('end_date', PickRollingDateType::class, [
|
||||||
|
'label' => 'export.filter.step_history.by_date.end_date_label',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormDefaultData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START),
|
||||||
|
'end_date' => new RollingDate(RollingDate::T_TODAY),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function describeAction($data, $format = 'string')
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'exports.filter.step_history.by_date.description',
|
||||||
|
[
|
||||||
|
'start_date' => $this->rollingDateConverter->convert($data['start_date']),
|
||||||
|
'end_date' => $this->rollingDateConverter->convert($data['end_date']),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addRole(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
|
{
|
||||||
|
$startDate = 'acp_step_history_by_date_start_filter';
|
||||||
|
$endDate = 'acp_step_history_by_date_end_filter';
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->andWhere(
|
||||||
|
"acpstephistory.startDate >= :{$startDate} AND (acpstephistory.endDate < :{$endDate} OR acpstephistory.endDate IS NULL)"
|
||||||
|
)
|
||||||
|
->setParameter($startDate, $this->rollingDateConverter->convert($data['start_date']))
|
||||||
|
->setParameter($endDate, $this->rollingDateConverter->convert($data['end_date']));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyOn()
|
||||||
|
{
|
||||||
|
return Declarations::ACP_STEP_HISTORY;
|
||||||
|
}
|
||||||
|
}
|
@ -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\Filter\AccompanyingPeriodStepHistoryFilters;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Export\FilterInterface;
|
||||||
|
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;
|
||||||
|
|
||||||
|
final readonly class ByStepFilter implements FilterInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private TranslatorInterface $translator,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return 'export.filter.step_history.by_step.title';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
|
{
|
||||||
|
$steps = [
|
||||||
|
AccompanyingPeriod::STEP_CONFIRMED,
|
||||||
|
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
|
||||||
|
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
|
||||||
|
AccompanyingPeriod::STEP_CLOSED,
|
||||||
|
];
|
||||||
|
|
||||||
|
$builder->add('steps', ChoiceType::class, [
|
||||||
|
'choices' => array_combine(
|
||||||
|
array_map(static fn (string $step): string => 'accompanying_period.'.$step, $steps),
|
||||||
|
$steps
|
||||||
|
),
|
||||||
|
'label' => 'export.filter.step_history.by_step.pick_steps',
|
||||||
|
'multiple' => true,
|
||||||
|
'expanded' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormDefaultData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'steps' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function describeAction($data, $format = 'string')
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'export.filter.step_history.by_step.description',
|
||||||
|
[
|
||||||
|
'%steps%' => implode(', ', array_map(fn (string $step) => $this->translator->trans('accompanying_period.'.$step), $data['steps'])),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addRole(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
|
{
|
||||||
|
$qb
|
||||||
|
->andWhere('acpstephistory.step IN (:acpstephistory_by_step_filter_steps)')
|
||||||
|
->setParameter('acpstephistory_by_step_filter_steps', $data['steps']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyOn()
|
||||||
|
{
|
||||||
|
return Declarations::ACP_STEP_HISTORY;
|
||||||
|
}
|
||||||
|
}
|
@ -312,4 +312,34 @@ final class AccompanyingPeriodTest extends \PHPUnit\Framework\TestCase
|
|||||||
$this->assertNull($period->getRequestorPerson());
|
$this->assertNull($period->getRequestorPerson());
|
||||||
$this->assertNull($period->getRequestor());
|
$this->assertNull($period->getRequestor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSetStep(): void
|
||||||
|
{
|
||||||
|
$period = new AccompanyingPeriod();
|
||||||
|
|
||||||
|
$period->setStep(AccompanyingPeriod::STEP_CONFIRMED);
|
||||||
|
|
||||||
|
self::assertEquals(AccompanyingPeriod::STEP_CONFIRMED, $period->getStep());
|
||||||
|
self::assertCount(1, $period->getStepHistories());
|
||||||
|
|
||||||
|
$period->setStep(AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT);
|
||||||
|
|
||||||
|
self::assertEquals(AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT, $period->getStep());
|
||||||
|
self::assertCount(2, $period->getStepHistories());
|
||||||
|
|
||||||
|
$periodInactiveSteps = $period->getStepHistories()->filter(fn (AccompanyingPeriod\AccompanyingPeriodStepHistory $h) => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT === $h->getStep());
|
||||||
|
self::assertCount(1, $periodInactiveSteps);
|
||||||
|
|
||||||
|
$period->setStep(AccompanyingPeriod::STEP_CLOSED, ['closing_motive' => $closingMotive = new AccompanyingPeriod\ClosingMotive()]);
|
||||||
|
|
||||||
|
self::assertEquals(AccompanyingPeriod::STEP_CLOSED, $period->getStep());
|
||||||
|
self::assertCount(3, $period->getStepHistories());
|
||||||
|
|
||||||
|
$periodClosedSteps = $period->getStepHistories()->filter(fn (AccompanyingPeriod\AccompanyingPeriodStepHistory $h) => AccompanyingPeriod::STEP_CLOSED === $h->getStep());
|
||||||
|
self::assertCount(1, $periodClosedSteps);
|
||||||
|
|
||||||
|
$periodClosedStep = $periodClosedSteps->first();
|
||||||
|
|
||||||
|
self::assertSame($closingMotive, $periodClosedStep->getClosingMotive());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
<?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\Tests\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodStepHistory;
|
||||||
|
use Chill\PersonBundle\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators\ByClosingMotiveAggregator;
|
||||||
|
use Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepositoryInterface;
|
||||||
|
use Chill\PersonBundle\Templating\Entity\ClosingMotiveRender;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class ByClosingMotiveAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
private ClosingMotiveRender $closingMotiveRender;
|
||||||
|
private ClosingMotiveRepositoryInterface $closingMotiveRepository;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
self::bootKernel();
|
||||||
|
$this->closingMotiveRender = self::$container->get(ClosingMotiveRender::class);
|
||||||
|
$this->closingMotiveRepository = self::$container->get(ClosingMotiveRepositoryInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
return new ByClosingMotiveAggregator(
|
||||||
|
$this->closingMotiveRepository,
|
||||||
|
$this->closingMotiveRender
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryBuilders()
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$qb = $em->createQueryBuilder()
|
||||||
|
->select('COUNT(DISTINCT acpstephistory.id) As export_result')
|
||||||
|
->from(AccompanyingPeriodStepHistory::class, 'acpstephistory')
|
||||||
|
->join('acpstephistory.period', 'acp');
|
||||||
|
|
||||||
|
return [
|
||||||
|
$qb,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
<?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\Tests\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodStepHistory;
|
||||||
|
use Chill\PersonBundle\Export\Enum\DateGroupingChoiceEnum;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Chill\PersonBundle\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators\ByDateAggregator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class ByDateAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
return new ByDateAggregator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'frequency' => DateGroupingChoiceEnum::YEAR->value,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'frequency' => DateGroupingChoiceEnum::WEEK->value,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'frequency' => DateGroupingChoiceEnum::MONTH->value,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryBuilders()
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$qb = $em->createQueryBuilder()
|
||||||
|
->select('COUNT(DISTINCT acpstephistory.id) As export_result')
|
||||||
|
->from(AccompanyingPeriodStepHistory::class, 'acpstephistory')
|
||||||
|
->join('acpstephistory.period', 'acp');
|
||||||
|
|
||||||
|
return [
|
||||||
|
$qb,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
<?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\Tests\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodStepHistory;
|
||||||
|
use Chill\PersonBundle\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators\ByStepAggregator;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class ByStepAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
$translator = new class () implements TranslatorInterface {
|
||||||
|
public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null)
|
||||||
|
{
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new ByStepAggregator($translator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData()
|
||||||
|
{
|
||||||
|
return [[]];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryBuilders()
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$qb = $em->createQueryBuilder()
|
||||||
|
->select('COUNT(DISTINCT acpstephistory.id) As export_result')
|
||||||
|
->from(AccompanyingPeriodStepHistory::class, 'acpstephistory')
|
||||||
|
->join('acpstephistory.period', 'acp');
|
||||||
|
|
||||||
|
return [
|
||||||
|
$qb,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
<?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 src\Bundle\ChillPersonBundle\Tests\Export\Export;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractExportTest;
|
||||||
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
|
use Chill\PersonBundle\Export\Export\CountAccompanyingCourseStepHistory;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class CountAccompanyingCourseStepHistoryTest extends AbstractExportTest
|
||||||
|
{
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExport()
|
||||||
|
{
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
yield new CountAccompanyingCourseStepHistory($em, $this->getParameters(true));
|
||||||
|
yield new CountAccompanyingCourseStepHistory($em, $this->getParameters(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [[]];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getModifiersCombination()
|
||||||
|
{
|
||||||
|
return [[Declarations::ACP_TYPE], [Declarations::ACP_TYPE, Declarations::ACP_STEP_HISTORY]];
|
||||||
|
}
|
||||||
|
}
|
@ -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 src\Bundle\ChillPersonBundle\Tests\Export\Filter\AccompanyingPeriodStepHistoryFilters;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||||
|
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodStepHistory;
|
||||||
|
use Chill\PersonBundle\Export\Filter\AccompanyingPeriodStepHistoryFilters\ByDateFilter;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class ByDateFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private RollingDateConverterInterface $rollingDateConverter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->rollingDateConverter = self::$container->get(RollingDateConverterInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return new ByDateFilter($this->rollingDateConverter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START),
|
||||||
|
'end_date' => new RollingDate(RollingDate::T_TODAY),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryBuilders()
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$qb = $em->createQueryBuilder()
|
||||||
|
->select('COUNT(DISTINCT acpstephistory.id) As export_result')
|
||||||
|
->from(AccompanyingPeriodStepHistory::class, 'acpstephistory')
|
||||||
|
->join('acpstephistory.period', 'acp');
|
||||||
|
|
||||||
|
return [
|
||||||
|
$qb,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -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 src\Bundle\ChillPersonBundle\Tests\Export\Filter\AccompanyingPeriodStepHistoryFilters;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodStepHistory;
|
||||||
|
use Chill\PersonBundle\Export\Filter\AccompanyingPeriodStepHistoryFilters\ByStepFilter;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class ByStepFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
$translator = new class () implements TranslatorInterface {
|
||||||
|
public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null)
|
||||||
|
{
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new ByStepFilter($translator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'steps' => [AccompanyingPeriod::STEP_CONFIRMED, AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'steps' => [AccompanyingPeriod::STEP_CLOSED],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryBuilders()
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$qb = $em->createQueryBuilder()
|
||||||
|
->select('COUNT(DISTINCT acpstephistory.id) As export_result')
|
||||||
|
->from(AccompanyingPeriodStepHistory::class, 'acpstephistory')
|
||||||
|
->join('acpstephistory.period', 'acp');
|
||||||
|
|
||||||
|
return [
|
||||||
|
$qb,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
|
# exports
|
||||||
|
Chill\PersonBundle\Export\Export\CountAccompanyingCourseStepHistory:
|
||||||
|
tags:
|
||||||
|
- { name: chill.export, alias: count_acpstephistory }
|
||||||
|
|
||||||
|
# filters
|
||||||
|
Chill\PersonBundle\Export\Filter\AccompanyingPeriodStepHistoryFilters\ByDateFilter:
|
||||||
|
tags:
|
||||||
|
- { name: chill.export_filter, alias: acpstephistory_filter_by_date }
|
||||||
|
|
||||||
|
Chill\PersonBundle\Export\Filter\AccompanyingPeriodStepHistoryFilters\ByStepFilter:
|
||||||
|
tags:
|
||||||
|
- { name: chill.export_filter, alias: acpstephistory_filter_by_step }
|
||||||
|
|
||||||
|
# aggregators
|
||||||
|
Chill\PersonBundle\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators\ByClosingMotiveAggregator:
|
||||||
|
tags:
|
||||||
|
- { name: chill.export_aggregator, alias: acpstephistory_agg_by_closing_motive }
|
||||||
|
|
||||||
|
Chill\PersonBundle\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators\ByDateAggregator:
|
||||||
|
tags:
|
||||||
|
- { name: chill.export_aggregator, alias: acpstephistory_agg_by_date }
|
||||||
|
|
||||||
|
Chill\PersonBundle\Export\Aggregator\AccompanyingPeriodStepHistoryAggregators\ByStepAggregator:
|
||||||
|
tags:
|
||||||
|
- { name: chill.export_aggregator, alias: acpstephistory_agg_by_step }
|
@ -0,0 +1,52 @@
|
|||||||
|
<?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\Migrations\Person;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20240123161457 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Store closing motive when closing a course';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_person_accompanying_period_step_history ADD closingMotive_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_person_accompanying_period_step_history ADD CONSTRAINT FK_84D514AC504CB38D FOREIGN KEY (closingMotive_id) REFERENCES chill_person_accompanying_period_closingmotive (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE chill_person_accompanying_period_step_history ADD CONSTRAINT FK_84D514AC65FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql(<<<'EOF'
|
||||||
|
WITH last_step AS (
|
||||||
|
SELECT * FROM (
|
||||||
|
SELECT *, rank() OVER (partition by period_id ORDER BY startdate DESC, id DESC) AS r FROM chill_person_accompanying_period_step_history cpapsh
|
||||||
|
) as sq
|
||||||
|
WHERE r = 1
|
||||||
|
)
|
||||||
|
UPDATE chill_person_accompanying_period_step_history
|
||||||
|
SET closingMotive_id = chill_person_accompanying_period.closingmotive_id
|
||||||
|
FROM last_step, chill_person_accompanying_period
|
||||||
|
WHERE last_step.period_id = chill_person_accompanying_period_step_history.period_id AND chill_person_accompanying_period.id = chill_person_accompanying_period_step_history.period_id
|
||||||
|
AND last_step.step = 'CLOSED';
|
||||||
|
EOF);
|
||||||
|
$this->addSql('CREATE INDEX IDX_84D514AC504CB38D ON chill_person_accompanying_period_step_history (closingMotive_id)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_person_accompanying_period_step_history DROP CONSTRAINT FK_84D514AC504CB38D');
|
||||||
|
$this->addSql('ALTER TABLE chill_person_accompanying_period_step_history DROP CONSTRAINT FK_84D514AC65FF1AEC');
|
||||||
|
$this->addSql('DROP INDEX IDX_84D514AC504CB38D');
|
||||||
|
$this->addSql('ALTER TABLE chill_person_accompanying_period_step_history DROP closingMotive_id');
|
||||||
|
}
|
||||||
|
}
|
@ -136,14 +136,20 @@ exports:
|
|||||||
Filtered by person\'s geographical unit (based on address) computed at date, only units:
|
Filtered by person\'s geographical unit (based on address) computed at date, only units:
|
||||||
"Filtré par zone géographique sur base de l'adresse, calculé à {datecalc, date, short}, seulement les zones suivantes: {units}"
|
"Filtré par zone géographique sur base de l'adresse, calculé à {datecalc, date, short}, seulement les zones suivantes: {units}"
|
||||||
filter:
|
filter:
|
||||||
work:
|
|
||||||
by_treating_agent:
|
|
||||||
Filtered by treating agent at date: >-
|
|
||||||
Les agents traitant au { agent_at, date, medium }, seulement {agents}
|
|
||||||
course:
|
course:
|
||||||
not_having_address_reference:
|
not_having_address_reference:
|
||||||
describe: >-
|
describe: >-
|
||||||
Uniquement les parcours qui ne sont pas localisés à une adresse de référence, à la date du {date_calc, date, medium}
|
Uniquement les parcours qui ne sont pas localisés à une adresse de référence, à la date du {date_calc, date, medium}
|
||||||
|
work:
|
||||||
|
by_treating_agent:
|
||||||
|
Filtered by treating agent at date: >-
|
||||||
|
Les agents traitant au { agent_at, date, medium }, seulement {agents}
|
||||||
|
|
||||||
|
step_history:
|
||||||
|
by_date:
|
||||||
|
description: >-
|
||||||
|
Changements de statuts filtrés par date: après le { start_date, date, medium } (inclus), avant le { end_date, date, medium }
|
||||||
|
|
||||||
|
|
||||||
Les agents traitants au { agent_at, date, medium }, seulement {agents}
|
Les agents traitants au { agent_at, date, medium }, seulement {agents}
|
||||||
|
|
||||||
|
@ -785,7 +785,9 @@ accompanying_period:
|
|||||||
dates_from_%opening_date%_to_%closing_date%: Ouvert du %opening_date% au %closing_date%
|
dates_from_%opening_date%_to_%closing_date%: Ouvert du %opening_date% au %closing_date%
|
||||||
DRAFT: Brouillon
|
DRAFT: Brouillon
|
||||||
CONFIRMED: Confirmé
|
CONFIRMED: Confirmé
|
||||||
CLOSED: Clotûré
|
CLOSED: Clôturé
|
||||||
|
CONFIRMED_INACTIVE_SHORT: Hors file active
|
||||||
|
CONFIRMED_INACTIVE_LONG: Pré-archivé
|
||||||
emergency: Urgent
|
emergency: Urgent
|
||||||
occasional: ponctuel
|
occasional: ponctuel
|
||||||
regular: régulier
|
regular: régulier
|
||||||
@ -985,6 +987,9 @@ export:
|
|||||||
YYYY-MM: par mois
|
YYYY-MM: par mois
|
||||||
YYYY: par année
|
YYYY: par année
|
||||||
export:
|
export:
|
||||||
|
acp_closing:
|
||||||
|
title: Nombre de changements de statuts de parcours
|
||||||
|
description: Compte le nombre de changements de statuts de parcours. Cet export est indiqué pour obtenir le nombre de parcours ouverts ou fermés pendant une période de temps (un parcours pouvant être clôturé, puis ré-ouvert pendant la période de temps indiquée)
|
||||||
acp_stats:
|
acp_stats:
|
||||||
avg_duration: Moyenne de la durée de participation de chaque usager concerné
|
avg_duration: Moyenne de la durée de participation de chaque usager concerné
|
||||||
count_participations: Nombre de participations distinctes
|
count_participations: Nombre de participations distinctes
|
||||||
@ -1037,6 +1042,18 @@ export:
|
|||||||
at_date: Date de calcul de l'adresse
|
at_date: Date de calcul de l'adresse
|
||||||
header: Code postal
|
header: Code postal
|
||||||
|
|
||||||
|
step_history:
|
||||||
|
by_step:
|
||||||
|
title: Grouper les changements de statut du parcours par étape
|
||||||
|
header: Nouveau statut du parcours
|
||||||
|
by_date:
|
||||||
|
title: Grouper les changements de statut du parcours par date
|
||||||
|
header: Date du changement de statut du parcours
|
||||||
|
date_grouping_label: Grouper par
|
||||||
|
by_closing_motive:
|
||||||
|
title: Grouper les changements de statut du parcours par motif de clôture
|
||||||
|
header: Motif de clôture
|
||||||
|
|
||||||
course:
|
course:
|
||||||
by-user:
|
by-user:
|
||||||
title: Grouper les parcours par usager participant
|
title: Grouper les parcours par usager participant
|
||||||
@ -1128,6 +1145,16 @@ export:
|
|||||||
by_geog_unit:
|
by_geog_unit:
|
||||||
Filtered by person's geographical unit (based on address) computed at %datecalc%, only %units%: Filtré par unité géographique (sur base de l'adresse), calculé le %datecalc%, seulement %units%
|
Filtered by person's geographical unit (based on address) computed at %datecalc%, only %units%: Filtré par unité géographique (sur base de l'adresse), calculé le %datecalc%, seulement %units%
|
||||||
|
|
||||||
|
step_history:
|
||||||
|
by_step:
|
||||||
|
title: Filtrer les changements de statut du parcours par étape
|
||||||
|
pick_steps: Nouvelles étapes
|
||||||
|
description: "Filtré par étape: seulement %steps%"
|
||||||
|
by_date:
|
||||||
|
title: Filtrer les changements de statut du parcours par date
|
||||||
|
start_date_label: Changements après le
|
||||||
|
end_date_label: Changements avant le
|
||||||
|
|
||||||
person:
|
person:
|
||||||
by_composition:
|
by_composition:
|
||||||
Filter by household composition: Filtrer les usagers par composition du ménage
|
Filter by household composition: Filtrer les usagers par composition du ménage
|
||||||
|
Loading…
x
Reference in New Issue
Block a user