time_accountings_controller.rb 11 KB

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