ticket_biz_break.rb 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Escalation
  3. class TicketBizBreak
  4. def initialize(ticket, calendar)
  5. @ticket = ticket
  6. @history_list = ticket.history_get
  7. @calendar = calendar
  8. end
  9. def biz_breaks
  10. accumulate_breaks(history_list_in_break.map { |from, to| history_range_to_breaks(from, to) })
  11. end
  12. private
  13. def history_list_states
  14. @history_list_states ||= @history_list.select { |elem| elem['attribute'] == 'state' }
  15. end
  16. def history_list_in_break
  17. @history_list_in_break ||= begin
  18. history_list_states
  19. .tap { |elem| elem.unshift(mock_initial_state) if mock_initial_state }
  20. .each_cons(2) # group in from/to pairs
  21. .select { |from, to| range_on_break?(from, to) }
  22. end
  23. end
  24. def ignored_escalation_state_names
  25. @ignored_escalation_state_names ||= Ticket::State.where(ignore_escalation: true).map(&:name)
  26. end
  27. def range_on_break?(from, _to)
  28. ignored_escalation_state_names.include? from['value_to']
  29. end
  30. def history_range_to_breaks(from, to)
  31. date_from = from['created_at'].in_time_zone(@calendar.timezone)
  32. date_to = to['created_at'].in_time_zone(@calendar.timezone)
  33. (date_from.to_date..date_to.to_date).each_with_object({}) do |elem, memo|
  34. key = history_range_break_key(elem, date_from)
  35. value = history_range_break_value(elem, date_to)
  36. memo[elem] = { key => value }
  37. end
  38. end
  39. def history_range_break_key(elem, date_from)
  40. elem == date_from.to_date ? date_from.strftime('%H:%M') : '00:00'
  41. end
  42. def history_range_break_value(elem, date_to)
  43. elem == date_to.to_date ? date_to.strftime('%H:%M') : '24:00'
  44. end
  45. def accumulate_breaks(input)
  46. input.each_with_object({}) do |elem, memo|
  47. memo.deep_merge! elem
  48. end
  49. end
  50. def mock_initial_state
  51. @mock_initial_state ||= begin
  52. first_state = history_list_states.first
  53. # if history set right on ticket creation, no need for extra step
  54. if first_state&.dig('created_at') == @ticket.created_at
  55. nil
  56. else
  57. {
  58. 'value_to' => first_state&.dig('value_from') || @ticket.state.name, # if no history yet, use current state
  59. 'created_at' => @ticket.created_at
  60. }
  61. end
  62. end
  63. end
  64. end
  65. end