diff --git a/src/Bundle/ChillMainBundle/Tests/Util/DateRangeCoveringTest.php b/src/Bundle/ChillMainBundle/Tests/Util/DateRangeCoveringTest.php
index c06b4a4f4..18af61849 100644
--- a/src/Bundle/ChillMainBundle/Tests/Util/DateRangeCoveringTest.php
+++ b/src/Bundle/ChillMainBundle/Tests/Util/DateRangeCoveringTest.php
@@ -37,6 +37,18 @@ class DateRangeCoveringTest extends TestCase
$this->assertNotContains(3, $cover->getIntersections()[0][2]);
}
+ public function testCoveringWithMinCover1_NoCoveringWithNullDates()
+ {
+ $cover = new DateRangeCovering(1, new \DateTimeZone('Europe/Brussels'));
+ $cover
+ ->add(new \DateTime('2021-10-05'), new \DateTime('2021-10-18'), 521)
+ ->add(new \DateTime('2021-10-26'), null, 663)
+ ->compute()
+ ;
+
+ $this->assertFalse($cover->hasIntersections());
+ }
+
public function testCoveringWithMinCover1WithTwoIntersections()
{
$cover = new DateRangeCovering(1, new \DateTimeZone('Europe/Brussels'));
diff --git a/src/Bundle/ChillMainBundle/Util/DateRangeCovering.php b/src/Bundle/ChillMainBundle/Util/DateRangeCovering.php
index a10ebb883..3eb6d1433 100644
--- a/src/Bundle/ChillMainBundle/Util/DateRangeCovering.php
+++ b/src/Bundle/ChillMainBundle/Util/DateRangeCovering.php
@@ -140,67 +140,6 @@ class DateRangeCovering
return $this;
}
- private function process(array $intersections): array
- {
- $result = [];
- $starts = [];
- $ends = [];
- $metadatas = [];
-
- while (null !== ($current = \array_pop($intersections))) {
- list($cStart, $cEnd, $cMetadata) = $current;
- $n = count($cMetadata);
-
- foreach ($intersections as list($iStart, $iEnd, $iMetadata)) {
- $start = max($cStart, $iStart);
- $end = min($cEnd, $iEnd);
-
- if ($start <= $end) {
- if (FALSE !== ($key = \array_search($start, $starts))) {
- if ($ends[$key] === $end) {
- $metadatas[$key] = \array_unique(\array_merge($metadatas[$key], $iMetadata));
- continue;
- }
- }
- $starts[] = $start;
- $ends[] = $end;
- $metadatas[] = \array_unique(\array_merge($iMetadata, $cMetadata));
- }
- }
- }
-
- // recompose results
- foreach ($starts as $k => $start) {
- $result[] = [$start, $ends[$k], \array_unique($metadatas[$k])];
- }
-
- return $result;
- }
-
- private function addToIntersections(array $intersections, array $intersection)
- {
- $foundExisting = false;
- list($nStart, $nEnd, $nMetadata) = $intersection;
-
- \array_walk($intersections,
- function(&$i, $key) use ($nStart, $nEnd, $nMetadata, $foundExisting) {
- if ($foundExisting) {
- return;
- };
- if ($i[0] === $nStart && $i[1] === $nEnd) {
- $foundExisting = true;
- $i[2] = \array_merge($i[2], $nMetadata);
- }
- }
- );
-
- if (!$foundExisting) {
- $intersections[] = $intersection;
- }
-
- return $intersections;
- }
-
public function hasIntersections(): bool
{
if (!$this->computed) {
diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php
index bce888876..ba033f562 100644
--- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php
+++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php
@@ -54,10 +54,14 @@ class AccompanyingCourseApiController extends ApiController
$accompanyingPeriod = $this->getEntity('participation', $id, $request);
$this->checkACL('confirm', $request, $_format, $accompanyingPeriod);
-$workflow = $this->registry->get($accompanyingPeriod);
+ $workflow = $this->registry->get($accompanyingPeriod);
if (FALSE === $workflow->can($accompanyingPeriod, 'confirm')) {
- throw new BadRequestException('It is not possible to confirm this period');
+ // throw new BadRequestException('It is not possible to confirm this period');
+ $errors = $this->validator->validate($accompanyingPeriod, null, [$accompanyingPeriod::STEP_CONFIRMED]);
+ if( count($errors) > 0 ){
+ return $this->json($errors, 422);
+ }
}
$workflow->apply($accompanyingPeriod, 'confirm');
@@ -109,6 +113,13 @@ $workflow = $this->registry->get($accompanyingPeriod);
public function resourceApi($id, Request $request, string $_format): Response
{
+ $accompanyingPeriod = $this->getEntity('resource', $id, $request);
+ $errors = $this->validator->validate($accompanyingPeriod);
+
+ if ($errors->count() > 0) {
+ return $this->json($errors, 422);
+ }
+
return $this->addRemoveSomething('resource', $id, $request, $_format, 'resource', Resource::class);
}
diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php
index cbec9c439..eef8d7b47 100644
--- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php
+++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodOrigin.php
@@ -40,7 +40,7 @@ class LoadAccompanyingPeriodOrigin extends AbstractFixture implements OrderedFix
public function getOrder()
{
- return 10005;
+ return 9000;
}
private $phoneCall = ['en' => 'phone call', 'fr' => 'appel téléphonique'];
diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php
index adc37d5b5..b9b0b4946 100644
--- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php
+++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php
@@ -247,7 +247,9 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
if (\random_int(0, 10) > 3) {
// always add social scope:
$accompanyingPeriod->addScope($this->getReference('scope_social'));
-
+ $origin = $this->getReference(LoadAccompanyingPeriodOrigin::ACCOMPANYING_PERIOD_ORIGIN);
+ $accompanyingPeriod->setOrigin($origin);
+ $accompanyingPeriod->setIntensity('regular');
$accompanyingPeriod->setAddressLocation($this->createAddress());
$manager->persist($accompanyingPeriod->getAddressLocation());
$workflow = $this->workflowRegistry->get($accompanyingPeriod);
diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
index 9ad0c75dd..dab1dcb9d 100644
--- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
+++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
@@ -45,6 +45,9 @@ use Chill\MainBundle\Entity\User;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
use Symfony\Component\Validator\Constraints as Assert;
+use Symfony\Component\Validator\GroupSequenceProviderInterface;
+use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ParticipationOverlap;
+use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ResourceDuplicateCheck;
/**
* AccompanyingPeriod Class
@@ -54,9 +57,10 @@ use Symfony\Component\Validator\Constraints as Assert;
* @DiscriminatorMap(typeProperty="type", mapping={
* "accompanying_period"=AccompanyingPeriod::class
* })
+ * @Assert\GroupSequenceProvider
*/
class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface,
- HasScopesInterface, HasCentersInterface
+ HasScopesInterface, HasCentersInterface, GroupSequenceProviderInterface
{
/**
* Mark an accompanying period as "occasional"
@@ -132,6 +136,7 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
* cascade={"persist", "remove"},
* orphanRemoval=true
* )
+ * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_DRAFT})
*/
private $comments;
@@ -147,9 +152,10 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
* @var Collection
*
* @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class,
- * mappedBy="accompanyingPeriod",
+ * mappedBy="accompanyingPeriod", orphanRemoval=true,
* cascade={"persist", "refresh", "remove", "merge", "detach"})
* @Groups({"read"})
+ * @ParticipationOverlap(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED})
*/
private $participations;
@@ -188,6 +194,7 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
* @ORM\ManyToOne(targetEntity=Origin::class)
* @ORM\JoinColumn(nullable=true)
* @Groups({"read", "write"})
+ * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CONFIRMED})
*/
private $origin;
@@ -195,8 +202,9 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
* @var string
* @ORM\Column(type="string", nullable=true)
* @Groups({"read", "write"})
+ * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CONFIRMED})
*/
- private $intensity;
+ private $intensity = self::INTENSITY_OCCASIONAL;
/**
* @var Collection
@@ -210,6 +218,7 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
* inverseJoinColumns={@ORM\JoinColumn(name="scope_id", referencedColumnName="id")}
* )
* @Groups({"read"})
+ * @Assert\Count(min=1, groups={AccompanyingPeriod::STEP_CONFIRMED})
*/
private $scopes;
@@ -256,6 +265,7 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
* orphanRemoval=true
* )
* @Groups({"read"})
+ * @ResourceDuplicateCheck(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED, "Default", "default"})
*/
private $resources;
@@ -267,6 +277,7 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
* name="chill_person_accompanying_period_social_issues"
* )
* @Groups({"read"})
+ * @Assert\Count(min=1, groups={AccompanyingPeriod::STEP_CONFIRMED})
*/
private Collection $socialIssues;
@@ -606,6 +617,14 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
return $participation;
}
+ /**
+ * Remove Participation
+ */
+
+ public function removeParticipation(AccompanyingPeriodParticipation $participation)
+ {
+ $participation->setAccompanyingPeriod(null);
+ }
/**
* Remove Person
@@ -1115,4 +1134,17 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
return $centers ?? null;
}
+
+ public function getGroupSequence()
+ {
+ if($this->getStep() == self::STEP_DRAFT)
+ {
+ return [[self::STEP_DRAFT]];
+ }
+
+ if($this->getStep() == self::STEP_CONFIRMED)
+ {
+ return [[self::STEP_DRAFT, self::STEP_CONFIRMED]];
+ }
+ }
}
diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php
index a50e28621..48e532e10 100644
--- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php
+++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php
@@ -33,7 +33,13 @@ use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ORM\Entity
- * @ORM\Table(name="chill_person_accompanying_period_resource")
+ * @ORM\Table(
+ * name="chill_person_accompanying_period_resource",
+ * uniqueConstraints={
+ * @ORM\UniqueConstraint(name="person_unique", columns={"person_id", "accompanyingperiod_id"}),
+ * @ORM\UniqueConstraint(name="thirdparty_unique", columns={"thirdparty_id", "accompanyingperiod_id"})
+ * }
+ * )
* @DiscriminatorMap(typeProperty="type", mapping={
* "accompanying_period_resource"=Resource::class
* })
diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php
index c873e527a..f246c25bd 100644
--- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php
+++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php
@@ -134,4 +134,11 @@ class AccompanyingPeriodParticipation
{
return $this->endDate === null;
}
+
+ private function checkSameStartEnd()
+ {
+ if($this->endDate == $this->startDate) {
+ $this->accompanyingPeriod->removeParticipation($this);
+ }
+ }
}
diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/App.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/App.vue
index 9c65137bd..ff77f77ce 100644
--- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/App.vue
+++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/App.vue
@@ -16,16 +16,16 @@