Init version of zammad karma.

This commit is contained in:
Martin Edenhofer 2016-07-11 00:47:21 +02:00
parent 05cf8c208a
commit 8db9723042
13 changed files with 1178 additions and 0 deletions

View 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')

View 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('Youre 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>

View 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
View 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

View 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

View 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
View 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

View file

@ -73,6 +73,7 @@ class Observer::Transaction < ActiveRecord::Observer
object_id: 123,
article_id: 123,
user_id: 123,
created_at: Time.zone.now,
},
9 => {
object: 'Ticket',
@ -83,6 +84,7 @@ class Observer::Transaction < ActiveRecord::Observer
attribute2: [before, now],
},
user_id: 123,
created_at: Time.zone.now,
},
},
}
@ -99,6 +101,7 @@ class Observer::Transaction < ActiveRecord::Observer
attribute2: [before, now],
},
user_id: 123,
created_at: Time.zone.now,
},
},
}
@ -140,6 +143,7 @@ class Observer::Transaction < ActiveRecord::Observer
store[:object] = event[:object]
store[:object_id] = object.id
store[:user_id] = event[:user_id]
store[:created_at] = event[:created_at]
if !store[:type] || store[:type] == 'update'
store[:type] = event[:type]
@ -179,6 +183,7 @@ class Observer::Transaction < ActiveRecord::Observer
data: record,
id: record.id,
user_id: record.created_by_id,
created_at: Time.zone.now,
}
EventBuffer.add('transaction', e)
end
@ -220,6 +225,7 @@ class Observer::Transaction < ActiveRecord::Observer
changes: real_changes,
id: record.id,
user_id: changed_by_id,
created_at: Time.zone.now,
}
EventBuffer.add('transaction', e)
end

View 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
View 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

View 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

View file

@ -1977,6 +1977,66 @@ Setting.create_if_not_exists(
state: 'Transaction::CtiCallerIdDetection',
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(
id: 1,

521
test/unit/karma_test.rb Normal file
View 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