<?php
namespace Webkul\UVDesk\CoreFrameworkBundle\Controller;
use Webkul\UVDesk\CoreFrameworkBundle\Entity;
use Webkul\UVDesk\CoreFrameworkBundle\Form;
use Webkul\UVDesk\CoreFrameworkBundle\Entity\User;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportGroup;
use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportTeam;
use Webkul\UVDesk\CoreFrameworkBundle\Entity\UserInstance;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Webkul\UVDesk\CoreFrameworkBundle\Services\UserService;
use Webkul\UVDesk\CoreFrameworkBundle\Services\UVDeskService;
use Webkul\UVDesk\CoreFrameworkBundle\Services\ReportService;
use Symfony\Contracts\Translation\TranslatorInterface;
use Knp\Component\Pager\PaginatorInterface;
use Doctrine\ORM\Query;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketRating;
use Webkul\UVDesk\CoreFrameworkBundle\Entity\Ticket;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
class Chart extends AbstractController
{
private $userService;
private $reportService;
private $uvdeskService;
private $paginator;
private $translator;
public function __construct(UserService $userService, UVDeskService $uvdeskService,ReportService $reportService, PaginatorInterface $paginator, TranslatorInterface $translator)
{
$this->userService = $userService;
$this->reportService = $reportService;
$this->uvdeskService = $uvdeskService;
$this->paginator = $paginator;
$this->translator = $translator;
}
public function listReportActivity(Request $request)
{
if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_AGENT_ACTIVITY')){
return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
}
return $this->render('@UVDeskCoreFramework/Reports/listReport.html.twig', [
'agents' => $this->userService->getAgentsPartialDetails(),
]);
}
public function agentChartXHR(Request $request)
{
$json = [];
if ($request->isXmlHttpRequest()) {
$json = $this->agentChartData($request);
}
return new Response(json_encode($json), 200, ['Content-Type' => 'application/json']);
}
public function agentChartData(Request $request)
{
if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_AGENT_ACTIVITY')) {
throw new \Exception('Access Denied', 403);
}
$reportService = $this->reportService;
$reportService->parameters = $request->query->all();
$startDate = $reportService->parameters['after'] ?? null;
$endDate = $reportService->parameters['before'] ?? null;
// guard for dates (optional)
if (!$startDate || !$endDate) {
throw new \InvalidArgumentException('Missing required date filters: after / before');
}
$agentIds = [];
if (isset($reportService->parameters['agent']) && $reportService->parameters['agent'] !== '') {
$agentIds = explode(',', $reportService->parameters['agent']);
}
$from = $startDate . ' 00:00:01';
$to = $endDate . ' 23:59:59';
// Build the base query
$qb = $reportService->getAgentChartData($agentIds, $from, $to);
// Pagination inputs
$page = max(1, (int) $request->query->get('page', 1));
$perPage = 8;
// Paginate
$paginator = $this->paginator;
$results = $paginator->paginate(
// You can pass the QueryBuilder directly; KnpPaginator will handle it.
$qb,
$page,
$perPage,
array('distinct' => true)
);
// Build pagination metadata + URL template
$paginationData = $results->getPaginationData();
$queryParameters = $results->getParams();
$queryParameters['page'] = 'replacePage';
$paginationData['url'] = '#' . $this->uvdeskService->buildPaginationQuery($queryParameters);
// Transform rows
$data = [];
$ticketIds = [];
$agentsUsed = [];
$now = new \DateTimeImmutable('now');
foreach ($results as $activity) {
// $activity already has the fields you selected in getAgentChartData()
// so avoid N+1: do NOT re-fetch Ticket by id.
$activityDateTime = $activity['createdAt'] instanceof \DateTimeInterface
? $activity['createdAt']
: new \DateTimeImmutable((string) $activity['createdAt']);
$diffSeconds = $now->getTimestamp() - $activityDateTime->getTimestamp();
$lastReply = $reportService->time2string($diffSeconds);
$ticketViewURL = $this->get('router')->generate(
'helpdesk_member_ticket',
['ticketId' => $activity['ticketId']],
UrlGeneratorInterface::ABSOLUTE_URL
);
$data[] = [
'agentName' => $activity['agentName'],
'ticketId' => $activity['ticketId'],
'agentId' => $activity['agentId'],
'ticketURL' => $ticketViewURL,
'customerName' => $activity['customerName'],
'threadType' => $activity['threadType'],
'createdAt' => $activity['createdAt'],
'subject' => $activity['subject'],
'lastReply' => $lastReply,
'dueDate' => $activity['dueDate'],
'dueDate' => $activity['dueDate'] instanceof \DateTime
? $activity['dueDate']->format('Y-m-d') // Example: 2025-03-06
: null,
'userID' => $activity['userId'],
'firstName' => $activity['firstName'],
'lastName' => $activity['lastName'],
'ticketStatus' => $activity['ticketStatus'],
];
$ticketIds[] = $activity['ticketId'];
$agentsUsed[] = $activity['agentId'];
}
// Compute totals for tickets shown on THIS PAGE only
$threadDetails = [];
if (!empty($ticketIds)) {
$threadDetails = $reportService->getTotalReplies(array_unique($ticketIds), array_unique($agentsUsed), $from, $to);
// index by ticketId for O(1) lookups
$byTicket = [];
foreach ($threadDetails as $detail) {
$byTicket[(string) $detail['ticketId']] = (int) $detail['ticketCount'];
}
foreach ($data as &$row) {
$tid = (string) $row['ticketId'];
$row['totalReply'] = $byTicket[$tid] ?? 0;
}
unset($row);
}
// FINAL payload — note: NO all-pages aggregation
$agentActivity = [
'data' => $data, // max 20 items for the requested page
'pagination_data' => $paginationData, // has pageCount, current, next, previous, etc.
];
// Persist in session if you need it elsewhere
$request->getSession()->set('agentActivity', $agentActivity);
return $agentActivity;
}
}