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/Models/Traits/AgentTrait.php +78 -33 2.3.0 → 2.4.5 View file →
@@ -3,8 +3,9 @@
3 3 namespace FluentSupport\App\Models\Traits;
4 4
5 5 use FluentSupport\App\Models\Attachment;
6 6 use FluentSupport\App\Models\Conversation;
7 +use FluentSupport\App\Models\Meta;
7 8 use FluentSupport\App\Models\Product;
8 9 use FluentSupport\App\Models\AgentGroup;
9 10 use FluentSupport\App\Models\TagPivot;
10 11 use FluentSupport\App\Models\Ticket;
@@ -11,9 +12,11 @@
11 12 use FluentSupport\App\Modules\PermissionManager;
12 13 use FluentSupport\App\Models\Person;
13 14 use FluentSupport\App\Modules\Reporting\Reporting;
14 15 use FluentSupport\App\Modules\StatModule;
16 +use FluentSupport\App\Services\Helper;
15 17 use FluentSupport\App\Services\TicketHelper;
18 +use FluentSupport\App\Services\Tickets\AgentTicketAccess;
16 19 use FluentSupport\Framework\Support\Arr;
17 20 use Exception;
18 21
19 22 trait AgentTrait
@@ -21,10 +24,64 @@
21 24 public function getAgents($search)
22 25 {
23 26 $agents = static::latest()
24 27 ->searchBy($search)
28 + ->with(['groups' => function ($query) {
29 + $query->select(['fs_taggables.id', 'title']);
30 + }])
25 31 ->paginate();
26 32
33 + $agentIds = $agents->pluck('id')->map('intval')->all();
34 +
35 + if (!$agentIds) {
36 + return $agents;
37 + }
38 +
39 + // One query per kind of data for the whole page, not per agent.
40 + $repliesCount = Conversation::whereIn('person_id', $agentIds)
41 + ->groupBy('person_id')
42 + ->selectRaw('person_id, COUNT(*) AS total')
43 + ->pluck('total', 'person_id')
44 + ->all();
45 +
46 + $interactionsCount = Conversation::whereIn('person_id', $agentIds)
47 + ->groupBy('person_id')
48 + ->selectRaw('person_id, COUNT(DISTINCT ticket_id) AS total')
49 + ->pluck('total', 'person_id')
50 + ->all();
51 +
52 + $metaDefaults = [
53 + 'telegram_chat_id' => '',
54 + 'slack_user_id' => '',
55 + 'whatsapp_number' => '',
56 + 'agent_restrictions' => [
57 + 'restrictedBusinessBoxes' => [],
58 + 'businessBoxRestrictions' => false
59 + ],
60 + 'agent_signature' => '',
61 + 'agent_signature_enabled' => 'no',
62 + ];
63 +
64 + $metaRows = Meta::where('object_type', 'person_meta')
65 + ->whereIn('object_id', $agentIds)
66 + ->whereIn('key', array_keys($metaDefaults))
67 + ->orderBy('id', 'ASC')
68 + ->get(['object_id', 'key', 'value']);
69 +
70 + // First row per agent and key wins, as getMeta()'s first() did.
71 + $metaValues = [];
72 + foreach ($metaRows as $row) {
73 + if (!isset($metaValues[$row->object_id][$row->key])) {
74 + $metaValues[$row->object_id][$row->key] = Helper::safeUnserialize($row->value);
75 + }
76 + }
77 +
78 + // Prime WordPress's user and user meta caches for the permission lookups.
79 + $userIds = array_filter(array_map('intval', $agents->pluck('user_id')->all()));
80 + if ($userIds) {
81 + cache_users($userIds);
82 + }
83 +
27 84 foreach ($agents as $agent) {
28 85 $agent->permissions = PermissionManager::getUserPermissions($agent->user_id);
29 86
30 87 if ($agent->user_id) {
@@ -30,23 +87,23 @@
30 87 if ($agent->user_id) {
31 88 $agent->user_profile = admin_url('user-edit.php?user_id=' . $agent->user_id);
32 89 }
33 90
34 - $agent->replies_count = Conversation::where('person_id', $agent->id)->count();
35 - $agent->interactions_count = Conversation::where('person_id', $agent->id)->groupBy('ticket_id')->get()->count();
91 + $agent->replies_count = (int) Arr::get($repliesCount, $agent->id, 0);
92 + $agent->interactions_count = (int) Arr::get($interactionsCount, $agent->id, 0);
36 93
37 - $agent->telegram_chat_id = $agent->getMeta('telegram_chat_id');
38 - $agent->slack_user_id = $agent->getMeta('slack_user_id');
39 - $agent->whatsapp_number = $agent->getMeta('whatsapp_number');
40 - $agent->restrictions = $agent->getMeta('agent_restrictions', [
41 - 'restrictedBusinessBoxes' => [],
42 - 'businessBoxRestrictions' => false
43 - ]);
94 + // Same rule as getMeta(): a missing or empty value falls back to the default.
95 + $meta = function ($key) use ($metaValues, $metaDefaults, $agent) {
96 + $value = $metaValues[$agent->id][$key] ?? null;
97 + return $value ? $value : $metaDefaults[$key];
98 + };
44 99
45 - $agent->agent_signature = $agent->getMeta('agent_signature', '');
46 - $agent->agent_signature_enabled = $agent->getMeta('agent_signature_enabled', 'no');
47 -
48 - $agent->groups = $agent->groups()->select(['fs_taggables.id', 'title'])->get();
100 + $agent->telegram_chat_id = $meta('telegram_chat_id');
101 + $agent->slack_user_id = $meta('slack_user_id');
102 + $agent->whatsapp_number = $meta('whatsapp_number');
103 + $agent->restrictions = $meta('agent_restrictions');
104 + $agent->agent_signature = $meta('agent_signature');
105 + $agent->agent_signature_enabled = $meta('agent_signature_enabled');
49 106 }
50 107
51 108 return $agents;
52 109 }
@@ -58,9 +115,8 @@
58 115 }
59 116
60 117 $data = $this->setAgentInfo($data, $user);
61 118
62 - // check if another agent has same email address
63 119 $person = Person::where('email', $data['email'])->first();
64 120
65 121 if ($person) {
66 122 throw new \Exception('Sorry, Another agent/person exist with the same email address. Please use a different email address');
@@ -84,11 +140,10 @@
84 140 return $agent;
85 141 }
86 142
87 143 /**
88 - * Method to update agent info
89 144 * @param array $data
90 - * @param $agent
145 + * @param object $agent
91 146 * @return object
92 147 * @throws Exception
93 148 */
94 149 public function updateAgent(array $data, object $agent)
@@ -112,9 +167,10 @@
112 167 }
113 168
114 169
115 170 /**
116 - * This method will delete an agent by agent id
171 + * Delete an agent and move their records to the fallback agent.
172 + *
117 173 * @param int $fallBackAgentId
118 174 * @param int $agentId
119 175 * @return void
120 176 * @throws Exception
@@ -126,10 +182,8 @@
126 182 }
127 183
128 184 $agent = static::findOrFail($agentId);
129 185
130 - PermissionManager::detachPermissions($agent->user_id);
131 -
132 186 try {
133 187 $newAgent = static::findOrFail($fallBackAgentId);
134 188 } catch (\Exception $e) {
135 189 throw new \Exception('Fallback agent could not be found');
@@ -134,8 +188,10 @@
134 188 } catch (\Exception $e) {
135 189 throw new \Exception('Fallback agent could not be found');
136 190 }
137 191
192 + PermissionManager::detachPermissions($agent->user_id);
193 +
138 194 $this->assignDataToFallbackAgent($agent->id, $newAgent);
139 195
140 196 TagPivot::where('source_id', $agent->id)
141 197 ->where('source_type', 'agent_group')
@@ -146,9 +202,8 @@
146 202 static::where('id', $agentId)->delete();
147 203 }
148 204
149 205 /**
150 - * This method will assign data to fallback agent
151 206 * @param int $agentId
152 207 * @param object $newAgent
153 208 * @return void
154 209 */
@@ -188,39 +243,28 @@
188 243 }
189 244
190 245 private function agentDashboardWidgets($data, $with, $agentId)
191 246 {
192 - //If the request come with suggested_tickets
193 247 if (in_array('suggested_tickets', $with)) {
194 - //Get suggested tickets from ticketHelper
195 248 $data['suggested_tickets'] = TicketHelper::getSuggestedTickets($agentId);
196 249 }
197 250
198 - //If the request come with mentioned_tickets
199 251 if (defined('FLUENTSUPPORTPRO') && in_array('ticket_to_watch', $with)) {
200 - //Get the overall statistics by the agent
201 252 $data['ticket_to_watch'] = TicketHelper::getTicketsToWatch();
202 253 }
203 254
204 - //If the request come with overall_stats
205 255 if (in_array('overall_stats', $with)) {
206 - //Get overall status
207 256 $data['overall_stats'] = (new Reporting())->getActiveStats();
208 257 }
209 258
210 - //If the request come with individual_stat
211 259 if (in_array('individual_stat', $with)) {
212 - //get overall statistics by agent id
213 260 $data['individual_stat'] = (new Reporting())->getActiveStatByAgent($agentId);
214 261 }
215 - //If the request come with my_overall_stats
216 262 if (in_array('my_overall_stats', $with)) {
217 - //Get the overall statistics by the agent
218 263 $data['my_overall_stats'] = StatModule::getAgentOverallStats($agentId);
219 264 }
220 265
221 266 if (in_array('tickets_by_products', $with)) {
222 - //Get tickets by product which are waiting for agent reply
223 267 $data['tickets_by_product'] = StatModule::getActiveTicketsByProductStats();
224 268 }
225 269
226 270 return $data;
@@ -226,9 +270,8 @@
226 270 return $data;
227 271 }
228 272
229 273 /**
230 - * Method to set agent info
231 274 * @param array $data
232 275 * @param $user
233 276 * @return array
234 277 */
@@ -247,9 +290,10 @@
247 290 return $data;
248 291 }
249 292
250 293 /**
251 - * Method to set agent meta data
294 + * Save permissions and agent settings meta.
295 + *
252 296 * @param $user
253 297 * @param array $data
254 298 * @param object $agent
255 299 * @return object
@@ -285,8 +329,9 @@
285 329 'businessBoxRestrictions' => $businessBoxRestrictions
286 330 ];
287 331
288 332 $agent->updateMeta('agent_restrictions', $restrictions);
333 + AgentTicketAccess::resetCache();
289 334 $agent->restrictions = $restrictions;
290 335 }
291 336
292 337 if (isset($data['agent_signature'])) {