PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.3.27
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.3.27
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
fluent-cart / app / Services / Filter / OrderFilter.php

OrderFilter.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.3.27, at app/Services/Filter/OrderFilter.php

502 lines 21.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Services\Filter;
4
5 use FluentCart\Api\ModuleSettings;
6 use FluentCart\App\App;
7 use FluentCart\App\Helpers\AddressHelper;
8 use FluentCart\App\Helpers\Status;
9 use FluentCart\App\Models\Order;
10 use FluentCart\Framework\Database\Orm\Builder;
11 use FluentCart\Framework\Support\Arr;
12 use FluentCartPro\App\Modules\Licensing\Models\License;
13 use FluentCart\App\Modules\PaymentMethods\Core\GatewayManager;
14
15
16 class OrderFilter extends BaseFilter
17 {
18 protected static function statusFilterKeys(): array
19 {
20 return ['payment_statuses', 'order_statuses', 'shipping_statuses'];
21 }
22
23 public function applySimpleFilter(?string $search = null): void
24 {
25 $search = $search ?? $this->search;
26 $isApplied = $this->applySimpleOperatorFilter($search);
27 if ($isApplied) {
28 return;
29 }
30
31 foreach (static::statusFilterKeys() as $statusKey) {
32 $this->query->when(Arr::get($this->args, $statusKey), function ($query, $values) use ($statusKey) {
33 return $query->whereIn($statusKey, Arr::wrap($values));
34 });
35 }
36
37 if (!empty($search)) {
38 $search = trim($search);
39 $searchLike = addcslashes($search, '\\%_');
40
41 $this->query->where(function ($query) use ($search, $searchLike) {
42 $query->where('invoice_no', 'LIKE', "%{$search}%")
43 ->orWhereHas('customer', function ($customerQuery) use ($search, $searchLike) {
44 $customerQuery
45 ->where('email', 'LIKE', "%{$search}%")
46 ->orWhereRaw("CONCAT(first_name, ' ', last_name) LIKE ?", ["%{$searchLike}%"]);
47 })
48 ->orWhereHas('order_items', function ($query) use ($searchLike) {
49 $query->where('title', 'LIKE', "%{$searchLike}%");
50 $query->orWhere('post_title', 'LIKE', "%{$searchLike}%");
51 });
52 });
53 }
54 }
55
56 public function tabsMap(): array
57 {
58 return [
59 'on-hold' => 'status',
60 'paid' => 'payment_status',
61 //'unpaid' => 'payment_status',
62 'completed' => 'status',
63 'processing' => 'status',
64 'renewal' => 'type',
65 'subscription' => 'type',
66 'onetime' => 'type',
67 'refunded' => 'payment_status',
68 'partially_refunded' => 'payment_status',
69 'upgraded_to' => 'upgraded_to',
70 'upgraded_from' => 'upgraded_from'
71 ];
72 }
73
74 public function getModel(): string
75 {
76 return Order::class;
77 }
78
79 public static function getFilterName(): string
80 {
81 return 'orders';
82 }
83
84 public static function parseableKeys(): array
85 {
86 return array_merge(
87 parent::parseableKeys(),
88 static::statusFilterKeys()
89 );
90 }
91
92
93 public function applyActiveViewFilter(?string $activeView = null): void
94 {
95 $activeView = $activeView ?? $this->activeView;
96 $tabsMap = $this->tabsMap();
97
98 //Apply Active Tab view
99 $this->query = $this->query->when($activeView, function (Builder $query, $activeView) use ($tabsMap) {
100
101 if ($activeView === 'upgraded_to') {
102 return $query
103 ->whereRaw("JSON_EXTRACT(config, '$.upgraded_to') IS NOT NULL")
104 ->whereRaw("JSON_EXTRACT(config, '$.upgraded_to') != 0");
105 } else if ($activeView === 'upgraded_from') {
106 return $query
107 ->whereRaw("JSON_EXTRACT(config, '$.upgraded_from') IS NOT NULL")
108 ->whereRaw("JSON_EXTRACT(config, '$.upgraded_from') != 0");
109 } else {
110 return $query->where(
111 $tabsMap[$activeView],
112 $activeView
113 );
114 }
115
116
117 });
118 }
119
120 public static function getSearchableFields(): array
121 {
122 $fields = [
123 'id' => [
124 'column' => 'id',
125 'description' => __('Order Id', 'fluent-cart'),
126 'type' => 'numeric',
127 'examples' => [
128 'id = 1',
129 'id > 5',
130 'id :: 1-10'
131 ]
132 ],
133 'status' => [
134 'column' => 'status',
135 'description' => __('Search by order status e.g., completed, processing, on-hold, canceled, failed', 'fluent-cart'),
136 'type' => 'string',
137 'examples' => [
138 'status = completed',
139 ]
140 ],
141 'invoice' => [
142 'column' => 'status',
143 'description' => __('Invoice Number', 'fluent-cart'),
144 'type' => 'string'
145 ],
146
147 'payment' => [
148 'column' => 'payment_status',
149 'description' => __('Search by payment status e.g., paid, pending, partially_paid, refunded, partially_refunded', 'fluent-cart'),
150 'type' => 'string',
151 'examples' => [
152 'payment = paid',
153 'payment = partially_paid',
154 'payment = partially_refunded',
155 ]
156 ],
157 'payment_by' => [
158 'column' => 'payment_method',
159 'description' => __('Search by payment method e.g., stripe, PayPal, offline_payment', 'fluent-cart'),
160 'type' => 'string',
161 'examples' => [
162 'payment_by = stripe',
163 'payment_by = paypal',
164 ]
165 ],
166
167 'customer' => [
168 'description' => __('Search by customer name or email', 'fluent-cart'),
169 'note' => __("only supports '=' operator", 'fluent-cart'),
170 'type' => 'custom',
171 'callback' => function ($query, $search) {
172 $query->whereHas('customer', function ($query) use ($search) {
173 $query->whereRaw("CONCAT(first_name, ' ', last_name) LIKE ?", ["%{$search}%"])
174 ->orWhere('email', 'like', '%' . $search . '%');
175 });
176 },
177 'examples' => [
178 'customer = jhon',
179 ]
180 ],
181 ];
182
183
184 if (class_exists(License::class)) {
185 $fields['license'] = [
186 'description' => __('Search by license key', 'fluent-cart'),
187 'note' => __("only supports '=' operator", 'fluent-cart'),
188 'type' => 'custom',
189 'callback' => function ($query, $search) {
190 $query->whereHas('licenses', function ($query) use ($search) {
191 $query->where('license_key', 'like', '%' . $search . '%');
192 });
193 },
194 'examples' => [
195 'license = ff-78d47b3fed89bda25cdc5b60d0298d60',
196 ]
197 ];
198 }
199
200 return $fields;
201 }
202
203 public static function advanceFilterOptions(): array
204 {
205 $manager = GatewayManager::getInstance();
206 $payment_routes = $manager->getRoutes();
207 $availablePaymentMethods = [];
208
209 foreach ($payment_routes as $route) {
210 $availablePaymentMethods[$route['name']] = Arr::get($route, 'meta.title', $route['name']);
211 }
212
213
214 $filters = [
215 'order' => [
216 'label' => __('Order Property', 'fluent-cart'),
217 'value' => 'order',
218 'children' => [
219 [
220 'label' => __('By Order Items', 'fluent-cart'),
221 'value' => 'order_items',
222 'column' => 'object_id',
223 'filter_type' => 'relation',
224 'relation' => 'order_items',
225 'remote_data_key' => 'product_variations',
226 'type' => 'remote_tree_select',
227 'limit' => 10,
228 ],
229 [
230 'label' => __('Order Status', 'fluent-cart'),
231 'value' => 'status',
232 'type' => 'selections',
233 'options' => [
234 'completed' => __('Completed', 'fluent-cart'),
235 'processing' => __('Processing', 'fluent-cart'),
236 'on-hold' => __('On Hold', 'fluent-cart'),
237 'canceled' => __('Canceled', 'fluent-cart')
238 ],
239 'is_multiple' => true,
240 'is_only_in' => true
241 ],
242 [
243 'label' => __('Payment Status', 'fluent-cart'),
244 'value' => 'payment_status',
245 'type' => 'selections',
246 'options' => [
247 'paid' => __('Paid', 'fluent-cart'),
248 'pending' => __('Pending', 'fluent-cart'),
249 'partially_paid' => __('Partially Paid', 'fluent-cart'),
250 'refunded' => __('Refunded', 'fluent-cart'),
251 'partially_refunded' => __('Partially Refunded', 'fluent-cart'),
252 //'authorized' => __('Authorized', 'fluent-cart')
253 ],
254 'is_multiple' => true,
255 'is_only_in' => true
256 ],
257 // [
258 // 'label' => __('Shipping Status', 'fluent-cart'),
259 // 'value' => 'shipping_status',
260 // 'type' => 'selections',
261 // 'options' => [
262 // 'fulfilled' => __('Fulfilled', 'fluent-cart'),
263 // 'unfulfilled' => __('Unfulfilled', 'fluent-cart'),
264 // 'on_hold' => __('On Hold', 'fluent-cart')
265 // ],
266 // 'is_multiple' => true,
267 // 'is_only_in' => true
268 // ],
269 [
270 'label' => __('Order Type', 'fluent-cart'),
271 'value' => 'type',
272 'type' => 'selections',
273 'options' => [
274 'payment' => __('Single Payment', 'fluent-cart'),
275 'subscription' => __('Subscription', 'fluent-cart'),
276 'renewal' => __('Renewal', 'fluent-cart'),
277 ],
278 'is_multiple' => true,
279 'is_only_in' => true
280 ],
281 [
282 'label' => __('Payment Method', 'fluent-cart'),
283 'value' => 'payment_method',
284 'type' => 'selections',
285 'column' => 'payment_method',
286 'relation' => 'transactions',
287 'filter_type' => 'relation',
288 'options' => $availablePaymentMethods,
289 'is_multiple' => true,
290 'is_only_in' => true
291 ],
292 [
293 'label' => __('Order Amount', 'fluent-cart'),
294 'value' => 'total_amount',
295 'type' => 'numeric',
296 ],
297 [
298 'label' => __('Order Hash (UUID)', 'fluent-cart'),
299 'value' => 'uuid',
300 'type' => 'text',
301 'column' => 'uuid',
302 'operators' => [
303 'equals' => __('Equals', 'fluent-cart'),
304 'not_equals' => __('Not Equals', 'fluent-cart'),
305 ]
306 ],
307 [
308 'label' => __('Order Date', 'fluent-cart'),
309 'value' => 'created_at',
310 'type' => 'dates',
311 'filter_type' => 'date',
312 ],
313 ],
314 ],
315 'customer' => [
316 'label' => __('Customer Property', 'fluent-cart'),
317 'value' => 'customer',
318
319 'children' => [
320 [
321 'label' => __('Customer Name', 'fluent-cart'),
322 'value' => 'customer_full_name',
323 'type' => 'text',
324 'filter_type' => 'custom',
325 'operators' => [
326 'like_all' => __('Contains', 'fluent-cart'),
327 'starts_with' => __('Starts With', 'fluent-cart'),
328 'ends_with' => __('Ends With', 'fluent-cart'),
329 'not_like' => __('Not Contains', 'fluent-cart'),
330 ],
331 'callback' => function ($query, $data) {
332 $query->whereHas('customer', function ($query) use ($data) {
333 $query->searchByFullName($data);
334 });
335 }
336 ],
337
338 [
339 'label' => __('Customer Email', 'fluent-cart'),
340 'value' => 'customer_email',
341 'type' => 'text',
342 'filter_type' => 'relation',
343 'column' => 'email',
344 'relation' => 'customer',
345 ]
346 ],
347 ],
348 'transactions' => [
349 'label' => __('Transactions Property', 'fluent-cart'),
350 'value' => 'transactions',
351
352 'children' => [
353 [
354 'label' => __('Transaction Id', 'fluent-cart'),
355 'value' => 'transaction_id',
356 'type' => 'text',
357 'filter_type' => 'relation',
358 'column' => 'vendor_charge_id',
359 'relation' => 'transactions',
360 ],
361 [
362 'label' => __('Transaction Status', 'fluent-cart'),
363 'value' => 'transaction_status',
364 'type' => 'selections',
365 'filter_type' => 'relation',
366 'column' => 'status',
367 'relation' => 'transactions',
368 'options' => [
369 Status::TRANSACTION_SUCCEEDED => __('Succeeded', 'fluent-cart'),
370 Status::TRANSACTION_PENDING => __('Pending', 'fluent-cart'),
371 Status::TRANSACTION_REFUNDED => __('Refunded', 'fluent-cart'),
372 Status::TRANSACTION_FAILED => __('Failed', 'fluent-cart'),
373 ],
374 'is_multiple' => true,
375 'is_only_in' => true
376 ],
377 [
378 'label' => __('Transaction Type', 'fluent-cart'),
379 'value' => 'transaction_type',
380 'type' => 'selections',
381 'filter_type' => 'relation',
382 'column' => 'transaction_type',
383 'relation' => 'transactions',
384 'options' => [
385 Status::TRANSACTION_TYPE_CHARGE => __('Charge', 'fluent-cart'),
386 Status::TRANSACTION_TYPE_REFUND => __('Refunded', 'fluent-cart'),
387 Status::TRANSACTION_TYPE_DISPUTE => __('Dispute', 'fluent-cart'),
388 ],
389 'is_multiple' => true,
390 'is_only_in' => true
391 ],
392 [
393 'label' => __('Card last 4', 'fluent-cart'),
394 'value' => 'transaction_card_last',
395 'type' => 'text',
396 'filter_type' => 'relation',
397 'column' => 'card_last_4',
398 'relation' => 'transactions',
399 ],
400 [
401 'label' => __('Card Brand', 'fluent-cart'),
402 'value' => 'transaction_card_brand',
403 'type' => 'text',
404 'filter_type' => 'relation',
405 'column' => 'card_brand',
406 'relation' => 'transactions',
407 ],
408 [
409 'label' => __('Payer email', 'fluent-cart'),
410 'value' => 'payer_email',
411 'type' => 'text',
412 'filter_type' => 'custom',
413 'operators' => [
414 'equals' => __('Equals', 'fluent-cart'),
415 'contains' => __('Contains', 'fluent-cart'),
416 'starts_with' => __('Starts With', 'fluent-cart'),
417 'ends_with' => __('Ends With', 'fluent-cart'),
418 'not_like' => __('Not Contains', 'fluent-cart')
419 ],
420 'callback' => function ($query, $data) {
421 $query->whereHas('transactions', function ($query) use ($data) {
422 $query->searchByPayerEmail($data);
423 });
424 },
425 'examples' => [
426 'payer_email = [email protected]',
427 ]
428 ]
429 ]
430 ]
431 ];
432
433 if (ModuleSettings::isActive('license') && App::isProActive()) {
434 $filters['license'] = [
435 'label' => __('License Property', 'fluent-cart'),
436 'value' => 'license',
437 'children' => [
438 [
439 'label' => __('License key', 'fluent-cart'),
440 'value' => 'license_key',
441 'type' => 'text',
442 'filter_type' => 'relation',
443 'column' => 'license_key',
444 'relation' => 'licenses',
445 ],
446 [
447 'label' => __('License Status', 'fluent-cart'),
448 'value' => 'license_status',
449 'type' => 'selections',
450 'filter_type' => 'relation',
451 'column' => 'status',
452 'relation' => 'licenses',
453 'options' => [
454 Status::LICENSE_ACTIVE => __('Active', 'fluent-cart'),
455 Status::LICENSE_DISABLED => __('Disabled', 'fluent-cart'),
456 Status::LICENSE_EXPIRED => __('Expired', 'fluent-cart'),
457 ],
458 'is_multiple' => true,
459 'is_only_in' => true
460 ]
461 ],
462 ];
463 }
464
465 $utmFilters = [
466 'utm_campaign' => __('Utm Campaign', 'fluent-cart'),
467 'utm_term' => __('Utm Term', 'fluent-cart'),
468 'utm_source' => __('Utm Source', 'fluent-cart'),
469 'utm_medium' => __('Utm Medium', 'fluent-cart'),
470 'utm_content' => __('Utm Content', 'fluent-cart'),
471 'utm_id' => __('Utm Id', 'fluent-cart'),
472 'refer_url' => __('Refer Url', 'fluent-cart'),
473 ];
474
475 $utmChildren = [];
476 foreach ($utmFilters as $key => $label) {
477 $utmChildren[] = [
478 'label' => $label,
479 'value' => $key,
480 'type' => 'text',
481 'filter_type' => 'relation',
482 'column' => $key,
483 'relation' => 'orderOperation',
484 ];
485 }
486
487 $filters['utm'] = [
488 'label' => __('Utm Property', 'fluent-cart'),
489 'value' => 'utm',
490
491 'children' => $utmChildren
492 ];
493 return LabelFilter::advanceFilterOptionsForOther($filters);
494 }
495
496
497 public function centColumns(): array
498 {
499 return ['subtotal', 'shipping_total', 'total_amount', 'total_paid', 'total_refund'];
500 }
501 }
502