diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 439e74a8e..4612cbc08 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -40,12 +40,12 @@ job_unit_mysql:
- mysql
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- rake db:seed
- rake test:units
- rake test:controllers
+ - rake db:drop
job_unit_postgresql:
stage: test
@@ -54,12 +54,12 @@ job_unit_postgresql:
- postgresql
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- rake db:seed
- rake test:units
- rake test:controllers
+ - rake db:drop
job_integration_email_helper:
stage: test
@@ -67,10 +67,10 @@ job_integration_email_helper:
- core
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/email_helper_test.rb
+ - rake db:drop
job_integration_twitter:
stage: test
@@ -79,11 +79,12 @@ job_integration_twitter:
- twitter
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- rake db:seed
- ruby -I test/ test/integration/twitter_test.rb
+ - rake db:drop
+ allow_failure: true
job_integration_facebook:
stage: test
@@ -91,11 +92,12 @@ job_integration_facebook:
- core
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- rake db:seed
- ruby -I test/ test/integration/facebook_test.rb
+ - rake db:drop
+ allow_failure: true
job_integration_geo_ip:
stage: test
@@ -103,10 +105,10 @@ job_integration_geo_ip:
- core
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/geo_ip_test.rb
+ - rake db:drop
job_integration_geo_location:
stage: test
@@ -114,10 +116,10 @@ job_integration_geo_location:
- core
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/geo_location_test.rb
+ - rake db:drop
job_integration_geo_calendar:
stage: test
@@ -125,10 +127,10 @@ job_integration_geo_calendar:
- core
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/geo_calendar_test.rb
+ - rake db:drop
job_integration_user_agent:
stage: test
@@ -136,10 +138,10 @@ job_integration_user_agent:
- core
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/user_agent_test.rb
+ - rake db:drop
job_integration_es_mysql:
stage: test
@@ -150,12 +152,12 @@ job_integration_es_mysql:
- export RAILS_ENV=test
- export ES_INDEX_RAND=true
- export ES_URL="http://localhost:9200"
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/elasticsearch_test.rb
- ruby -I test/ test/controllers/search_controller_test.rb
- ruby -I test/ test/integration/report_test.rb
+ - rake db:drop
job_integration_es_postgresql:
stage: test
@@ -166,12 +168,12 @@ job_integration_es_postgresql:
- export RAILS_ENV=test
- export ES_INDEX_RAND=true
- export ES_URL="http://localhost:9200"
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/elasticsearch_test.rb
- ruby -I test/ test/controllers/search_controller_test.rb
- ruby -I test/ test/integration/report_test.rb
+ - rake db:drop
job_integration_zendesk_mysql:
stage: test
@@ -180,10 +182,10 @@ job_integration_zendesk_mysql:
- mysql
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/zendesk_import_test.rb
+ - rake db:drop
job_integration_zendesk_postgresql:
stage: test
@@ -192,10 +194,10 @@ job_integration_zendesk_postgresql:
- postgresql
script:
- export RAILS_ENV=test
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/zendesk_import_test.rb
+ - rake db:drop
job_integration_otrs_5_mysql:
stage: test
@@ -205,10 +207,10 @@ job_integration_otrs_5_mysql:
script:
- export RAILS_ENV=test
- export IMPORT_OTRS_ENDPOINT="http://vz599.demo.znuny.com/otrs/public.pl?Action=ZammadMigrator"
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/otrs_import_test.rb
+ - rake db:drop
job_integration_otrs_5_postgresql:
stage: test
@@ -218,10 +220,10 @@ job_integration_otrs_5_postgresql:
script:
- export RAILS_ENV=test
- export IMPORT_OTRS_ENDPOINT="http://vz599.demo.znuny.com/otrs/public.pl?Action=ZammadMigrator"
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/otrs_import_test.rb
+ - rake db:drop
job_integration_otrs_4:
stage: test
@@ -230,10 +232,10 @@ job_integration_otrs_4:
script:
- export RAILS_ENV=test
- export IMPORT_OTRS_ENDPOINT="http://vz383.demo.znuny.com/otrs/public.pl?Action=ZammadMigrator"
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/otrs_import_test.rb
+ - rake db:drop
job_integration_otrs_33:
stage: test
@@ -242,10 +244,10 @@ job_integration_otrs_33:
script:
- export RAILS_ENV=test
- export IMPORT_OTRS_ENDPOINT="http://vz305.demo.znuny.com/otrs/public.pl?Action=ZammadMigrator"
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/otrs_import_test.rb
+ - rake db:drop
job_integration_otrs_32:
stage: test
@@ -254,10 +256,10 @@ job_integration_otrs_32:
script:
- export RAILS_ENV=test
- export IMPORT_OTRS_ENDPOINT="http://vz382.demo.znuny.com/otrs/public.pl?Action=ZammadMigrator"
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/otrs_import_test.rb
+ - rake db:drop
job_integration_otrs_31:
stage: test
@@ -266,10 +268,10 @@ job_integration_otrs_31:
script:
- export RAILS_ENV=test
- export IMPORT_OTRS_ENDPOINT="http://vz381.demo.znuny.com/otrs/public.pl?Action=ZammadMigrator"
- - rake db:drop;
- rake db:create
- rake db:migrate
- ruby -I test/ test/integration/otrs_import_test.rb
+ - rake db:drop
job_integration_twitter_ff:
stage: browser
diff --git a/Gemfile b/Gemfile
index bcdb47fe8..ecc9a8afd 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,7 +2,7 @@ source 'https://rubygems.org'
ruby '2.2.3'
-gem 'rails', '4.2.5.2'
+gem 'rails', '4.2.6'
gem 'rails-observers'
gem 'activerecord-session_store'
@@ -122,7 +122,7 @@ group :development, :test do
end
-gem 'puma', '< 3.0'
+gem 'puma'
# load onw gem's
local_gemfile = File.join(File.dirname(__FILE__), 'Gemfile.local')
diff --git a/Gemfile.lock b/Gemfile.lock
index c5cd62765..d51b0aba6 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,40 +1,40 @@
GEM
remote: https://rubygems.org/
specs:
- actionmailer (4.2.5.2)
- actionpack (= 4.2.5.2)
- actionview (= 4.2.5.2)
- activejob (= 4.2.5.2)
+ actionmailer (4.2.6)
+ actionpack (= 4.2.6)
+ actionview (= 4.2.6)
+ activejob (= 4.2.6)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5)
- actionpack (4.2.5.2)
- actionview (= 4.2.5.2)
- activesupport (= 4.2.5.2)
+ actionpack (4.2.6)
+ actionview (= 4.2.6)
+ activesupport (= 4.2.6)
rack (~> 1.6)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (4.2.5.2)
- activesupport (= 4.2.5.2)
+ actionview (4.2.6)
+ activesupport (= 4.2.6)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- activejob (4.2.5.2)
- activesupport (= 4.2.5.2)
+ activejob (4.2.6)
+ activesupport (= 4.2.6)
globalid (>= 0.3.0)
- activemodel (4.2.5.2)
- activesupport (= 4.2.5.2)
+ activemodel (4.2.6)
+ activesupport (= 4.2.6)
builder (~> 3.1)
- activerecord (4.2.5.2)
- activemodel (= 4.2.5.2)
- activesupport (= 4.2.5.2)
+ activerecord (4.2.6)
+ activemodel (= 4.2.6)
+ activesupport (= 4.2.6)
arel (~> 6.0)
activerecord-session_store (0.1.2)
actionpack (>= 4.0.0, < 5)
activerecord (>= 4.0.0, < 5)
railties (>= 4.0.0, < 5)
- activesupport (4.2.5.2)
+ activesupport (4.2.6)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
@@ -45,7 +45,7 @@ GEM
ast (2.2.0)
autoprefixer-rails (6.3.3.1)
execjs
- biz (1.3.4)
+ biz (1.4.0)
clavius (~> 1.0)
tzinfo
browser (2.0.2)
@@ -76,7 +76,7 @@ GEM
diffy (3.1.0)
dnsruby (1.59.2)
docile (1.1.5)
- domain_name (0.5.20160216)
+ domain_name (0.5.20160309)
unf (>= 0.0.5, < 1.0.0)
eco (1.0.0)
coffee-script
@@ -90,7 +90,7 @@ GEM
dnsruby (>= 1.5)
equalizer (0.0.10)
erubis (2.7.0)
- eventmachine (1.0.9.1)
+ eventmachine (1.2.0.1)
execjs (2.6.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
@@ -172,8 +172,8 @@ GEM
rack (>= 1.0, < 3)
omniauth-facebook (3.0.0)
omniauth-oauth2 (~> 1.2)
- omniauth-google-oauth2 (0.3.1)
- jwt (~> 1.0)
+ omniauth-google-oauth2 (0.4.0)
+ jwt (~> 1.5.0)
multi_json (~> 1.3)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.3.1)
@@ -199,22 +199,22 @@ GEM
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
- puma (2.16.0)
+ puma (3.1.0)
rack (1.6.4)
rack-livereload (0.3.16)
rack
rack-test (0.6.3)
rack (>= 1.0)
- rails (4.2.5.2)
- actionmailer (= 4.2.5.2)
- actionpack (= 4.2.5.2)
- actionview (= 4.2.5.2)
- activejob (= 4.2.5.2)
- activemodel (= 4.2.5.2)
- activerecord (= 4.2.5.2)
- activesupport (= 4.2.5.2)
+ rails (4.2.6)
+ actionmailer (= 4.2.6)
+ actionpack (= 4.2.6)
+ actionview (= 4.2.6)
+ activejob (= 4.2.6)
+ activemodel (= 4.2.6)
+ activerecord (= 4.2.6)
+ activesupport (= 4.2.6)
bundler (>= 1.3.0, < 2.0)
- railties (= 4.2.5.2)
+ railties (= 4.2.6)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
@@ -226,23 +226,23 @@ GEM
loofah (~> 2.0)
rails-observers (0.1.2)
activemodel (~> 4.0)
- railties (4.2.5.2)
- actionpack (= 4.2.5.2)
- activesupport (= 4.2.5.2)
+ railties (4.2.6)
+ actionpack (= 4.2.6)
+ activesupport (= 4.2.6)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.1.0)
- rake (10.5.0)
+ rake (11.1.1)
rb-fsevent (0.9.7)
rb-inotify (0.9.7)
ffi (>= 0.5.0)
ref (2.0.0)
- rubocop (0.37.2)
- parser (>= 2.3.0.4, < 3.0)
+ rubocop (0.38.0)
+ parser (>= 2.3.0.6, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
- unicode-display_width (~> 0.3)
+ unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.7.5)
rubyzip (1.2.0)
sass (3.4.21)
@@ -253,9 +253,8 @@ GEM
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
scrub_rb (1.0.1)
- selenium-webdriver (2.52.0)
+ selenium-webdriver (2.53.0)
childprocess (~> 0.5)
- multi_json (~> 1.0)
rubyzip (~> 1.0)
websocket (~> 1.0)
shellany (0.0.1)
@@ -273,7 +272,7 @@ GEM
sprockets (3.5.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
- sprockets-rails (3.0.3)
+ sprockets-rails (3.0.4)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
@@ -305,7 +304,7 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.7.2)
- unicode-display_width (0.3.1)
+ unicode-display_width (1.0.2)
websocket (1.2.2)
writeexcel (1.0.5)
zendesk_api (1.13.4)
@@ -352,9 +351,9 @@ DEPENDENCIES
omniauth-linkedin
omniauth-twitter
pre-commit
- puma (< 3.0)
+ puma
rack-livereload
- rails (= 4.2.5.2)
+ rails (= 4.2.6)
rails-observers
rb-fsevent
rubocop
diff --git a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
index 50f586140..86f22598e 100644
--- a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
+++ b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
@@ -728,6 +728,9 @@ class App.WizardModal extends App.Controller
if type
@$(".#{screen}").find("[name=\"options::#{field}\"]").closest('.form-group').addClass('has-error')
+ render: ->
+ # do nothing
+
class App.WizardFullScreen extends App.WizardModal
className: 'getstarted fit'
diff --git a/app/assets/javascripts/app/controllers/_ui_element/active.coffee b/app/assets/javascripts/app/controllers/_ui_element/active.coffee
index e7947ed62..56d0b363e 100644
--- a/app/assets/javascripts/app/controllers/_ui_element/active.coffee
+++ b/app/assets/javascripts/app/controllers/_ui_element/active.coffee
@@ -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 ) )
\ No newline at end of file
diff --git a/app/assets/javascripts/app/controllers/_ui_element/boolean.coffee b/app/assets/javascripts/app/controllers/_ui_element/boolean.coffee
index fac677ef0..04951ae39 100644
--- a/app/assets/javascripts/app/controllers/_ui_element/boolean.coffee
+++ b/app/assets/javascripts/app/controllers/_ui_element/boolean.coffee
@@ -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 ) )
\ No newline at end of file
+ $(App.view('generic/select')(attribute: attribute))
\ No newline at end of file
diff --git a/app/assets/javascripts/app/controllers/_ui_element/radio.coffee b/app/assets/javascripts/app/controllers/_ui_element/radio.coffee
index 6b03e62f8..00c5ec5b6 100644
--- a/app/assets/javascripts/app/controllers/_ui_element/radio.coffee
+++ b/app/assets/javascripts/app/controllers/_ui_element/radio.coffee
@@ -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 ) )
diff --git a/app/assets/javascripts/app/controllers/_ui_element/select.coffee b/app/assets/javascripts/app/controllers/_ui_element/select.coffee
index 91a3ad8db..ada6c0b07 100644
--- a/app/assets/javascripts/app/controllers/_ui_element/select.coffee
+++ b/app/assets/javascripts/app/controllers/_ui_element/select.coffee
@@ -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 ) )
\ No newline at end of file
diff --git a/app/assets/javascripts/app/controllers/_ui_element/tag.coffee b/app/assets/javascripts/app/controllers/_ui_element/tag.coffee
index 3fb865259..701bae89b 100644
--- a/app/assets/javascripts/app/controllers/_ui_element/tag.coffee
+++ b/app/assets/javascripts/app/controllers/_ui_element/tag.coffee
@@ -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
\ No newline at end of file
diff --git a/app/assets/javascripts/app/controllers/_ui_element/textarea.coffee b/app/assets/javascripts/app/controllers/_ui_element/textarea.coffee
index f0e7fc601..2a63da75f 100644
--- a/app/assets/javascripts/app/controllers/_ui_element/textarea.coffee
+++ b/app/assets/javascripts/app/controllers/_ui_element/textarea.coffee
@@ -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
\ No newline at end of file
diff --git a/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee b/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee
index 9d1322a9e..b12765ee8 100644
--- a/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee
+++ b/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee
@@ -36,7 +36,7 @@ class App.UiElement.ticket_perform_action
item.find('.js-attributeSelector').prepend(selector)
# add filter
- item.find('.js-add').bind('click', (e) ->
+ item.find('.js-add').bind('click', (e) =>
element = $(e.target).closest('.js-filterElement')
elementClone = element.clone(true)
element.after(elementClone)
diff --git a/app/assets/javascripts/app/controllers/_ui_element/timer.coffee b/app/assets/javascripts/app/controllers/_ui_element/timer.coffee
new file mode 100644
index 000000000..860ccb8ce
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/_ui_element/timer.coffee
@@ -0,0 +1,138 @@
+# coffeelint: disable=camel_case_classes
+class App.UiElement.timer
+ @render: (attribute) ->
+ days =
+ Mon: 'Monday'
+ Tue: 'Tuesday'
+ Wed: 'Wednesday'
+ Thu: 'Thursday'
+ Fri: 'Friday'
+ Sat: 'Saturday'
+ Sun: 'Sunday'
+ hours =
+ 0: '12 am'
+ 1: '1 am'
+ 2: '2 am'
+ 3: '3 am'
+ 4: '4 am'
+ 5: '5 am'
+ 6: '6 am'
+ 7: '7 am'
+ 8: '8 am'
+ 9: '9 am'
+ 10: '10 am'
+ 11: '11 am'
+ 12: '12 am'
+ 13: '1 pm'
+ 14: '2 pm'
+ 15: '3 pm'
+ 16: '4 pm'
+ 17: '5 pm'
+ 18: '6 pm'
+ 19: '7 pm'
+ 20: '8 pm'
+ 21: '9 pm'
+ 22: '10 pm'
+ 23: '11 pm'
+ hours =
+ 0: '00'
+ 1: '01'
+ 2: '02'
+ 3: '03'
+ 4: '04'
+ 5: '05'
+ 6: '06'
+ 7: '07'
+ 8: '08'
+ 9: '09'
+ 10: '10'
+ 11: '11'
+ 12: '12'
+ 13: '13'
+ 14: '14'
+ 15: '15'
+ 16: '16'
+ 17: '17'
+ 18: '18'
+ 19: '19'
+ 20: '20'
+ 21: '21'
+ 22: '22'
+ 23: '23'
+ minutes =
+ 0: '00'
+ 10: '10'
+ 20: '20'
+ 30: '30'
+ 40: '40'
+ 50: '50'
+
+ if !attribute.value
+ attribute.value = {}
+ if _.isEmpty(attribute.value.days)
+ attribute.value.days =
+ Mon: true
+ if _.isEmpty(attribute.value.hours)
+ attribute.value.hours =
+ 0: true
+ if _.isEmpty(attribute.value.minutes)
+ attribute.value.minutes =
+ 0: true
+
+ timer = $( App.view('generic/timer')( attribute: attribute, days: days, hours: hours, minutes: minutes ) )
+
+ timer.find('.select-value').bind('click', (e) =>
+ @select(e)
+ )
+ @createOutputString(timer)
+
+ timer
+
+ @select: (e) =>
+ target = $(e.currentTarget)
+
+ if target.hasClass('is-selected')
+ # prevent zero selections
+ if target.siblings('.is-selected').size() > 0
+ target.removeClass('is-selected')
+ target.next().val('false')
+ else
+ target.addClass('is-selected')
+ target.next().val('true')
+
+ formGroup = $(e.currentTarget).closest('.form-group')
+ @createOutputString(formGroup)
+
+ @createOutputString: (formGroup) =>
+ days = $.map(formGroup.find('[data-type=day]').filter('.is-selected'), (el) -> return $(el).text() )
+ hours = $.map(formGroup.find('[data-type=hour]').filter('.is-selected'), (el) -> return $(el).text() )
+ minutes = $.map(formGroup.find('[data-type=minute]').filter('.is-selected'), (el) -> return $(el).text() )
+
+ hours = @injectMinutes(hours, minutes)
+
+ days = @joinItems days
+ hours = @joinItems hours
+
+ formGroup.find('.js-timerResult').text(App.i18n.translateInline('Run every %s at %s', days, hours))
+
+ @injectMinutes: (hours, minutes) ->
+ newHours = [] # hours.length x minutes.length long
+
+ for hour in hours
+ # split off am/pm
+ [hour, suffix] = hour.split(' ')
+
+ for minute in minutes
+ combined = "#{ hour }:#{ minute }"
+ combined += " #{suffix}" if suffix
+
+ newHours.push combined
+
+ newHours
+
+ @joinItems: (items) ->
+ switch items.length
+ when 1 then return items[0]
+ when 2 then return "#{ items[0] } #{App.i18n.translateInline('and')} #{ items[1] }"
+ else
+ return "#{ items.slice(0, -1).join(', ') } #{App.i18n.translateInline('and')} #{ items[items.length-1] }"
diff --git a/app/assets/javascripts/app/controllers/_ui_element/timezone.coffee b/app/assets/javascripts/app/controllers/_ui_element/timezone.coffee
index a72413280..ce78512cd 100644
--- a/app/assets/javascripts/app/controllers/_ui_element/timezone.coffee
+++ b/app/assets/javascripts/app/controllers/_ui_element/timezone.coffee
@@ -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...')
diff --git a/app/assets/javascripts/app/controllers/getting_started.coffee b/app/assets/javascripts/app/controllers/getting_started.coffee
index f9541a037..6809e910a 100644
--- a/app/assets/javascripts/app/controllers/getting_started.coffee
+++ b/app/assets/javascripts/app/controllers/getting_started.coffee
@@ -59,7 +59,7 @@ class Index extends App.WizardFullScreen
App.Config.set( 'getting_started', Index, 'Routes' )
-class AutoWizard extends App.ControllerContent
+class AutoWizard extends App.WizardFullScreen
constructor: ->
super
diff --git a/app/assets/javascripts/app/controllers/job.coffee b/app/assets/javascripts/app/controllers/job.coffee
new file mode 100644
index 000000000..3d29dc0ee
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/job.coffee
@@ -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')
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee
index 68770b19b..8b3c12112 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee
@@ -77,21 +77,38 @@ class App.TicketZoomArticleActions extends App.Controller
href: '#'
}
recipients = []
- if article.sender.name is 'Agent'
- if article.to
- localRecipients = emailAddresses.parseAddressList(article.to)
- if localRecipients
- recipients = recipients.concat localRecipients
- else
+ if article.sender.name is 'Customer'
if article.from
localRecipients = emailAddresses.parseAddressList(article.from)
if localRecipients
recipients = recipients.concat localRecipients
+ if article.to
+ localRecipients = emailAddresses.parseAddressList(article.to)
+ if localRecipients
+ recipients = recipients.concat localRecipients
if article.cc
localRecipients = emailAddresses.parseAddressList(article.cc)
if localRecipients
recipients = recipients.concat localRecipients
- if recipients.length > 1
+
+ # remove system addresses
+ localAddresses = App.EmailAddress.all()
+ forgeinRecipients = []
+ recipientUsed = {}
+ for recipient in recipients
+ localRecipientAddeess = recipient.address.toString().toLowerCase()
+ if !recipientUsed[localRecipientAddeess]
+ recipientUsed[localRecipientAddeess] = true
+ localAddess = false
+ for address in localAddresses
+ if localRecipientAddeess is address.email.toString().toLowerCase()
+ recipientUsed[localRecipientAddeess] = true
+ localAddess = true
+ if !localAddess
+ forgeinRecipients.push recipient
+
+ # check if reply all is neede
+ if forgeinRecipients.length > 1
actions.push {
name: 'reply all'
type: 'emailReplyAll'
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee
index da24eeaa8..6dda62756 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee
@@ -100,7 +100,7 @@ class ArticleViewItem extends App.Controller
# set @el attributes
if !article
@el.addClass("ticket-article-item #{@article.sender.name.toLowerCase()}")
- @el.attr('data-id', @article.id)
+ @el.attr('data-id', @article.id)
@el.attr('id', "article-#{@article.id}")
# set internal change directly in dom, without rerender while article
@@ -166,7 +166,7 @@ class ArticleViewItem extends App.Controller
@shown = false
a = =>
@setSeeMore()
- @delay( a, 50 )
+ @delay(a, 50)
# set highlighter
@setHighlighter()
diff --git a/app/assets/javascripts/app/controllers/trigger.coffee b/app/assets/javascripts/app/controllers/trigger.coffee
index 123f79965..4376f2d6f 100644
--- a/app/assets/javascripts/app/controllers/trigger.coffee
+++ b/app/assets/javascripts/app/controllers/trigger.coffee
@@ -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')
diff --git a/app/assets/javascripts/app/lib/app_post/websocket.coffee b/app/assets/javascripts/app/lib/app_post/websocket.coffee
index 8795e66a4..6664a52f1 100644
--- a/app/assets/javascripts/app/lib/app_post/websocket.coffee
+++ b/app/assets/javascripts/app/lib/app_post/websocket.coffee
@@ -98,10 +98,10 @@ class _webSocketSingleton extends App.Controller
# send ping after visibilitychange to check if connection is open again after wakeup
$(document).bind('visibilitychange', =>
- console.log('visibilitychange')
+ @log 'debug', 'visibilitychange'
return if document.hidden
return if !@connectionEstablished
- console.log('ping')
+ @log 'debug', 'ping'
@ping()
)
diff --git a/app/assets/javascripts/app/models/job.coffee b/app/assets/javascripts/app/models/job.coffee
index 855408151..36fd9611b 100644
--- a/app/assets/javascripts/app/models/job.coffee
+++ b/app/assets/javascripts/app/models/job.coffee
@@ -1,27 +1,30 @@
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: '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 },
- { name: 'processed', display: 'Processed', readonly: 1 },
- { name: 'last_run_at', display: 'Last run', tag: 'datetime', readonly: 1 },
- { name: 'running', display: 'Running', tag: 'boolean', readonly: 1 },
- { name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
- { name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
- { name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
- { name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
+ { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
+ { 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: 'Will process', readonly: 1 },
+ { name: 'processed', display: 'Has processed', readonly: 1 },
+ { name: 'last_run_at', display: 'Last run', tag: 'datetime', readonly: 1 },
+ { name: 'next_run_at', display: 'Scheduled for', tag: 'datetime', readonly: 1 },
+ { name: 'running', display: 'Running', tag: 'boolean', readonly: 1 },
+ { name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
+ { name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
+ { name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
+ { name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
]
@configure_delete = true
@configure_overview = [
'name',
'last_run_at',
- 'matching',
'processed',
+ 'next_run_at',
+ 'matching',
]
diff --git a/app/assets/javascripts/app/models/trigger.coffee b/app/assets/javascripts/app/models/trigger.coffee
new file mode 100644
index 000000000..2c9352d60
--- /dev/null
+++ b/app/assets/javascripts/app/models/trigger.coffee
@@ -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....
+
+'''
\ No newline at end of file
diff --git a/app/assets/javascripts/app/views/generic/timer.jst.eco b/app/assets/javascripts/app/views/generic/timer.jst.eco
new file mode 100644
index 000000000..fd531f5fa
--- /dev/null
+++ b/app/assets/javascripts/app/views/generic/timer.jst.eco
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ <% for day, dayLong of @days: %>
+
<%- @T(dayLong) %>
+
+ <% end %>
+
+
+
+ <% for hour, hourLong of @hours: %>
+
<%- hourLong %>
+
+ <% end %>
+
+
+
+ <% for minute, minuteLong of @minutes: %>
+
<%- minuteLong %>
+
+ <% end %>
+
+
\ No newline at end of file
diff --git a/app/controllers/triggers_controller.rb b/app/controllers/triggers_controller.rb
new file mode 100644
index 000000000..867f67454
--- /dev/null
+++ b/app/controllers/triggers_controller.rb
@@ -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
diff --git a/app/models/application_model.rb b/app/models/application_model.rb
index eefa7ef27..28e0c17a8 100644
--- a/app/models/application_model.rb
+++ b/app/models/application_model.rb
@@ -92,7 +92,7 @@ returns
=begin
-set rellations of model based on params
+set relations of model based on params
model = Model.find(1)
result = model.param_set_associations(params)
@@ -117,6 +117,7 @@ returns
end
list = []
list_of_items.each {|item|
+ next if !item
list.push(assoc.klass.find(item))
}
send(assoc.name.to_s + '=', list)
diff --git a/app/models/channel/email_parser.rb b/app/models/channel/email_parser.rb
index 15e8a6fe4..e449ea0b5 100644
--- a/app/models/channel/email_parser.rb
+++ b/app/models/channel/email_parser.rb
@@ -507,7 +507,7 @@ retrns
end
end
- # execute ticket events
+ # execute ticket notification events
Observer::Ticket::Notification.transaction
# run postmaster post filter
diff --git a/app/models/job.rb b/app/models/job.rb
index 352e71972..7d4a66bf7 100644
--- a/app/models/job.rb
+++ b/app/models/job.rb
@@ -3,85 +3,233 @@
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, :update_next_run_at
+ before_update :updated_matching, :update_next_run_at
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|
+
+ # use transaction
+ ActiveRecord::Base.transaction do
+ UserInfo.current_user_id = 1
+
+ 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.save
+
+ # execute ticket notification events
+ if !job.disable_notification
+ Observer::Ticket::Notification.transaction
+ end
+ end
+ end
+ end
+
+ job.running = false
job.last_run_at = Time.zone.now
job.save
end
true
end
+ def executable?
+ return false if !active
+
+ # 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
+
+ def next_run_at_calculate(time = Time.zone.now)
+ if last_run_at
+ diff = time - last_run_at
+ if diff > 0
+ time = time + 10.minutes
+ end
+ end
+ day_map = {
+ 0 => 'Sun',
+ 1 => 'Mon',
+ 2 => 'Tue',
+ 3 => 'Wed',
+ 4 => 'Thu',
+ 5 => 'Fri',
+ 6 => 'Sat',
+ }
+ return nil if !active
+ return nil if !timeplan['days']
+ return nil if !timeplan['hours']
+ return nil if !timeplan['minutes']
+
+ # loop week days
+ (0..7).each do |day_counter|
+ time_to_check = nil
+ day_to_check = if day_counter == 0
+ time
+ else
+ time + 1.day
+ end
+ if !timeplan['days'][day_map[day_to_check.wday]]
+
+ # start on next day at 00:00:00
+ time = day_to_check - day_to_check.sec.seconds
+ time = time - day_to_check.min.minutes
+ time = time - day_to_check.hour.hours
+ next
+ end
+
+ min = day_to_check.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 < 60
+ min = 50
+ end
+
+ # move to [0-5]0:00 time stamps
+ day_to_check = day_to_check - day_to_check.min.minutes + min.minutes
+ day_to_check = day_to_check - day_to_check.sec.seconds
+
+ # loop minutes till next full hour
+ if day_to_check.min != 0
+ (0..5).each do |minute_counter|
+ if minute_counter != 0
+ break if day_to_check.min == 0
+ day_to_check = day_to_check + 10.minutes
+ end
+ next if !timeplan['hours'][day_to_check.hour] && !timeplan['hours'][day_to_check.hour.to_s]
+ next if !timeplan['minutes'][match_minutes(day_to_check.min)] && !timeplan['minutes'][match_minutes(day_to_check.min).to_s]
+ return day_to_check
+ end
+ end
+
+ # loop hours
+ hour_to_check = nil
+ (0..23).each do |hour_counter|
+ hour_to_check = day_to_check + hour_counter.hours
+
+ # start on next day
+ if hour_to_check.day != day_to_check.day
+ time = day_to_check - day_to_check.hour.hours
+ break
+ end
+
+ # ignore not configured hours
+ next if !timeplan['hours'][hour_to_check.hour] && !timeplan['hours'][hour_to_check.hour.to_s]
+ return nil if !hour_to_check
+
+ # loop minutes
+ minute_to_check = nil
+ (0..5).each do |minute_counter|
+ minute_to_check = hour_to_check + minute_counter.minutes * 10
+ next if !timeplan['minutes'][match_minutes(minute_to_check.min)] && !timeplan['minutes'][match_minutes(minute_to_check.min).to_s]
+ time_to_check = minute_to_check
+ break
+ end
+ next if !minute_to_check
+ return time_to_check
+ end
+
+ end
+ nil
+ 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 update_next_run_at
+ self.next_run_at = next_run_at_calculate
end
- private_class_method :match_minutes
+
+ def match_minutes(minutes)
+ return 0 if minutes < 10
+ "#{minutes.to_s.gsub(/(\d)\d/, '\\1')}0".to_i
+ end
+
end
diff --git a/app/models/ticket.rb b/app/models/ticket.rb
index 68448d6b9..b89d8b317 100644
--- a/app/models/ticket.rb
+++ b/app/models/ticket.rb
@@ -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
diff --git a/app/models/ticket/number/date.rb b/app/models/ticket/number/date.rb
index 48884dc2f..8e57f5b65 100644
--- a/app/models/ticket/number/date.rb
+++ b/app/models/ticket/number/date.rb
@@ -13,9 +13,9 @@ module Ticket::Number::Date
# read counter
counter_increment = nil
Ticket::Counter.transaction do
- counter = Ticket::Counter.where( generator: 'Date' ).lock(true).first
+ counter = Ticket::Counter.where(generator: 'Date').lock(true).first
if !counter
- counter = Ticket::Counter.new( generator: 'Date', content: '0' )
+ counter = Ticket::Counter.new(generator: 'Date', content: '0')
end
# increase counter
@@ -48,7 +48,7 @@ module Ticket::Number::Date
mult = 1
(1..number.length).each do |i|
digit = number.to_s[i, 1]
- chksum = chksum + ( mult * digit.to_i )
+ chksum = chksum + (mult * digit.to_i)
mult += 1
if mult == 3
mult = 1
@@ -65,6 +65,7 @@ module Ticket::Number::Date
end
def check(string)
+ return if !string || string.empty?
# get config
system_id = Setting.get('system_id') || ''
@@ -73,10 +74,15 @@ module Ticket::Number::Date
ticket = nil
# probe format
- if string =~ /#{ticket_hook}#{ticket_hook_divider}(#{system_id}\d{2,50})/i
- ticket = Ticket.find_by( number: $1 )
- elsif string =~ /#{ticket_hook}\s{0,2}(#{system_id}\d{2,50})/i
- ticket = Ticket.find_by( number: $1 )
+ string.scan(/#{ticket_hook}#{ticket_hook_divider}(#{system_id}\d{2,48})/i) {
+ ticket = Ticket.find_by(number: $1)
+ break if ticket
+ }
+ if !ticket
+ string.scan(/#{ticket_hook}\s{0,2}(#{system_id}\d{2,48})/i) {
+ ticket = Ticket.find_by(number: $1)
+ break if ticket
+ }
end
ticket
end
diff --git a/app/models/ticket/number/increment.rb b/app/models/ticket/number/increment.rb
index 31f464ba9..d268b44d9 100644
--- a/app/models/ticket/number/increment.rb
+++ b/app/models/ticket/number/increment.rb
@@ -12,9 +12,9 @@ module Ticket::Number::Increment
min_digs = config[:min_size] || 4
counter_increment = nil
Ticket::Counter.transaction do
- counter = Ticket::Counter.where( generator: 'Increment' ).lock(true).first
+ counter = Ticket::Counter.where(generator: 'Increment').lock(true).first
if !counter
- counter = Ticket::Counter.new( generator: 'Increment', content: '0' )
+ counter = Ticket::Counter.new(generator: 'Increment', content: '0')
end
counter_increment = counter.content.to_i
@@ -31,9 +31,9 @@ module Ticket::Number::Increment
min_digs = min_digs.to_i - 1
end
fillup = Setting.get('system_id').to_s || '1'
- ( 1..100 ).each {
+ (1..100).each {
- next if ( fillup.length.to_i + counter_increment.to_s.length.to_i ) >= min_digs.to_i
+ next if (fillup.length.to_i + counter_increment.to_s.length.to_i) >= min_digs.to_i
fillup = fillup + '0'
}
@@ -53,7 +53,7 @@ module Ticket::Number::Increment
mult = 1
(1..number.length).each do |i|
digit = number.to_s[i, 1]
- chksum = chksum + ( mult * digit.to_i )
+ chksum = chksum + (mult * digit.to_i)
mult += 1
if mult == 3
mult = 1
@@ -70,6 +70,7 @@ module Ticket::Number::Increment
end
def check(string)
+ return if !string || string.empty?
# get config
system_id = Setting.get('system_id') || ''
@@ -78,10 +79,15 @@ module Ticket::Number::Increment
ticket = nil
# probe format
- if string =~ /#{ticket_hook}#{ticket_hook_divider}(#{system_id}\d{2,48})/i
- ticket = Ticket.find_by( number: $1 )
- elsif string =~ /#{ticket_hook}\s{0,2}(#{system_id}\d{2,48})/i
- ticket = Ticket.find_by( number: $1 )
+ string.scan(/#{ticket_hook}#{ticket_hook_divider}(#{system_id}\d{2,48})/i) {
+ ticket = Ticket.find_by(number: $1)
+ break if ticket
+ }
+ if !ticket
+ string.scan(/#{ticket_hook}\s{0,2}(#{system_id}\d{2,48})/i) {
+ ticket = Ticket.find_by(number: $1)
+ break if ticket
+ }
end
ticket
end
diff --git a/app/views/tests/form_timer.html.erb b/app/views/tests/form_timer.html.erb
new file mode 100644
index 000000000..5e9a1eaad
--- /dev/null
+++ b/app/views/tests/form_timer.html.erb
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/application.rb b/config/application.rb
index b599993a4..59a17ebcf 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -48,7 +48,7 @@ module Zammad
config.api_path = '/api/v1'
# define cache store
- config.cache_store = :file_store, "tmp/cache_file_store_#{Rails.env}"
+ config.cache_store = :file_store, "#{Rails.root}/tmp/cache_file_store_#{Rails.env}"
# default preferences by role
config.preferences_default_by_role = {
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 85a53a8d0..5600b66ed 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -54,9 +54,6 @@ Rails.application.configure do
# Use a different logger for distributed setups.
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
- # Use a different cache store in production.
- # config.cache_store = :mem_cache_store
-
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
@@ -83,7 +80,4 @@ Rails.application.configure do
# format log
config.log_formatter = Logger::Formatter.new
- # define cache store
- config.cache_store = :file_store, 'tmp/cache_file_store_production'
-
end
diff --git a/config/puma.rb b/config/puma.rb
new file mode 100644
index 000000000..bfd115475
--- /dev/null
+++ b/config/puma.rb
@@ -0,0 +1,10 @@
+workers Integer(ENV['WEB_CONCURRENCY'] || 0)
+threads_count_min = Integer(ENV['MIN_THREADS'] || 5)
+threads_count_max = Integer(ENV['MAX_THREADS'] || 30)
+threads threads_count_min, threads_count_max
+
+preload_app!
+
+on_worker_boot do
+ ActiveRecord::Base.establish_connection
+end
diff --git a/config/routes/test.rb b/config/routes/test.rb
index 9e2a315ec..639adf2d1 100644
--- a/config/routes/test.rb
+++ b/config/routes/test.rb
@@ -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
diff --git a/config/routes/trigger.rb b/config/routes/trigger.rb
new file mode 100644
index 000000000..3c34c4d2d
--- /dev/null
+++ b/config/routes/trigger.rb
@@ -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
diff --git a/db/migrate/20120101000010_create_ticket.rb b/db/migrate/20120101000010_create_ticket.rb
index 2c0912898..b2359d099 100644
--- a/db/migrate/20120101000010_create_ticket.rb
+++ b/db/migrate/20120101000010_create_ticket.rb
@@ -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,37 @@ 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 :next_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
diff --git a/db/migrate/20141221000001_create_job.rb b/db/migrate/20141221000001_create_job.rb
deleted file mode 100644
index 17723d5b5..000000000
--- a/db/migrate/20141221000001_create_job.rb
+++ /dev/null
@@ -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
diff --git a/db/migrate/20160314000001_overview_user_relation.rb b/db/migrate/20160314000001_overview_user_relation.rb
deleted file mode 100644
index 5a7adfe07..000000000
--- a/db/migrate/20160314000001_overview_user_relation.rb
+++ /dev/null
@@ -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
diff --git a/db/migrate/20160316000006_renew_triggers.rb b/db/migrate/20160316000006_renew_triggers.rb
new file mode 100644
index 000000000..5469f2d1e
--- /dev/null
+++ b/db/migrate/20160316000006_renew_triggers.rb
@@ -0,0 +1,49 @@
+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 :next_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
diff --git a/db/seeds.rb b/db/seeds.rb
index 17abd8e95..05ea1c932 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -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',
diff --git a/lib/auto_wizard.rb b/lib/auto_wizard.rb
index f69c521f0..8830b5705 100644
--- a/lib/auto_wizard.rb
+++ b/lib/auto_wizard.rb
@@ -73,7 +73,7 @@ returns
# set Settings
if auto_wizard_hash['Settings']
auto_wizard_hash['Settings'].each { |setting_data|
- Setting.set( setting_data['name'], setting_data['value'] )
+ Setting.set(setting_data['name'], setting_data['value'])
}
end
diff --git a/lib/cache.rb b/lib/cache.rb
index 69ef8f905..b225c2dd0 100644
--- a/lib/cache.rb
+++ b/lib/cache.rb
@@ -28,11 +28,7 @@ write a cache
if !params[:expires_in]
params[:expires_in] = 7.days
end
- begin
- Rails.cache.write(key.to_s, data, params)
- rescue => e
- Rails.logger.error "NOTICE: #{e.message}"
- end
+ Rails.cache.write(key.to_s, data, params)
end
=begin
diff --git a/public/assets/tests/form_timer.js b/public/assets/tests/form_timer.js
new file mode 100644
index 000000000..9650c2637
--- /dev/null
+++ b/public/assets/tests/form_timer.js
@@ -0,0 +1,214 @@
+
+test("form elements check", function() {
+
+ $('#forms').append('
form elements check
')
+ var el = $('#form1')
+ var defaults = {
+ }
+ new App.ControllerForm({
+ el: el,
+ model: {
+ configure_attributes: [
+ { name: 'input1', display: 'Input1', tag: 'input', type: 'text', limit: 100, null: true, default: defaults['input1'] },
+ { name: 'timer_params', display: 'Timer', tag: 'timer', null: false, default: defaults['timer_params'] },
+ ]
+ },
+ autofocus: true
+ });
+
+ equal('Run every Monday at 00:00', el.find('.js-timerResult').val())
+
+ var params = App.ControllerForm.params(el)
+ var test_params = {
+ input1: '',
+ timer_params: {
+ days: {
+ 'Mon': true,
+ 'Tue': false,
+ 'Wed': false,
+ 'Thu': false,
+ 'Fri': false,
+ 'Sat': false,
+ 'Sun': false,
+ },
+ hours: {
+ 0: true,
+ 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: true,
+ 10: false,
+ 20: false,
+ 30: false,
+ 40: false,
+ 50: false,
+ },
+ },
+ }
+ deepEqual(params, test_params, 'form param check')
+
+ $('#forms').append('
form elements check
')
+ var el = $('#form2')
+ var defaults = {
+ input1: '123abc',
+ timer_params: {
+ days: {
+ 'Mon': true,
+ 'Fri': true,
+ },
+ hours: {
+ 0: true,
+ 10: true,
+ 16: true,
+ },
+ minutes: {
+ 0: true,
+ 10: true,
+ 50: true,
+ },
+ },
+ }
+ new App.ControllerForm({
+ el: el,
+ model: {
+ configure_attributes: [
+ { name: 'input1', display: 'Input1', tag: 'input', type: 'text', limit: 100, null: true, default: defaults['input1'] },
+ { name: 'timer_params', display: 'Timer', tag: 'timer', null: false, default: defaults['timer_params'] },
+ ]
+ },
+ autofocus: true
+ });
+
+ equal('Run every Monday and Friday at 00:00, 00:10, 00:50, 10:00, 10:10, 10:50, 16:00, 16:10 and 16:50', el.find('.js-timerResult').val())
+
+ var params = App.ControllerForm.params(el)
+ var test_params = {
+ input1: '123abc',
+ timer_params: {
+ days: {
+ 'Mon': true,
+ 'Tue': false,
+ 'Wed': false,
+ 'Thu': false,
+ 'Fri': true,
+ 'Sat': false,
+ 'Sun': false,
+ },
+ hours: {
+ 0: true,
+ 1: false,
+ 2: false,
+ 3: false,
+ 4: false,
+ 5: false,
+ 6: false,
+ 7: false,
+ 8: false,
+ 9: false,
+ 10: true,
+ 11: false,
+ 12: false,
+ 13: false,
+ 14: false,
+ 15: false,
+ 16: true,
+ 17: false,
+ 18: false,
+ 19: false,
+ 20: false,
+ 21: false,
+ 22: false,
+ 23: false,
+ },
+ minutes: {
+ 0: true,
+ 10: true,
+ 20: false,
+ 30: false,
+ 40: false,
+ 50: true,
+ },
+ },
+ }
+ deepEqual(params, test_params, 'form param check')
+
+ $('#form2 .js-day [data-value="Sat"]').click()
+ $('#form2 .js-hour [data-value="16"]').click()
+ $('#form2 .js-minute [data-value="10"]').click()
+
+ equal('Run every Monday, Friday and Saturday at 00:00, 00:50, 10:00 and 10:50', el.find('.js-timerResult').val())
+
+ var params = App.ControllerForm.params(el)
+ var test_params = {
+ input1: '123abc',
+ timer_params: {
+ days: {
+ 'Mon': true,
+ 'Tue': false,
+ 'Wed': false,
+ 'Thu': false,
+ 'Fri': true,
+ 'Sat': true,
+ 'Sun': false,
+ },
+ hours: {
+ 0: true,
+ 1: false,
+ 2: false,
+ 3: false,
+ 4: false,
+ 5: false,
+ 6: false,
+ 7: false,
+ 8: false,
+ 9: false,
+ 10: true,
+ 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: true,
+ 10: false,
+ 20: false,
+ 30: false,
+ 40: false,
+ 50: true,
+ },
+ },
+ }
+ deepEqual(params, test_params, 'form param check')
+
+});
\ No newline at end of file
diff --git a/script/build/test_startup.sh b/script/build/test_startup.sh
index 825c9c207..f12d731df 100755
--- a/script/build/test_startup.sh
+++ b/script/build/test_startup.sh
@@ -16,6 +16,6 @@ echo "export IP=$IP"
echo "export BROWSER_PORT=$BROWSER_PORT"
#rails s puma -d --pid tmp/pids/server.pid --bind 0.0.0.0 --port $APP_PORT
-pumactl start --pidfile tmp/pids/server.pid -d -p $APP_PORT -e $RAILS_ENV
+puma --pidfile tmp/pids/server.pid -d -p $APP_PORT -e $RAILS_ENV
script/websocket-server.rb start -d -p $WS_PORT
script/scheduler.rb start
diff --git a/script/init-script-normal-user-rvm-fedora b/script/init-script-normal-user-rvm-fedora
index 3358e06d2..e8f5eebf9 100755
--- a/script/init-script-normal-user-rvm-fedora
+++ b/script/init-script-normal-user-rvm-fedora
@@ -63,7 +63,7 @@ start() {
echo -n $"Starting ${NAME}/${RAILS_ENV} application server on port: ${APP_PORT}"
# $RAILS server -d -p $APP_PORT --pid $APP_PIDFILE &> /dev/null
# thin start --threaded -d -p $APP_PORT --pid $APP_PIDFILE
- pumactl start --pidfile $APP_PIDFILE -d -p $APP_PORT -e $RAILS_ENV &> /dev/null
+ puma --pidfile $APP_PIDFILE -d -p $APP_PORT -e $RAILS_ENV &> /dev/null
sleep 2
status -p $APP_PIDFILE &> /dev/null && echo_success || echo_failure
echo
diff --git a/script/local_browser_tests.sh b/script/local_browser_tests.sh
index 35bbca3ea..9900a72c7 100755
--- a/script/local_browser_tests.sh
+++ b/script/local_browser_tests.sh
@@ -38,16 +38,18 @@ rails r "Setting.set('developer_mode', true)"
pumactl --pidfile tmp/pids/puma.pid stop
script/websocket-server.rb stop
-pumactl start --pidfile tmp/pids/puma.pid -d -p 4445 -e $RAILS_ENV
+rails s puma -d --pid tmp/pids/puma.pid --bind 0.0.0.0 --port 4445
script/websocket-server.rb start -d
script/scheduler.rb start
-sleep 15
+sleep 10
#export REMOTE_URL='http://medenhofer:765d0dd4-994b-4e15-9f89-13f3aedeb462@ondemand.saucelabs.com:80/wd/hub' BROWSER_OS='Windows 2012' BROWSER_VERSION=35 BROWSER=firefox
#export REMOTE_URL='http://192.168.178.32:4444/wd/hub'
#export REMOTE_URL='http://192.168.178.45:4444/wd/hub'
-export REMOTE_URL='http://10.0.0.9:4444/wd/hub'
+#export REMOTE_URL='http://10.0.0.9:4444/wd/hub'
+#export REMOTE_URL='http://10.8.0.22:4449/wd/hub'
+export REMOTE_URL='http://localhost:4444/wd/hub'
export RAILS_ENV=test
@@ -58,10 +60,10 @@ time rake db:create
echo "rake db:migrate"
time rake db:migrate
+#rake test:browser["BROWSER_URL=http://10.8.0.6:3000"]
rake test:browser["BROWSER_URL=http://localhost:4445"]
#rake test:browser["BROWSER_URL=http://10.0.0.3:4445"]
#rake test:browser["BROWSER_URL=http://localhost:4445 BROWSER=chrome"]
-#rake test:browser["BROWSER_URL=http://192.168.178.28:4445"]
script/scheduler.rb stop
script/websocket-server.rb stop
diff --git a/test/browser/aab_unit_test.rb b/test/browser/aab_unit_test.rb
index 1cc92f5cf..8d54d4756 100644
--- a/test/browser/aab_unit_test.rb
+++ b/test/browser/aab_unit_test.rb
@@ -59,6 +59,13 @@ class AAbUnitTest < TestCase
value: '0',
)
+ location( url: browser_url + '/tests_form_timer' )
+ sleep 4
+ match(
+ css: '.result .failed',
+ value: '0',
+ )
+
location( url: browser_url + '/tests_form_extended' )
sleep 4
match(
diff --git a/test/unit/calendar_subscription_test.rb b/test/unit/calendar_subscription_test.rb
index a7d4c799f..e43f46ee7 100644
--- a/test/unit/calendar_subscription_test.rb
+++ b/test/unit/calendar_subscription_test.rb
@@ -95,7 +95,7 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
owner_id: agent2.id,
state: Ticket::State.lookup(name: 'new'),
priority: Ticket::Priority.lookup(name: '2 normal'),
- created_at: '2016-02-05 16:37:00',
+ created_at: '2016-02-05 16:38:00',
updated_by_id: 1,
created_by_id: 1,
)
@@ -107,7 +107,7 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
state: Ticket::State.lookup(name: 'pending reminder'),
pending_time: '2016-02-07 16:37:00',
priority: Ticket::Priority.lookup(name: '2 normal'),
- created_at: '2016-02-05 16:37:00',
+ created_at: '2016-02-05 16:39:00',
updated_by_id: 1,
created_by_id: 1,
)
@@ -117,9 +117,9 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
customer_id: customer1.id,
owner_id: agent2.id,
state: Ticket::State.lookup(name: 'pending reminder'),
- pending_time: '2016-02-07 16:37:00',
+ pending_time: '2016-02-07 16:38:00',
priority: Ticket::Priority.lookup(name: '2 normal'),
- created_at: '2016-02-05 16:37:00',
+ created_at: '2016-02-05 16:40:00',
updated_by_id: 1,
created_by_id: 1,
)
@@ -129,9 +129,9 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
customer_id: customer1.id,
owner_id: agent1.id,
state: Ticket::State.lookup(name: 'new'),
- escalation_time: '2016-02-07 17:37:00',
+ escalation_time: '2016-02-07 17:39:00',
priority: Ticket::Priority.lookup(name: '2 normal'),
- created_at: '2016-02-05 16:37:00',
+ created_at: '2016-02-05 16:41:00',
updated_by_id: 1,
created_by_id: 1,
)
@@ -143,7 +143,7 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
state: Ticket::State.lookup(name: 'new'),
escalation_time: '2016-02-07 16:37:00',
priority: Ticket::Priority.lookup(name: '2 normal'),
- created_at: '2016-02-05 16:37:00',
+ created_at: '2016-02-05 16:42:00',
updated_by_id: 1,
created_by_id: 1,
)
@@ -166,7 +166,7 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
owner_id: 1,
state: Ticket::State.lookup(name: 'new'),
priority: Ticket::Priority.lookup(name: '2 normal'),
- created_at: '2016-02-05 17:37:00',
+ created_at: '2016-02-05 17:38:00',
updated_by_id: 1,
created_by_id: 1,
)
@@ -178,7 +178,7 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
state: Ticket::State.lookup(name: 'pending reminder'),
pending_time: '2016-02-08 16:37:00',
priority: Ticket::Priority.lookup(name: '2 normal'),
- created_at: '2016-02-05 17:37:00',
+ created_at: '2016-02-05 17:39:00',
updated_by_id: 1,
created_by_id: 1,
)
@@ -188,9 +188,9 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
customer_id: customer1.id,
owner_id: 1,
state: Ticket::State.lookup(name: 'pending reminder'),
- pending_time: '2016-02-08 16:37:00',
+ pending_time: '2016-02-08 16:38:00',
priority: Ticket::Priority.lookup(name: '2 normal'),
- created_at: '2016-02-05 17:37:00',
+ created_at: '2016-02-05 17:40:00',
updated_by_id: 1,
created_by_id: 1,
)
@@ -200,9 +200,9 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
customer_id: customer1.id,
owner_id: 1,
state: Ticket::State.lookup(name: 'new'),
- escalation_time: '2016-02-08 17:37:00',
+ escalation_time: '2016-02-08 18:37:00',
priority: Ticket::Priority.lookup(name: '2 normal'),
- created_at: '2016-02-05 17:37:00',
+ created_at: '2016-02-05 17:41:00',
updated_by_id: 1,
created_by_id: 1,
)
@@ -212,9 +212,9 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
customer_id: customer1.id,
owner_id: 1,
state: Ticket::State.lookup(name: 'new'),
- escalation_time: '2016-02-08 16:37:00',
+ escalation_time: '2016-02-08 18:38:00',
priority: Ticket::Priority.lookup(name: '2 normal'),
- created_at: '2016-02-05 17:37:00',
+ created_at: '2016-02-05 17:42:00',
updated_by_id: 1,
created_by_id: 1,
)
@@ -230,13 +230,13 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
assert_equal(cal.events.count, 4)
assert_equal(cal.events[0].dtstart, Time.zone.today)
- assert_equal(cal.events[0].summary, 'new ticket: \'some title1 - new - group_calendar\'')
- assert_equal(cal.events[0].description, "T##{ticket1.number}")
+ assert_equal(cal.events[0].summary, 'new ticket: \'some title1 - escalation - group_calendar\'')
+ assert_equal(cal.events[0].description, "T##{ticket5.number}")
assert_equal(cal.events[0].has_alarm?, false)
assert_equal(cal.events[1].dtstart, Time.zone.today)
- assert_equal(cal.events[1].summary, 'new ticket: \'some title1 - escalation - group_calendar\'')
- assert_equal(cal.events[1].description, "T##{ticket5.number}")
+ assert_equal(cal.events[1].summary, 'new ticket: \'some title1 - new - group_calendar\'')
+ assert_equal(cal.events[1].description, "T##{ticket1.number}")
assert_equal(cal.events[1].has_alarm?, false)
assert_equal(cal.events[2].dtstart, Time.zone.today)
@@ -279,23 +279,23 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
assert_equal(cal.events.count, 8)
assert_equal(cal.events[0].dtstart, Time.zone.today)
- assert_equal(cal.events[0].summary, 'new ticket: \'some title2 - new - group_calendar\'')
- assert_equal(cal.events[0].description, "T##{ticket7.number}")
+ assert_equal(cal.events[0].summary, 'new ticket: \'some title2 - escalation - group_calendar\'')
+ assert_equal(cal.events[0].description, "T##{ticket11.number}")
assert_equal(cal.events[0].has_alarm?, false)
assert_equal(cal.events[1].dtstart, Time.zone.today)
- assert_equal(cal.events[1].summary, 'new ticket: \'some title2 - escalation - group_calendar\'')
- assert_equal(cal.events[1].description, "T##{ticket11.number}")
+ assert_equal(cal.events[1].summary, 'new ticket: \'some title2 - new - group_calendar\'')
+ assert_equal(cal.events[1].description, "T##{ticket7.number}")
assert_equal(cal.events[1].has_alarm?, false)
assert_equal(cal.events[2].dtstart, Time.zone.today)
- assert_equal(cal.events[2].summary, 'new ticket: \'some title1 - new - group_calendar\'')
- assert_equal(cal.events[2].description, "T##{ticket1.number}")
+ assert_equal(cal.events[2].summary, 'new ticket: \'some title1 - escalation - group_calendar\'')
+ assert_equal(cal.events[2].description, "T##{ticket5.number}")
assert_equal(cal.events[2].has_alarm?, false)
assert_equal(cal.events[3].dtstart, Time.zone.today)
- assert_equal(cal.events[3].summary, 'new ticket: \'some title1 - escalation - group_calendar\'')
- assert_equal(cal.events[3].description, "T##{ticket5.number}")
+ assert_equal(cal.events[3].summary, 'new ticket: \'some title1 - new - group_calendar\'')
+ assert_equal(cal.events[3].description, "T##{ticket1.number}")
assert_equal(cal.events[3].has_alarm?, false)
assert_equal(cal.events[4].dtstart, Time.zone.today)
@@ -329,12 +329,12 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
assert_equal(cal.events.count, 4)
assert_equal(cal.events[0].dtstart, Time.zone.today)
- assert_equal(cal.events[0].summary, 'new ticket: \'some title1 - new - group_default\'')
- assert_equal(cal.events[0].description, "T##{ticket2.number}")
+ assert_equal(cal.events[0].summary, 'new ticket: \'some title1 - escalation - group_default\'')
+ assert_equal(cal.events[0].description, "T##{ticket6.number}")
assert_equal(cal.events[1].dtstart, Time.zone.today)
- assert_equal(cal.events[1].summary, 'new ticket: \'some title1 - escalation - group_default\'')
- assert_equal(cal.events[1].description, "T##{ticket6.number}")
+ assert_equal(cal.events[1].summary, 'new ticket: \'some title1 - new - group_default\'')
+ assert_equal(cal.events[1].description, "T##{ticket2.number}")
assert_equal(cal.events[2].dtstart, Time.zone.today)
assert_equal(cal.events[2].summary, 'pending reminder ticket: \'some title1 - pending - group_default\' customer: Notification Customer1 (Selector Org)')
@@ -374,23 +374,23 @@ class CalendarSubscriptionTest < ActiveSupport::TestCase
assert_equal(cal.events.count, 8)
assert_equal(cal.events[0].dtstart, Time.zone.today)
- assert_equal(cal.events[0].summary, 'new ticket: \'some title2 - new - group_default\'')
- assert_equal(cal.events[0].description, "T##{ticket8.number}")
+ assert_equal(cal.events[0].summary, 'new ticket: \'some title2 - escalation - group_default\'')
+ assert_equal(cal.events[0].description, "T##{ticket12.number}")
assert_equal(cal.events[0].has_alarm?, false)
assert_equal(cal.events[1].dtstart, Time.zone.today)
- assert_equal(cal.events[1].summary, 'new ticket: \'some title2 - escalation - group_default\'')
- assert_equal(cal.events[1].description, "T##{ticket12.number}")
+ assert_equal(cal.events[1].summary, 'new ticket: \'some title2 - new - group_default\'')
+ assert_equal(cal.events[1].description, "T##{ticket8.number}")
assert_equal(cal.events[1].has_alarm?, false)
assert_equal(cal.events[2].dtstart, Time.zone.today)
- assert_equal(cal.events[2].summary, 'new ticket: \'some title1 - new - group_default\'')
- assert_equal(cal.events[2].description, "T##{ticket2.number}")
- assert_equal(cal.events[1].has_alarm?, false)
+ assert_equal(cal.events[2].summary, 'new ticket: \'some title1 - escalation - group_default\'')
+ assert_equal(cal.events[2].description, "T##{ticket6.number}")
+ assert_equal(cal.events[2].has_alarm?, false)
assert_equal(cal.events[3].dtstart, Time.zone.today)
- assert_equal(cal.events[3].summary, 'new ticket: \'some title1 - escalation - group_default\'')
- assert_equal(cal.events[3].description, "T##{ticket6.number}")
+ assert_equal(cal.events[3].summary, 'new ticket: \'some title1 - new - group_default\'')
+ assert_equal(cal.events[3].description, "T##{ticket2.number}")
assert_equal(cal.events[3].has_alarm?, false)
assert_equal(cal.events[4].dtstart, Time.zone.today)
diff --git a/test/unit/email_process_follow_up_test.rb b/test/unit/email_process_follow_up_test.rb
index 353c6d8e4..b6e9a1011 100644
--- a/test/unit/email_process_follow_up_test.rb
+++ b/test/unit/email_process_follow_up_test.rb
@@ -85,45 +85,45 @@ no reference "
Setting.set('postmaster_follow_up_search_in', %w(body attachment references))
sleep 1
- ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string_subject)
+ ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_subject)
assert_equal(ticket.id, ticket_p.id)
sleep 1
- ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string_body)
+ ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_body)
assert_equal(ticket.id, ticket_p.id)
sleep 1
- ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string_attachment)
+ ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_attachment)
assert_equal(ticket.id, ticket_p.id)
sleep 1
- ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string_references1)
+ ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references1)
assert_equal(ticket.id, ticket_p.id)
sleep 1
- ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string_references2)
+ ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references2)
assert_equal(ticket.id, ticket_p.id)
Setting.set('postmaster_follow_up_search_in', setting_orig)
sleep 1
- ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string_subject)
+ ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_subject)
assert_equal(ticket.id, ticket_p.id)
sleep 1
- ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string_body)
+ ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_body)
assert_not_equal(ticket.id, ticket_p.id)
sleep 1
- ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string_attachment)
+ ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_attachment)
assert_not_equal(ticket.id, ticket_p.id)
sleep 1
- ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string_references1)
+ ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references1)
assert_not_equal(ticket.id, ticket_p.id)
sleep 1
- ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string_references2)
+ ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string_references2)
assert_not_equal(ticket.id, ticket_p.id)
end
@@ -165,7 +165,51 @@ Auto-Submitted: auto-replied
Some Text"
- ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process( {}, email_raw_string)
+ ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
+ ticket = Ticket.find(ticket.id)
+ assert_equal(ticket.id, ticket_p.id)
+ assert_equal('open', ticket.state.name)
+ end
+
+ test 'process with follow up check - email with more forgein T#\'s in subject' do
+
+ ticket = Ticket.create(
+ title: 'email with more forgein T#\'s in subject',
+ group: Group.lookup(name: 'Users'),
+ customer_id: 2,
+ state: Ticket::State.lookup(name: 'closed'),
+ priority: Ticket::Priority.lookup(name: '2 normal'),
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+ article = Ticket::Article.create(
+ ticket_id: ticket.id,
+ from: 'some_sender@example.com',
+ to: 'some_recipient@example.com',
+ subject: 'follow up with references follow up check',
+ message_id: '<20151222145601.30.608881@edenhofer.zammad.com>',
+ body: 'some message with references follow up check',
+ internal: false,
+ sender: Ticket::Article::Sender.lookup(name: 'Agent'),
+ type: Ticket::Article::Type.lookup(name: 'email'),
+ updated_by_id: 1,
+ created_by_id: 1,
+ )
+ sleep 1
+
+ system_id = Setting.get('system_id')
+ ticket_hook = Setting.get('ticket_hook')
+ ticket_hook_divider = Setting.get('ticket_hook_divider')
+
+ tn = "[#{ticket_hook}#{ticket_hook_divider}#{system_id}#{Ticket::Number.generate}99]"
+
+ email_raw_string_subject = "From: me@example.com
+To: customer@example.com
+Subject: First foreign Tn #{tn} #{tn} #{tn} - #{ticket.subject_build('some new subject')}
+
+Some Text"
+
+ ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string_subject)
ticket = Ticket.find(ticket.id)
assert_equal(ticket.id, ticket_p.id)
assert_equal('open', ticket.state.name)
diff --git a/test/unit/job_test.rb b/test/unit/job_test.rb
new file mode 100644
index 000000000..63c8c1b13
--- /dev/null
+++ b/test/unit/job_test.rb
@@ -0,0 +1,725 @@
+# 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.next_run_at)
+ 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?)
+
+ job1.active = false
+ job1.save
+ assert_not(job1.executable?)
+
+ job1.active = true
+ job1.save
+ assert_not(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 < 60
+ 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.next_run_at)
+ 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
+
+ test 'case 3' do
+
+ # create jobs
+ job1 = Job.create_or_update(
+ name: 'Test Job1',
+ timeplan: {
+ days: {
+ Mon: true,
+ Tue: false,
+ Wed: false,
+ Thu: false,
+ Fri: true,
+ Sat: false,
+ Sun: false,
+ },
+ hours: {
+ 0 => false,
+ 1 => true,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => true,
+ 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 => true,
+ 10 => false,
+ 20 => false,
+ 30 => false,
+ 40 => true,
+ 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,
+ )
+
+ time_now = Time.zone.parse('2016-03-18 09:17:13 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-18 10:00:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-18 10:37:13 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-18 10:40:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-17 09:17:13 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-18 01:00:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-17 11:17:13 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-18 01:00:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-19 11:17:13 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-21 01:00:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-22 00:59:59 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-25 01:00:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-25 00:59:59 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-25 01:00:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-24 00:59:59 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-25 01:00:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-24 23:59:59 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-25 01:00:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-25 01:00:01 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-25 01:00:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-25 01:09:01 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-25 01:40:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-25 01:09:59 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-25 01:40:00 UTC', next_run_at.to_s)
+
+ job1.last_run_at = Time.zone.parse('2016-03-18 10:00:01 UTC')
+ job1.save
+ time_now = Time.zone.parse('2016-03-18 10:00:02 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-18 10:40:00 UTC', next_run_at.to_s)
+
+ job1.last_run_at = Time.zone.parse('2016-03-18 10:40:01 UTC')
+ job1.save
+ time_now = Time.zone.parse('2016-03-18 10:40:02 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-21 01:00:00 UTC', next_run_at.to_s)
+
+ end
+
+ test 'case 4' do
+
+ # create jobs
+ job1 = Job.create_or_update(
+ name: 'Test Job1',
+ timeplan: {
+ days: {
+ Mon: true,
+ Tue: false,
+ Wed: false,
+ Thu: false,
+ Fri: true,
+ Sat: false,
+ Sun: false,
+ },
+ hours: {
+ 0 => true,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => true,
+ 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 => true,
+ 10 => false,
+ 20 => false,
+ 30 => false,
+ 40 => true,
+ 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,
+ )
+
+ time_now = Time.zone.parse('2016-03-17 23:51:23 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-18 00:00:00 UTC', next_run_at.to_s)
+
+ job1.last_run_at = Time.zone.parse('2016-03-17 23:45:01 UTC')
+ job1.save
+ time_now = Time.zone.parse('2016-03-17 23:51:23 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-18 00:00:00 UTC', next_run_at.to_s)
+
+ job1.last_run_at = Time.zone.parse('2016-03-17 23:59:01 UTC')
+ job1.save
+ time_now = Time.zone.parse('2016-03-17 23:59:23 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-18 00:40:00 UTC', next_run_at.to_s)
+
+ time_now = Time.zone.parse('2016-03-17 23:59:23 UTC')
+ assert_not(job1.in_timeplan?(time_now))
+
+ time_now = Time.zone.parse('2016-03-18 00:01:23 UTC')
+ assert(job1.in_timeplan?(time_now))
+
+ end
+
+ test 'case 5' do
+
+ # create jobs
+ job1 = Job.create_or_update(
+ name: 'Test Job1',
+ timeplan: {
+ days: {
+ Mon: true,
+ Tue: false,
+ Wed: false,
+ Thu: false,
+ Fri: false,
+ Sat: false,
+ Sun: false,
+ },
+ hours: {
+ '0' => true,
+ '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' => true,
+ '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,
+ )
+
+ time_now = Time.zone.parse('2016-03-17 23:51:23 UTC')
+ next_run_at = job1.next_run_at_calculate(time_now)
+ assert_equal('2016-03-21 00:00:00 UTC', next_run_at.to_s)
+
+ end
+
+end
diff --git a/test/unit/ticket_selector_test.rb b/test/unit/ticket_selector_test.rb
index 32d63631e..6e4e69c4e 100644
--- a/test/unit/ticket_selector_test.rb
+++ b/test/unit/ticket_selector_test.rb
@@ -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' => {