Added ticket job feature.
This commit is contained in:
parent
cf2b451d8c
commit
1950f82322
23 changed files with 841 additions and 221 deletions
|
@ -17,13 +17,13 @@ class App.UiElement.active extends App.UiElement.ApplicationUiElement
|
|||
attribute.name = '{boolean}' + attribute.name
|
||||
|
||||
# build options list based on config
|
||||
@getConfigOptionList( attribute, params )
|
||||
@getConfigOptionList(attribute, params)
|
||||
|
||||
# sort attribute.options
|
||||
@sortOptions( attribute, params )
|
||||
@sortOptions(attribute, params)
|
||||
|
||||
# finde selected/checked item of list
|
||||
@selectedOptions( attribute, params )
|
||||
@selectedOptions(attribute, params)
|
||||
|
||||
# return item
|
||||
$( App.view('generic/select')( attribute: attribute ) )
|
|
@ -14,13 +14,13 @@ class App.UiElement.boolean extends App.UiElement.ApplicationUiElement
|
|||
attribute.name = '{boolean}' + attribute.name
|
||||
|
||||
# build options list based on config
|
||||
@getConfigOptionList( attribute, params )
|
||||
@getConfigOptionList(attribute, params)
|
||||
|
||||
# sort attribute.options
|
||||
@sortOptions( attribute, params )
|
||||
@sortOptions(attribute, params)
|
||||
|
||||
# finde selected/checked item of list
|
||||
@selectedOptions( attribute, params )
|
||||
@selectedOptions(attribute, params)
|
||||
|
||||
# return item
|
||||
$( App.view('generic/select')( attribute: attribute ) )
|
||||
$(App.view('generic/select')(attribute: attribute))
|
|
@ -3,24 +3,24 @@ class App.UiElement.radio extends App.UiElement.ApplicationUiElement
|
|||
@render: (attribute, params) ->
|
||||
|
||||
# build options list based on config
|
||||
@getConfigOptionList( attribute, params )
|
||||
@getConfigOptionList(attribute, params)
|
||||
|
||||
# build options list based on relation
|
||||
@getRelationOptionList( attribute, params )
|
||||
@getRelationOptionList(attribute, params)
|
||||
|
||||
# add null selection if needed
|
||||
@addNullOption( attribute, params )
|
||||
@addNullOption(attribute, params)
|
||||
|
||||
# sort attribute.options
|
||||
@sortOptions( attribute, params )
|
||||
@sortOptions(attribute, params)
|
||||
|
||||
# finde selected/checked item of list
|
||||
@selectedOptions( attribute, params )
|
||||
@selectedOptions(attribute, params)
|
||||
|
||||
# disable item of list
|
||||
@disabledOptions( attribute, params )
|
||||
@disabledOptions(attribute, params)
|
||||
|
||||
# filter attributes
|
||||
@filterOption( attribute, params )
|
||||
@filterOption(attribute, params)
|
||||
|
||||
$( App.view('generic/radio')( attribute: attribute ) )
|
||||
|
|
|
@ -9,25 +9,25 @@ class App.UiElement.select extends App.UiElement.ApplicationUiElement
|
|||
attribute.multiple = ''
|
||||
|
||||
# build options list based on config
|
||||
@getConfigOptionList( attribute, params )
|
||||
@getConfigOptionList(attribute, params)
|
||||
|
||||
# build options list based on relation
|
||||
@getRelationOptionList( attribute, params )
|
||||
@getRelationOptionList(attribute, params)
|
||||
|
||||
# add null selection if needed
|
||||
@addNullOption( attribute, params )
|
||||
@addNullOption(attribute, params)
|
||||
|
||||
# sort attribute.options
|
||||
@sortOptions( attribute, params )
|
||||
@sortOptions(attribute, params)
|
||||
|
||||
# finde selected/checked item of list
|
||||
@selectedOptions( attribute, params )
|
||||
@selectedOptions(attribute, params)
|
||||
|
||||
# disable item of list
|
||||
@disabledOptions( attribute, params )
|
||||
@disabledOptions(attribute, params)
|
||||
|
||||
# filter attributes
|
||||
@filterOption( attribute, params )
|
||||
@filterOption(attribute, params)
|
||||
|
||||
# return item
|
||||
$( App.view('generic/select')( attribute: attribute ) )
|
|
@ -5,5 +5,5 @@ class App.UiElement.tag
|
|||
a = ->
|
||||
$('#' + attribute.id ).tokenfield()
|
||||
$('#' + attribute.id ).parent().css('height', 'auto')
|
||||
App.Delay.set( a, 120, undefined, 'tags' )
|
||||
App.Delay.set(a, 120, undefined, 'tags')
|
||||
item
|
|
@ -13,7 +13,7 @@ class App.UiElement.textarea
|
|||
if visible && !$( item[0] ).expanding('active')
|
||||
$( item[0] ).expanding().focus()
|
||||
)
|
||||
App.Delay.set( a, 80 )
|
||||
App.Delay.set(a, 80)
|
||||
|
||||
if attribute.upload
|
||||
|
||||
|
@ -39,5 +39,5 @@ class App.UiElement.textarea
|
|||
fail: ''
|
||||
debug: false
|
||||
)
|
||||
App.Delay.set( u, 100, undefined, 'form_upload' )
|
||||
App.Delay.set(u, 100, undefined, 'form_upload')
|
||||
item
|
|
@ -15,13 +15,13 @@ class App.UiElement.timezone extends App.UiElement.ApplicationUiElement
|
|||
attribute.options.push item
|
||||
|
||||
# add null selection if needed
|
||||
@addNullOption( attribute, params )
|
||||
@addNullOption(attribute, params)
|
||||
|
||||
# sort attribute.options
|
||||
@sortOptions( attribute, params )
|
||||
@sortOptions(attribute, params)
|
||||
|
||||
# finde selected/checked item of list
|
||||
@selectedOptions( attribute, params )
|
||||
@selectedOptions(attribute, params)
|
||||
|
||||
attribute.tag = 'searchable_select'
|
||||
attribute.placeholder = App.i18n.translateInline('Enter timzone...')
|
||||
|
|
29
app/assets/javascripts/app/controllers/job.coffee
Normal file
29
app/assets/javascripts/app/controllers/job.coffee
Normal file
|
@ -0,0 +1,29 @@
|
|||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
# check authentication
|
||||
return if !@authenticate(false, 'Admin')
|
||||
|
||||
new App.ControllerGenericIndex(
|
||||
el: @el
|
||||
id: @id
|
||||
genericObject: 'Job'
|
||||
defaultSortBy: 'name'
|
||||
pageData:
|
||||
title: 'Scheduler'
|
||||
home: 'Jobs'
|
||||
object: 'Scheduler'
|
||||
objects: 'Schedulers'
|
||||
navupdate: '#Jobs'
|
||||
notes: [
|
||||
'Scheduler are ...'
|
||||
]
|
||||
buttons: [
|
||||
{ name: 'New Scheduler', 'data-type': 'new', class: 'btn--success' }
|
||||
]
|
||||
container: @el.closest('.content')
|
||||
#large: true
|
||||
)
|
||||
|
||||
App.Config.set('Job', { prio: 3400, name: 'Scheduler', parent: '#manage', target: '#manage/job', controller: Index, role: ['Admin'] }, 'NavBarAdmin')
|
|
@ -1,88 +1,30 @@
|
|||
class Index extends App.ControllerTabs
|
||||
header: 'Trigger'
|
||||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
@title 'Trigger', true
|
||||
# check authentication
|
||||
return if !@authenticate(false, 'Admin')
|
||||
|
||||
@tabs = [
|
||||
{
|
||||
name: 'Time Based',
|
||||
target: 'c-time-based',
|
||||
controller: App.TriggerTime,
|
||||
},
|
||||
{
|
||||
name: 'Event Based',
|
||||
target: 'c-event-based',
|
||||
controller: App.SettingsArea,
|
||||
params: { area: 'Email::Base' },
|
||||
},
|
||||
{
|
||||
name: 'Notifications',
|
||||
target: 'c-notification',
|
||||
controller: App.SettingsArea,
|
||||
params: { area: 'Email::Base' },
|
||||
},
|
||||
{
|
||||
name: 'Web Hooks',
|
||||
target: 'c-web-hook',
|
||||
controller: App.SettingsArea,
|
||||
params: { area: 'Email::Base' },
|
||||
},
|
||||
]
|
||||
|
||||
@render()
|
||||
|
||||
App.Config.set( 'Trigger', { prio: 3000, name: 'Trigger', parent: '#manage', target: '#manage/triggers', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )
|
||||
|
||||
class App.TriggerTime extends App.Controller
|
||||
events:
|
||||
'click .js-new': 'new'
|
||||
#'click .js-edit': 'edit'
|
||||
'click .js-delete': 'delete'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@interval(@load, 30000)
|
||||
#@load()
|
||||
|
||||
load: =>
|
||||
@startLoading()
|
||||
@ajax(
|
||||
id: 'trigger_time_index'
|
||||
type: 'GET'
|
||||
url: @apiPath + '/jobs'
|
||||
processData: true
|
||||
success: (data, status, xhr) =>
|
||||
#App.Collection.loadAssets(data.assets)
|
||||
@stopLoading()
|
||||
@render(data)
|
||||
)
|
||||
|
||||
render: (data = {}) =>
|
||||
|
||||
@html App.view('trigger/time/index')(
|
||||
triggers: []
|
||||
)
|
||||
|
||||
|
||||
delete: (e) =>
|
||||
e.preventDefault()
|
||||
id = $(e.target).closest('.action').data('id')
|
||||
item = App.Channel.find(id)
|
||||
new App.ControllerGenericDestroyConfirm(
|
||||
item: item
|
||||
container: @el.closest('.content')
|
||||
callback: @load
|
||||
)
|
||||
|
||||
new: (e) =>
|
||||
e.preventDefault()
|
||||
channel_id = $(e.target).closest('.action').data('id')
|
||||
new App.ControllerGenericNew(
|
||||
new App.ControllerGenericIndex(
|
||||
el: @el
|
||||
id: @id
|
||||
genericObject: 'Trigger'
|
||||
defaultSortBy: 'name'
|
||||
#groupBy: 'role'
|
||||
pageData:
|
||||
object: 'Jobs'
|
||||
genericObject: 'Job'
|
||||
title: 'Triggers'
|
||||
home: 'triggers'
|
||||
object: 'Trigger'
|
||||
objects: 'Triggers'
|
||||
navupdate: '#triggers'
|
||||
notes: [
|
||||
'Triggers are ...'
|
||||
]
|
||||
buttons: [
|
||||
{ name: 'New Trigger', 'data-type': 'new', class: 'btn--success' }
|
||||
]
|
||||
container: @el.closest('.content')
|
||||
callback: @load
|
||||
#large: true
|
||||
)
|
||||
|
||||
App.Config.set('Trigger', { prio: 3300, name: 'Trigger', parent: '#manage', target: '#manage/trigger', controller: Index, role: ['Admin'] }, 'NavBarAdmin')
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
class App.Job extends App.Model
|
||||
@configure 'Job', 'name', 'timeplan', 'condition', 'execute', 'note', 'active'
|
||||
@configure 'Job', 'name', 'timeplan', 'condition', 'perform', 'disable_notiifcation', 'note', 'active'
|
||||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/jobs'
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
# { name: 'timeplan', display: 'The times where the job should run.', tag: 'timeplan', null: true },
|
||||
{ name: 'condition', display: 'Conditions for matching objects.', tag: 'ticket_selector', null: true },
|
||||
{ name: 'execute', display: 'Execute changes on objects.', tag: 'ticket_perform_action', null: true },
|
||||
{ name: 'timeplan', display: 'When should the job run?', tag: 'timer', null: true },
|
||||
{ name: 'condition', display: 'Conditions for effected objects', tag: 'ticket_selector', null: true },
|
||||
{ name: 'perform', display: 'Execute changes on objects', tag: 'ticket_perform_action', null: true },
|
||||
{ name: 'disable_notiifcation', display: 'Disable Notifications', tag: 'boolean', default: true },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true },
|
||||
{ name: 'active', display: 'Active', tag: 'active', default: true },
|
||||
{ name: 'matching', display: 'Matching', readonly: 1 },
|
||||
|
|
21
app/assets/javascripts/app/models/trigger.coffee
Normal file
21
app/assets/javascripts/app/models/trigger.coffee
Normal file
|
@ -0,0 +1,21 @@
|
|||
class App.Trigger extends App.Model
|
||||
@configure 'Trigger', 'name', 'condition', 'perform', 'active'
|
||||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/triggers'
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
{ name: 'condition', display: 'Conditions for effected objects', tag: 'ticket_selector', null: false },
|
||||
{ name: 'perform', display: 'Execute changes on objects', tag: 'ticket_perform_action', null: true },
|
||||
{ name: 'disable_notiifcation', display: 'Disable Notifications', tag: 'boolean', default: true },
|
||||
{ name: 'active', display: 'Active', tag: 'active', default: true },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
]
|
||||
@configure_delete = true
|
||||
@configure_overview = [
|
||||
'name',
|
||||
]
|
||||
|
||||
@description = '''
|
||||
Trigger are....
|
||||
|
||||
'''
|
30
app/controllers/triggers_controller.rb
Normal file
30
app/controllers/triggers_controller.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class TriggersController < ApplicationController
|
||||
before_action :authentication_check
|
||||
|
||||
def index
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
model_index_render(Trigger, params)
|
||||
end
|
||||
|
||||
def show
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
model_show_render(Trigger, params)
|
||||
end
|
||||
|
||||
def create
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
model_create_render(Trigger, params)
|
||||
end
|
||||
|
||||
def update
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
model_update_render(Trigger, params)
|
||||
end
|
||||
|
||||
def destroy
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
model_destory_render(Trigger, params)
|
||||
end
|
||||
end
|
|
@ -3,85 +3,118 @@
|
|||
class Job < ApplicationModel
|
||||
store :timeplan
|
||||
store :condition
|
||||
store :execute
|
||||
store :perform
|
||||
validates :name, presence: true
|
||||
|
||||
before_create :updated_matching
|
||||
before_update :updated_matching
|
||||
before_create :updated_matching
|
||||
before_update :updated_matching
|
||||
|
||||
notify_clients_support
|
||||
|
||||
def self.run
|
||||
time = Time.zone.now
|
||||
day_map = {
|
||||
0 => 'sun',
|
||||
1 => 'mon',
|
||||
2 => 'tue',
|
||||
3 => 'wed',
|
||||
4 => 'thu',
|
||||
5 => 'fri',
|
||||
6 => 'sat',
|
||||
}
|
||||
jobs = Job.where( active: true )
|
||||
jobs = Job.where(active: true, running: false)
|
||||
jobs.each do |job|
|
||||
logger.debug "Execute job #{job.inspect}"
|
||||
|
||||
# only execute jobs, older then 1 min, to give admin posibility to change
|
||||
next if job.updated_at > Time.zone.now - 1.minute
|
||||
next if !job.executable?
|
||||
|
||||
# check if jobs need to be executed
|
||||
# ignore if job was running within last 10 min.
|
||||
next if job.last_run_at && job.last_run_at > Time.zone.now - 10.minutes
|
||||
|
||||
# check day
|
||||
next if !job.timeplan['days'].include?( day_map[time.wday] )
|
||||
|
||||
# check hour
|
||||
next if !job.timeplan['hours'].include?( time.hour.to_s )
|
||||
|
||||
# check min
|
||||
next if !job.timeplan['minutes'].include?( match_minutes(time.min.to_s) )
|
||||
|
||||
# find tickets to change
|
||||
tickets = Ticket.where( job.condition.permit! )
|
||||
.order( '`tickets`.`created_at` DESC' )
|
||||
.limit( 1_000 )
|
||||
job.processed = tickets.count
|
||||
tickets.each do |ticket|
|
||||
logger.debug "CHANGE #{job.execute.inspect}"
|
||||
changed = false
|
||||
job.execute.each do |key, value|
|
||||
changed = true
|
||||
attribute = key.split('.', 2).last
|
||||
logger.debug "-- #{Ticket.columns_hash[ attribute ].type}"
|
||||
#value = 4
|
||||
#if Ticket.columns_hash[ attribute ].type == :integer
|
||||
# logger.debug "to i #{attribute}/#{value.inspect}/#{value.to_i.inspect}"
|
||||
# #value = value.to_i
|
||||
#end
|
||||
ticket[attribute] = value
|
||||
logger.debug "set #{attribute} = #{value.inspect}"
|
||||
end
|
||||
next if !changed
|
||||
ticket.updated_by_id = 1
|
||||
ticket.save
|
||||
matching = job.matching_count
|
||||
if job.matching != matching
|
||||
job.matching = matching
|
||||
job.save
|
||||
end
|
||||
|
||||
next if !job.in_timeplan?
|
||||
|
||||
# find tickets to change
|
||||
ticket_count, tickets = Ticket.selectors(job.condition, 2_000)
|
||||
|
||||
logger.debug "Job #{job.name} with #{ticket_count} tickets"
|
||||
|
||||
job.processed = ticket_count || 0
|
||||
job.running = true
|
||||
job.save
|
||||
|
||||
if tickets
|
||||
tickets.each do |ticket|
|
||||
logger.debug "Perform job #{job.perform.inspect} in Ticket.find(#{ticket.id})"
|
||||
changed = false
|
||||
job.perform.each do |key, value|
|
||||
(object_name, attribute) = key.split('.', 2)
|
||||
raise "Unable to update object #{object_name}.#{attribute}, only can update tickets!" if object_name != 'ticket'
|
||||
|
||||
next if ticket[attribute].to_s == value['value'].to_s
|
||||
changed = true
|
||||
|
||||
ticket[attribute] = value['value']
|
||||
logger.debug "set #{object_name}.#{attribute} = #{value['value'].inspect}"
|
||||
end
|
||||
next if !changed
|
||||
ticket.updated_by_id = 1
|
||||
ticket.save
|
||||
end
|
||||
end
|
||||
|
||||
job.running = false
|
||||
job.last_run_at = Time.zone.now
|
||||
job.save
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def executable?
|
||||
|
||||
# only execute jobs, older then 1 min, to give admin posibility to change
|
||||
return false if updated_at > Time.zone.now - 1.minute
|
||||
|
||||
# check if jobs need to be executed
|
||||
# ignore if job was running within last 10 min.
|
||||
return false if last_run_at && last_run_at > Time.zone.now - 10.minutes
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def in_timeplan?
|
||||
time = Time.zone.now
|
||||
day_map = {
|
||||
0 => 'Sun',
|
||||
1 => 'Mon',
|
||||
2 => 'Tue',
|
||||
3 => 'Wed',
|
||||
4 => 'Thu',
|
||||
5 => 'Fri',
|
||||
6 => 'Sat',
|
||||
}
|
||||
|
||||
# check day
|
||||
return false if !timeplan['days']
|
||||
return false if !timeplan['days'][day_map[time.wday]]
|
||||
|
||||
# check hour
|
||||
return false if !timeplan['hours']
|
||||
return false if !timeplan['hours'][time.hour.to_s] && !timeplan['hours'][time.hour]
|
||||
|
||||
# check min
|
||||
return false if !timeplan['minutes']
|
||||
return false if !timeplan['minutes'][match_minutes(time.min).to_s] && !timeplan['minutes'][match_minutes(time.min)]
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def matching_count
|
||||
ticket_count, tickets = Ticket.selectors(condition, 1)
|
||||
ticket_count || 0
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def updated_matching
|
||||
count = Ticket.where( condition.permit! ).count
|
||||
self.matching = count
|
||||
self.matching = matching_count
|
||||
end
|
||||
|
||||
def self.match_minutes(minutes)
|
||||
minutes.gsub!(/(\d)\d/, '\\1')
|
||||
minutes.to_s + '0'
|
||||
def match_minutes(minutes)
|
||||
return 0 if minutes < 10
|
||||
"#{minutes.to_s.gsub(/(\d)\d/, '\\1')}0".to_i
|
||||
end
|
||||
private_class_method :match_minutes
|
||||
|
||||
end
|
||||
|
|
|
@ -468,7 +468,7 @@ condition example
|
|||
raise "Invalid selector, operator missing #{selector.inspect}" if !selector['operator']
|
||||
|
||||
# validate value / allow empty but only if pre_condition exists
|
||||
if (selector['value'].class == String || selector['value'].class == Array) && (selector['value'].respond_to?(:empty?) && selector['value'].empty?)
|
||||
if !selector.key?('value') || ((selector['value'].class == String || selector['value'].class == Array) && (selector['value'].respond_to?(:empty?) && selector['value'].empty?))
|
||||
return nil if selector['pre_condition'].nil? || (selector['pre_condition'].respond_to?(:empty?) && selector['pre_condition'].empty?)
|
||||
end
|
||||
|
||||
|
@ -679,7 +679,7 @@ result
|
|||
|
||||
return if !customer_id
|
||||
|
||||
customer = User.find( customer_id )
|
||||
customer = User.find(customer_id)
|
||||
return if organization_id == customer.organization_id
|
||||
|
||||
self.organization_id = customer.organization_id
|
||||
|
@ -691,8 +691,8 @@ result
|
|||
return if !changes['state_id']
|
||||
|
||||
# check if new state isn't pending*
|
||||
current_state = Ticket::State.lookup( id: state_id )
|
||||
current_state_type = Ticket::StateType.lookup( id: current_state.state_type_id )
|
||||
current_state = Ticket::State.lookup(id: state_id)
|
||||
current_state_type = Ticket::StateType.lookup(id: current_state.state_type_id)
|
||||
|
||||
# in case, set pending_time to nil
|
||||
return if current_state_type.name =~ /^pending/i
|
||||
|
@ -706,7 +706,7 @@ result
|
|||
articles.destroy_all
|
||||
|
||||
# destroy online notifications
|
||||
OnlineNotification.remove( self.class.to_s, id )
|
||||
OnlineNotification.remove(self.class.to_s, id)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -8,6 +8,7 @@ Zammad::Application.routes.draw do
|
|||
match '/tests_form_find', to: 'tests#form_find', via: :get
|
||||
match '/tests_form_trim', to: 'tests#form_trim', via: :get
|
||||
match '/tests_form_extended', to: 'tests#form_extended', via: :get
|
||||
match '/tests_form_timer', to: 'tests#form_timer', via: :get
|
||||
match '/tests_form_validation', to: 'tests#form_validation', via: :get
|
||||
match '/tests_form_column_select', to: 'tests#form_column_select', via: :get
|
||||
match '/tests_form_searchable_select', to: 'tests#form_searchable_select', via: :get
|
||||
|
|
11
config/routes/trigger.rb
Normal file
11
config/routes/trigger.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
Zammad::Application.routes.draw do
|
||||
api_path = Rails.configuration.api_path
|
||||
|
||||
# triggers
|
||||
match api_path + '/triggers', to: 'triggers#index', via: :get
|
||||
match api_path + '/triggers/:id', to: 'triggers#show', via: :get
|
||||
match api_path + '/triggers', to: 'triggers#create', via: :post
|
||||
match api_path + '/triggers/:id', to: 'triggers#update', via: :put
|
||||
match api_path + '/triggers/:id', to: 'triggers#destroy', via: :delete
|
||||
|
||||
end
|
|
@ -188,7 +188,6 @@ class CreateTicket < ActiveRecord::Migration
|
|||
add_index :ticket_counters, [:generator], unique: true
|
||||
|
||||
create_table :overviews do |t|
|
||||
t.references :user, null: true
|
||||
t.references :role, null: false
|
||||
t.column :name, :string, limit: 250, null: false
|
||||
t.column :link, :string, limit: 250, null: false
|
||||
|
@ -203,9 +202,15 @@ class CreateTicket < ActiveRecord::Migration
|
|||
t.column :created_by_id, :integer, null: false
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :overviews, [:user_id]
|
||||
add_index :overviews, [:name]
|
||||
|
||||
create_table :overviews_users, id: false do |t|
|
||||
t.integer :overview_id
|
||||
t.integer :user_id
|
||||
end
|
||||
add_index :overviews_users, [:overview_id]
|
||||
add_index :overviews_users, [:user_id]
|
||||
|
||||
create_table :overviews_groups, id: false do |t|
|
||||
t.integer :overview_id
|
||||
t.integer :group_id
|
||||
|
@ -214,13 +219,36 @@ class CreateTicket < ActiveRecord::Migration
|
|||
add_index :overviews_groups, [:group_id]
|
||||
|
||||
create_table :triggers do |t|
|
||||
t.column :name, :string, limit: 250, null: false
|
||||
t.column :key, :string, limit: 250, null: false
|
||||
t.column :value, :string, limit: 250, null: false
|
||||
t.column :name, :string, limit: 250, null: false
|
||||
t.column :condition, :string, limit: 2500, null: false
|
||||
t.column :perform, :string, limit: 2500, null: false
|
||||
t.column :disable_notification, :boolean, null: false, default: true
|
||||
t.column :note, :string, limit: 250, null: true
|
||||
t.column :active, :boolean, null: false, default: true
|
||||
t.column :updated_by_id, :integer, null: false
|
||||
t.column :created_by_id, :integer, null: false
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :triggers, [:name]
|
||||
add_index :triggers, [:key]
|
||||
add_index :triggers, [:value]
|
||||
add_index :triggers, [:name], unique: true
|
||||
|
||||
create_table :jobs do |t|
|
||||
t.column :name, :string, limit: 250, null: false
|
||||
t.column :timeplan, :string, limit: 500, null: false
|
||||
t.column :condition, :string, limit: 2500, null: false
|
||||
t.column :perform, :string, limit: 2500, null: false
|
||||
t.column :disable_notification, :boolean, null: false, default: true
|
||||
t.column :last_run_at, :timestamp, null: true
|
||||
t.column :running, :boolean, null: false, default: false
|
||||
t.column :processed, :integer, null: false, default: 0
|
||||
t.column :matching, :integer, null: false
|
||||
t.column :pid, :string, limit: 250, null: true
|
||||
t.column :note, :string, limit: 250, null: true
|
||||
t.column :active, :boolean, null: false, default: false
|
||||
t.column :updated_by_id, :integer, null: false
|
||||
t.column :created_by_id, :integer, null: false
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :jobs, [:name], unique: true
|
||||
|
||||
create_table :notifications do |t|
|
||||
t.column :subject, :string, limit: 250, null: false
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
class CreateJob < ActiveRecord::Migration
|
||||
def up
|
||||
create_table :jobs do |t|
|
||||
t.column :name, :string, limit: 250, null: false
|
||||
t.column :timeplan, :string, limit: 500, null: false
|
||||
t.column :condition, :string, limit: 2500, null: false
|
||||
t.column :execute, :string, limit: 2500, null: false
|
||||
t.column :last_run_at, :timestamp, null: true
|
||||
t.column :running, :boolean, null: false, default: false
|
||||
t.column :processed, :integer, null: false, default: 0
|
||||
t.column :matching, :integer, null: false
|
||||
t.column :pid, :string, limit: 250, null: true
|
||||
t.column :note, :string, limit: 250, null: true
|
||||
t.column :active, :boolean, null: false, default: false
|
||||
t.column :updated_by_id, :integer, null: false
|
||||
t.column :created_by_id, :integer, null: false
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :jobs, [:name], unique: true
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :jobs
|
||||
end
|
||||
end
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
class OverviewUserRelation < ActiveRecord::Migration
|
||||
def up
|
||||
create_table :overviews_users, id: false do |t|
|
||||
t.integer :overview_id
|
||||
t.integer :user_id
|
||||
end
|
||||
add_index :overviews_users, [:overview_id]
|
||||
add_index :overviews_users, [:user_id]
|
||||
remove_column :overviews, :user_id
|
||||
end
|
||||
|
||||
end
|
48
db/migrate/20160316000005_renew_triggers.rb
Normal file
48
db/migrate/20160316000005_renew_triggers.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
class RenewTriggers < ActiveRecord::Migration
|
||||
def up
|
||||
drop_table :triggers
|
||||
create_table :triggers do |t|
|
||||
t.column :name, :string, limit: 250, null: false
|
||||
t.column :condition, :string, limit: 2500, null: false
|
||||
t.column :perform, :string, limit: 2500, null: false
|
||||
t.column :disable_notification, :boolean, null: false, default: true
|
||||
t.column :note, :string, limit: 250, null: true
|
||||
t.column :active, :boolean, null: false, default: true
|
||||
t.column :updated_by_id, :integer, null: false
|
||||
t.column :created_by_id, :integer, null: false
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :triggers, [:name], unique: true
|
||||
|
||||
drop_table :jobs
|
||||
create_table :jobs do |t|
|
||||
t.column :name, :string, limit: 250, null: false
|
||||
t.column :timeplan, :string, limit: 1000, null: false
|
||||
t.column :condition, :string, limit: 2500, null: false
|
||||
t.column :perform, :string, limit: 2500, null: false
|
||||
t.column :disable_notification, :boolean, null: false, default: true
|
||||
t.column :last_run_at, :timestamp, null: true
|
||||
t.column :running, :boolean, null: false, default: false
|
||||
t.column :processed, :integer, null: false, default: 0
|
||||
t.column :matching, :integer, null: false, default: 0
|
||||
t.column :pid, :string, limit: 250, null: true
|
||||
t.column :note, :string, limit: 250, null: true
|
||||
t.column :active, :boolean, null: false, default: false
|
||||
t.column :updated_by_id, :integer, null: false
|
||||
t.column :created_by_id, :integer, null: false
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :jobs, [:name], unique: true
|
||||
|
||||
Scheduler.create_if_not_exists(
|
||||
name: 'Execute jobs',
|
||||
method: 'Job.run',
|
||||
period: 5 * 60,
|
||||
prio: 2,
|
||||
active: true,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
end
|
||||
end
|
|
@ -3367,6 +3367,15 @@ Scheduler.create_if_not_exists(
|
|||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
Scheduler.create_if_not_exists(
|
||||
name: 'Execute jobs',
|
||||
method: 'Job.run',
|
||||
period: 5 * 60,
|
||||
prio: 2,
|
||||
active: true,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
Scheduler.create_if_not_exists(
|
||||
name: 'Cleanup expired sessions',
|
||||
method: 'SessionHelper.cleanup_expired',
|
||||
|
|
425
test/unit/job_test.rb
Normal file
425
test/unit/job_test.rb
Normal file
|
@ -0,0 +1,425 @@
|
|||
# encoding: utf-8
|
||||
require 'test_helper'
|
||||
|
||||
class JobTest < ActiveSupport::TestCase
|
||||
test 'case 1' do
|
||||
|
||||
# create ticket
|
||||
group1 = Group.lookup(name: 'Users')
|
||||
group2 = Group.create_or_update(
|
||||
name: 'JobTest2',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
ticket1 = Ticket.create(
|
||||
title: 'job test 1',
|
||||
group: group1,
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'new'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
created_at: Time.zone.now - 3.days,
|
||||
updated_at: Time.zone.now - 3.days,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
ticket2 = Ticket.create(
|
||||
title: 'job test 2',
|
||||
group: group1,
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'new'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
created_at: Time.zone.now - 1.day,
|
||||
created_by_id: 1,
|
||||
updated_at: Time.zone.now - 1.day,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
ticket3 = Ticket.create(
|
||||
title: 'job test 3',
|
||||
group: group2,
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'open'),
|
||||
priority: Ticket::Priority.lookup(name: '3 high'),
|
||||
created_at: Time.zone.now - 1.day,
|
||||
created_by_id: 1,
|
||||
updated_at: Time.zone.now - 1.day,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
ticket4 = Ticket.create(
|
||||
title: 'job test 4',
|
||||
group: group2,
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'closed'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
created_at: Time.zone.now - 3.days,
|
||||
created_by_id: 1,
|
||||
updated_at: Time.zone.now - 3.days,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
ticket5 = Ticket.create(
|
||||
title: 'job test 5',
|
||||
group: group2,
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'open'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
created_at: Time.zone.now - 3.days,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
updated_at: Time.zone.now - 3.days,
|
||||
)
|
||||
|
||||
# create jobs
|
||||
job1 = Job.create_or_update(
|
||||
name: 'Test Job1',
|
||||
timeplan: {
|
||||
days: {
|
||||
Mon: false,
|
||||
Tue: false,
|
||||
Wed: false,
|
||||
Thu: false,
|
||||
Fri: false,
|
||||
Sat: false,
|
||||
Sun: false,
|
||||
},
|
||||
hours: {
|
||||
0 => false,
|
||||
1 => false,
|
||||
2 => false,
|
||||
3 => false,
|
||||
4 => false,
|
||||
5 => false,
|
||||
6 => false,
|
||||
7 => false,
|
||||
8 => false,
|
||||
9 => false,
|
||||
10 => false,
|
||||
11 => false,
|
||||
12 => false,
|
||||
13 => false,
|
||||
14 => false,
|
||||
15 => false,
|
||||
16 => false,
|
||||
17 => false,
|
||||
18 => false,
|
||||
19 => false,
|
||||
20 => false,
|
||||
21 => false,
|
||||
22 => false,
|
||||
23 => false,
|
||||
},
|
||||
minutes: {
|
||||
0 => false,
|
||||
10 => false,
|
||||
20 => false,
|
||||
30 => false,
|
||||
40 => false,
|
||||
50 => false,
|
||||
},
|
||||
},
|
||||
condition: {
|
||||
'ticket.state_id' => { 'operator' => 'is', 'value' => [Ticket::State.lookup(name: 'new').id.to_s, Ticket::State.lookup(name: 'open').id.to_s] },
|
||||
'ticket.created_at' => { 'operator' => 'before (relative)', 'value' => '2', 'range' => 'day' },
|
||||
},
|
||||
perform: {
|
||||
'ticket.state_id' => { 'value' => Ticket::State.lookup(name: 'closed').id.to_s }
|
||||
},
|
||||
disable_notification: true,
|
||||
last_run_at: nil,
|
||||
active: true,
|
||||
created_by_id: 1,
|
||||
created_at: Time.zone.now,
|
||||
updated_by_id: 1,
|
||||
updated_at: Time.zone.now,
|
||||
)
|
||||
assert_not(job1.executable?)
|
||||
|
||||
job1.last_run_at = Time.zone.now - 15.minutes
|
||||
job1.save
|
||||
assert_not(job1.executable?)
|
||||
|
||||
job1.updated_at = Time.zone.now - 15.minutes
|
||||
job1.save
|
||||
assert(job1.executable?)
|
||||
|
||||
assert_not(job1.in_timeplan?)
|
||||
time = Time.zone.now
|
||||
day_map = {
|
||||
0 => 'Sun',
|
||||
1 => 'Mon',
|
||||
2 => 'Tue',
|
||||
3 => 'Wed',
|
||||
4 => 'Thu',
|
||||
5 => 'Fri',
|
||||
6 => 'Sat',
|
||||
}
|
||||
job1.timeplan['days'][day_map[time.wday]] = true
|
||||
job1.save
|
||||
assert_not(job1.in_timeplan?)
|
||||
job1.timeplan['hours'][time.hour.to_s] = true
|
||||
job1.save
|
||||
assert_not(job1.in_timeplan?)
|
||||
min = time.min
|
||||
if min < 9
|
||||
min = 0
|
||||
elsif min < 20
|
||||
min = 10
|
||||
elsif min < 30
|
||||
min = 20
|
||||
elsif min < 40
|
||||
min = 30
|
||||
elsif min < 50
|
||||
min = 40
|
||||
elsif min < 59
|
||||
min = 50
|
||||
end
|
||||
job1.timeplan['minutes'][min.to_s] = true
|
||||
job1.save
|
||||
assert(job1.in_timeplan?)
|
||||
|
||||
job1.timeplan['hours'][time.hour] = true
|
||||
job1.save
|
||||
|
||||
job1.timeplan['minutes'][min] = true
|
||||
job1.save
|
||||
assert(job1.in_timeplan?)
|
||||
|
||||
# execute jobs
|
||||
job1.updated_at = Time.zone.now - 15.minutes
|
||||
job1.save
|
||||
Job.run
|
||||
|
||||
assert(job1.executable?)
|
||||
assert(job1.in_timeplan?)
|
||||
|
||||
# verify changes on tickets
|
||||
ticket1_later = Ticket.find(ticket1.id)
|
||||
assert_equal('closed', ticket1_later.state.name)
|
||||
assert_not_equal(ticket1.updated_at.to_s, ticket1_later.updated_at.to_s)
|
||||
|
||||
ticket2_later = Ticket.find(ticket2.id)
|
||||
assert_equal('new', ticket2_later.state.name)
|
||||
assert_equal(ticket2.updated_at.to_s, ticket2_later.updated_at.to_s)
|
||||
|
||||
ticket3_later = Ticket.find(ticket3.id)
|
||||
assert_equal('open', ticket3_later.state.name)
|
||||
assert_equal(ticket3.updated_at.to_s, ticket3_later.updated_at.to_s)
|
||||
|
||||
ticket4_later = Ticket.find(ticket4.id)
|
||||
assert_equal('closed', ticket4_later.state.name)
|
||||
assert_equal(ticket4.updated_at.to_s, ticket4_later.updated_at.to_s)
|
||||
|
||||
ticket5_later = Ticket.find(ticket5.id)
|
||||
assert_equal('closed', ticket5_later.state.name)
|
||||
assert_not_equal(ticket5.updated_at.to_s, ticket5_later.updated_at.to_s)
|
||||
|
||||
# execute jobs again
|
||||
job1.updated_at = Time.zone.now - 15.minutes
|
||||
job1.save
|
||||
Job.run
|
||||
|
||||
# verify changes on tickets
|
||||
ticket1_later_next = Ticket.find(ticket1.id)
|
||||
assert_equal('closed', ticket1_later_next.state.name)
|
||||
assert_equal(ticket1_later.updated_at.to_s, ticket1_later_next.updated_at.to_s)
|
||||
|
||||
ticket2_later_next = Ticket.find(ticket2.id)
|
||||
assert_equal('new', ticket2_later_next.state.name)
|
||||
assert_equal(ticket2_later.updated_at.to_s, ticket2_later_next.updated_at.to_s)
|
||||
|
||||
ticket3_later_next = Ticket.find(ticket3.id)
|
||||
assert_equal('open', ticket3_later_next.state.name)
|
||||
assert_equal(ticket3_later.updated_at.to_s, ticket3_later_next.updated_at.to_s)
|
||||
|
||||
ticket4_later_next = Ticket.find(ticket4.id)
|
||||
assert_equal('closed', ticket4_later_next.state.name)
|
||||
assert_equal(ticket4_later.updated_at.to_s, ticket4_later_next.updated_at.to_s)
|
||||
|
||||
ticket5_later_next = Ticket.find(ticket5.id)
|
||||
assert_equal('closed', ticket5_later_next.state.name)
|
||||
assert_equal(ticket5_later.updated_at.to_s, ticket5_later_next.updated_at.to_s)
|
||||
|
||||
end
|
||||
|
||||
test 'case 2' do
|
||||
|
||||
# create ticket
|
||||
group1 = Group.lookup(name: 'Users')
|
||||
group2 = Group.create_or_update(
|
||||
name: 'JobTest2',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
ticket1 = Ticket.create(
|
||||
title: 'job test 1',
|
||||
group: group1,
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'new'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
created_at: Time.zone.now - 3.days,
|
||||
updated_at: Time.zone.now - 3.days,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
ticket2 = Ticket.create(
|
||||
title: 'job test 2',
|
||||
group: group1,
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'new'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
created_at: Time.zone.now - 1.day,
|
||||
created_by_id: 1,
|
||||
updated_at: Time.zone.now - 1.day,
|
||||
updated_by_id: 1,
|
||||
)
|
||||
|
||||
# create jobs
|
||||
job1 = Job.create_or_update(
|
||||
name: 'Test Job1',
|
||||
timeplan: {
|
||||
days: {
|
||||
Mon: true,
|
||||
Tue: true,
|
||||
Wed: true,
|
||||
Thu: true,
|
||||
Fri: true,
|
||||
Sat: true,
|
||||
Sun: true,
|
||||
},
|
||||
hours: {
|
||||
0 => true,
|
||||
1 => true,
|
||||
2 => true,
|
||||
3 => true,
|
||||
4 => true,
|
||||
5 => true,
|
||||
6 => true,
|
||||
7 => true,
|
||||
8 => true,
|
||||
9 => true,
|
||||
10 => true,
|
||||
11 => true,
|
||||
12 => true,
|
||||
13 => true,
|
||||
14 => true,
|
||||
15 => true,
|
||||
16 => true,
|
||||
17 => true,
|
||||
18 => true,
|
||||
19 => true,
|
||||
20 => true,
|
||||
21 => true,
|
||||
22 => true,
|
||||
23 => true,
|
||||
},
|
||||
minutes: {
|
||||
0 => true,
|
||||
10 => true,
|
||||
20 => true,
|
||||
30 => true,
|
||||
40 => true,
|
||||
50 => true,
|
||||
},
|
||||
},
|
||||
condition: {
|
||||
'ticket.state_id' => { 'operator' => 'is', 'value' => '' },
|
||||
'ticket.created_at' => { 'operator' => 'before (relative)', 'value' => '2', 'range' => 'day' },
|
||||
},
|
||||
perform: {
|
||||
'ticket.state_id' => { 'value' => Ticket::State.lookup(name: 'closed').id.to_s }
|
||||
},
|
||||
disable_notification: true,
|
||||
last_run_at: nil,
|
||||
updated_at: Time.zone.now - 15.minutes,
|
||||
active: true,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
assert(job1.executable?)
|
||||
assert(job1.in_timeplan?)
|
||||
Job.run
|
||||
|
||||
# verify changes on tickets
|
||||
ticket1_later = Ticket.find(ticket1.id)
|
||||
assert_equal('new', ticket1_later.state.name)
|
||||
assert_equal(ticket1.updated_at.to_s, ticket1_later.updated_at.to_s)
|
||||
|
||||
ticket2_later = Ticket.find(ticket2.id)
|
||||
assert_equal('new', ticket2_later.state.name)
|
||||
assert_equal(ticket2.updated_at.to_s, ticket2_later.updated_at.to_s)
|
||||
|
||||
job1 = Job.create_or_update(
|
||||
name: 'Test Job1',
|
||||
timeplan: {
|
||||
days: {
|
||||
Mon: true,
|
||||
Tue: true,
|
||||
Wed: true,
|
||||
Thu: true,
|
||||
Fri: true,
|
||||
Sat: true,
|
||||
Sun: true,
|
||||
},
|
||||
hours: {
|
||||
0 => true,
|
||||
1 => true,
|
||||
2 => true,
|
||||
3 => true,
|
||||
4 => true,
|
||||
5 => true,
|
||||
6 => true,
|
||||
7 => true,
|
||||
8 => true,
|
||||
9 => true,
|
||||
10 => true,
|
||||
11 => true,
|
||||
12 => true,
|
||||
13 => true,
|
||||
14 => true,
|
||||
15 => true,
|
||||
16 => true,
|
||||
17 => true,
|
||||
18 => true,
|
||||
19 => true,
|
||||
20 => true,
|
||||
21 => true,
|
||||
22 => true,
|
||||
23 => true,
|
||||
},
|
||||
minutes: {
|
||||
0 => true,
|
||||
10 => true,
|
||||
20 => true,
|
||||
30 => true,
|
||||
40 => true,
|
||||
50 => true,
|
||||
},
|
||||
},
|
||||
condition: {
|
||||
'ticket.state_id' => { 'operator' => 'is' },
|
||||
'ticket.created_at' => { 'operator' => 'before (relative)', 'value' => '2', 'range' => 'day' },
|
||||
},
|
||||
perform: {
|
||||
'ticket.state_id' => { 'value' => Ticket::State.lookup(name: 'closed').id.to_s }
|
||||
},
|
||||
disable_notification: true,
|
||||
last_run_at: nil,
|
||||
updated_at: Time.zone.now - 15.minutes,
|
||||
active: true,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
assert(job1.executable?)
|
||||
assert(job1.in_timeplan?)
|
||||
Job.run
|
||||
|
||||
# verify changes on tickets
|
||||
ticket1_later = Ticket.find(ticket1.id)
|
||||
assert_equal('new', ticket1_later.state.name)
|
||||
assert_equal(ticket1.updated_at.to_s, ticket1_later.updated_at.to_s)
|
||||
|
||||
ticket2_later = Ticket.find(ticket2.id)
|
||||
assert_equal('new', ticket2_later.state.name)
|
||||
assert_equal(ticket2.updated_at.to_s, ticket2_later.updated_at.to_s)
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -146,6 +146,86 @@ class TicketSelectorTest < ActiveSupport::TestCase
|
|||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal(ticket_count, 0)
|
||||
|
||||
# search matching with empty value / missing key
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.state_id' => {
|
||||
operator: 'is',
|
||||
},
|
||||
}
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
# search matching with empty value []
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.state_id' => {
|
||||
operator: 'is',
|
||||
value: [],
|
||||
},
|
||||
}
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
# search matching with empty value ''
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
operator: 'is',
|
||||
value: group.id,
|
||||
},
|
||||
'ticket.state_id' => {
|
||||
operator: 'is',
|
||||
value: '',
|
||||
},
|
||||
}
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent1)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, agent2)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer1)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
ticket_count, tickets = Ticket.selectors(condition, 10, customer2)
|
||||
assert_equal(ticket_count, nil)
|
||||
|
||||
# search matching
|
||||
condition = {
|
||||
'ticket.group_id' => {
|
||||
|
|
Loading…
Reference in a new issue