src/ApplicationBundle/Controller/ApprovalController.php line 262

Open in your IDE?
  1. <?php
  2. namespace ApplicationBundle\Controller;
  3. use ApplicationBundle\Constants\GeneralConstant;
  4. use ApplicationBundle\Constants\NotificationEventCatalogue;
  5. use ApplicationBundle\Entity\EncryptedSignature;
  6. use ApplicationBundle\Interfaces\SessionCheckInterface;
  7. use ApplicationBundle\Modules\Authentication\Constants\UserConstants;
  8. use ApplicationBundle\Modules\Api\Constants\ApiConstants;
  9. use ApplicationBundle\Modules\System\DocValidation;
  10. use ApplicationBundle\Modules\System\MiscActions;
  11. use ApplicationBundle\Modules\System\System;
  12. use ApplicationBundle\Modules\User\Users;
  13. use ApplicationBundle\Notification\NotificationEvent;
  14. use Symfony\Component\HttpFoundation\JsonResponse;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\Routing\Generator\UrlGenerator;
  17. class ApprovalController extends GenericController implements SessionCheckInterface
  18. {
  19.     public function ApproveDocumentAction(Request $request)
  20.     {
  21.         $em $this->getDoctrine()->getManager();
  22.         if ($request->isMethod('POST')) {
  23.             if (isset(GeneralConstant::$Entity_list_details[$request->request->get('approvalEntity')]['entity_view_route_path_name']))
  24.                 $url $this->generateUrl(
  25.                     GeneralConstant::$Entity_list_details[$request->request->get('approvalEntity')]['entity_view_route_path_name']
  26.                 );
  27.             else {
  28.                 $url '';
  29.             }
  30.             $options = array(
  31.                 'notification_enabled' => $this->container->getParameter('notification_enabled'),
  32.                 'notification_server' => $this->container->getParameter('notification_server'),
  33. //                'appId'=>$request->getSession()->get(UserConstants::USER_APP_ID),
  34. //                'url'=>$this->generateUrl(
  35. //                    GeneralConstant::$Entity_list_details[$request->request->get('approvalEntity')]['entity_view_route_path_name']
  36. //                )
  37.             );
  38.             if ($request->request->has('approvalAction')) {
  39.                 $message System::approveDocument(
  40.                     $em,
  41.                     $options,
  42.                     $request->request->get('approvalEntity'),
  43.                     $request->request->get('approvalEntityId'),
  44.                     $request->request->get('approvalId'),
  45.                     $this->getLoggedUserLoginId($request),
  46.                     $request->request->get('approvalAction'),
  47.                     $request->request->get('approvalNote'),
  48.                     $request->request->get('approvalHash'),
  49.                     $url,
  50.                     $request->request->get('forwardTo'),
  51.                     $this->get('mail_module'),
  52.                     $request->request->get('approvedAmount')   // partial approval (expense): reduce to this if < current
  53.                 );
  54.                 // ── Notify the next approver(s) in line ──────────────────────
  55.                 // approveDocument() returns userIdList = next pending approvers.
  56.                 // We notify them that a document is now waiting for their approval.
  57.                 if ($message['success'] == true && !empty($message['userIdList'])) {
  58.                     $entityAlias GeneralConstant::$Entity_list_details[$request->request->get('approvalEntity')]['entity_alias'] ?? 'Document';
  59.                     /** @var \ApplicationBundle\Service\NotificationDispatcher $dispatcher */
  60.                     $dispatcher $this->get('app.notification_dispatcher');
  61.                     $dispatcher->dispatchDirect(
  62.                         \ApplicationBundle\Notification\NotificationEvent::make(
  63.                             \ApplicationBundle\Constants\NotificationEventCatalogue::DOC_AWAITING_MY_APPROVAL,
  64.                             (int) $request->getSession()->get(UserConstants::USER_COMPANY_ID),
  65.                             (int) $request->getSession()->get(UserConstants::USER_APP_ID),
  66.                             [
  67.                                 'entityType'   => $entityAlias,
  68.                                 'documentHash' => $message['docHash'] ?? '',
  69.                                 'targetRoute'  => GeneralConstant::$Entity_list_details[$request->request->get('approvalEntity')]['entity_view_route_path_name'] ?? '',
  70.                                 'targetId'     => $request->request->get('approvalEntityId'),
  71.                                 'actorUserId'  => (int) $request->getSession()->get(UserConstants::USER_ID),
  72.                             ]
  73.                         ),
  74.                         array_map('intval'$message['userIdList'])
  75.                     );
  76.                 }
  77. //            $this->addFlash(
  78. //                $message[0],
  79. //                $message[1]
  80. //            );
  81.                 if ($message['success'] == true)
  82.                     return new JsonResponse(array("success" => true,
  83.                             'message' => $message,
  84.                             'approvalEntity' => $request->request->get('approvalEntity'),
  85.                             'approvalEntityId' => $request->request->get('approvalEntityId'),
  86.                             'approvalId' => $request->request->get('approvalId'),
  87.                             'approvalAction' => $request->request->get('approvalAction'),
  88.                         )
  89.                     );
  90.                 else
  91.                     return new JsonResponse(array("success" => false'message' => $message,
  92.                             'approvalEntity' => $request->request->get('approvalEntity'),
  93.                             'approvalEntityId' => $request->request->get('approvalEntityId'),
  94.                             'approvalId' => $request->request->get('approvalId'),
  95.                             'approvalAction' => $request->request->get('approvalAction'),
  96.                         )
  97.                     );
  98.             }
  99.             return new JsonResponse(array("success" => false));
  100.         }
  101. //        $userList=$this->get('user_module')->showUserList();
  102.         return new JsonResponse(array("success" => false));
  103.     }
  104.     public function getPendingApprovalListForUserAction(Request $request)
  105.     {
  106.         $em $this->getDoctrine()->getManager();
  107.         $session $request->getSession();
  108.         $currentDateTime = new \DateTime();
  109.         $currTs $currentDateTime->format('U');
  110.         $tvp $this->get('url_encryptor')->encrypt(json_encode(
  111.             array(
  112.                 'timeout' => $currTs 3600,
  113.                 'token' => $session->get('token'0),
  114.             )
  115.         ));
  116.         $absoluteUrlList = [];
  117.         $filterApprovalEntityId=$request->request->get('entity','_all_');
  118.         foreach (GeneralConstant::$Entity_list_details as $e => $d) {
  119.             if (isset($d['entity_view_route_path_name']))
  120.                 $absoluteUrlList[$e] = $this->generateUrl($d['entity_view_route_path_name'], [], UrlGenerator::ABSOLUTE_URL);
  121.         }
  122.         return new JsonResponse(System::getPendingApprovalListByUserLoginId($em$this->getLoggedUserLoginId($request), 1$absoluteUrlList$tvp,$filterApprovalEntityId));
  123.     }
  124.     public function getPendingApprovalListForAppAction(Request $request)
  125.     {
  126.         $em $this->getDoctrine()->getManager();
  127.         $absoluteUrlList = [];
  128.         $session $request->getSession();
  129.         $currentDateTime = new \DateTime();
  130.         $currTs $currentDateTime->format('U');
  131.         $absoluteUrl $this->generateUrl('dashboard', [], UrlGenerator::ABSOLUTE_URL);
  132.         $tvp $this->get('url_encryptor')->encrypt(json_encode(
  133.             array(
  134.                 'timeout' => $currTs 3600,
  135.                 'token' => $session->get('token'0),
  136.             )
  137.         ));
  138.         foreach (GeneralConstant::$Entity_list_details as $e => $d) {
  139.             if (isset($d['entity_view_route_path_name']))
  140.                 $absoluteUrlList[$e] = $this->generateUrl(isset($d['entity_print_route_path_name']) ? $d['entity_print_route_path_name'] : $d['entity_view_route_path_name'], [], UrlGenerator::ABSOLUTE_URL);
  141.         }
  142.         return new JsonResponse(System::getPendinDocumentListForAppByUserLoginId($em$this->getLoggedUserLoginId($request), 1$absoluteUrlList$tvp,'_all_',
  143.             $request->query->get('page''_UNSET_'),
  144.             $request->query->get('offset'0),
  145.             $request->query->get('limit'999999),
  146.             $absoluteUrl
  147.         ));
  148. //        $em = $this->getDoctrine()->getManager();
  149. //
  150. //        $absoluteUrlList = [];
  151. //        foreach (GeneralConstant::$Entity_list_details as $e => $d) {
  152. //            if (isset($d['entity_view_route_path_name']))
  153. //                $absoluteUrlList[$e] = $this->generateUrl(isset($d['entity_print_route_path_name']) ? $d['entity_print_route_path_name'] : $d['entity_view_route_path_name'], [], UrlGenerator::ABSOLUTE_URL);
  154. //        }
  155. //        $session = $request->getSession();
  156. //        $currentDateTime = new \DateTime();
  157. //        $currTs = $currentDateTime->format('U');
  158. //        $tvp = $this->get('url_encryptor')->encrypt(json_encode(
  159. //            array(
  160. //                'timeout' => 1 * $currTs + 3600,
  161. //                'token' => $session->get('token', 0),
  162. //
  163. //            )
  164. //        ));
  165. //
  166. //
  167. //        return new JsonResponse(System::getPendinDocumentListForAppByUserLoginId($em, $this->getLoggedUserLoginId($request), 1, $absoluteUrlList,
  168. //            $tvp,
  169. //            $request->query->get('page', '_UNSET_'),
  170. //            $request->query->get('offset', 0),
  171. //            $request->query->get('limit', 999999)
  172. //        ));
  173.     }
  174.     public function getMyDocumentListForAppAction(Request $request)
  175.     {
  176.         $em $this->getDoctrine()->getManager();
  177.         $absoluteUrlList = [];
  178.         $session $request->getSession();
  179.         $currentDateTime = new \DateTime();
  180.         $currTs $currentDateTime->format('U');
  181.         $absoluteUrl $this->generateUrl('dashboard', [], UrlGenerator::ABSOLUTE_URL);
  182.         $tvp $this->get('url_encryptor')->encrypt(json_encode(
  183.             array(
  184.                 'timeout' => $currTs 3600,
  185.                 'token' => $session->get('token'0),
  186.             )
  187.         ));
  188.         foreach (GeneralConstant::$Entity_list_details as $e => $d) {
  189.             if (isset($d['entity_view_route_path_name']))
  190.                 $absoluteUrlList[$e] = $this->generateUrl(isset($d['entity_print_route_path_name']) ? $d['entity_print_route_path_name'] : $d['entity_view_route_path_name'], [], UrlGenerator::ABSOLUTE_URL);
  191.         }
  192.         return new JsonResponse(System::getMyDocumentListForAppByUserLoginId($em$this->getLoggedUserLoginId($request),$absoluteUrl1$absoluteUrlList$tvp,'_all_',
  193.             $request->query->get('page''_UNSET_'),
  194.             $request->query->get('limit'999999)
  195.         ));
  196. //        $em = $this->getDoctrine()->getManager();
  197. //
  198. //        $absoluteUrlList = [];
  199. //        foreach (GeneralConstant::$Entity_list_details as $e => $d) {
  200. //            if (isset($d['entity_view_route_path_name']))
  201. //                $absoluteUrlList[$e] = $this->generateUrl(isset($d['entity_print_route_path_name']) ? $d['entity_print_route_path_name'] : $d['entity_view_route_path_name'], [], UrlGenerator::ABSOLUTE_URL);
  202. //        }
  203. //        $session = $request->getSession();
  204. //        $currentDateTime = new \DateTime();
  205. //        $currTs = $currentDateTime->format('U');
  206. //        $tvp = $this->get('url_encryptor')->encrypt(json_encode(
  207. //            array(
  208. //                'timeout' => 1 * $currTs + 3600,
  209. //                'token' => $session->get('token', 0),
  210. //
  211. //            )
  212. //        ));
  213. //
  214. //
  215. //        return new JsonResponse(System::getPendinDocumentListForAppByUserLoginId($em, $this->getLoggedUserLoginId($request), 1, $absoluteUrlList,
  216. //            $tvp,
  217. //            $request->query->get('page', '_UNSET_'),
  218. //            $request->query->get('offset', 0),
  219. //            $request->query->get('limit', 999999)
  220. //        ));
  221.     }
  222.     /**
  223.      * First-run guard: does the logged-in user have a usable signature yet?
  224.      * Used by the first-login modal so a new user is prompted to set their
  225.      * signature + approval hash BEFORE they hit an approval action and get stuck.
  226.      * Local-only check (cheap); a central copy is pulled lazily on first verify.
  227.      */
  228.     public function SignatureStatusAction(Request $request)
  229.     {
  230.         $em $this->getDoctrine()->getManager();
  231.         $userId $request->getSession()->get('userId');
  232.         $has false;
  233.         if ($userId) {
  234.             $rec $em->getRepository('ApplicationBundle\\Entity\\EncryptedSignature')
  235.                 ->findOneBy(['userId' => $userId]);
  236.             $has = ($rec && $rec->getData());
  237.         }
  238.         return new JsonResponse(['hasSignature' => (bool) $has]);
  239.     }
  240.     /**
  241.      * App: does the logged-in user have an approval signature yet? Lets the
  242.      * mobile client route between "enter your existing PIN" and "create a
  243.      * new PIN" on first use.
  244.      */
  245.     public function SignatureStatusForAppAction(Request $request)
  246.     {
  247.         $em $this->getDoctrine()->getManager();
  248.         $userId $request->getSession()->get('userId');
  249.         $has false;
  250.         if ($userId) {
  251.             $rec $em->getRepository('ApplicationBundle\\Entity\\EncryptedSignature')
  252.                 ->findOneBy(['userId' => $userId]);
  253.             $has = ($rec && $rec->getData());
  254.         }
  255.         return new JsonResponse(array('success' => true'hasSignature' => (bool) $has));
  256.     }
  257.     /**
  258.      * App: set or change the approval hash WITHOUT the ERP web. Mirrors
  259.      * UpdateSignatureAction, minus the mandatory image upload:
  260.      *   - first-time set → a simple name-stamp signature image is generated
  261.      *     server-side and encrypted under the new hash;
  262.      *   - change → the current hash must verify first, and the existing
  263.      *     signature image is preserved (re-encrypted under the new hash).
  264.      * Synced to CENTRAL exactly like the web flow.
  265.      */
  266.     public function SetSignatureForAppAction(Request $request)
  267.     {
  268.         $em $this->getDoctrine()->getManager();
  269.         $systemType $this->container->hasParameter('system_type') ? $this->container->getParameter('system_type') : '_ERP_';
  270.         $session $request->getSession();
  271.         $userId $session->get('userId');
  272.         $companyId $session->get('userCompanyId');
  273.         $loginId $this->getLoggedUserLoginId($request);
  274.         $newHash trim((string) $request->request->get('newHash'''));
  275.         $oldHash trim((string) $request->request->get('oldHash'''));
  276.         if ($userId == null || $loginId == null) {
  277.             return new JsonResponse(array('success' => false'message' => 'Not signed in.'));
  278.         }
  279.         if (strlen($newHash) < 4) {
  280.             return new JsonResponse(array('success' => false'message' => 'PIN must be at least 4 characters.'));
  281.         }
  282.         $repo $em->getRepository('ApplicationBundle\\Entity\\EncryptedSignature');
  283.         $record $repo->findOneBy(['userId' => $userId]);
  284.         if ($record && $record->getData()) {
  285.             // Changing an existing hash: the current one must verify, and we
  286.             // keep the user's existing signature image.
  287.             if ($oldHash === '') {
  288.                 return new JsonResponse(array('success' => false'message' => 'Your current PIN is required to change it.'));
  289.             }
  290.             $check DocValidation::isSignatureOk($em$loginId$oldHash1);
  291.             if (!isset($check['success']) || $check['success'] != true) {
  292.                 return new JsonResponse(array('success' => false'message' => 'Current PIN did not match.'));
  293.             }
  294.             $imageData $check['data'];
  295.         } else {
  296.             // First-time set from the app: no drawn signature exists, so
  297.             // generate a clean name-stamp image to act as the signature.
  298.             $user_data Users::getUserInfoByLoginId($em$loginId);
  299.             $name = isset($user_data['name']) && $user_data['name'] != '' $user_data['name'] : 'Approved';
  300.             $img imagecreatetruecolor(24080);
  301.             $bg imagecolorallocate($img255255255);
  302.             imagefilledrectangle($img0024080$bg);
  303.             $fg imagecolorallocate($img262828);
  304.             imagestring($img51232substr($name026), $fg);
  305.             ob_start();
  306.             imagepng($img);
  307.             $png ob_get_clean();
  308.             imagedestroy($img);
  309.             $imageData base64_encode($png);
  310.         }
  311.         $encoded System::encryptSignature($imageData$newHash);
  312.         if ($encoded === false) {
  313.             return new JsonResponse(array('success' => false'message' => 'Could not secure the signature. Try again.'));
  314.         }
  315.         if (!$record) {
  316.             $record = new \ApplicationBundle\Entity\EncryptedSignature();
  317.             $record->setUserId($userId);
  318.             $record->setCreatedAt(new \DateTime());
  319.         }
  320.         $record->setCompanyId($companyId);
  321.         $record->setData($encoded);
  322.         $record->setSigExists(0);
  323.         $record->setLastDecryptedSigId(0);
  324.         $record->setUpdatedAt(new \DateTime());
  325.         $em->persist($record);
  326.         $em->flush();
  327.         // Sync to CENTRAL (same contract as the web UpdateSignatureAction).
  328.         if ($systemType !== '_CENTRAL_') {
  329.             $applicantId null;
  330.             $sysUser $em->getRepository('ApplicationBundle\\Entity\\SysUser')->findOneBy(['userId' => $userId]);
  331.             if ($sysUser) {
  332.                 $applicantId $sysUser->getGlobalId();
  333.             }
  334.             $curl curl_init();
  335.             curl_setopt_array($curl, [
  336.                 CURLOPT_RETURNTRANSFER => true,
  337.                 CURLOPT_POST => true,
  338.                 CURLOPT_URL => GeneralConstant::HONEYBEE_CENTRAL_SERVER '/SyncSignatureToCentral',
  339.                 CURLOPT_CONNECTTIMEOUT => 10,
  340.                 CURLOPT_SSL_VERIFYPEER => false,
  341.                 CURLOPT_SSL_VERIFYHOST => false,
  342.                 CURLOPT_HTTPHEADER => [
  343.                     'Accept: application/json',
  344.                     'Content-Type: application/json'
  345.                 ],
  346.                 CURLOPT_POSTFIELDS => json_encode([
  347.                     'userId' => $userId,
  348.                     'approvalHash' => $newHash,
  349.                     'signatureData' => $encoded,
  350.                     'companyId' => $companyId,
  351.                     'applicantId' => $applicantId
  352.                 ])
  353.             ]);
  354.             curl_exec($curl);
  355.             curl_close($curl);
  356.         }
  357.         return new JsonResponse(array(
  358.             'success' => true,
  359.             'hasSignature' => true,
  360.             'message' => 'Approval PIN saved.'
  361.         ));
  362.     }
  363.     public function UpdateSignatureAction(Request $request)
  364.     {
  365.         $em $this->getDoctrine()->getManager();
  366.         $systemType $this->container->hasParameter('system_type') ? $this->container->getParameter('system_type') : '_ERP_';
  367.         $session $request->getSession();
  368.         $userId $session->get('userId');
  369.         $companyId $session->get('userCompanyId');
  370.         $appId $session->get('userAppId');
  371.         $user $em->getRepository('ApplicationBundle\\Entity\\SysUser')->findOneBy(['userId' => $userId]);
  372.         $applicantId $user->getGlobalId();
  373.         $user_data Users::getUserInfoByLoginId($em$this->getLoggedUserLoginId($request));
  374.         $g_path '';
  375.         if ($request->isMethod('POST')) {
  376.             $path "";
  377.             $extension_here '';
  378.             foreach ($request->files as $uploadedFile) {
  379.                 if ($uploadedFile != null) {
  380.                     $extension_here $uploadedFile->guessExtension();
  381.                     $fileName md5(uniqid()) . '.' $extension_here;
  382.                     $path $fileName;
  383.                     $upl_dir $this->container->getParameter('kernel.root_dir') . '/../web/uploads/FileUploads/';
  384.                     if (!file_exists($upl_dir)) {
  385.                         mkdir($upl_dir0777true);
  386.                     }
  387.                     $file $uploadedFile->move($upl_dir$path);
  388.                 }
  389.             }
  390.             if ($path != "") {
  391.                 $file_path 'uploads/FileUploads/' $path;
  392.                 $g_path $this->container->getParameter('kernel.root_dir') . '/../web/' $file_path;
  393.                 list($width$height) = getimagesize($g_path);
  394.                 $percent = (200 $width);
  395.                 $newwidth $width $percent;
  396.                 $newheight $height $percent;
  397.                 $thumb imagecreatetruecolor($newwidth$newheight);
  398.                 $source = ($extension_here == 'png') ? imagecreatefrompng($g_path) : imagecreatefromjpeg($g_path);
  399.                 imagecopyresampled($thumb$source0000$newwidth$newheight$width$height);
  400.                 $thumbPath $this->container->getParameter('kernel.root_dir') . '/../web/uploads/FileUploads/th.png';
  401.                 imagepng($thumb$thumbPath);
  402.                 $th_file file_get_contents($thumbPath);
  403.                 $image_data base64_encode($th_file);
  404.                 $encoded_data System::encryptSignature($image_data$request->request->get('approvalHash'));
  405.                 if ($encoded_data !== false) {
  406.                     $repo $em->getRepository('ApplicationBundle\\Entity\\EncryptedSignature');
  407.                     $record $repo->findOneBy(['userId' => $userId]);
  408.                     if (!$record) {
  409.                         $record = new \ApplicationBundle\Entity\EncryptedSignature();
  410.                         $record->setUserId($userId);
  411.                         $record->setCreatedAt(new \DateTime());
  412.                     }
  413.                     $record->setCompanyId($companyId);
  414.                     $record->setData($encoded_data);
  415.                     $record->setSigExists(0);
  416.                     $record->setLastDecryptedSigId(0);
  417.                     $record->setUpdatedAt(new \DateTime());
  418.                     $em->persist($record);
  419.                     $em->flush();
  420.                     // Sync to central server
  421.                     if ($systemType !== '_CENTRAL_') {
  422.                         $centralUrl GeneralConstant::HONEYBEE_CENTRAL_SERVER '/SyncSignatureToCentral';
  423.                         $payload = [
  424.                             'userId' => $userId,
  425.                             'approvalHash' => $request->request->get('approvalHash'),
  426.                             'signatureData' => $encoded_data,
  427.                             'companyId' => $companyId,
  428.                             'applicantId' => $applicantId
  429.                         ];
  430.                         $curl curl_init();
  431.                         curl_setopt_array($curl, [
  432.                             CURLOPT_RETURNTRANSFER => true,
  433.                             CURLOPT_POST => true,
  434.                             CURLOPT_URL => $centralUrl,
  435.                             CURLOPT_CONNECTTIMEOUT => 10,
  436.                             CURLOPT_SSL_VERIFYPEER => false,
  437.                             CURLOPT_SSL_VERIFYHOST => false,
  438.                             CURLOPT_HTTPHEADER => [
  439.                                 'Accept: application/json',
  440.                                 'Content-Type: application/json'
  441.                             ],
  442.                             CURLOPT_POSTFIELDS => json_encode($payload)
  443.                         ]);
  444.                         $retData curl_exec($curl);
  445.                         $err curl_error($curl);
  446.                         curl_close($curl);
  447. //                             return new JsonResponse($retData);
  448.                         if ($err) {
  449.                             $this->addFlash('error''Signature sent failed: ' $err);
  450.                         } else {
  451.                             $response json_decode($retDatatrue);
  452.                             if (isset($response['success']) && $response['success'] === true) {
  453.                                 $this->addFlash('success''Signature synced successfully to CENTRAL.');
  454.                             } else {
  455.                                 $this->addFlash('error''CENTRAL server error: ' . ($response['message'] ?? 'Unknown error.'));
  456.                             }
  457.                         }
  458.                     }
  459.                 }
  460.                 // Delete temp files
  461.                 @unlink($g_path);
  462.                 @unlink($thumbPath);
  463.             }
  464.             // First-run modal posts with a redirectTo so the user lands back where
  465.             // they were (instead of the settings page) once the signature is set.
  466.             $redirectTo $request->request->get('redirectTo');
  467.             if ($redirectTo) {
  468.                 return $this->redirect($redirectTo);
  469.             }
  470.         }
  471.         return $this->render('@System/pages/settings/update_signature.html.twig', [
  472.             'page_title' => 'Update Signature',
  473.             'user_data' => $user_data,
  474.             'path' => $g_path
  475.         ]);
  476.     }
  477.     public function SignatureCheckFromCentralAction(Request $request)
  478.     {
  479.         $systemType $this->container->hasParameter('system_type') ? $this->container->getParameter('system_type') : '_ERP_';
  480.         if ($systemType !== '_CENTRAL_') {
  481.             return new JsonResponse(['success' => false'message' => 'Only allowed on CENTRAL server.'], 403);
  482.         }
  483.         $em $this->getDoctrine()->getManager('company_group');
  484.         $em->getConnection()->connect();
  485.         $data json_decode($request->getContent(), true);
  486.         if (
  487.             !$data ||
  488.             !isset($data['userId']) ||
  489.             !isset($data['companyId']) ||
  490.             !isset($data['signatureData']) ||
  491.             !isset($data['approvalHash']) ||
  492.             !isset($data['applicantId'])
  493.         ) {
  494.             return new JsonResponse(['success' => false'message' => 'Missing parameters.'], 400);
  495.         }
  496.         $userId $data['userId'];
  497.         $companyId $data['companyId'];
  498.         $signatureData $data['signatureData'];
  499.         $approvalHash $data['approvalHash'];
  500.         $applicantId $data['applicantId'];
  501.         try {
  502.             $centralUser $em
  503.                 ->getRepository("CompanyGroupBundle\\Entity\\EntityApplicantDetails")
  504.                 ->findOneBy(['applicantId' => $applicantId]);
  505.             if (!$centralUser) {
  506.                 return new JsonResponse(['success' => false'message' => 'Central user not found.'], 404);
  507.             }
  508.             $userAppIds json_decode($centralUser->getUserAppIds(), true);
  509.             if (!is_array($userAppIds)) $userAppIds = [];
  510.             $companies $em->getRepository('CompanyGroupBundle\\Entity\\CompanyGroup')->findBy([
  511.                 'appId' => $userAppIds
  512.             ]);
  513.             if (count($companies) < 1) {
  514.                 return new JsonResponse(['success' => false'message' => 'No companies found for userAppIds.'], 404);
  515.             }
  516.             $repo $em->getRepository('CompanyGroupBundle\\Entity\\EntitySignature');
  517.             $record $repo->findOneBy(['userId' => $userId]);
  518.             if (!$record) {
  519.                 $record = new \CompanyGroupBundle\Entity\EntitySignature();
  520.                 $record->setUserId($applicantId);
  521.                 $record->setCreatedAt(new \DateTime());
  522.             }
  523.             $record->setCompanyId($companyId);
  524.             $record->setApplicantId($applicantId);
  525.             $record->setData($signatureData);
  526.             $record->setSigExists(0);
  527.             $record->setLastDecryptedSigId(0);
  528.             $record->setUpdatedAt(new \DateTime());
  529.             $em->persist($record);
  530.             $em->flush();
  531.             $dataByServerId = [];
  532.             $gocDataListByAppId = [];
  533.             foreach ($companies as $entry) {
  534.                 $gocDataListByAppId[$entry->getAppId()] = [
  535.                     'dbName' => $entry->getDbName(),
  536.                     'dbUser' => $entry->getDbUser(),
  537.                     'dbPass' => $entry->getDbPass(),
  538.                     'dbHost' => $entry->getDbHost(),
  539.                     'serverAddress' => $entry->getCompanyGroupServerAddress(),
  540.                     'port' => $entry->getCompanyGroupServerPort() ?: 80,
  541.                     'appId' => $entry->getAppId(),
  542.                     'serverId' => $entry->getCompanyGroupServerId(),
  543.                 ];
  544.                 if (!isset($dataByServerId[$entry->getCompanyGroupServerId()]))
  545.                     $dataByServerId[$entry->getCompanyGroupServerId()] = array(
  546.                         'serverId' => $entry->getCompanyGroupServerId(),
  547.                         'serverAddress' => $entry->getCompanyGroupServerAddress(),
  548.                         'port' => $entry->getCompanyGroupServerPort() ?: 80,
  549.                         'payload' => array(
  550.                             'globalId' => $applicantId,
  551.                             'companyId' => $userAppIds,
  552.                             'signatureData' => $signatureData,
  553. //                                      'approvalHash' => $approvalHash
  554.                         )
  555.                     );
  556.             }
  557.             $urls = [];
  558.             foreach ($dataByServerId as $entry) {
  559.                 $serverAddress $entry['serverAddress'];
  560.                 if (!$serverAddress) continue;
  561. //                     $connector = $this->container->get('application_connector');
  562. //                     $connector->resetConnection(
  563. //                         'default',
  564. //                         $entry['dbName'],
  565. //                         $entry['dbUser'],
  566. //                         $entry['dbPass'],
  567. //                         $entry['dbHost'],
  568. //                         $reset = true
  569. //                     );
  570.                 $syncUrl $serverAddress '/ReceiveSignatureFromCentral';
  571.                 $payload $entry['payload'];
  572.                 $curl curl_init();
  573.                 curl_setopt_array($curl, [
  574.                     CURLOPT_RETURNTRANSFER => true,
  575.                     CURLOPT_POST => true,
  576.                     CURLOPT_URL => $syncUrl,
  577. //                         CURLOPT_PORT => $entry['port'],
  578.                     CURLOPT_CONNECTTIMEOUT => 10,
  579.                     CURLOPT_SSL_VERIFYPEER => false,
  580.                     CURLOPT_SSL_VERIFYHOST => false,
  581.                     CURLOPT_HTTPHEADER => [
  582.                         'Accept: application/json',
  583.                         'Content-Type: application/json'
  584.                     ],
  585.                     CURLOPT_POSTFIELDS => json_encode($payload)
  586.                 ]);
  587.                 $response curl_exec($curl);
  588.                 $err curl_error($curl);
  589.                 $httpCode curl_getinfo($curlCURLINFO_HTTP_CODE);
  590.                 curl_close($curl);
  591. //                     if ($err) {
  592. //                         error_log("ERP Sync Error [AppID $appId]: $err");
  593. //                          $urls[]=$err;
  594. //                     } else {
  595. //                         error_log("ERP Sync Response [AppID $appId] (HTTP $httpCode): $response");
  596. //                         $res = json_decode($response, true);
  597. //                         if (!isset($res['success']) || !$res['success']) {
  598. //                             error_log("❗ ERP Sync error for AppID $appId: " . ($res['message'] ?? 'Unknown'));
  599. //                         }
  600. //
  601. //                      $urls[]=$response;
  602. //                     }
  603.             }
  604.             return new JsonResponse(['success' => true'message' => 'Signature synced successfully.']);
  605.         } catch (\Exception $e) {
  606.             return new JsonResponse(['success' => false'message' => 'DB error: ' $e->getMessage()], 500);
  607.         }
  608.     }
  609.     public function ReceiveSignatureFromCentralAction(Request $request)
  610.     {
  611.         $data json_decode($request->getContent(), true);
  612.         if (
  613.             !$data ||
  614.             !isset($data['globalId']) ||
  615.             !isset($data['companyId']) ||
  616.             !isset($data['signatureData'])
  617.         ) {
  618.             return new JsonResponse(['success' => false'message' => 'Missing required fields'], 400);
  619.         }
  620.         $em_goc $this->getDoctrine()->getManager('company_group');
  621.         $globalId $data['globalId'];
  622.         $signatureData $data['signatureData'];
  623.         $companyId $data['companyId'];
  624.         $companies $em_goc->getRepository('CompanyGroupBundle\\Entity\\CompanyGroup')->findBy([
  625.             'appId' => $companyId
  626.         ]);
  627.         foreach ($companies as $entry) {
  628.             $goc = [
  629.                 'dbName' => $entry->getDbName(),
  630.                 'dbUser' => $entry->getDbUser(),
  631.                 'dbPass' => $entry->getDbPass(),
  632.                 'dbHost' => $entry->getDbHost(),
  633.                 'serverAddress' => $entry->getCompanyGroupServerAddress(),
  634.                 'port' => $entry->getCompanyGroupServerPort() ?: 80,
  635.                 'appId' => $entry->getAppId(),
  636. //                                 'serverId' => $entry->getServerId(),
  637.             ];
  638.             $connector $this->container->get('application_connector');
  639.             $connector->resetConnection(
  640.                 'default',
  641.                 $goc['dbName'],
  642.                 $goc['dbUser'],
  643.                 $goc['dbPass'],
  644.                 $goc['dbHost'],
  645.                 $reset true
  646.             );
  647.             $em $this->getDoctrine()->getManager();
  648.             $user $em->getRepository('ApplicationBundle\\Entity\\SysUser')->findOneBy(['globalId' => $globalId]);
  649.             if (!$user) {
  650.                 return new JsonResponse(['success' => false'message' => 'User not found'], 404);
  651.             }
  652.             $sig $em->getRepository('ApplicationBundle\\Entity\\EncryptedSignature')->findOneBy(['userId' => $user->getUserId()]);
  653.             if (!$sig) {
  654.                 $sig = new \ApplicationBundle\Entity\EncryptedSignature();
  655.                 $sig->setUserId($user->getUserId());
  656.                 $sig->setData($signatureData);
  657.                 $sig->setCreatedAt(new \DateTime());
  658.             }
  659.             $sig->setCompanyId($companyId);
  660.             $sig->setData($signatureData);
  661.             $sig->setSigExists(1);
  662.             $sig->setLastDecryptedSigId(0);
  663.             $sig->setUpdatedAt(new \DateTime());
  664.             $em->persist($sig);
  665.             $em->flush();
  666.         }
  667.         return new JsonResponse(['success' => true'message' => 'Signature updated in ERP']);
  668.     }
  669.     public function CheckSignatureHashAction(Request $request)
  670.     {
  671.         $details_ids = [];
  672.         $em $this->getDoctrine()->getManager();
  673.         if ($request->isMethod('POST')) {
  674.             $em $this->getDoctrine()->getManager();
  675.             $loginId $request->getSession()->get(UserConstants::USER_LOGIN_ID);
  676.             $approveHash $request->request->get('approvalHash');
  677. //
  678.             $retData DocValidation::isSignatureOk($em$loginId$approveHash1);
  679. //            $this->addFlash(
  680. //                'success',
  681. //                'New Transaction Added.'
  682. //            );
  683.             return new JsonResponse(array(
  684.                 "success" => $retData['success'],
  685.                 "data" => $retData['data'],
  686.             ));
  687.         }
  688.         return $this->render('@Application/pages/accounts/input_forms/payment_voucher.html.twig',
  689.             array(
  690.                 'test' => $details_ids,
  691.             )
  692.         );
  693.     }
  694.     public function CheckSignatureHashForAppAction(Request $request)
  695.     {
  696.         $details_ids = [];
  697.         $em $this->getDoctrine()->getManager();
  698.         if ($request->isMethod('POST')) {
  699.             $em $this->getDoctrine()->getManager();
  700.             $loginId $request->getSession()->get(UserConstants::USER_LOGIN_ID);
  701.             $approveHash $request->request->get('approvalHash');
  702. //
  703.             $retData DocValidation::isSignatureOk($em$loginId$approveHash1);
  704. //            $this->addFlash(
  705. //                'success',
  706. //                'New Transaction Added.'
  707. //            );
  708.             return new JsonResponse(array(
  709.                 "success" => $retData['success'],
  710. //                "data"=>$retData['data'],
  711.             ));
  712.         }
  713.         return $this->render('@Application/pages/accounts/input_forms/payment_voucher.html.twig',
  714.             array(
  715.                 'test' => $details_ids,
  716.             )
  717.         );
  718.     }
  719.     public function approvalRoleAction()
  720.     {
  721.         $approvalRole GeneralConstant::$approvalRoleList;
  722.         return new JsonResponse($approvalRole);
  723.     }
  724.     public function PendingApprovalListAction(Request $request)
  725.     {
  726.         $em $this->getDoctrine()->getManager();
  727.         $login_id $this->getLoggedUserLoginId($request);
  728.         $pending_data System::getPendingApprovalListByUserLoginId($em$login_id);
  729. //        $user_data=Users::getUserInfoByLoginId($em,$login_id);
  730.         //1st get only currently pendings
  731.         if ($request->request->has('getSummaryData'))
  732.             $pending_data MiscActions::getSummaryData($em$pending_data);
  733.         $pending_approval_list $pending_data['pending_approval_list'];
  734.         $override_approval_list $pending_data['override_approval_list'];
  735.         if ($request->request->has('returnJson')) {
  736.             return new JsonResponse(
  737.                 array(
  738.                     'success' => true,
  739.                     'page_title' => 'View',
  740.                     'override_approval_list' => $override_approval_list,
  741.                     'pending_approval_list' => $pending_approval_list
  742. //                'productByCodeData' => $productByCodeData,
  743. //                'productData' => $productData,
  744. //                'currInvList' => $currInvList,
  745. //                'productList' => Inventory::ProductList($em, $companyId),
  746. //                'subCategoryList' => Inventory::ProductSubCategoryList($em, $companyId),
  747. //                'categoryList' => Inventory::ProductCategoryList($em, $companyId),
  748. //                'igList' => Inventory::ItemGroupList($em, $companyId),
  749. //                'unitList' => Inventory::UnitTypeList($em),
  750. //                'brandList' => Inventory::GetBrandList($em, $companyId),
  751. //                'warehouse_action_list' => Inventory::warehouse_action_list($em,$this->getLoggedUserCompanyId($request),'object'),
  752. //                'warehouseList' => Inventory::WarehouseList($em),
  753.                 )
  754.             );
  755.         }
  756.         return $this->render('@System/pages/settings/my_pending_list.html.twig',
  757.             array(
  758.                 'page_title' => 'View',
  759.                 'override_approval_list' => $override_approval_list,
  760.                 'pending_approval_list' => $pending_approval_list
  761.             )
  762.         );
  763.     }
  764.     public function getApprovalLogAction(Request $request)
  765.     {
  766.         $em $this->getDoctrine()->getManager();
  767.         $entityId $request->query->get('entityId');
  768.         $entity $request->query->get('entity');
  769.             $doc $em->getRepository('ApplicationBundle\\Entity\\' GeneralConstant::$Entity_list[$entity])
  770.             ->findOneBy(
  771.                 array(
  772.                     GeneralConstant::$Entity_id_field_list[$entity] => $entityId,
  773.                 )
  774.             );
  775.         $log_data = [];
  776.         $data = [];
  777.         $pending_data = [];
  778.         $remaining_data = [];
  779.         $created_data = [];
  780.         $created_data['dt'] = [];
  781.         $edited_data = [];
  782.         $edited_data['dt'] = [];
  783.         if($doc) {
  784.             $set $em->getRepository('ApplicationBundle\\Entity\\Approval')
  785.                 ->findBy(
  786.                     array(
  787.                         'entity' => $entity,
  788.                         'entityId' => $entityId,
  789.                     )
  790.                 );
  791.             $roleType GeneralConstant::$approvalRole;
  792.             //        $approvalRoles=GeneralConstant::$approvalRoleForPrint;
  793.             //now add additional roles form dbase
  794.             $addRoles $em->getRepository('ApplicationBundle\\Entity\\ApprovalRole')
  795.                 ->findBy(
  796.                     array( //                    'id' => $v->getSigId()
  797.                     )
  798.                 );
  799.             foreach ($addRoles as $addRole) {
  800.                 $roleType[$addRole->getIndexId()] = $addRole->getName();
  801.             }
  802.             if ($doc->getCreatedLoginId() && $doc->getCreatedLoginId() != && $doc->getCreatedLoginId() != null) {
  803.                 $usrDT Users::getUserInfoByLoginId($em$doc->getCreatedLoginId());
  804.                 if (isset($usrDT['id'])) {
  805.                     $gg Users::getUserInfoByUserId($em$usrDT['id']);
  806.                     $gg['action'] = '';
  807.                     $gg['sequence'] = 0;
  808.                     $gg['actionId'] = 0;
  809.                     $gg['role'] = 1;
  810.                     $gg['roleName'] = GeneralConstant::$approvalRole[1];
  811.                     $gg['note'] = '';
  812.                     $gg['current'] = 0;
  813.                     $gg['loginIp'] = $usrDT['loginIp'];
  814.                     $gg['dateTs'] = $doc->getCreatedAt()->format('U');
  815.                     $data[] = $gg;
  816.                 }
  817.             }
  818.             if ($doc->getEditedLoginId() != null && $doc->getEditedLoginId() != 0) {
  819.                 $usrDT Users::getUserInfoByLoginId($em$doc->getEditedLoginId());
  820.                 if (isset($usrDT['id'])) {
  821.                     $gg Users::getUserInfoByUserId($em$usrDT['id']);
  822.                     $gg['action'] = '';
  823.                     $gg['sequence'] = 0;
  824.                     $gg['actionId'] = 0;
  825.                     $gg['role'] = 2;
  826.                     $gg['roleName'] = GeneralConstant::$approvalRole[2];
  827.                     $gg['note'] = '';
  828.                     $gg['current'] = 0;
  829. //                $gg['date'] = $doc->getUpdatedAt();
  830.                     $gg['loginIp'] = $usrDT['loginIp'];
  831.                     $gg['dateTs'] = $doc->getUpdatedAt()->format('U');
  832.                     $data[] = $gg;
  833.                 }
  834.             }
  835.             //        $remaining_data=[];
  836.             foreach ($roleType as $key => $value) {
  837.                 $log_data[$key] = array(
  838.                     'role_name' => $value,
  839.                     'dt' => []
  840.                 );
  841.             }
  842.             foreach ($set as $entry) {
  843.                 if ($entry->getAction() == 3) {
  844.                     foreach (json_decode($entry->getUserIds(), true) as $item)
  845.                         if ($item != null) {
  846.                             $gg Users::getUserInfoByUserId($em$item);
  847.                             $gg['action'] = GeneralConstant::$approvalAction[$entry->getAction()];
  848.                             $gg['sequence'] = $entry->getSequence();
  849.                             $gg['actionId'] = $entry->getAction();
  850.                             $gg['role'] = $entry->getRoleType();
  851.                             $gg['roleName'] = GeneralConstant::$approvalRole[$entry->getRoleType()];
  852.                             $gg['note'] = $entry->getNote();
  853.                             $gg['current'] = $entry->getCurrent() == GeneralConstant::CURRENTLY_PENDING_APPROVAL 0;
  854.                             $gg['dateTs'] = $doc->getUpdatedAt()->format('U');
  855.                             $data[] = $gg;
  856.                         }
  857.                 } else {
  858.                     $usrDT Users::getUserInfoByLoginId($em$doc->getCreatedLoginId());
  859.                     if (isset($usrDT['id'])) {
  860.                         $gg Users::getUserInfoByUserId($em$usrDT['id']);
  861.                         $gg['action'] = GeneralConstant::$approvalAction[$entry->getAction()];
  862.                         $gg['sequence'] = $entry->getSequence();
  863.                         $gg['actionId'] = $entry->getAction();
  864.                         $gg['role'] = $entry->getRoleType();
  865.                         $gg['roleName'] = GeneralConstant::$approvalRole[$entry->getRoleType()];
  866.                         $gg['note'] = $entry->getNote();
  867.                         $gg['current'] = $entry->getCurrent() == GeneralConstant::CURRENTLY_PENDING_APPROVAL 0;
  868.                         $gg['dateTs'] = $usrDT['logTime']->format('U');
  869.                         $gg['loginIp'] = $usrDT['loginIp'];
  870.                         $data[] = $gg;
  871.                     }
  872.                 }
  873.             }
  874.         }
  875.         return new JsonResponse([
  876.             "message" => !empty($data) ? "success" "false",
  877.             "data" => empty($data) ? "No data found using the entity" $data
  878.         ]);
  879.     }
  880.     public function getDocumentDataAction(Request $request)
  881.     {
  882.         $entityListDetails GeneralConstant::$Entity_list_details;
  883.         $entityListForApp = [];
  884.         foreach ($entityListDetails as $id => $entity) {
  885.             $entityListForApp[] = [
  886.                 'id' => $id,
  887.                 'entity_alias' => $entity['entity_alias'],
  888.                 'imageUrl' => isset($entity['image_url']) ? $entity['image_url'] : 'app_asset/default_document.svg'
  889.             ];
  890.         }
  891.         return new JsonResponse($entityListForApp);
  892.     }
  893.     public function documentSummaryAction(Request $request)
  894.     {
  895.         // No document context here, so return an empty key-facts list rather than the
  896.         // Lorem-Ipsum placeholder (mobile shows a graceful fallback). Real per-document
  897.         // rows come from pending_approval_list[i].summary. See APPROVAL_SUMMARY_FIX.md.
  898.         return new JsonResponse([]);
  899.     }
  900. }