Added support of pending reminder notifications.
This commit is contained in:
parent
8f1dd9cccd
commit
7c46db4be4
10 changed files with 195 additions and 65 deletions
|
@ -120,11 +120,33 @@ class Observer::Ticket::Notification::BackgroundJob
|
||||||
changes = human_changes(user, ticket)
|
changes = human_changes(user, ticket)
|
||||||
next if @p[:type] == 'update' && !article && ( !changes || changes.empty? )
|
next if @p[:type] == 'update' && !article && ( !changes || changes.empty? )
|
||||||
|
|
||||||
|
# check if today already notified within last 24 hours
|
||||||
|
if @p[:type] == 'reminder_reached' || @p[:type] == 'escalation'
|
||||||
|
identifier = user.email
|
||||||
|
if !identifier || identifier == ''
|
||||||
|
identifier = user.login
|
||||||
|
end
|
||||||
|
already_notified = false
|
||||||
|
History.list('Ticket', ticket.id).each {|history|
|
||||||
|
next if history['type'] != 'notification'
|
||||||
|
next if history['value_to'] !~ /\(#{Regexp.escape(@p[:type])}:/
|
||||||
|
next if history['value_to'] !~ /#{Regexp.escape(identifier)}\(/
|
||||||
|
next if history['created_at'] < Time.zone.now - 24.hours
|
||||||
|
already_notified = true
|
||||||
|
}
|
||||||
|
next if already_notified
|
||||||
|
end
|
||||||
|
|
||||||
# create online notification
|
# create online notification
|
||||||
used_channels = []
|
used_channels = []
|
||||||
if channels['online']
|
if channels['online']
|
||||||
used_channels.push 'online'
|
used_channels.push 'online'
|
||||||
seen = ticket.online_notification_seen_state(user.id)
|
seen = ticket.online_notification_seen_state(user.id)
|
||||||
|
|
||||||
|
# delete old notifications
|
||||||
|
if @p[:type] == 'reminder_reached' || @p[:type] == 'escalation'
|
||||||
|
OnlineNotification.remove_by_type('Ticket', ticket.id, @p[:type])
|
||||||
|
end
|
||||||
OnlineNotification.add(
|
OnlineNotification.add(
|
||||||
type: @p[:type],
|
type: @p[:type],
|
||||||
object: 'Ticket',
|
object: 'Ticket',
|
||||||
|
@ -138,12 +160,12 @@ class Observer::Ticket::Notification::BackgroundJob
|
||||||
|
|
||||||
# ignore email channel notificaiton and empty emails
|
# ignore email channel notificaiton and empty emails
|
||||||
if !channels['email'] || !user.email || user.email == ''
|
if !channels['email'] || !user.email || user.email == ''
|
||||||
add_recipient_list(ticket, user, used_channels)
|
add_recipient_list(ticket, user, used_channels, @p[:type])
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
used_channels.push 'email'
|
used_channels.push 'email'
|
||||||
add_recipient_list(ticket, user, used_channels)
|
add_recipient_list(ticket, user, used_channels, @p[:type])
|
||||||
|
|
||||||
# get user based notification template
|
# get user based notification template
|
||||||
# if create, send create message / block update messages
|
# if create, send create message / block update messages
|
||||||
|
@ -152,6 +174,10 @@ class Observer::Ticket::Notification::BackgroundJob
|
||||||
template = 'ticket_create'
|
template = 'ticket_create'
|
||||||
elsif @p[:type] == 'update'
|
elsif @p[:type] == 'update'
|
||||||
template = 'ticket_update'
|
template = 'ticket_update'
|
||||||
|
elsif @p[:type] == 'reminder_reached'
|
||||||
|
template = 'ticket_reminder_reached'
|
||||||
|
elsif @p[:type] == 'escalation'
|
||||||
|
template = 'ticket_escalation'
|
||||||
else
|
else
|
||||||
fail "unknown type for notification #{@p[:type]}"
|
fail "unknown type for notification #{@p[:type]}"
|
||||||
end
|
end
|
||||||
|
@ -173,13 +199,13 @@ class Observer::Ticket::Notification::BackgroundJob
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_recipient_list(ticket, user, channels)
|
def add_recipient_list(ticket, user, channels, type)
|
||||||
return if channels.empty?
|
return if channels.empty?
|
||||||
identifier = user.email
|
identifier = user.email
|
||||||
if !identifier || identifier == ''
|
if !identifier || identifier == ''
|
||||||
identifier = user.login
|
identifier = user.login
|
||||||
end
|
end
|
||||||
recipient_list = "#{identifier}(#{channels.join(',')})"
|
recipient_list = "#{identifier}(#{type}:#{channels.join(',')})"
|
||||||
History.add(
|
History.add(
|
||||||
o_id: ticket.id,
|
o_id: ticket.id,
|
||||||
history_type: 'notification',
|
history_type: 'notification',
|
||||||
|
|
|
@ -28,10 +28,10 @@ add a new online notification for this user
|
||||||
|
|
||||||
# lookups
|
# lookups
|
||||||
if data[:type]
|
if data[:type]
|
||||||
type_id = TypeLookup.by_name( data[:type] )
|
type_id = TypeLookup.by_name(data[:type])
|
||||||
end
|
end
|
||||||
if data[:object]
|
if data[:object]
|
||||||
object_id = ObjectLookup.by_name( data[:object] )
|
object_id = ObjectLookup.by_name(data[:object])
|
||||||
end
|
end
|
||||||
|
|
||||||
record = {
|
record = {
|
||||||
|
@ -66,12 +66,12 @@ mark online notification as seen
|
||||||
|
|
||||||
remove whole online notifications of an object
|
remove whole online notifications of an object
|
||||||
|
|
||||||
OnlineNotification.remove( 'Ticket', 123 )
|
OnlineNotification.remove('Ticket', 123)
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.remove( object_name, o_id )
|
def self.remove(object_name, o_id)
|
||||||
object_id = ObjectLookup.by_name( object_name )
|
object_id = ObjectLookup.by_name(object_name)
|
||||||
OnlineNotification.where(
|
OnlineNotification.where(
|
||||||
object_lookup_id: object_id,
|
object_lookup_id: object_id,
|
||||||
o_id: o_id,
|
o_id: o_id,
|
||||||
|
@ -80,22 +80,40 @@ remove whole online notifications of an object
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
|
remove whole online notifications of an object by type
|
||||||
|
|
||||||
|
OnlineNotification.remove_by_type('Ticket', 123, type)
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.remove_by_type(object_name, o_id, type)
|
||||||
|
object_id = ObjectLookup.by_name(object_name)
|
||||||
|
type_id = TypeLookup.by_name(type)
|
||||||
|
OnlineNotification.where(
|
||||||
|
object_lookup_id: object_id,
|
||||||
|
type_lookup_id: type_id,
|
||||||
|
o_id: o_id,
|
||||||
|
).destroy_all
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
return all online notifications of an user
|
return all online notifications of an user
|
||||||
|
|
||||||
notifications = OnlineNotification.list( user, limit )
|
notifications = OnlineNotification.list(user, limit)
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.list(user, limit)
|
def self.list(user, limit)
|
||||||
|
|
||||||
notifications = OnlineNotification.where(user_id: user.id)
|
notifications = OnlineNotification.where(user_id: user.id)
|
||||||
.order( 'created_at DESC, id DESC' )
|
.order('created_at DESC, id DESC')
|
||||||
.limit( limit )
|
.limit(limit)
|
||||||
list = []
|
list = []
|
||||||
notifications.each do |item|
|
notifications.each do |item|
|
||||||
data = item.attributes
|
data = item.attributes
|
||||||
data['object'] = ObjectLookup.by_id( data['object_lookup_id'] )
|
data['object'] = ObjectLookup.by_id(data['object_lookup_id'])
|
||||||
data['type'] = TypeLookup.by_id( data['type_lookup_id'] )
|
data['type'] = TypeLookup.by_id(data['type_lookup_id'])
|
||||||
data.delete('object_lookup_id')
|
data.delete('object_lookup_id')
|
||||||
data.delete('type_lookup_id')
|
data.delete('type_lookup_id')
|
||||||
list.push data
|
list.push data
|
||||||
|
@ -107,18 +125,18 @@ return all online notifications of an user
|
||||||
|
|
||||||
return all online notifications of an object
|
return all online notifications of an object
|
||||||
|
|
||||||
notifications = OnlineNotification.list_by_object( 'Ticket', 123 )
|
notifications = OnlineNotification.list_by_object('Ticket', 123)
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.list_by_object( object_name, o_id)
|
def self.list_by_object(object_name, o_id)
|
||||||
object_id = ObjectLookup.by_name( object_name )
|
object_id = ObjectLookup.by_name(object_name)
|
||||||
notifications = OnlineNotification.where(
|
notifications = OnlineNotification.where(
|
||||||
object_lookup_id: object_id,
|
object_lookup_id: object_id,
|
||||||
o_id: o_id,
|
o_id: o_id,
|
||||||
)
|
)
|
||||||
.order( 'created_at DESC, id DESC' )
|
.order('created_at DESC, id DESC')
|
||||||
.limit( 10_000 )
|
.limit(10_000)
|
||||||
notifications
|
notifications
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -126,12 +144,12 @@ return all online notifications of an object
|
||||||
|
|
||||||
mark online notification as seen by object
|
mark online notification as seen by object
|
||||||
|
|
||||||
OnlineNotification.seen_by_object( 'Ticket', 123, user_id )
|
OnlineNotification.seen_by_object('Ticket', 123, user_id)
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.seen_by_object(object_name, o_id)
|
def self.seen_by_object(object_name, o_id)
|
||||||
object_id = ObjectLookup.by_name( object_name )
|
object_id = ObjectLookup.by_name(object_name)
|
||||||
notifications = OnlineNotification.where(
|
notifications = OnlineNotification.where(
|
||||||
object_lookup_id: object_id,
|
object_lookup_id: object_id,
|
||||||
o_id: o_id,
|
o_id: o_id,
|
||||||
|
@ -148,7 +166,7 @@ mark online notification as seen by object
|
||||||
|
|
||||||
return all online notifications of an user with assets
|
return all online notifications of an user with assets
|
||||||
|
|
||||||
OnlineNotification.list_full( user )
|
OnlineNotification.list_full(user)
|
||||||
|
|
||||||
returns:
|
returns:
|
||||||
|
|
||||||
|
|
|
@ -135,39 +135,61 @@ returns
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.process_pending
|
def self.process_pending
|
||||||
|
|
||||||
ticket_states = Ticket::State.where(
|
|
||||||
state_type_id: Ticket::StateType.find_by( name: 'pending action' ),
|
|
||||||
)
|
|
||||||
.where.not(next_state_id: nil)
|
|
||||||
|
|
||||||
return [] if !ticket_states
|
|
||||||
|
|
||||||
next_state_map = {}
|
|
||||||
ticket_states.each { |state|
|
|
||||||
next_state_map[state.id] = state.next_state_id
|
|
||||||
}
|
|
||||||
|
|
||||||
tickets = where(
|
|
||||||
state_id: next_state_map.keys,
|
|
||||||
)
|
|
||||||
.where( 'pending_time <= ?', Time.zone.now )
|
|
||||||
|
|
||||||
return [] if !tickets
|
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
tickets.each { |ticket|
|
|
||||||
ticket.state_id = next_state_map[ticket.state_id]
|
|
||||||
ticket.updated_at = Time.zone.now
|
|
||||||
ticket.updated_by_id = 1
|
|
||||||
ticket.save!
|
|
||||||
|
|
||||||
result.push ticket
|
# process pending action tickets
|
||||||
}
|
pending_action = Ticket::StateType.find_by(name: 'pending action')
|
||||||
|
ticket_states_pending_action = Ticket::State.where(state_type_id: pending_action)
|
||||||
|
.where.not(next_state_id: nil)
|
||||||
|
if !ticket_states_pending_action.empty?
|
||||||
|
next_state_map = {}
|
||||||
|
ticket_states_pending_action.each { |state|
|
||||||
|
next_state_map[state.id] = state.next_state_id
|
||||||
|
}
|
||||||
|
|
||||||
# we do not have an destructor at this point, so we need to
|
tickets = where(state_id: next_state_map.keys)
|
||||||
# execute ticket events manually
|
.where('pending_time <= ?', Time.zone.now)
|
||||||
Observer::Ticket::Notification.transaction
|
|
||||||
|
tickets.each { |ticket|
|
||||||
|
ticket.state_id = next_state_map[ticket.state_id]
|
||||||
|
ticket.updated_at = Time.zone.now
|
||||||
|
ticket.updated_by_id = 1
|
||||||
|
ticket.save!
|
||||||
|
|
||||||
|
# we do not have an destructor at this point, so we need to
|
||||||
|
# execute ticket events manually
|
||||||
|
Observer::Ticket::Notification.transaction
|
||||||
|
|
||||||
|
result.push ticket
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# process pending reminder tickets
|
||||||
|
pending_reminder = Ticket::StateType.find_by(name: 'pending reminder')
|
||||||
|
ticket_states_pending_reminder = Ticket::State.where(state_type_id: pending_reminder)
|
||||||
|
|
||||||
|
if !ticket_states_pending_reminder.empty?
|
||||||
|
reminder_state_map = {}
|
||||||
|
ticket_states_pending_reminder.each { |state|
|
||||||
|
reminder_state_map[state.id] = state.next_state_id
|
||||||
|
}
|
||||||
|
|
||||||
|
tickets = where(state_id: reminder_state_map.keys)
|
||||||
|
.where('pending_time <= ?', Time.zone.now)
|
||||||
|
|
||||||
|
tickets.each { |ticket|
|
||||||
|
|
||||||
|
# send notification
|
||||||
|
bg = Observer::Ticket::Notification::BackgroundJob.new(
|
||||||
|
ticket_id: ticket.id,
|
||||||
|
article_id: ticket.articles.last.id,
|
||||||
|
type: 'reminder_reached',
|
||||||
|
)
|
||||||
|
bg.perform
|
||||||
|
|
||||||
|
result.push ticket
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
|
@ -78,7 +78,7 @@ class User < ApplicationModel
|
||||||
fullname of user
|
fullname of user
|
||||||
|
|
||||||
user = User.find(123)
|
user = User.find(123)
|
||||||
result = user.fulename
|
result = user.fullname
|
||||||
|
|
||||||
returns
|
returns
|
||||||
|
|
||||||
|
@ -87,20 +87,48 @@ returns
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def fullname
|
def fullname
|
||||||
fullname = ''
|
name = ''
|
||||||
if firstname && !firstname.empty?
|
if firstname && !firstname.empty?
|
||||||
fullname = fullname + firstname
|
name = name + firstname
|
||||||
end
|
end
|
||||||
if lastname && !lastname.empty?
|
if lastname && !lastname.empty?
|
||||||
if fullname != ''
|
if name != ''
|
||||||
fullname = fullname + ' '
|
name += ' '
|
||||||
end
|
end
|
||||||
fullname = fullname + lastname
|
name += lastname
|
||||||
end
|
end
|
||||||
if fullname == '' && email
|
if name == '' && email
|
||||||
fullname = email
|
name = email
|
||||||
end
|
end
|
||||||
fullname
|
name
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
longname of user
|
||||||
|
|
||||||
|
user = User.find(123)
|
||||||
|
result = user.longname
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
result = "Bob Smith"
|
||||||
|
|
||||||
|
or with org
|
||||||
|
|
||||||
|
result = "Bob Smith (Org ABC)"
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def longname
|
||||||
|
name = fullname
|
||||||
|
if organization_id
|
||||||
|
organization = Organization.lookup(id: organization_id)
|
||||||
|
if organization
|
||||||
|
name += " (#{organization.name})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
name
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
|
@ -2,7 +2,7 @@ Neues Ticket (<%= d 'ticket.title' %>)
|
||||||
|
|
||||||
<p>Hallo <%= d 'recipient.firstname' %>,</p>
|
<p>Hallo <%= d 'recipient.firstname' %>,</p>
|
||||||
<br>
|
<br>
|
||||||
<p>es wurde ein neues Ticket (<%= d 'ticket.title' %>) von "<b><%= d 'ticket.updated_by.fullname' %></b>" erstellt.</p>
|
<p>es wurde ein neues Ticket (<%= d 'ticket.title' %>) von "<b><%= d 'ticket.updated_by.longname' %></b>" erstellt.</p>
|
||||||
<br>
|
<br>
|
||||||
<p>
|
<p>
|
||||||
<%= t 'Group' %>: <%= d 'ticket.group.name' %><br>
|
<%= t 'Group' %>: <%= d 'ticket.group.name' %><br>
|
||||||
|
|
|
@ -2,7 +2,7 @@ New Ticket (<%= d 'ticket.title' %>)
|
||||||
|
|
||||||
<p>Hi <%= d 'recipient.firstname' %>,</p>
|
<p>Hi <%= d 'recipient.firstname' %>,</p>
|
||||||
<br>
|
<br>
|
||||||
<p>a new Ticket (<%= d 'ticket.title' %>) has been created by "<b><%= d 'ticket.updated_by.fullname' %></b>".</p>
|
<p>a new Ticket (<%= d 'ticket.title' %>) has been created by "<b><%= d 'ticket.updated_by.longname' %></b>".</p>
|
||||||
<br>
|
<br>
|
||||||
<p>
|
<p>
|
||||||
<%= t 'Group' %>: <%= d 'ticket.group.name' %><br>
|
<%= t 'Group' %>: <%= d 'ticket.group.name' %><br>
|
||||||
|
|
18
app/views/mailer/ticket_reminder_reached/de.html.erb
Normal file
18
app/views/mailer/ticket_reminder_reached/de.html.erb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
Warten auf Erinnerung erreicht! (<%= d 'ticket.title' %>)
|
||||||
|
|
||||||
|
<p>Hallo <%= d 'recipient.firstname' %>,</p>
|
||||||
|
<br>
|
||||||
|
<p>dieses Ticket benötigt Deine Aufmerksamkeit, warten auf Erinnerung für (<%= d 'ticket.title' %>) mit dem Kunden "<b><%= d 'ticket.customer.longname' %></b>" ist erreicht.</p>
|
||||||
|
<br>
|
||||||
|
<% if @objects[:article] %>
|
||||||
|
<p>
|
||||||
|
<%= t 'Information' %>:
|
||||||
|
<blockquote type="cite">
|
||||||
|
<%= a 'article' %>
|
||||||
|
</blockquote>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
<br>
|
||||||
|
<p>
|
||||||
|
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
|
||||||
|
</p>
|
18
app/views/mailer/ticket_reminder_reached/en.html.erb
Normal file
18
app/views/mailer/ticket_reminder_reached/en.html.erb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
Reminder reached (<%= d 'ticket.title' %>)
|
||||||
|
|
||||||
|
<p>Hi <%= d 'recipient.firstname' %>,</p>
|
||||||
|
<br>
|
||||||
|
<p>ticket needs attachen, reminder reached for Ticket (<%= d 'ticket.title' %>) with customer "<b><%= d 'ticket.customer.longname' %></b>".</p>
|
||||||
|
<br>
|
||||||
|
<% if @objects[:article] %>
|
||||||
|
<p>
|
||||||
|
<%= t 'Information' %>:
|
||||||
|
<blockquote type="cite">
|
||||||
|
<%= a 'article' %>
|
||||||
|
</blockquote>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
<br>
|
||||||
|
<p>
|
||||||
|
<a href="<%= c 'http_type' %>://<%= c 'fqdn' %>/#ticket/zoom/<%= d 'ticket.id' %>" target="zammad_app"><%= t 'View this in Zammad' %></a>
|
||||||
|
</p>
|
|
@ -3,7 +3,7 @@ Ticket aktualisiert (<%= d 'ticket.title' %>)
|
||||||
<p>Hi <%= d 'recipient.firstname' %>,</p>
|
<p>Hi <%= d 'recipient.firstname' %>,</p>
|
||||||
<br>
|
<br>
|
||||||
<div>
|
<div>
|
||||||
Ticket (<%= d 'ticket.title' %>) wurde von "<b><%= d 'ticket.updated_by.fullname' %></b>" aktualisiert.
|
Ticket (<%= d 'ticket.title' %>) wurde von "<b><%= d 'ticket.updated_by.longname' %></b>" aktualisiert.
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<% if @objects[:changes] && !@objects[:changes].empty? %>
|
<% if @objects[:changes] && !@objects[:changes].empty? %>
|
||||||
|
|
|
@ -3,7 +3,7 @@ Updated Ticket (<%= d 'ticket.title' %>)
|
||||||
<p>Hi <%= d 'recipient.firstname' %>,</p>
|
<p>Hi <%= d 'recipient.firstname' %>,</p>
|
||||||
<br>
|
<br>
|
||||||
<div>
|
<div>
|
||||||
Ticket (<%= d 'ticket.title' %>) has been updated by "<b><%= d 'ticket.updated_by.fullname' %></b>".
|
Ticket (<%= d 'ticket.title' %>) has been updated by "<b><%= d 'ticket.updated_by.longname' %></b>".
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<% if @objects[:changes] && !@objects[:changes].empty? %>
|
<% if @objects[:changes] && !@objects[:changes].empty? %>
|
||||||
|
|
Loading…
Reference in a new issue