vendor/uvdesk/core-framework/Repository/TicketRepository.php line 147

Open in your IDE?
  1. <?php
  2. namespace Webkul\UVDesk\CoreFrameworkBundle\Repository;
  3. use Doctrine\ORM\Query;
  4. use Doctrine\ORM\QueryBuilder;
  5. use Doctrine\Common\Collections\Criteria;
  6. use Webkul\UVDesk\CoreFrameworkBundle\Entity\User;
  7. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Ticket;
  8. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketType;
  9. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Tag;
  10. use Symfony\Component\HttpFoundation\ParameterBag;
  11. use Symfony\Component\DependencyInjection\ContainerInterface;
  12. /**
  13. * TicketRepository
  14. *
  15. * This class was generated by the Doctrine ORM. Add your own custom
  16. * repository methods below.
  17. */
  18. class TicketRepository extends \Doctrine\ORM\EntityRepository
  19. {
  20. const LIMIT = 15;
  21. const TICKET_GLOBAL_ACCESS = 1;
  22. const TICKET_GROUP_ACCESS = 2;
  23. const TICKET_TEAM_ACCESS = 3;
  24. const DEFAULT_PAGINATION_LIMIT = 15;
  25. private $container;
  26. private $requestStack;
  27. private $safeFields = ['page', 'limit', 'sort', 'order', 'direction'];
  28. public function getTicketLabelCollection(Ticket $ticket, User $user)
  29. {
  30. // $queryBuilder = $this->getEntityManager()->createQueryBuilder()
  31. // ->select("DISTINCT supportLabel.id, supportLabel.name, supportLabel.colorCode as color")
  32. // ->from(Ticket::class, 'ticket')
  33. // ->leftJoin('ticket.supportLabels', 'supportLabel')
  34. // // ->leftJoin('supportLabel.user', 'user')
  35. // ->where('ticket.id = :ticketId')->setParameter('ticketId', $ticket->getId())
  36. // ->andWhere('supportLabel.user = :user')->setParameter('user', $user);
  37. return [];
  38. }
  39. public function getAllTickets(ParameterBag $obj = null, $container, $actAsUser = null)
  40. {
  41. $currentUser = $actAsUser ? : $container->get('user.service')->getCurrentUser();
  42. $json = array();
  43. $qb = $this->getEntityManager()->createQueryBuilder();
  44. $qb->select('DISTINCT t,gr,pr,tp,s,a.id as agentId,c.id as customerId')->from($this->getEntityName(), 't');
  45. $qb->leftJoin('t.agent', 'a');
  46. $qb->leftJoin('a.userInstance', 'ad');
  47. $qb->leftJoin('t.status', 's');
  48. $qb->leftJoin('t.customer', 'c');
  49. $qb->leftJoin('t.supportGroup', 'gr');
  50. $qb->leftJoin('t.priority', 'pr');
  51. $qb->leftJoin('t.type', 'tp');
  52. $qb->addSelect("CONCAT(a.firstName,' ', a.lastName) AS name");
  53. $qb->andWhere("t.agent IS NULL OR ad.supportRole != 4");
  54. $data = $obj ? $obj->all() : [];
  55. $data = array_reverse($data);
  56. foreach ($data as $key => $value) {
  57. if (!in_array($key,$this->safeFields)) {
  58. if (isset($data['search']) && $key == 'search') {
  59. $qb->andWhere("t.subject LIKE :subject OR a.email LIKE :agentName OR t.id LIKE :ticketId");
  60. $qb->setParameter('subject', '%'.urldecode(trim($value)).'%');
  61. $qb->setParameter('agentName', '%'.urldecode(trim($value)).'%');
  62. $qb->setParameter('ticketId', '%'.urldecode(trim($value)).'%');
  63. } elseif (isset($data['group']) && $key == 'group') {
  64. // Prüfen ob mehrere Gruppen (Array)
  65. if (is_array($value)) {
  66. // Alle Werte zu Integer konvertieren
  67. $groups = array_map('intval', $value);
  68. $groups = array_filter($groups, fn($v) => $v > 0);
  69. if (!empty($groups)) {
  70. $qb->andWhere($qb->expr()->in('t.supportGroup', $groups));
  71. }
  72. // Prüfen ob Komma-String "1,2,3"
  73. } elseif (strpos($value, ',') !== false) {
  74. $parts = explode(',', $value);
  75. $groups = array_map('intval', $parts);
  76. $groups = array_filter($groups, fn($v) => $v > 0);
  77. if (!empty($groups)) {
  78. $qb->andWhere($qb->expr()->in('t.supportGroup', $groups));
  79. }
  80. // Einzelwert
  81. } else {
  82. $qb->andWhere('t.supportGroup = :singleGroup');
  83. $qb->setParameter('singleGroup', intval($value));
  84. }
  85. } elseif ($key == 'status') {
  86. $qb->andWhere('t.status = '.intval($value));
  87. } elseif ($key == 'nstatus') {
  88. $qb->andWhere('t.status != '.intval($value));
  89. } elseif ($key == 'lstatus') {
  90. $qb->andWhere('t.status IN ('.str_replace('+', ',', $value).')');
  91. }
  92. }
  93. }
  94. $qb->andWhere('t.isTrashed != 1');
  95. if (!isset($data['sort'])) {
  96. $qb->orderBy('t.id',Criteria::DESC);
  97. }
  98. if (isset($data['sort']) && $data['sort'] == "t.updatedAt") {
  99. $qb->orderBy('t.updatedAt',Criteria::DESC);
  100. }
  101. $paginator = $container->get('knp_paginator');
  102. $newQb = clone $qb;
  103. $newQb->select('COUNT(DISTINCT t.id)');
  104. $query = $newQb->getQuery();
  105. try {
  106. $results = $paginator->paginate(
  107. $qb->getQuery()->setHydrationMode(Query::HYDRATE_ARRAY)->setHint('knp_paginator.count', $newQb->getQuery()->getSingleScalarResult()),
  108. isset($data['page']) ? $data['page'] : 1,
  109. isset($data['limit']) && !empty($data['limit']) ? $data['limit'] : self::LIMIT,
  110. array('distinct' => true)
  111. );
  112. } catch (\Throwable $e) {
  113. dump($e->getMessage());
  114. dump($e->getTraceAsString());
  115. die();
  116. }
  117. $paginationData = $results->getPaginationData();
  118. $queryParameters = $results->getParams();
  119. $queryParameters['page'] = "replacePage";
  120. // Arrays in Query-Parameter sauber serialisieren, damit rawurlencode funktioniert
  121. $cleanQueryParameters = $queryParameters;
  122. foreach ($cleanQueryParameters as $key => $value) {
  123. if (is_array($value)) {
  124. // Standard UVDesk expects group=1,4,5 format
  125. $cleanQueryParameters[$key] = implode(',', $value);
  126. }
  127. }
  128. try {
  129. $paginationData['url'] = '#'.$container->get('uvdesk.service')->buildPaginationQuery($cleanQueryParameters);
  130. } catch (\Throwable $e) {
  131. dump($e->getMessage());
  132. dump($e->getTraceAsString());
  133. die();
  134. }
  135. $data = array();
  136. $userService = $container->get('user.service');
  137. $ticketService = $container->get('ticket.service');
  138. $translatorService = $container->get('translator');
  139. foreach ($results as $key => $ticket) {
  140. $ticket[0]['status']['description'] = $translatorService->trans($ticket[0]['status']['description']);
  141. //print_r($ticket[0]);die();
  142. $data[] = [
  143. 'id' => $ticket[0]['id'],
  144. 'subject' => $ticket[0]['subject'],
  145. 'isCustomerView' => $ticket[0]['isCustomerViewed'],
  146. 'status' => $ticket[0]['status'],
  147. 'source' => $ticket[0]['source'],
  148. 'isStarred' => $ticket[0]['isStarred'],
  149. 'group' => $ticket[0]['supportGroup'],
  150. 'type' => $ticket[0]['type'],
  151. 'priority' => $ticket[0]['priority'],
  152. //'formatedCreatedAt' => $userService->convertToTimezone($ticket[0]['createdAt']),
  153. 'formatedCreatedAt' => $ticket[0]['createdAt'],
  154. //'formatedUpdatedAt' => $userService->convertToTimezone($ticket[0]['updatedAt']),
  155. 'formatedUpdatedAt' => $ticket[0]['updatedAt'],
  156. 'totalThreads' => $ticketService->getTicketTotalThreads($ticket[0]['id']),
  157. 'agent' => $ticket['agentId'] ? $userService->getAgentDetailById($ticket['agentId']) : null,
  158. 'customer' => $ticket['customerId'] ? $userService->getCustomerPartialDetailById($ticket['customerId']) : null,
  159. 'hasAttachments' => $ticketService->hasAttachments($ticket[0]['id'])
  160. ];
  161. }
  162. $json['tickets'] = $data;
  163. $json['pagination'] = $paginationData;
  164. return $json;
  165. }
  166. public function getAllCustomerTickets(ParameterBag $obj = null, $container, $actAsUser = null)
  167. {
  168. $currentUser = $actAsUser ? : $container->get('user.service')->getCurrentUser();
  169. $json = array();
  170. $qb = $this->getEntityManager()->createQueryBuilder();
  171. $qb->select('DISTINCT t,gr,pr,tp,s,a.id as agentId,c.id as customerId')->from($this->getEntityName(), 't');
  172. $qb->leftJoin('t.agent', 'a');
  173. $qb->leftJoin('a.userInstance', 'ad');
  174. $qb->leftJoin('t.status', 's');
  175. $qb->leftJoin('t.customer', 'c');
  176. $qb->leftJoin('t.supportGroup', 'gr');
  177. $qb->leftJoin('t.priority', 'pr');
  178. $qb->leftJoin('t.type', 'tp');
  179. $qb->leftJoin('t.collaborators', 'tc');
  180. $qb->addSelect("CONCAT(a.firstName,' ', a.lastName) AS name");
  181. $qb->andWhere("t.agent IS NULL OR ad.supportRole != 4");
  182. $data = $obj->all();
  183. $data = array_reverse($data);
  184. foreach ($data as $key => $value) {
  185. if (! in_array($key,$this->safeFields)) {
  186. if (isset($data['search']) && $key == 'search') {
  187. $qb->andWhere("t.subject LIKE :subject OR a.email LIKE :agentName OR t.id LIKE :ticketId");
  188. $qb->setParameter('subject', '%'.urldecode(trim($value)).'%');
  189. $qb->setParameter('agentName', '%'.urldecode(trim($value)).'%');
  190. $qb->setParameter('ticketId', '%'.urldecode(trim($value)).'%');
  191. } elseif ($key == 'status') {
  192. $qb->andWhere('t.status = '.intval($value));
  193. }
  194. }
  195. }
  196. $qb->andWhere('t.customer = :customerId OR tc.id =:collaboratorId');
  197. $qb->setParameter('customerId', $currentUser->getId());
  198. $qb->setParameter('collaboratorId', $currentUser->getId());
  199. $qb->andWhere('t.isTrashed != 1');
  200. if(!isset($data['sort'])) {
  201. $qb->orderBy('t.id',Criteria::DESC);
  202. }
  203. $paginator = $container->get('knp_paginator');
  204. $newQb = clone $qb;
  205. $newQb->select('COUNT(DISTINCT t.id)');
  206. $results = $paginator->paginate(
  207. $qb->getQuery()->setHydrationMode(Query::HYDRATE_ARRAY)->setHint('knp_paginator.count', $newQb->getQuery()->getSingleScalarResult()),
  208. isset($data['page']) ? $data['page'] : 1,
  209. self::LIMIT,
  210. array('distinct' => true)
  211. );
  212. $paginationData = $results->getPaginationData();
  213. $queryParameters = $results->getParams();
  214. $queryParameters['page'] = "replacePage";
  215. $paginationData['url'] = '#'.$container->get('uvdesk.service')->buildPaginationQuery($queryParameters);
  216. $data = array();
  217. $userService = $container->get('user.service');
  218. $ticketService = $container->get('ticket.service');
  219. $translatorService = $container->get('translator');
  220. foreach ($results as $key => $ticket) {
  221. $ticket[0]['status']['code'] = $translatorService->trans($ticket[0]['status']['code']);
  222. $data[] = [
  223. 'id' => $ticket[0]['id'],
  224. 'subject' => $ticket[0]['subject'],
  225. 'isCustomerView' => $ticket[0]['isCustomerViewed'],
  226. 'status' => $ticket[0]['status'],
  227. 'group' => $ticket[0]['supportGroup'],
  228. 'type' => $ticket[0]['type'],
  229. 'priority' => $ticket[0]['priority'],
  230. 'totalThreads' => $ticketService->getTicketTotalThreads($ticket[0]['id']),
  231. 'agent' => $ticket['agentId'] ? $userService->getAgentDetailById($ticket['agentId']) : null,
  232. 'customer' => $ticket['customerId'] ? $userService->getCustomerPartialDetailById($ticket['customerId']) : null,
  233. 'formatedCreatedAt' => $userService->getLocalizedFormattedTime($ticket[0]['createdAt'],$userService->getSessionUser()),
  234. ];
  235. }
  236. $json['tickets'] = $data;
  237. $json['pagination'] = $paginationData;
  238. return $json;
  239. }
  240. public function addPermissionFilter($qb, User $user, array $supportGroupReferences = [], array $supportTeamReferences = [])
  241. {
  242. $userInstance = $user->getAgentInstance();
  243. if (!empty($userInstance) && ('ROLE_AGENT' == $userInstance->getSupportRole()->getCode() && $userInstance->getTicketAccesslevel() != self::TICKET_GLOBAL_ACCESS)) {
  244. $qualifiedGroups = empty($this->params['group']) ? $supportGroupReferences : array_intersect($supportGroupReferences, explode(',', $this->params['group']));
  245. $qualifiedTeams = empty($this->params['team']) ? $supportTeamReferences : array_intersect($supportTeamReferences, explode(',', $this->params['team']));
  246. switch ($userInstance->getTicketAccesslevel()) {
  247. case self::TICKET_GROUP_ACCESS:
  248. $qb
  249. ->andWhere("ticket.agent = :agentId OR supportGroup.id IN(:supportGroupIds) OR supportTeam.id IN(:supportTeamIds)")
  250. ->setParameter('agentId', $user->getId())
  251. ->setParameter('supportGroupIds', $qualifiedGroups)
  252. ->setParameter('supportTeamIds', $qualifiedTeams);
  253. break;
  254. case self::TICKET_TEAM_ACCESS:
  255. $qb
  256. ->andWhere("ticket.agent = :agentId OR supportTeam.id IN(:supportTeamIds)")
  257. ->setParameter('agentId', $user->getId())
  258. ->setParameter('supportTeamIds', $qualifiedTeams);
  259. break;
  260. default:
  261. $qb
  262. ->andWhere("ticket.agent = :agentId")
  263. ->setParameter('agentId', $user->getId());
  264. break;
  265. }
  266. }
  267. return $qb;
  268. }
  269. public function prepareBaseTicketQuery(User $user, array $supportGroupIds = [], array $supportTeamIds = [], array $params = [], bool $filterByStatus = true)
  270. {
  271. $queryBuilder = $this->getEntityManager()->createQueryBuilder()
  272. ->select("
  273. DISTINCT ticket,
  274. supportGroup.name as groupName,
  275. supportTeam.name as teamName,
  276. priority,
  277. type.code as typeName,
  278. agent.id as agentId,
  279. agent.email as agentEmail,
  280. agentInstance.profileImagePath as smallThumbnail,
  281. customer.id as customerId,
  282. customer.email as customerEmail,
  283. customerInstance.profileImagePath as customersmallThumbnail,
  284. CONCAT(customer.firstName, ' ', customer.lastName) AS customerName,
  285. CONCAT(agent.firstName,' ', agent.lastName) AS agentName
  286. ")
  287. ->from(Ticket::class, 'ticket')
  288. ->leftJoin('ticket.type', 'type')
  289. ->leftJoin('ticket.agent', 'agent')
  290. ->leftJoin('ticket.threads', 'threads')
  291. ->leftJoin('ticket.priority', 'priority')
  292. ->leftJoin('ticket.customer', 'customer')
  293. ->leftJoin('ticket.supportTeam', 'supportTeam')
  294. ->leftJoin('ticket.supportTags', 'supportTags')
  295. ->leftJoin('agent.userInstance', 'agentInstance')
  296. ->leftJoin('ticket.supportLabels', 'supportLabel')
  297. ->leftJoin('ticket.supportGroup', 'supportGroup')
  298. ->leftJoin('customer.userInstance', 'customerInstance')
  299. ->where('customerInstance.supportRole = 4')
  300. ->andWhere("agent.id IS NULL OR agentInstance.supportRole != 4")
  301. ->andWhere('ticket.isTrashed = :isTrashed')->setParameter('isTrashed', isset($params['trashed']) ? true : false);
  302. if (!isset($params['sort'])) {
  303. $queryBuilder->orderBy('ticket.updatedAt', Criteria::DESC);
  304. }
  305. if ($filterByStatus) {
  306. $queryBuilder->andWhere('ticket.status = :status')->setParameter('status', isset($params['status']) ? $params['status'] : 1);
  307. }
  308. $this->addPermissionFilter($queryBuilder, $user, $supportGroupIds, $supportTeamIds);
  309. // applyFilter according to params
  310. return $this->prepareTicketListQueryWithParams($queryBuilder, $params, $user);
  311. }
  312. public function prepareBasePaginationTicketTypesQuery(array $params)
  313. {
  314. $queryBuilder = $this->getEntityManager()->createQueryBuilder()
  315. ->select("ticketType")
  316. ->from(TicketType::class, 'ticketType');
  317. // Apply filters
  318. foreach ($params as $field => $fieldValue) {
  319. if (in_array($field, $this->safeFields)) {
  320. continue;
  321. }
  322. switch ($field) {
  323. case 'search':
  324. $queryBuilder->andWhere("ticketType.code LIKE :searchQuery OR ticketType.description LIKE :searchQuery");
  325. $queryBuilder->setParameter('searchQuery', '%' . urldecode(trim($fieldValue)) . '%');
  326. break;
  327. case 'isActive':
  328. $queryBuilder->andWhere("ticketType.isActive LIKE :searchQuery");
  329. $queryBuilder->setParameter('searchQuery', '%' . urldecode(trim($fieldValue)) . '%');
  330. break;
  331. default:
  332. break;
  333. }
  334. }
  335. // Define sort by
  336. if (empty($params['sort']) || 'a.id' == $params['sort']) {
  337. $queryBuilder->orderBy('ticketType.id', (empty($params['direction']) || 'ASC' == strtoupper($params['direction'])) ? Criteria::ASC : Criteria::DESC);
  338. } else {
  339. $queryBuilder->orderBy('ticketType.code', (empty($params['direction']) || 'ASC' == strtoupper($params['direction'])) ? Criteria::ASC : Criteria::DESC);
  340. }
  341. return $queryBuilder;
  342. }
  343. public function prepareBasePaginationTagsQuery(array $params)
  344. {
  345. $queryBuilder = $this->getEntityManager()->createQueryBuilder()
  346. ->select('supportTag.id as id, supportTag.name as name, COUNT(ticket) as totalTickets')
  347. ->from(Tag::class, 'supportTag')
  348. ->leftJoin('supportTag.tickets', 'ticket')
  349. ->groupBy('supportTag.id');
  350. // Apply filters
  351. foreach ($params as $field => $fieldValue) {
  352. if (in_array($field, $this->safeFields)) {
  353. continue;
  354. }
  355. switch ($field) {
  356. case 'search':
  357. $queryBuilder->andWhere("supportTag.name LIKE :searchQuery")->setParameter('searchQuery', '%' . urldecode(trim($fieldValue)) . '%');
  358. break;
  359. default:
  360. break;
  361. }
  362. }
  363. // Define sort by
  364. if (empty($params['sort']) || 'a.id' == $params['sort']) {
  365. $queryBuilder->orderBy('supportTag.id', (empty($params['direction']) || 'ASC' == strtoupper($params['direction'])) ? Criteria::ASC : Criteria::DESC);
  366. } else {
  367. $queryBuilder->orderBy('supportTag.name', (empty($params['direction']) || 'ASC' == strtoupper($params['direction'])) ? Criteria::ASC : Criteria::DESC);
  368. }
  369. return $queryBuilder;
  370. }
  371. public function getTicketTabDetails(User $user, array $supportGroupIds = [], array $supportTeamIds = [], array $params = [], bool $filterByStatus = true)
  372. {
  373. $data = array(1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0);
  374. $queryBuilder = $this->getEntityManager()->createQueryBuilder()
  375. ->select("
  376. COUNT(DISTINCT ticket.id) as countTicket,
  377. status.id as statusId,
  378. status.code as tab
  379. ")
  380. ->from(Ticket::class, 'ticket')
  381. ->leftJoin('ticket.type', 'type')
  382. ->leftJoin('ticket.agent', 'agent')
  383. ->leftJoin('ticket.status', 'status')
  384. ->leftJoin('ticket.threads', 'threads')
  385. ->leftJoin('ticket.priority', 'priority')
  386. ->leftJoin('ticket.customer', 'customer')
  387. ->leftJoin('ticket.supportTeam', 'supportTeam')
  388. ->leftJoin('ticket.supportTags', 'supportTags')
  389. ->leftJoin('ticket.supportGroup', 'supportGroup')
  390. ->leftJoin('agent.userInstance', 'agentInstance')
  391. ->leftJoin('ticket.supportLabels', 'supportLabel')
  392. ->leftJoin('customer.userInstance', 'customerInstance')
  393. ->where('customerInstance.supportRole = 4')
  394. ->andWhere("agent.id IS NULL OR agentInstance.supportRole != 4")
  395. ->andWhere('ticket.isTrashed = :isTrashed')->setParameter('isTrashed', isset($params['trashed']) ? true : false)
  396. ->groupBy('status');
  397. // applyFilter according to permission
  398. $this->addPermissionFilter($queryBuilder, $user, $supportGroupIds, $supportTeamIds);
  399. $queryBuilder = $this->prepareTicketListQueryWithParams($queryBuilder, $params, $user);
  400. $results = $queryBuilder->getQuery()->getResult();
  401. foreach ($results as $status) {
  402. $data[$status['statusId']] += $status['countTicket'];
  403. }
  404. return $data;
  405. }
  406. public function countTicketTotalThreads($ticketId, $threadType = 'reply')
  407. {
  408. $totalThreads = $this->getEntityManager()->createQueryBuilder()
  409. ->select('COUNT(thread.id) as threads')
  410. ->from(Ticket::class, 'ticket')
  411. ->leftJoin('ticket.threads', 'thread')
  412. ->where('ticket.id = :ticketId')->setParameter('ticketId', $ticketId)
  413. ->andWhere('thread.threadType = :threadType')->setParameter('threadType', $threadType)
  414. ->getQuery()->getSingleScalarResult();
  415. return (int) $totalThreads;
  416. }
  417. public function getTicketNavigationIteration($ticket, $container)
  418. {
  419. $ticketsCollection = $this->getEntityManager()->getRepository(Ticket::class)
  420. ->getAllTickets(null, $container);
  421. if ($ticketsCollection)
  422. $results = $ticketsCollection['tickets'];
  423. $nextPrevPage = array('next' => 0,'prev' => 0);
  424. for ($i = 0; $i < count($results); $i++) {
  425. if ($results[$i]['id'] == $ticket->getId()) {
  426. $nextPrevPage['next'] = isset($results[$i + 1]) ? $results[$i + 1]['id'] : 0;
  427. $nextPrevPage['prev'] = isset($results[$i - 1]) ? $results[$i - 1]['id'] : 0;
  428. }
  429. }
  430. return $nextPrevPage;
  431. }
  432. public function countCustomerTotalTickets(User $user, $container)
  433. {
  434. $userService = $container->get('user.service');
  435. $queryBuilder = $this->getEntityManager()->createQueryBuilder()
  436. ->select('COUNT(ticket.id) as tickets')
  437. ->from(Ticket::class, 'ticket')
  438. ->leftJoin('ticket.priority', 'p')
  439. ->leftJoin('ticket.status', 's')
  440. ->leftJoin('ticket.agent', 'a')
  441. ->leftJoin('ticket.type', 'type')
  442. ->leftJoin('ticket.supportGroup', 'supportGroup')
  443. ->leftJoin('ticket.supportTeam', 'supportTeam')
  444. ->leftJoin('a.userInstance', 'ad')
  445. ->andWhere('ticket.customer = :customerId')
  446. ->andWhere('ticket.isTrashed != 1')
  447. ->setParameter('customerId', $user->getId())
  448. ->andWhere("a IS NULL OR ad.supportRole != 4")
  449. ->orderBy('ticket.id', Criteria::DESC);
  450. $agent = $userService->getCurrentUser();
  451. $supportGroupReference = $this->getEntityManager()->getRepository(User::class)->getUserSupportGroupReferences($agent);
  452. $supportTeamReference = $this->getEntityManager()->getRepository(User::class)->getUserSupportTeamReferences($agent);
  453. $this->addPermissionFilter($queryBuilder, $agent, $supportGroupReference, $supportTeamReference);
  454. return (int) $queryBuilder->getQuery()->getSingleScalarResult();
  455. }
  456. public function isLabelAlreadyAdded($ticket,$label)
  457. {
  458. $qb = $this->getEntityManager()->createQueryBuilder();
  459. $qb->select('COUNT(t.id) as ticketCount')->from(Ticket::class, 't')
  460. ->leftJoin('t.supportLabels','tl')
  461. ->andWhere('tl.id = :labelId')
  462. ->andWhere('t.id = :ticketId')
  463. ->setParameter('labelId',$label->getId())
  464. ->setParameter('ticketId',$ticket->getId());
  465. return $qb->getQuery()->getSingleScalarResult() ? true : false;
  466. }
  467. public function isTicketCollaborator($ticket, $collaboratorEmail)
  468. {
  469. if ($ticket->getCollaborators()) {
  470. foreach ($ticket->getCollaborators() as $collaborator) {
  471. if (strtolower($collaborator->getEmail()) == strtolower($collaboratorEmail)) {
  472. return true;
  473. }
  474. }
  475. }
  476. return false;
  477. }
  478. public function getTicketDetails(ParameterBag $obj = null, $container)
  479. {
  480. $data = $obj->all();
  481. $userService = $container->get('user.service');
  482. $ticketService = $container->get('ticket.service');
  483. $json = [];
  484. $qb = $this->getEntityManager()->createQueryBuilder();
  485. $qb->select('DISTINCT t,gr.name as groupName,supportTeam.name as supportTeamName,tp.code as typeName,s,pr,a.id as agentId,c.id as customerId')->from($this->getEntityName(), 't')
  486. ->leftJoin('t.agent', 'a')
  487. ->leftJoin('t.status', 's')
  488. ->leftJoin('t.customer', 'c')
  489. ->leftJoin('t.supportGroup', 'gr')
  490. ->leftJoin('t.supportTeam', 'supportTeam')
  491. ->leftJoin('t.priority', 'pr')
  492. ->leftJoin('t.type', 'tp')
  493. ->leftJoin('c.userInstance', 'cd')
  494. ->leftJoin('a.userInstance', 'ad')
  495. ->leftJoin('t.supportTags', 'tg')
  496. ->leftJoin('t.supportLabels', 'tl')
  497. ->andWhere('t.id = :ticketId')
  498. ->setParameter('ticketId', $data['ticketId']);
  499. $results = $qb->getQuery()->getArrayResult();
  500. $ticket = array_shift($results);
  501. return [
  502. 'id' => $ticket[0]['id'],
  503. 'subject' => $ticket[0]['subject'],
  504. 'isStarred' => $ticket[0]['isStarred'],
  505. 'isAgentView' => $ticket[0]['isAgentViewed'],
  506. 'isTrashed' => $ticket[0]['isTrashed'],
  507. 'status' => $ticket[0]['status'],
  508. 'groupName' => $ticket['groupName'],
  509. 'subGroupName' => $ticket['supportTeamName'],
  510. 'typeName' => $ticket['typeName'],
  511. 'priority' => $ticket[0]['priority'],
  512. 'formatedCreatedAt' => $ticketService->timeZoneConverter($ticket[0]['createdAt']),
  513. 'ticketLabels' => $ticketService->getTicketLabels($ticket[0]['id']),
  514. 'totalThreads' => $ticketService->getTicketTotalThreads($ticket[0]['id']),
  515. 'agent' => $ticket['agentId'] ? $userService->getAgentDetailById($ticket['agentId']) : null,
  516. 'customer' => $ticket['customerId'] ? $userService->getCustomerPartialDetailById($ticket['customerId']) : null,
  517. 'lastReplyAgentName' => $ticketService->getlastReplyAgentName($ticket[0]['id']),
  518. 'createThread' => $ticketService->getCreateReply($ticket[0]['id']),
  519. 'lastReply' => $ticketService->getLastReply($ticket[0]['id']),
  520. ];
  521. }
  522. // Get customer more ticket sidebar details
  523. public function getCustomerMoreTicketsSidebar($customerId, $container, $request) {
  524. $userService = $container->get('user.service');
  525. $ticketService = $container->get('ticket.service');
  526. $qb = $this->getEntityManager()->createQueryBuilder();
  527. $qb->select("DISTINCT ticket as tickets,s.code as statusName, supportTeam.name as teamName,supportGroup.name as groupName, p.code as priorityName, p.colorCode as priorityColor, type.code as typeName, a.id as agentId, CONCAT(a.firstName, ' ', a.lastName) AS agentName")
  528. ->from($this->getEntityName(), 'ticket')
  529. ->leftJoin('ticket.priority', 'p')
  530. ->leftJoin('ticket.status', 's')
  531. ->leftJoin('ticket.agent', 'a')
  532. ->leftJoin('ticket.type', 'type')
  533. ->leftJoin('ticket.supportGroup', 'supportGroup')
  534. ->leftJoin('ticket.supportTeam', 'supportTeam')
  535. ->leftJoin('a.userInstance', 'ad')
  536. ->andWhere('ticket.customer = :customerId')
  537. ->andWhere('ticket.isTrashed != 1')
  538. ->setParameter('customerId', $customerId)
  539. ->andWhere("a IS NULL OR ad.supportRole != 4")
  540. ->orderBy('ticket.id', Criteria::DESC);
  541. $user = $userService->getCurrentUser();
  542. $supportGroupReference = $this->getEntityManager()->getRepository(User::class)->getUserSupportGroupReferences($user);
  543. $supportTeamReference = $this->getEntityManager()->getRepository(User::class)->getUserSupportTeamReferences($user);
  544. // if($currentUser->getRole() == "ROLE_AGENT" && $currentUser->detail['agent']->getTicketView() != UserData::GLOBAL_ACCESS) {
  545. // $this->em->getRepository('WebkulTicketBundle:Ticket')->addPermissionFilter($qb, $this->container, false);
  546. // $qb->addSelect('gr.name as groupName');
  547. // } else {
  548. // $qb->leftJoin('t.supportGroup', 'gr');
  549. // $qb->addSelect('gr.name as groupName');
  550. // }
  551. $this->addPermissionFilter($qb, $user, $supportGroupReference, $supportTeamReference);
  552. $results = $qb->getQuery()->getArrayResult();
  553. foreach ($results as $key => $ticket) {
  554. $results[$key] = $ticket['tickets'];
  555. unset($ticket['tickets']);
  556. $results[$key] = array_merge($results[$key], $ticket);
  557. $results[$key]['timestamp']= $userService->convertToTimezone($results[$key]['createdAt']);
  558. $results[$key]['formatedCreatedAt'] = $results[$key]['createdAt']->format('d-m-Y H:i A');
  559. $results[$key]['totalThreads']= $ticketService->getTicketTotalThreads($results[$key]['id']);
  560. }
  561. return $results;
  562. }
  563. public function prepareTicketListQueryWithParams($queryBuilder, $params, $actAsUser = null)
  564. {
  565. if (!empty($params['search']) && !empty($params['searchType'])) {
  566. $sanitizedSearchContent = trim(urldecode($params['search']));
  567. $sanitizedSearchTicketIncrementId = str_replace('#', '', $sanitizedSearchContent);
  568. // Initialize search query
  569. switch ($params['searchType']) {
  570. case 'email':
  571. $whereTicketSearchQuery = "customer.email LIKE :search";
  572. break;
  573. case 'subject':
  574. $whereTicketSearchQuery = "ticket.subject LIKE :search";
  575. break;
  576. case 'id':
  577. $whereTicketSearchQuery = "ticket.id = :searchExact";
  578. break;
  579. default:
  580. break;
  581. }
  582. // Apply condition
  583. $queryBuilder->andWhere($whereTicketSearchQuery);
  584. // Set parameters based on search type
  585. if ($params['searchType'] === 'id') {
  586. $queryBuilder->setParameter('searchExact', $sanitizedSearchTicketIncrementId);
  587. } else {
  588. $queryBuilder->setParameter('search', '%' . $sanitizedSearchContent . '%');
  589. }
  590. }
  591. foreach ($params as $field => $fieldValue) {
  592. if (in_array($field, $this->safeFields)) {
  593. continue;
  594. }
  595. if ($actAsUser != null ) {
  596. $userInstance = $actAsUser->getAgentInstance();
  597. if (!empty($userInstance) && ('ROLE_AGENT' == $userInstance->getSupportRole()->getCode() && $field == 'mine') || ('ROLE_ADMIN' == $userInstance->getSupportRole()->getCode()) && $field == 'mine') {
  598. $fieldValue = $actAsUser->getId();
  599. }
  600. }
  601. switch ($field) {
  602. case 'label':
  603. $queryBuilder->andWhere('supportLabel.id = :labelIds');
  604. $queryBuilder->setParameter('labelIds', $fieldValue);
  605. break;
  606. case 'starred':
  607. $queryBuilder->andWhere('ticket.isStarred = 1');
  608. break;
  609. case 'unassigned':
  610. $queryBuilder->andWhere("agent.id is NULL");
  611. break;
  612. case 'notreplied':
  613. $queryBuilder->andWhere('ticket.isReplied = 0');
  614. break;
  615. case 'mine':
  616. $queryBuilder->andWhere('agent = :agentId')->setParameter('agentId', $fieldValue);
  617. break;
  618. case 'new':
  619. $queryBuilder->andWhere('ticket.isNew = 1');
  620. break;
  621. case 'priority':
  622. $queryBuilder->andWhere('priority.id = :priority')->setParameter('priority', $fieldValue);
  623. break;
  624. case 'type':
  625. $queryBuilder->andWhere('type.id IN (:typeCollection)')->setParameter('typeCollection', explode(',', $fieldValue));
  626. break;
  627. case 'agent':
  628. $queryBuilder->andWhere('agent.id IN (:agentCollection)')->setParameter('agentCollection', explode(',', $fieldValue));
  629. break;
  630. case 'customer':
  631. $queryBuilder->andWhere('customer.id IN (:customerCollection)')->setParameter('customerCollection', explode(',', $fieldValue));
  632. break;
  633. case 'group':
  634. $queryBuilder->andWhere('supportGroup.id IN (:groupIds)');
  635. $queryBuilder->setParameter('groupIds', explode(',', $fieldValue));
  636. break;
  637. case 'team':
  638. $queryBuilder->andWhere("supportTeam.id In(:subGrpKeys)");
  639. $queryBuilder->setParameter('subGrpKeys', explode(',', $fieldValue));
  640. break;
  641. case 'tag':
  642. $queryBuilder->andWhere("supportTags.id In(:tagIds)");
  643. $queryBuilder->setParameter('tagIds', explode(',', $fieldValue));
  644. break;
  645. case 'source':
  646. $queryBuilder->andWhere('ticket.source IN (:sources)');
  647. $queryBuilder->setParameter('sources', explode(',', $fieldValue));
  648. break;
  649. case 'after':
  650. $date = \DateTime::createFromFormat('d-m-Y H:i', $fieldValue.' 23:59');
  651. if ($date) {
  652. // $date = \DateTime::createFromFormat('d-m-Y H:i', $this->userService->convertTimezoneToServer($date, 'd-m-Y H:i'));
  653. $queryBuilder->andWhere('ticket.createdAt > :afterDate');
  654. $queryBuilder->setParameter('afterDate', $date);
  655. }
  656. break;
  657. case 'before':
  658. $date = \DateTime::createFromFormat('d-m-Y H:i', $fieldValue.' 00:00');
  659. if ($date) {
  660. //$date = \DateTime::createFromFormat('d-m-Y H:i', $container->get('user.service')->convertTimezoneToServer($date, 'd-m-Y H:i'));
  661. $queryBuilder->andWhere('ticket.createdAt < :beforeDate');
  662. $queryBuilder->setParameter('beforeDate', $date);
  663. }
  664. break;
  665. case 'repliesLess':
  666. $queryBuilder->andWhere('threads.threadType = :threadType')->setParameter('threadType', 'reply')
  667. ->groupBy('ticket.id')
  668. ->andHaving('count(threads.id) < :threadValueLesser')->setParameter('threadValueLesser', intval($params['repliesLess']));
  669. break;
  670. case 'repliesMore':
  671. $queryBuilder->andWhere('threads.threadType = :threadType')->setParameter('threadType', 'reply')
  672. ->groupBy('ticket.id')
  673. ->andHaving('count(threads.id) > :threadValueGreater')->setParameter('threadValueGreater', intval($params['repliesMore']));
  674. break;
  675. case 'mailbox':
  676. $queryBuilder->andWhere('ticket.mailboxEmail IN (:mailboxEmails)');
  677. $queryBuilder->setParameter('mailboxEmails', explode(',', $fieldValue));
  678. break;
  679. default:
  680. break;
  681. }
  682. }
  683. return $queryBuilder;
  684. }
  685. public function getAgentTickets($agentId,$container) {
  686. $qb = $this->getEntityManager()->createQueryBuilder();
  687. $qb->select('t')->from(Ticket::class, 't');
  688. $qb->andWhere('t.agent = :agentId');
  689. $qb->setParameter('agentId',$agentId);
  690. return $qb->getQuery()->getResult();
  691. }
  692. }