tickets/app/controllers/admin/tickets_controller.rb

444 lines
16 KiB
Ruby

class Admin::TicketsController < OrbitAdminController
include TicketsHelper
before_action :set_smart_tags
def index
mp = current_user.member_profile rescue nil
@tickets = {}
@urgent_tickets = {}
if !mp.nil?
authorizations = Authorization.where(:role_id.in => mp.roles.collect{|mm| mm.id})
if authorizations.count == 0
@categories = ModuleApp.find_by_key("ticket").categories rescue []
@categories.each do |category|
@tickets[category] = Ticket.where(:category_id => category.id).open.not_urgent.limit(5).asc(:created_at)
@urgent_tickets[category] = Ticket.where(:category_id => category.id).open.all_urgent.asc(:created_at)
end
else
@categories = authorizations.collect{|authorization| authorization.category}
@categories.delete(nil)
@categories.uniq!
@categories.each do |category|
temp = Ticket.where(:category_id => category.id).open.not_urgent.limit(5).asc(:created_at)
@tickets[category] = temp if temp.count > 0
temp = Ticket.where(:category_id => category.id).open.all_urgent.asc(:created_at)
@urgent_tickets[category] = temp if temp.count > 0
end
end
end
end
def my_tickets
if params[:type] == "history"
if params[:keywords].present?
@tickets = search_tickets
@tickets = @tickets.where(:taken_by => current_user.id).closed.group_by(&:category)
else
@tickets = Ticket.where(:taken_by => current_user.id).closed.group_by(&:category)
end
else
if params[:keywords].present?
@tickets = search_tickets
@tickets = @tickets.where(:taken_by => current_user.id).commenced.desc(:urgent).group_by(&:category)
else
@tickets = Ticket.where(:taken_by => current_user.id).commenced.desc(:urgent).group_by(&:category)
end
end
@categories = @tickets.keys
end
def tagged_tickets
if params[:keywords].present?
statuses = ["open","commenced", "closed"]
else
statuses = ["open","commenced"]
end
tqrs = TicketQueryResponse.where(:user_tags.in => [current_user.id.to_s], :read_by.nin => [current_user.id.to_s])
@unread_tickets = []
@read_tickets = []
tqrs.each do |tqr|
@unread_tickets << tqr.ticket_query.ticket if !tqr.ticket_query.nil? && !tqr.ticket_query.ticket.nil? && statuses.include?(tqr.ticket_query.ticket.status)
end
tqrs = TicketQueryResponse.where(:user_tags.in => [current_user.id.to_s], :read_by.in => [current_user.id.to_s])
tqrs.each do |tqr|
@read_tickets << tqr.ticket_query.ticket if !tqr.ticket_query.nil? && !tqr.ticket_query.ticket.nil? && statuses.include?(tqr.ticket_query.ticket.status)
end
@read_tickets.uniq!
@unread_tickets.uniq!
if params[:keywords].present?
tickets = search_tickets
@read_tickets = @read_tickets & tickets
@unread_tickets = @unread_tickets & tickets
end
@unread_tickets = @unread_tickets.group_by(&:category)
@read_tickets = @read_tickets.group_by(&:category)
@unread_tickets_categories = @unread_tickets.keys
@read_tickets_categories = @read_tickets.keys
end
def show
@ticket = Ticket.find(params[:id]) rescue nil
@categories = ModuleApp.find_by_key("ticket").categories
@members = []
MemberProfile.all.each do |mp|
user = mp.user rescue nil
if !user.nil? && user.id.to_s != current_user.id.to_s
avatar = (mp.avatar.thumb.url == "thumb_person.png" ? "/assets/thumb_person.png" : mp.avatar.thumb.url rescue "/assets/thumb_person.png")
@members << {
"id" => user.id.to_s,
"user_name" => (user.user_name rescue ""),
"avatar" => avatar,
"name" => (mp.name_translations rescue {"en" => "","zh_tw" => ""})
}
end
end
end
def changecategory
ticket = Ticket.find(params[:ticket_id]) rescue nil
category = Category.find(params[:category_id]) rescue nil
if !category.nil?
ticket.category_id = category.id
ticket.save
end
redirect_to admin_ticket_path(ticket.id)
end
def start
ticket = Ticket.find(params[:ticket_id]) rescue nil
ticket.status = "commenced"
ticket.taken_by = current_user.id
ticket.save
redirect_to admin_ticket_path(ticket.id)
end
def close
ticket = Ticket.find(params[:ticket_id]) rescue nil
ticket.status = "closed"
ticket.urgent = false
ticket.save
redirect_to admin_ticket_path(ticket.id)
end
def leave
ticket = Ticket.find(params[:ticket_id]) rescue nil
ticket.status = "open"
ticket.taken_by = nil
ticket.save
redirect_to admin_ticket_path(ticket.id)
end
def reopen
ticket = Ticket.find(params[:ticket_id]) rescue nil
ticket.status = "open"
ticket.reopened_count = ticket.reopened_count + 1
tq = TicketQuery.new
tq.query = params[:ticket_query]
tq.ticket = ticket
tq.save
ticket.save
response = {}
response["success"] = true
render :json => response.to_json
end
def destroy
tick = Ticket.find(params[:id]) rescue nil
tick.destroy if !tick.nil?
redirect_to admin_tickets_path
end
def toggleurgent
mark_urgent = params[:mark_urgent]
if mark_urgent
ticket = Ticket.find(params[:ticket_id]) rescue nil
if !ticket.nil?
if mark_urgent == "true"
if can_mark_urgent?(ticket)
ticket.urgent = true
ticket.save
response = {"success" => true, "can_make_urgent" => true}
else
response = {"success" => true, "can_make_urgent" => false}
end
else
ticket.urgent = false
ticket.save
response = {"success" => true, "can_make_urgent" => true}
end
else
response = {"success" => false}
end
end
render :json => response.to_json
end
def search
@tickets = search_tickets
if !@tickets.nil?
@tickets = @tickets.group_by(&:category)
@categories = @tickets.keys
else
@tickets = {}
@categories = []
end
end
def submit_response
tq = TicketQuery.find(params[:ticket_query_id]) rescue nil
if !tq.nil?
response = TicketQueryResponse.new
response.response = smart_store_link_parser(params[:ticket_query_response])
response.response_by = current_user.id
response.internal_response = params[:internal_response] if params[:internal_response].present?
response.user_tags = params[:user_tags] if params[:user_tags].present?
response.save
if !response.internal_response
notify_response_to_client(tq.ticket) rescue nil
end
tq.ticket_query_responses << response
if params[:user_tags].present?
Thread.new do
begin
send_notification_emails(response, tq.ticket)
rescue e
end
end
# url = "/admin/tickets-manage/#{tq.ticket.id.to_s}#response_#{response.id.to_s}"
# Fiber.new{
# params[:user_tags].each do |user_id|
# WebsocketRails["tag_notifications_for_#{user_id}".to_sym].trigger(:new_notification_recieved, {"ticket_link" => "<a href='#{url}'>#{tq.ticket.subject}</a>", "total_ticket_count" => Ticket.get_ticket_unread_count_for_user(user_id), "blink_message" => "#{current_user.name} tagged you!"})
# end
# }.resume
end
render :partial => "response", :object => response
else
render :json => {"success" => true}.to_json
end
end
def mark_response_read
response = TicketQueryResponse.find(params[:response_id]) rescue nil
if !response.nil?
response.read_by << current_user.id.to_s if !response.read_by.include?(current_user.id.to_s)
response.save
data = {"success" => true, "user_id" => current_user.id.to_s, "total_ticket_count" => Ticket.get_ticket_unread_count_for_user(current_user)}
else
data = {"success" => false}
end
render :json => data.to_json
end
def delete_response
response = TicketQueryResponse.find(params[:response_id]) rescue nil
response.destroy if !response.nil?
render :json => {"success" => true}.to_json
end
def tickets_by_category
@table_fields = [:tagged, :ticket_number, :site_name, :subject, :created_at, :tags, :status, :taken_by, :urgent]
statuses = params["type"] == "history" ? ["closed"] : ["open","commenced"]
@category = Category.find(params[:category_id]) rescue nil
if params[:keywords].present?
keywords = params[:keywords]
type = (keywords.is_i? ? (keywords.length == 8 ? "number" : "text") : "text")
if type == "text"
regex = Regexp.new(/[a-z]+:/)
matches = keywords.scan(regex)
if !matches.blank?
smart_field = matches.first
if @smart_search_fields.include?(smart_field)
type = "smart"
keywords = keywords.sub(smart_field,"")
end
end
end
end
if type.nil?
@tickets = Ticket.where(:category_id => @category.id, :status.in => statuses).order_by(sort)
else
case type
when "number"
@tickets = Ticket.where(:category_id => @category.id, :status.in => statuses, :uid => keywords).order_by(sort)
when "text"
@tickets = Ticket.where(:category_id => @category.id, :status.in => statuses).order_by(sort)
@tickets = search_data(@tickets,[:subject, :uid, :status, :site_type, :ticket_creater_id, :ticket_creater_name])
regex = Regexp.new(".*"+keywords+".*", "i")
sites = RegisteredSite.any_of({:title => regex},{:site_domain => regex})
sites.each do |site|
@tickets = (@tickets | site.tickets.where(:category_id => @category.id, :status.in => statuses))
end
when "smart"
@tickets = smart_search(statuses,@category,smart_field,keywords)
@tickets = @tickets.order_by(sort) rescue @tickets
end
end if !@category.nil?
@tickets = @tickets.where(:taken_by => current_user.id) if params[:takenby].present?
@tickets = Kaminari.paginate_array(@tickets).page(params[:page]).per(15) if !@tickets.nil?
end
private
def search_tickets
statuses = ["open","commenced","closed"]
if params[:keywords].present?
keywords = params[:keywords]
type = (keywords.is_i? ? (keywords.length == 8 ? "number" : "text") : "text")
if type == "text"
regex = Regexp.new(/[a-z]+:/)
matches = keywords.scan(regex)
if !matches.blank?
smart_field = matches.first
if @smart_search_fields.include?(smart_field)
type = "smart"
keywords = keywords.sub(smart_field,"")
end
end
end
end
case type
when "number"
tickets = Ticket.where(:status.in => statuses, :uid => keywords)
when "text"
tickets = Ticket.where(:status.in => statuses)
tickets = search_data(tickets,[:subject, :uid, :status, :site_type, :ticket_creater_id, :ticket_creater_name])
regex = Regexp.new(".*"+keywords+".*", "i")
sites = RegisteredSite.any_of({:title => regex},{:site_domain => regex})
sites.each do |site|
tickets = (tickets | site.tickets.where(:status.in => statuses))
end
when "smart"
tickets = smart_search(statuses,nil,smart_field,keywords)
end
tickets
end
def can_mark_urgent?(ticket)
tickets = Ticket.where(:category_id => ticket.category_id, :urgent => true).count
return tickets < 5
end
def set_smart_tags
@smart_search_fields = ["sitename:","domain:","subject:","ticket:","status:","query:","type:","takenby:","time:"]
end
def smart_search(statuses, category = nil, smart_field, keywords)
keywords = keywords.strip.nil? ? keywords : keywords.strip
regexes = keywords.split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/)
regex = Regexp.union(regexes.map{|word| Regexp.new(".*"+word+".*", "i")})
tickets = []
case smart_field
when "sitename:"
sites = RegisteredSite.where(:title => regex)
sites.each do |site|
if category.nil?
tickets = site.tickets.where(:status.in => statuses).limit(25)
else
tickets = site.tickets.where(:category_id => category.id, :status.in => statuses)
end
end
when "domain:"
sites = RegisteredSite.where(:site_domain => regex)
sites.each do |site|
if category.nil?
tickets = site.tickets.where(:status.in => statuses).limit(25)
else
tickets = site.tickets.where(:category_id => category.id, :status.in => statuses)
end
end
when "subject:"
if category.nil?
tickets = Ticket.where(:subject => regex, :status.in => statuses).limit(25)
else
tickets = Ticket.where(:subject => regex, :status.in => statuses, :category_id => category.id)
end
when "ticket:"
if category.nil?
tickets = Ticket.where(:uid => keywords)
else
tickets = Ticket.where(:uid => keywords, :category_id => category.id)
end
when "status:"
if category.nil?
tickets = Ticket.where(:status => keywords).limit(25)
else
tickets = Ticket.where(:status => keywords, :category_id => category.id)
end
when "type:"
category = Category.where(:"title.en" => regex).first rescue nil
if category.nil?
category = Category.where(:"title.zh_tw" => regex).first rescue nil
end
tickets = Ticket.where(:category_id => category.id, :status.in => statuses).limit(25) if !category.nil?
when "time:"
if keywords.include?("..")
times = keywords.split("..")
start_time = times.first
end_time = times.last
start_time = start_time + ".01" if start_time.length <= 7
end_time = end_time + ".#{Time.days_in_month(end_time.split(".").last.to_i, end_time.split(".").first.to_i)}" if end_time.length <= 7
start_date = DateTime.parse(start_time) - 1 rescue nil
end_date = DateTime.parse(end_time) + 1 rescue nil
else
if keywords.length <= 7
start_time = keywords + ".01"
end_time = keywords + ".#{Time.days_in_month(keywords.split(".").last.to_i, keywords.split(".").first.to_i)}"
start_date = DateTime.parse(start_time) - 1 rescue nil
end_date = DateTime.parse(end_time) + 1 rescue nil
else
start_time = keywords
start_date = DateTime.parse(start_time) rescue nil
end_date = DateTime.parse(start_time) + 1 rescue nil
end
end
return tickets if start_date.nil? || end_date.nil?
if category.nil?
tickets = Ticket.where(:created_at => (start_date..end_date), :status.in => statuses).limit(25)
else
tickets = Ticket.where(:created_at => (start_date..end_date), :status.in => statuses, :category_id => category.id)
end
when "takenby:"
profiles = MemberProfile.any_of({:"first_name.en" => regex},{:"first_name.zh_tw" => regex},{:"last_name.en" => regex},{:"last_name.zh_tw" => regex})
profiles.each do |profile|
user_id = profile.user.id
if category.nil?
tickets = (tickets | Ticket.where(:taken_by => user_id, :status.in => statuses))
else
tickets = (tickets | Ticket.where(:taken_by => user_id, :category_id => category.id, :status.in => statuses))
end
end
when "query:"
queries = TicketQuery.where(:query => regex).limit(25)
queries.each do |query|
if category.nil?
tickets << query.ticket if statuses.include?(query.ticket.status) && !tickets.include?(query.ticket)
else
tickets << query.ticket if statuses.include?(query.ticket.status) && query.ticket.category_id == category.id && !tickets.include?(query.ticket)
end
end
if params[:sort].present?
s = Sanitize.clean(params[:sort]).to_sym
if params[:order] == "desc"
tickets = tickets.sort{|a,b| b[s] <=> a[s]}
elsif params[:order] == "asc"
tickets = tickets.sort{|a,b| a[s] <=> b[s]}
end
end
end
tickets
end
end