src/Model/Form/UserField.php line 76

Open in your IDE?
  1. <?php
  2. namespace App\Model\Form;
  3. use App\Constants\UserExtension;
  4. use App\Entity\BillingPoint;
  5. use App\Entity\PointConversionRate;
  6. use App\Entity\PointOfSale;
  7. use App\Entity\Programme;
  8. use App\Entity\Regate;
  9. use App\Entity\SaleOrderValidation;
  10. use App\Entity\Univers;
  11. use App\Entity\User;
  12. use App\Form\Type\Back\CoverageAreaDepartmentType;
  13. use App\Form\Type\Back\User\UserSubscriptionType;
  14. use App\Form\Type\Custom\RegateChoiceType;
  15. use App\Model\Form\Type\FormField;
  16. use App\Model\Form\Type\FormFieldEntity;
  17. use App\Model\Form\Type\FormFieldEntityParent;
  18. use App\Model\Form\Type\FormFieldEntityRegate;
  19. use App\Model\Form\Type\FormFieldRegateChoice;
  20. use App\Services\Common\CommunityService;
  21. use App\Services\DTV\YamlConfig\YamlReader;
  22. use DateTime;
  23. use Doctrine\ORM\EntityManagerInterface;
  24. use Doctrine\ORM\EntityRepository;
  25. use Exception;
  26. use Karser\Recaptcha3Bundle\Form\Recaptcha3Type;
  27. use Karser\Recaptcha3Bundle\Validator\Constraints\Recaptcha3;
  28. use Presta\ImageBundle\Form\Type\ImageType;
  29. use Psr\Log\LoggerInterface;
  30. use Symfony\Bridge\Doctrine\Form\ChoiceList\DoctrineChoiceLoader;
  31. use Symfony\Bridge\Doctrine\Form\Type\EntityType;
  32. use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
  33. use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  34. use Symfony\Component\Form\Extension\Core\Type\DateType;
  35. use Symfony\Component\Form\Extension\Core\Type\EmailType;
  36. use Symfony\Component\Form\Extension\Core\Type\NumberType;
  37. use Symfony\Component\Form\Extension\Core\Type\PasswordType;
  38. use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
  39. use Symfony\Component\Form\Extension\Core\Type\TextareaType;
  40. use Symfony\Component\Form\Extension\Core\Type\TextType;
  41. use Symfony\Component\Security\Core\Security;
  42. use Symfony\Component\Validator\Constraints\IsTrue;
  43. use Symfony\Contracts\Translation\TranslatorInterface;
  44. /**
  45. * Permet de générer les formType des User (Back, register, etc en passant une configuration dans le yaml
  46. * global.form_type.user
  47. */
  48. class UserField extends Field
  49. {
  50. private CommunityService $communityService;
  51. private EntityManagerInterface $em;
  52. /**
  53. * @param LoggerInterface $logger
  54. * @param Security $security
  55. * @param CommunityService $communityService
  56. * @param EntityManagerInterface $em
  57. * @param TranslatorInterface $translator
  58. */
  59. public function __construct(
  60. LoggerInterface $logger,
  61. Security $security,
  62. CommunityService $communityService,
  63. EntityManagerInterface $em,
  64. YamlReader $yamlReader,
  65. TranslatorInterface $translator
  66. )
  67. {
  68. parent::__construct( $logger, $security, $yamlReader);
  69. $this->communityService = $communityService;
  70. $this->em = $em;
  71. $this->translator = $translator;
  72. }
  73. /**
  74. * Permet de configurer dans quelle catégorie de configuration les champs sont accessibles
  75. *
  76. * @param $formType
  77. *
  78. * @return string[][]
  79. */
  80. public static function getAllFieldByFormType( $formType ): array
  81. {
  82. $fields = [
  83. 'email' => [ 'back_office', 'register', 'profile', 'membership_security' ],
  84. 'transactionalEmail' => [ 'back_office' ],
  85. 'civility' => [
  86. 'back_office',
  87. 'register',
  88. 'profile',
  89. 'membership_security',
  90. 'accept_cgu_first',
  91. ],
  92. 'firstName' => [
  93. 'back_office',
  94. 'register',
  95. 'profile',
  96. 'membership_security',
  97. 'accept_cgu_first',
  98. ],
  99. 'lastName' => [
  100. 'back_office',
  101. 'register',
  102. 'profile',
  103. 'membership_security',
  104. 'accept_cgu_first',
  105. ],
  106. 'phone' => [
  107. 'back_office',
  108. 'register',
  109. 'profile',
  110. 'membership_security',
  111. 'accept_cgu_first',
  112. ],
  113. 'avatarFile' => [
  114. 'back_office',
  115. 'profile',
  116. ],
  117. 'logoFile' => [
  118. 'back_office',
  119. 'profile',
  120. ],
  121. 'mobile' => [
  122. 'back_office',
  123. 'register',
  124. 'profile',
  125. 'membership_security',
  126. 'accept_cgu_first',
  127. ],
  128. 'canOrder' => [ 'back_office' ],
  129. 'roles' => [ 'back_office' ],
  130. 'createdAt' => [ 'back_office' ],
  131. 'regate' => [ 'back_office', 'register', 'profile' ],
  132. 'responsableRegate' => [ 'back_office' ],
  133. 'job' => [ 'back_office', 'register', 'accept_cgu_first' ],
  134. 'sapAccount' => [ 'back_office', 'register' ],
  135. 'company' => [
  136. 'back_office',
  137. 'register',
  138. 'profile',
  139. 'membership_security',
  140. 'accept_cgu_first',
  141. ],
  142. 'companySiret' => [
  143. 'back_office',
  144. 'register',
  145. 'profile',
  146. 'membership_security',
  147. 'accept_cgu_first',
  148. ],
  149. 'address1' => [
  150. 'back_office',
  151. 'register',
  152. 'profile',
  153. 'membership_security',
  154. 'accept_cgu_first',
  155. ],
  156. 'address2' => [
  157. 'back_office',
  158. 'register',
  159. 'profile',
  160. 'membership_security',
  161. 'accept_cgu_first',
  162. ],
  163. 'postcode' => [
  164. 'back_office',
  165. 'register',
  166. 'profile',
  167. 'membership_security',
  168. 'accept_cgu_first',
  169. ],
  170. 'city' => [
  171. 'back_office',
  172. 'register',
  173. 'profile',
  174. 'membership_security',
  175. 'accept_cgu_first',
  176. ],
  177. 'commercial' => [ 'back_office' ],
  178. 'coverageArea' => [ 'back_office' ],
  179. 'agency' => [ 'back_office', 'register' ],
  180. 'rrdiCode' => [ 'back_office', 'register' ],
  181. 'sellerCode' => [ 'back_office', 'register' ],
  182. 'customerId' => [ 'back_office', 'register' ],
  183. 'groupement' => [ 'back_office', 'register', 'accept_cgu_first' ],
  184. 'birthDate' => [ 'back_office', 'register', 'profile' ],
  185. 'birthPlace' => [ 'back_office', 'register', 'profile' ],
  186. 'programme' => [ 'back_office' ],
  187. 'password' => [ 'register' ],
  188. 'newsletter' => [ 'register' ],
  189. 'cguAt' => [ 'back_office', 'register', 'membership_security' ],
  190. 'companyIsOk' => [ 'register' ],
  191. 'message' => [ 'membership_security' ],
  192. 'saleOrderValidation' => [ 'back_office' ],
  193. 'universes' => [ 'back_office' ],
  194. 'billingPoint' => [ 'back_office' ],
  195. 'parents' => [ 'back_office' ],
  196. 'subscription' => [ 'back_office' ],
  197. 'pointExpirationDate' => [ 'back_office' ],
  198. 'pointSystem' => [ 'back_office' ],
  199. 'pointConversionRate' => [ 'back_office' ],
  200. 'pointOfSale' => [ 'back_office' ],
  201. 'internalIdentification1' => [ 'back_office' ],
  202. 'internalCode' => [ 'back_office, register' ],
  203. 'commitmentLevel' => [ 'back_office' ],
  204. 'potentialPoints' => [ 'back_office' ],
  205. 'status' => [ 'back_office' ],
  206. 'accountId' => [ 'back_office' ],
  207. ];
  208. return array_filter( $fields, static function ( $value ) use ( $formType ) {
  209. return in_array( $formType, $value, TRUE );
  210. } );
  211. }
  212. /**
  213. * Génère l'objet qui sera ensuite utilisé pour ajouter le formType avec sa configuration
  214. *
  215. * @param string $fieldName
  216. * @param array $fieldConfig
  217. * @param User|null $entity
  218. * @param string $roleContext
  219. *
  220. * @return FormField
  221. *
  222. * @throws Exception
  223. */
  224. public function getField( string $fieldName, array $fieldConfig = [], $entity = NULL, string $roleContext = 'ROLE_USER' ): FormField
  225. {
  226. /** @var User $currentUser */
  227. $currentUser = $this->security->getUser();
  228. $config = $this->getConfig( $fieldName, $fieldConfig, $entity, $roleContext );
  229. // on récupère l'instance du field
  230. $fieldType = $this->getFieldType( $config );
  231. // En fonction du formType, on utilise Formfield ou un enfant pour le configurer.
  232. // C'est ici qu'on peut override les actions en interceptant le type avant d'aller chercher la fonction par défaut
  233. switch ( $fieldType ) {
  234. case EntityType::class :
  235. // surcharge pour le champ Parents
  236. if ( $fieldName === 'parents' ) {
  237. $field = new FormFieldEntityParent( $this->communityService, $config[ 'entity_parents_options' ], $currentUser );
  238. } elseif ( $fieldName === 'regate' && isset( $config[ 'entity_regate_options' ] ) ) {
  239. $field = new FormFieldEntityRegate( $this->communityService, $config[ 'entity_regate_options' ], $currentUser );
  240. } else {
  241. $field = new FormFieldEntity();
  242. }
  243. break;
  244. case RegateChoiceType::class :
  245. $config[ 'choice_loader' ] = new DoctrineChoiceLoader(
  246. $this->em,
  247. Regate::class,
  248. $config[ 'query_builder' ],
  249. NULL // Group by
  250. );
  251. unset(
  252. $config[ 'query_builder' ],
  253. );
  254. $field = new FormFieldRegateChoice();
  255. break;
  256. default:
  257. $field = $this->createDefaultFormField( $fieldType, $config );
  258. }
  259. if ( isset( $config[ 'override_data' ] ) ) {
  260. $field->createProperty( 'data', $config[ 'override_data' ] );
  261. }
  262. if ( isset( $config[ 'readonly' ] ) ) {
  263. $field->createProperty( 'disabled', $config[ 'readonly' ] );
  264. }
  265. // On set les options sur l'objet FormField
  266. $this->setFormFieldOptions( $config, $fieldType, $field );
  267. return $field;
  268. }
  269. /**
  270. * @param string $fieldName
  271. * @param array $fieldConfig
  272. * @param $entity
  273. * @param string $roleContext
  274. *
  275. * @return array
  276. *
  277. * @throws Exception
  278. */
  279. protected function getConfig( string $fieldName, array $fieldConfig = [], $entity = NULL, string $roleContext = 'ROLE_USER' ): array
  280. {
  281. // Merge des configs par défaut et de ce qui se trouve dans le yaml
  282. return FormField::getFieldConfig( $this->defaultValue( $fieldName, $entity, $roleContext ), $fieldConfig );
  283. }
  284. /**
  285. * Tableau des valeurs par défaut de tous les champs configurable dans le yaml
  286. *
  287. * @param $field
  288. * @param User|null $entity Utilisateur
  289. * @param string $roleContext
  290. *
  291. * @return array|mixed
  292. *
  293. * @throws Exception
  294. */
  295. public function defaultValue( $field, $entity = NULL, string $roleContext = 'ROLE_USER' )
  296. {
  297. /** @var User $currentUser */
  298. $currentUser = $this->security->getUser();
  299. $defaultJobs = [
  300. 'Pas de fonction' => NULL,
  301. ];
  302. $roles = ( $entity === NULL || $entity->getId() === NULL ) ? [ $roleContext ] : $entity->getRoles();
  303. $jobs = array_merge(
  304. $defaultJobs,
  305. $this->communityService->getJobSlugAllowedToRoles( $roles )
  306. );
  307. // fin de modif
  308. // Hack pour filter les jobs quand un CDEF edit un user
  309. if ( $currentUser !== NULL && $currentUser->getJob() === 'CDEV' ) {
  310. $jobs = [];
  311. $jobSlugs = $this->communityService->getInferiorJobsOf( 'CDEV' );
  312. foreach ( $jobSlugs as $slug ) {
  313. $jobs[ $this->communityService->getJob( $slug )[ 'label' ] ] = $slug;
  314. }
  315. }
  316. $defaultData = [
  317. 'pointExpirationDate' => NULL,
  318. 'pointExpirationDateRelative' => 0,
  319. 'pointSystem' => NULL,
  320. 'internalIdentification1' => NULL,
  321. 'internalIdentification2' => NULL,
  322. 'internalIdentification3' => NULL,
  323. 'potentialPoints' => 0,
  324. 'socialSecurityNbr' => NULL,
  325. 'closeDateContract' => NULL
  326. ];
  327. if ( $entity instanceof User ) {
  328. if ( $entity->getExtensionBySlug( UserExtension::POINT_DATE_EXPIRATION ) ) {
  329. $defaultData[ 'pointExpirationDate' ] = new DateTime(
  330. $entity->getExtensionBySlug( UserExtension::POINT_DATE_EXPIRATION )
  331. );
  332. $defaultData[ 'pointExpirationDateRelative' ] = $entity->getExtensionBySlug( UserExtension::POINT_DATE_EXPIRATION );
  333. }
  334. if ( $entity->getExtensionBySlug( UserExtension::POINT_SYSTEM ) ) {
  335. $defaultData[ 'pointSystem' ] = $entity->getExtensionBySlug( UserExtension::POINT_SYSTEM );
  336. }
  337. if ( $entity->getExtensionBySlug( UserExtension::INTERNAL_IDENTIFICATION_1 ) ) {
  338. $defaultData[ 'internalIdentification1' ] = $entity->getExtensionBySlug(
  339. UserExtension::INTERNAL_IDENTIFICATION_1
  340. );
  341. }
  342. if ( $entity->getExtensionBySlug( UserExtension::INTERNAL_IDENTIFICATION_2 ) ) {
  343. $defaultData[ 'internalIdentification2' ] = $entity->getExtensionBySlug(
  344. UserExtension::INTERNAL_IDENTIFICATION_2
  345. );
  346. }
  347. if ( $entity->getExtensionBySlug( UserExtension::INTERNAL_IDENTIFICATION_3 ) ) {
  348. $defaultData[ 'internalIdentification3' ] = $entity->getExtensionBySlug(
  349. UserExtension::INTERNAL_IDENTIFICATION_3
  350. );
  351. }
  352. if ( $entity->getExtensionBySlug( UserExtension::POTENTIAL_POINTS ) ) {
  353. $defaultData[ 'potentialPoints' ] = $entity->getExtensionBySlug(
  354. UserExtension::POTENTIAL_POINTS
  355. );
  356. }
  357. if ( $entity->getExtensionBySlug( UserExtension::SOCIAL_SECURITY_NUMBER ) ) {
  358. $defaultData[ 'socialSecurityNbr' ] = $entity->getExtensionBySlug(
  359. UserExtension::SOCIAL_SECURITY_NUMBER
  360. );
  361. }
  362. if ( $entity->getExtensionBySlug( UserExtension::CLOSE_DATE_CONTRACT ) ) {
  363. $defaultData[ 'closeDateContract' ] = new DateTime($entity->getExtensionBySlug(
  364. UserExtension::CLOSE_DATE_CONTRACT
  365. ));
  366. }
  367. // @TODO : le test ci-dessous ne semble plus utilisé, à vérifier
  368. // if ($entity->getExtensionBySlug(UserExtension::QUOTAS_ORDERS)) {
  369. // $defaultData[ 'quotasOrders' ] = $entity->getExtensionBySlug(
  370. // UserExtension::QUOTAS_ORDERS
  371. // );
  372. // }
  373. }
  374. $fields = [
  375. 'avatarFile' => [
  376. 'formType' => ImageType::class,
  377. 'label' => $this->translator->trans('avatar'),
  378. 'help' => 'Dimensions minimales recommandées : 400px / 400px',
  379. 'required' => TRUE,
  380. 'enable_remote' => FALSE,
  381. 'upload_button_class' => 'btn btn-sm btn-primary',
  382. 'preview_width' => '100%',
  383. 'preview_height' => '100%',
  384. 'max_width' => 800,
  385. 'max_height' => 800,
  386. 'upload_quality' => 1,
  387. 'upload_mimetype' => 'image/jpg',
  388. 'aspect_ratios' => [
  389. [
  390. 'value' => 1,
  391. 'label' => '800/800',
  392. 'checked' => TRUE,
  393. ],
  394. ],
  395. 'description' => "Import d'une image pour un avatar si prévu",
  396. ],
  397. 'logoFile' => [
  398. 'formType' => ImageType::class,
  399. 'label' => $this->translator->trans('company_logo'),
  400. 'help' => 'Dimensions minimales recommandées : 400px / 400px',
  401. 'required' => TRUE,
  402. 'enable_remote' => FALSE,
  403. 'upload_button_class' => 'btn btn-sm btn-primary',
  404. 'preview_width' => '100%',
  405. 'preview_height' => '100%',
  406. 'max_width' => 400,
  407. 'max_height' => 400,
  408. 'upload_quality' => 1,
  409. 'upload_mimetype' => 'image/jpg',
  410. 'aspect_ratios' => [
  411. [
  412. 'value' => 1,
  413. 'label' => '400/400',
  414. 'checked' => TRUE,
  415. ],
  416. ],
  417. 'description' => "Import d'une image pour un logo si prévu",
  418. ],
  419. 'transactionalEmail' => [
  420. 'formType' => EmailType::class,
  421. 'label' => $this->translator->trans('secondary_email'),
  422. 'help' => 'Adresse email renseignée par l\'utilisateur en cas de pare-feu d\'enteprise. Cette adresse est utilisée pour les envois d\'email uniquement',
  423. 'required' => TRUE,
  424. 'attr' => [
  425. 'data-parsley-type' => 'email',
  426. ],
  427. 'description' => "Affiche le champ de l'email secondaire si actif sur la plateforme",
  428. ],
  429. 'civility' => [
  430. 'formType' => ChoiceType::class,
  431. 'label' => 'Civilité',
  432. 'choices' => [
  433. "Monsieur" => "M",
  434. "Madame" => "Mme",
  435. ],
  436. ],
  437. 'canOrder' => [
  438. 'formType' => CheckboxType::class,
  439. 'label' => 'Utilisateur peut commander',
  440. 'required' => FALSE,
  441. ],
  442. 'roles' => [
  443. 'formType' => ChoiceType::class,
  444. 'label' => $this->translator->trans('role'),
  445. // 'data' => ['Utilisateur' => 'ROLE_USER'],
  446. 'empty_data' => 'ROLE_USER',
  447. 'choices' => [
  448. 'Utilisateur' => 'ROLE_USER',
  449. 'Administrateur' => 'ROLE_ADMIN',
  450. ],
  451. 'multiple' => TRUE,
  452. 'required' => TRUE,
  453. ],
  454. 'regate' => [
  455. 'formType' => EntityType::class,
  456. 'label' => 'Régate',
  457. 'class' => Regate::class,
  458. 'placeholder' => "Choisir une régate",
  459. 'by_reference' => TRUE,
  460. 'multiple' => FALSE,
  461. 'attr' => [
  462. 'class' => '',
  463. ],
  464. 'entity_regate_options' => [
  465. 'method' => NULL,
  466. ],
  467. 'query_builder' => NULL,
  468. 'choice_label' => function ( Regate $regate ) {
  469. return $regate->getAffectation() . ' | ' . $regate->getName() . ' | ' . $regate->getLevel();
  470. },
  471. 'description' => "Lien avec une régate déjà existante dans la BDD, si des filtrages doivent s'appliquer, prévenir les dev",
  472. ],
  473. 'responsableRegate' => [
  474. 'formType' => EntityType::class,
  475. 'by_reference' => TRUE,
  476. 'label' => 'Responsable de la régate',
  477. 'class' => Regate::class,
  478. 'placeholder' => "Choisir une régate",
  479. 'choice_label' => function ( $regate ) {
  480. return $regate->getAffectation() . ' | ' . $regate->getName() . ' | ' . $regate->getLevel();
  481. },
  482. 'description' => "Défini la régate dont l'utilisateur est responsable. 1 utilisateur n'est responsable que d'une régate, une régate n'a qu'un seul responsable ",
  483. ],
  484. 'job' => [
  485. 'formType' => ChoiceType::class,
  486. 'label' => 'Fonction',
  487. 'placeholder' => 'Choisir',
  488. 'choices' => $jobs,
  489. 'description' => "Attribuer une fonction a un utilisateur d'après une liste déjà définie, compte pour les ACL",
  490. ],
  491. 'sapAccount' => [
  492. 'formType' => TextType::class,
  493. 'label' => 'Compte SAP',
  494. 'attr' => [
  495. 'data-parsley-type' => "digits",
  496. 'data-parsley-pattern-message' => "Doit contenir 6 ou 7 chiffres",
  497. 'minlength' => 6,
  498. 'maxlength' => 7,
  499. ],
  500. ],
  501. 'company' => [
  502. 'formType' => TextType::class,
  503. 'label' => 'Entreprise',
  504. ],
  505. 'companySiret' => [
  506. 'formType' => TextType::class,
  507. 'label' => 'N° Siret ou Siren',
  508. 'attr' => [
  509. 'data-parsley-type' => "digits",
  510. 'data-parsley-pattern-message' => "Doit contenir entre 9 et 14 chiffres",
  511. 'minlength' => 9,
  512. 'maxlength' => 14,
  513. ],
  514. 'description' => "de 9 à 14 chiffres",
  515. ],
  516. 'address1' => [
  517. 'formType' => TextareaType::class,
  518. 'label' => 'Adresse',
  519. 'description' => "Textarea par défaut",
  520. ],
  521. 'address2' => [
  522. 'formType' => TextareaType::class,
  523. 'label' => "Complément d'adresse",
  524. 'description' => "Textarea par défaut",
  525. ],
  526. 'postcode' => [
  527. 'formType' => TextType::class,
  528. 'label' => 'Code postal',
  529. 'attr' => [
  530. 'data-parsley-length' => '[4,5]',
  531. 'data-parsley-type' => 'number',
  532. 'maxlength' => '5',
  533. ],
  534. 'description' => "5 chiffres",
  535. ],
  536. 'city' => [
  537. 'formType' => TextType::class,
  538. 'label' => 'Ville',
  539. ],
  540. 'commercial' => [
  541. 'formType' => EntityType::class,
  542. 'by_reference' => TRUE,
  543. 'choice_label' => 'email',
  544. 'label' => 'Commercial',
  545. 'class' => User::class,
  546. 'query_builder' => function ( EntityRepository $er ) {
  547. return $er->createQueryBuilder( 'u' )
  548. ->where( '(u.roles LIKE \'%ROLE_COMMERCIAL%\' or u.job LIKE \'%commercial%\' or u.job LIKE \'%commercial_agent%\')' )
  549. ->orderBy( 'u.username', 'ASC' )
  550. ;
  551. },
  552. 'description' => "Relation avec un utilisateur existant portant le role de commercial (REHAU et DAIKIN uniquement)",
  553. ],
  554. 'coverageArea' => [
  555. 'formType' => CoverageAreaDepartmentType::class,
  556. 'label' => 'Zone de couverture',
  557. 'options' => [
  558. 'type' => [
  559. 'required' => TRUE,
  560. 'multiple' => TRUE,
  561. 'expanded' => TRUE,
  562. 'attr' => [
  563. 'class' => 'd-column',
  564. 'data-select-all' => TRUE,
  565. ],
  566. ],
  567. ],
  568. 'description' => "Choix d'une zone de couverture en selectionnant des départements uniquement",
  569. ],
  570. 'pointOfSale' => [
  571. 'formType' => EntityType::class,
  572. 'label' => 'Point de vente',
  573. "choice_label" => "name",
  574. 'by_reference' => TRUE,
  575. "class" => PointOfSale::class,
  576. 'query_builder' => function ( EntityRepository $er ) use ( $currentUser ) {
  577. $qb = $er->createQueryBuilder( 'pos' );
  578. if ( $currentUser->getJob() !== NULL ) {
  579. $qb->andWhere( 'pos.createdBy = :id' )
  580. ->setParameter( 'id', $currentUser->getId() )
  581. ;
  582. }
  583. $qb->orderBy( 'pos.name', 'ASC' );
  584. return $qb;
  585. },
  586. 'description' => "Attribut un point de vente existant dans la BDD",
  587. ],
  588. 'rrdiCode' => [
  589. 'formType' => TextType::class,
  590. 'label' => 'Code Rrdi',
  591. ],
  592. 'sellerCode' => [
  593. 'formType' => TextType::class,
  594. 'label' => 'Code vendeur',
  595. ],
  596. 'customerId' => [
  597. 'formType' => TextType::class,
  598. 'label' => 'Id Client',
  599. ],
  600. 'groupement' => [
  601. 'formType' => TextType::class,
  602. 'label' => 'Groupement',
  603. ],
  604. 'birthDate' => [
  605. 'formType' => DateType::class,
  606. 'label' => "Date de naissance",
  607. 'widget' => 'single_text',
  608. 'html5' => TRUE,
  609. 'attr' => [
  610. 'placeholder' => 'jj/mm/aaaa',
  611. 'autocomplete' => 'none',
  612. ],
  613. ],
  614. 'birthPlace' => [
  615. 'formType' => TextType::class,
  616. 'label' => 'Lieux de naissance',
  617. ],
  618. 'programme' => [
  619. 'formType' => EntityType::class,
  620. 'by_reference' => TRUE,
  621. 'label' => 'Programme',
  622. 'class' => Programme::class,
  623. 'placeholder' => "Choisir un programme",
  624. 'choice_label' => 'name',
  625. 'description' => "Attribut un programme existant dans la BDD",
  626. ],
  627. 'password' => [
  628. 'formType' => RepeatedType::class,
  629. 'type' => PasswordType::class,
  630. 'first_options' => [
  631. 'label' => 'Créer mon mot de passe',
  632. 'label_attr' => [
  633. 'class' => 'custom-account-label',
  634. ],
  635. 'attr' => [
  636. 'autocomplete' => 'new-password',
  637. 'data-parsley-error-message' => 'Le mot de passe doit contenir au moins 8 caractères, 1 majuscule, 1 minuscule, 1 chiffre et un caractère spécial @ $ ! % * ? &',
  638. 'data-parsley-pattern' => "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[^A-Za-z0-9]).{8,}$",
  639. 'class' => 'custom-account-input',
  640. ],
  641. ],
  642. 'second_options' => [
  643. 'label' => 'Confirmer mon mot de passe',
  644. 'label_attr' => [
  645. 'class' => 'custom-account-label',
  646. ],
  647. 'attr' => [
  648. 'class' => 'custom-account-input',
  649. ],
  650. ],
  651. 'invalid_message' => 'Les champs de mot de passe doivent correspondre.',
  652. // instead of being set onto the object directly,
  653. // this is read and encoded in the controller
  654. 'mapped' => FALSE,
  655. 'required' => TRUE,
  656. 'description' => "Affiche la modification du mot de passe",
  657. ],
  658. 'newsletter' => [
  659. 'formType' => CheckboxType::class,
  660. 'label' => 'Je souhaite recevoir la Newsletter',
  661. 'required' => FALSE,
  662. ],
  663. 'cguAt' => [
  664. 'formType' => CheckboxType::class,
  665. 'label' => "J'ai lu et j'accepte le <a href='/document/reglement' target='blank'>règlement de la plateforme</a> ",
  666. 'label_html' => TRUE,
  667. 'mapped' => FALSE,
  668. 'constraints' => [
  669. new IsTrue( [
  670. 'message' => 'Vous devez accepter le règlement de la plateforme continuer votre inscription',
  671. ] ),
  672. ],
  673. ],
  674. 'companyIsOk' => [
  675. 'formType' => CheckboxType::class,
  676. 'label' => "J'atteste être le dirigeant de l’entreprise, ou à défaut avoir informé le dirigeant de mon inscription au Club REHAU expert fenêtre",
  677. 'mapped' => FALSE,
  678. 'constraints' => [
  679. new IsTrue( [
  680. 'message' => 'Vous devez accepter pour continuer votre inscription',
  681. ] ),
  682. ],
  683. ],
  684. 'message' => [
  685. 'formType' => TextareaType::class,
  686. 'label' => 'Votre message',
  687. ],
  688. 'parents' => [
  689. 'formType' => EntityType::class,
  690. 'label' => 'Parents',
  691. 'class' => User::class,
  692. 'placeholder' => 'Choisir',
  693. 'by_reference' => FALSE,
  694. 'multiple' => TRUE,
  695. 'attr' => [
  696. 'class' => '',
  697. ],
  698. 'entity_parents_options' => [
  699. 'byRoles' => NULL,
  700. 'byJobsParentOf' => NULL,
  701. 'byJobs' => NULL,
  702. ],
  703. 'query_builder' => NULL,
  704. 'choice_label' => function ( User $user ) use ( $jobs ) {
  705. $job = array_search( $user->getJob(), $jobs, TRUE );
  706. if ( $job ) {
  707. return $user->getFullName() . " ($job)";
  708. }
  709. return $user->getFullName();
  710. },
  711. 'description' => "Défini une liste d'utilisateur existant comme parents",
  712. ],
  713. 'saleOrderValidation' => [
  714. 'formType' => EntityType::class,
  715. 'by_reference' => TRUE,
  716. 'label' => 'Seuil de validation',
  717. 'required' => FALSE,
  718. 'class' => SaleOrderValidation::class,
  719. 'choice_label' => function ( $saleOrderValidation ) {
  720. return $saleOrderValidation->getLevel() . ' | >= ' . $saleOrderValidation->getAmount();
  721. },
  722. 'description' => "Attribut un seuil de validation existant dans la BDD si la plateforme le demande",
  723. ],
  724. 'universes' => [
  725. 'formType' => EntityType::class,
  726. 'by_reference' => TRUE,
  727. 'label' => 'Univers',
  728. 'required' => FALSE,
  729. 'class' => Univers::class,
  730. 'multiple' => TRUE,
  731. 'expanded' => TRUE,
  732. 'choice_label' => function ( $univers ) {
  733. return $univers->getSlug() . ' | ' . $univers->getDescription();
  734. },
  735. 'description' => "Attribut un univers existant dans la BDD",
  736. ],
  737. 'billingPoint' => [
  738. 'formType' => EntityType::class,
  739. 'by_reference' => TRUE,
  740. 'label' => "Point de facturation",
  741. 'required' => TRUE,
  742. 'class' => BillingPoint::class,
  743. 'multiple' => FALSE,
  744. 'choice_label' => function ( $entity ) {
  745. return $entity->getName() . ' | ' . $entity->getCompany();
  746. },
  747. 'description' => "Attribut un point de facturation existant dans la BDD",
  748. ],
  749. 'subscription' => [
  750. 'formType' => UserSubscriptionType::class,
  751. 'label' => "Adhésion",
  752. 'description' => "Attribut une adhésion existante dans la BDD + date",
  753. ],
  754. 'pointExpirationDate' => [
  755. 'formType' => DateType::class,
  756. 'label' => "Date d'expiration des points",
  757. 'widget' => 'single_text',
  758. 'html5' => TRUE,
  759. 'attr' => [
  760. 'placeholder' => 'jj/mm/aaaa',
  761. 'autocomplete' => 'none',
  762. 'relative_data' => $defaultData[ 'pointExpirationDateRelative' ],
  763. ],
  764. 'override_data' => $defaultData[ 'pointExpirationDate' ],
  765. 'mapped' => FALSE,
  766. 'description' => "Défini une date d'expiration spécifique pour l'utilisateur (ALGOREL)",
  767. ],
  768. 'pointSystem' => [
  769. 'formType' => ChoiceType::class,
  770. 'label' => 'Type de système',
  771. 'choices' => [
  772. "Conversion du CA en points" => "ca",
  773. "Import de points simple" => "point",
  774. ],
  775. 'override_data' => $defaultData[ 'pointSystem' ],
  776. 'mapped' => FALSE,
  777. 'description' => "Défini un système de point spécifique pour l'utilisateur (ALGOREL)",
  778. ],
  779. 'internalIdentification1' => [
  780. 'formType' => TextType::class,
  781. 'label' => 'Code Identification',
  782. 'override_data' => $defaultData[ 'internalIdentification1' ],
  783. 'mapped' => FALSE,
  784. 'description' => "Défini un code spécifique au user, sans relation, (userExtension)",
  785. ],
  786. 'internalIdentification2' => [
  787. 'formType' => TextType::class,
  788. 'label' => 'Code Identification N°2',
  789. 'override_data' => $defaultData[ 'internalIdentification2' ],
  790. 'mapped' => FALSE,
  791. 'description' => "Défini un code spécifique au user, sans relation, (userExtension)",
  792. ],
  793. 'internalIdentification3' => [
  794. 'formType' => TextType::class,
  795. 'label' => 'Code Identification N°3',
  796. 'override_data' => $defaultData[ 'internalIdentification3' ],
  797. 'mapped' => FALSE,
  798. 'description' => "Défini un code spécifique au user, sans relation, (userExtension)",
  799. ],
  800. 'pointConversionRate' => [
  801. 'formType' => EntityType::class,
  802. 'label' => "Taux de conversion",
  803. 'by_reference' => TRUE,
  804. 'class' => PointConversionRate::class,
  805. 'placeholder' => 'Veuillez choisir une catégorie',
  806. 'required' => TRUE,
  807. 'query_builder' => function ( EntityRepository $er ) use ( $currentUser ) {
  808. return $er->createQueryBuilder( 'pcr' )
  809. ->andWhere( 'pcr.owner = :userId' )
  810. ->addOrderBy( 'pcr.label', 'ASC' )
  811. ->setParameter( 'userId', $currentUser->getId() )
  812. ;
  813. },
  814. 'choice_label' => function ( PointConversionRate $pcr ) {
  815. return $pcr->getLabel() . ' - ' . $pcr->getRate() . '€ = 1 point';
  816. },
  817. 'description' => "Attribut un taux de conversion existant dans la BDD (ALGOREL)",
  818. ],
  819. 'internalCode' => [
  820. 'formType' => TextType::class,
  821. 'label' => 'Code interne',
  822. ],
  823. 'captcha' => [
  824. 'formType' => Recaptcha3Type::class,
  825. 'mapped' => false,
  826. 'label' => false,
  827. 'required' => false
  828. ],
  829. 'commitmentLevel' => [
  830. 'formType' => ChoiceType::class,
  831. 'label' => "Niveaux d'engagement",
  832. ],
  833. 'potentialPoints' => [
  834. 'formType' => NumberType::class,
  835. 'label' => "Points potentiels",
  836. 'override_data' => $defaultData[ 'potentialPoints' ],
  837. 'mapped' => FALSE,
  838. 'description' => "Défini un montant de point potentiel, sans relation, informatif uniquement, (userExtension)",
  839. ],
  840. 'socialSecurityNbr' => [
  841. 'formType' => TextType::class,
  842. 'label' => 'N° de Sécurité sociale',
  843. 'override_data' => $defaultData[ 'socialSecurityNbr' ],
  844. 'mapped' => FALSE,
  845. 'description' => "Défini le numéro de sécu, (userExtension)",
  846. ],
  847. 'createdAt' => [
  848. 'formType' => DateType::class,
  849. 'label' => 'Date de création',
  850. 'widget' => 'single_text',
  851. 'html5' => TRUE,
  852. ],
  853. 'status' => [
  854. 'formType' => ChoiceType::class,
  855. 'mapped' => FALSE,
  856. 'label' => 'Status',
  857. 'multiple' => FALSE,
  858. 'override_data' => $entity !== NULL ? $entity->getStatus() : NULL,
  859. 'choices' => $entity instanceof User ? $this->getUserStatusChoices( $entity ) : [],
  860. 'description' => "Permet de modifier le statut du user en fonction du workflow",
  861. ],
  862. 'accountId' => [
  863. 'formType' => TextType::class,
  864. 'label' => 'Identifiant unique',
  865. ],
  866. /// MGL
  867. 'codePartenaire' => [
  868. 'formType' => TextType::class,
  869. 'label' => 'Code partenaire',
  870. ],
  871. /// myrcmreward
  872. 'closeDateContract' => [
  873. 'formType' => DateType::class,
  874. 'label' => 'Date de fin de mission',
  875. 'widget' => 'single_text',
  876. 'html5' => true,
  877. 'mapped' => false,
  878. 'override_data' => $defaultData[ 'closeDateContract' ]
  879. ],
  880. 'sendCguBySms' => [
  881. 'formType' => CheckboxType::class,
  882. 'label' => 'Recevoir le mail de bienvenue par sms ?',
  883. 'required' => FALSE,
  884. 'mapped' => false,
  885. ],
  886. ];
  887. if ( !isset( $fields[ $field ] ) && parent::defaultValue( $field ) !== [] ) {
  888. return parent::defaultValue( $field, $entity );
  889. }
  890. // retourne le tableau entier ou juste le champ demandé.
  891. try {
  892. $fields[ $field ] = $this->addLabelHtml( $fields[ $field ] );
  893. return $field === 'all' ? $fields : $fields[ $field ];
  894. }
  895. catch ( Exception $e ) {
  896. $this->logger->error( $e->getMessage() . ' : ' . $e->getTraceAsString() );
  897. throw new Exception( 'Le champ "' . $field . '" n\'existe pas dans UserField.php' );
  898. }
  899. }
  900. /**
  901. * @param User $user
  902. *
  903. * @return array
  904. */
  905. private function getUserStatusChoices( User $user ): array
  906. {
  907. $defaultStatus = [
  908. 'register_pending' => 'Attente d\'inscription',
  909. 'admin_pending' => 'Attente validation par admin',
  910. 'cgu_pending' => 'En attente validation CGU',
  911. 'cgu_declined' => 'CGU refusées',
  912. 'enabled' => 'Actif',
  913. 'disabled' => 'Désactivé',
  914. 'archived' => 'Archivé',
  915. 'deleted' => 'Supprimer définitivement !',
  916. ];
  917. $status = [];
  918. // user pas encore créé
  919. if ( $user->getId() === NULL ) {
  920. $status = [ 'admin_pending', 'cgu_pending', 'disabled' ];
  921. } else {
  922. switch ( $user->getStatus() ) {
  923. case 'register_pending' :
  924. $status = [ 'register_pending', 'admin_pending', 'cgu_pending' ];
  925. break;
  926. case 'admin_pending' :
  927. $status = [ 'admin_pending', 'cgu_pending', 'deleted' ];
  928. $defaultStatus[ 'cgu_pending' ] = 'Accepter Inscription';
  929. $defaultStatus[ 'deleted' ] = 'Refuser Inscription';
  930. break;
  931. case 'cgu_pending' :
  932. $status = [ 'admin_pending', 'cgu_pending', 'disabled' ];
  933. break;
  934. case 'cgu_declined' :
  935. $status = [ 'cgu_declined', 'cgu_pending', 'deleted' ];
  936. break;
  937. case 'enabled' :
  938. $status = [ 'archived', 'disabled', 'enabled' ];
  939. break;
  940. case 'disabled' :
  941. $status = [ 'disabled', 'enabled', 'cgu_pending', 'archived' ];
  942. break;
  943. case 'archived' :
  944. $status = [ 'archived', 'cgu_pending', 'deleted' ];
  945. break;
  946. case 'deleted' :
  947. $status = [ 'deleted' ];
  948. break;
  949. }
  950. }
  951. $choices = [];
  952. foreach ( $status as $s ) {
  953. $choices[ $defaultStatus[ $s ] ] = $s;
  954. }
  955. return $choices;
  956. }
  957. }