mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Feature: Change accompanying period info step in a cronjob
This commit is contained in:
parent
97b7ff2e43
commit
722f053f06
@ -34,6 +34,7 @@
|
|||||||
"sensio/framework-extra-bundle": "^5.5",
|
"sensio/framework-extra-bundle": "^5.5",
|
||||||
"spomky-labs/base64url": "^2.0",
|
"spomky-labs/base64url": "^2.0",
|
||||||
"symfony/browser-kit": "^4.4",
|
"symfony/browser-kit": "^4.4",
|
||||||
|
"symfony/clock": "^6.2",
|
||||||
"symfony/css-selector": "^4.4",
|
"symfony/css-selector": "^4.4",
|
||||||
"symfony/expression-language": "^4.4",
|
"symfony/expression-language": "^4.4",
|
||||||
"symfony/form": "^4.4",
|
"symfony/form": "^4.4",
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
parameters:
|
parameters:
|
||||||
# cl_chill_main.example.class: Chill\MainBundle\Example
|
# cl_chill_main.example.class: Chill\MainBundle\Example
|
||||||
|
|
||||||
|
imports:
|
||||||
|
- ./services/clock.yaml
|
||||||
|
|
||||||
services:
|
services:
|
||||||
_defaults:
|
_defaults:
|
||||||
autowire: true
|
autowire: true
|
||||||
|
4
src/Bundle/ChillMainBundle/config/services/clock.yaml
Normal file
4
src/Bundle/ChillMainBundle/config/services/clock.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# temporary, waiting for symfony 6.0 to load clock
|
||||||
|
services:
|
||||||
|
Symfony\Component\Clock\NativeClock: ~
|
||||||
|
Symfony\Component\Clock\ClockInterface: '@Symfony\Component\Clock\NativeClock'
|
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\AccompanyingPeriod\Lifecycle;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Cron\CronJobInterface;
|
||||||
|
use Chill\MainBundle\Entity\CronJobExecution;
|
||||||
|
use Symfony\Component\Clock\ClockInterface;
|
||||||
|
|
||||||
|
readonly class AccompanyingPeriodStepChangeCronjob implements CronJobInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private ClockInterface $clock,
|
||||||
|
private AccompanyingPeriodStepChangeRequestor $requestor,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canRun(?CronJobExecution $cronJobExecution): bool
|
||||||
|
{
|
||||||
|
$now = $this->clock->now();
|
||||||
|
|
||||||
|
if ($now->sub(new \DateInterval('P1D')) < $cronJobExecution->getLastStart()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_array((int) $now->format('H'), [1, 2, 3, 4, 5, 6], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getKey(): string
|
||||||
|
{
|
||||||
|
return 'accompanying-period-step-change';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
($this->requestor)();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
<?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\AccompanyingPeriod\Lifecycle;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
|
||||||
|
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
|
||||||
|
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
|
||||||
|
|
||||||
|
#[AsMessageHandler]
|
||||||
|
class AccompanyingPeriodStepChangeMessageHandler implements MessageHandlerInterface
|
||||||
|
{
|
||||||
|
private const LOG_PREFIX = '[accompanying period step change message handler] ';
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private AccompanyingPeriodRepository $accompanyingPeriodRepository,
|
||||||
|
private AccompanyingPeriodStepChanger $changer,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(AccompanyingPeriodStepChangeRequestMessage $message): void
|
||||||
|
{
|
||||||
|
if (null === $period = $this->accompanyingPeriodRepository->find($message->getPeriodId())) {
|
||||||
|
throw new \RuntimeException(self::LOG_PREFIX . 'Could not find period with this id: '. $message->getPeriodId());
|
||||||
|
}
|
||||||
|
|
||||||
|
($this->changer)($period, $message->getTransition());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
<?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\AccompanyingPeriod\Lifecycle;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message which will request a change in the step of accompanying period
|
||||||
|
*/
|
||||||
|
class AccompanyingPeriodStepChangeRequestMessage
|
||||||
|
{
|
||||||
|
private int $periodId;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
AccompanyingPeriod|int $period,
|
||||||
|
private string $transition,
|
||||||
|
) {
|
||||||
|
if (is_int($period)) {
|
||||||
|
$this->periodId = $period;
|
||||||
|
} else {
|
||||||
|
if (null !== $id = $period->getId()) {
|
||||||
|
$this->periodId = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \LogicException("This AccompanyingPeriod does not have and id yet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPeriodId(): int
|
||||||
|
{
|
||||||
|
return $this->periodId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTransition(): string
|
||||||
|
{
|
||||||
|
return $this->transition;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
<?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\AccompanyingPeriod\Lifecycle;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
|
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodInfoRepositoryInterface;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
|
use Symfony\Component\Messenger\MessageBusInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gather all the accompanying period which needs a change in step
|
||||||
|
*/
|
||||||
|
class AccompanyingPeriodStepChangeRequestor
|
||||||
|
{
|
||||||
|
private \DateInterval $intervalForShortInactive;
|
||||||
|
|
||||||
|
private \DateInterval $intervalForLongInactive;
|
||||||
|
|
||||||
|
private bool $isMarkInactive;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private AccompanyingPeriodInfoRepositoryInterface $accompanyingPeriodInfoRepository,
|
||||||
|
private LoggerInterface $logger,
|
||||||
|
private MessageBusInterface $messageBus,
|
||||||
|
ParameterBagInterface $parameterBag,
|
||||||
|
) {
|
||||||
|
$config = $parameterBag->get('chill_person')['accompanying_period_lifecycle_delays'];
|
||||||
|
$this->isMarkInactive = $config['mark_inactive'];
|
||||||
|
$this->intervalForShortInactive = new \DateInterval($config['mark_inactive_short_after']);
|
||||||
|
$this->intervalForLongInactive = new \DateInterval($config['mark_inactive_long_after']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(): void
|
||||||
|
{
|
||||||
|
if (!$this->isMarkInactive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the oldest ones first
|
||||||
|
foreach (
|
||||||
|
$olders = $this->accompanyingPeriodInfoRepository->findAccompanyingPeriodIdInactiveAfter(
|
||||||
|
$this->intervalForLongInactive,
|
||||||
|
[AccompanyingPeriod::STEP_CONFIRMED, AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT]
|
||||||
|
) as $accompanyingPeriodId
|
||||||
|
) {
|
||||||
|
$this->logger->debug('request mark period as inactive_short', ['period' => $accompanyingPeriodId]);
|
||||||
|
$this->messageBus->dispatch(new AccompanyingPeriodStepChangeRequestMessage($accompanyingPeriodId, 'mark_inactive_long'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// the newest
|
||||||
|
foreach (
|
||||||
|
$this->accompanyingPeriodInfoRepository->findAccompanyingPeriodIdInactiveAfter(
|
||||||
|
$this->intervalForShortInactive,
|
||||||
|
[AccompanyingPeriod::STEP_CONFIRMED]
|
||||||
|
) as $accompanyingPeriodId
|
||||||
|
) {
|
||||||
|
if (in_array($accompanyingPeriodId, $olders, true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->debug('request mark period as inactive_long', ['period' => $accompanyingPeriodId]);
|
||||||
|
$this->messageBus->dispatch(new AccompanyingPeriodStepChangeRequestMessage($accompanyingPeriodId, 'mark_inactive_short'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// a new event has been created => remove inactive long, or short
|
||||||
|
foreach (
|
||||||
|
$this->accompanyingPeriodInfoRepository->findAccompanyingPeriodIdActiveSince(
|
||||||
|
$this->intervalForShortInactive,
|
||||||
|
[AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT, AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG]
|
||||||
|
) as $accompanyingPeriodId
|
||||||
|
) {
|
||||||
|
$this->logger->debug('request mark period as active', ['period' => $accompanyingPeriodId]);
|
||||||
|
$this->messageBus->dispatch(new AccompanyingPeriodStepChangeRequestMessage($accompanyingPeriodId, 'mark_active'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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\AccompanyingPeriod\Lifecycle;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\Workflow\Registry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the step of an accompanying period
|
||||||
|
*
|
||||||
|
* This should be invoked through scripts (not in the in context of an http request, or an
|
||||||
|
* action from a user).
|
||||||
|
*/
|
||||||
|
class AccompanyingPeriodStepChanger
|
||||||
|
{
|
||||||
|
private const LOG_PREFIX = '[AccompanyingPeriodStepChanger] ';
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private EntityManagerInterface $entityManager,
|
||||||
|
private LoggerInterface $logger,
|
||||||
|
private Registry $workflowRegistry,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(AccompanyingPeriod $period, string $transition, ?string $workflowName = null): void
|
||||||
|
{
|
||||||
|
$workflow = $this->workflowRegistry->get($period, $workflowName);
|
||||||
|
|
||||||
|
if (!$workflow->can($period, $transition)) {
|
||||||
|
$this->logger->info(self::LOG_PREFIX . 'not able to apply the transition on period', [
|
||||||
|
'period_id' => $period->getId(),
|
||||||
|
'transition' => $transition
|
||||||
|
]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$workflow->apply($period, $transition);
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
$this->logger->info(self::LOG_PREFIX . 'could apply a transition', [
|
||||||
|
'period_id' => $period->getId(),
|
||||||
|
'transition' => $transition
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ use Chill\MainBundle\DependencyInjection\MissingBundleException;
|
|||||||
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
|
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
|
||||||
use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController;
|
use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController;
|
||||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter;
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter;
|
||||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodResourceVoter;
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodResourceVoter;
|
||||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||||
@ -1010,18 +1011,42 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
|||||||
],
|
],
|
||||||
'initial_marking' => 'DRAFT',
|
'initial_marking' => 'DRAFT',
|
||||||
'places' => [
|
'places' => [
|
||||||
'DRAFT',
|
AccompanyingPeriod::STEP_DRAFT,
|
||||||
'CONFIRMED',
|
AccompanyingPeriod::STEP_CONFIRMED,
|
||||||
'CLOSED',
|
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
|
||||||
|
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
|
||||||
|
AccompanyingPeriod::STEP_CLOSED,
|
||||||
],
|
],
|
||||||
'transitions' => [
|
'transitions' => [
|
||||||
'confirm' => [
|
'confirm' => [
|
||||||
'from' => 'DRAFT',
|
'from' => AccompanyingPeriod::STEP_DRAFT,
|
||||||
'to' => 'CONFIRMED',
|
'to' => AccompanyingPeriod::STEP_CONFIRMED,
|
||||||
|
],
|
||||||
|
'mark_inactive_short' => [
|
||||||
|
'from' => AccompanyingPeriod::STEP_CONFIRMED,
|
||||||
|
'to' => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
|
||||||
|
],
|
||||||
|
'mark_inactive_long' => [
|
||||||
|
'from' => [
|
||||||
|
AccompanyingPeriod::STEP_CONFIRMED,
|
||||||
|
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT
|
||||||
|
],
|
||||||
|
'to' => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
|
||||||
|
],
|
||||||
|
'mark_active' => [
|
||||||
|
'from' => [
|
||||||
|
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
|
||||||
|
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
|
||||||
|
],
|
||||||
|
'to' => AccompanyingPeriod::STEP_CONFIRMED
|
||||||
],
|
],
|
||||||
'close' => [
|
'close' => [
|
||||||
'from' => 'CONFIRMED',
|
'from' => [
|
||||||
'to' => 'CLOSED',
|
AccompanyingPeriod::STEP_CONFIRMED,
|
||||||
|
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
|
||||||
|
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
|
||||||
|
],
|
||||||
|
'to' => AccompanyingPeriod::STEP_CLOSED,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
@ -128,6 +128,15 @@ class Configuration implements ConfigurationInterface
|
|||||||
->info('Can we have more than one simultaneous accompanying period in the same time. Default false.')
|
->info('Can we have more than one simultaneous accompanying period in the same time. Default false.')
|
||||||
->defaultValue(false)
|
->defaultValue(false)
|
||||||
->end()
|
->end()
|
||||||
|
->arrayNode('accompanying_period_lifecycle_delays')
|
||||||
|
->addDefaultsIfNotSet()
|
||||||
|
->info('Delays before marking an accompanying period as inactive')
|
||||||
|
->children()
|
||||||
|
->booleanNode('mark_inactive')->defaultTrue()->end()
|
||||||
|
->scalarNode('mark_inactive_short_after')->defaultValue('P6M')->end()
|
||||||
|
->scalarNode('mark_inactive_long_after')->defaultValue('P2Y')->end()
|
||||||
|
->end()
|
||||||
|
->end() // end of 'accompanying_period_lifecycle_delays
|
||||||
->end() // children of 'root', parent = root
|
->end() // children of 'root', parent = root
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -116,7 +116,16 @@ class AccompanyingPeriod implements
|
|||||||
* confirmed, but no activity (Activity, AccompanyingPeriod, ...)
|
* confirmed, but no activity (Activity, AccompanyingPeriod, ...)
|
||||||
* has been associated, or updated, within this accompanying period.
|
* has been associated, or updated, within this accompanying period.
|
||||||
*/
|
*/
|
||||||
public const STEP_CONFIRMED_INACTIVE = 'CONFIRMED_INACTIVE';
|
public const STEP_CONFIRMED_INACTIVE_SHORT = 'CONFIRMED_INACTIVE_SHORT';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark an accompanying period as confirmed, but inactive
|
||||||
|
*
|
||||||
|
* this means that the accompanying period **is**
|
||||||
|
* confirmed, but no activity (Activity, AccompanyingPeriod, ...)
|
||||||
|
* has been associated, or updated, within this accompanying period.
|
||||||
|
*/
|
||||||
|
public const STEP_CONFIRMED_INACTIVE_LONG = 'CONFIRMED_INACTIVE_LONG';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark an accompanying period as "draft".
|
* Mark an accompanying period as "draft".
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Repository\AccompanyingPeriod;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo;
|
||||||
|
use DateInterval;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
use LogicException;
|
||||||
|
use Symfony\Component\Clock\ClockInterface;
|
||||||
|
|
||||||
|
readonly class AccompanyingPeriodInfoRepository implements AccompanyingPeriodInfoRepositoryInterface
|
||||||
|
{
|
||||||
|
private EntityRepository $entityRepository;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private ClockInterface $clock,
|
||||||
|
private EntityManagerInterface $em,
|
||||||
|
) {
|
||||||
|
$this->entityRepository = $em->getRepository($this->getClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findAccompanyingPeriodIdInactiveAfter(DateInterval $interval, array $statuses = []): array
|
||||||
|
{
|
||||||
|
$query = $this->em->createQuery();
|
||||||
|
$baseDql = 'SELECT DISTINCT IDENTITY(ai.accompanyingPeriod) FROM '.AccompanyingPeriodInfo::class.' ai JOIN ai.accompanyingPeriod a WHERE NOT EXISTS
|
||||||
|
(SELECT 1 FROM ' . AccompanyingPeriodInfo::class . ' aiz WHERE aiz.infoDate > :after AND IDENTITY(aiz.accompanyingPeriod) = IDENTITY(ai.accompanyingPeriod))';
|
||||||
|
|
||||||
|
if ([] !== $statuses) {
|
||||||
|
$dql = $baseDql . ' AND a.step IN (:statuses)';
|
||||||
|
$query->setParameter('statuses', $statuses);
|
||||||
|
} else {
|
||||||
|
$dql = $baseDql;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query->setDQL($dql)
|
||||||
|
->setParameter('after', $this->clock->now()->sub($interval))
|
||||||
|
->getSingleColumnResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findAccompanyingPeriodIdActiveSince(DateInterval $interval, array $statuses = []): array
|
||||||
|
{
|
||||||
|
$query = $this->em->createQuery();
|
||||||
|
$baseDql = 'SELECT DISTINCT IDENTITY(ai.accompanyingPeriod) FROM ' . AccompanyingPeriodInfo::class . ' ai
|
||||||
|
JOIN ai.accompanyingPeriod a WHERE ai.infoDate > :after';
|
||||||
|
|
||||||
|
if ([] !== $statuses) {
|
||||||
|
$dql = $baseDql . ' AND a.step IN (:statuses)';
|
||||||
|
$query->setParameter('statuses', $statuses);
|
||||||
|
} else {
|
||||||
|
$dql = $baseDql;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query->setDQL($dql)
|
||||||
|
->setParameter('after', $this->clock->now()->sub($interval))
|
||||||
|
->getSingleColumnResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function find($id): ?AccompanyingPeriodInfo
|
||||||
|
{
|
||||||
|
throw new LogicException("Calling an accompanying period info by his id does not make sense");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findAll(): array
|
||||||
|
{
|
||||||
|
return $this->entityRepository->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
|
||||||
|
{
|
||||||
|
return $this->entityRepository->findBy($criteria, $orderBy, $limit, $offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findOneBy(array $criteria): ?AccompanyingPeriodInfo
|
||||||
|
{
|
||||||
|
return $this->entityRepository->findOneBy($criteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClassName(): string
|
||||||
|
{
|
||||||
|
return AccompanyingPeriodInfo::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
<?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\Repository\AccompanyingPeriod;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo;
|
||||||
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template-extends ObjectRepository<AccompanyingPeriodInfo>
|
||||||
|
*/
|
||||||
|
interface AccompanyingPeriodInfoRepositoryInterface extends ObjectRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Return a list of id for inactive accompanying periods
|
||||||
|
*
|
||||||
|
* @param \DateInterval $interval
|
||||||
|
* @param list<AccompanyingPeriod::STEP_*> $statuses
|
||||||
|
* @return list<int>
|
||||||
|
*/
|
||||||
|
public function findAccompanyingPeriodIdInactiveAfter(\DateInterval $interval, array $statuses = []): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \DateInterval $interval
|
||||||
|
* @param list<AccompanyingPeriod::STEP_*> $statuses
|
||||||
|
* @return list<int>
|
||||||
|
*/
|
||||||
|
public function findAccompanyingPeriodIdActiveSince(\DateInterval $interval, array $statuses = []): array;
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
<?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 AccompanyingPeriod\Lifecycle;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\CronJobExecution;
|
||||||
|
use Chill\PersonBundle\AccompanyingPeriod\Lifecycle\AccompanyingPeriodStepChangeCronjob;
|
||||||
|
use Chill\PersonBundle\AccompanyingPeriod\Lifecycle\AccompanyingPeriodStepChangeRequestor;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
use Symfony\Component\Clock\MockClock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class AccompanyingPeriodStepChangeCronjobTest extends TestCase
|
||||||
|
{
|
||||||
|
use ProphecyTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideRunTimes
|
||||||
|
*/
|
||||||
|
public function testCanRun(string $datetime, \DateTimeImmutable $lastExecutionStart, bool $canRun): void
|
||||||
|
{
|
||||||
|
$requestor = $this->prophesize(AccompanyingPeriodStepChangeRequestor::class);
|
||||||
|
$clock = new MockClock($datetime);
|
||||||
|
|
||||||
|
$cronJob = new AccompanyingPeriodStepChangeCronjob($clock, $requestor->reveal());
|
||||||
|
$cronJobExecution = (new CronJobExecution($cronJob->getKey()))->setLastStart($lastExecutionStart);
|
||||||
|
|
||||||
|
$this->assertEquals($canRun, $cronJob->canRun($cronJobExecution));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideRunTimes(): iterable
|
||||||
|
{
|
||||||
|
// can run, during the night
|
||||||
|
yield ['2023-01-15T01:00:00+02:00', new \DateTimeImmutable('2023-01-14T00:00:00+02:00'), true];
|
||||||
|
|
||||||
|
// can not run, not during the night
|
||||||
|
yield ['2023-01-15T10:00:00+02:00', new \DateTimeImmutable('2023-01-14T00:00:00+02:00'), false];
|
||||||
|
|
||||||
|
// can not run: not enough elapsed time
|
||||||
|
yield ['2023-01-15T01:00:00+02:00', new \DateTimeImmutable('2023-01-15T00:30:00+02:00'), false];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -25,6 +25,11 @@ services:
|
|||||||
autowire: true
|
autowire: true
|
||||||
autoconfigure: true
|
autoconfigure: true
|
||||||
|
|
||||||
|
Chill\PersonBundle\AccompanyingPeriod\Lifecycle\:
|
||||||
|
resource: './../../AccompanyingPeriod/Lifecycle'
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
Chill\PersonBundle\AccompanyingPeriod\Events\UserRefEventSubscriber:
|
Chill\PersonBundle\AccompanyingPeriod\Events\UserRefEventSubscriber:
|
||||||
autowire: true
|
autowire: true
|
||||||
autoconfigure: true
|
autoconfigure: true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user