Reworked iCal functionality and integration tests.
This commit is contained in:
parent
a98c02d582
commit
aba5be2fb8
6 changed files with 280 additions and 179 deletions
57
app/controllers/i_cal_controller.rb
Normal file
57
app/controllers/i_cal_controller.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
# Copyright (C) 2012-2015 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
require 'icalendar'
|
||||
|
||||
class ICalController < ApplicationController
|
||||
before_action { authentication_check( { basic_auth_promt: true, token_action: 'iCal' } ) }
|
||||
|
||||
# @path [GET] /ical
|
||||
#
|
||||
# @summary Returns an iCal file with all objects matching the iCal preferences of the current user as events.
|
||||
#
|
||||
# @response_message 200 [String] iCal file ready to import in calendar applications.
|
||||
# @response_message 401 Permission denied.
|
||||
def all
|
||||
ical_object = ICal.new( current_user )
|
||||
ical = ical_object.all
|
||||
|
||||
send_data(
|
||||
ical,
|
||||
filename: 'zammad.ical',
|
||||
type: 'text/plain',
|
||||
disposition: 'inline'
|
||||
)
|
||||
rescue => e
|
||||
logger.error e.message
|
||||
logger.error e.backtrace.inspect
|
||||
render json: { error: e.message }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
# @path [GET] /ical/:object
|
||||
# @path [GET] /ical/:object/:method
|
||||
#
|
||||
# @summary Returns an iCal file of the given object (and method) matching the iCal preferences of the current user as events.
|
||||
#
|
||||
# @response_message 200 [String] iCal file ready to import in calendar applications.
|
||||
# @response_message 401 Permission denied.
|
||||
def object
|
||||
ical_object = ICal.new( current_user )
|
||||
|
||||
# remove the last char (s/plural) from the object name
|
||||
object_name = params[:object].to_s[0...-1].to_sym
|
||||
|
||||
ical = ical_object.generic( object_name, params[:method] )
|
||||
|
||||
send_data(
|
||||
ical,
|
||||
filename: 'zammad.ical',
|
||||
type: 'text/plain',
|
||||
disposition: 'inline'
|
||||
)
|
||||
rescue => e
|
||||
logger.error e.message
|
||||
logger.error e.backtrace.inspect
|
||||
render json: { error: e.message }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
end
|
7
config/routes/i_cal.rb
Normal file
7
config/routes/i_cal.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
Zammad::Application.routes.draw do
|
||||
api_path = Rails.configuration.api_path
|
||||
|
||||
match api_path + '/ical', to: 'i_cal#all', via: :get
|
||||
match api_path + '/ical/:object', to: 'i_cal#object', via: :get
|
||||
match api_path + '/ical/:object/:method', to: 'i_cal#object', via: :get
|
||||
end
|
48
lib/i_cal.rb
48
lib/i_cal.rb
|
@ -1,24 +1,48 @@
|
|||
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
module ICal
|
||||
class ICal
|
||||
|
||||
def self.preferenced(user)
|
||||
def initialize(user)
|
||||
@user = user
|
||||
@preferences = {}
|
||||
|
||||
|
||||
if @user.preferences[:ical] && !@user.preferences[:ical].empty?
|
||||
@preferences = @user.preferences[:ical]
|
||||
end
|
||||
end
|
||||
|
||||
def all
|
||||
events_data = []
|
||||
|
||||
user.preferences[:ical].each { |sub_class, _sub_structure|
|
||||
|
||||
sub_class_name = sub_class.to_s.capitalize
|
||||
class_name = "ICal::#{sub_class_name}"
|
||||
|
||||
object = Kernel.const_get( class_name )
|
||||
events_data += object.preferenced( user )
|
||||
@preferences.each { |object_name, _sub_structure|
|
||||
result = generic_call( object_name )
|
||||
events_data = events_data + result
|
||||
}
|
||||
|
||||
to_ical( events_data )
|
||||
end
|
||||
|
||||
def self.to_ical(events_data)
|
||||
def generic(object_name, method_name = 'all')
|
||||
|
||||
events_data = generic_call( object_name, method_name )
|
||||
to_ical( events_data )
|
||||
end
|
||||
|
||||
def generic_call(object_name, method_name = 'all')
|
||||
|
||||
method_name ||= 'all'
|
||||
|
||||
events_data = []
|
||||
if @preferences[ object_name ] && !@preferences[ object_name ].empty?
|
||||
sub_class_name = object_name.to_s.capitalize
|
||||
object = Object.const_get('ICal').const_get("ICal#{sub_class_name}")
|
||||
instance = object.new( @user, @preferences[ object_name ] )
|
||||
method = instance.method( method_name )
|
||||
events_data += method.call
|
||||
end
|
||||
events_data
|
||||
end
|
||||
|
||||
def to_ical(events_data)
|
||||
|
||||
cal = Icalendar::Calendar.new
|
||||
|
||||
|
|
168
lib/i_cal/i_cal_ticket.rb
Normal file
168
lib/i_cal/i_cal_ticket.rb
Normal file
|
@ -0,0 +1,168 @@
|
|||
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class ICal
|
||||
|
||||
class ICalTicket
|
||||
|
||||
def initialize(user, preferences)
|
||||
@user = user
|
||||
@preferences = preferences
|
||||
end
|
||||
|
||||
def all
|
||||
|
||||
events_data = []
|
||||
return events_data if @preferences.empty?
|
||||
|
||||
events_data += new_open
|
||||
events_data += pending
|
||||
events_data += escalation
|
||||
|
||||
events_data
|
||||
end
|
||||
|
||||
def owner_ids(method)
|
||||
|
||||
owner_ids = []
|
||||
|
||||
return owner_ids if @preferences.empty?
|
||||
return owner_ids if !@preferences[ method ]
|
||||
return owner_ids if @preferences[ method ].empty?
|
||||
|
||||
preferences = @preferences[ method ]
|
||||
|
||||
if preferences[:own]
|
||||
owner_ids = [ @user.id ]
|
||||
end
|
||||
if preferences[:not_assigned]
|
||||
owner_ids.push( 1 )
|
||||
end
|
||||
|
||||
owner_ids
|
||||
end
|
||||
|
||||
def new_open
|
||||
|
||||
events_data = []
|
||||
owner_ids = owner_ids(:new_open)
|
||||
return events_data if owner_ids.empty?
|
||||
|
||||
condition = {
|
||||
'tickets.owner_id' => owner_ids,
|
||||
'tickets.state_id' => Ticket::State.where(
|
||||
state_type_id: Ticket::StateType.where(
|
||||
name: %w(new open),
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
tickets = Ticket.search(
|
||||
current_user: @user,
|
||||
condition: condition,
|
||||
)
|
||||
|
||||
events_data = []
|
||||
tickets.each do |ticket|
|
||||
|
||||
event_data = {}
|
||||
|
||||
event_data[:dtstart] = Icalendar::Values::Date.new( Time.zone.today )
|
||||
event_data[:dtend] = Icalendar::Values::Date.new( Time.zone.today )
|
||||
event_data[:summary] = "#{ticket.state.name} ticket: '#{ticket.title}'"
|
||||
event_data[:description] = "T##{ticket.number}"
|
||||
|
||||
events_data.push event_data
|
||||
end
|
||||
|
||||
events_data
|
||||
end
|
||||
|
||||
def pending
|
||||
|
||||
events_data = []
|
||||
owner_ids = owner_ids(:pending)
|
||||
return events_data if owner_ids.empty?
|
||||
|
||||
condition = {
|
||||
'tickets.owner_id' => owner_ids,
|
||||
'tickets.state_id' => Ticket::State.where(
|
||||
state_type_id: Ticket::StateType.where(
|
||||
name: [
|
||||
'pending reminder',
|
||||
'pending action',
|
||||
],
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
tickets = Ticket.search(
|
||||
current_user: @user,
|
||||
condition: condition,
|
||||
)
|
||||
|
||||
events_data = []
|
||||
tickets.each do |ticket|
|
||||
|
||||
next if !ticket.pending_time
|
||||
|
||||
event_data = {}
|
||||
|
||||
pending_time = ticket.pending_time
|
||||
if pending_time < Time.zone.today
|
||||
pending_time = Time.zone.today
|
||||
end
|
||||
|
||||
# rubocop:disable Rails/TimeZone
|
||||
event_data[:dtstart] = Icalendar::Values::DateTime.new( pending_time )
|
||||
event_data[:dtend] = Icalendar::Values::DateTime.new( pending_time )
|
||||
# rubocop:enable Rails/TimeZone
|
||||
event_data[:summary] = "#{ticket.state.name} ticket: '#{ticket.title}'"
|
||||
event_data[:description] = "T##{ticket.number}"
|
||||
|
||||
events_data.push event_data
|
||||
end
|
||||
|
||||
events_data
|
||||
end
|
||||
|
||||
def escalation
|
||||
|
||||
events_data = []
|
||||
owner_ids = owner_ids(:escalation)
|
||||
return events_data if owner_ids.empty?
|
||||
|
||||
condition = [
|
||||
'tickets.owner_id IN (?) AND tickets.escalation_time IS NOT NULL', owner_ids
|
||||
]
|
||||
|
||||
tickets = Ticket.search(
|
||||
current_user: @user,
|
||||
condition: condition,
|
||||
)
|
||||
|
||||
tickets.each do |ticket|
|
||||
|
||||
next if !ticket.escalation_time
|
||||
|
||||
event_data = {}
|
||||
|
||||
escalation_time = ticket.escalation_time
|
||||
if escalation_time < Time.zone.today
|
||||
escalation_time = Time.zone.today
|
||||
end
|
||||
|
||||
# rubocop:disable Rails/TimeZone
|
||||
event_data[:dtstart] = Icalendar::Values::DateTime.new( escalation_time )
|
||||
event_data[:dtend] = Icalendar::Values::DateTime.new( escalation_time )
|
||||
# rubocop:enable Rails/TimeZone
|
||||
event_data[:summary] = "ticket escalation: '#{ticket.title}'"
|
||||
event_data[:description] = "T##{ticket.number}"
|
||||
|
||||
events_data.push event_data
|
||||
end
|
||||
|
||||
events_data
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -1,161 +0,0 @@
|
|||
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
module ICal::Ticket
|
||||
|
||||
def self.preferenced(user)
|
||||
|
||||
events_data = []
|
||||
return events_data if !user.preferences[:ical]
|
||||
return events_data if !user.preferences[:ical][:ticket]
|
||||
|
||||
preferences = user.preferences[:ical][:ticket]
|
||||
|
||||
[:new_open, :pending, :escalation].each { |state_type|
|
||||
|
||||
next if !preferences[ state_type ]
|
||||
|
||||
owner_ids = []
|
||||
if preferences[ state_type ][:own]
|
||||
owner_ids = [ user.id ]
|
||||
end
|
||||
if preferences[ state_type ][:not_assigned]
|
||||
owner_ids.push( 1 )
|
||||
end
|
||||
|
||||
next if owner_ids.empty?
|
||||
|
||||
if state_type == :new_open
|
||||
events_data += new_open(user, owner_ids)
|
||||
elsif state_type == :pending
|
||||
events_data += pending(user, owner_ids)
|
||||
elsif state_type == :escalation
|
||||
events_data += escalation(user, owner_ids)
|
||||
end
|
||||
}
|
||||
|
||||
events_data
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.new_open(user, owner_ids)
|
||||
|
||||
events_data = []
|
||||
return events_data if owner_ids.empty?
|
||||
|
||||
condition = {
|
||||
'tickets.owner_id' => owner_ids,
|
||||
'tickets.state_id' => Ticket::State.where(
|
||||
state_type_id: Ticket::StateType.where(
|
||||
name: %w(new open),
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
tickets = Ticket.search(
|
||||
current_user: user,
|
||||
condition: condition,
|
||||
)
|
||||
|
||||
events_data = []
|
||||
tickets.each do |ticket|
|
||||
|
||||
event_data = {}
|
||||
|
||||
event_data[:dtstart] = Icalendar::Values::Date.new( Time.zone.today )
|
||||
event_data[:dtend] = Icalendar::Values::Date.new( Time.zone.today )
|
||||
event_data[:summary] = "#{ticket.state.name} ticket: '#{ticket.title}'"
|
||||
event_data[:description] = "T##{ticket.number}"
|
||||
|
||||
events_data.push event_data
|
||||
end
|
||||
|
||||
events_data
|
||||
end
|
||||
|
||||
def self.pending(user, owner_ids)
|
||||
|
||||
events_data = []
|
||||
return events_data if owner_ids.empty?
|
||||
|
||||
condition = {
|
||||
'tickets.owner_id' => owner_ids,
|
||||
'tickets.state_id' => Ticket::State.where(
|
||||
state_type_id: Ticket::StateType.where(
|
||||
name: [
|
||||
'pending reminder',
|
||||
'pending action',
|
||||
],
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
tickets = Ticket.search(
|
||||
current_user: user,
|
||||
condition: condition,
|
||||
)
|
||||
|
||||
events_data = []
|
||||
tickets.each do |ticket|
|
||||
|
||||
next if !ticket.pending_time
|
||||
|
||||
event_data = {}
|
||||
|
||||
pending_time = ticket.pending_time
|
||||
if pending_time < Time.zone.today
|
||||
pending_time = Time.zone.today
|
||||
end
|
||||
|
||||
# rubocop:disable Rails/TimeZone
|
||||
event_data[:dtstart] = Icalendar::Values::DateTime.new( pending_time )
|
||||
event_data[:dtend] = Icalendar::Values::DateTime.new( pending_time )
|
||||
# rubocop:enable Rails/TimeZone
|
||||
event_data[:summary] = "#{ticket.state.name} ticket: '#{ticket.title}'"
|
||||
event_data[:description] = "T##{ticket.number}"
|
||||
|
||||
events_data.push event_data
|
||||
end
|
||||
|
||||
events_data
|
||||
end
|
||||
|
||||
def self.escalation(user, owner_ids)
|
||||
|
||||
events_data = []
|
||||
return events_data if owner_ids.empty?
|
||||
|
||||
condition = [
|
||||
'tickets.owner_id IN (?) AND tickets.escalation_time IS NOT NULL', owner_ids
|
||||
]
|
||||
|
||||
tickets = Ticket.search(
|
||||
current_user: user,
|
||||
condition: condition,
|
||||
)
|
||||
|
||||
tickets.each do |ticket|
|
||||
|
||||
next if !ticket.escalation_time
|
||||
|
||||
event_data = {}
|
||||
|
||||
escalation_time = ticket.escalation_time
|
||||
if escalation_time < Time.zone.today
|
||||
escalation_time = Time.zone.today
|
||||
end
|
||||
|
||||
# rubocop:disable Rails/TimeZone
|
||||
event_data[:dtstart] = Icalendar::Values::DateTime.new( escalation_time )
|
||||
event_data[:dtend] = Icalendar::Values::DateTime.new( escalation_time )
|
||||
# rubocop:enable Rails/TimeZone
|
||||
event_data[:summary] = "ticket escalation: '#{ticket.title}'"
|
||||
event_data[:description] = "T##{ticket.number}"
|
||||
|
||||
events_data.push event_data
|
||||
end
|
||||
|
||||
events_data
|
||||
end
|
||||
|
||||
end
|
|
@ -244,11 +244,13 @@ class ICalTicketTest < ActiveSupport::TestCase
|
|||
user.preferences[:ical] = {}
|
||||
user.preferences[:ical][:ticket] = test_data[:preferences]
|
||||
|
||||
event_data = ICal::Ticket.new_open( user, test_data[:owner_ids] )
|
||||
ical_ticket = ICal::ICalTicket.new( user, test_data[:preferences] )
|
||||
event_data = ical_ticket.new_open
|
||||
|
||||
assert_equal( test_data[:count], event_data.length, "#{test_data[:name]} event count" )
|
||||
|
||||
ical = ICal.preferenced( user )
|
||||
ical_object = ICal.new( user )
|
||||
ical = ical_object.all
|
||||
|
||||
event_data.each { |event|
|
||||
|
||||
|
@ -316,11 +318,13 @@ class ICalTicketTest < ActiveSupport::TestCase
|
|||
user.preferences[:ical] = {}
|
||||
user.preferences[:ical][:ticket] = test_data[:preferences]
|
||||
|
||||
event_data = ICal::Ticket.pending( user, test_data[:owner_ids] )
|
||||
ical_ticket = ICal::ICalTicket.new( user, test_data[:preferences] )
|
||||
event_data = ical_ticket.pending
|
||||
|
||||
assert_equal( test_data[:count], event_data.length, "#{test_data[:name]} event count" )
|
||||
|
||||
ical = ICal.preferenced( user )
|
||||
ical_object = ICal.new( user )
|
||||
ical = ical_object.all
|
||||
|
||||
event_data.each { |event|
|
||||
|
||||
|
@ -388,11 +392,13 @@ class ICalTicketTest < ActiveSupport::TestCase
|
|||
user.preferences[:ical] = {}
|
||||
user.preferences[:ical][:ticket] = test_data[:preferences]
|
||||
|
||||
event_data = ICal::Ticket.escalation( user, test_data[:owner_ids] )
|
||||
ical_ticket = ICal::ICalTicket.new( user, test_data[:preferences] )
|
||||
event_data = ical_ticket.escalation
|
||||
|
||||
assert_equal( test_data[:count], event_data.length, "#{test_data[:name]} event count" )
|
||||
|
||||
ical = ICal.preferenced( user )
|
||||
ical_object = ICal.new( user )
|
||||
ical = ical_object.all
|
||||
|
||||
event_data.each { |event|
|
||||
|
||||
|
|
Loading…
Reference in a new issue