PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.3.2
Fluent Support – Helpdesk & Customer Support Ticket System v2.3.2
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 1.5.6 All 67 releases
fluent-support / app / Modules / MCP / Tools / CustomerTools.php

CustomerTools.php in Fluent Support – Helpdesk & Customer Support Ticket System 2.3.2, at app/Modules/MCP/Tools/CustomerTools.php

161 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentSupport\App\Modules\MCP\Tools;
4
5 use FluentSupport\App\Models\Customer;
6 use FluentSupport\App\Models\Ticket;
7 use FluentSupport\App\Modules\MCP\Helpers\MCPHelper;
8 use FluentSupport\App\Modules\PermissionManager;
9
10 class CustomerTools
11 {
12 public static function searchCustomers($params)
13 {
14 $agent = MCPHelper::resolveAgent();
15 if (!$agent) {
16 return MCPHelper::error('unauthorized', __('No agent found for current user', 'fluent-support'));
17 }
18
19 $search = sanitize_text_field($params['search'] ?? '');
20
21 ['page' => $page, 'per_page' => $perPage] = MCPHelper::pagination($params);
22
23 $restricted = PermissionManager::getRestrictedMailboxIds();
24
25 $query = Customer::select([
26 'id', 'first_name', 'last_name', 'email', 'status', 'city', 'state', 'country', 'created_at',
27 ]);
28
29 if ($search) {
30 $query->where(function ($q) use ($search) {
31 $q->where('first_name', 'LIKE', "%{$search}%")
32 ->orWhere('last_name', 'LIKE', "%{$search}%")
33 ->orWhere('email', 'LIKE', "%{$search}%")
34 ->orWhereRaw("CONCAT(first_name, ' ', last_name) LIKE ?", ["%{$search}%"]);
35 });
36 }
37
38 // Exclude customers who only have tickets in restricted mailboxes.
39 if ($restricted) {
40 $query->where(function ($q) use ($restricted) {
41 $q->whereDoesntHave('tickets')
42 ->orWhereHas('tickets', function ($tq) use ($restricted) {
43 $tq->whereNotIn('mailbox_id', $restricted);
44 });
45 });
46 }
47
48 $paginated = $query->orderBy('id', 'DESC')->paginate($perPage, ['*'], 'page', $page);
49
50 $pageItems = $paginated->items();
51 $customerIds = array_map(fn($c) => $c->id, $pageItems);
52
53 $ticketCounts = [];
54 if ($customerIds) {
55 $countQuery = Ticket::whereIn('customer_id', $customerIds);
56 if ($restricted) {
57 $countQuery->whereNotIn('mailbox_id', $restricted);
58 }
59 $rows = $countQuery
60 ->selectRaw('customer_id, COUNT(*) as total_tickets, SUM(CASE WHEN status != \'closed\' THEN 1 ELSE 0 END) as open_tickets')
61 ->groupBy('customer_id')
62 ->get()
63 ->keyBy('customer_id');
64
65 foreach ($rows as $cid => $row) {
66 $ticketCounts[$cid] = [
67 'total_tickets' => (int) $row->total_tickets,
68 'open_tickets' => (int) $row->open_tickets,
69 ];
70 }
71 }
72
73 $customers = [];
74 foreach ($pageItems as $customer) {
75 $item = MCPHelper::formatCustomerForMCP($customer);
76 $item['total_tickets'] = $ticketCounts[$customer->id]['total_tickets'] ?? 0;
77 $item['open_tickets'] = $ticketCounts[$customer->id]['open_tickets'] ?? 0;
78 $customers[] = $item;
79 }
80
81 $total = $paginated->total();
82 $summary = $search
83 ? sprintf(_n("Found %d customer matching '%s'", "Found %d customers matching '%s'", $total, 'fluent-support'), $total, $search)
84 : sprintf(_n('Found %d customer', 'Found %d customers', $total, 'fluent-support'), $total);
85
86 return MCPHelper::envelope($summary, ['customers' => $customers], MCPHelper::pagingMeta($paginated));
87 }
88
89 public static function getCustomerTickets($params)
90 {
91 $customerId = (int) ($params['customer_id'] ?? 0);
92 $email = sanitize_email($params['email'] ?? '');
93 $name = sanitize_text_field($params['name'] ?? '');
94
95 $customer = null;
96
97 if ($customerId) {
98 $customer = Customer::find($customerId);
99 } elseif ($email) {
100 $customer = Customer::where('email', $email)->first();
101 } elseif ($name) {
102 $customer = Customer::where(function ($q) use ($name) {
103 $q->where('first_name', 'LIKE', '%' . $name . '%')
104 ->orWhere('last_name', 'LIKE', '%' . $name . '%')
105 ->orWhere('email', 'LIKE', '%' . $name . '%');
106 })->first();
107 }
108
109 if (!$customer) {
110 return MCPHelper::error('not_found', __('Customer not found. Provide customer_id, email, or name.', 'fluent-support'), ['next_step' => 'Use search-customers to find the customer first']);
111 }
112
113 ['page' => $page, 'per_page' => $perPage] = MCPHelper::pagination($params);
114
115 $query = Ticket::with([
116 'agent' => function ($q) {
117 $q->select(['id', 'first_name', 'last_name', 'email']);
118 },
119 ])->where('customer_id', $customer->id);
120
121 if (!empty($params['status'])) {
122 $statuses = \FluentSupport\App\Services\Helper::getTkStatusesByGroupName($params['status']);
123 if ($statuses) {
124 $query->whereIn('status', $statuses);
125 }
126 }
127
128 do_action_ref_array('fluent_support/tickets_query_by_permission_ref', [&$query]);
129
130 $restricted = PermissionManager::getRestrictedMailboxIds();
131 if ($restricted) {
132 $query->whereNotIn('mailbox_id', $restricted);
133 }
134
135 $paginated = $query->orderBy('id', 'DESC')->paginate($perPage, ['*'], 'page', $page);
136
137 $tickets = [];
138 foreach ($paginated->items() as $ticket) {
139 $tickets[] = [
140 'id' => $ticket->id,
141 'title' => $ticket->title,
142 'status' => $ticket->status,
143 'priority' => MCPHelper::normalizePriority($ticket->priority),
144 'response_count' => (int) $ticket->response_count,
145 'created_at' => MCPHelper::toIso8601($ticket->created_at),
146 'agent' => $ticket->agent ? MCPHelper::formatPersonSummary($ticket->agent) : null,
147 ];
148 }
149
150 $total = $paginated->total();
151 $identifier = $customer->email ?: MCPHelper::personName($customer);
152 $summary = sprintf(_n('Found %d ticket for %s', 'Found %d tickets for %s', $total, 'fluent-support'), $total, $identifier);
153
154 return MCPHelper::envelope(
155 $summary,
156 ['customer' => MCPHelper::formatCustomerForMCP($customer), 'tickets' => $tickets],
157 MCPHelper::pagingMeta($paginated)
158 );
159 }
160 }
161