Просмотр исходного кода

Fixed issue #645 - Dashboard widget "Waiting time today" is not counting.

Rolf Schmidt 8 лет назад
Родитель
Сommit
c5c6876054

+ 13 - 15
app/assets/javascripts/app/controllers/_dashboard/stats.coffee

@@ -12,8 +12,8 @@ class App.DashboardStats extends App.Controller
       @render()
 
   render: (data = {}) ->
-    if !data.TicketResponseTime
-      data.TicketResponseTime =
+    if !data.StatsTicketWaitingTime
+      data.StatsTicketWaitingTime =
         handling_time: 0
         average: 0
         average_per_agent: 0
@@ -60,10 +60,10 @@ class App.DashboardStats extends App.Controller
 
     @html App.view('dashboard/stats')(data)
 
-    if data.TicketResponseTime
-      @renderWidgetClockFace data.TicketResponseTime.handling_time
+    if data.StatsTicketWaitingTime
+      @renderWidgetClockFace data.StatsTicketWaitingTime.handling_time, data.StatsTicketWaitingTime.state, data.StatsTicketWaitingTime.percent
 
-  renderWidgetClockFace: (time, max_time = 60) =>
+  renderWidgetClockFace: (time, state, percent) =>
     canvas = @el.find 'canvas'
     ctx    = canvas.get(0).getContext '2d'
     radius = 26
@@ -73,17 +73,15 @@ class App.DashboardStats extends App.Controller
     canvas.attr 'width', 2 * radius
     canvas.attr 'height', 2 * radius
 
-    time = max_time if time > max_time
-
     handlingTimeColors = {}
-    handlingTimeColors[max_time/12] = '#38AE6A' # supergood
-    handlingTimeColors[max_time/6] = '#A9AC41' # good
-    handlingTimeColors[max_time/4] = '#FAAB00' # ok
-    handlingTimeColors[max_time/3] = '#F6820B' # bad
-    handlingTimeColors[max_time/2] = '#F35910' # superbad
+    handlingTimeColors['supergood'] = '#38AE6A' # supergood
+    handlingTimeColors['good'] = '#A9AC41' # good
+    handlingTimeColors['ok'] = '#FAAB00' # ok
+    handlingTimeColors['bad'] = '#F6820B' # bad
+    handlingTimeColors['superbad'] = '#F35910' # superbad
 
-    for handlingTime, timeColor of handlingTimeColors
-      if time <= handlingTime
+    for handlingState, timeColor of handlingTimeColors
+      if state == handlingState
         backgroundColor = timeColor
         break
 
@@ -101,7 +99,7 @@ class App.DashboardStats extends App.Controller
 
     ctx.beginPath()
     ctx.moveTo radius, radius
-    arcsector = Math.PI * 2 * time/max_time
+    arcsector = Math.PI * 2 * percent
     ctx.arc radius, radius, radius, -Math.PI/2, arcsector - Math.PI/2, false
     ctx.lineTo radius, radius
     ctx.closePath()

+ 2 - 2
app/assets/javascripts/app/views/dashboard/stats.jst.eco

@@ -8,8 +8,8 @@
         <div class="stat-amount"></div>
       </div>
     </div>
-    <div class="stat-label"><%- @T('My handling time: %s minutes', @TicketResponseTime.handling_time) %></div>
-    <div class="stat-detail"><%- @T('Average: %s minutes', @TicketResponseTime.average_per_agent) %></div>
+    <div class="stat-label"><%- @T('My handling time: %s minutes', @StatsTicketWaitingTime.handling_time) %></div>
+    <div class="stat-detail"><%- @T('Average: %s minutes', @StatsTicketWaitingTime.average_per_agent) %></div>
   </div>
 </div>
 <div class="column">

+ 1 - 0
lib/stats.rb

@@ -24,6 +24,7 @@ returns
       Stats::TicketLoadMeasure,
       Stats::TicketEscalation,
       Stats::TicketReopen,
+      Stats::TicketWaitingTime,
     ]
 
     # generate stats per agent

+ 73 - 0
lib/stats/ticket_waiting_time.rb

@@ -0,0 +1,73 @@
+# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
+
+class Stats::TicketWaitingTime
+
+  def self.generate(user)
+
+    open_state_ids = Ticket::State.by_category(:open).pluck(:id)
+
+    # get users groups
+    group_ids = user.groups.map(&:id)
+
+    own_waiting = Ticket.where(
+      'owner_id = ? AND group_id IN (?) AND state_id IN (?) AND updated_at > ?', user.id, group_ids, open_state_ids, Time.zone.today
+    )
+    all_waiting = Ticket.where(
+      'group_id IN (?) AND state_id IN (?) AND updated_at > ?', group_ids, open_state_ids, Time.zone.today
+    )
+
+    handling_time = calculate_average(own_waiting, Time.zone.today)
+    if handling_time.positive?
+      handling_time = (handling_time / 60).round
+    end
+    average_per_agent = calculate_average(all_waiting, Time.zone.today)
+    if average_per_agent.positive?
+      average_per_agent = (average_per_agent / 60).round
+    end
+
+    state   = 'supergood'
+    percent = 0
+    state   = if handling_time <= 60
+                percent = handling_time.to_f / 60
+                'supergood'
+              elsif handling_time <= 60 * 4
+                percent = (handling_time.to_f - 60) / (60 * 3)
+                'good'
+              elsif handling_time <= 60 * 8
+                percent = (handling_time.to_f - 60 * 4) / (60 * 4)
+                'ok'
+              else
+                percent = 1.00
+                'bad'
+              end
+
+    {
+      handling_time: handling_time,
+      average_per_agent: average_per_agent,
+      state: state,
+      percent: percent,
+    }
+  end
+
+  def self.average_state(result, _user_id)
+    result
+  end
+
+  def self.calculate_average(tickets, start_time)
+    average_time = 0
+    count_time   = 0
+
+    tickets.each { |ticket|
+      ticket.articles.joins(:type).where('ticket_articles.created_at > ? AND ticket_articles.internal = ? AND ticket_article_types.communication = ?', start_time, false, true).each { |article|
+        if article.sender.name == 'Customer'
+          count_time = article.created_at.to_i
+        else
+          average_time += article.created_at.to_i - count_time
+          count_time    = 0
+        end
+      }
+    }
+
+    average_time
+  end
+end

+ 150 - 0
test/unit/stats_ticket_waiting_time_test.rb

@@ -0,0 +1,150 @@
+# encoding: utf-8
+require 'test_helper'
+require 'stats/ticket_waiting_time'
+
+class StatsTicketWaitingTimeTest < ActiveSupport::TestCase
+
+  test 'single ticket' do
+    ticket1 = Ticket.create(
+      title: 'com test 1',
+      group: Group.lookup(name: 'Users'),
+      customer_id: 2,
+      state: Ticket::State.lookup(name: 'new'),
+      priority: Ticket::Priority.lookup(name: '2 normal'),
+      updated_by_id: 1,
+      created_by_id: 1,
+    )
+
+    # communication 1: waiting time 2 hours (BUT too old yesterday)
+    Ticket::Article.create(
+      ticket_id:     ticket1.id,
+      from:          'a@example.com',
+      to:            'a@example.com',
+      subject:       'com test 1',
+      message_id:    'some@id_com_1',
+      body:          'some message 123',
+      internal:      false,
+      sender:        Ticket::Article::Sender.find_by(name: 'Customer'),
+      type:          Ticket::Article::Type.find_by(name: 'email'),
+      updated_by_id: 1,
+      created_by_id: 1,
+      created_at:    '2017-04-12 08:00',
+      updated_at:    '2017-04-12 08:00',
+    )
+    Ticket::Article.create(
+      ticket_id:     ticket1.id,
+      from:          'a@example.com',
+      to:            'a@example.com',
+      subject:       'com test 1',
+      message_id:    'some@id_com_1',
+      body:          'some message 123',
+      internal:      false,
+      sender:        Ticket::Article::Sender.find_by(name: 'Agent'),
+      type:          Ticket::Article::Type.find_by(name: 'email'),
+      updated_by_id: 1,
+      created_by_id: 1,
+      created_at:    '2017-04-12 10:00',
+      updated_at:    '2017-04-12 10:00',
+    )
+
+    # communication 2: waiting time 2 hours
+    Ticket::Article.create(
+      ticket_id:     ticket1.id,
+      from:          'a@example.com',
+      to:            'a@example.com',
+      subject:       'com test 1',
+      message_id:    'some@id_com_1',
+      body:          'some message 123',
+      internal:      false,
+      sender:        Ticket::Article::Sender.find_by(name: 'Customer'),
+      type:          Ticket::Article::Type.find_by(name: 'email'),
+      updated_by_id: 1,
+      created_by_id: 1,
+      created_at:    '2017-04-13 08:00',
+      updated_at:    '2017-04-13 08:00',
+    )
+    Ticket::Article.create(
+      ticket_id:     ticket1.id,
+      from:          'a@example.com',
+      to:            'a@example.com',
+      subject:       'com test 1',
+      message_id:    'some@id_com_1',
+      body:          'some message 123',
+      internal:      false,
+      sender:        Ticket::Article::Sender.find_by(name: 'Agent'),
+      type:          Ticket::Article::Type.find_by(name: 'email'),
+      updated_by_id: 1,
+      created_by_id: 1,
+      created_at:    '2017-04-13 10:00',
+      updated_at:    '2017-04-13 10:00',
+    )
+
+    # communication 3: waiting time 4 hours
+    Ticket::Article.create(
+      ticket_id:     ticket1.id,
+      from:          'a@example.com',
+      to:            'a@example.com',
+      subject:       'com test 1',
+      message_id:    'some@id_com_1',
+      body:          'some message 123',
+      internal:      false,
+      sender:        Ticket::Article::Sender.find_by(name: 'Customer'),
+      type:          Ticket::Article::Type.find_by(name: 'email'),
+      updated_by_id: 1,
+      created_by_id: 1,
+      created_at:    '2017-04-13 11:00',
+      updated_at:    '2017-04-13 11:00',
+    )
+    Ticket::Article.create(
+      ticket_id:     ticket1.id,
+      from:          'a@example.com',
+      to:            'a@example.com',
+      subject:       'com test 1',
+      message_id:    'some@id_com_1',
+      body:          'some message 123',
+      internal:      false,
+      sender:        Ticket::Article::Sender.find_by(name: 'System'),
+      type:          Ticket::Article::Type.find_by(name: 'email'),
+      updated_by_id: 1,
+      created_by_id: 1,
+      created_at:    '2017-04-13 15:00',
+      updated_at:    '2017-04-13 15:00',
+    )
+
+    # communication 4: INVALID waiting time 1 hour (because internal)
+    Ticket::Article.create(
+      ticket_id:     ticket1.id,
+      from:          'a@example.com',
+      to:            'a@example.com',
+      subject:       'com test 1',
+      message_id:    'some@id_com_1',
+      body:          'some message 123',
+      internal:      true,
+      sender:        Ticket::Article::Sender.find_by(name: 'Customer'),
+      type:          Ticket::Article::Type.find_by(name: 'email'),
+      updated_by_id: 1,
+      created_by_id: 1,
+      created_at:    '2017-04-13 15:00',
+      updated_at:    '2017-04-13 15:00',
+    )
+    Ticket::Article.create(
+      ticket_id:     ticket1.id,
+      from:          'a@example.com',
+      to:            'a@example.com',
+      subject:       'com test 1',
+      message_id:    'some@id_com_1',
+      body:          'some message 123',
+      internal:      true,
+      sender:        Ticket::Article::Sender.find_by(name: 'System'),
+      type:          Ticket::Article::Type.find_by(name: 'email'),
+      updated_by_id: 1,
+      created_by_id: 1,
+      created_at:    '2017-04-13 15:10',
+      updated_at:    '2017-04-13 15:10',
+    )
+
+    average_time = Stats::TicketWaitingTime.calculate_average([ticket1, ticket1], '2017-04-13 00:00:00')
+    assert_equal(60 * 60 * 6 * 2, average_time)
+  end
+
+end