diff --git a/src/Bundle/ChillPersonBundle/Controller/EmploymentStatusController.php b/src/Bundle/ChillPersonBundle/Controller/EmploymentStatusController.php new file mode 100644 index 000000000..aeefc55ce --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/EmploymentStatusController.php @@ -0,0 +1,26 @@ +addOrderBy('e.order', 'ASC'); + + return parent::orderQuery($action, $query, $request, $paginator); + } +} diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadEmploymentStatus.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadEmploymentStatus.php new file mode 100644 index 000000000..8b07a224b --- /dev/null +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadEmploymentStatus.php @@ -0,0 +1,45 @@ + ['fr' => 'Salarié·e']], + ['name' => ['fr' => 'Indépendant·e']], + ['name' => ['fr' => 'Chômeur·euse']], + ['name' => ['fr' => 'Bénéficiaire du CPAS']], + ['name' => ['fr' => 'Pensionsé·e']], + ]; + + foreach ($status as $val) { + $employmentStatus = (new EmploymentStatus()) + ->setName($val['name']) + ->setActive(true); + $manager->persist($employmentStatus); + } + + $manager->flush(); + } +} diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index e9e1b79b5..9320a1246 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -15,10 +15,13 @@ use Chill\MainBundle\DependencyInjection\MissingBundleException; use Chill\MainBundle\Security\Authorization\ChillExportVoter; use Chill\PersonBundle\Controller\AccompanyingPeriodCommentApiController; use Chill\PersonBundle\Controller\AccompanyingPeriodResourceApiController; +use Chill\PersonBundle\Controller\EmploymentStatusController; use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController; use Chill\PersonBundle\Controller\RelationApiController; use Chill\PersonBundle\Doctrine\DQL\AddressPart; use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\EmploymentStatus; +use Chill\PersonBundle\Form\EmploymentStatusType; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodResourceVoter; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; @@ -192,6 +195,28 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac ], ], ], + [ + 'class' => EmploymentStatus::class, + 'name' => 'employment_status', + 'base_path' => '/admin/employment', + 'base_role' => 'ROLE_ADMIN', + 'form_class' => EmploymentStatusType::class, + 'controller' => EmploymentStatusController::class, + 'actions' => [ + 'index' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillPerson/EmploymentStatus/index.html.twig', + ], + 'new' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillPerson/EmploymentStatus/new.html.twig', + ], + 'edit' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillPerson/EmploymentStatus/edit.html.twig', + ], + ], + ], [ 'class' => \Chill\PersonBundle\Entity\MaritalStatus::class, 'name' => 'person_marital-status', diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php index 97eb4c423..5f75f0d69 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php @@ -85,6 +85,7 @@ class Configuration implements ConfigurationInterface ->append($this->addFieldNode('number_of_children')) ->append($this->addFieldNode('acceptEmail')) ->append($this->addFieldNode('deathdate')) + ->append($this->addFieldNode('employment_status', 'hidden')) ->arrayNode('alt_names') ->defaultValue([]) ->arrayPrototype() diff --git a/src/Bundle/ChillPersonBundle/Entity/EmploymentStatus.php b/src/Bundle/ChillPersonBundle/Entity/EmploymentStatus.php new file mode 100644 index 000000000..08b1f45ac --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/EmploymentStatus.php @@ -0,0 +1,80 @@ + EmploymentStatus::class])] +#[ORM\Entity] +#[ORM\Table(name: 'chill_person_employment_status')] +class EmploymentStatus +{ + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] + private ?int $id = null; + + #[Serializer\Groups(['read', 'docgen:read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + #[Serializer\Context(['is-translatable' => true], groups: ['docgen:read'])] + private array $name = []; + + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] + private bool $active = true; + + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, name: 'ordering', nullable: true, options: ['default' => '0.0'])] + private float $order = 0; + + public function getId(): ?int + { + return $this->id; + } + + public function getActive(): ?bool + { + return $this->active; + } + + public function getName(): ?array + { + return $this->name; + } + + public function getOrder(): ?float + { + return $this->order; + } + + public function setActive(bool $active): self + { + $this->active = $active; + + return $this; + } + + public function setName(array $name): self + { + $this->name = $name; + + return $this; + } + + public function setOrder(float $order): self + { + $this->order = $order; + + return $this; + } +} diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index 74b4a2ef5..04607a0e0 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -311,6 +311,13 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI #[PhonenumberConstraint(type: 'mobile')] private ?PhoneNumber $mobilenumber = null; + /** + * The person's professional status. + */ + #[ORM\ManyToOne(targetEntity: EmploymentStatus::class)] + #[ORM\JoinColumn(nullable: true)] + private ?EmploymentStatus $employmentStatus = null; + /** * The person's nationality. */ @@ -1033,6 +1040,11 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this->fullnameCanonical; } + public function getEmploymentStatus(): ?EmploymentStatus + { + return $this->employmentStatus; + } + public function getGender(): ?Gender { return $this->gender; @@ -1551,6 +1563,13 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this; } + public function setEmploymentStatus(?EmploymentStatus $employmentStatus): self + { + $this->employmentStatus = $employmentStatus; + + return $this; + } + public function setGenderComment(CommentEmbeddable $genderComment): self { $this->genderComment = $genderComment; diff --git a/src/Bundle/ChillPersonBundle/Form/EmploymentStatusType.php b/src/Bundle/ChillPersonBundle/Form/EmploymentStatusType.php new file mode 100644 index 000000000..07fd00ca3 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Form/EmploymentStatusType.php @@ -0,0 +1,44 @@ +add('name', TranslatableStringFormType::class, [ + 'required' => true, + ]) + ->add('active', ChoiceType::class, [ + 'choices' => [ + 'Active' => true, + 'Inactive' => false, + ], + ]) + ->add('order', NumberType::class); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => EmploymentStatus::class, + ]); + } +} diff --git a/src/Bundle/ChillPersonBundle/Form/PersonType.php b/src/Bundle/ChillPersonBundle/Form/PersonType.php index 0f4fbd8e4..c03221f04 100644 --- a/src/Bundle/ChillPersonBundle/Form/PersonType.php +++ b/src/Bundle/ChillPersonBundle/Form/PersonType.php @@ -26,6 +26,7 @@ use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\PersonPhone; use Chill\PersonBundle\Form\Type\PersonAltNameType; use Chill\PersonBundle\Form\Type\PersonPhoneType; +use Chill\PersonBundle\Form\Type\PickEmploymentStatusType; use Chill\PersonBundle\Form\Type\PickGenderType; use Chill\PersonBundle\Form\Type\Select2MaritalStatusType; use Symfony\Component\Form\AbstractType; @@ -102,6 +103,11 @@ class PersonType extends AbstractType ->add('memo', ChillTextareaType::class, ['required' => false]); } + if ('visible' === $this->config['employment_status']) { + $builder + ->add('employmentStatus', PickEmploymentStatusType::class, ['required' => false]); + } + if ('visible' === $this->config['place_of_birth']) { $builder->add('placeOfBirth', TextType::class, [ 'required' => false, diff --git a/src/Bundle/ChillPersonBundle/Form/Type/PickEmploymentStatusType.php b/src/Bundle/ChillPersonBundle/Form/Type/PickEmploymentStatusType.php new file mode 100644 index 000000000..4dabcdaf6 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Form/Type/PickEmploymentStatusType.php @@ -0,0 +1,50 @@ +setDefault('label', 'Employment status') + ->setDefault( + 'choice_label', + fn (EmploymentStatus $employmentStatus): string => $this->translatableStringHelper->localize($employmentStatus->getName()) + ) + ->setDefault( + 'query_builder', + static fn (EntityRepository $er): QueryBuilder => $er->createQueryBuilder('c') + ->where('c.active = true') + ->orderBy('c.order'), + ) + ->setDefault('placeholder', $this->translatableStringHelper->localize(['Select an option…'])) + ->setDefault('class', EmploymentStatus::class); + } + + public function getParent() + { + return EntityType::class; + } +} diff --git a/src/Bundle/ChillPersonBundle/Menu/AdminPersonMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/AdminPersonMenuBuilder.php index c3d369f00..bfcb5e436 100644 --- a/src/Bundle/ChillPersonBundle/Menu/AdminPersonMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/AdminPersonMenuBuilder.php @@ -13,6 +13,7 @@ namespace Chill\PersonBundle\Menu; use Chill\MainBundle\Routing\LocalMenuBuilderInterface; use Knp\Menu\MenuItem; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; class AdminPersonMenuBuilder implements LocalMenuBuilderInterface @@ -22,9 +23,14 @@ class AdminPersonMenuBuilder implements LocalMenuBuilderInterface */ protected $authorizationChecker; - public function __construct(AuthorizationCheckerInterface $authorizationChecker) - { + private array $fields_visibility; + + public function __construct( + AuthorizationCheckerInterface $authorizationChecker, + ParameterBagInterface $parameterBag, + ) { $this->authorizationChecker = $authorizationChecker; + $this->fields_visibility = $parameterBag->get('chill_person.person_fields'); } public function buildMenu($menuId, MenuItem $menu, array $parameters) @@ -53,6 +59,12 @@ class AdminPersonMenuBuilder implements LocalMenuBuilderInterface 'route' => 'chill_crud_person_marital-status_index', ])->setExtras(['order' => 2030]); + if ('visible' == $this->fields_visibility['employment_status']) { + $menu->addChild('Employment status', [ + 'route' => 'chill_crud_employment_status_index', + ])->setExtras(['order' => 2035]); + } + $menu->addChild('person_admin.person_resource_kind', [ 'route' => 'chill_crud_person_resource-kind_index', ])->setExtras(['order' => 2040]); diff --git a/src/Bundle/ChillPersonBundle/Resources/views/EmploymentStatus/edit.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/EmploymentStatus/edit.html.twig new file mode 100644 index 000000000..4d55c480c --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/views/EmploymentStatus/edit.html.twig @@ -0,0 +1,11 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block title %} + {% include('@ChillMain/CRUD/_edit_title.html.twig') %} +{% endblock %} + +{% block admin_content %} + {% embed '@ChillMain/CRUD/_edit_content.html.twig' %} + {% block content_form_actions_save_and_show %}{% endblock %} + {% endembed %} +{% endblock admin_content %} diff --git a/src/Bundle/ChillPersonBundle/Resources/views/EmploymentStatus/index.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/EmploymentStatus/index.html.twig new file mode 100644 index 000000000..feb385280 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/views/EmploymentStatus/index.html.twig @@ -0,0 +1,42 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block admin_content %} + {% embed '@ChillMain/CRUD/_index.html.twig' %} + {% block table_entities_thead_tr %} +
diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20241121080214.php b/src/Bundle/ChillPersonBundle/migrations/Version20241121080214.php new file mode 100644 index 000000000..80fa77b34 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20241121080214.php @@ -0,0 +1,43 @@ +addSql('CREATE SEQUENCE chill_person_employment_status_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_person_employment_status (id INT NOT NULL, name JSON NOT NULL, active BOOLEAN NOT NULL, ordering DOUBLE PRECISION DEFAULT \'0.0\', PRIMARY KEY(id))'); + $this->addSql('ALTER TABLE chill_person_person ADD employmentstatus_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_person ADD CONSTRAINT FK_BF210A14BAE6AEE2 FOREIGN KEY (employmentstatus_id) REFERENCES chill_person_employment_status (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX BF210A14BAE6AEE2 ON chill_person_person (employmentstatus_id)'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP SEQUENCE chill_person_employment_status_id_seq CASCADE'); + $this->addSql('ALTER TABLE chill_person_person DROP CONSTRAINT FK_BF210A14BAE6AEE2'); + $this->addSql('ALTER TABLE chill_person_person DROP employmentstatus_id'); + $this->addSql('DROP TABLE chill_person_employment_status'); + } +} diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index fb084e2a6..2a9186ffc 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1,4 +1,5 @@ Edit: Modifier +Select an option…: Choisissez une option… 'First name': Prénom firstname: prénom firstName: prénom @@ -98,7 +99,7 @@ memo: Commentaire numberOfChildren: Nombre d'enfants contactInfo: Commentaire des contacts spokenLanguages: Langues parlées - +Employment status: Situation professionelle # dédoublonnage @@ -653,6 +654,12 @@ crud: add_new: Ajouter un nouveau title_new: Nouveau motif de clotûre title_edit: Modifier le motif de clotûre + employment_status: + index: + title: Situations professionelles + add_new: Ajouter une nouvelle + title_new: Ajouter une situation professionelle + title_edit: Modifier cette situation professionelle origin: index: title: Liste des origines de parcours