Fixed issue #2420 - Unable to show ticket history.
This commit is contained in:
parent
3d45432f78
commit
ed448c7f50
13 changed files with 158 additions and 68 deletions
|
@ -314,10 +314,7 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co
|
||||||
organization = Organization.find(params[:id])
|
organization = Organization.find(params[:id])
|
||||||
|
|
||||||
# get history of organization
|
# get history of organization
|
||||||
history = organization.history_get(true)
|
render json: organization.history_get(true)
|
||||||
|
|
||||||
# return result
|
|
||||||
render json: history
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# @path [GET] /organizations/import_example
|
# @path [GET] /organizations/import_example
|
||||||
|
|
|
@ -294,10 +294,7 @@ class TicketsController < ApplicationController
|
||||||
access!(ticket, 'read')
|
access!(ticket, 'read')
|
||||||
|
|
||||||
# get history of ticket
|
# get history of ticket
|
||||||
history = ticket.history_get(true)
|
render json: ticket.history_get(true)
|
||||||
|
|
||||||
# return result
|
|
||||||
render json: history
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /api/v1/ticket_related/1
|
# GET /api/v1/ticket_related/1
|
||||||
|
|
|
@ -502,10 +502,7 @@ class UsersController < ApplicationController
|
||||||
user = User.find(params[:id])
|
user = User.find(params[:id])
|
||||||
|
|
||||||
# get history of user
|
# get history of user
|
||||||
history = user.history_get(true)
|
render json: user.history_get(true)
|
||||||
|
|
||||||
# return result
|
|
||||||
render json: history
|
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
|
@ -204,12 +204,14 @@ returns
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def history_get(fulldata = false)
|
def history_get(fulldata = false)
|
||||||
|
relation_object = self.class.instance_variable_get(:@history_relation_object) || nil
|
||||||
|
|
||||||
if !fulldata
|
if !fulldata
|
||||||
return History.list(self.class.name, self['id'])
|
return History.list(self.class.name, self['id'], relation_object)
|
||||||
end
|
end
|
||||||
|
|
||||||
# get related objects
|
# get related objects
|
||||||
history = History.list(self.class.name, self['id'], nil, true)
|
history = History.list(self.class.name, self['id'], relation_object, true)
|
||||||
history[:list].each do |item|
|
history[:list].each do |item|
|
||||||
record = Kernel.const_get(item['object']).find(item['o_id'])
|
record = Kernel.const_get(item['object']).find(item['o_id'])
|
||||||
|
|
||||||
|
@ -242,5 +244,21 @@ end
|
||||||
def history_attributes_ignored(*attributes)
|
def history_attributes_ignored(*attributes)
|
||||||
@history_attributes_ignored = attributes
|
@history_attributes_ignored = attributes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
serve methode to ignore model attributes in historization
|
||||||
|
|
||||||
|
class Model < ApplicationModel
|
||||||
|
include HasHistory
|
||||||
|
history_relation_object 'Some::Relation::Object'
|
||||||
|
end
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def history_relation_object(attribute)
|
||||||
|
@history_relation_object = attribute
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,19 +40,19 @@ add a new history entry for an object
|
||||||
return if Setting.get('import_mode') && !data[:id]
|
return if Setting.get('import_mode') && !data[:id]
|
||||||
|
|
||||||
# lookups
|
# lookups
|
||||||
if data[:history_type]
|
if data[:history_type].present?
|
||||||
history_type = type_lookup(data[:history_type])
|
history_type = type_lookup(data[:history_type])
|
||||||
end
|
end
|
||||||
if data[:history_object]
|
if data[:history_object].present?
|
||||||
history_object = object_lookup(data[:history_object])
|
history_object = object_lookup(data[:history_object])
|
||||||
end
|
end
|
||||||
related_history_object_id = nil
|
related_history_object_id = nil
|
||||||
if data[:related_history_object]
|
if data[:related_history_object].present?
|
||||||
related_history_object = object_lookup(data[:related_history_object])
|
related_history_object = object_lookup(data[:related_history_object])
|
||||||
related_history_object_id = related_history_object.id
|
related_history_object_id = related_history_object.id
|
||||||
end
|
end
|
||||||
history_attribute_id = nil
|
history_attribute_id = nil
|
||||||
if data[:history_attribute]
|
if data[:history_attribute].present?
|
||||||
history_attribute = attribute_lookup(data[:history_attribute])
|
history_attribute = attribute_lookup(data[:history_attribute])
|
||||||
history_attribute_id = history_attribute.id
|
history_attribute_id = history_attribute.id
|
||||||
end
|
end
|
||||||
|
@ -80,11 +80,11 @@ add a new history entry for an object
|
||||||
if history_record
|
if history_record
|
||||||
history_record.update!(record)
|
history_record.update!(record)
|
||||||
else
|
else
|
||||||
record_new = History.create(record)
|
record_new = History.create!(record)
|
||||||
if record[:id]
|
if record[:id]
|
||||||
record_new.id = record[:id]
|
record_new.id = record[:id]
|
||||||
end
|
end
|
||||||
record_new.save
|
record_new.save!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ returns
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.list(requested_object, requested_object_id, related_history_object = nil, assets = nil)
|
def self.list(requested_object, requested_object_id, related_history_object = nil, assets = nil)
|
||||||
if !related_history_object
|
if related_history_object.blank?
|
||||||
history_object = object_lookup(requested_object)
|
history_object = object_lookup(requested_object)
|
||||||
history = History.where(history_object_id: history_object.id)
|
history = History.where(history_object_id: history_object.id)
|
||||||
.where(o_id: requested_object_id)
|
.where(o_id: requested_object_id)
|
||||||
|
@ -220,14 +220,10 @@ returns
|
||||||
def self.type_lookup(name)
|
def self.type_lookup(name)
|
||||||
# lookup
|
# lookup
|
||||||
history_type = History::Type.lookup(name: name)
|
history_type = History::Type.lookup(name: name)
|
||||||
if history_type
|
return history_type if history_type
|
||||||
return history_type
|
|
||||||
end
|
|
||||||
|
|
||||||
# create
|
# create
|
||||||
History::Type.create(
|
History::Type.create!(name: name)
|
||||||
name: name
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.object_lookup_id(id)
|
def self.object_lookup_id(id)
|
||||||
|
@ -237,14 +233,10 @@ returns
|
||||||
def self.object_lookup(name)
|
def self.object_lookup(name)
|
||||||
# lookup
|
# lookup
|
||||||
history_object = History::Object.lookup(name: name)
|
history_object = History::Object.lookup(name: name)
|
||||||
if history_object
|
return history_object if history_object
|
||||||
return history_object
|
|
||||||
end
|
|
||||||
|
|
||||||
# create
|
# create
|
||||||
History::Object.create(
|
History::Object.create!(name: name)
|
||||||
name: name
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.attribute_lookup_id(id)
|
def self.attribute_lookup_id(id)
|
||||||
|
@ -254,14 +246,10 @@ returns
|
||||||
def self.attribute_lookup(name)
|
def self.attribute_lookup(name)
|
||||||
# lookup
|
# lookup
|
||||||
history_attribute = History::Attribute.lookup(name: name)
|
history_attribute = History::Attribute.lookup(name: name)
|
||||||
if history_attribute
|
return history_attribute if history_attribute
|
||||||
return history_attribute
|
|
||||||
end
|
|
||||||
|
|
||||||
# create
|
# create
|
||||||
History::Attribute.create(
|
History::Attribute.create!(name: name)
|
||||||
name: name
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Object < ApplicationModel
|
class Object < ApplicationModel
|
||||||
|
|
|
@ -53,6 +53,8 @@ class Ticket < ApplicationModel
|
||||||
:article_count,
|
:article_count,
|
||||||
:preferences
|
:preferences
|
||||||
|
|
||||||
|
history_relation_object 'Ticket::Article'
|
||||||
|
|
||||||
belongs_to :group
|
belongs_to :group
|
||||||
belongs_to :organization
|
belongs_to :organization
|
||||||
has_many :articles, class_name: 'Ticket::Article', after_add: :cache_update, after_remove: :cache_update, dependent: :destroy, inverse_of: :ticket
|
has_many :articles, class_name: 'Ticket::Article', after_add: :cache_update, after_remove: :cache_update, dependent: :destroy, inverse_of: :ticket
|
||||||
|
@ -878,7 +880,7 @@ perform changes on ticket
|
||||||
next if value['value'].blank?
|
next if value['value'].blank?
|
||||||
next if value['value'] != 'delete'
|
next if value['value'] != 'delete'
|
||||||
|
|
||||||
logger.debug { "Deleted ticket from #{perform_origin} #{perform.inspect} Ticket.find(#{id})" }
|
logger.info { "Deleted ticket from #{perform_origin} #{perform.inspect} Ticket.find(#{id})" }
|
||||||
destroy!
|
destroy!
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
@ -1158,27 +1160,6 @@ result
|
||||||
Ticket::Article.where(ticket_id: id).order(:created_at, :id)
|
Ticket::Article.where(ticket_id: id).order(:created_at, :id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def history_get(fulldata = false)
|
|
||||||
list = History.list(self.class.name, self['id'], 'Ticket::Article')
|
|
||||||
return list if !fulldata
|
|
||||||
|
|
||||||
# get related objects
|
|
||||||
assets = {}
|
|
||||||
list.each do |item|
|
|
||||||
record = Kernel.const_get(item['object']).find(item['o_id'])
|
|
||||||
assets = record.assets(assets)
|
|
||||||
|
|
||||||
if item['related_object']
|
|
||||||
record = Kernel.const_get(item['related_object']).find( item['related_o_id'])
|
|
||||||
assets = record.assets(assets)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
{
|
|
||||||
history: list,
|
|
||||||
assets: assets,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def check_generate
|
def check_generate
|
||||||
|
|
|
@ -210,7 +210,7 @@ retunes
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.already_sent?(ticket, recipient, type)
|
def self.already_sent?(ticket, recipient, type)
|
||||||
result = ticket.history_get()
|
result = ticket.history_get
|
||||||
count = 0
|
count = 0
|
||||||
result.each do |item|
|
result.each do |item|
|
||||||
next if item['type'] != 'notification'
|
next if item['type'] != 'notification'
|
||||||
|
|
|
@ -452,6 +452,22 @@ RSpec.describe 'Organization', type: :request, searchindex: true do
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does organization history' do
|
||||||
|
organization1 = create(
|
||||||
|
:organization,
|
||||||
|
name: 'some org',
|
||||||
|
)
|
||||||
|
|
||||||
|
authenticated_as(agent_user)
|
||||||
|
get "/api/v1/organizations/history/#{organization1.id}", params: {}, as: :json
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(json_response).to be_a_kind_of(Hash)
|
||||||
|
expect(json_response['history'].class).to eq(Array)
|
||||||
|
expect(json_response['assets'].class).to eq(Hash)
|
||||||
|
expect(json_response['assets']['Ticket']).to be_nil
|
||||||
|
expect(json_response['assets']['Organization'][organization1.id.to_s]).not_to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
it 'does csv example - customer no access' do
|
it 'does csv example - customer no access' do
|
||||||
authenticated_as(customer_user)
|
authenticated_as(customer_user)
|
||||||
get '/api/v1/organizations/import_example', params: {}, as: :json
|
get '/api/v1/organizations/import_example', params: {}, as: :json
|
||||||
|
|
|
@ -2078,6 +2078,30 @@ RSpec.describe 'Ticket', type: :request do
|
||||||
expect(json_response).to be_a_kind_of(Hash)
|
expect(json_response).to be_a_kind_of(Hash)
|
||||||
expect(json_response['tickets']).to eq([ticket2.id, ticket1.id])
|
expect(json_response['tickets']).to eq([ticket2.id, ticket1.id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does ticket history ' do
|
||||||
|
ticket1 = create(
|
||||||
|
:ticket,
|
||||||
|
title: 'some title',
|
||||||
|
group: ticket_group,
|
||||||
|
customer_id: customer_user.id,
|
||||||
|
)
|
||||||
|
create(
|
||||||
|
:ticket_article,
|
||||||
|
type: Ticket::Article::Type.lookup(name: 'note'),
|
||||||
|
sender: Ticket::Article::Sender.lookup(name: 'Customer'),
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
authenticated_as(agent_user)
|
||||||
|
get "/api/v1/ticket_history/#{ticket1.id}", params: {}, as: :json
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(json_response).to be_a_kind_of(Hash)
|
||||||
|
expect(json_response['history'].class).to eq(Array)
|
||||||
|
expect(json_response['assets'].class).to eq(Hash)
|
||||||
|
expect(json_response['assets']['User'][customer_user.id.to_s]).not_to be_nil
|
||||||
|
expect(json_response['assets']['Ticket'][ticket1.id.to_s]).not_to be_nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'stats' do
|
describe 'stats' do
|
||||||
|
|
|
@ -919,6 +919,25 @@ RSpec.describe 'User', type: :request, searchindex: true do
|
||||||
user2.destroy!
|
user2.destroy!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does user history' do
|
||||||
|
user1 = create(
|
||||||
|
:customer_user,
|
||||||
|
login: 'history@example.com',
|
||||||
|
firstname: 'History',
|
||||||
|
lastname: 'Customer1',
|
||||||
|
email: 'history@example.com',
|
||||||
|
)
|
||||||
|
|
||||||
|
authenticated_as(agent_user)
|
||||||
|
get "/api/v1/users/history/#{user1.id}", params: {}, as: :json
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(json_response).to be_a_kind_of(Hash)
|
||||||
|
expect(json_response['history'].class).to eq(Array)
|
||||||
|
expect(json_response['assets'].class).to eq(Hash)
|
||||||
|
expect(json_response['assets']['Ticket']).to be_nil
|
||||||
|
expect(json_response['assets']['User'][user1.id.to_s]).not_to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
it 'does user search sortable' do
|
it 'does user search sortable' do
|
||||||
firstname = "user_search_sortable #{rand(999_999_999)}"
|
firstname = "user_search_sortable #{rand(999_999_999)}"
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class HistoryTest < ActiveSupport::TestCase
|
class HistoryTest < ActiveSupport::TestCase
|
||||||
current_user = User.lookup(email: 'nicole.braun@zammad.org')
|
|
||||||
|
|
||||||
test 'ticket' do
|
test 'ticket' do
|
||||||
|
current_user = User.lookup(email: 'nicole.braun@zammad.org')
|
||||||
tests = [
|
tests = [
|
||||||
|
|
||||||
# test 1
|
# test 1
|
||||||
|
@ -188,6 +188,7 @@ class HistoryTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'user' do
|
test 'user' do
|
||||||
|
current_user = User.lookup(email: 'nicole.braun@zammad.org')
|
||||||
name = rand(999_999)
|
name = rand(999_999)
|
||||||
tests = [
|
tests = [
|
||||||
|
|
||||||
|
@ -275,6 +276,7 @@ class HistoryTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'organization' do
|
test 'organization' do
|
||||||
|
current_user = User.lookup(email: 'nicole.braun@zammad.org')
|
||||||
tests = [
|
tests = [
|
||||||
|
|
||||||
# test 1
|
# test 1
|
||||||
|
@ -337,6 +339,57 @@ class HistoryTest < ActiveSupport::TestCase
|
||||||
organizations.each(&:destroy!)
|
organizations.each(&:destroy!)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'ticket assets' do
|
||||||
|
UserInfo.current_user_id = 1
|
||||||
|
agent1 = User.create!(
|
||||||
|
login: 'agent1@example.com',
|
||||||
|
firstname: 'agent',
|
||||||
|
lastname: '1',
|
||||||
|
email: 'agent1@example.com',
|
||||||
|
password: 'agentpw',
|
||||||
|
active: true,
|
||||||
|
roles: Role.where(name: %w[Agent Admin]),
|
||||||
|
groups: Group.all,
|
||||||
|
)
|
||||||
|
current_user = User.lookup(email: 'nicole.braun@zammad.org')
|
||||||
|
UserInfo.current_user_id = current_user.id
|
||||||
|
|
||||||
|
ticket = Ticket.create!(
|
||||||
|
title: 'test 1',
|
||||||
|
group: Group.first,
|
||||||
|
customer_id: current_user.id,
|
||||||
|
state: Ticket::State.lookup(name: 'new'),
|
||||||
|
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||||
|
)
|
||||||
|
article = Ticket::Article.create!(
|
||||||
|
ticket_id: ticket.id,
|
||||||
|
from: 'some_customer_com-1@example.com',
|
||||||
|
to: 'some_zammad_com-1@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'),
|
||||||
|
)
|
||||||
|
|
||||||
|
# verify if user of history record is in assets
|
||||||
|
UserInfo.current_user_id = agent1.id
|
||||||
|
ticket.state = Ticket::State.find_by(name: 'closed')
|
||||||
|
ticket.save!
|
||||||
|
|
||||||
|
# update updated_by (to not include agent1 in assets by ticket)
|
||||||
|
UserInfo.current_user_id = current_user.id
|
||||||
|
ticket.priority = Ticket::Priority.find_by(name: '3 high')
|
||||||
|
ticket.save!
|
||||||
|
|
||||||
|
history = ticket.history_get(true)
|
||||||
|
assert(history[:assets][:User][current_user.id])
|
||||||
|
assert(history[:assets][:User][agent1.id])
|
||||||
|
assert(history[:assets][:Ticket][ticket.id])
|
||||||
|
assert(history[:assets][:TicketArticle][article.id])
|
||||||
|
end
|
||||||
|
|
||||||
def history_check(history_list, history_check)
|
def history_check(history_list, history_check)
|
||||||
history_check.each do |check_item|
|
history_check.each do |check_item|
|
||||||
match = false
|
match = false
|
||||||
|
|
|
@ -8,7 +8,7 @@ class NotificationFactoryMailerTemplateTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
groups = Group.where(name: 'Users')
|
groups = Group.where(name: 'Users')
|
||||||
roles = Role.where(name: 'Agent')
|
roles = Role.where(name: 'Agent')
|
||||||
agent1 = User.create_or_update(
|
agent1 = User.create!(
|
||||||
login: 'notification-template-agent1@example.com',
|
login: 'notification-template-agent1@example.com',
|
||||||
firstname: 'Notification<b>xxx</b>',
|
firstname: 'Notification<b>xxx</b>',
|
||||||
lastname: 'Agent1<b>yyy</b>',
|
lastname: 'Agent1<b>yyy</b>',
|
||||||
|
@ -24,7 +24,7 @@ class NotificationFactoryMailerTemplateTest < ActiveSupport::TestCase
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
agent_current_user = User.create_or_update(
|
agent_current_user = User.create!(
|
||||||
login: 'notification-template-current_user@example.com',
|
login: 'notification-template-current_user@example.com',
|
||||||
firstname: 'Notification Current',
|
firstname: 'Notification Current',
|
||||||
lastname: 'User',
|
lastname: 'User',
|
||||||
|
|
|
@ -83,7 +83,7 @@ class NotificationFactoryMailerTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
groups = Group.all
|
groups = Group.all
|
||||||
roles = Role.where(name: 'Agent')
|
roles = Role.where(name: 'Agent')
|
||||||
agent1 = User.create_or_update(
|
agent1 = User.create!(
|
||||||
login: 'notification-settings-agent1@example.com',
|
login: 'notification-settings-agent1@example.com',
|
||||||
firstname: 'Notification<b>xxx</b>',
|
firstname: 'Notification<b>xxx</b>',
|
||||||
lastname: 'Agent1',
|
lastname: 'Agent1',
|
||||||
|
@ -96,7 +96,7 @@ class NotificationFactoryMailerTest < ActiveSupport::TestCase
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
agent2 = User.create_or_update(
|
agent2 = User.create!(
|
||||||
login: 'notification-settings-agent2@example.com',
|
login: 'notification-settings-agent2@example.com',
|
||||||
firstname: 'Notification<b>xxx</b>',
|
firstname: 'Notification<b>xxx</b>',
|
||||||
lastname: 'Agent2',
|
lastname: 'Agent2',
|
||||||
|
@ -109,7 +109,7 @@ class NotificationFactoryMailerTest < ActiveSupport::TestCase
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
group_notification_setting = Group.create_or_update(
|
group_notification_setting = Group.create!(
|
||||||
name: 'NotificationSetting',
|
name: 'NotificationSetting',
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
|
|
Loading…
Reference in a new issue