Browse Source

Init version of scheduler.

Martin Edenhofer 10 years ago
parent
commit
51d485670e

+ 379 - 40
app/assets/javascripts/app/controllers/_application_controller_form.js.coffee

@@ -923,18 +923,286 @@ class App.ControllerForm extends App.Controller
       item.find( "[name=\"#{attribute.name}::count\"]").find("option[value=\"#{attribute.value.count}\"]").attr( 'selected', 'selected' )
       item.find( "[name=\"#{attribute.name}::area\"]").find("option[value=\"#{attribute.value.area}\"]").attr( 'selected', 'selected' )
 
+    # ticket attribute set
+    else if attribute.tag is 'ticket_attribute_set'
+
+      # list of possible attributes
+      item = $(
+        App.view('generic/ticket_attribute_manage')(
+          attribute: attribute
+        )
+      )
+
+      addShownAttribute = ( key, value ) =>
+        parts = key.split(/::/)
+        key   = parts[0]
+        type  = parts[1]
+        if key is 'tickets.title'
+          attribute_config = {
+            name:       attribute.name + '::tickets.title'
+            display:    'Title'
+            tag:        'input'
+            type:       'text'
+            null:       false
+            value:      value
+            remove:     true
+          }
+        else if key is 'tickets.group_id'
+          attribute_config = {
+            name:       attribute.name + '::tickets.group_id'
+            display:    'Group'
+            tag:        'select'
+            multiple:   false
+            null:       false
+            nulloption: false
+            relation:   'Group'
+            value:      value
+            remove:     true
+          }
+        else if key is 'tickets.owner_id' || key is 'tickets.customer_id'
+          display = 'Owner'
+          name    = 'owner_id'
+          if key is 'customer_id'
+            display = 'Customer'
+            name    = 'customer_id'
+          attribute_config = {
+            name:       attribute.name + '::tickets.' + name
+            display:    display
+            tag:        'select'
+            multiple:   false
+            null:       false
+            nulloption: false
+            relation:   'User'
+            value:      value || null
+            remove:     true
+            filter:     ( all, type ) ->
+              return all if type isnt 'collection'
+              all = _.filter( all, (item) ->
+                return if item.id is 1
+                return item
+              )
+              all.unshift( {
+                id: ''
+                name:  '--'
+              } )
+              all.unshift( {
+                id: 1
+                name:  '*** not set ***'
+              } )
+              all.unshift( {
+                id: 'current_user.id'
+                name:  '*** current user ***'
+              } )
+              all
+          }
+        else if key is 'tickets.organization_id'
+          attribute_config = {
+            name:       attribute.name + '::tickets.organization_id'
+            display:    'Organization'
+            tag:        'select'
+            multiple:   false
+            null:       false
+            nulloption: false
+            relation:   'Organization'
+            value:      value || null
+            remove:     true
+            filter:     ( all, type ) ->
+              return all if type isnt 'collection'
+              all.unshift( {
+                id: ''
+                name:  '--'
+              } )
+              all.unshift( {
+                id: 'current_user.organization_id'
+                name:  '*** organization of current user ***'
+              } )
+              all
+          }
+        else if key is 'tickets.state_id'
+          attribute_config = {
+            name:       attribute.name + '::tickets.state_id'
+            display:    'State'
+            tag:        'select'
+            multiple:   false
+            null:       false
+            nulloption: false
+            relation:   'TicketState'
+            value:      value
+            translate:  true
+            remove:     true
+          }
+        else if key is 'tickets.priority_id'
+          attribute_config = {
+            name:       attribute.name + '::tickets.priority_id'
+            display:    'Priority'
+            tag:        'select'
+            multiple:   false
+            null:       false
+            nulloption: false
+            relation:   'TicketPriority'
+            value:      value
+            translate:  true
+            remove:     true
+          }
+        else
+          attribute_config = {
+            name:       attribute.name + '::' + key
+            display:    'FIXME!'
+            tag:        'input'
+            type:       'text'
+            value:      value
+            remove:     true
+          }
+        item.find('select[name=ticket_attribute_list] option[value="' + key + '"]').hide().prop('disabled', true)
+
+        itemSub = @formGenItem( attribute_config )
+        itemSub.find('.glyphicon-minus').bind('click', (e) ->
+          e.preventDefault()
+          value = $(e.target).closest('.controls').find('[name]').attr('name')
+          if value
+            value = value.replace("#{attribute.name}::", '')
+            $(e.target).closest('.sub_attribute').find('select[name=ticket_attribute_list] option[value="' + value + '"]').show().prop('disabled', false)
+          $(@).parent().parent().parent().remove()
+        )
+#        itemSub.append('<a href=\"#\" class=\"icon-minus\"></a>')
+        item.find('.ticket_attribute_item').append( itemSub )
+
+      # list of existing attributes
+      attribute_config = {
+        name:       'ticket_attribute_list'
+        display:    'Add Attribute'
+        tag:        'select'
+        multiple:   false
+        null:       false
+#        nulloption: true
+        options: [
+          {
+            value:    ''
+            name:     '-- Ticket --'
+            selected: false
+            disable:  true
+          },
+          {
+            value:    'tickets.title'
+            name:     'Title'
+            selected: false
+            disable:  false
+          },
+          {
+            value:    'tickets.group_id'
+            name:     'Group'
+            selected: false
+            disable:  false
+          },
+          {
+            value:    'tickets.state_id'
+            name:     'State'
+            selected: false
+            disable:  false
+          },
+          {
+            value:    'tickets.priority_id'
+            name:     'Priority'
+            selected: true
+            disable:  false
+          },
+          {
+            value:    'tickets.owner_id'
+            name:     'Owner'
+            selected: true
+            disable:  false
+          },
+#         # {
+#            value:    'tag'
+#            name:     'Tag'
+#            selected: true
+#            disable:  false
+#          },
+#          {
+#            value:    '-a'
+#            name:     '-- ' + App.i18n.translateInline('Article') + ' --'
+#            selected: false
+#            disable:  true
+#          },
+#          {
+#            value:    'ticket_articles.from'
+#            name:     'From'
+#            selected: true
+#            disable:  false
+#          },
+#          {
+#            value:    'ticket_articles.to'
+#            name:     'To'
+#            selected: true
+#            disable:  false
+#          },
+#          {
+#            value:    'ticket_articles.cc'
+#            name:     'Cc'
+#            selected: true
+#            disable:  false
+#          },
+#          {
+#            value:    'ticket_articles.subject'
+#            name:     'Subject'
+#            selected: true
+#            disable:  false
+#          },
+#          {
+#            value:    'ticket_articles.body'
+#            name:     'Text'
+#            selected: true
+#            disable:  false
+#          },
+          {
+            value:    '-c'
+            name:     '-- ' + App.i18n.translateInline('Customer') + ' --'
+            selected: false
+            disable:  true
+          },
+          {
+            value:    'customers.id'
+            name:     'Customer'
+            selected: true
+            disable:  false
+          },
+          {
+            value:    'organization.id'
+            name:     'Organization'
+            selected: true
+            disable:  false
+          },
+        ]
+        default:    ''
+        translate:  true
+        class:      'medium'
+        add:        true
+      }
+      list = @formGenItem( attribute_config )
+      list.find('.glyphicon-plus').bind('click', (e) ->
+        e.preventDefault()
+        value = $(e.target).closest('.controls').find('[name=ticket_attribute_list]').val()
+        addShownAttribute( value, '' )
+      )
+      item.find('.ticket_attribute_list').prepend( list )
+
+      # list of shown attributes
+      show = []
+      if attribute.value
+        for key, value of attribute.value
+          addShownAttribute( key, value )
+
     # ticket attribute selection
     else if attribute.tag is 'ticket_attribute_selection'
 
       # list of possible attributes
       item = $(
-        App.view('generic/ticket_attribute_selection')(
+        App.view('generic/ticket_attribute_manage')(
           attribute: attribute
         )
       )
 
       addShownAttribute = ( key, value ) =>
-        console.log( 'addShownAttribute', key, value )
         parts = key.split(/::/)
         key   = parts[0]
         type  = parts[1]
@@ -946,7 +1214,6 @@ class App.ControllerForm extends App.Controller
             type:       'text'
             null:       false
             value:      value
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.title'
@@ -957,7 +1224,6 @@ class App.ControllerForm extends App.Controller
             type:       'text'
             null:       false
             value:      value
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.group_id'
@@ -970,7 +1236,6 @@ class App.ControllerForm extends App.Controller
             nulloption: false
             relation:   'Group'
             value:      value
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.owner_id' || key is 'tickets.customer_id'
@@ -988,7 +1253,6 @@ class App.ControllerForm extends App.Controller
             nulloption: false
             relation:   'User'
             value:      value || null
-            class:      'medium'
             remove:     true
             filter:     ( all, type ) ->
               return all if type isnt 'collection'
@@ -1020,7 +1284,6 @@ class App.ControllerForm extends App.Controller
             nulloption: false
             relation:   'Organization'
             value:      value || null
-            class:      'medium'
             remove:     true
             filter:     ( all, type ) ->
               return all if type isnt 'collection'
@@ -1045,7 +1308,6 @@ class App.ControllerForm extends App.Controller
             relation:   'TicketState'
             value:      value
             translate:  true
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.priority_id'
@@ -1059,7 +1321,6 @@ class App.ControllerForm extends App.Controller
             relation:   'TicketPriority'
             value:      value
             translate:  true
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.created_at' && ( type is '<>' || value.count )
@@ -1069,7 +1330,6 @@ class App.ControllerForm extends App.Controller
             tag:        'time_before_last'
             value:      value
             translate:  true
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.created_at' && ( type is '><' || 0 )
@@ -1079,7 +1339,6 @@ class App.ControllerForm extends App.Controller
             tag:        'time_range'
             value:      value
             translate:  true
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.close_time' && ( type is '<>' || value.count )
@@ -1089,7 +1348,6 @@ class App.ControllerForm extends App.Controller
             tag:        'time_before_last'
             value:      value
             translate:  true
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.close_time' && ( type is '><' || 0 )
@@ -1099,7 +1357,6 @@ class App.ControllerForm extends App.Controller
             tag:        'time_range'
             value:      value
             translate:  true
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.updated_at' && ( type is '<>' || value.count )
@@ -1109,7 +1366,6 @@ class App.ControllerForm extends App.Controller
             tag:        'time_before_last'
             value:      value
             translate:  true
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.updated_at' && ( type is '><' || 0 )
@@ -1119,7 +1375,6 @@ class App.ControllerForm extends App.Controller
             tag:        'time_range'
             value:      value
             translate:  true
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.escalation_time' && ( type is '<>' || value.count )
@@ -1129,7 +1384,6 @@ class App.ControllerForm extends App.Controller
             tag:        'time_before_last'
             value:      value
             translate:  true
-            class:      'medium'
             remove:     true
           }
         else if key is 'tickets.escalation_time' && ( type is '><' || 0 )
@@ -1139,7 +1393,6 @@ class App.ControllerForm extends App.Controller
             tag:        'time_range'
             value:      value
             translate:  true
-            class:      'medium'
             remove:     true
           }
         else
@@ -1149,24 +1402,23 @@ class App.ControllerForm extends App.Controller
             tag:        'input'
             type:       'text'
             value:      value
-            class:      'medium'
             remove:     true
           }
+
+        item.find('select[name=ticket_attribute_list] option[value="' + key + '"]').hide().prop('disabled', true)
+
         itemSub = @formGenItem( attribute_config )
         itemSub.find('.glyphicon-minus').bind('click', (e) ->
           e.preventDefault()
+          value = $(e.target).closest('.controls').find('[name]').attr('name')
+          if value
+            value = value.replace("#{attribute.name}::", '')
+            $(e.target).closest('.sub_attribute').find('select[name=ticket_attribute_list] option[value="' + value + '"]').show().prop('disabled', false)
           $(@).parent().parent().parent().remove()
         )
 #        itemSub.append('<a href=\"#\" class=\"icon-minus\"></a>')
         item.find('.ticket_attribute_item').append( itemSub )
 
-
-      # list of shown attributes
-      show = []
-      if attribute.value
-        for key, value of attribute.value
-          addShownAttribute( key, value )
-
       # list of existing attributes
       attribute_config = {
         name:       'ticket_attribute_list'
@@ -1182,19 +1434,18 @@ class App.ControllerForm extends App.Controller
             selected: false
             disable:  true
           },
-          #
-          #{
-          #  value:    'tickets.number'
-          #  name:     'Number'
-          #  selected: true
-          #  disable:  false
-          #},
-          #{
-          #  value:    'tickets.title'
-          #  name:     'Title'
-          #  selected: true
-          #  disable:  false
-          #},
+          {
+            value:    'tickets.number'
+            name:     'Number'
+            selected: false
+            disable:  false
+          },
+          {
+            value:    'tickets.title'
+            name:     'Title'
+            selected: false
+            disable:  false
+          },
           {
             value:    'tickets.group_id'
             name:     'Group'
@@ -1373,12 +1624,100 @@ class App.ControllerForm extends App.Controller
 
       list.find('.glyphicon-plus').bind('click', (e) ->
         e.preventDefault()
-
-        value = $(e.target).parents().find('[name=ticket_attribute_list]').val()
+        value = $(e.target).closest('.controls').find('[name=ticket_attribute_list]').val()
         addShownAttribute( value, '' )
       )
       item.find('.ticket_attribute_list').prepend( list )
 
+      # list of shown attributes
+      show = []
+      if attribute.value
+        for key, value of attribute.value
+          addShownAttribute( key, value )
+
+    # timeplan
+    else if attribute.tag is 'timeplan'
+      item = $( App.view('generic/timeplan')( attribute: attribute ) )
+      attribute_config = {
+        name:     "#{attribute.name}::days"
+        tag:      'select'
+        multiple: true
+        null:     false
+        options:  [
+          {
+            value:    'mon'
+            name:     'Monday'
+            selected: false
+            disable:  false
+          },
+          {
+            value:    'tue'
+            name:     'Tuesday'
+            selected: false
+            disable:  false
+          },
+          {
+            value:    'wed'
+            name:     'Wednesday'
+            selected: false
+            disable:  false
+          },
+          {
+            value:    'thu'
+            name:     'Thursday'
+            selected: false
+            disable:  false
+          },
+          {
+            value:    'fri'
+            name:     'Friday'
+            selected: false
+            disable:  false
+          },
+          {
+            value:    'sat'
+            name:     'Saturday'
+            selected: false
+            disable:  false
+          },
+          {
+            value:    'sun'
+            name:     'Sunday'
+            selected: false
+            disable:  false
+          },
+        ]
+        default:  attribute.default?.days
+      }
+      item.find('.days').append( @formGenItem( attribute_config ) )
+
+      hours = {}
+      for hour in [0..23]
+        localHour = "0#{hour}"
+        hours[hour] = localHour.substr(localHour.length-2,2)
+      attribute_config = {
+        name:     "#{attribute.name}::hours"
+        tag:      'select'
+        multiple: true
+        null:     false
+        options:  hours
+        default:  attribute.default?.hours
+      }
+      item.find('.hours').append( @formGenItem( attribute_config ) )
+
+      minutes = {}
+      for minute in [0..5]
+        minutes["#{minute}0"] = "#{minute}0"
+      attribute_config = {
+        name:     "#{attribute.name}::minutes"
+        tag:      'select'
+        multiple: true
+        null:     false
+        options:  minutes
+        default:  attribute.default?.miuntes
+      }
+      item.find('.minutes').append( @formGenItem( attribute_config ) )
+
     # input
     else
       item = $( App.view('generic/input')( attribute: attribute ) )

+ 18 - 12
app/assets/javascripts/app/controllers/scheduler.js.coffee

@@ -5,17 +5,23 @@ class Index extends App.ControllerContent
     # check authentication
     return if !@authenticate()
 
-    # set title
-    @title 'Scheduler'
-    @navupdate '#scheduler'
-
-    # render page
-    @render()
-
-  render: ->
-
-    @html App.view('scheduler')(
-      head: 'some header'
+    new App.ControllerGenericIndex(
+      el: @el,
+      id: @id,
+      genericObject: 'Job',
+      pageData: {
+        title: 'Schedulers',
+        home: 'schedulers',
+        object: 'Scheduler',
+        objects: 'Schedulers',
+        navupdate: '#schedulers',
+        notes: [
+          'Scheduler are ...'
+        ],
+        buttons: [
+          { name: 'New Scheduler', 'data-type': 'new', class: 'btn--success' },
+        ],
+      },
     )
 
-App.Config.set( 'Scheduler', { prio: 2000, name: 'Schedulers', parent: '#manage', target: '#manage/schedulers', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )
+App.Config.set( 'Scheduler', { prio: 3000, name: 'Schedulers', parent: '#manage', target: '#manage/schedulers', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

+ 1 - 5
app/assets/javascripts/app/controllers/trigger.js.coffee

@@ -18,8 +18,4 @@ class Index extends App.ControllerContent
       head: 'some header'
     )
 
-#App.Config.set( 'trigger', Index, 'Routes' )
-#App.Config.set( 'Trigger', { prio: 3000, parent: '#admin', name: 'Trigger', target: '#trigger', role: ['Admin'] }, 'NavBar' )
-
-App.Config.set( 'Trigger', { prio: 3000, name: 'Triggers', target: '#manage/triggers', controller: Index, role: ['Admin'] }, 'NavBarLevel2' )
-
+App.Config.set( 'Trigger', { prio: 3100, name: 'Triggers', parent: '#manage', target: '#manage/triggers', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

+ 27 - 0
app/assets/javascripts/app/models/job.js.coffee

@@ -0,0 +1,27 @@
+class App.Job extends App.Model
+  @configure 'Job', 'name', 'timeplan', 'condition', 'execute', '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_attribute_selection', null: true },
+    { name: 'execute',        display: 'Execute changes on objects.', tag: 'ticket_attribute_set', 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: 'boolean',  note: 'boolean', 'default': true, null: false },
+    { name: 'matching',       display: 'Matching',    readonly: 1 },
+    { name: 'processed',      display: 'Processed',    readonly: 1 },
+    { name: 'last_run_at',    display: 'Last run',    type: 'time', 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',     type: 'time', readonly: 1 },
+    { name: 'updated_by_id',  display: 'Updated by',  relation: 'User', readonly: 1 },
+    { name: 'updated_at',     display: 'Updated',     type: 'time', readonly: 1 },
+  ]
+  @configure_delete = true
+  @configure_overview = [
+    'name',
+    'last_run_at',
+    'matching',
+    'processed',
+  ]

+ 1 - 2
app/assets/javascripts/app/views/generic/ticket_attribute_selection.jst.eco → app/assets/javascripts/app/views/generic/ticket_attribute_manage.jst.eco

@@ -2,5 +2,4 @@
 	<div class="ticket_attribute_item"></div>
 	<hr>
 	<div class="ticket_attribute_list"></div>
-</div>
-
+</div>

+ 11 - 0
app/assets/javascripts/app/views/generic/timeplan.jst.eco

@@ -0,0 +1,11 @@
+<div>
+  <label><%- @T('Days') %>
+    <div class="days"></div>
+  </label>
+  <label><%- @T('Hours') %>
+    <div class="hours"></div>
+  </label>
+  <label><%- @T('Minutes') %>
+    <div class="minutes"></div>
+  </label>
+</div>

+ 0 - 91
app/assets/javascripts/app/views/scheduler.jst.eco

@@ -1,91 +0,0 @@
-<div class="page-header-title">
-  <h1>Scheduler <small>Management</small></h1>
-</div>
-
-<ul class="nav nav-tabs nav-stacked">
-  <li><a href="#">Jobs</a></li>
-</ul>
-
-<div class="table-overview">
-  <div class="tabbable">
-    <ul class="nav nav-tabs">
-      <li class="active"><a href="#channel-inbound" data-toggle="tab">Times</a></li>
-      <li><a href="#channel-outbound" data-toggle="tab">Properties</a></li>
-      <li><a href="#channel-filter" data-toggle="tab">Message</a></li>
-    </ul>
-    <div class="tab-content">
-      <div class="tab-pane active" id="channel-inbound">         
-        <table class="table table-striped">
-          <tr>
-            <th>Host</th>
-            <th>User</th>
-            <th>Type</th>
-            <th>Active</th>
-            <th>Delete</th>
-          </tr>
-          <tr> 
-            <td>lalal.example.com</td>
-            <td>wpt234rwr</td>
-            <td>IMAP</td>
-            <td>true</td>
-            <td>x</td>
-          </tr>
-          <tr> 
-            <td>l31alal.example.com</td>
-            <td>wpt23dd4rwr</td>
-            <td>POP3</td>
-            <td>true</td>
-            <td>x</td>
-          </tr>
-        </table>
-      </div>
-      <div class="tab-pane" id="channel-outbound">
-        <table class="table table-striped">
-          <tr>
-            <th>Host</th>
-            <th>User</th>
-            <th>Type</th>
-            <th>Active</th>
-            <th>Delete</th>
-          </tr>
-          <tr> 
-            <td>lalal.example.com</td>
-            <td>wpt234rwr</td>
-            <td>SMTP</td>
-            <td>true</td>
-            <td>x</td>
-          </tr>
-          <tr> 
-            <td>l31alal.example.com</td>
-            <td>wpt23dd4rwr</td>
-            <td>Sendmail</td>
-            <td>true</td>
-            <td>x</td>
-          </tr>
-        </table>
-      </div>
-      <div class="tab-pane" id="channel-filter">
-        <table class="table table-striped">
-          <tr>
-            <th>Name</th>
-            <th>Active</th>
-            <th>Last Run</th>
-            <th>Delete</th>
-          </tr>
-          <tr> 
-            <td>lalal.example.com</td>
-            <td>true</td>
-            <td>true</td>
-            <td>x</td>
-          </tr>
-          <tr> 
-            <td>wpt23dd4rwr</td>
-            <td>true</td>
-            <td>true</td>
-            <td>x</td>
-          </tr>
-        </table>
-      </div>
-    </div>
-  </div>
-</div>

+ 7 - 0
app/controllers/tests_controller.rb

@@ -23,6 +23,13 @@ class TestsController < ApplicationController
     end
   end
 
+  # GET /tests/from_extended
+  def form
+    respond_to do |format|
+      format.html # index.html.erb
+    end
+  end
+
   # GET /tests/table
   def table
     respond_to do |format|

+ 88 - 0
app/models/job.rb

@@ -0,0 +1,88 @@
+# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
+
+class Job < ApplicationModel
+  store     :timeplan
+  store     :condition
+  store     :execute
+  validates :name, :presence => true
+
+  before_create   :updated_matching
+  before_update   :updated_matching
+
+  after_create    :notify_clients_after_create
+  after_update    :notify_clients_after_update
+  after_destroy   :notify_clients_after_destroy
+
+  def self.run
+    time    = Time.new
+    day_map = {
+      0 => 'sun',
+      1 => 'mon',
+      2 => 'tue',
+      3 => 'wed',
+      4 => 'thu',
+      5 => 'fri',
+      6 => 'sat',
+    }
+    jobs = Job.where( :active => true )
+    jobs.each do |job|
+
+      # only execute jobs, older then 2 min, to give admin posibility to change
+      next if job.updated_at > Time.now - 2.minutes
+
+      # check if jobs need to be executed
+      # ignore if job was running within last 10 min.
+      next if job.last_run_at > Time.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|
+        #puts "CHANGE #{job.execute.inspect}"
+        changed = false
+        job.execute.each do |key, value|
+          changed = true
+          attribute = key.split('.', 2).last
+          #puts "-- #{Ticket.columns_hash[ attribute ].type.to_s}"
+          #value = 4
+          #if Ticket.columns_hash[ attribute ].type == :integer
+          #  puts "to i #{attribute}/#{value.inspect}/#{value.to_i.inspect}"
+          #  #value = value.to_i
+          #end
+          ticket[attribute] = value
+          #puts "set #{attribute} = #{value.inspect}"
+        end
+        next if !changed
+        ticket.updated_by_id = 1
+        ticket.save
+      end
+
+      job.last_run_at = Time.now
+      job.save
+    end
+    true
+  end
+
+  private
+
+  def updated_matching
+    count = Ticket.where( self.condition.permit! ).count
+    self.matching = count
+  end
+
+  def self.match_minutes(minutes)
+    minutes.gsub!(/(\d)\d/, "\\1")
+    minutes.to_s + '0'
+  end
+end

+ 1 - 1
app/models/overview.rb

@@ -7,4 +7,4 @@ class Overview < ApplicationModel
   validates :name, :presence => true
   validates :prio, :presence => true
   validates :link, :presence => true
-end
+end

Some files were not shown because too many files changed in this diff