PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.4.0
Fluent Support – Helpdesk & Customer Support Ticket System v2.4.0
2.4.0 2.3.2 2.3.1 2.3.0 2.2.1 2.2.0 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.4.0 1.4.1 1.4.2 1.4.5 1.4.6 1.4.7 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 All 68 releases
← All changes | app/Http/Controllers/ReportingController.php +203 -33 1.4.62.4.0 View file →
@@ -1,70 +1,94 @@
1 1 <?php
2 2
3 3 namespace FluentSupport\App\Http\Controllers;
4 4
5 -use FluentSupport\App\Models\Agent;
6 5 use FluentSupport\App\Modules\Reporting\Reporting;
7 6 use FluentSupport\App\Modules\StatModule;
8 7 use FluentSupport\App\Services\Helper;
9 -use FluentSupport\Framework\Request\Request;
8 +use FluentSupport\Framework\Http\Request\Request;
9 +use FluentSupport\App\Models\Ticket;
10 +use FluentSupport\App\Services\Tickets\AgentTicketAccess;
11 +use FluentSupport\App\Models\Conversation;
12 +use FluentSupport\App\Models\TagPivot;
10 13
14 +/**
15 + * ReportingController class for REST API
16 + * This class is responsible for getting data for all request related to report
17 + * @package FluentSupport\App\Http\Controllers
18 + *
19 + * @version 1.0.0
20 + */
11 21 class ReportingController extends Controller
12 22 {
13 - public function getOverallReports(Request $request)
23 + public static function getSanitizedDateRange(Request $request)
14 24 {
15 - return [
16 - 'overall_reports' => StatModule::getOverAllStats()
17 - ];
18 - }
25 + $dateRange = $request->get('date_range', []);
19 26
20 - public function getTicketsChart(Request $request, Reporting $reporting)
21 - {
22 - list($from, $to) = $request->get('date_range') ?: ['', ''];
27 + if (is_array($dateRange) && count($dateRange) >= 2) {
28 + return [
29 + sanitize_text_field($dateRange[0] ?? ''),
30 + sanitize_text_field($dateRange[1] ?? '')
31 + ];
32 + }
23 33
24 - return [
25 - 'stats' => $reporting->getTicketsGrowth($from, $to)
26 - ];
27 - }
34 + if (is_string($dateRange)) {
35 + $parts = array_map('trim', explode(',', $dateRange));
36 + return [
37 + sanitize_text_field($parts[0] ?? ''),
38 + sanitize_text_field($parts[1] ?? '')
39 + ];
40 + }
28 41
29 - public function getResolveChart(Request $request, Reporting $reporting)
30 - {
31 - list($from, $to) = $request->get('date_range') ?: ['', ''];
32 -
33 - return [
34 - 'stats' => $reporting->getTicketResolveGrowth($from, $to)
35 - ];
42 + return ['', ''];
36 43 }
37 44
38 - public function getResponseChart(Request $request, Reporting $reporting)
45 + public static function getAgentIdsForGroup(Request $request)
39 46 {
40 - list($from, $to) = $request->get('date_range') ?: ['', ''];
47 + $groupId = $request->getSafe('agent_group_id', 'intval');
48 + if (!$groupId) {
49 + return null;
50 + }
41 51
42 - return [
43 - 'stats' => $reporting->getResponseGrowth($from, $to)
44 - ];
52 + return TagPivot::where('source_type', 'agent_group')
53 + ->where('tag_id', $groupId)
54 + ->pluck('source_id')
55 + ->toArray();
45 56 }
46 57
47 - public function getAgentsSummary(Request $request, Reporting $reporting)
58 + public function getActiveTicketsByProduct()
48 59 {
49 60 return [
50 - 'summary' => $reporting->agentSummary($request->get('from'), $request->get('to'))
61 + 'stats' => StatModule::getActiveTicketsByProductStats()
51 62 ];
52 63 }
53 64
54 - public function getAgentOverallReports(Request $request)
65 + /**
66 + * getAgentOverallReports method will return the overall statistics report for logged-in agent
67 + * @param Request $request
68 + * @return array
69 + */
70 + public function getAgentOverallReports(Request $request): array
55 71 {
56 72 $agent = Helper::getAgentByUserId(get_current_user_id());
57 73
58 74 return [
59 - 'overall_reports' => StatModule::getAgentOverallStats($agent->id)
75 + 'overall_reports' => StatModule::getAgentOverallStats($agent->id),
76 + 'today_reports' => StatModule::getTodayStats($agent->id)
60 77 ];
61 78 }
62 79
80 + /**
81 + * getAgentResolveChart method will generate ticket data for resolved ticket
82 + * @param Request $request
83 + * @param Reporting $reporting
84 + * @return array
85 + */
63 86 public function getAgentResolveChart(Request $request, Reporting $reporting)
64 87 {
88 + //Get logged in agent information
65 89 $agent = Helper::getAgentByUserId(get_current_user_id());
66 - list($from, $to) = $request->get('date_range') ?: ['', ''];
90 + list($from, $to) = self::getSanitizedDateRange($request);
67 91
68 92 return [
69 93 'stats' => $reporting->getTicketResolveGrowth($from, $to, ['agent_id' => $agent->id])
70 94 ];
@@ -69,12 +93,18 @@
69 93 'stats' => $reporting->getTicketResolveGrowth($from, $to, ['agent_id' => $agent->id])
70 94 ];
71 95 }
72 96
97 + /**
98 + * getAgentResponseChart method will generate the statistics of response by agent in tickets within date range
99 + * @param Request $request
100 + * @param Reporting $reporting
101 + * @return array
102 + */
73 103 public function getAgentResponseChart(Request $request, Reporting $reporting)
74 104 {
75 105 $agent = Helper::getAgentByUserId(get_current_user_id());
76 - list($from, $to) = $request->get('date_range') ?: ['', ''];
106 + list($from, $to) = self::getSanitizedDateRange($request);
77 107
78 108 return [
79 109 'stats' => $reporting->getResponseGrowth($from, $to, ['person_id' => $agent->id])
80 110 ];
@@ -79,13 +109,153 @@
79 109 'stats' => $reporting->getResponseGrowth($from, $to, ['person_id' => $agent->id])
80 110 ];
81 111 }
82 112
113 + /**
114 + * getPersonalSummary method will generate summary for specific agent
115 + * This method will count closed tickets, open tickets, responses/interactions with ticket by agent within a date range
116 + * @param Reporting $reporting
117 + * @param Request $request
118 + * @return array
119 + */
83 120 public function getPersonalSummary(Reporting $reporting, Request $request)
84 121 {
85 122 $agent = Helper::getAgentByUserId(get_current_user_id());
86 123
87 124 return [
88 - 'summary' => $reporting->agentSummary($request->get('from'), $request->get('to'), $agent->id)
125 + 'summary' => $reporting->agentSummary($request->getSafe('from', 'sanitize_text_field'), $request->getSafe('to', 'sanitize_text_field'), $agent->id)
89 126 ];
90 127 }
128 +
129 + /**
130 + * getStats method will return statistics similar to getOverallReports but with filters
131 + * Returns: New Tickets, Active Tickets, Closed Tickets, and Responses
132 + * Filters: date_range, mailbox_id (business_box), product_id, agent_id, customer_id
133 + * @param Request $request
134 + * @return array
135 + */
136 + public function getStats(Request $request)
137 + {
138 + list($from, $to) = self::getSanitizedDateRange($request);
139 +
140 + $filters = [
141 + 'mailbox_id' => $request->getSafe('mailbox_id', 'intval') ?: $request->getSafe('business_box', 'intval'),
142 + 'product_id' => $request->getSafe('product_id', 'intval'),
143 + 'agent_id' => $request->getSafe('agent_id', 'intval'),
144 + 'customer_id' => $request->getSafe('customer_id', 'intval'),
145 + ];
146 +
147 + $agentIds = self::getAgentIdsForGroup($request);
148 +
149 + $access = new AgentTicketAccess();
150 +
151 + // Bound first: a caller-supplied mailbox_id below is not proof of access.
152 + $baseQuery = $access->applyMailboxRestrictionScope(Ticket::query());
153 +
154 + foreach ($filters as $field => $value) {
155 + if ($value) {
156 + $baseQuery->where($field, $value);
157 + }
158 + }
159 +
160 + if ($agentIds !== null) {
161 + $baseQuery->whereIn('agent_id', $agentIds);
162 + }
163 +
164 + $applyDateRange = function($query, $dateField = 'created_at') use ($from, $to) {
165 + if ($from && $to) {
166 + $query->whereBetween($dateField, ["$from 00:00:00", "$to 23:59:59"]);
167 + } elseif ($from) {
168 + $query->where($dateField, '>=', "$from 00:00:00");
169 + } elseif ($to) {
170 + $query->where($dateField, '<=', "$to 23:59:59");
171 + }
172 + };
173 +
174 + $countTickets = function($status, $dateField = 'created_at') use ($baseQuery, $applyDateRange) {
175 + $query = clone $baseQuery;
176 + $query->where('status', $status);
177 + $applyDateRange($query, $dateField);
178 + return $query->count();
179 + };
180 +
181 + $newTickets = $countTickets('new');
182 + $closedTickets = $countTickets('closed', 'resolved_at');
183 +
184 + $openQuery = clone $baseQuery;
185 + $openQuery->where('status', '!=', 'closed');
186 + $applyDateRange($openQuery);
187 + $openTickets = $openQuery->count();
188 +
189 + $responsesQuery = $access->applyMailboxRestrictionScopeViaTicket(
190 + Conversation::query()->where('conversation_type', 'response')
191 + );
192 +
193 + if (array_filter($filters) || $agentIds !== null) {
194 + $responsesQuery->whereHas('ticket', function ($q) use ($filters, $agentIds) {
195 + foreach ($filters as $field => $value) {
196 + if ($value) {
197 + $q->where($field, $value);
198 + }
199 + }
200 + if ($agentIds !== null) {
201 + $q->whereIn('agent_id', $agentIds);
202 + }
203 + });
204 + }
205 +
206 + $applyDateRange($responsesQuery, 'created_at');
207 + $responses = $responsesQuery->count();
208 +
209 + $agentId = $filters['agent_id'];
210 +
211 + if ($agentId) {
212 + $repliesQuery = $access->applyMailboxRestrictionScopeViaTicket(
213 + Conversation::query()
214 + ->where('person_id', $agentId)
215 + ->where('conversation_type', 'response')
216 + );
217 +
218 + $applyDateRange($repliesQuery, 'created_at');
219 + $totalReplies = $repliesQuery->count();
220 +
221 + $stats = [
222 + 'total_replies' => $totalReplies,
223 + 'new_tickets' => $newTickets,
224 + 'closed_tickets' => $closedTickets,
225 + 'responses' => $responses,
226 + 'open_tickets' => $openTickets,
227 + ];
228 + } else {
229 + $activeTickets = $countTickets('active');
230 +
231 + $stats = [
232 + 'new_tickets' => $newTickets,
233 + 'active_tickets' => $activeTickets,
234 + 'closed_tickets' => $closedTickets,
235 + 'responses' => $responses,
236 + 'open_tickets' => $openTickets,
237 + ];
238 + }
239 +
240 + $labels = [
241 + 'total_replies' => __('Total Replies', 'fluent-support'),
242 + 'new_tickets' => __('New Tickets', 'fluent-support'),
243 + 'active_tickets' => __('Active Tickets', 'fluent-support'),
244 + 'closed_tickets' => __('Closed Tickets', 'fluent-support'),
245 + 'responses' => __('Responses', 'fluent-support'),
246 + 'open_tickets' => __('Open Tickets', 'fluent-support'),
247 + ];
248 +
249 + $overallReports = [];
250 + foreach ($stats as $key => $count) {
251 + $overallReports[$key] = [
252 + 'title' => $labels[$key] ?? ucwords(str_replace('_', ' ', (string) $key)),
253 + 'key' => $key,
254 + 'count' => $count,
255 + ];
256 + }
257 +
258 + return ['overall_reports' => $overallReports];
259 + }
260 +
91 261 }