Init version of zammad karma.
This commit is contained in:
parent
05cf8c208a
commit
8db9723042
13 changed files with 1178 additions and 0 deletions
41
app/assets/javascripts/app/controllers/karma.coffee
Normal file
41
app/assets/javascripts/app/controllers/karma.coffee
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
class KarmaContent extends App.ControllerContent
|
||||||
|
constructor: ->
|
||||||
|
new Karma()
|
||||||
|
|
||||||
|
class Karma extends App.ControllerModal
|
||||||
|
head: 'Zammad Karma'
|
||||||
|
buttonSubmit: false
|
||||||
|
buttonCancel: true
|
||||||
|
shown: false
|
||||||
|
#events:
|
||||||
|
# 'click .js-check': 'done'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@load()
|
||||||
|
|
||||||
|
# rerender view, e. g. on langauge change
|
||||||
|
@bind('ui:rerender', =>
|
||||||
|
@update()
|
||||||
|
'karma'
|
||||||
|
)
|
||||||
|
|
||||||
|
# fetch data, render view
|
||||||
|
load: ->
|
||||||
|
@ajax(
|
||||||
|
id: 'karma'
|
||||||
|
type: 'GET'
|
||||||
|
url: "#{@apiPath}/karma"
|
||||||
|
success: (data) =>
|
||||||
|
@data = data
|
||||||
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
|
content: ->
|
||||||
|
App.view('karma/index')(
|
||||||
|
levels: @data.levels
|
||||||
|
user: @data.user
|
||||||
|
logs: @data.logs
|
||||||
|
)
|
||||||
|
|
||||||
|
App.Config.set('karma', KarmaContent, 'Routes')
|
60
app/assets/javascripts/app/views/karma/index.jst.eco
Normal file
60
app/assets/javascripts/app/views/karma/index.jst.eco
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<%- @T('Zammad Karma is a powerful tool that tracks and visualizes your productivity.') %>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2><%- @T('Karma Level') %></h2>
|
||||||
|
|
||||||
|
<%- @T('You are an |%s|.', App.i18n.translatePlain(@user.level)) %> <%- @T('Your karma is |%s|.', @user.score) %>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<% for level in @levels: %>
|
||||||
|
<tr>
|
||||||
|
<td style="width: 60px;"><%= level.start %></td>
|
||||||
|
<td style="width: 40px;">→ </td>
|
||||||
|
<td style="width: 100px;"><% if level.end is null: %>∞<% else: %><%= level.end %><% end %></td>
|
||||||
|
<td><%- @T(level.name) %></td>
|
||||||
|
<td><% if @user.level is level.name: %>(<%- @T('Your current level') %>)<% end %></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2><%- @T('Latest updates') %></h2>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<% for log in @logs: %>
|
||||||
|
<tr>
|
||||||
|
<td style="width: 180px;"><%- @humanTime(log.created_at) %></td>
|
||||||
|
<td style="width: 80px;"><%- log.score_total %></td>
|
||||||
|
<td>
|
||||||
|
<% for comment in log.comments: %>
|
||||||
|
<% if comment.score >= 0: %>+<% end %><%- comment.score %> <%- @T(comment.description) %>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2><%- @T('What affects your Zammad Karma?') %></h2>
|
||||||
|
|
||||||
|
<p><%- @T('You accumulate "positive Karma" when you regularly answer and close tickets on time and when you use advanced features such as text modules, ticket reminders or tagging tickets. Zammad Karma will decrease when you have re-opend tickets, escalated tickets or tickets that are two or more days overdue.') %></p>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<p><%- @T('You’re able to set goals regarding the number of tickets you want to answer or close you want to complete either daily or weekly. Reaching these self-set goals will result in bonus Karma. Zammad also tracks how many days/weeks you have attained your goals, and achieving ongoing "streaks" will similarly result in positive Karma.') %></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><%- @T('Karma Trends') %></h2>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><%- @T('last week') %></h2>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><%- @T('last month') %></h2>
|
||||||
|
-->
|
||||||
|
|
||||||
|
</div>
|
14
app/controllers/karma_controller.rb
Normal file
14
app/controllers/karma_controller.rb
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class KarmaController < ApplicationController
|
||||||
|
before_action :authentication_check
|
||||||
|
|
||||||
|
def index
|
||||||
|
render json: {
|
||||||
|
levels: Setting.get('karma_levels'),
|
||||||
|
user: Karma::User.by_user(current_user),
|
||||||
|
logs: Karma::ActivityLog.latest(current_user, 20),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
11
app/models/karma.rb
Normal file
11
app/models/karma.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class Karma
|
||||||
|
|
||||||
|
def self.score_by_user(user)
|
||||||
|
last_activity_log = Karma::ActivityLog.where(user_id: user.id).order(id: :desc).first
|
||||||
|
return 0 if !last_activity_log
|
||||||
|
last_activity_log.score_total
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
6
app/models/karma/activity.rb
Normal file
6
app/models/karma/activity.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class Karma::Activity < ApplicationModel
|
||||||
|
self.table_name = 'karma_activities'
|
||||||
|
validates :name, presence: true
|
||||||
|
end
|
75
app/models/karma/activity_log.rb
Normal file
75
app/models/karma/activity_log.rb
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class Karma::ActivityLog < ApplicationModel
|
||||||
|
belongs_to :object_lookup, class_name: 'ObjectLookup'
|
||||||
|
|
||||||
|
self.table_name = 'karma_activity_logs'
|
||||||
|
|
||||||
|
def self.add(action, user, object, o_id)
|
||||||
|
activity = Karma::Activity.lookup(name: action)
|
||||||
|
|
||||||
|
if object
|
||||||
|
object_id = ObjectLookup.by_name(object)
|
||||||
|
end
|
||||||
|
|
||||||
|
Karma::ActivityLog.transaction do
|
||||||
|
last_activity = Karma::ActivityLog.where(user_id: user.id).order(id: :desc).lock(true).first
|
||||||
|
latest_activity = Karma::ActivityLog.where(
|
||||||
|
user_id: user.id,
|
||||||
|
object_lookup_id: object_id,
|
||||||
|
o_id: o_id,
|
||||||
|
activity_id: activity.id,
|
||||||
|
).find_by('created_at >= ?', Time.zone.now - activity.once_ttl.seconds)
|
||||||
|
return false if latest_activity
|
||||||
|
score_total = 0
|
||||||
|
if last_activity
|
||||||
|
score_total = last_activity.score_total
|
||||||
|
end
|
||||||
|
|
||||||
|
Karma::ActivityLog.create(
|
||||||
|
object_lookup_id: object_id,
|
||||||
|
o_id: o_id,
|
||||||
|
user_id: user.id,
|
||||||
|
activity_id: activity.id,
|
||||||
|
score: activity.score,
|
||||||
|
score_total: score_total + activity.score,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# set new karma level
|
||||||
|
Karma::User.sync(user)
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.latest(user, limit = 20)
|
||||||
|
result = []
|
||||||
|
logs = Karma::ActivityLog.where(user_id: user.id).order(id: :desc).limit(limit)
|
||||||
|
logs.each { |log|
|
||||||
|
last = result.last
|
||||||
|
if last && last[:object_id] == log.object_id && last[:o_id] == log.o_id && last[:created_at] == log.created_at
|
||||||
|
comment = {
|
||||||
|
description: Karma::Activity.lookup(id: log.activity_id).description,
|
||||||
|
score: log.score,
|
||||||
|
}
|
||||||
|
last[:comments].push comment
|
||||||
|
last[:score_total] = score_total
|
||||||
|
next
|
||||||
|
end
|
||||||
|
comment = {
|
||||||
|
object_id: log.object_id,
|
||||||
|
o_id: log.o_id,
|
||||||
|
description: Karma::Activity.lookup(id: log.activity_id).description,
|
||||||
|
score: log.score,
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
comments: [comment],
|
||||||
|
score_total: log.score_total,
|
||||||
|
created_at: log.created_at,
|
||||||
|
}
|
||||||
|
result.push data
|
||||||
|
}
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
44
app/models/karma/user.rb
Normal file
44
app/models/karma/user.rb
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class Karma::User < ApplicationModel
|
||||||
|
self.table_name = 'karma_users'
|
||||||
|
|
||||||
|
def self.sync(user)
|
||||||
|
score = Karma.score_by_user(user)
|
||||||
|
level = level_by_score(score)
|
||||||
|
record = Karma::User.find_by(user_id: user.id)
|
||||||
|
if record
|
||||||
|
return record if record.score == score && record.level == level
|
||||||
|
record.score = score
|
||||||
|
record.level = level
|
||||||
|
record.save
|
||||||
|
return record
|
||||||
|
end
|
||||||
|
Karma::User.create(
|
||||||
|
user_id: user.id,
|
||||||
|
level: level,
|
||||||
|
score: score,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.by_user(user)
|
||||||
|
record = Karma::User.find_by(user_id: user.id)
|
||||||
|
return record if record
|
||||||
|
sync(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.level_by_score(score)
|
||||||
|
level = nil
|
||||||
|
karma_levels = Setting.get('karma_levels')
|
||||||
|
karma_levels.each { |local_level|
|
||||||
|
if !level
|
||||||
|
level = local_level[:name]
|
||||||
|
end
|
||||||
|
next if local_level[:start] && score < local_level[:start]
|
||||||
|
next if local_level[:end] && score > local_level[:end]
|
||||||
|
level = local_level[:name]
|
||||||
|
}
|
||||||
|
level
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -73,6 +73,7 @@ class Observer::Transaction < ActiveRecord::Observer
|
||||||
object_id: 123,
|
object_id: 123,
|
||||||
article_id: 123,
|
article_id: 123,
|
||||||
user_id: 123,
|
user_id: 123,
|
||||||
|
created_at: Time.zone.now,
|
||||||
},
|
},
|
||||||
9 => {
|
9 => {
|
||||||
object: 'Ticket',
|
object: 'Ticket',
|
||||||
|
@ -83,6 +84,7 @@ class Observer::Transaction < ActiveRecord::Observer
|
||||||
attribute2: [before, now],
|
attribute2: [before, now],
|
||||||
},
|
},
|
||||||
user_id: 123,
|
user_id: 123,
|
||||||
|
created_at: Time.zone.now,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -99,6 +101,7 @@ class Observer::Transaction < ActiveRecord::Observer
|
||||||
attribute2: [before, now],
|
attribute2: [before, now],
|
||||||
},
|
},
|
||||||
user_id: 123,
|
user_id: 123,
|
||||||
|
created_at: Time.zone.now,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -140,6 +143,7 @@ class Observer::Transaction < ActiveRecord::Observer
|
||||||
store[:object] = event[:object]
|
store[:object] = event[:object]
|
||||||
store[:object_id] = object.id
|
store[:object_id] = object.id
|
||||||
store[:user_id] = event[:user_id]
|
store[:user_id] = event[:user_id]
|
||||||
|
store[:created_at] = event[:created_at]
|
||||||
|
|
||||||
if !store[:type] || store[:type] == 'update'
|
if !store[:type] || store[:type] == 'update'
|
||||||
store[:type] = event[:type]
|
store[:type] = event[:type]
|
||||||
|
@ -179,6 +183,7 @@ class Observer::Transaction < ActiveRecord::Observer
|
||||||
data: record,
|
data: record,
|
||||||
id: record.id,
|
id: record.id,
|
||||||
user_id: record.created_by_id,
|
user_id: record.created_by_id,
|
||||||
|
created_at: Time.zone.now,
|
||||||
}
|
}
|
||||||
EventBuffer.add('transaction', e)
|
EventBuffer.add('transaction', e)
|
||||||
end
|
end
|
||||||
|
@ -220,6 +225,7 @@ class Observer::Transaction < ActiveRecord::Observer
|
||||||
changes: real_changes,
|
changes: real_changes,
|
||||||
id: record.id,
|
id: record.id,
|
||||||
user_id: changed_by_id,
|
user_id: changed_by_id,
|
||||||
|
created_at: Time.zone.now,
|
||||||
}
|
}
|
||||||
EventBuffer.add('transaction', e)
|
EventBuffer.add('transaction', e)
|
||||||
end
|
end
|
||||||
|
|
172
app/models/transaction/karma.rb
Normal file
172
app/models/transaction/karma.rb
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class Transaction::Karma
|
||||||
|
|
||||||
|
=begin
|
||||||
|
{
|
||||||
|
object: 'Ticket',
|
||||||
|
type: 'update',
|
||||||
|
object_id: 123,
|
||||||
|
via_web: true,
|
||||||
|
changes: {
|
||||||
|
'attribute1' => [before, now],
|
||||||
|
'attribute2' => [before, now],
|
||||||
|
},
|
||||||
|
created_at: Time.zone.now,
|
||||||
|
user_id: 123,
|
||||||
|
},
|
||||||
|
=end
|
||||||
|
|
||||||
|
def initialize(item, params = {})
|
||||||
|
@item = item
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform
|
||||||
|
|
||||||
|
# return if we run import mode
|
||||||
|
return if Setting.get('import_mode')
|
||||||
|
|
||||||
|
user = User.lookup(id: @item[:user_id])
|
||||||
|
|
||||||
|
# ticket
|
||||||
|
if @item[:object] == 'Ticket'
|
||||||
|
ticket_karma(user)
|
||||||
|
ticket_article_karma(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
# add tagging (check last action time)
|
||||||
|
if @item[:object] == 'Tag'
|
||||||
|
tagging(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def ticket_karma(user)
|
||||||
|
ticket = Ticket.lookup(id: @item[:object_id])
|
||||||
|
return if !ticket
|
||||||
|
|
||||||
|
if @item[:type] == 'create'
|
||||||
|
Karma::ActivityLog.add('ticket create', user, 'Ticket', ticket.id)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if @item[:type] == 'reminder_reached'
|
||||||
|
return if ticket.owner_id == 1
|
||||||
|
return if ticket.pending_time > Time.zone.now - 2.days
|
||||||
|
Karma::ActivityLog.add('ticket reminder overdue (+2 days)', ticket.owner, 'Ticket', ticket.id)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if @item[:type] == 'escalation'
|
||||||
|
return if ticket.owner_id == 1
|
||||||
|
Karma::ActivityLog.add('ticket escalated', ticket.owner, 'Ticket', ticket.id)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
return if @item[:type] != 'update'
|
||||||
|
return if !@item[:changes]
|
||||||
|
return if !@item[:changes]['state_id']
|
||||||
|
state_before = Ticket::State.lookup(id: @item[:changes]['state_id'][0])
|
||||||
|
state_now = Ticket::State.lookup(id: @item[:changes]['state_id'][1])
|
||||||
|
|
||||||
|
# close
|
||||||
|
if state_before.state_type.name != 'closed' && state_now.state_type.name == 'closed'
|
||||||
|
|
||||||
|
# did user send a response to customer before?
|
||||||
|
current_time = @item[:created_at]
|
||||||
|
ticket.articles.reverse.each { |local_article|
|
||||||
|
next if local_article.created_at > current_time
|
||||||
|
next if local_article.created_by_id != @item[:user_id]
|
||||||
|
next if local_article.internal
|
||||||
|
|
||||||
|
local_type = Ticket::Article::Type.lookup(id: local_article.type_id)
|
||||||
|
return false if !local_type
|
||||||
|
next if !local_type.communication
|
||||||
|
|
||||||
|
local_sender = Ticket::Article::Sender.lookup(id: local_article.sender_id)
|
||||||
|
return false if !local_sender
|
||||||
|
|
||||||
|
Karma::ActivityLog.add('ticket close', user, 'Ticket', ticket.id)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# pending state
|
||||||
|
if (!state_before.next_state_id && state_before.state_type.name != 'pending reminder') && (state_now.next_state_id || state_now.state_type.name == 'pending reminder')
|
||||||
|
Karma::ActivityLog.add('ticket pending state', user, 'Ticket', ticket.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def ticket_article_karma(user)
|
||||||
|
return if !@item[:article_id]
|
||||||
|
article = Ticket::Article.lookup(id: @item[:article_id])
|
||||||
|
return if !article
|
||||||
|
|
||||||
|
# get sender
|
||||||
|
sender = Ticket::Article::Sender.lookup(id: article.sender_id)
|
||||||
|
return if !sender
|
||||||
|
return if sender.name != 'Agent'
|
||||||
|
|
||||||
|
# get type
|
||||||
|
type = Ticket::Article::Type.lookup(id: article.type_id)
|
||||||
|
return if !type
|
||||||
|
return if !type.communication
|
||||||
|
|
||||||
|
### answer sent (check last action time / within what time?)
|
||||||
|
articles = Ticket::Article.where(ticket_id: article.ticket_id).order(created_at: :asc)
|
||||||
|
if articles.count > 1
|
||||||
|
last_sender_customer = nil
|
||||||
|
last_customer_contact = nil
|
||||||
|
articles.each { |local_article|
|
||||||
|
next if local_article.id == article.id
|
||||||
|
next if local_article.internal
|
||||||
|
|
||||||
|
local_type = Ticket::Article::Type.lookup(id: local_article.type_id)
|
||||||
|
return false if !local_type
|
||||||
|
next if !local_type.communication
|
||||||
|
|
||||||
|
local_sender = Ticket::Article::Sender.lookup(id: local_article.sender_id)
|
||||||
|
return false if !local_sender
|
||||||
|
|
||||||
|
last_sender_customer = if local_sender.name == 'Customer'
|
||||||
|
true
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
next if local_sender.name != 'Customer'
|
||||||
|
last_customer_contact = local_article.created_at
|
||||||
|
}
|
||||||
|
if last_sender_customer && last_customer_contact
|
||||||
|
diff = article.created_at - last_customer_contact
|
||||||
|
if diff > 0
|
||||||
|
if diff < 1.hour
|
||||||
|
Karma::ActivityLog.add('ticket answer 1h', user, 'Ticket', @item[:object_id])
|
||||||
|
elsif diff < 2.hours
|
||||||
|
Karma::ActivityLog.add('ticket answer 2h', user, 'Ticket', @item[:object_id])
|
||||||
|
elsif diff < 12.hours
|
||||||
|
Karma::ActivityLog.add('ticket answer 12h', user, 'Ticket', @item[:object_id])
|
||||||
|
elsif diff < 24.hours
|
||||||
|
Karma::ActivityLog.add('ticket answer 24h', user, 'Ticket', @item[:object_id])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
### text module
|
||||||
|
if article.preferences[:text_module_ids] && !article.preferences[:text_module_ids].empty?
|
||||||
|
Karma::ActivityLog.add('text module', user, 'Ticket', @item[:object_id])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def tagging(user)
|
||||||
|
return if @item[:type] != 'create'
|
||||||
|
tag = Tag.lookup(id: @item[:object_id])
|
||||||
|
return if !tag
|
||||||
|
Karma::ActivityLog.add('tagging', user, tag.tag_object.name, tag.o_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
6
config/routes/karma.rb
Normal file
6
config/routes/karma.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Zammad::Application.routes.draw do
|
||||||
|
api_path = Rails.configuration.api_path
|
||||||
|
|
||||||
|
match api_path + '/karma', to: 'karma#index', via: :get
|
||||||
|
|
||||||
|
end
|
162
db/migrate/20160704000001_add_karma.rb
Normal file
162
db/migrate/20160704000001_add_karma.rb
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
class AddKarma < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
|
||||||
|
create_table :karma_users do |t|
|
||||||
|
t.integer :user_id, null: false
|
||||||
|
t.integer :score, null: false
|
||||||
|
t.string :level, limit: 200, null: false
|
||||||
|
t.timestamps null: false
|
||||||
|
end
|
||||||
|
add_index :karma_users, [:user_id], unique: true
|
||||||
|
|
||||||
|
create_table :karma_activities do |t|
|
||||||
|
t.column :name, :string, limit: 200, null: false
|
||||||
|
t.column :description, :string, limit: 200, null: false
|
||||||
|
t.column :score, :integer, null: false
|
||||||
|
t.column :once_ttl, :integer, null: false
|
||||||
|
t.timestamps null: false
|
||||||
|
end
|
||||||
|
add_index :karma_activities, [:name], unique: true
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'ticket create',
|
||||||
|
description: 'You have created a ticket',
|
||||||
|
score: 10,
|
||||||
|
once_ttl: 60,
|
||||||
|
)
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'ticket close',
|
||||||
|
description: 'You have closed a ticket',
|
||||||
|
score: 5,
|
||||||
|
once_ttl: 60,
|
||||||
|
)
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'ticket answer 1h',
|
||||||
|
description: 'You have answered a ticket within 1h',
|
||||||
|
score: 25,
|
||||||
|
once_ttl: 60,
|
||||||
|
)
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'ticket answer 2h',
|
||||||
|
description: 'You have answered a ticket within 2h',
|
||||||
|
score: 20,
|
||||||
|
once_ttl: 60,
|
||||||
|
)
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'ticket answer 12h',
|
||||||
|
description: 'You have answered a ticket within 12h',
|
||||||
|
score: 10,
|
||||||
|
once_ttl: 60,
|
||||||
|
)
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'ticket answer 24h',
|
||||||
|
description: 'You have answered a ticket within 24h',
|
||||||
|
score: 5,
|
||||||
|
once_ttl: 60,
|
||||||
|
)
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'ticket pending state',
|
||||||
|
description: 'Usage of advanced features',
|
||||||
|
score: 2,
|
||||||
|
once_ttl: 60,
|
||||||
|
)
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'ticket escalated',
|
||||||
|
description: 'You have escalated tickets',
|
||||||
|
score: -5,
|
||||||
|
once_ttl: 60 * 60 * 24,
|
||||||
|
)
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'ticket reminder overdue (+2 days)',
|
||||||
|
description: 'You have tickets that are over 2 days overdue',
|
||||||
|
score: -5,
|
||||||
|
once_ttl: 60 * 60 * 24,
|
||||||
|
)
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'text module',
|
||||||
|
description: 'Usage of advanced features',
|
||||||
|
score: 4,
|
||||||
|
once_ttl: 60 * 30,
|
||||||
|
)
|
||||||
|
Karma::Activity.create_or_update(
|
||||||
|
name: 'tagging',
|
||||||
|
description: 'Usage of advanced features',
|
||||||
|
score: 4,
|
||||||
|
once_ttl: 60 * 60 * 4,
|
||||||
|
)
|
||||||
|
|
||||||
|
create_table :karma_activity_logs do |t|
|
||||||
|
t.integer :o_id, null: false
|
||||||
|
t.integer :object_lookup_id, null: false
|
||||||
|
t.integer :user_id, null: false
|
||||||
|
t.integer :activity_id, null: false
|
||||||
|
t.integer :score, null: false
|
||||||
|
t.integer :score_total, null: false
|
||||||
|
t.timestamps null: false
|
||||||
|
end
|
||||||
|
add_index :karma_activity_logs, [:user_id]
|
||||||
|
add_index :karma_activity_logs, [:created_at]
|
||||||
|
add_index :karma_activity_logs, [:o_id, :object_lookup_id]
|
||||||
|
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Define transaction backend.',
|
||||||
|
name: '9200_karma',
|
||||||
|
area: 'Transaction::Backend::Async',
|
||||||
|
description: 'Define the transaction backend which creates the karma score.',
|
||||||
|
options: {},
|
||||||
|
state: 'Transaction::Karma',
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Define karma levels.',
|
||||||
|
name: 'karma_levels',
|
||||||
|
area: 'Core::Karma',
|
||||||
|
description: 'Define the karma levels.',
|
||||||
|
options: {},
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
name: 'Beginner',
|
||||||
|
start: 0,
|
||||||
|
end: 499,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Newbie',
|
||||||
|
start: 500,
|
||||||
|
end: 1999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Intermediate',
|
||||||
|
start: 2000,
|
||||||
|
end: 4999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Professional',
|
||||||
|
start: 5000,
|
||||||
|
end: 6999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Expert',
|
||||||
|
start: 7000,
|
||||||
|
end: 8999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Master',
|
||||||
|
start: 9000,
|
||||||
|
end: 18_999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Evangelist',
|
||||||
|
start: 19_000,
|
||||||
|
end: 45_999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Hero',
|
||||||
|
start: 50_000,
|
||||||
|
end: nil,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
60
db/seeds.rb
60
db/seeds.rb
|
@ -1977,6 +1977,66 @@ Setting.create_if_not_exists(
|
||||||
state: 'Transaction::CtiCallerIdDetection',
|
state: 'Transaction::CtiCallerIdDetection',
|
||||||
frontend: false
|
frontend: false
|
||||||
)
|
)
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Define transaction backend.',
|
||||||
|
name: '9200_karma',
|
||||||
|
area: 'Transaction::Backend::Async',
|
||||||
|
description: 'Define the transaction backend which creates the karma score.',
|
||||||
|
options: {},
|
||||||
|
state: 'Transaction::Karma',
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Define karma levels.',
|
||||||
|
name: 'karma_levels',
|
||||||
|
area: 'Core::Karma',
|
||||||
|
description: 'Define the karma levels.',
|
||||||
|
options: {},
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
name: 'Beginner',
|
||||||
|
start: 0,
|
||||||
|
end: 499,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Newbie',
|
||||||
|
start: 500,
|
||||||
|
end: 1999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Intermediate',
|
||||||
|
start: 2000,
|
||||||
|
end: 4999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Professional',
|
||||||
|
start: 5000,
|
||||||
|
end: 6999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Expert',
|
||||||
|
start: 7000,
|
||||||
|
end: 8999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Master',
|
||||||
|
start: 9000,
|
||||||
|
end: 18999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Evangelist',
|
||||||
|
start: 19000,
|
||||||
|
end: 45999,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Hero',
|
||||||
|
start: 50000,
|
||||||
|
end: nil,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
signature = Signature.create_if_not_exists(
|
signature = Signature.create_if_not_exists(
|
||||||
id: 1,
|
id: 1,
|
||||||
|
|
521
test/unit/karma_test.rb
Normal file
521
test/unit/karma_test.rb
Normal file
|
@ -0,0 +1,521 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class KarmaTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
|
test 'basic' do
|
||||||
|
|
||||||
|
groups = Group.all
|
||||||
|
roles = Role.where(name: 'Agent')
|
||||||
|
agent1 = User.create_or_update(
|
||||||
|
login: 'karma-agent1@example.com',
|
||||||
|
firstname: 'Karma',
|
||||||
|
lastname: 'Agent1',
|
||||||
|
email: 'karma-agent1@example.com',
|
||||||
|
password: 'agentpw',
|
||||||
|
active: true,
|
||||||
|
roles: roles,
|
||||||
|
groups: groups,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
agent2 = User.create_or_update(
|
||||||
|
login: 'karma-agent2@example.com',
|
||||||
|
firstname: 'Karma',
|
||||||
|
lastname: 'Agent2',
|
||||||
|
email: 'karma-agent2@example.com',
|
||||||
|
password: 'agentpw',
|
||||||
|
active: true,
|
||||||
|
roles: roles,
|
||||||
|
groups: groups,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
customer1 = User.create_or_update(
|
||||||
|
login: 'karma-customer1@example.com',
|
||||||
|
firstname: 'Karma',
|
||||||
|
lastname: 'Customer1',
|
||||||
|
email: 'karma-customer1@example.com',
|
||||||
|
password: 'customerpw',
|
||||||
|
active: true,
|
||||||
|
roles: roles,
|
||||||
|
groups: groups,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
ticket1 = Ticket.create(
|
||||||
|
title: 'karma test 1',
|
||||||
|
group: Group.lookup(name: 'Users'),
|
||||||
|
customer: customer1,
|
||||||
|
state: Ticket::State.lookup(name: 'new'),
|
||||||
|
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||||
|
updated_by_id: agent1.id,
|
||||||
|
created_by_id: agent1.id,
|
||||||
|
updated_at: Time.zone.now - 10.hours,
|
||||||
|
created_at: Time.zone.now - 10.hours,
|
||||||
|
)
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
from: 'some_sender@example.com',
|
||||||
|
to: 'some_recipient@example.com',
|
||||||
|
subject: 'some subject',
|
||||||
|
message_id: 'some@id',
|
||||||
|
body: 'some message',
|
||||||
|
internal: false,
|
||||||
|
sender: Ticket::Article::Sender.lookup(name: 'Agent'),
|
||||||
|
type: Ticket::Article::Type.lookup(name: 'phone'),
|
||||||
|
updated_by_id: agent1.id,
|
||||||
|
created_by_id: agent1.id,
|
||||||
|
updated_at: Time.zone.now - 10.hours,
|
||||||
|
created_at: Time.zone.now - 10.hours,
|
||||||
|
)
|
||||||
|
assert(ticket1)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(0, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
karma_user = Karma::User.by_user(agent1)
|
||||||
|
assert_equal('Beginner', karma_user.level)
|
||||||
|
assert_equal(10, karma_user.score)
|
||||||
|
|
||||||
|
karma_user = Karma::User.by_user(agent2)
|
||||||
|
assert_equal('Beginner', karma_user.level)
|
||||||
|
assert_equal(0, karma_user.score)
|
||||||
|
|
||||||
|
ticket1.state = Ticket::State.lookup(name: 'pending reminder')
|
||||||
|
ticket1.updated_by_id = agent1.id
|
||||||
|
ticket1.updated_at = Time.zone.now - 9.hours
|
||||||
|
ticket1.created_at = Time.zone.now - 9.hours
|
||||||
|
ticket1.save
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(0, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
karma_user = Karma::User.by_user(agent1)
|
||||||
|
assert_equal('Beginner', karma_user.level)
|
||||||
|
assert_equal(12, karma_user.score)
|
||||||
|
|
||||||
|
karma_user = Karma::User.by_user(agent2)
|
||||||
|
assert_equal('Beginner', karma_user.level)
|
||||||
|
assert_equal(0, karma_user.score)
|
||||||
|
|
||||||
|
ticket1.state = Ticket::State.lookup(name: 'pending close')
|
||||||
|
ticket1.updated_by_id = agent1.id
|
||||||
|
ticket1.updated_at = Time.zone.now - 9.hours
|
||||||
|
ticket1.created_at = Time.zone.now - 9.hours
|
||||||
|
ticket1.save
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(0, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
ticket1.state = Ticket::State.lookup(name: 'closed')
|
||||||
|
ticket1.updated_by_id = agent2.id
|
||||||
|
ticket1.updated_at = Time.zone.now - 9.hours
|
||||||
|
ticket1.created_at = Time.zone.now - 9.hours
|
||||||
|
ticket1.save
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(0, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
ticket1.state = Ticket::State.lookup(name: 'open')
|
||||||
|
ticket1.save
|
||||||
|
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
from: 'some_sender@example.com',
|
||||||
|
to: 'some_recipient@example.com',
|
||||||
|
subject: 'reply: some subject',
|
||||||
|
message_id: 'some@id',
|
||||||
|
body: 'some message',
|
||||||
|
internal: false,
|
||||||
|
sender: Ticket::Article::Sender.lookup(name: 'Agent'),
|
||||||
|
type: Ticket::Article::Type.lookup(name: 'phone'),
|
||||||
|
updated_by_id: agent2.id,
|
||||||
|
created_by_id: agent2.id,
|
||||||
|
updated_at: Time.zone.now - (9.hours + 15.minutes),
|
||||||
|
created_at: Time.zone.now - (9.hours + 15.minutes),
|
||||||
|
)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(0, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
ticket1.state = Ticket::State.lookup(name: 'closed')
|
||||||
|
ticket1.save
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
from: 'some_sender@example.com',
|
||||||
|
to: 'some_recipient@example.com',
|
||||||
|
subject: 'some subject',
|
||||||
|
message_id: 'some@id',
|
||||||
|
body: 'some message',
|
||||||
|
internal: false,
|
||||||
|
sender: Ticket::Article::Sender.lookup(name: 'Customer'),
|
||||||
|
type: Ticket::Article::Type.lookup(name: 'phone'),
|
||||||
|
updated_by_id: customer1.id,
|
||||||
|
created_by_id: customer1.id,
|
||||||
|
updated_at: Time.zone.now - 8.hours,
|
||||||
|
created_at: Time.zone.now - 8.hours,
|
||||||
|
)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
from: 'some_sender@example.com',
|
||||||
|
to: 'some_recipient@example.com',
|
||||||
|
subject: 'some subject',
|
||||||
|
message_id: 'some@id',
|
||||||
|
body: 'some message',
|
||||||
|
internal: false,
|
||||||
|
sender: Ticket::Article::Sender.lookup(name: 'Agent'),
|
||||||
|
type: Ticket::Article::Type.lookup(name: 'phone'),
|
||||||
|
updated_by_id: agent1.id,
|
||||||
|
created_by_id: agent1.id,
|
||||||
|
updated_at: Time.zone.now - (7.hours + 30.minutes),
|
||||||
|
created_at: Time.zone.now - (7.hours + 30.minutes),
|
||||||
|
)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
from: 'some_sender@example.com',
|
||||||
|
to: 'some_recipient@example.com',
|
||||||
|
subject: 'some subject',
|
||||||
|
message_id: 'some@id',
|
||||||
|
body: 'some message',
|
||||||
|
internal: false,
|
||||||
|
sender: Ticket::Article::Sender.lookup(name: 'Agent'),
|
||||||
|
type: Ticket::Article::Type.lookup(name: 'phone'),
|
||||||
|
updated_by_id: agent1.id,
|
||||||
|
created_by_id: agent1.id,
|
||||||
|
updated_at: Time.zone.now - (7.hours + 15.minutes),
|
||||||
|
created_at: Time.zone.now - (7.hours + 15.minutes),
|
||||||
|
)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
from: 'some_sender@example.com',
|
||||||
|
to: 'some_recipient@example.com',
|
||||||
|
subject: 'some subject',
|
||||||
|
message_id: 'some@id',
|
||||||
|
body: 'some message',
|
||||||
|
internal: false,
|
||||||
|
sender: Ticket::Article::Sender.lookup(name: 'Customer'),
|
||||||
|
type: Ticket::Article::Type.lookup(name: 'phone'),
|
||||||
|
updated_by_id: customer1.id,
|
||||||
|
created_by_id: customer1.id,
|
||||||
|
updated_at: Time.zone.now - 7.hours,
|
||||||
|
created_at: Time.zone.now - 7.hours,
|
||||||
|
)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
from: 'some_sender@example.com',
|
||||||
|
to: 'some_recipient@example.com',
|
||||||
|
subject: 'some subject',
|
||||||
|
message_id: 'some@id',
|
||||||
|
body: 'some message',
|
||||||
|
internal: false,
|
||||||
|
sender: Ticket::Article::Sender.lookup(name: 'Agent'),
|
||||||
|
type: Ticket::Article::Type.lookup(name: 'phone'),
|
||||||
|
updated_by_id: agent2.id,
|
||||||
|
created_by_id: agent2.id,
|
||||||
|
updated_at: Time.zone.now - (2.hours + 30.minutes),
|
||||||
|
created_at: Time.zone.now - (2.hours + 30.minutes),
|
||||||
|
)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5 + 10, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
from: 'some_sender@example.com',
|
||||||
|
to: 'some_recipient@example.com',
|
||||||
|
subject: 'some subject',
|
||||||
|
message_id: 'some@id',
|
||||||
|
body: 'some message',
|
||||||
|
internal: false,
|
||||||
|
sender: Ticket::Article::Sender.lookup(name: 'Agent'),
|
||||||
|
type: Ticket::Article::Type.lookup(name: 'phone'),
|
||||||
|
updated_by_id: agent1.id,
|
||||||
|
created_by_id: agent1.id,
|
||||||
|
updated_at: Time.zone.now - (2.hours + 45.minutes),
|
||||||
|
created_at: Time.zone.now - (2.hours + 45.minutes),
|
||||||
|
)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5 + 10, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
Tag.tag_add(
|
||||||
|
object: 'Ticket',
|
||||||
|
o_id: ticket1.id,
|
||||||
|
item: 'Tag1',
|
||||||
|
created_by_id: agent1.id,
|
||||||
|
)
|
||||||
|
#sleep 5
|
||||||
|
Tag.tag_add(
|
||||||
|
object: 'Ticket',
|
||||||
|
o_id: ticket1.id,
|
||||||
|
item: 'Tag2',
|
||||||
|
created_by_id: agent1.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25 + 4, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5 + 10, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
Tag.tag_add(
|
||||||
|
object: 'Ticket',
|
||||||
|
o_id: ticket1.id,
|
||||||
|
item: 'Tag3',
|
||||||
|
created_by_id: agent1.id,
|
||||||
|
)
|
||||||
|
Tag.tag_add(
|
||||||
|
object: 'Ticket',
|
||||||
|
o_id: ticket1.id,
|
||||||
|
item: 'Tag4',
|
||||||
|
created_by_id: agent2.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25 + 4, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5 + 10 + 4, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
ticket2 = Ticket.create(
|
||||||
|
title: 'karma test 1',
|
||||||
|
group: Group.lookup(name: 'Users'),
|
||||||
|
customer: customer1,
|
||||||
|
state: Ticket::State.lookup(name: 'new'),
|
||||||
|
owner_id: agent1.id,
|
||||||
|
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||||
|
updated_by_id: agent1.id,
|
||||||
|
created_by_id: agent1.id,
|
||||||
|
updated_at: Time.zone.now - 10.hours,
|
||||||
|
created_at: Time.zone.now - 10.hours,
|
||||||
|
)
|
||||||
|
Ticket::Article.create(
|
||||||
|
ticket_id: ticket2.id,
|
||||||
|
from: 'some_sender@example.com',
|
||||||
|
to: 'some_recipient@example.com',
|
||||||
|
subject: 'some subject',
|
||||||
|
message_id: 'some@id',
|
||||||
|
body: 'some message',
|
||||||
|
internal: false,
|
||||||
|
sender: Ticket::Article::Sender.lookup(name: 'Agent'),
|
||||||
|
type: Ticket::Article::Type.lookup(name: 'phone'),
|
||||||
|
updated_by_id: agent1.id,
|
||||||
|
created_by_id: agent1.id,
|
||||||
|
updated_at: Time.zone.now - 2.hours,
|
||||||
|
created_at: Time.zone.now - 2.hours,
|
||||||
|
)
|
||||||
|
assert(ticket2)
|
||||||
|
|
||||||
|
# execute object transaction
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25 + 4 + 10, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5 + 10 + 4, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
ticket2.state = Ticket::State.lookup(name: 'pending reminder')
|
||||||
|
ticket2.pending_time = Time.zone.now - 1.day
|
||||||
|
ticket2.save
|
||||||
|
|
||||||
|
Ticket.process_pending
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25 + 4 + 10, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5 + 10 + 4, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
ticket2.state = Ticket::State.lookup(name: 'pending reminder')
|
||||||
|
ticket2.pending_time = Time.zone.now - 3.days
|
||||||
|
ticket2.save
|
||||||
|
|
||||||
|
Ticket.process_pending
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25 + 4 + 10 - 5, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5 + 10 + 4, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
Ticket.process_pending
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25 + 4 + 10 - 5, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5 + 10 + 4, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
calendar1 = Calendar.create_or_update(
|
||||||
|
name: 'EU 1',
|
||||||
|
timezone: 'Europe/Berlin',
|
||||||
|
business_hours: {
|
||||||
|
mon: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
tue: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
wed: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
thu: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
fri: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
sat: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
sun: {
|
||||||
|
active: true,
|
||||||
|
timeframes: [ ['00:00', '23:59'] ]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: true,
|
||||||
|
ical_url: nil,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
sla = Sla.create_or_update(
|
||||||
|
name: 'test sla 1',
|
||||||
|
condition: {},
|
||||||
|
first_response_time: 20,
|
||||||
|
update_time: 60,
|
||||||
|
solution_time: 120,
|
||||||
|
calendar_id: calendar1.id,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
ticket2.state = Ticket::State.lookup(name: 'open')
|
||||||
|
ticket2.save
|
||||||
|
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Scheduler.worker(true)
|
||||||
|
|
||||||
|
#Scheduler.worker(true)
|
||||||
|
#Ticket::Escalation.rebuild_all
|
||||||
|
Ticket.process_escalation
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25 + 4 + 10 - 5 - 5, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5 + 10 + 4, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
Ticket.process_escalation
|
||||||
|
|
||||||
|
assert_equal(10 + 2 + 25 + 4 + 10 - 5 - 5, Karma.score_by_user(agent1))
|
||||||
|
assert_equal(5 + 10 + 4, Karma.score_by_user(agent2))
|
||||||
|
assert_equal(0, Karma.score_by_user(customer1))
|
||||||
|
|
||||||
|
# test score/level
|
||||||
|
assert_equal('Beginner', Karma::User.level_by_score(0))
|
||||||
|
assert_equal('Beginner', Karma::User.level_by_score(400))
|
||||||
|
assert_equal('Beginner', Karma::User.level_by_score(499))
|
||||||
|
assert_equal('Newbie', Karma::User.level_by_score(500))
|
||||||
|
assert_equal('Newbie', Karma::User.level_by_score(1999))
|
||||||
|
assert_equal('Intermediate', Karma::User.level_by_score(2000))
|
||||||
|
assert_equal('Intermediate', Karma::User.level_by_score(4999))
|
||||||
|
assert_equal('Professional', Karma::User.level_by_score(5000))
|
||||||
|
assert_equal('Professional', Karma::User.level_by_score(6999))
|
||||||
|
assert_equal('Expert', Karma::User.level_by_score(7000))
|
||||||
|
assert_equal('Expert', Karma::User.level_by_score(8999))
|
||||||
|
assert_equal('Master', Karma::User.level_by_score(9000))
|
||||||
|
assert_equal('Master', Karma::User.level_by_score(18_999))
|
||||||
|
assert_equal('Evangelist', Karma::User.level_by_score(19_000))
|
||||||
|
assert_equal('Evangelist', Karma::User.level_by_score(45_999))
|
||||||
|
assert_equal('Hero', Karma::User.level_by_score(50_000))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in a new issue