ticket.rb 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. class Ticket < ApplicationModel
  2. before_create :number_generate, :check_defaults
  3. before_update :check_defaults
  4. before_destroy :destroy_dependencies
  5. belongs_to :group
  6. has_many :articles, :class_name => 'Ticket::Article', :after_add => :cache_update, :after_remove => :cache_update
  7. belongs_to :organization
  8. belongs_to :ticket_state, :class_name => 'Ticket::State'
  9. belongs_to :ticket_priority, :class_name => 'Ticket::Priority'
  10. belongs_to :owner, :class_name => 'User'
  11. belongs_to :customer, :class_name => 'User'
  12. belongs_to :created_by, :class_name => 'User'
  13. belongs_to :create_article_type, :class_name => 'Ticket::Article::Type'
  14. belongs_to :create_article_sender, :class_name => 'Ticket::Article::Sender'
  15. def self.number_check (string)
  16. self.number_adapter.number_check_item(string)
  17. end
  18. def agent_of_group
  19. Group.find( self.group_id ).users.where( :active => true ).joins(:roles).where( 'roles.name' => 'Agent', 'roles.active' => true ).uniq()
  20. end
  21. def self.agents
  22. User.where( :active => true ).joins(:roles).where( 'roles.name' => 'Agent', 'roles.active' => true ).uniq()
  23. end
  24. def merge_to(data)
  25. # update articles
  26. Ticket::Article.where( :ticket_id => self.id ).update_all( ['ticket_id = ?', data[:ticket_id] ] )
  27. # update history
  28. # create new merge article
  29. Ticket::Article.create(
  30. :created_by_id => data[:created_by_id],
  31. :ticket_id => self.id,
  32. :ticket_article_type_id => Ticket::Article::Type.lookup( :name => 'note' ).id,
  33. :ticket_article_sender_id => Ticket::Article::Sender.lookup( :name => 'Agent' ).id,
  34. :body => 'merged',
  35. :internal => false
  36. )
  37. # add history to both
  38. # link tickets
  39. Link.add(
  40. :link_type => 'parent',
  41. :link_object_source => 'Ticket',
  42. :link_object_source_value => data[:ticket_id],
  43. :link_object_target => 'Ticket',
  44. :link_object_target_value => self.id
  45. )
  46. # set state to 'merged'
  47. self.ticket_state_id = Ticket::State.lookup( :name => 'merged' ).id
  48. # rest owner
  49. self.owner_id = User.where( :login => '-' ).first.id
  50. # save ticket
  51. self.save
  52. end
  53. # def self.agent
  54. # Role.where( :name => ['Agent'], :active => true ).first.users.where( :active => true ).uniq()
  55. # end
  56. def subject_build (subject)
  57. # clena subject
  58. subject = self.subject_clean(subject)
  59. ticket_hook = Setting.get('ticket_hook')
  60. ticket_hook_divider = Setting.get('ticket_hook_divider')
  61. # none position
  62. if Setting.get('ticket_hook_position') == 'none'
  63. return subject
  64. end
  65. # right position
  66. if Setting.get('ticket_hook_position') == 'right'
  67. return subject + " [#{ticket_hook}#{ticket_hook_divider}#{self.number}] "
  68. end
  69. # left position
  70. return "[#{ticket_hook}#{ticket_hook_divider}#{self.number}] " + subject
  71. end
  72. def subject_clean (subject)
  73. ticket_hook = Setting.get('ticket_hook')
  74. ticket_hook_divider = Setting.get('ticket_hook_divider')
  75. ticket_subject_size = Setting.get('ticket_subject_size')
  76. # remove all possible ticket hook formats with []
  77. subject = subject.gsub /\[#{ticket_hook}: #{self.number}\](\s+?|)/, ''
  78. subject = subject.gsub /\[#{ticket_hook}:#{self.number}\](\s+?|)/, ''
  79. subject = subject.gsub /\[#{ticket_hook}#{ticket_hook_divider}#{self.number}\](\s+?|)/, ''
  80. # remove all possible ticket hook formats without []
  81. subject = subject.gsub /#{ticket_hook}: #{self.number}(\s+?|)/, ''
  82. subject = subject.gsub /#{ticket_hook}:#{self.number}(\s+?|)/, ''
  83. subject = subject.gsub /#{ticket_hook}#{ticket_hook_divider}#{self.number}(\s+?|)/, ''
  84. # remove leading "..:\s" and "..[\d+]:\s" e. g. "Re: " or "Re[5]: "
  85. subject = subject.gsub /^(..(\[\d+\])?:\s)+/, ''
  86. # resize subject based on config
  87. if subject.length > ticket_subject_size.to_i
  88. subject = subject[ 0, ticket_subject_size.to_i ] + '[...]'
  89. end
  90. return subject
  91. end
  92. # ticket.permission(
  93. # :current_user => 123
  94. # )
  95. def permission (data)
  96. # check customer
  97. if data[:current_user].is_role('Customer')
  98. # access ok if its own ticket
  99. return true if self.customer_id == data[:current_user].id
  100. # access ok if its organization ticket
  101. if data[:current_user].organization_id && self.organization_id
  102. return true if self.organization_id == data[:current_user].organization_id
  103. end
  104. # no access
  105. return false
  106. end
  107. # check agent
  108. return true if self.owner_id == data[:current_user].id
  109. data[:current_user].groups.each {|group|
  110. return true if self.group.id == group.id
  111. }
  112. return false
  113. end
  114. # Ticket.overview_list(
  115. # :current_user => 123,
  116. # )
  117. def self.overview_list (data)
  118. # get customer overviews
  119. if data[:current_user].is_role('Customer')
  120. role = data[:current_user].is_role( 'Customer' )
  121. if data[:current_user].organization_id && data[:current_user].organization.shared
  122. overviews = Overview.where( :role_id => role.id )
  123. else
  124. overviews = Overview.where( :role_id => role.id, :organization_shared => false )
  125. end
  126. return overviews
  127. end
  128. # get agent overviews
  129. role = data[:current_user].is_role( 'Agent' )
  130. overviews = Overview.where( :role_id => role.id )
  131. return overviews
  132. end
  133. # Ticket.overview(
  134. # :view => 'some_view_url',
  135. # :current_user => OBJECT,
  136. # )
  137. def self.overview (data)
  138. overviews = self.overview_list(data)
  139. # build up attributes hash
  140. overview_selected = nil
  141. overview_selected_raw = nil
  142. overviews.each { |overview|
  143. # remember selected view
  144. if data[:view] && data[:view] == overview.meta[:url]
  145. overview_selected = overview
  146. overview_selected_raw = Marshal.load( Marshal.dump(overview.attributes) )
  147. end
  148. # replace e.g. 'current_user.id' with current_user.id
  149. overview.condition.each { |item, value |
  150. if value && value.class.to_s == 'String'
  151. parts = value.split( '.', 2 )
  152. if parts[0] && parts[1] && parts[0] == 'current_user'
  153. overview.condition[item] = data[:current_user][parts[1].to_sym]
  154. end
  155. end
  156. }
  157. }
  158. if data[:view] && !overview_selected
  159. return
  160. end
  161. # sortby
  162. # prio
  163. # state
  164. # group
  165. # customer
  166. # order
  167. # asc
  168. # desc
  169. # groupby
  170. # prio
  171. # state
  172. # group
  173. # customer
  174. # all = attributes[:myopenassigned]
  175. # all.merge( { :group_id => groups } )
  176. # @tickets = Ticket.where(:group_id => groups, attributes[:myopenassigned] ).limit(params[:limit])
  177. # get only tickets with permissions
  178. if data[:current_user].is_role('Customer')
  179. group_ids = Group.select( 'groups.id' ).
  180. where( 'groups.active = ?', true ).
  181. map( &:id )
  182. else
  183. group_ids = Group.select( 'groups.id' ).joins(:users).
  184. where( 'groups_users.user_id = ?', [ data[:current_user].id ] ).
  185. where( 'groups.active = ?', true ).
  186. map( &:id )
  187. end
  188. # overview meta for navbar
  189. if !overview_selected
  190. # loop each overview
  191. result = []
  192. overviews.each { |overview|
  193. # get count
  194. count = Ticket.where( :group_id => group_ids ).where( overview.condition ).count()
  195. # get meta info
  196. all = overview.meta
  197. # push to result data
  198. result.push all.merge( { :count => count } )
  199. }
  200. return result
  201. end
  202. # get result list
  203. if data[:array]
  204. order_by = overview_selected[:order][:by].to_s + ' ' + overview_selected[:order][:direction].to_s
  205. if overview_selected.group_by && !overview_selected.group_by.empty?
  206. order_by = overview_selected.group_by + '_id, ' + order_by
  207. end
  208. tickets = Ticket.select( 'id' ).
  209. where( :group_id => group_ids ).
  210. where( overview_selected.condition ).
  211. order( order_by ).
  212. limit( 500 )
  213. ticket_ids = []
  214. tickets.each { |ticket|
  215. ticket_ids.push ticket.id
  216. }
  217. tickets_count = Ticket.where( :group_id => group_ids ).
  218. where( overview_selected.condition ).
  219. count()
  220. return {
  221. :ticket_list => ticket_ids,
  222. :tickets_count => tickets_count,
  223. :overview => overview_selected_raw,
  224. }
  225. end
  226. # get tickets for overview
  227. data[:start_page] ||= 1
  228. tickets = Ticket.where( :group_id => group_ids ).
  229. where( overview_selected.condition ).
  230. order( overview_selected[:order][:by].to_s + ' ' + overview_selected[:order][:direction].to_s ).
  231. limit( overview_selected.view[ data[:view_mode].to_sym ][:per_page] ).
  232. offset( overview_selected.view[ data[:view_mode].to_sym ][:per_page].to_i * ( data[:start_page].to_i - 1 ) )
  233. tickets_count = Ticket.where( :group_id => group_ids ).
  234. where( overview_selected.condition ).
  235. count()
  236. return {
  237. :tickets => tickets,
  238. :tickets_count => tickets_count,
  239. :overview => overview_selected_raw,
  240. }
  241. end
  242. # Ticket.create_attributes(
  243. # :current_user_id => 123,
  244. # )
  245. def self.create_attributes (data)
  246. # get groups
  247. group_ids = []
  248. Group.where( :active => true ).each { |group|
  249. group_ids.push group.id
  250. }
  251. # get related users
  252. # users = {}
  253. user_ids = []
  254. agents = {}
  255. Ticket.agents.each { |user|
  256. agents[ user.id ] = 1
  257. user_ids.push user.id
  258. }
  259. groups_users = {}
  260. group_ids.each {|group_id|
  261. groups_users[ group_id ] = []
  262. Group.find(group_id).users.each {|user|
  263. next if !agents[ user.id ]
  264. groups_users[ group_id ].push user.id
  265. # if !users[user.id]
  266. # users[user.id] = User.user_data_full(user.id)
  267. # end
  268. }
  269. }
  270. # get states
  271. ticket_state_ids = []
  272. Ticket::State.where( :active => true ).each { |state|
  273. ticket_state_ids.push state.id
  274. }
  275. # get priorities
  276. ticket_priority_ids = []
  277. Ticket::Priority.where( :active => true ).each { |priority|
  278. ticket_priority_ids.push priority.id
  279. }
  280. return {
  281. # :users => users,
  282. :owner_id => user_ids,
  283. :group_id__owner_id => groups_users,
  284. :group_id => group_ids,
  285. :ticket_state_id => ticket_state_ids,
  286. :ticket_priority_id => ticket_priority_ids,
  287. }
  288. end
  289. def self.number_adapter
  290. # load backend based on config
  291. adapter_name = Setting.get('ticket_number')
  292. adapter = nil
  293. case adapter_name
  294. when Symbol, String
  295. require "ticket/number/#{adapter_name.to_s.downcase}"
  296. adapter = Ticket::Number.const_get("#{adapter_name.to_s.capitalize}")
  297. else
  298. raise "Missing number_adapter '#{adapter_name}'"
  299. end
  300. return adapter
  301. end
  302. private
  303. def number_generate
  304. # generate number
  305. (1..25_000).each do |i|
  306. number = Ticket.number_adapter.number_generate_item()
  307. ticket = Ticket.where( :number => number ).first
  308. if ticket != nil
  309. number = Ticket.number_adapter.number_generate_item()
  310. else
  311. self.number = number
  312. return number
  313. end
  314. end
  315. end
  316. def check_defaults
  317. if !self.owner_id
  318. self.owner_id = 1
  319. end
  320. # if self.customer_id && ( !self.organization_id || self.organization_id.empty? )
  321. if self.customer_id
  322. customer = User.find( self.customer_id )
  323. if self.organization_id != customer.organization_id
  324. self.organization_id = customer.organization_id
  325. end
  326. end
  327. end
  328. def destroy_dependencies
  329. # delete history
  330. History.history_destroy( 'Ticket', self.id )
  331. # delete articles
  332. self.articles.destroy_all
  333. end
  334. class Number
  335. end
  336. class Flag < ApplicationModel
  337. end
  338. class Priority < ApplicationModel
  339. self.table_name = 'ticket_priorities'
  340. validates :name, :presence => true
  341. end
  342. class StateType < ApplicationModel
  343. has_many :states, :class_name => 'Ticket::State'
  344. validates :name, :presence => true
  345. end
  346. class State < ApplicationModel
  347. belongs_to :state_type, :class_name => 'Ticket::StateType'
  348. validates :name, :presence => true
  349. end
  350. end