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