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/Modules/StatModule.php +161 -49 1.5.52.4.0 View file →
@@ -1,10 +1,14 @@
1 1 <?php
2 2
3 3 namespace FluentSupport\App\Modules;
4 4
5 +use FluentSupport\App\Models\Agent;
5 6 use FluentSupport\App\Models\Conversation;
6 7 use FluentSupport\App\Models\Ticket;
8 +use FluentSupport\App\Models\Product;
9 +use FluentSupport\App\Services\Tickets\AgentTicketAccess;
10 +
7 11 /**
8 12 * StatModule class is responsible for getting data related to report
9 13 * @package FluentSupport\App\Modules
10 14 *
@@ -27,40 +31,44 @@
27 31 $startDate = $currentDate;
28 32 $endDate = $currentDate;
29 33 }
30 34
31 - $startDate = date('Y-m-d 00:00.01', strtotime($startDate));
32 - $endDate = date('Y-m-d 23:59.59', strtotime($endDate));
35 + $startDate = gmdate('Y-m-d 00:00.01', strtotime($startDate));
36 + $endDate = gmdate('Y-m-d 23:59.59', strtotime($endDate));
33 37
38 + $access = new AgentTicketAccess();
39 +
34 40 //Get list of new ticket by agent
35 - $newTickets = Ticket::where('agent_id', $agentId)
36 - ->where('status', 'new')
37 - ->count();
41 + $newTickets = $access->applyMailboxRestrictionScope(
42 + Ticket::where('agent_id', $agentId)->where('status', 'new')
43 + )->count();
38 44
39 45 //Get list of active ticket by agent
40 - $activeTickets = Ticket::where('agent_id', $agentId)
41 - ->where('status', 'active')
42 - ->count();
46 + $activeTickets = $access->applyMailboxRestrictionScope(
47 + Ticket::where('agent_id', $agentId)->where('status', 'active')
48 + )->count();
43 49
44 50 //Get list of closed ticket by agent within a date range(default today)
45 - $closedTickets = Ticket::where('agent_id', $agentId)
46 - ->where('status', 'closed')
47 - ->whereBetween('resolved_at', [$startDate, $endDate])
48 - ->count();
51 + $closedTickets = $access->applyMailboxRestrictionScope(
52 + Ticket::where('agent_id', $agentId)
53 + ->where('status', 'closed')
54 + ->whereBetween('resolved_at', [$startDate, $endDate])
55 + )->count();
49 56
50 57 //Get list of response by agent id within a date range(default today)
51 - $responses = Conversation::where('conversation_type', 'response')
52 - ->where('person_id', $agentId)
53 - ->whereBetween('created_at', [$startDate, $endDate])
54 - ->count();
58 + $responses = $access->applyMailboxRestrictionScopeViaTicket(
59 + Conversation::where('conversation_type', 'response')
60 + ->where('person_id', $agentId)
61 + ->whereBetween('created_at', [$startDate, $endDate])
62 + )->count();
55 63
56 64 //Count the response in tickets within a date range(default today) for agent
57 - $interactions = Conversation::where('person_id', $agentId)
58 - ->where('conversation_type', 'response')
59 - ->whereBetween('created_at', [$startDate, $endDate])
60 - ->groupBy('ticket_id')
61 - ->get()
62 - ->count();
65 + $interactions = $access->applyMailboxRestrictionScopeViaTicket(
66 + Conversation::where('person_id', $agentId)
67 + ->where('conversation_type', 'response')
68 + ->whereBetween('created_at', [$startDate, $endDate])
69 + ->groupBy('ticket_id')
70 + )->get()->count();
63 71
64 72 return [
65 73 'new_tickets' => [
66 74 'title' => __('New Tickets', 'fluent-support'),
@@ -77,9 +85,9 @@
77 85 'responses' => [
78 86 'title' => __('Responses', 'fluent-support'),
79 87 'count' => $responses
80 88 ],
81 - 'interactions' =>[
89 + 'interactions' => [
82 90 'title' => __('Interactions', 'fluent-support'),
83 91 'count' => $interactions
84 92 ]
85 93 ];
@@ -91,19 +99,23 @@
91 99 * @return array[]
92 100 */
93 101 public static function getOverAllStats()
94 102 {
95 - $newTickets = Ticket::where('status', 'new')
103 + $access = new AgentTicketAccess();
104 +
105 + // Same mailbox boundary as the ticket list; these totals are agent-facing.
106 + $newTickets = $access->applyMailboxRestrictionScope(Ticket::where('status', 'new'))
96 107 ->count();
97 108
98 - $activeTickets = Ticket::where('status', 'active')
109 + $activeTickets = $access->applyMailboxRestrictionScope(Ticket::where('status', 'active'))
99 110 ->count();
100 111
101 - $closedTickets = Ticket::where('status', 'closed')
112 + $closedTickets = $access->applyMailboxRestrictionScope(Ticket::where('status', 'closed'))
102 113 ->count();
103 114
104 - $responses = Conversation::where('conversation_type', 'response')
105 - ->count();
115 + $responses = $access->applyMailboxRestrictionScopeViaTicket(
116 + Conversation::where('conversation_type', 'response')
117 + )->count();
106 118
107 119 return [
108 120 'new_tickets' => [
109 121 'title' => __('New Tickets', 'fluent-support'),
@@ -126,24 +138,36 @@
126 138
127 139 /**
128 140 * getTodayStats method will return a stats of today's tickets
129 141 * This method will count the ticket number by ticket status and return the array
130 - * @param bool $agentId By default value set to false however when it gets an agent id it will fetch
142 + * @param bool|int $agentId By default value set to false however when it gets an agent id it will fetch
131 143 * the result by this id
132 144 * @return array result in array format
133 145 */
134 - public static function getTodayStats($agentId=false)
146 + public static function getTodayStats($agentId = false, ?AgentTicketAccess $access = null)
135 147 {
136 - $start = date('Y-m-d 00:00.01');
137 - $end = date('Y-m-d 23:59.59');
148 + $start = gmdate('Y-m-d 00:00.01');
149 + $end = gmdate('Y-m-d 23:59.59');
138 150
139 - $newTickets = Ticket::whereBetween('created_at', [$start, $end]);
151 + $access = $access ?: new AgentTicketAccess();
140 152
141 - $closedTickets = Ticket::where('status', 'closed')->whereBetween('resolved_at', [$start, $end]);
153 + $newTickets = $access->applyMailboxRestrictionScope(
154 + Ticket::whereBetween('created_at', [$start, $end])
155 + );
142 156
143 - $responses = Conversation::where('conversation_type', 'response')->whereBetween('created_at', [$start, $end]);
157 + $closedTickets = $access->applyMailboxRestrictionScope(
158 + Ticket::where('status', 'closed')->whereBetween('resolved_at', [$start, $end])
159 + );
144 160
145 - if($agentId) {
161 + $responses = $access->applyMailboxRestrictionScopeViaTicket(
162 + Conversation::where('conversation_type', 'response')
163 + ->whereHas('person', function ($q) {
164 + $q->where('person_type', 'agent');
165 + })
166 + ->whereBetween('created_at', [$start, $end])
167 + );
168 +
169 + if ($agentId) {
146 170 $newTickets->where('agent_id', $agentId);
147 171 $closedTickets->where('agent_id', $agentId);
148 172 $responses->where('person_id', $agentId);
149 173 }
@@ -171,33 +195,121 @@
171 195 */
172 196 public static function getAgentOverallStats($agentId)
173 197 {
174 198 //Get count of response by the agent
175 - $replies_count = Conversation::where('person_id', $agentId)->count();
199 + $replies_count = (new AgentTicketAccess())->applyMailboxRestrictionScopeViaTicket(
200 + Conversation::where('person_id', $agentId)
201 + )->count();
176 202
177 203 //Get the number of interactions/responses by agent with tickets
178 - $interactions_count = Conversation::where('person_id', $agentId)
179 - ->where('conversation_type', 'response')
180 - ->groupBy('ticket_id')
181 - ->get()
182 - ->count();
204 + $interactions_count = (new AgentTicketAccess())->applyMailboxRestrictionScopeViaTicket(
205 + Conversation::where('person_id', $agentId)
206 + ->where('conversation_type', 'response')
207 + ->groupBy('ticket_id')
208 + )->get()->count();
183 209
184 210 //Get the number of tickets that are closed by this agent
185 - $total_closed = Ticket::where('agent_id', $agentId)->where('status', 'closed')->count();
211 + $total_closed = (new AgentTicketAccess())->applyMailboxRestrictionScope(
212 + Ticket::where('agent_id', $agentId)->where('status', 'closed')
213 + )->count();
186 214
187 215 return [
188 - 'replies_count' => [
216 + 'replies_count' => [
189 217 'title' => __('Total Replies', 'fluent-support'),
190 218 'count' => $replies_count
191 219 ],
192 - 'interactions_count' => [
193 - 'title' => __('Total Interactions', 'fluent-support'),
194 - 'count' => $interactions_count
195 - ],
196 - 'total_closed' => [
220 + // 'interactions_count' => [
221 + // 'title' => __('Total Interactions', 'fluent-support'),
222 + // 'count' => $interactions_count
223 + // ],
224 + 'total_closed' => [
197 225 'title' => __('Total Closed', 'fluent-support'),
198 226 'count' => $total_closed
199 227 ]
200 228 ];
229 + }
230 +
231 + /**
232 + * This `getActiveTicketsByProductStats` method will count today's tickets by product that are waiting for reply
233 + * @return array $result
234 + */
235 + public static function getActiveTicketsByProductStats()
236 + {
237 + $products = Product::all();
238 + $result = [];
239 + $access = new AgentTicketAccess();
240 +
241 + foreach ($products as $product) {
242 + $result[$product->id] = [
243 + 'title' => $product->title,
244 + 'count' => static::countAwaitingTickets('product_id', $product->id, $access)
245 + ];
246 + }
247 +
248 + return $result;
249 + }
250 +
251 +
252 + /**
253 + * This will count the number of tickets that are waiting for response also it can receive parameters
254 + * @param string $whereClause // This is the where clause that will be used in the query
255 + * @param string $whereClauseValue // This is the value of the where clause
256 + * @return int $awatingTicketCount
257 + */
258 + public static function countAwaitingTickets($whereClause = null, $whereClauseValue = null, ?AgentTicketAccess $access = null)
259 + {
260 + // Must be a builder: ->where() on a bare model returns a new one, losing the scope.
261 + $ticket = Ticket::query();
262 +
263 + if ($whereClause && $whereClauseValue) {
264 + $ticket = $ticket->where(sanitize_text_field($whereClause), sanitize_text_field($whereClauseValue));
265 + }
266 +
267 + $ticket = ($access ?: new AgentTicketAccess())->applyMailboxRestrictionScope($ticket);
268 +
269 + $awatingTicketCount = $ticket->where('status', '!=', 'closed')
270 + ->where(function ($query) {
271 + $query->whereColumn('last_agent_response', '<', 'last_customer_response')
272 + ->orWhereNull('last_agent_response')
273 + ->orWhere('status', 'new');
274 + })->count();
275 +
276 + return $awatingTicketCount;
277 + }
278 +
279 + /**
280 + * This method will return a summary of today's stats of all agent
281 + * @return array
282 + */
283 + public static function getAgentTodayStats()
284 + {
285 + $stats = [];
286 + // One instance for the whole loop: resolving restrictions costs an agent and
287 + // meta read, and a fresh instance per agent would repeat it 44 times.
288 + $access = new AgentTicketAccess();
289 +
290 + Agent::get()->each(function ($agent) use (&$stats, $access) {
291 + $agentStat = static::getTodayStats($agent->id, $access);
292 + $waiting = static::countAwaitingTickets('agent_id', $agent->id, $access);
293 + if(!empty($agentStat['responses']['count']) || $waiting) {
294 + $stats[] = [
295 + 'agent_id' => $agent->id,
296 + 'agent_name' => $agent->full_name,
297 + 'agent_email' => $agent->email,
298 + 'avatar' => $agent->photo,
299 + 'stats' => array_merge(
300 + [
301 + 'waiting_today' => [
302 + 'title' => __('Waiting Today', 'fluent-support'),
303 + 'count' => $waiting
304 + ]
305 + ],
306 + $agentStat
307 + )
308 + ];
309 + }
310 + });
311 +
312 + return $stats;
201 313 }
202 314
203 315 }