src\Controller\Admin\UserController.php line 612

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Admin;
  3. use App\Entity\Admin\Produit;
  4. use App\Entity\Admin\User;
  5. use App\Entity\Admin\UserDocument;
  6. use App\Form\Admin\UserType;
  7. use App\Form\Admin\UserMassType;
  8. use App\Manager\Admin\BranchManager;
  9. use App\Manager\Admin\BranchProduitManager;
  10. use App\Manager\Admin\BranchTypeManager;
  11. use App\Manager\Admin\DepartmentManager;
  12. use App\Manager\Admin\DroitManager;
  13. use App\Manager\Admin\PerimetreManager;
  14. use App\Manager\Admin\PerimetreSystemManager;
  15. use App\Manager\Admin\ProduitManager;
  16. use App\Manager\Admin\ProprietaireManager;
  17. use App\Manager\Admin\UserFonctionnaliteManager;
  18. use App\Manager\Admin\UserManager;
  19. use App\Manager\Admin\UserProduitManager;
  20. use App\Manager\Admin\UserProfilManager;
  21. use App\Manager\Admin\UserProprietaireManager;
  22. use App\Manager\Admin\UserDocumentManager;
  23. use App\Manager\Nose\PrestationManager;
  24. use App\Manager\Admin\ChampPersoManager;
  25. use App\Manager\Admin\ChampPersoValueManager;
  26. use App\Manager\Admin\DepartmentProduitManager;
  27. use App\Repository\Admin\ProfilRepository;
  28. use App\Service\FileService;
  29. use App\Service\FilterService;
  30. use App\Service\MessageManager;
  31. use App\Service\ProduitApiConnector;
  32. use App\Service\Utilities;
  33. use Doctrine\DBAL\Connection;
  34. use Doctrine\Persistence\ManagerRegistry;
  35. use Exception;
  36. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  37. use Symfony\Component\HttpFoundation\JsonResponse;
  38. use Symfony\Component\HttpFoundation\RedirectResponse;
  39. use Symfony\Component\HttpFoundation\Request;
  40. use Symfony\Component\HttpFoundation\Response;
  41. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  42. use Symfony\Component\HttpFoundation\File\UploadedFile;
  43. use Symfony\Contracts\Cache\CacheInterface;
  44. use Symfony\Contracts\Cache\ItemInterface;
  45. use Symfony\Component\Routing\Annotation\Route;
  46. /**
  47.  * Class UserController
  48.  * @package App\Controller\Admin
  49.  * @Route("/admin/user", name="admin_user_")
  50.  */
  51. class UserController extends AbstractController
  52. {
  53.     private Connection $abiConnection;
  54.     private string $droit = "UTILISATEUR";
  55.     public function __construct(
  56.         ManagerRegistry $managerRegistry,
  57.         private readonly BranchManager $branchManager,
  58.         private readonly BranchTypeManager $branchTypeManager,
  59.         private readonly ChampPersoManager $champPersoManager,
  60.         private readonly ChampPersoValueManager $champPersoValueManager,
  61.         private readonly DepartmentManager $departmentManager,
  62.         private readonly DroitManager $droitManager,
  63.         private readonly MessageManager $messageManager,
  64.         private readonly PerimetreManager $perimetreManager,
  65.         private readonly PerimetreSystemManager $perimetreSystemManager,
  66.         private readonly ProduitManager $produitManager,
  67.         private readonly PrestationManager $prestationManager,
  68.         private readonly ProprietaireManager $proprietaireManager,
  69.         private readonly UserManager $userManager,
  70.         private readonly UserFonctionnaliteManager $userFonctionnaliteManager,
  71.         private readonly UserProduitManager $userProduitManager,
  72.         private readonly UserProfilManager $userProfilManager,
  73.         private readonly UserProprietaireManager $userProprietaireManager,
  74.         private readonly FileService $fileService,
  75.         private readonly CacheInterface $cache
  76.     ) {
  77.         $this->abiConnection = $managerRegistry->getConnection('abi');
  78.     }
  79.     /**
  80.      * @Route("/home/{page}/{nbOfResults}", name="home", defaults={"page" = 1, "nbOfResults" = 10})
  81.      */
  82.     public function index(Request $request, FilterService  $filterService, int $page, int $nbOfResults): Response
  83.     {
  84.         $this->droitManager->verifyUserRight($this->droit, "R");
  85.         [$success, $error, $filters] = $filterService->filterWithRequest($request, ['User'], $this->userManager->getRepository(), $page, $nbOfResults, false);
  86.         $users = $filterService->getItems();
  87.         /*foreach ($users as $user) {
  88.             $produitsTmp = $this->produitManager->getRepository()->getProduitByUser($user);
  89.             $user->produits = [];
  90.             if ($produitsTmp) {
  91.                 foreach ($produitsTmp as $pt) {
  92.                     if (!isset($user->produits[$pt['id']])) {
  93.                         $user->produits[$pt['id']] = ['name' => $pt['name'], 'id' => $pt['id'], 'fullname' => $pt['name'] . ' ()'];
  94.                     }
  95.                     $user->produits[$pt['id']]['fullname'] = str_replace('(, ', '(', str_replace(')', (', ' . $pt['profil'] . ')'), $user->produits[$pt['id']]['fullname']));
  96.                 }
  97.                 $user->produits = array_values($user->produits);
  98.             }
  99.         }*/
  100.         $form = $this->createForm(UserMassType::class);
  101.         [$produits, $services, $branchs, $branch_types, $proprietaires] = $this->cache->get('user_filtres', function (ItemInterface $item) {
  102.             $item->expiresAfter(300);
  103.             return [
  104.                 $this->produitManager->getRepository()->findAll(),
  105.                 $this->departmentManager->getRepository()->findBy(['deletedAt' => null], ['name' => 'ASC']),
  106.                 $this->branchManager->getRepository()->findBy(['deletedAt' => null], ['raisonSociale' => 'ASC']),
  107.                 $this->branchTypeManager->getRepository()->findAll(),
  108.                 $this->proprietaireManager->getRepository()->findBy([], ['nom' => 'ASC'])
  109.             ];
  110.         });
  111.         return $this->render('admin/user/index.html.twig', [
  112.             'users' => $users,
  113.             'pagination' => $filterService->getPagination(),
  114.             'filters' => $filters,
  115.             'produits' => $produits,
  116.             'services' => $services,
  117.             'branchs' => $branchs,
  118.             'fields' => $filterService->getFields('user'),
  119.             'branch_types' => $branch_types,
  120.             'form' => $form->createView(),
  121.             'success' => $this->messageManager->getSuccess($success),
  122.             'error' => $this->messageManager->getError($error),
  123.             'udroits' => $this->droitManager->getUserRight($this->droit),
  124.             'proprietaires' => $proprietaires
  125.         ]);
  126.     }
  127.     /**
  128.      * @Route("/new", name="new")
  129.      */
  130.     public function create(Request $request): Response
  131.     {
  132.         $this->droitManager->verifyUserRight($this->droit, "C", "JAZMIN", 1);
  133.         $username = $request->get('username');
  134.         $user = $this->userManager->getRepository()->findOneBy(['username' => $username]);
  135.         if (empty($user)) {
  136.             $department = $this->departmentManager->getRepository()->find($request->get('department'));
  137.             $user = $this->userManager->insert($username, $request->get('lastname'), $request->get('firstname'), [], $request->get('email'), $request->get('type'), $department);
  138.             $data = [
  139.                 'success' => true,
  140.                 'error' => null,
  141.                 'message' => 'OK !',
  142.                 'user' => ['id' => $user->getId()],
  143.             ];
  144.         } else {
  145.             $data = [
  146.                 'success' => false,
  147.                 'error' => "L'identifiant " . $username . " est déjà utilisé.",
  148.                 'message' => "Erreur",
  149.             ];
  150.         }
  151.         return new JsonResponse($data);
  152.     }
  153.     /**
  154.      * @Route("/new/embed", name="new_embed")
  155.      */
  156.     public function newEmbed(Request $request): Response
  157.     {
  158.         $this->droitManager->verifyUserRight($this->droit, "C");
  159.         return $this->render('admin/user/new_embed.html.twig', [
  160.             'departments' => $this->departmentManager->getRepository()->findBy(['branch' => $request->get('branch_id'), 'deletedAt' => null], ['name' => 'ASC']),
  161.             'udroits' => [
  162.                 'UTILISATEUR' => $this->droitManager->getUserRight($this->droit),
  163.                 'PERIM_USER' => $this->droitManager->getUserRight("PERIM_USER"),
  164.                 'FONCTIONNALITE' => $this->droitManager->getUserRight("FONCTIONNALITE"),
  165.                 'PROFIL' => $this->droitManager->getUserRight("PROFIL")
  166.             ]
  167.         ]);
  168.     }
  169.     /**
  170.      * @Route("/show/{user}", name="show")
  171.      */
  172.     public function read(User $user): Response
  173.     {
  174.         $this->droitManager->verifyUserRight($this->droit, "R");
  175.         $produitsData = [];
  176.         foreach ($user->getUserProfils() as $userProfil) {
  177.             if ($userProfil->getIsActive()) {
  178.                 $profil = $userProfil->getProfil();
  179.                 $profilDroits = $profil->getProfilDroits();
  180.                 foreach ($profilDroits as $profilDroit) {
  181.                     $droit = $profilDroit->getDroit();
  182.                     $produit = $droit->getProduit();
  183.                     $profilDroitData = [
  184.                         "droit-code" => $droit->getCode(),
  185.                         "droit-name" => $droit->getName(),
  186.                         "has-read" => $profilDroit->getHasRead() ? '1' : '0',
  187.                         "has-update" => $profilDroit->getHasUpdate() ? '1' : '0',
  188.                         "has-create" => $profilDroit->getHasCreate() ? '1' : '0',
  189.                         "has-delete" => $profilDroit->getHasDelete() ? '1' : '0',
  190.                         "has-execute" => $profilDroit->getHasExecute() ? '1' : '0',
  191.                     ];
  192.                     $produitsData[$produit->getName()]['profils'][$profil->getName()]['profilDroits'][] =
  193.                         $profilDroitData;
  194.                     $produitsData[$produit->getName()]['profils'][$profil->getName()]['id'] = $profil->getId();
  195.                     $produitsData[$produit->getName()]['id'] = $produit->getId();
  196.                 }
  197.             }
  198.         }
  199.         foreach ($produitsData as &$produit) {
  200.             foreach ($produit['profils'] as &$profil) {
  201.                 $profil['profilDroits'] = htmlspecialchars(json_encode($profil['profilDroits']));
  202.             }
  203.             unset($profil);
  204.             ksort($produit['profils']);
  205.         }
  206.         unset($produit);
  207.         ksort($produitsData);
  208.         return $this->render('admin/user/show.html.twig', [
  209.             'user' => $user,
  210.             'produits' => $produitsData,
  211.             'udroits' => [
  212.                 'UTILISATEUR' => $this->droitManager->getUserRight($this->droit),
  213.                 'PERIM_USER' => $this->droitManager->getUserRight("PERIM_USER"),
  214.                 'FONCTIONNALITE' => $this->droitManager->getUserRight("FONCTIONNALITE"),
  215.                 'PROFIL' => $this->droitManager->getUserRight("PROFIL")
  216.             ],
  217.         ]);
  218.     }
  219.     /**
  220.      * @Route("/edit/{user}/embed", name="edit_embed")
  221.      */
  222.     public function editEmbed(Request $request, User $user): Response
  223.     {
  224.         return $this->edit($request, $user, true);
  225.     }
  226.     /**
  227.      * @Route("/edit/{user}", name="edit")
  228.      */
  229.     public function edit(Request $request, User $user, bool $embed = false): Response
  230.     {
  231.         $this->droitManager->verifyUserRight($this->droit, "U");
  232.         $redirect = $request->get('redirect');
  233.         $success = $request->get('success');
  234.         $userDept = $user->getDepartment();
  235.         $branch = $userDept->getBranch();
  236.         $departments = $this->departmentManager->getRepository()->findBy(['branch' => $branch, 'deletedAt' => null], ['name' => 'ASC']);
  237.         $userTreeList = $this->userManager->getUsersTreeListByBranch($branch, $departments);
  238.         // Enregistrement des infos du formulaire
  239.         $form = $this->createForm(UserType::class, $user);
  240.         $form->handleRequest($request);
  241.         $okForm = false;
  242.         $clientList = Utilities::selectDistinct($this->abiConnection, 'CO_DOSSIER', 'CLI_CODE', [], '', true);
  243.         if ($form->isSubmitted() && $form->isValid()) {
  244.             $okForm = true;
  245.             $this->champPersoManager->saveChampPersos("User", $user->getId(), $form);
  246.             // Périmètre client
  247.             $giveAccessUsers = $form->get('accessUsersInverse')->getData();
  248.             foreach ($giveAccessUsers as $giveAccessUser) {
  249.                 /** @var User $targerUser */
  250.                 $targerUser = $giveAccessUser;
  251.                 $targerUser->addAccessUser($user);
  252.                 $this->userManager->update($targerUser);
  253.             }
  254.             if ($this->droitManager->getUserRight("PERIM_USER", "U")) {
  255.                 $this->perimetreManager->processRequest($user, $request, $clientList);
  256.             }
  257.             // Fonctionnalités
  258.             if ($this->droitManager->getUserRight("FONCTIONNALITE", "U")) {
  259.                 $this->userFonctionnaliteManager->processRequest($user, $request);
  260.             }
  261.             // Profils
  262.             if ($this->droitManager->getUserRight("PROFIL", "U")) {
  263.                 $this->userProfilManager->processRequest($user, $request);
  264.             }
  265.             if ($request->get('new_user')) {
  266.                 $this->userManager->initializePassword($user);
  267.             }
  268.             $user->setDepartment($form->get('department')->getData());
  269.             $this->userManager->update($user);
  270.             $success = $this->messageManager->getSuccess('user_updated');
  271.         }
  272.         $openOffCanvas = $request->get('offcanvas') === 'on';
  273.         $newUser = $request->get('user') === 'new';
  274.         // Produits
  275.         $produitMesssage = '';
  276.         $produitList = [];
  277.         $reglages = [];
  278.         $fonctionnaliteList = [];
  279.         $profils = [];
  280.         $perimetres = [];
  281.         $etapeList = Utilities::selectDistinct($this->abiConnection, 'CO_DOSSIER', 'ETAPE', [], '', true);
  282.         $proprietaireList = Utilities::selectDistinct($this->abiConnection, 'CO_DOSSIER', 'PROPRIETAIRE', [], '', true);
  283.         $typeEnqueteList = Utilities::selectDistinct($this->abiConnection, 'CO_DOSSIER', 'TYPE', [], '', true);
  284.         if (empty($branch)) {
  285.             $produitMesssage = 'Veuillez sélectionner une organisation puis valider les modifications.';
  286.         } else {
  287.             $deptProduits = $userDept->getDepartmentProduits();
  288.             foreach ($deptProduits as $deptProduit) {
  289.                 if ($deptProduit->getIsActive()) $produitList[] = $deptProduit->getProduit();
  290.             }
  291.             if (empty($produitList)) {
  292.                 $produitMesssage = "Aucun produit trouvé pour le departement [" . $branch->getRaisonSociale() . " (" . $userDept->getName() . ")].";
  293.             } else {
  294.                 // Fonctionnalités
  295.                 $departmentFonctionnalites = $user->getDepartment()->getDepartmentFonctionnalites();
  296.                 foreach ($departmentFonctionnalites as $departmentFonctionnalite) {
  297.                     $userFonctionnalite = $this->userFonctionnaliteManager
  298.                         ->getRepository()
  299.                         ->findOneBy(['departmentFonctionnalite' => $departmentFonctionnalite->getId(), 'user_' => $user->getId()], []);
  300.                     if (empty($userFonctionnalite)) {
  301.                         $userFonctionnalite = $this->userFonctionnaliteManager->insert($user, $departmentFonctionnalite, true);
  302.                     }
  303.                     if ($departmentFonctionnalite->getIsActive()) {
  304.                         $detailFonctionnalite = $departmentFonctionnalite->getDetailFonctionnalite();
  305.                         $fonctionnalite = $detailFonctionnalite->getFonctionnalite();
  306.                         $fonctionnaliteList[$fonctionnalite->getProduit()->getId()][] = [
  307.                             'id' => $userFonctionnalite->getId(),
  308.                             'libelle' => $detailFonctionnalite->getLibelleOverride() ?? $fonctionnalite->getLibelle(),
  309.                             'is_active' => $userFonctionnalite->getIsActive()
  310.                         ];
  311.                     }
  312.                 }
  313.                 foreach ($produitList as $produit) {
  314.                     $reglages[$produit->getId()] = $this->userProduitManager->processRequest($user, $produit, $request, $okForm);
  315.                     $profils[strval($produit->getId())] = $this->userProfilManager->processRequestProduit($user, $produit);
  316.                     // Périmètres
  317.                     $perimetres = $this->perimetreManager->processRequestWithProduit($user, $produit, $clientList, $etapeList, $proprietaireList, $typeEnqueteList, $perimetres);
  318.                 }
  319.             }
  320.         }
  321.         // Propriétaires
  322.         $proprietaires = $this->userProprietaireManager->processRequest($user, $request, $okForm ?? false);
  323.         $userDocuments = [];
  324.         foreach ($user->getDocuments() as $userDocument) {
  325.             $userDocuments[] = $this->champPersoValueManager->populateChampPersos('UserDocument', $userDocument->getFormattedDatas(), true, true);
  326.         }
  327.         $perimetreSystemsByProduit = $this->perimetreSystemManager->getRepository()->getPerimetreSystemsByUserGroupedByProducts($user);
  328.         $perimetreSystemsByProduitNot = $this->perimetreSystemManager->getRepository()->getPerimetreSystemsByUserGroupedByProducts($user, true);
  329.         if (!empty($redirect)) {
  330.             return $this->redirect($redirect);
  331.         }
  332.         return $this->render('admin/user/edit' . ($embed ? '_embed' : '') . '.html.twig', [
  333.             'openOffCanvas' => $openOffCanvas,
  334.             'newUser' => $newUser,
  335.             'user' => $user,
  336.             'user_trees' => $userTreeList,
  337.             'departments' => $departments,
  338.             'department_selected' => $user->getDepartment(),
  339.             'form' => $form->createView(),
  340.             'profils' => $profils,
  341.             'produits' => $produitList,
  342.             'reglages' => $reglages,
  343.             'fonctionnalites' => $fonctionnaliteList,
  344.             'produit_message' => $produitMesssage,
  345.             'success' => $success,
  346.             'userDocuments' => $userDocuments,
  347.             'listChampsPerso' => $this->champPersoManager->getRepository()->getListChampPersos("UserDocument"),
  348.             // Périmètre dossier
  349.             'perimetres' => $perimetres,
  350.             'perimetreSystemsByProduit' => $perimetreSystemsByProduit,
  351.             'perimetreSystemsByProduitNot' => $perimetreSystemsByProduitNot,
  352.             'gestionnaires' => $this->userManager->getRepository()->findAll(),
  353.             'prestations' => $this->prestationManager->getRepository()->findAll(),
  354.             'gammes' => [],
  355.             'clients' => [],
  356.             'orga_affects' => [],
  357.             'etapes' => [
  358.                 ['id' => '1', 'label' => '1'],
  359.                 ['id' => '2', 'label' => '2'],
  360.                 ['id' => '3', 'label' => '3'],
  361.                 ['id' => '4', 'label' => '4'],
  362.                 ['id' => '5', 'label' => '5']
  363.             ],
  364.             'groupes_commerciaux' => [],
  365.             'proprietaires' => $proprietaires,
  366.             'types_enquetes' => [],
  367.             'statut_archive' => [
  368.                 ['id' => '0', 'label' => '0'],
  369.                 ['id' => '1', 'label' => '1'],
  370.                 ['id' => '2', 'label' => '2'],
  371.             ],
  372.             'user_highlight' => $request->get("user_highlight"),
  373.             'udroits' => [
  374.                 'UTILISATEUR' => $this->droitManager->getUserRight($this->droit),
  375.                 'PERIM_USER' => $this->droitManager->getUserRight("PERIM_USER"),
  376.                 'FONCTIONNALITE' => $this->droitManager->getUserRight("FONCTIONNALITE"),
  377.                 'PROFIL' => $this->droitManager->getUserRight("PROFIL")
  378.             ]
  379.         ]);
  380.     }
  381.     /**
  382.      * @Route("/tree", name="edit_tree")
  383.      */
  384.     public function updateUserTrees(Request $request): Response
  385.     {
  386.         $this->droitManager->verifyUserRight($this->droit, "U", "JAZMIN", 1);
  387.         $trees = $request->get('user_trees');
  388.         if (!empty($trees)) {
  389.             foreach ($trees as $node) {
  390.                 if (empty($node['parent'])) {
  391.                     $this->userManager->getRepository()->cleanParentRootNiveauLeftAndRight($node['id']);
  392.                 }
  393.             }
  394.             $this->userManager->updateUserTree($trees);
  395.         }
  396.         return new JsonResponse(['trees' => $trees]);
  397.     }
  398.     /**
  399.      * @Route("/delete/{user}/{route}", name="delete")
  400.      */
  401.     public function delete(User $user, ?string $route = null): Response
  402.     {
  403.         $this->droitManager->verifyUserRight($this->droit, "D");
  404.         $error = null;
  405.         $success = null;
  406.         try {
  407.             $this->userManager->softDelete($user);
  408.             $success = 'user_removed';
  409.         } catch (Exception $exception) {
  410.             $error = $exception->getMessage();
  411.         }
  412.         if (!empty($route)) {
  413.             return $this->redirectToRoute('admin_user_home', [
  414.                 'error' => $error,
  415.                 'success' => $success,
  416.             ]);
  417.         }
  418.         return new JsonResponse(json_encode([
  419.             'success' => $this->messageManager->getSuccess($success),
  420.             'error' => $this->messageManager->getError($error)
  421.         ]));
  422.     }
  423.     /**
  424.      * @Route("/activate/{user}", name="activate")
  425.      */
  426.     public function activate(User $user): Response
  427.     {
  428.         $this->droitManager->verifyUserRight($this->droit, "U");
  429.         $this->userManager->activate($user);
  430.         return $this->redirectToRoute('admin_user_home', [
  431.             'success' => 'user_activated',
  432.         ]);
  433.     }
  434.     /**
  435.      * @Route("/deactivate/{user}", name="deactivate")
  436.      */
  437.     public function deactivate(User $user): Response
  438.     {
  439.         $this->droitManager->verifyUserRight($this->droit, "U");
  440.         $this->userManager->deactivate($user);
  441.         return $this->redirectToRoute('admin_user_home', [
  442.             'success' => 'user_deactivated',
  443.         ]);
  444.     }
  445.     /**
  446.      * @Route("/init_password", name="init_password")
  447.      */
  448.     public function initPassword(Request $request, ProduitApiConnector $connector): JsonResponse|RedirectResponse
  449.     {
  450.         $this->droitManager->verifyUserRight($this->droit, "U");
  451.         $error = $this->initOnePassword($request->get('user_id'), $request->get('produit')[0], $connector);
  452.         $response_data = [
  453.             'success' => $error ? '' : 'user_password_initiated',
  454.             'error' => $error
  455.         ];
  456.         $redirection = $request->get('redirection');
  457.         if (!empty($redirection) && $redirection) {
  458.             return new JsonResponse($response_data);
  459.         }
  460.         return $this->redirectToRoute('admin_user_home', $response_data);
  461.     }
  462.     /**
  463.      * @Route("/bulk_init_password", name="bulk_init_password")
  464.      */
  465.     public function bulkInitPassword(Request $request, ProduitApiConnector $connector): RedirectResponse
  466.     {
  467.         $this->droitManager->verifyUserRight($this->droit, "U");
  468.         $produit = $request->get('produit')[0];
  469.         $usersId = $request->get('users_id');
  470.         $error = null;
  471.         if (!empty($usersId) && !empty($produit)) {
  472.             foreach ($usersId as $userId) {
  473.                 $error = $this->initOnePassword($userId, $produit, $connector) ?? $error;
  474.             }
  475.         } else $error = 'produit_or_user_missing';
  476.         return $this->redirectToRoute('admin_user_home', [
  477.             'success' => $error ? '' : 'user_password_initiated',
  478.             'error' => $error
  479.         ]);
  480.     }
  481.     
  482.     private function initOnePassword(string $userId, string $produitName, ProduitApiConnector $connector): ?string
  483.     {
  484.         if (empty($userId) || empty($produitName)) {
  485.             return 'produit_or_user_missing';
  486.         }
  487.         /** @var Produit $produit */
  488.         $produit = $this->produitManager->getRepository()->find($produitName);
  489.         /** @var User $user */
  490.         $user = $this->userManager->getRepository()->find($userId);
  491.         if ($produit === null || $user === null || !empty($user->getDeletedAt())) {
  492.             return 'produit_or_user_missing';
  493.         }
  494.         if ($produit->getName() === 'JAZMIN') {
  495.             $this->userManager->initializePasswordForJazmin($user);
  496.         } else if ($produit->getName() === 'NOSE') {
  497.             $this->userManager->initializePasswordForNose($user);
  498.         } else {
  499.             $token = $this->userManager->setInitTokenForProduit($user->getUsername());
  500.             $organisation = $user->getDepartment()->getBranch();
  501.             $parameters = [
  502.                 'token' => $token,
  503.                 'username' => $user->getUsername(),
  504.                 'nom' => $user->getLastname() . ' ' . $user->getFirstname(),
  505.                 'email' => $user->getEmail(),
  506.                 'ste' => $organisation->getMnemonique(),
  507.             ];
  508.             $connector->sendRequestToProduit($produit, $parameters, 'GET', $produit->getInitPasswordUrl() ?? 'user/pass/init');
  509.         }
  510.         return null;
  511.     }
  512.     /**
  513.      * @Route("/reset_password", name="reset_password")
  514.      */
  515.     public function resetPassword(Request $request, ProduitApiConnector $connector): JsonResponse|RedirectResponse
  516.     {
  517.         $this->droitManager->verifyUserRight($this->droit, "U");
  518.         $error = $this->resetOnePassword($request->get('user_id'), $request->get('produit')[0], $connector);
  519.         $response_data = [
  520.             'success' => $error ? '' : 'user_password_initiated',
  521.             'error' => $error
  522.         ];
  523.         $redirection = $request->get('redirection');
  524.         if (!empty($redirection) && $redirection) {
  525.             return new JsonResponse($response_data);
  526.         }
  527.         return $this->redirectToRoute('admin_user_home', $response_data);
  528.     }
  529.     /**
  530.      * @Route("/bulk_reset_password", name="bulk_reset_password")
  531.      */
  532.     public function bulkResetPassword(Request $request, ProduitApiConnector $connector): RedirectResponse
  533.     {
  534.         $this->droitManager->verifyUserRight($this->droit, "U");
  535.         $produit = $request->get('produit')[0];
  536.         $usersId = $request->get('users_id');
  537.         $error = null;
  538.         if (!empty($usersId) && !empty($produit)) {
  539.             foreach ($usersId as $userId) {
  540.                 $error = $this->resetOnePassword($userId, $produit, $connector) ?? $error;
  541.             }
  542.         } else $error = 'produit_or_user_missing';
  543.         return $this->redirectToRoute('admin_user_home', [
  544.             'success' => $error ? '' : 'user_password_reset',
  545.             'error' => $error
  546.         ]);
  547.     }
  548.     
  549.     private function resetOnePassword(string $userId, string $produitName, ProduitApiConnector $connector): ?string
  550.     {
  551.         if (empty($userId) || empty($produitName)) {
  552.             return 'produit_or_user_missing';
  553.         }
  554.         /** @var Produit $produit */
  555.         $produit = $this->produitManager->getRepository()->find($produitName);
  556.         /** @var User $user */
  557.         $user = $this->userManager->getRepository()->find($userId);
  558.         if ($produit === null || $user === null || !empty($user->getDeletedAt())) {
  559.             return 'produit_or_user_missing';
  560.         }
  561.         if ($produit->getName() === 'JAZMIN') {
  562.             $this->userManager->resetPasswordForJazmin($user->getUsername());
  563.         } else if ($produit->getName() === 'NOSE') {
  564.             $this->userManager->resetPasswordForNose($user->getUsername());
  565.         } else {
  566.             $token = $this->userManager->resetPasswordForProduit($user->getUsername());
  567.             $organisation = $user->getDepartment()->getBranch();
  568.             $parameters = [
  569.                 'token' => $token,
  570.                 'username' => $user->getUsername(),
  571.                 'nom' => $user->getLastname() . ' ' . $user->getFirstname(),
  572.                 'email' => $user->getEmail(),
  573.                 'ste' => $organisation->getMnemonique(),
  574.             ];
  575.             $connector->sendRequestToProduit($produit, $parameters, 'GET', $produit->getResetPasswordUrl() ?? 'user/pass/reset');
  576.         }
  577.         return null;
  578.     }
  579.     /**
  580.      * @Route("/switch/{user}/{produit}", name="switch")
  581.      */
  582.     public function switchUser(User $user, Produit $produit): JsonResponse
  583.     {
  584.         $this->droitManager->verifyUserRight($this->droit, "R");
  585.         [$url, $error] = $this->userManager->getSwitchUrl($user, $produit, $this->getUser());
  586.         return new JsonResponse(['url' => $url, 'error' => $error, 'success' => $error ? '' : 'URL trouvée']);
  587.     }
  588.     /**
  589.      * @Route("/mass/{users}/{key}/{value}/{route}", name="mass")
  590.      */
  591.     public function mass(
  592.         string $users,
  593.         string $key,
  594.         $value,
  595.         ?string $route = null,
  596.         BranchProduitManager $branchProduitManager,
  597.         DepartmentProduitManager $departmentProduitManager,
  598.         ProfilRepository $profilRepository
  599.     ): Response {
  600.         $this->droitManager->verifyUserRight($this->droit, "U", "JAZMIN", 1);
  601.         $success = null;
  602.         $error = null;
  603.         try {
  604.             switch ($key) {
  605.                 case 'department':
  606.                     $value = $this->departmentManager->getRepository()->find($value);
  607.                     break;
  608.                 case 'fonction':
  609.                 case 'type':
  610.                     if (empty($value)) $value = null;
  611.                     break;
  612.                 case 'produit':
  613.                     $value = explode('_', $value);
  614.                     break;
  615.             }
  616.             foreach (explode(',', $users) as $user) {
  617.                 $user = $this->userManager->getRepository()->find($user);
  618.                 if ($user) {
  619.                     switch ($key) {
  620.                         case 'department':
  621.                             $user->setDeparment($value);
  622.                             break;
  623.                         case 'fonction':
  624.                         case 'type':
  625.                             $user->{'set' . ucfirst($key)}($value);
  626.                             break;
  627.                         case 'produit':
  628.                             $produit = $this->produitManager->getRepository()->find($value[0]);
  629.                             $profil = $profilRepository->find($value[1]);
  630.                             $branchProduitManager->checkAndInsert($user->getDepartment()->getBranch(), $produit, true, null, true);
  631.                             $departmentProduitManager->checkAndInsert($user->getDepartment(), $produit, true, null, true);
  632.                             $this->userProduitManager->checkAndInsert($user, $produit, true, null, true, null);
  633.                             $this->userProfilManager->insert($user, $profil, true);
  634.                             break;
  635.                         default:
  636.                             $this->champPersoManager->saveChampPerso("User", $user->getId(), $this->champPersoManager->getRepository()->findOneBy(['code' => $key]), $value);
  637.                             break;
  638.                     }
  639.                     $this->userManager->update($user);
  640.                 }
  641.             }
  642.             $success = 'user_mass_maj';
  643.         } catch (Exception $exception) {
  644.             $error = $exception->getMessage() . ' at ' . $exception->getLine();
  645.         }
  646.         if (!empty($route)) {
  647.             return $this->redirectToRoute('admin_user_' . $route, [
  648.                 'success' => $success,
  649.                 'error' => $error
  650.             ]);
  651.         }
  652.         return new JsonResponse(json_encode([
  653.             'success' => $this->messageManager->getSuccess($success),
  654.             'error' => $this->messageManager->getError($error)
  655.         ]));
  656.     }
  657.     /**
  658.      * @Route("/document/upload/{user}", name="upload_user_document", methods={"POST"})
  659.      */
  660.     public function uploadUserDocument(Request $request, User $user, UserDocumentManager $userDocumentManager): JsonResponse
  661.     {
  662.         $this->droitManager->verifyUserRight("ORGANISATION", "U");
  663.         /** @var UploadedFile|null $file */
  664.         $file = $request->files->get('file');
  665.         if (!$file || !$file->isValid()) {
  666.             throw new \RuntimeException('Fichier invalide ou manquant');
  667.         }
  668.         // ---------- Nom du fichier ----------
  669.         $originalFilename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
  670.         $safeFilename = strtolower(Utilities::cleanString($originalFilename));
  671.         $uniq = uniqid();
  672.         $filename = sprintf(
  673.             '%s-%s.%s',
  674.             $safeFilename,
  675.             $uniq,
  676.             $file->guessExtension()
  677.         );
  678.         // ---------- DB ----------
  679.         $userDocument = $userDocumentManager->insert(
  680.             $user,
  681.             $request->request->get('nom'),
  682.             $filename,
  683.             $request->request->get('dateValid'),
  684.             $request->request->get('dateAlert')
  685.         );
  686.         // ---------- Stockage (local ou SMB) ----------
  687.         $this->fileService->saveUploadedFile(
  688.             $userDocument->getDocPath(),
  689.             $file,
  690.             $filename
  691.         );
  692.         // ---------- Champ perso ----------
  693.         $this->champPersoManager->saveChampPerso(
  694.             'UserDocument',
  695.             $userDocument->getId(),
  696.             $this->champPersoManager
  697.                 ->getRepository()
  698.                 ->findOneBy(['code' => 'USERDOCUMENT']),
  699.             $request->request->get('typeDeDocument')
  700.         );
  701.         return new JsonResponse(
  702.             $this->champPersoValueManager->populateChampPersos(
  703.                 'UserDocument',
  704.                 $userDocument->getFormattedDatas(),
  705.                 true,
  706.                 true
  707.             )
  708.         );
  709.     }
  710.     /**
  711.      * @Route("/document/view/{userDocument}", name="view_user_document", methods={"GET"})
  712.      */
  713.     public function viewUserDocument(UserDocument $userDocument): BinaryFileResponse
  714.     {
  715.         $this->droitManager->verifyUserRight("ORGANISATION", "R");
  716.         return $this->fileService->getBinaryResponse($userDocument->getDocPath() . '/' . $userDocument->getPath());
  717.     }
  718.     /**
  719.      * @Route("/document/delete/{userDocument}", name="delete_user_document", methods={"GET"})
  720.      */
  721.     public function deleteUserDocument(UserDocument $userDocument, UserDocumentManager $userDocumentManager): JsonResponse
  722.     {
  723.         $this->droitManager->verifyUserRight("ORGANISATION", "D");
  724.         $userDocumentManager->delete($userDocument);
  725.         return new JsonResponse(['ok']);
  726.     }
  727.     /**
  728.      * @Route("/getproduits/{user}", name="getproduits")
  729.      */
  730.     public function getProduits(int $user): JsonResponse
  731.     {
  732.         $this->droitManager->verifyUserRight($this->droit, "R");
  733.         if ($user === 0) {
  734.             return new JsonResponse($this->produitManager->getRepository()->getSwitchableProduits());
  735.         }
  736.         return new JsonResponse($this->userManager->getRepository()->getProduits($user));
  737.     }
  738. }