diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5f22e6dd9..467ed8037 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to
## Unreleased
+* [activity] add custom validation on the Activity class, based on what is required from the ActivityType (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/188)
* [main] translate multiselect messages when selecting/creating address
* [main] set the coordinates of the city when creating a new address OR choosing "pas d'adresse complète"
* Use the user.label in accompanying course banner, instead of username;
diff --git a/phpstan-critical.neon b/phpstan-critical.neon
index 6147f2022..b214654bf 100644
--- a/phpstan-critical.neon
+++ b/phpstan-critical.neon
@@ -70,11 +70,6 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Serializer/Normalizer/MembersEditorNormalizer.php
- -
- message: "#^Undefined variable\\: \\$value$#"
- count: 1
- path: src/Bundle/ChillPersonBundle/Validator/Constraints/AccompanyingPeriod/LocationValidityValidator.php
-
-
message: "#^Undefined variable\\: \\$choiceSlug$#"
count: 1
diff --git a/src/Bundle/ChillActivityBundle/Controller/ActivityController.php b/src/Bundle/ChillActivityBundle/Controller/ActivityController.php
index 0c43c4d91..0f725c2b3 100644
--- a/src/Bundle/ChillActivityBundle/Controller/ActivityController.php
+++ b/src/Bundle/ChillActivityBundle/Controller/ActivityController.php
@@ -408,7 +408,7 @@ final class ActivityController extends AbstractController
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
- $defaultLocationId = $this->getUser()->getCurrentLocation()->getId();
+ $defaultLocation = $this->getUser()->getCurrentLocation();
return $this->render($view, [
'person' => $person,
@@ -416,7 +416,7 @@ final class ActivityController extends AbstractController
'entity' => $entity,
'form' => $form->createView(),
'activity_json' => $activity_array,
- 'default_location_id' => $defaultLocationId,
+ 'default_location' => $defaultLocation,
]);
}
diff --git a/src/Bundle/ChillActivityBundle/Controller/AdminActivityTypeController.php b/src/Bundle/ChillActivityBundle/Controller/AdminActivityTypeController.php
index 140a0b855..81c978bf2 100644
--- a/src/Bundle/ChillActivityBundle/Controller/AdminActivityTypeController.php
+++ b/src/Bundle/ChillActivityBundle/Controller/AdminActivityTypeController.php
@@ -23,6 +23,7 @@ class AdminActivityTypeController extends CRUDController
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
{
/** @var \Doctrine\ORM\QueryBuilder $query */
- return $query->orderBy('e.ordering', 'ASC');
+ return $query->orderBy('e.ordering', 'ASC')
+ ->addOrderBy('e.id', 'ASC');
}
}
diff --git a/src/Bundle/ChillActivityBundle/Entity/Activity.php b/src/Bundle/ChillActivityBundle/Entity/Activity.php
index 85abed5e5..c63ce90f7 100644
--- a/src/Bundle/ChillActivityBundle/Entity/Activity.php
+++ b/src/Bundle/ChillActivityBundle/Entity/Activity.php
@@ -9,6 +9,7 @@
namespace Chill\ActivityBundle\Entity;
+use Chill\ActivityBundle\Validator\Constraints as ActivityValidator;
use Chill\DocStoreBundle\Entity\Document;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
@@ -41,6 +42,7 @@ use Symfony\Component\Serializer\Annotation\SerializedName;
* @DiscriminatorMap(typeProperty="type", mapping={
* "activity": Activity::class
* })
+ * @ActivityValidator\ActivityValidity
*/
/*
@@ -202,7 +204,9 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
public function addPerson(?Person $person): self
{
if (null !== $person) {
- $this->persons[] = $person;
+ if (!$this->persons->contains($person)) {
+ $this->persons[] = $person;
+ }
}
return $this;
@@ -236,7 +240,9 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
public function addThirdParty(?ThirdParty $thirdParty): self
{
if (null !== $thirdParty) {
- $this->thirdParties[] = $thirdParty;
+ if (!$this->thirdParties->contains($thirdParty)) {
+ $this->thirdParties[] = $thirdParty;
+ }
}
return $this;
@@ -245,7 +251,9 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
public function addUser(?User $user): self
{
if (null !== $user) {
- $this->users[] = $user;
+ if (!$this->users->contains($user)) {
+ $this->users[] = $user;
+ }
}
return $this;
diff --git a/src/Bundle/ChillActivityBundle/Entity/ActivityType.php b/src/Bundle/ChillActivityBundle/Entity/ActivityType.php
index 0e9b1150a..4cb4250b5 100644
--- a/src/Bundle/ChillActivityBundle/Entity/ActivityType.php
+++ b/src/Bundle/ChillActivityBundle/Entity/ActivityType.php
@@ -12,6 +12,7 @@ namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use InvalidArgumentException;
use Symfony\Component\Serializer\Annotation\Groups;
+use Symfony\Component\Validator\Constraints as Assert;
/**
* Class ActivityType.
@@ -29,11 +30,13 @@ class ActivityType
public const FIELD_REQUIRED = 2;
/**
+ * @deprecated not in use
* @ORM\Column(type="string", nullable=false, options={"default": ""})
*/
private string $accompanyingPeriodLabel = '';
/**
+ * @deprecated not in use
* @ORM\Column(type="smallint", nullable=false, options={"default": 1})
*/
private int $accompanyingPeriodVisible = self::FIELD_INVISIBLE;
@@ -195,16 +198,21 @@ class ActivityType
/**
* @ORM\Column(type="smallint", nullable=false, options={"default": 1})
+ * @Assert\EqualTo(propertyPath="socialIssuesVisible", message="This parameter must be equal to social issue parameter")
*/
private int $socialActionsVisible = self::FIELD_INVISIBLE;
/**
* @ORM\Column(type="string", nullable=false, options={"default": ""})
+ *
+ * @deprecated not in use
*/
private string $socialDataLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default": 1})
+ *
+ * @deprecated not in use
*/
private int $socialDataVisible = self::FIELD_INVISIBLE;
@@ -260,16 +268,6 @@ class ActivityType
*/
private int $userVisible = self::FIELD_REQUIRED;
- public function getAccompanyingPeriodLabel(): string
- {
- return $this->accompanyingPeriodLabel;
- }
-
- public function getAccompanyingPeriodVisible(): int
- {
- return $this->accompanyingPeriodVisible;
- }
-
/**
* Get active
* return true if the type is active.
@@ -446,16 +444,6 @@ class ActivityType
return $this->socialActionsVisible;
}
- public function getSocialDataLabel(): string
- {
- return $this->socialDataLabel;
- }
-
- public function getSocialDataVisible(): int
- {
- return $this->socialDataVisible;
- }
-
public function getSocialIssuesLabel(): ?string
{
return $this->socialIssuesLabel;
@@ -537,20 +525,6 @@ class ActivityType
return self::FIELD_INVISIBLE !== $this->{$property};
}
- public function setAccompanyingPeriodLabel(string $accompanyingPeriodLabel): self
- {
- $this->accompanyingPeriodLabel = $accompanyingPeriodLabel;
-
- return $this;
- }
-
- public function setAccompanyingPeriodVisible(int $accompanyingPeriodVisible): self
- {
- $this->accompanyingPeriodVisible = $accompanyingPeriodVisible;
-
- return $this;
- }
-
/**
* Set active
* set to true if the type is active.
@@ -768,20 +742,6 @@ class ActivityType
return $this;
}
- public function setSocialDataLabel(string $socialDataLabel): self
- {
- $this->socialDataLabel = $socialDataLabel;
-
- return $this;
- }
-
- public function setSocialDataVisible(int $socialDataVisible): self
- {
- $this->socialDataVisible = $socialDataVisible;
-
- return $this;
- }
-
public function setSocialIssuesLabel(string $socialIssuesLabel): self
{
$this->socialIssuesLabel = $socialIssuesLabel;
diff --git a/src/Bundle/ChillActivityBundle/Form/ActivityTypeType.php b/src/Bundle/ChillActivityBundle/Form/ActivityTypeType.php
index 300be5c4c..682d73aaf 100644
--- a/src/Bundle/ChillActivityBundle/Form/ActivityTypeType.php
+++ b/src/Bundle/ChillActivityBundle/Form/ActivityTypeType.php
@@ -56,7 +56,7 @@ class ActivityTypeType extends AbstractType
'persons', 'user', 'date', 'place', 'persons',
'thirdParties', 'durationTime', 'travelTime', 'attendee',
'reasons', 'comment', 'sentReceived', 'documents',
- 'emergency', 'accompanyingPeriod', 'socialData', 'users',
+ 'emergency', 'socialIssues', 'socialActions', 'users',
];
foreach ($fields as $field) {
diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/App.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/App.vue
index 52454c2f7..2fb9d022d 100644
--- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/App.vue
+++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/App.vue
@@ -1,7 +1,7 @@
-
-
-
+
+
+
{{ encore_entry_script_tags('vue_activity') }}
{% endblock %}
diff --git a/src/Bundle/ChillActivityBundle/Validator/Constraints/ActivityValidity.php b/src/Bundle/ChillActivityBundle/Validator/Constraints/ActivityValidity.php
new file mode 100644
index 000000000..6164c3c5d
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Validator/Constraints/ActivityValidity.php
@@ -0,0 +1,42 @@
+getActivityType()->getPersonsVisible() === 2 && count($activity->getPersons()) === 0) {
+ $this->context
+ ->buildViolation($constraint->noPersonsMessage)
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getUsersVisible() === 2 && count($activity->getUsers()) === 0) {
+ $this->context
+ ->buildViolation($constraint->noUsersMessage)
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getThirdPartiesVisible() === 2 && count($activity->getThirdParties()) === 0) {
+ $this->context
+ ->buildViolation($constraint->noThirdPartiesMessage)
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getUserVisible() === 2 && null === $activity->getUser()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('user'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getDateVisible() === 2 && null === $activity->getDate()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('date'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getLocationVisible() === 2 && null === $activity->getLocation()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('location'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getDurationTimeVisible() === 2 && null === $activity->getDurationTime()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('duration time'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getTravelTimeVisible() === 2 && null === $activity->getTravelTime()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('travel time'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getAttendeeVisible() === 2 && null === $activity->getAttendee()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('attendee'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getReasonsVisible() === 2 && null === $activity->getReasons()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('reasons'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getCommentVisible() === 2 && null === $activity->getComment()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('comment'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getSentReceivedVisible() === 2 && null === $activity->getSentReceived()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('sent/received'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getDocumentsVisible() === 2 && null === $activity->getDocuments()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('document'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getEmergencyVisible() === 2 && null === $activity->getEmergency()) {
+ $this->context
+ ->buildViolation($constraint->makeIsRequiredMessage('emergency'))
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getSocialIssuesVisible() === 2 && $activity->getSocialIssues()->count() === 0) {
+ $this->context
+ ->buildViolation($constraint->socialIssuesMessage)
+ ->addViolation();
+ }
+
+ if ($activity->getActivityType()->getSocialActionsVisible() === 2 && $activity->getSocialActions()->count() === 0) {
+ $this->context
+ ->buildViolation($constraint->socialActionsMessage)
+ ->addViolation();
+ }
+ }
+}
diff --git a/src/Bundle/ChillActivityBundle/config/services.yaml b/src/Bundle/ChillActivityBundle/config/services.yaml
index 4e93e38be..1ca413f0e 100644
--- a/src/Bundle/ChillActivityBundle/config/services.yaml
+++ b/src/Bundle/ChillActivityBundle/config/services.yaml
@@ -27,3 +27,8 @@ services:
Chill\ActivityBundle\Repository\:
resource: '../Repository/'
+
+ Chill\ActivityBundle\Validator\Constraints\:
+ autowire: true
+ autoconfigure: true
+ resource: '../Validator/Constraints/'
diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml
index d0c3ddc6d..959eee233 100644
--- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml
@@ -139,34 +139,40 @@ ActivityReasonCategory is inactive and won't be proposed: La catégorie est inac
# activity type type admin
ActivityType list: Types d'activités
Create a new activity type: Créer un nouveau type d'activité
-Persons visible: Visibilté du champ Personnes
+Persons visible: Visibilité du champ Personnes
Persons label: Libellé du champ Personnes
-User visible: Visibilté du champ Utilisateur
+User visible: Visibilité du champ Utilisateur
User label: Libellé du champ Utilisateur
-Date visible: Visibilté du champ Date
+Date visible: Visibilité du champ Date
Date label: Libellé du champ Date
-Place visible: Visibilté du champ Lieu
+Place visible: Visibilité du champ Lieu
Place label: Libellé du champ Lieu
-Third parties visible: Visibilté du champ Tiers
+Third parties visible: Visibilité du champ Tiers
Third parties label: Libellé du champ Tiers
-Duration time visible: Visibilté du champ Durée
+Duration time visible: Visibilité du champ Durée
Duration time label: Libellé du champ Durée
-Travel time visible: Visibilté du champ Durée de déplacement
+Travel time visible: Visibilité du champ Durée de déplacement
Travel time label: Libellé du champ Durée de déplacement
-Attendee visible: Visibilté du champ Présence de l'usager
+Attendee visible: Visibilité du champ Présence de l'usager
Attendee label: Libellé du champ Présence de l'usager
-Reasons visible: Visibilté du champ Sujet
+Reasons visible: Visibilité du champ Sujet
Reasons label: Libellé du champ Sujet
-Comment visible: Visibilté du champ Commentaire
+Comment visible: Visibilité du champ Commentaire
Comment label: Libellé du champ Commentaire
-Emergency visible: Visibilté du champ Urgent
+Emergency visible: Visibilité du champ Urgent
Emergency label: Libellé du champ Urgent
-Accompanying period visible: Visibilté du champ Période d'accompagnement
+Accompanying period visible: Visibilité du champ Période d'accompagnement
Accompanying period label: Libellé du champ Période d'accompagnement
-Social data visible: Visibilté du champ Données sociales
-Social data label: Libellé du champ Données sociales
-Users visible: Visibilté du champ Utilisateurs
+Social issues visible: Visibilité du champ Problématiques sociales
+Social issues label: Libellé du champ Problématiques sociales
+Social actions visible: Visibilité du champ Action sociale
+Social actions label: Libellé du champ Action sociale
+Users visible: Visibilité du champ Utilisateurs
Users label: Libellé du champ Utilisateurs
+Sent received visible: Visibilité du champ Entrant / Sortant
+Sent received label: Libellé du champ Entrant / Sortant
+Documents visible: Visibilité du champ Documents
+Documents label: Libellé du champ Documents
# activity type category admin
ActivityTypeCategory list: Liste des catégories des types d'activité
diff --git a/src/Bundle/ChillActivityBundle/translations/validators.fr.yml b/src/Bundle/ChillActivityBundle/translations/validators.fr.yml
index edda0b67b..072ac55d2 100644
--- a/src/Bundle/ChillActivityBundle/translations/validators.fr.yml
+++ b/src/Bundle/ChillActivityBundle/translations/validators.fr.yml
@@ -1,2 +1,22 @@
The reasons's level should not be empty: Le niveau du sujet ne peut pas être vide
At least one reason must be choosen: Au moins un sujet doit être choisi
+For this type of activity, you must add at least one person: Pour ce type d'activité, vous devez ajouter au moins un usager
+For this type of activity, you must add at least one user: Pour ce type d'activité, vous devez ajouter au moins un utilisateur
+For this type of activity, you must add at least one third party: Pour ce type d'activité, vous devez ajouter au moins un tiers
+For this type of activity, user is required: Pour ce type d'activité, l'utilisateur est requis
+For this type of activity, date is required: Pour ce type d'activité, la date est requise
+For this type of activity, location is required: Pour ce type d'activité, la localisation est requise
+For this type of activity, attendee is required: Pour ce type d'activité, le champ "Présence de la personne" est requis
+For this type of activity, duration time is required: Pour ce type d'activité, la durée est requise
+For this type of activity, travel time is required: Pour ce type d'activité, la durée du trajet est requise
+For this type of activity, reasons is required: Pour ce type d'activité, le champ "sujet" est requis
+For this type of activity, comment is required: Pour ce type d'activité, un commentaire est requis
+For this type of activity, sent/received is required: Pour ce type d'activité, le champ Entrant/Sortant est requis
+For this type of activity, document is required: Pour ce type d'activité, un document est requis
+For this type of activity, emergency is required: Pour ce type d'activité, le champ "Urgent" est requis
+For this type of activity, accompanying period is required: Pour ce type d'activité, le parcours d'accompagnement est requis
+For this type of activity, you must add at least one social issue: Pour ce type d'activité, vous devez ajouter au moins une problématique sociale
+For this type of activity, you must add at least one social action: Pour ce type d'activité, vous devez indiquez au moins une action sociale
+
+# admin
+This parameter must be equal to social issue parameter: Ce paramètre doit être égal au paramètre "Visibilité du champs Problématiques sociales"
diff --git a/src/Bundle/ChillPersonBundle/Validator/Constraints/AccompanyingPeriod/LocationValidityValidator.php b/src/Bundle/ChillPersonBundle/Validator/Constraints/AccompanyingPeriod/LocationValidityValidator.php
index 167553909..275ab281f 100644
--- a/src/Bundle/ChillPersonBundle/Validator/Constraints/AccompanyingPeriod/LocationValidityValidator.php
+++ b/src/Bundle/ChillPersonBundle/Validator/Constraints/AccompanyingPeriod/LocationValidityValidator.php
@@ -32,7 +32,7 @@ class LocationValidityValidator extends ConstraintValidator
}
if (!$period instanceof AccompanyingPeriod) {
- throw new UnexpectedValueException($value, AccompanyingPeriod::class);
+ throw new UnexpectedValueException($period, AccompanyingPeriod::class);
}
if ($period->getLocationStatus() === 'person') {