time_accounting.rb 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Service::Ticket::Update::Validator
  3. class TimeAccounting < Base
  4. def valid!
  5. return if !Setting.get('time_accounting')
  6. # Only kick in if an article was actually created.
  7. return if @article_data.blank?
  8. return if @article_data[:time_unit].present?
  9. return if !TicketPolicy.new(@user, @ticket).agent_update_access?
  10. return if !time_accounting_condition_matches?
  11. raise Error
  12. end
  13. class Error < Service::Ticket::Update::Validator::BaseError
  14. def initialize
  15. super(__('The ticket time accounting condition is met.'))
  16. end
  17. end
  18. private
  19. def time_accounting_condition_matches?
  20. CoreWorkflow.matches_selector?(
  21. check: 'selected',
  22. id: @ticket.id,
  23. user: @user,
  24. params: params,
  25. selector: Setting.get('time_accounting_selector')&.dig('condition') || {},
  26. )
  27. end
  28. # In GraphQL context, all IDs are transformed into corresponding records.
  29. # However, Core Workflow expects only record names as param values, and will try to lookup the correct IDs.
  30. # Therefore, here we map them back to IDs in order to skip this lookup mechanism,
  31. # since all information is present at this point.
  32. def params
  33. { 'id' => @ticket.id }.merge(
  34. map_to_ids(@ticket_data).merge(
  35. 'article' => map_to_ids(@article_data),
  36. )
  37. )
  38. end
  39. def map_to_ids(input)
  40. {}.tap do |data|
  41. input.each do |key, value|
  42. if !value.is_a?(ApplicationModel::CanLookup)
  43. data[key] = value
  44. next
  45. end
  46. next if ticket_data["#{key}_id"].present?
  47. data["#{key}_id"] = value.id
  48. end
  49. end
  50. end
  51. end
  52. end