Here's the whole sql method...
/**
* Converting ticket SQL to Eloquent/QueryBuilder magic
* Hopefully this works =T
*
* @param search:term - Search term for deep searching issues and comments
* @param billable:bool - Filters billable tickets
* @param assigned:id - Filters tickets by ticket assignee id
* @param closed:bool - Filters closed tickets
* @param all:bool - Removes filters for opened, closed, on-hold, etc.
* @param department:id - Filters tickets by location department id
* @param customer:id - Filters tickets by location customer id
* @param location:id - Filters tickets by location id
* @param opener:id - Filters tickets by ticket created_by id
* @param closer:id - Filters tickets by ticket closed_by id
* @param action:open|closed - Filters tickets closed/not-closed betweem dates
* @param from:datestamp
* @param to:datestamp
* @param sort:assignee|status|date
*/
public function sql(Request $request)
{
$tickets = Ticket::query();
$tickets = $tickets->select(
'tickets.id',
'tickets.location_id',
'tickets.status_id',
'tickets.assignee_id',
'tickets.issue',
'tickets.weekend',
'tickets.after_hours',
'tickets.billable',
'tickets.billed',
'tickets.created_by',
'tickets.created_at',
'tickets.closed_by',
'tickets.closed_at',
'locations.customer_id',
'locations.label',
'ticket_statuses.id as status_id',
'customers.name'
);
$tickets = $tickets->leftJoin('locations', 'locations.id', '=', 'tickets.location_id');
$tickets = $tickets->leftJoin('customers', 'customers.id', '=', 'locations.customer_id');
$tickets = $tickets->leftJoin('ticket_statuses', 'ticket_statuses.id', '=', 'tickets.status_id');
// Filter: Search Term - Ticket Issue & All Comments
if ($request->is('ticket*') && $request->filled('search')) {
$tickets = $tickets->addSelect('comments.commentable_id', 'comments.commentable_type', 'comments.comment');
$tickets = $tickets->leftJoin('comments', function ($join) {
$join->on('tickets.id', '=', 'comments.commentable_id')
->where('comments.commentable_type', '=', 'App\Models\Ticket');
});
$searchedWords = collect(explode(' ', $request->search));
$searchedWords->each(function ($searchedWord) use ($tickets) {
$tickets = $tickets->where(function ($query) use ($searchedWord) {
$query->where('tickets.issue', 'like', '%'.$searchedWord.'%');
$query->orWhere('comments.comment', 'like', '%'.$searchedWord.'%');
});
});
}
// Filter: Billable
if ($request->is('ticket*') && $request->filled('billable')) {
$tickets = $tickets->billable();
}
// Filter: Assigned to user
if ($request->is('ticket*') && $request->filled('assigned')) {
$tickets = $tickets->where('tickets.assignee_id', $request->assigned);
}
// Filter: Closed
if ($request->is('ticket*') && $request->scope == 'closed') {
$tickets = $tickets->closed();
}
// Filter: All or Not-Closed (Default)
if ((!$request->scope == 'all') || ($request->scope == 'open')) {
$tickets = $tickets->notClosed();
}
// Filter: Department
if ($request->is('ticket*') && $request->filled('department')) {
$tickets = $tickets->whereHas('location', function (Builder $query) use ($request) {
$query->where('locations.department_id', $request->department);
});
}
// Filter: Customer
if ($request->is('ticket*') && $request->filled('customer')) {
$tickets = $tickets->whereHas('location', function (Builder $query) use ($request) {
$query->where('locations.customer_id', $request->customer);
});
}
// Filter: Location
if ($request->is('ticket*') && $request->filled('location')) {
$tickets = $tickets->where('tickets.location_id', $request->location);
}
// Filter: Opened By & Closed By
if ($request->is('ticket*') && $request->filled('opener')) {
$tickets = $tickets->where('tickets.created_by', $request->opener);
}
if ($request->is('ticket*') && $request->filled('closer')) {
$tickets = $tickets->where('tickets.closed_by', $request->closer);
}
/**
* Filter: Date Range
* @param scope - all, opened, closed
* @param from - 2020-01-01
* @param to - 2022-03-31
*/
if ($request->is('ticket*') && ($request->filled('from') || $request->filled('to'))) {
// Default to waaay in the past
$from = now()->subYears(500)->toDateTimeString();
if ($request->from) {
$from = Carbon::parse($request->from, auth()->user()->settings->timezone)
->startOfDay()->timezone('UTC')->toDateTimeString();
}
// Default to waaay in the future
// Theory being, nothing can happen before "now" anyways
$to = now()->addYears(500)->toDateTimeString();
if ($request->to) {
$to = Carbon::parse($request->to, auth()->user()->settings->timezone)
->endOfDay()->timezone('UTC')->toDateTimeString();
}
if ((in_array($request->scope, ['all', 'open'])) && (!$request->has('closer'))) {
$tickets = $tickets->whereBetween('tickets.created_at', [$from, $to]);
}
if (($request->scope == 'closed') || $request->has('closer')) {
$tickets = $tickets->whereBetween('tickets.closed_at', [$from, $to]);
}
}
// Ignore hidden locations
$tickets = $tickets->whereHas('location', function (Builder $query) {
$query->where('locations.hidden', false);
});
// Clear multiple results if searching because of comment left join
if ($request->is('ticket*') && $request->filled('search')) {
$tickets = $tickets->distinct('tickets.id');
}
/**
* Sort
* @param sort - assignee, date, status
* @param scope - closed
*/
if ($request->is('ticket*') && $request->scope == 'closed') {
$tickets = $tickets->orderByDesc('tickets.closed_at');
}
$sort = $request->sort ?: auth()->user()->settings->tix_sort;
if ($request->is('ticket*') && $sort == 'assignee') {
$tickets = $tickets->orderByDesc('tickets.assignee_id')
->orderBy('ticket_statuses.priority')
->orderByDesc('tickets.created_at');
}
if ($request->is('ticket*') && $sort == 'status') {
$tickets = $tickets->orderBy('ticket_statuses.priority')
->orderByDesc('tickets.created_at');
}
if ($request->is('ticket*') && $sort == 'date') {
$tickets = $tickets->orderByDesc('tickets.created_at');
}
$tickets = $tickets->orderBy('customers.name');
// dd($tickets->toSql());
return $tickets;
}
This is the method that calls it...
/**
* This is the server-driven-parital that actually shows the ticket list
*/
public function display(Request $request)
{
$tickets = $this->sql($request);
// Pagination Limit
if (!$request->page || ($request->page == '1')) {
$tickets = $tickets->offset(0)->limit(auth()->user()->settings->pagination);
} else {
$page = $request->page - 1;
$page = $page * auth()->user()->settings->pagination;
$tickets = $tickets->offset($page)->limit(auth()->user()->settings->pagination);
}
$tickets = $tickets->get();
return view('pages.resources.ticket.ticket-display.main', compact('tickets'));
}
Here is the SQL output...
select
distinct `tickets`.`id`,
`tickets`.`location_id`,
`tickets`.`status_id`,
`tickets`.`assignee_id`,
`tickets`.`issue`,
`tickets`.`weekend`,
`tickets`.`after_hours`,
`tickets`.`billable`,
`tickets`.`billed`,
`tickets`.`created_by`,
`tickets`.`created_at`,
`tickets`.`closed_by`,
`tickets`.`closed_at`,
`locations`.`customer_id`,
`locations`.`label`,
`ticket_statuses`.`id` as `status_id`,
`customers`.`name`,
`comments`.`commentable_id`,
`comments`.`commentable_type`,
`comments`.`comment`
from
`tickets`
left join `locations` on `locations`.`id` = `tickets`.`location_id`
left join `customers` on `customers`.`id` = `locations`.`customer_id`
left join `ticket_statuses` on `ticket_statuses`.`id` = `tickets`.`status_id`
left join `comments` on `tickets`.`id` = `comments`.`commentable_id`
and `comments`.`commentable_type` = 'App\Models\Ticket'
where
(
`tickets`.`issue` like '%eod%'
or `comments`.`comment` like '%eod%'
)
and `status_id` != 5
and `tickets`.`created_at` between '2020-09-01 05:00:00'
and '2020-09-13 04:59:59'
and exists (
select
*
from
`locations`
where
`tickets`.`location_id` = `locations`.`id`
and `locations`.`hidden` = 0
)
order by
`tickets`.`created_at` desc,
`customers`.`name` asc
limit
20 offset 0