time_accountings_controller.rb 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. class TimeAccountingsController < ApplicationController
  3. prepend_before_action :authenticate_and_authorize!
  4. def by_activity
  5. year = params[:year] || Time.zone.now.year
  6. month = params[:month] || Time.zone.now.month
  7. start_periode = Time.zone.parse("#{year}-#{month}-01")
  8. end_periode = start_periode.end_of_month
  9. records = []
  10. Ticket::TimeAccounting.where('created_at >= ? AND created_at <= ?', start_periode, end_periode).pluck(:ticket_id, :ticket_article_id, :time_unit, :type_id, :created_by_id, :created_at).each do |record|
  11. records.push record
  12. end
  13. customers = {}
  14. organizations = {}
  15. types = {}
  16. agents = {}
  17. results = []
  18. records.each do |record|
  19. ticket = Ticket.lookup(id: record[0])
  20. next if !ticket
  21. customers[ticket.customer_id] ||= User.lookup(id: ticket.customer_id).fullname
  22. organizations[ticket.organization_id] ||= Organization.lookup(id: ticket.organization_id)&.name
  23. types[record[3]] ||= Ticket::TimeAccounting::Type.lookup(id: record[3])&.name
  24. agents[record[4]] ||= User.lookup(id: record[4])
  25. result = if params[:download]
  26. [
  27. ticket.number,
  28. ticket.title,
  29. customers[ticket.customer_id] || '-',
  30. organizations[ticket.organization_id] || '-',
  31. agents[record[4]].fullname,
  32. agents[record[4]].login,
  33. record[2],
  34. *([types[record[3]] || '-'] if Setting.get('time_accounting_types')),
  35. record[5]
  36. ]
  37. else
  38. {
  39. ticket: ticket.attributes,
  40. time_unit: record[2],
  41. type: ((types[record[3]] || '-') if Setting.get('time_accounting_types')),
  42. customer: customers[ticket.customer_id] || '-',
  43. organization: organizations[ticket.organization_id] || '-',
  44. agent: agents[record[4]].fullname,
  45. created_at: record[5],
  46. }.compact
  47. end
  48. results.push result
  49. end
  50. if !params[:download]
  51. results = results.last(params[:limit].to_i) if params[:limit]
  52. render json: results
  53. return
  54. end
  55. header = [
  56. {
  57. name: __('Ticket#'),
  58. width: 20,
  59. },
  60. {
  61. name: __('Title'),
  62. width: 20,
  63. },
  64. {
  65. name: "#{__('Customer')} - #{__('Name')}",
  66. width: 20,
  67. },
  68. {
  69. name: __('Organization'),
  70. width: 20,
  71. },
  72. {
  73. name: "#{__('Agent')} - #{__('Name')}",
  74. width: 20,
  75. },
  76. {
  77. name: "#{__('Agent')} - #{__('Login')}",
  78. width: 20,
  79. },
  80. {
  81. name: __('Time Units'),
  82. width: 10,
  83. data_type: 'float'
  84. },
  85. *(if Setting.get('time_accounting_types')
  86. [{
  87. name: __('Activity Type'),
  88. width: 20,
  89. }]
  90. end),
  91. {
  92. name: __('Created at'),
  93. width: 20,
  94. },
  95. ]
  96. excel = ExcelSheet.new(
  97. title: "By Activity #{year}-#{month}",
  98. header: header,
  99. records: results,
  100. timezone: params[:timezone],
  101. locale: current_user.locale,
  102. )
  103. send_data(
  104. excel.content,
  105. filename: "by_activity-#{year}-#{month}.xlsx",
  106. type: ExcelSheet::CONTENT_TYPE,
  107. disposition: 'attachment'
  108. )
  109. end
  110. def by_ticket
  111. year = params[:year] || Time.zone.now.year
  112. month = params[:month] || Time.zone.now.month
  113. start_periode = Time.zone.parse("#{year}-#{month}-01")
  114. end_periode = start_periode.end_of_month
  115. time_unit = {}
  116. Ticket::TimeAccounting.where('created_at >= ? AND created_at <= ?', start_periode, end_periode).pluck(:ticket_id, :time_unit, :created_by_id).each do |record|
  117. if !time_unit[record[0]]
  118. time_unit[record[0]] = {
  119. time_unit: 0,
  120. agent_id: record[2],
  121. }
  122. end
  123. time_unit[record[0]][:time_unit] += record[1]
  124. end
  125. if !params[:download]
  126. customers = {}
  127. organizations = {}
  128. agents = {}
  129. results = []
  130. time_unit.each do |ticket_id, local_time_unit|
  131. ticket = Ticket.lookup(id: ticket_id)
  132. next if !ticket
  133. customers[ticket.customer_id] ||= User.lookup(id: ticket.customer_id).fullname
  134. organizations[ticket.organization_id] ||= Organization.lookup(id: ticket.organization_id)&.name
  135. agents[local_time_unit[:agent_id]] ||= User.lookup(id: local_time_unit[:agent_id]).fullname
  136. result = {
  137. ticket: ticket.attributes,
  138. time_unit: local_time_unit[:time_unit],
  139. customer: customers[ticket.customer_id] || '-',
  140. organization: organizations[ticket.organization_id] || '-',
  141. agent: agents[local_time_unit[:agent_id]],
  142. }
  143. results.push result
  144. end
  145. results = results.last(params[:limit].to_i) if params[:limit]
  146. render json: results
  147. return
  148. end
  149. ticket_ids = []
  150. additional_attributes = []
  151. additional_attributes_header = [{ display: __('Time Units'), name: 'time_unit_for_range', width: 10, data_type: 'float' }]
  152. time_unit.each do |ticket_id, local_time_unit|
  153. ticket_ids.push ticket_id
  154. additional_attribute = {
  155. time_unit_for_range: local_time_unit[:time_unit],
  156. }
  157. additional_attributes.push additional_attribute
  158. end
  159. excel = ExcelSheet::Ticket.new(
  160. title: "Tickets: #{year}-#{month}",
  161. ticket_ids: ticket_ids,
  162. additional_attributes: additional_attributes,
  163. additional_attributes_header: additional_attributes_header,
  164. timezone: params[:timezone],
  165. locale: current_user.locale,
  166. )
  167. send_data(
  168. excel.content,
  169. filename: "by_ticket-#{year}-#{month}.xlsx",
  170. type: ExcelSheet::CONTENT_TYPE,
  171. disposition: 'attachment'
  172. )
  173. end
  174. def by_customer
  175. year = params[:year] || Time.zone.now.year
  176. month = params[:month] || Time.zone.now.month
  177. start_periode = Time.zone.parse("#{year}-#{month}-01")
  178. end_periode = start_periode.end_of_month
  179. time_unit = {}
  180. Ticket::TimeAccounting.where('created_at >= ? AND created_at <= ?', start_periode, end_periode).pluck(:ticket_id, :time_unit, :created_by_id).each do |record|
  181. time_unit[record[0]] ||= {
  182. time_unit: 0,
  183. agent_id: record[2],
  184. }
  185. time_unit[record[0]][:time_unit] += record[1]
  186. end
  187. customers = {}
  188. time_unit.each do |ticket_id, local_time_unit|
  189. ticket = Ticket.lookup(id: ticket_id)
  190. next if !ticket
  191. customers[ticket.customer_id] ||= {}
  192. customers[ticket.customer_id][ticket.organization_id] ||= {
  193. customer: User.lookup(id: ticket.customer_id).attributes,
  194. organization: Organization.lookup(id: ticket.organization_id)&.attributes,
  195. time_unit: 0,
  196. }
  197. customers[ticket.customer_id][ticket.organization_id][:time_unit] += local_time_unit[:time_unit]
  198. end
  199. results = []
  200. customers.each_value do |organizations|
  201. organizations.each_value do |content|
  202. results.push content
  203. end
  204. end
  205. if params[:download]
  206. header = [
  207. {
  208. name: __('Customer'),
  209. width: 30,
  210. },
  211. {
  212. name: __('Organization'),
  213. width: 30,
  214. },
  215. {
  216. name: __('Time Units'),
  217. width: 10,
  218. data_type: 'float'
  219. }
  220. ]
  221. records = []
  222. results.each do |row|
  223. customer_name = User.find(row[:customer]['id']).fullname
  224. organization_name = ''
  225. if row[:organization].present?
  226. organization_name = row[:organization]['name']
  227. end
  228. result_row = [customer_name, organization_name, row[:time_unit]]
  229. records.push result_row
  230. end
  231. excel = ExcelSheet.new(
  232. title: "By Customer #{year}-#{month}",
  233. header: header,
  234. records: records,
  235. timezone: params[:timezone],
  236. locale: current_user.locale,
  237. )
  238. send_data(
  239. excel.content,
  240. filename: "by_customer-#{year}-#{month}.xlsx",
  241. type: ExcelSheet::CONTENT_TYPE,
  242. disposition: 'attachment'
  243. )
  244. return
  245. end
  246. results = results.last(params[:limit].to_i) if params[:limit]
  247. render json: results
  248. end
  249. def by_organization
  250. year = params[:year] || Time.zone.now.year
  251. month = params[:month] || Time.zone.now.month
  252. start_periode = Time.zone.parse("#{year}-#{month}-01")
  253. end_periode = start_periode.end_of_month
  254. time_unit = {}
  255. Ticket::TimeAccounting.where('created_at >= ? AND created_at <= ?', start_periode, end_periode).pluck(:ticket_id, :time_unit, :created_by_id).each do |record|
  256. time_unit[record[0]] ||= {
  257. time_unit: 0,
  258. agent_id: record[2],
  259. }
  260. time_unit[record[0]][:time_unit] += record[1]
  261. end
  262. organizations = {}
  263. time_unit.each do |ticket_id, local_time_unit|
  264. ticket = Ticket.lookup(id: ticket_id)
  265. next if !ticket
  266. next if !ticket.organization_id
  267. organizations[ticket.organization_id] ||= {
  268. organization: Organization.lookup(id: ticket.organization_id).attributes,
  269. time_unit: 0,
  270. }
  271. organizations[ticket.organization_id][:time_unit] += local_time_unit[:time_unit]
  272. end
  273. results = []
  274. organizations.each_value do |content|
  275. results.push content
  276. end
  277. if params[:download]
  278. header = [
  279. {
  280. name: __('Organization'),
  281. width: 40,
  282. },
  283. {
  284. name: __('Time Units'),
  285. width: 20,
  286. data_type: 'float',
  287. }
  288. ]
  289. records = []
  290. results.each do |row|
  291. organization_name = ''
  292. if row[:organization].present?
  293. organization_name = row[:organization]['name']
  294. end
  295. result_row = [organization_name, row[:time_unit]]
  296. records.push result_row
  297. end
  298. excel = ExcelSheet.new(
  299. title: "By Organization #{year}-#{month}",
  300. header: header,
  301. records: records,
  302. timezone: params[:timezone],
  303. locale: current_user.locale,
  304. )
  305. send_data(
  306. excel.content,
  307. filename: "by_organization-#{year}-#{month}.xlsx",
  308. type: ExcelSheet::CONTENT_TYPE,
  309. disposition: 'attachment'
  310. )
  311. return
  312. end
  313. results = results.last(params[:limit].to_i) if params[:limit]
  314. render json: results
  315. end
  316. end