src/Controller/DistributorsController.php line 75

  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Addresses;
  4. use App\Entity\AiProducts;
  5. use App\Entity\AiProductsSpecies;
  6. use App\Entity\Api;
  7. use App\Entity\ApiDetails;
  8. use App\Entity\AvailabilityTracker;
  9. use App\Entity\Clinics;
  10. use App\Entity\ClinicUsers;
  11. use App\Entity\Countries;
  12. use App\Entity\CronJob;
  13. use App\Entity\DistributorProducts;
  14. use App\Entity\Distributors;
  15. use App\Entity\DistributorUserPermissions;
  16. use App\Entity\DistributorUsers;
  17. use App\Entity\Notifications;
  18. use App\Entity\Products;
  19. use App\Entity\RefreshTokens;
  20. use App\Entity\RestrictedDomains;
  21. use App\Entity\ScraperUrls;
  22. use App\Entity\Tracking;
  23. use App\Entity\UserPermissions;
  24. use App\Form\AddressesFormType;
  25. use App\Form\DistributorFormType;
  26. use App\Form\DistributorUsersFormType;
  27. use App\Services\PaginationManager;
  28. use Doctrine\ORM\EntityManagerInterface;
  29. use Nzo\UrlEncryptorBundle\Encryptor\Encryptor;
  30. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  31. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  32. use Symfony\Component\HttpFoundation\JsonResponse;
  33. use Symfony\Component\HttpFoundation\Request;
  34. use Symfony\Component\HttpFoundation\RequestStack;
  35. use Symfony\Component\HttpFoundation\Response;
  36. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  37. use Symfony\Component\Mailer\MailerInterface;
  38. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  39. use Symfony\Component\Routing\Annotation\Route;
  40. use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
  41. class DistributorsController extends AbstractController
  42. {
  43. private $em;
  44. const ITEMS_PER_PAGE = 10;
  45. private $pageManager;
  46. private $requestStack;
  47. private $plainPassword;
  48. private $encryptor;
  49. private $mailer;
  50. public function __construct(EntityManagerInterface $em, PaginationManager $pagination, RequestStack $requestStack, Encryptor $encryptor, MailerInterface $mailer)
  51. {
  52. $this->em = $em;
  53. $this->pageManager = $pagination;
  54. $this->requestStack = $requestStack;
  55. $this->encryptor = $encryptor;
  56. $this->mailer = $mailer;
  57. }
  58. #[Route('/distributors/dashboard', name: 'distributor_dashboard')]
  59. #[Route('/distributors/account', name: 'distributor_account')]
  60. #[Route('/distributors/about', name: 'distributor_about')]
  61. #[Route('/distributors/operating-hours', name: 'distributor_operating_hours')]
  62. #[Route('/distributors/refund-policy', name: 'distributor_refund_policy')]
  63. #[Route('/distributors/sales-tax-policy', name: 'distributor_sales_tax_policy')]
  64. #[Route('/distributors/shipping-policy', name: 'distributor_shipping_policy')]
  65. #[Route('/distributors/manage-inventory', name: 'distributor_manage_inventory')]
  66. #[Route('/distributors/users', name: 'distributor_get_users')]
  67. #[Route('/distributors/order/{order_id}', name: 'distributor_order')]
  68. #[Route('/distributors/orders/{distributor_id}', name: 'distributor_order_list')]
  69. #[Route('/distributors/customers/1', name: 'distributor_customer_list')]
  70. #[Route('/distributors/inventory/list', name: 'distributor_inventory_list')]
  71. public function distributorDashboardAction(Request $request): Response
  72. {
  73. if($this->getUser()->getUserIdentifier() == null){
  74. $this->addFlash('danger', 'Your session expired due to inactivity, please login.');
  75. return $this->redirectToRoute('distributor_login');
  76. }
  77. $distributor = $this->getUser()->getDistributor();
  78. $user = $this->getUser();
  79. $username = $distributor->getDistributorName();
  80. $permissions = [];
  81. foreach($user->getDistributorUserPermissions() as $permission){
  82. $permissions[] = $permission->getPermission()->getId();
  83. }
  84. return $this->render('frontend/distributors/index.html.twig',[
  85. 'distributor' => $distributor,
  86. 'permissions' => json_encode($permissions),
  87. 'username' => $username,
  88. ]);
  89. }
  90. #[Route('/distributors/register', name: 'distributor_reg')]
  91. public function distributorReg(Request $request): Response
  92. {
  93. $countries = $this->em->getRepository(Countries::class)->findBy([
  94. 'isActive' => 1,
  95. ]);
  96. $form = $this->createRegisterForm();
  97. return $this->render('frontend/distributors/register.html.twig', [
  98. 'form' => $form->createView(),
  99. 'countries' => $countries
  100. ]);
  101. }
  102. #[Route('/sellers', name: 'sellers_page')]
  103. public function sellersAction(Request $request): Response
  104. {
  105. $sellers = $this->em->getRepository(Distributors::class)->findBy([
  106. 'isApproved' => true,
  107. ]);
  108. return $this->render('frontend/sellers.html.twig', [
  109. 'sellers' => $sellers,
  110. ]);
  111. }
  112. protected function createRegisterForm()
  113. {
  114. $distributors = new Distributors();
  115. return $this->createForm(DistributorFormType::class, $distributors);
  116. }
  117. #[Route('/distributors/register/check-email', name: 'distributor_check_email')]
  118. public function distributorsCheckEmailAction(Request $request): Response
  119. {
  120. $email = $request->request->get('email');
  121. $domainName = explode('@', $email);
  122. $response['response'] = true;
  123. $firstName = '';
  124. $restrictedDomains = $this->em->getRepository(RestrictedDomains::class)->arrayFindAll();
  125. foreach($restrictedDomains as $restrictedDomain)
  126. {
  127. if(md5($domainName[1]) == md5($restrictedDomain->getName()))
  128. {
  129. $response['response'] = false;
  130. $response['restricted'] = true;
  131. return new JsonResponse($response);
  132. }
  133. }
  134. $distributor = $this->em->getRepository(Distributors::class)->findOneBy([
  135. 'hashedEmail' => md5($email),
  136. ]);
  137. $distributorDomain = $this->em->getRepository(Distributors::class)->findOneBy([
  138. 'domainName' => md5($domainName[1]),
  139. ]);
  140. $distributorUsers = $this->em->getRepository(DistributorUsers::class)->findOneBy([
  141. 'hashedEmail' => md5($email),
  142. ]);
  143. $clinic = $this->em->getRepository(Clinics::class)->findOneBy([
  144. 'hashedEmail' => md5($email),
  145. ]);
  146. $clinicDomain = $this->em->getRepository(Clinics::class)->findOneBy([
  147. 'domainName' => md5($domainName[1]),
  148. ]);
  149. $clinicUsers = $this->em->getRepository(ClinicUsers::class)->findOneBy([
  150. 'hashedEmail' => md5($email),
  151. ]);
  152. if($clinicDomain != null)
  153. {
  154. $user = $this->em->getRepository(ClinicUsers::class)->findOneBy([
  155. 'clinic' => $clinicDomain->getId(),
  156. 'isPrimary' => 1
  157. ]);
  158. $firstName = $this->encryptor->decrypt($user->getFirstName());
  159. }
  160. if($distributorDomain != null)
  161. {
  162. $user = $this->em->getRepository(DistributorUsers::class)->findOneBy([
  163. 'distributor' => $distributorDomain->getId(),
  164. 'isPrimary' => 1
  165. ]);
  166. $firstName = $this->encryptor->decrypt($user->getFirstName());
  167. }
  168. $response['firstName'] = $firstName;
  169. if($distributor != null || $distributorUsers != null || $clinic != null || $clinicUsers != null || $clinicDomain != null || $distributorDomain != null)
  170. {
  171. $response['response'] = false;
  172. $response['restricted'] = false;
  173. }
  174. return new JsonResponse($response);
  175. }
  176. #[Route('/distributor/addresses', name: 'distributor_addresses')]
  177. public function createDistributorAddressesForm()
  178. {
  179. $addresses = new Addresses();
  180. return $this->createForm(AddressesFormType::class, $addresses);
  181. }
  182. #[Route('/distributor/register/create', name: 'distributor_create')]
  183. public function distributorCreateAction(Request $request, UserPasswordHasherInterface $passwordHasher, MailerInterface $mailer): Response
  184. {
  185. $data = $request->request;
  186. $distributor = $this->em->getRepository(Distributors::class)->findOneBy(['email' => $data->get('email')]);
  187. $countries = $this->em->getRepository(Countries::class)->find($data->get('country'));
  188. $tracking = $this->em->getRepository(Tracking::class)->find(3);
  189. if($distributor == null) {
  190. $distributors = new Distributors();
  191. $plainTextPwd = $this->generatePassword();
  192. if (!empty($plainTextPwd)) {
  193. $domainName = explode('@', $data->get('email'));
  194. $distributors->setDistributorName($this->encryptor->encrypt($data->get('distributor-name')));
  195. $distributors->setEmail($this->encryptor->encrypt($data->get('email')));
  196. $distributors->setHashedEmail(md5($data->get('email')));
  197. $distributors->setDomainName(md5($domainName[1]));
  198. $distributors->setTelephone($this->encryptor->encrypt($data->get('telephone')));
  199. $distributors->setIntlCode($this->encryptor->encrypt($data->get('intl-code')));
  200. $distributors->setIsoCode($this->encryptor->encrypt($data->get('iso-code')));
  201. $distributors->setAddressCountry($countries);
  202. $distributors->setTracking($tracking);
  203. $distributors->setIsApproved(0);
  204. $this->em->persist($distributors);
  205. $this->em->flush();
  206. // Create user
  207. $distributor = $this->em->getRepository(Distributors::class)->findOneBy([
  208. 'hashedEmail' => md5($data->get('email')),
  209. ]);
  210. $distributorUsers = new DistributorUsers();
  211. $hashed_pwd = $passwordHasher->hashPassword($distributorUsers, $plainTextPwd);
  212. $distributorUsers->setDistributor($distributor);
  213. $distributorUsers->setFirstName($this->encryptor->encrypt($data->get('first-name')));
  214. $distributorUsers->setLastName($this->encryptor->encrypt($data->get('last-name')));
  215. $distributorUsers->setPosition($this->encryptor->encrypt($data->get('position')));
  216. $distributorUsers->setEmail($this->encryptor->encrypt($data->get('email')));
  217. $distributorUsers->setHashedEmail(md5($data->get('email')));
  218. $distributorUsers->setTelephone($this->encryptor->encrypt($data->get('telephone')));
  219. $distributorUsers->setRoles(['ROLE_DISTRIBUTOR']);
  220. $distributorUsers->setPassword($hashed_pwd);
  221. $distributorUsers->setIsPrimary(1);
  222. $this->em->persist($distributorUsers);
  223. $this->em->flush();
  224. // Assign User Permissions
  225. $userPermissions = $this->em->getRepository(UserPermissions::class)->findBy([
  226. 'isDistributor' => 1,
  227. ]);
  228. foreach($userPermissions as $userPermission){
  229. $distributorUserPermissions = new DistributorUserPermissions();
  230. $distributorUserPermissions->setUser($distributorUsers);
  231. $distributorUserPermissions->setDistributor($distributors);
  232. $distributorUserPermissions->setPermission($userPermission);
  233. $this->em->persist($distributorUserPermissions);
  234. }
  235. $this->em->flush();
  236. // Send Email
  237. $body = '<table style="padding: 8px; border-collapse: collapse; border: none; font-family: arial">';
  238. $body .= '<tr><td colspan="2">Hi '. $data->get('first_name') .',</td></tr>';
  239. $body .= '<tr><td colspan="2">&nbsp;</td></tr>';
  240. $body .= '<tr><td colspan="2">Please use the credentials below login to the Fluid Backend.</td></tr>';
  241. $body .= '<tr><td colspan="2">&nbsp;</td></tr>';
  242. $body .= '<tr>';
  243. $body .= ' <td><b>URL: </b></td>';
  244. $body .= ' <td><a href="https://'. $_SERVER['HTTP_HOST'] .'/distributors/login">https://'. $_SERVER['HTTP_HOST'] .'/distributor/login</a></td>';
  245. $body .= '</tr>';
  246. $body .= '<tr>';
  247. $body .= ' <td><b>Username: </b></td>';
  248. $body .= ' <td>'. $data->get('email') .'</td>';
  249. $body .= '</tr>';
  250. $body .= '<tr>';
  251. $body .= ' <td><b>Password: </b></td>';
  252. $body .= ' <td>'. $plainTextPwd .'</td>';
  253. $body .= '</tr>';
  254. $body .= '</table>';
  255. $subject = 'Fluid Login Credentials';
  256. $to = $data->get('email');
  257. exec(__DIR__ . '/../../bin/console app:send-email "'. $subject .'" "'. addslashes($body) .'" "'. $to .'" "" "" "'. true .'" > /dev/null 2>&1 &');
  258. }
  259. $response = '
  260. <div class="row pt-3">
  261. <div class="col-12 text-center mt-1 pt-3 pb-3" id="order_header">
  262. <h4 class="text-primary">Let\'s Create Your Account.</h4>
  263. <span class="text-primary">
  264. Your Fluid account was successfully created, an email with your login credentials has been sent to your inbox.
  265. </span>
  266. </div>';
  267. } else {
  268. $response = false;
  269. }
  270. return new JsonResponse($response);
  271. }
  272. #[Route('/distributors/get/company-information', name: 'get_company_information')]
  273. public function getCompanyInformation(Request $request): Response
  274. {
  275. $distributorId = $this->getUser()->getDistributor()->getId();
  276. $distributor = $this->em->getRepository(Distributors::class)->find($distributorId);
  277. $countries = $this->em->getRepository(Countries::class)->findAll();
  278. $html = $this->render('frontend/distributors/company_information.html.twig', [
  279. 'distributor' => $distributor,
  280. 'countries' => $countries,
  281. ])->getContent();
  282. return new JsonResponse($html);
  283. }
  284. private function generatePassword(): string
  285. {
  286. $curl = curl_init();
  287. curl_setopt_array($curl, array(
  288. CURLOPT_URL => 'https://www.dinopass.com/password/simple',
  289. CURLOPT_RETURNTRANSFER => true,
  290. CURLOPT_ENCODING => '',
  291. CURLOPT_MAXREDIRS => 10,
  292. CURLOPT_TIMEOUT => 0,
  293. CURLOPT_FOLLOWLOCATION => true,
  294. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  295. CURLOPT_CUSTOMREQUEST => 'GET',
  296. ));
  297. $response = curl_exec($curl);
  298. curl_close($curl);
  299. $this->plainPassword = $response;
  300. return $this->plainPassword;
  301. }
  302. public function createDistributorUserForm()
  303. {
  304. $distributorUsers = new DistributorUsers();
  305. return $this->createForm(DistributorUsersFormType::class, $distributorUsers);
  306. }
  307. #[Route('/distributors/update/company-information', name: 'distributor_update_company_information')]
  308. public function distributorUpdateCompanyInformationAction(Request $request): Response
  309. {
  310. $data = $request->request->all('distributor_form');
  311. $distributor = $this->getUser()->getDistributor();
  312. $countryId = (int) $data['addressCountry'];
  313. $logo = '';
  314. $country = $this->em->getRepository(Countries::class)->find($countryId);
  315. $isApproved = (bool) $distributor->getIsApproved() ?? false;
  316. $tradeLicense = $_FILES['distributor_form']['name']['trade-license-file'];
  317. $tradeLicenseNo = $data['trade-license-no'];
  318. $tradeLicenseExpDate = $data['trade-license-exp-date'];
  319. // Account approval required if reg docs change
  320. if(
  321. !empty($tradeLicense) || $tradeLicenseNo != $this->encryptor->decrypt($distributor->getTradeLicenseNo()) ||
  322. $tradeLicenseExpDate != $distributor->getTradeLicenseExpDate()->format('Y-m-d')
  323. )
  324. {
  325. $distributor->setIsApproved(0);
  326. $isApproved = false;
  327. }
  328. if($distributor != null)
  329. {
  330. $domainName = explode('@', $data['email']);
  331. $distributor->setDistributorName($this->encryptor->encrypt($data['distributor-name']));
  332. $distributor->setTelephone($this->encryptor->encrypt($data['telephone']));
  333. $distributor->setEmail($this->encryptor->encrypt($data['email']));
  334. $distributor->setWebsite($this->encryptor->encrypt($data['website']));
  335. $distributor->setDomainName(md5($domainName[1]));
  336. $distributor->setAddressCountry($country);
  337. $distributor->setAddressStreet($this->encryptor->encrypt($data['address-street']));
  338. $distributor->setAddressCity($this->encryptor->encrypt($data['address-city']));
  339. $distributor->setAddressPostalCode($this->encryptor->encrypt($data['address-postal-code']));
  340. $distributor->setAddressState($this->encryptor->encrypt($data['address-state']));
  341. $distributor->setIsoCode($this->encryptor->encrypt($data['iso-code']));
  342. $distributor->setIntlCode($this->encryptor->encrypt($data['intl-code']));
  343. $distributor->setManagerFirstName($this->encryptor->encrypt($data['manager-first-name']));
  344. $distributor->setManagerLastName($this->encryptor->encrypt($data['manager-last-name']));
  345. $distributor->setManagerIdNo($this->encryptor->encrypt($data['manager-id-no']));
  346. $distributor->setManagerIdExpDate(new \DateTime($data['manager-id-exp-date']));
  347. $distributor->setTradeLicenseNo($this->encryptor->encrypt($data['trade-license-no']));
  348. $distributor->setTradeLicenseExpDate(new \DateTime($data['trade-license-exp-date']));
  349. if(!empty($_FILES['distributor_form']['name']['trade-license-file']))
  350. {
  351. $extension = pathinfo($_FILES['distributor_form']['name']['trade-license-file'], PATHINFO_EXTENSION);
  352. $file = $distributor->getId() . '-' . uniqid() . '.' . $extension;
  353. $targetFile = __DIR__ . '/../../public/documents/' . $file;
  354. if(move_uploaded_file($_FILES['distributor_form']['tmp_name']['trade-license-file'], $targetFile))
  355. {
  356. $distributor->setTradeLicense($file);
  357. }
  358. }
  359. if(!empty($_FILES['distributor_form']['name']['logo']))
  360. {
  361. $extension = pathinfo($_FILES['distributor_form']['name']['logo'], PATHINFO_EXTENSION);
  362. $file = $distributor->getId() . '-' . uniqid() . '.' . $extension;
  363. $targetFile = __DIR__ . '/../../public/images/logos/' . $file;
  364. if (move_uploaded_file($_FILES['distributor_form']['tmp_name']['logo'], $targetFile))
  365. {
  366. $distributor->setLogo($file);
  367. $logo = $file;
  368. }
  369. }
  370. $this->em->persist($distributor);
  371. $this->em->flush();
  372. // Send Approval Email
  373. if(!$isApproved)
  374. {
  375. $orderUrl = $this->getParameter('app.base_url') . '/admin/distributor/'. $distributor->getId();
  376. $html = '<p>Please <a href="'. $orderUrl .'">click here</a> to view the distributors details.</p><br>';
  377. $html = $this->forward('App\Controller\ResetPasswordController::emailFooter', [
  378. 'html' => $html,
  379. ]);
  380. $subject = 'Fluid - Account Approval Request';
  381. $to = $this->getParameter('app.email_admin');
  382. exec(__DIR__ . '/../../bin/console app:send-email "'. $subject .'" "'. addslashes($html) .'" "'. $to .'" "" "" "'. true .'" > /dev/null 2>&1 &');
  383. }
  384. $message = '<b><i class="fa-solid fa-circle-check"></i></i></b> Company details successfully updated.<div class="flash-close"><i class="fa-solid fa-xmark"></i></div>';
  385. }
  386. else
  387. {
  388. $message = '<b><i class="fas fa-check-circle"></i> Personal details successfully updated.';
  389. }
  390. $response = [
  391. 'message' => $message,
  392. 'logo' => $logo,
  393. ];
  394. return new JsonResponse($response);
  395. }
  396. #[Route('/distributors/download/trade-license/{tradeLicense}', name: 'distributors_download_trade_license')]
  397. public function distributorDownloadTradeLicenseAction(Request $request)
  398. {
  399. $path = __DIR__ . '/../../public/documents/';
  400. $tradeLicense = $path . $request->get('tradeLicense');
  401. $response = new BinaryFileResponse($tradeLicense);
  402. $response->setContentDisposition(
  403. ResponseHeaderBag::DISPOSITION_ATTACHMENT,
  404. basename($tradeLicense)
  405. );
  406. return $response;
  407. }
  408. #[Route('/distributors/update/about_us', name: 'distributor_update_about_us')]
  409. public function distributorUpdateAboutUsAction(Request $request): Response
  410. {
  411. $data = $request->request;
  412. $distributor = $this->getUser()->getDistributor();
  413. if($distributor != null)
  414. {
  415. $about = $data->get('about-us');
  416. if(!empty($about))
  417. {
  418. $distributor->setAbout($about);
  419. $this->em->persist($distributor);
  420. $this->em->flush();
  421. }
  422. $response = '<b><i class="fa-solid fa-circle-check"></i></i></b> About us successfully updated.<div class="flash-close"><i class="fa-solid fa-xmark"></i></div>';
  423. }
  424. else
  425. {
  426. $response = '<b><i class="fas fa-check-circle"></i> An error occurred.';
  427. }
  428. return new JsonResponse($response);
  429. }
  430. #[Route('/distributors/update/operating_hours', name: 'distributor_update_operating_hours')]
  431. public function distributorUpdateOperatingHoursAction(Request $request): Response
  432. {
  433. $data = $request->request;
  434. $distributor = $this->getUser()->getDistributor();
  435. if($distributor != null)
  436. {
  437. if(!empty($data->get('operating-hours')))
  438. {
  439. $distributor->setOperatingHours($data->get('operating-hours'));
  440. }
  441. $this->em->persist($distributor);
  442. $this->em->flush();
  443. $response = '<b><i class="fa-solid fa-circle-check"></i></i></b> Operating hours successfully updated.<div class="flash-close"><i class="fa-solid fa-xmark"></i></div>';
  444. }
  445. else
  446. {
  447. $response = '<b><i class="fas fa-check-circle"></i> Personal details successfully updated.';
  448. }
  449. return new JsonResponse($response);
  450. }
  451. #[Route('/distributors/update/refund_policy', name: 'distributor_update_refund_policy')]
  452. public function distributorUpdateRefundPolicyAction(Request $request): Response
  453. {
  454. $data = $request->request;
  455. $distributor = $this->getUser()->getDistributor();
  456. if($distributor != null)
  457. {
  458. if(!empty($data->get('refund-policy')))
  459. {
  460. $distributor->setRefundPolicy($data->get('refund-policy'));
  461. }
  462. $this->em->persist($distributor);
  463. $this->em->flush();
  464. $response = '<b><i class="fa-solid fa-circle-check"></i></i></b> Refund policy successfully updated.<div class="flash-close"><i class="fa-solid fa-xmark"></i></div>';
  465. }
  466. else
  467. {
  468. $response = '<b><i class="fas fa-check-circle"></i> Personal details successfully updated.';
  469. }
  470. return new JsonResponse($response);
  471. }
  472. #[Route('/distributors/update/sales_tax_policy', name: 'distributor_update_sales_tax_policy')]
  473. public function distributorUpdateSalesTaxPolicyAction(Request $request): Response
  474. {
  475. $data = $request->request;
  476. $distributor = $this->getUser()->getDistributor();
  477. if($distributor != null)
  478. {
  479. if(!empty($data->get('sales-tax-policy')))
  480. {
  481. $distributor->setSalesTaxPolicy($data->get('sales-tax-policy'));
  482. }
  483. $this->em->persist($distributor);
  484. $this->em->flush();
  485. $response = '<b><i class="fa-solid fa-circle-check"></i></i></b> Sales tax policy successfully updated.<div class="flash-close"><i class="fa-solid fa-xmark"></i></div>';
  486. }
  487. else
  488. {
  489. $response = '<b><i class="fas fa-check-circle"></i> Personal details successfully updated.';
  490. }
  491. return new JsonResponse($response);
  492. }
  493. #[Route('/distributors/update/shipping_policy', name: 'distributor_update_shipping_policy')]
  494. public function distributorUpdateShippingPolicyAction(Request $request): Response
  495. {
  496. $data = $request->request;
  497. $distributor = $this->getUser()->getDistributor();
  498. if($distributor != null)
  499. {
  500. if(!empty($data->get('shipping-policy')))
  501. {
  502. $distributor->setShippingPolicy($data->get('shipping-policy'));
  503. }
  504. $this->em->persist($distributor);
  505. $this->em->flush();
  506. $response = '<b><i class="fa-solid fa-circle-check"></i></i></b> Shipping policy successfully updated.<div class="flash-close"><i class="fa-solid fa-xmark"></i></div>';
  507. }
  508. else
  509. {
  510. $response = '<b><i class="fas fa-check-circle"></i> Personal details successfully updated.';
  511. }
  512. return new JsonResponse($response);
  513. }
  514. #[Route('/distributors/get/about', name: 'get_about')]
  515. public function getAbout(Request $request): Response
  516. {
  517. $distributorId = $this->getUser()->getDistributor()->getId();
  518. $distributor = $this->em->getRepository(Distributors::class)->find($distributorId);
  519. $html = $this->render('frontend/distributors/about.html.twig', [
  520. 'distributor' => $distributor,
  521. ])->getContent();
  522. return new JsonResponse($html);
  523. }
  524. #[Route('/distributors/get/operating-hours', name: 'get_distributor_operating_hours')]
  525. public function getDistributorOperatingHours(Request $request): Response
  526. {
  527. $distributorId = $this->getUser()->getDistributor()->getId();
  528. $distributor = $this->em->getRepository(Distributors::class)->find($distributorId);
  529. $html = $this->render('frontend/distributors/operating_hours.html.twig', [
  530. 'distributor' => $distributor,
  531. ])->getContent();
  532. return new JsonResponse($html);
  533. }
  534. #[Route('/distributors/get/refund-policy', name: 'get_distributor_refund_policy')]
  535. public function getDistributorRefundPolicy(Request $request): Response
  536. {
  537. $distributorId = $this->getUser()->getDistributor()->getId();
  538. $distributor = $this->em->getRepository(Distributors::class)->find($distributorId);
  539. $html = $this->render('frontend/distributors/refund_policy.html.twig', [
  540. 'distributor' => $distributor,
  541. ])->getContent();
  542. return new JsonResponse($html);
  543. }
  544. #[Route('/distributors/get/sales-tax-policy', name: 'get_distributor_sales_tax_policy')]
  545. public function getDistributorSalesTaxPolicy(Request $request): Response
  546. {
  547. $distributorId = $this->getUser()->getDistributor()->getId();
  548. $distributor = $this->em->getRepository(Distributors::class)->find($distributorId);
  549. $html = $this->render('frontend/distributors/sales_tax_policy.html.twig', [
  550. 'distributor' => $distributor,
  551. ])->getContent();
  552. return new JsonResponse($html);
  553. }
  554. #[Route('/distributors/get/shipping-policy', name: 'get_distributor_shipping_policy')]
  555. public function getDistributorShippingPolicy(Request $request): Response
  556. {
  557. $distributorId = $this->getUser()->getDistributor()->getId();
  558. $distributor = $this->em->getRepository(Distributors::class)->find($distributorId);
  559. $html = $this->render('frontend/distributors/shipping_policy.htm.twig', [
  560. 'distributor' => $distributor,
  561. ])->getContent();
  562. return new JsonResponse($html);
  563. }
  564. #[Route('/distributors/inventory-search', name: 'distributor_inventory_search')]
  565. public function distributorInventorySearchAction(Request $request): Response
  566. {
  567. $products = $this->em->getRepository(Products::class)->findBySearch($request->get('keyword'));
  568. $select = '<ul id="product_list">';
  569. foreach($products as $product){
  570. $id = $product->getId();
  571. $name = $product->getName();
  572. $dosage = '';
  573. $size = '';
  574. if(!empty($product->getDosage())) {
  575. $unit = '';
  576. if(!empty($product->getUnit())) {
  577. $unit = $product->getUnit();
  578. }
  579. $dosage = ' | '. $product->getDosage() . $unit;
  580. }
  581. if(!empty($product->getSize())) {
  582. $size = ' | '. $product->getSize();
  583. }
  584. $select .= "
  585. <li
  586. class=\"search-item\"
  587. data-product-id=\"$id\"
  588. data-product-name=\"$name\"
  589. data-action='click->products--distributor-products#onclickEditIcon'
  590. >$name$dosage$size</li>
  591. ";
  592. }
  593. $select .= '</ul>';
  594. return new Response($select);
  595. }
  596. #[Route('/distributors/inventory-get', name: 'distributor_inventory_get')]
  597. public function distributorGetInventoryAction(Request $request,TokenStorageInterface $tokenStorage): Response
  598. {
  599. $productId = (int) $request->request->get('product-id');
  600. $products = $this->em->getRepository(Products::class)->find($productId);
  601. if($products != null)
  602. {
  603. $distributorId = $this->getUser()->getDistributor()->getId();
  604. $distributor = $this->em->getRepository(Distributors::class)->find($distributorId);
  605. $response = [];
  606. $response['html'] = json_decode($this->forward('App\Controller\DistributorProductsController::getDistributorProductAction')
  607. ->getContent());
  608. $distributorProduct = $this->em->getRepository(Distributors::class)
  609. ->getDistributorProduct($distributor->getId(), $productId);
  610. if($distributorProduct != null)
  611. {
  612. $response['distributor_id'] = $distributor->getId();
  613. $response['itemId'] = $distributorProduct[0]['distributorProducts'][0]['itemId'];
  614. $response['sku'] = $distributorProduct[0]['distributorProducts'][0]['sku'];
  615. $response['unit_price'] = $distributorProduct[0]['distributorProducts'][0]['unitPrice'];
  616. $response['stock_count'] = $distributorProduct[0]['distributorProducts'][0]['stockCount'];
  617. $response['expiry_date'] = '';
  618. $response['tax_exempt'] = $distributorProduct[0]['distributorProducts'][0]['taxExempt'];
  619. $response['product'] = $distributorProduct[0]['distributorProducts'][0]['product'];
  620. if($distributorProduct[0]['distributorProducts'][0]['expiryDate'] != null)
  621. {
  622. $response['expiry_date'] = $distributorProduct[0]['distributorProducts'][0]['expiryDate']->format('Y-m-d');
  623. }
  624. }
  625. else
  626. {
  627. $product = $this->em->getRepository(Products::class)->find($productId);
  628. $response['distributor_id'] = $distributor->getId();
  629. $response['sku'] = '';
  630. $response['distributor_no'] = '';
  631. $response['unit_price'] = '';
  632. $response['stock_count'] = '';
  633. $response['expiry_date'] = '';
  634. $response['tax_exempt'] = 0;
  635. $response['product'] = [
  636. 'dosage' => $product->getDosage(),
  637. 'size' => $product->getSize(),
  638. 'unit' => $product->getUnit(),
  639. 'activeIngredient' => $product->getActiveIngredient(),
  640. ];
  641. }
  642. }
  643. else
  644. {
  645. $response['message'] = 'Inventory item not found';
  646. }
  647. return new JsonResponse($response);
  648. }
  649. #[Route('/distributors/inventory-update', name: 'distributor_inventory_update')]
  650. public function distributorUpdateInventoryAction(Request $request, MailerInterface $mailer): Response
  651. {
  652. $data = $request->request->all('distributor_products_form');
  653. $product = $this->em->getRepository(Products::class)->find($data['product']);
  654. $distributor = $this->em->getRepository(Distributors::class)->find($data['distributor']);
  655. $distributorProducts = $this->em->getRepository(DistributorProducts::class)->findOneBy(
  656. [
  657. 'product' => $data['product'],
  658. 'distributor' => $data['distributor']
  659. ]
  660. );
  661. $tracking = false;
  662. $response['unitPrice'] = 0.00;
  663. $response['stockLevel'] = 0;
  664. if($distributorProducts == null){
  665. $distributorProducts = new DistributorProducts();
  666. } else {
  667. if($distributorProducts->getStockCount() == 0){
  668. $tracking = true;
  669. }
  670. }
  671. if(!empty($data['product']) && !empty($data['distributor'])){
  672. $trackingId = $distributor->getTracking()->getId();
  673. $distributorProducts->setDistributor($distributor);
  674. $distributorProducts->setProduct($product);
  675. $distributorProducts->setSku($data['sku']);
  676. $distributorProducts->setItemId($data['itemId']);
  677. $distributorProducts->setTaxExempt($data['taxExempt']);
  678. $distributorProducts->setIsActive(1);
  679. $taxExempt = 0;
  680. if(!empty($data['taxExempt'])){
  681. $taxExempt = $data['taxExempt'];
  682. }
  683. $distributorProducts->setTaxExempt($taxExempt);
  684. if($trackingId == 3)
  685. {
  686. $distributorProducts->setUnitPrice($data['unitPrice']);
  687. $distributorProducts->setStockCount((int)$data['stockCount']);
  688. }
  689. // Get stock and price from API
  690. if($trackingId == 1){
  691. // Retrieve price & stock from api
  692. $distributorId = $distributor->getId();
  693. $priceStockLevels = json_decode($this->forward('App\Controller\ProductsController::zohoRetrieveItem',[
  694. 'distributorId' => $distributorId,
  695. 'itemId' => $data['itemId'],
  696. ])->getContent(), true);
  697. $response['unitPrice'] = $priceStockLevels['unitPrice'] ?? 0.00;
  698. $response['stockLevel'] = $priceStockLevels['stockLevel'] ?? 0;
  699. $distributorProducts->setUnitPrice($response['unitPrice']);
  700. $distributorProducts->setStockCount($response['stockLevel']);
  701. }
  702. $this->em->persist($distributorProducts);
  703. $this->em->flush();
  704. // Update parent stock level
  705. $stockCount = $this->em->getRepository(DistributorProducts::class)->getProductStockCount($product->getId());
  706. $product->setStockCount($stockCount[0][1]);
  707. // Get the lowest price
  708. $lowestPrice = $this->em->getRepository(DistributorProducts::class)->getLowestPrice($product->getId());
  709. $product->setUnitPrice($lowestPrice[0]['unitPrice'] ?? 0.00);
  710. $this->em->persist($product);
  711. $this->em->flush();
  712. // Availability Tracker
  713. $availabilityTracker = '';
  714. if($tracking){
  715. $availabilityTracker = $this->em->getRepository(AvailabilityTracker::class)->findBy([
  716. 'product' => $product->getId(),
  717. 'distributor' => $data['distributor'],
  718. 'isSent' => 0,
  719. ]);
  720. foreach($availabilityTracker as $tracker){
  721. $methodId = $tracker->getCommunication()->getCommunicationMethod()->getId();
  722. $sendTo = $tracker->getCommunication()->getSendTo();
  723. $product = $tracker->getProduct();
  724. // In app notifications
  725. if($methodId == 1){
  726. $notifications = new Notifications();
  727. $notifications->setClinic($tracker->getClinic());
  728. $notifications->setIsRead(0);
  729. $notifications->setIsReadDistributor(0);
  730. $notifications->setIsActive(1);
  731. $notifications->setAvailabilityTracker($tracker);
  732. $this->em->persist($notifications);
  733. $this->em->flush();
  734. // Get the newly created notification
  735. $notification = '
  736. <table class="w-100">
  737. <tr>
  738. <td><span class="badge bg-success me-3">New Stock</span></td>
  739. <td>'. $product->getName() .' '. $product->getDosage() . $product->getUnit() .'</td>
  740. <td>
  741. <a href="#" class="delete-notification" data-notification-id="'. $notifications->getId() .'">
  742. <i class="fa-solid fa-xmark text-black-25 ms-3 float-end"></i>
  743. </a>
  744. </td>
  745. </tr>
  746. </table>';
  747. $notifications = $this->em->getRepository(Notifications::class)->find($notifications->getId());
  748. $notifications->setNotification($notification);
  749. $this->em->persist($notifications);
  750. $this->em->flush();
  751. // Email notifications
  752. } elseif($methodId == 2){
  753. $body = '<table style="padding: 8px; border-collapse: collapse; border: none; font-family: arial">';
  754. $body .= '<tr><td colspan="2">'. $product->getName() .' '. $product->getDosage() . $product->getUnit() .' is back in stock</td></tr>';
  755. $body .= '<tr><td colspan="2">&nbsp;</td></tr>';
  756. $body .= '<tr>';
  757. $body .= ' <td><b>Distributor: </b></td>';
  758. $body .= ' <td>'. $tracker->getDistributor()->getDistributorName() .'</td>';
  759. $body .= '</tr>';
  760. $body .= '<tr>';
  761. $body .= ' <td><b>Stock Level: </b></td>';
  762. $body .= ' <td>'. $tracker->getProduct()->getDistributorProducts()[0]->getStockCount() .'</td>';
  763. $body .= '</tr>';
  764. $body .= '</table>';
  765. $subject = 'Fluid Stock Level Update';
  766. $to = $sendTo;
  767. exec(__DIR__ . '/../../bin/console app:send-email "'. $subject .'" "'. addslashes($body) .'" "'. $to .'" "" "" "'. true .'" > /dev/null 2>&1 &');
  768. // Text notifications
  769. } elseif($methodId == 3){
  770. }
  771. $availabilityTracker = $this->em->getRepository(AvailabilityTracker::class)->find($tracker->getId());
  772. $availabilityTracker->setIsSent(1);
  773. $this->em->persist($availabilityTracker);
  774. $this->em->flush();
  775. }
  776. }
  777. $response['flash'] = '<b><i class="fa-solid fa-circle-check"></i></i></b> '. $product->getName() .' successfully updated.<div class="flash-close"><i class="fa-solid fa-xmark"></i></div>';
  778. } else {
  779. $response['flash'] = 'An error occurred';
  780. }
  781. return new JsonResponse($response);
  782. }
  783. #[Route('/distributors/get/refresh-token', name: 'distributor_get_access_token')]
  784. public function distributorGetRefreshTokenAction(Request $request): Response
  785. {
  786. $id = $this->getUser()->getDistributor()->getId();
  787. $button = false;
  788. $token = false;
  789. $error = false;
  790. if($id == null){
  791. return $this->render('security/login.html.twig', [
  792. 'last_username' => '',
  793. 'error' => '',
  794. 'csrf_token_intention' => 'authenticate',
  795. 'user_type' => 'distributors',
  796. ]);
  797. }
  798. $api = $this->em->getRepository(ApiDetails::class)->findOneBy([
  799. 'distributor' => $id,
  800. ]);
  801. // Check client id & secret exist
  802. if($api == null){
  803. $error = true;
  804. } else {
  805. $refreshTokens = $api->getRefreshTokens();
  806. if(count($refreshTokens) == 0){
  807. $button = true;
  808. } else {
  809. $token = true;
  810. }
  811. }
  812. return new JsonResponse([
  813. 'token' => $token,
  814. 'button' => $button,
  815. 'error' => $error
  816. ]);
  817. }
  818. #[Route('/distributors/zoho/set/refresh-token', name: 'zoho_set_refresh_token')]
  819. public function setZohoRefreshTokenAction(Request $request): Response
  820. {
  821. $distributorId = $this->getUser()->getDistributor()->getId();
  822. $apiDetails = $this->em->getRepository(ApiDetails::class)->findOneBy([
  823. 'distributor' => $distributorId,
  824. ]);
  825. $code = $request->query->get('code');
  826. $error = $request->query->get('error');
  827. if($code != null) {
  828. $curl = curl_init();
  829. $clientId = $this->encryptor->decrypt($apiDetails->getClientId());
  830. $clientSecret = $this->encryptor->decrypt($apiDetails->getClientSecret());
  831. $endpoint = 'https://accounts.zoho.com/oauth/v2/token?code=' . $code . '&client_id=' . $clientId . '&';
  832. $endpoint .= 'client_secret=' . $clientSecret . '&redirect_uri='. $this->getParameter('app.base_url') .'/distributors/zoho/set/refresh-token&';
  833. $endpoint .= 'grant_type=authorization_code';
  834. curl_setopt_array($curl, [
  835. CURLOPT_URL => $endpoint,
  836. CURLOPT_RETURNTRANSFER => true,
  837. CURLOPT_ENCODING => '',
  838. CURLOPT_MAXREDIRS => 10,
  839. CURLOPT_TIMEOUT => 0,
  840. CURLOPT_FOLLOWLOCATION => true,
  841. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  842. CURLOPT_CUSTOMREQUEST => 'POST'
  843. ]);
  844. $json = curl_exec($curl);
  845. curl_close($curl);
  846. $response = json_decode($json, true);
  847. if(array_key_exists('refresh_token', $response)){
  848. $session = $this->requestStack->getSession();
  849. $session->set('accessToken', $response['access_token']);
  850. $session->set('refreshToken', $response['refresh_token']);
  851. $refreshToken = new RefreshTokens();
  852. $api = $this->getUser()->getDistributor()->getApiDetails();
  853. $refreshToken->setToken($response['refresh_token']);
  854. $refreshToken->setApiDetails($api);
  855. $this->em->persist($refreshToken);
  856. $this->em->flush();
  857. return $this->redirectToRoute('distributor_manage_inventory');
  858. } elseif(array_key_exists('error', $response)){
  859. echo $response['error'];
  860. }
  861. } elseif($error != null){
  862. echo $error;
  863. file_put_contents(__DIR__ . '/../../public/zoho.log', date('Y-m-d H:i:s') .': '. $error . "\n", FILE_APPEND);
  864. }
  865. return new JsonResponse('');
  866. }
  867. #[Route('/admin/get/distributors/list', name: 'admin_get_distributors_list')]
  868. public function adminGetDistributorsList(Request $request): Response
  869. {
  870. $status = (int) $request->request->get('status');
  871. $distributors = $this->em->getRepository(Distributors::class)->adminFindAll($status);
  872. $results = $this->pageManager->paginate($distributors[0], $request, self::ITEMS_PER_PAGE);
  873. $dataAction = 'data-action="click->admin--distributors#onClickGetList"';
  874. $pagination = $this->getPagination($request->get('page_id'), $results, $dataAction, self::ITEMS_PER_PAGE);
  875. $response = $this->render('Admin/distributors/distributors_list.html.twig', [
  876. 'distributors' => $results,
  877. 'pagination' => $pagination,
  878. ])->getContent();
  879. return new JsonResponse($response);
  880. }
  881. #[Route('/admin/get/distributor/form', name: 'admin_get_distributor_form')]
  882. public function adminGetDistributorForm(Request $request): Response
  883. {
  884. $distributorId = $request->request->get('distributor-id');
  885. $distributor = $this->em->getRepository(Distributors::class)->find($distributorId);
  886. $distributorUsers = $this->em->getRepository(DistributorUsers::class)->findBy([
  887. 'distributor' => $distributorId
  888. ]);
  889. $userPermissions = $this->em->getRepository(UserPermissions::class)->findBy([
  890. 'isDistributor' => 1
  891. ]);
  892. $api = $this->em->getRepository(Api::class)->findAll();
  893. $countries = $this->em->getRepository(Countries::class)->findBy([
  894. 'isActive' => true,
  895. ]);
  896. $distributorProducts = $this->getDistributorInventory(1, $distributorId, 0, 0, $request);
  897. $response = $this->render('Admin/distributors/distributors.html.twig', [
  898. 'distributor' => $distributor,
  899. 'distributorUsers' => $distributorUsers,
  900. 'userPermissions' => $userPermissions,
  901. 'api' => $api,
  902. 'countries' => $countries,
  903. 'distributorProducts' => $distributorProducts,
  904. ])->getContent();
  905. return new JsonResponse($response);
  906. }
  907. #[Route('/admin/approve/distributor', name: 'admin_approve_distributor')]
  908. public function adminApproveDistributor(Request $request): Response
  909. {
  910. $distributorId = $request->request->get('distributor-id');
  911. $isApproved = $request->request->get('is-approved');
  912. $distributor = $this->em->getRepository(Distributors::class)->find($distributorId);
  913. if($distributor != null)
  914. {
  915. if($isApproved == 1 || $isApproved == 0)
  916. {
  917. $isApproved = 2;
  918. }
  919. else if($isApproved == 2)
  920. {
  921. $isApproved = 1;
  922. }
  923. $distributor->setIsApproved($isApproved);
  924. $this->em->persist($distributor);
  925. $this->em->flush();
  926. }
  927. return new JsonResponse('');
  928. }
  929. #[Route('/admin/get-distributor-products', name: 'admin_get_distributor_products')]
  930. public function distributorInventory(Request $request): Response
  931. {
  932. $pageId = $request->request->get('page-id');
  933. $distributorId = $request->request->get('distributor-id');
  934. $manufacturerId = $request->request->get('manufacturer-id');
  935. $speciesId = $request->request->get('species-id');
  936. $response = $this->getDistributorInventory($pageId, $distributorId, $manufacturerId, $speciesId, $request);
  937. return new JsonResponse($response);
  938. }
  939. #[Route('/admin/save-scraper-frequency', name: 'admin_save_scraper_frequency')]
  940. public function saveScraperFrequency(Request $request): Response
  941. {
  942. $name = $request->request->get('name');
  943. $cron = $request->request->get('cron');
  944. $status = (int) $request->request->get('status');
  945. $scraperUrlId = $request->request->get('scraper-url-id');
  946. $frequency = $request->request->get('frequency');
  947. $scraperUrl = $this->em->getRepository(ScraperUrls::class)->find($scraperUrlId);
  948. if($scraperUrl == null)
  949. {
  950. $response = [
  951. 'flash' => 'Please first save the scraper url.',
  952. 'type' => 'danger'
  953. ];
  954. return new JsonResponse($response);
  955. }
  956. $cronJob = $this->em->getRepository(CronJob::class)->findOneBy([
  957. 'scraperUrl' => $scraperUrl->getId(),
  958. ]);
  959. if($cronJob == null)
  960. {
  961. $cronJob = new CronJob();
  962. }
  963. $cronJob->setName($name);
  964. $cronJob->setExpression($cron);
  965. $cronJob->setCommand($scraperUrl->getDistributor()->getScraperAunthentication()->getCommand());
  966. $cronJob->setActive($status);
  967. $cronJob->setScraperUrl($scraperUrl);
  968. $cronJob->setFrequency($frequency);
  969. $cronJob->setDescription($this->getCronDescription($cron, $frequency));
  970. $this->em->persist($cronJob);
  971. $this->em->flush();
  972. $response = [
  973. 'flash' => 'Schedule saved successfully.',
  974. 'type' => 'success'
  975. ];
  976. return new JsonResponse($response);
  977. }
  978. public function getCronDescription($cron, $frequency): string
  979. {
  980. $description = '';
  981. // Daily
  982. if(strtolower($frequency) == 'daily')
  983. {
  984. $pieces = explode(' ', $cron);
  985. $hour = $pieces[1];
  986. $timeOfDay = 'pm';
  987. if($hour >= 0 and $hour < 12)
  988. {
  989. $timeOfDay = 'am';
  990. }
  991. $description = 'Every day at '. $hour . $timeOfDay;
  992. }
  993. // Weekly
  994. if(strtolower($frequency) == 'weekly')
  995. {
  996. $pieces = explode(' ', $cron);
  997. $hour = $pieces[1];
  998. $day = (int) $pieces[4];
  999. $timeOfDay = 'pm';
  1000. if($hour >= 0 and $hour < 12)
  1001. {
  1002. $timeOfDay = 'am';
  1003. }
  1004. $date = new \DateTime();
  1005. $date->setISODate(date('Y'), 1, $day);
  1006. $day = $date->format('l');
  1007. $description = 'Every '. $day .' at '. $hour . $timeOfDay;
  1008. }
  1009. // Monthly
  1010. if(strtolower($frequency) == 'monthly')
  1011. {
  1012. $pieces = explode(' ', $cron);
  1013. $hour = $pieces[1];
  1014. $day = $pieces[2];
  1015. $timeOfDay = 'pm';
  1016. if($hour >= 0 and $hour < 12)
  1017. {
  1018. $timeOfDay = 'am';
  1019. }
  1020. $description = 'At '. $hour . $timeOfDay .' on day '. $day .' of the month';
  1021. }
  1022. return $description;
  1023. }
  1024. public function getDistributorInventory($pageId, $distributorId, $manufacturerId, $speciesId, $request)
  1025. {
  1026. $dataAction = 'data-action="click->admin--distributors#onClickPagination"';
  1027. $distributorProductsRepo = $this->em->getRepository(AiProducts::class)->findByManufacturer($distributorId,$manufacturerId,$speciesId);
  1028. $distributorProducts = $this->pageManager->paginate($distributorProductsRepo[0], $request, self::ITEMS_PER_PAGE);
  1029. $distributorProductsPagination = $this->getAjaxPagination($pageId, $distributorProducts, $distributorId, $dataAction);
  1030. $species = $this->em->getRepository(AiProductsSpecies::class)->adminFindByDistributorProducts($distributorId);
  1031. return $this->render('Admin/distributors/distributor_products.html.twig', [
  1032. 'species' => $species,
  1033. 'speciesId' => $speciesId,
  1034. 'distributorProducts' => $distributorProducts,
  1035. 'pagination' => $distributorProductsPagination,
  1036. ])->getContent();
  1037. }
  1038. public function getPagination($currentPage, $results, $dataAction = '', $itemsPerPage = 10): string
  1039. {
  1040. return $this->render('pagination.html.twig', [
  1041. 'currentPage' => $currentPage,
  1042. 'results' => $results,
  1043. 'dataAction' => $dataAction,
  1044. 'itemsPerPage' => $itemsPerPage,
  1045. 'lastPage' => $this->pageManager->lastPage($results),
  1046. 'totalPages' => ceil(count($results) / $itemsPerPage),
  1047. 'i' => max(1, $currentPage - 5),
  1048. 'forLimit' => min($currentPage + 5, ceil(count($results) / $itemsPerPage)),
  1049. ])->getContent();
  1050. }
  1051. public function getAjaxPagination($pageId, $results, $url, $dataAction = '', $itemsPerPage = 10): string
  1052. {
  1053. $currentPage = $pageId;
  1054. $totalPages = ceil(count($results) / $itemsPerPage);
  1055. $limit = 5;
  1056. $lastPage = $this->pageManager->lastPage($results);
  1057. $pagination = '';
  1058. if(count($results) > 0)
  1059. {
  1060. $pagination .= '
  1061. <!-- Pagination -->
  1062. <div class="row mt-3">
  1063. <div class="col-12">';
  1064. if ($lastPage > 1)
  1065. {
  1066. $previousPageNo = $currentPage - 1;
  1067. $previousPage = $url . $previousPageNo;
  1068. $pagination .= '
  1069. <nav class="custom-pagination">
  1070. <ul class="pagination justify-content-center">
  1071. ';
  1072. $disabled = 'disabled';
  1073. $dataDisabled = 'true';
  1074. // Previous Link
  1075. if ($currentPage > 1)
  1076. {
  1077. $disabled = '';
  1078. $dataDisabled = 'false';
  1079. }
  1080. if ($totalPages >= 1 && $pageId <= $totalPages && $currentPage != 1)
  1081. {
  1082. $pagination .= '
  1083. <li class="page-item ' . $disabled . '">
  1084. <a
  1085. class="address-pagination"
  1086. aria-disabled="' . $dataDisabled . '"
  1087. data-page-id="' . $currentPage - 1 . '"
  1088. href="#"
  1089. ' . $dataAction . '
  1090. >
  1091. <span aria-hidden="true">&laquo;</span> <span class="d-none d-sm-inline">Previous</span>
  1092. </a>
  1093. </li>
  1094. <li class="page-item ">
  1095. <a
  1096. class="address-pagination"
  1097. data-page-id="1"
  1098. href="#"
  1099. '. $dataAction .'
  1100. >
  1101. First
  1102. </a>
  1103. </li>';
  1104. }
  1105. $i = max(1, $currentPage - $limit);
  1106. $forLimit = min($currentPage + $limit, $totalPages);
  1107. $isActive = false;
  1108. for (; $i <= $forLimit; $i++)
  1109. {
  1110. $active = '';
  1111. if ($i == (int)$currentPage) {
  1112. $active = 'active';
  1113. $isActive = true;
  1114. }
  1115. // Go to previous page if all records for a page have been deleted
  1116. if (!$isActive && $i == count($results)) {
  1117. $active = 'active';
  1118. }
  1119. $pagination .= '
  1120. <li class="page-item ' . $active . '">
  1121. <a
  1122. class="address-pagination"
  1123. data-page-id="' . $i . '"
  1124. href="#"
  1125. ' . $dataAction . '
  1126. >' . $i . '</a>
  1127. </li>';
  1128. }
  1129. $disabled = 'disabled';
  1130. $dataDisabled = 'true';
  1131. if ($currentPage < $lastPage) {
  1132. $disabled = '';
  1133. $dataDisabled = 'false';
  1134. }
  1135. if ($currentPage < $lastPage)
  1136. {
  1137. $pagination .= '
  1138. <li class="page-item ">
  1139. <a
  1140. class="address-pagination"
  1141. data-page-id="'. $lastPage .'"
  1142. href="#"
  1143. '. $dataAction .'
  1144. >
  1145. Last
  1146. </a>
  1147. </li>
  1148. <li class="page-item ' . $disabled . '">
  1149. <a
  1150. class="address-pagination"
  1151. aria-disabled="' . $dataDisabled . '"
  1152. data-page-id="' . $currentPage + 1 . '"
  1153. href="#"
  1154. '. $dataAction .'
  1155. >
  1156. <span class="d-none d-sm-inline">Next</span> <span aria-hidden="true">&raquo;</span>
  1157. </a>
  1158. </li>';
  1159. }
  1160. $pagination .= '
  1161. </ul>
  1162. </nav>
  1163. <input type="hidden" id="page_no" value="' . $currentPage . '">
  1164. </div>';
  1165. }
  1166. }
  1167. return $pagination;
  1168. }
  1169. }