diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.coffee index 9890278d2..72c909783 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom.coffee @@ -428,6 +428,8 @@ class App.TicketZoom extends App.Controller callback: @submit task_key: @task_key ) + #if @shown + # @attributeBar.start() @form_id = App.ControllerForm.formId() @@ -660,7 +662,7 @@ class App.TicketZoom extends App.Controller taskAction = @$('.js-secondaryActionButtonLabel').data('type') - ticketParams = @formParam( @$('.edit') ) + ticketParams = @formParam(@$('.edit')) # validate ticket ticket = App.Ticket.find(@ticket_id) @@ -745,6 +747,35 @@ class App.TicketZoom extends App.Controller ticket.article = article + if !ticket.article + @submitPost(e, ticket) + return + + # verify if time accounting is enabled + if @Config.get('time_accounting') isnt true + @submitPost(e, ticket) + return + + + # verify if time accounting is active for ticket + if false + @submitPost(e, ticket) + return + + # time tracking + new App.TicketZoomTimeAccounting( + container: @el.closest('.content') + ticket: ticket + cancelCallback: => + @formEnable(e) + submitCallback: (params) => + if params.time_unit + ticket.article.time_unit = params.time_unit + @submitPost(e, ticket) + ) + + submitPost: (e, ticket) => + # submit changes @ajax( id: "ticket_update_#{ticket.id}" diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee index 7c6d58e6d..2dd77dcb2 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee @@ -42,7 +42,7 @@ class App.TicketZoomSidebar extends App.ObserverController render: (ticket) => editTicket = (el) => - el.append('
') + el.append(App.view('ticket_zoom/sidebar_ticket')()) @edit = new Edit( object_id: ticket.id @@ -52,7 +52,7 @@ class App.TicketZoomSidebar extends App.ObserverController markForm: @markForm ) - if !@permissionCheck('ticket.customer') + if @permissionCheck('ticket.agent') @tagWidget = new App.WidgetTag( el: @el.find('.tags') object_type: 'Ticket' @@ -66,6 +66,11 @@ class App.TicketZoomSidebar extends App.ObserverController links: @links ) + @timeUnitWidget = new App.TicketZoomTimeUnit( + el: @el.find('.js-timeUnit') + object_id: ticket.id + ) + showTicketHistory = => new App.TicketHistory( ticket_id: ticket.id diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/time_accounting.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/time_accounting.coffee new file mode 100644 index 000000000..ae7df3cda --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/time_accounting.coffee @@ -0,0 +1,20 @@ +class App.TicketZoomTimeAccounting extends App.ControllerModal + buttonClose: true + buttonCancel: 'skip' + buttonSubmit: 'Account Time' + buttonClass: 'btn--success' + head: 'Time Accounting' + small: true + + content: -> + App.view('ticket_zoom/time_accounting')() + + onCancel: => + if @cancelCallback + @cancelCallback() + + onSubmit: => + @close() + if @submitCallback + params = @formParams() + @submitCallback(params) diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/time_unit.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/time_unit.coffee new file mode 100644 index 000000000..b5ecd023c --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/time_unit.coffee @@ -0,0 +1,11 @@ +class App.TicketZoomTimeUnit extends App.ObserverController + model: 'Ticket' + observe: + time_unit: true + + render: (ticket) => + return if !@permissionCheck('ticket.agent') + return if !ticket.time_unit + @html App.view('ticket_zoom/time_unit')( + ticket: ticket + ) diff --git a/app/assets/javascripts/app/controllers/time_accounting.coffee b/app/assets/javascripts/app/controllers/time_accounting.coffee new file mode 100644 index 000000000..e81fa2c48 --- /dev/null +++ b/app/assets/javascripts/app/controllers/time_accounting.coffee @@ -0,0 +1,205 @@ +class Index extends App.ControllerSubContent + requiredPermission: 'admin.time_accounting' + header: 'Time Accounting' + events: + 'change .js-timeAccountingSetting input': 'setTimeAccounting' + 'click .js-timePickerYear': 'setYear' + 'click .js-timePickerMonth': 'setMonth' + + elements: + '.js-timeAccountingSetting input': 'timeAccountingSetting' + + constructor: -> + super + + current = new Date() + currentDay = current.getDate() + currentMonth = current.getMonth() + 1 + currentYear = current.getFullYear() + currentWeek = current.getWeek() + if !@month + @month = currentMonth + if !@year + @year = currentYear + + @subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false) + + release: => + App.Setting.unsubscribe(@subscribeId) + + render: => + currentNewTagSetting = @Config.get('time_accounting') || false + #return if currentNewTagSetting is @lastNewTagSetting + @lastNewTagSetting = currentNewTagSetting + + timeRangeYear = [] + year = new Date().getFullYear() + for item in [year-2..year] + record = { + display: item + value: item + } + timeRangeYear.push record + + timeRangeMonth = [ + { + display: 'Jan' + value: 1 + }, + { + display: 'Feb' + value: 2 + }, + { + display: 'Mar' + value: 3 + }, + { + display: 'Apr' + value: 4, + }, + { + display: 'Mai' + value: 5, + }, + { + display: 'Jun' + value: 6, + }, + { + display: 'Jul' + value: 7, + }, + { + display: 'Aug' + value: 8, + }, + { + display: 'Sep' + value: 9, + }, + { + display: 'Oct' + value: 10, + }, + { + display: 'Nov' + value: 11, + }, + { + display: 'Dec' + value: 12, + }, + ] + + @html App.view('time_accounting/index')( + timeRangeYear: timeRangeYear + timeRangeMonth: timeRangeMonth + year: @year + month: @month + ) + + configure_attributes = [ + { name: 'condition', display: 'Conditions for effected objects', tag: 'ticket_selector', null: false, preview: false, action: false, hasChanged: false }, + ] + + new App.ControllerForm( + el: @$('.js-selector') + model: + configure_attributes: configure_attributes, + autofocus: true + ) + + new ByTicket( + el: @$('.js-tableTicket') + year: @year + month: @month + ) + + new ByCustomer( + el: @$('.js-tableCustomer') + year: @year + month: @month + ) + + new ByOrganization( + el: @$('.js-tableOrganization') + year: @year + month: @month + ) + + setTimeAccounting: (e) => + value = @timeAccountingSetting.prop('checked') + App.Setting.set('time_accounting', value) + + setYear: (e) => + e.preventDefault() + @year = $(e.target).data('type') + @render() + + setMonth: (e) => + e.preventDefault() + @month = $(e.target).data('type') + @render() + +class ByTicket extends App.Controller + constructor: -> + super + @load() + + load: => + @ajax( + id: 'by_ticket' + type: 'GET' + url: "#{@apiPath}/time_accounting/log/by_ticket/#{@year}/#{@month}" + processData: true + success: (data, status, xhr) => + @render(data) + ) + + render: (rows) => + @html App.view('time_accounting/by_ticket')( + rows: rows + ) + +class ByCustomer extends App.Controller + constructor: -> + super + @load() + + load: => + @ajax( + id: 'by_customer' + type: 'GET' + url: "#{@apiPath}/time_accounting/log/by_customer/#{@year}/#{@month}" + processData: true + success: (data, status, xhr) => + @render(data) + ) + + render: (rows) => + @html App.view('time_accounting/by_customer')( + rows: rows + ) + +class ByOrganization extends App.Controller + constructor: -> + super + @load() + + load: => + @ajax( + id: 'by_organization' + type: 'GET' + url: "#{@apiPath}/time_accounting/log/by_organization/#{@year}/#{@month}" + processData: true + success: (data, status, xhr) => + @render(data) + ) + + render: (rows) => + @html App.view('time_accounting/by_organization')( + rows: rows + ) + +App.Config.set('TimeAccounting', { prio: 8500, name: 'Time Accounting', parent: '#manage', target: '#manage/time_accounting', controller: Index, permission: ['admin.time_accounting'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/models/ticket_article.coffee b/app/assets/javascripts/app/models/ticket_article.coffee index 1eb27461f..dc98d58d8 100644 --- a/app/assets/javascripts/app/models/ticket_article.coffee +++ b/app/assets/javascripts/app/models/ticket_article.coffee @@ -1,5 +1,5 @@ class App.TicketArticle extends App.Model - @configure 'TicketArticle', 'from', 'to', 'cc', 'subject', 'body', 'content_type', 'ticket_id', 'type_id', 'sender_id', 'internal', 'in_reply_to', 'form_id', 'preferences', 'updated_at' + @configure 'TicketArticle', 'from', 'to', 'cc', 'subject', 'body', 'content_type', 'ticket_id', 'type_id', 'sender_id', 'internal', 'in_reply_to', 'form_id', 'time_unit', 'preferences', 'updated_at' @extend Spine.Model.Ajax @url: @apiPath + '/ticket_articles' @configure_attributes = [ diff --git a/app/assets/javascripts/app/views/ticket_zoom/sidebar_ticket.jst.eco b/app/assets/javascripts/app/views/ticket_zoom/sidebar_ticket.jst.eco new file mode 100644 index 000000000..9bd538e05 --- /dev/null +++ b/app/assets/javascripts/app/views/ticket_zoom/sidebar_ticket.jst.eco @@ -0,0 +1,6 @@ +
+
+
+
+ +
\ No newline at end of file diff --git a/app/assets/javascripts/app/views/ticket_zoom/time_accounting.jst.eco b/app/assets/javascripts/app/views/ticket_zoom/time_accounting.jst.eco new file mode 100644 index 000000000..242e7f409 --- /dev/null +++ b/app/assets/javascripts/app/views/ticket_zoom/time_accounting.jst.eco @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/app/assets/javascripts/app/views/ticket_zoom/time_unit.jst.eco b/app/assets/javascripts/app/views/ticket_zoom/time_unit.jst.eco new file mode 100644 index 000000000..25c122b58 --- /dev/null +++ b/app/assets/javascripts/app/views/ticket_zoom/time_unit.jst.eco @@ -0,0 +1,4 @@ +
+ +
<%= @ticket.time_unit %>
+
\ No newline at end of file diff --git a/app/assets/javascripts/app/views/time_accounting/by_customer.jst.eco b/app/assets/javascripts/app/views/time_accounting/by_customer.jst.eco new file mode 100644 index 000000000..bf30ac763 --- /dev/null +++ b/app/assets/javascripts/app/views/time_accounting/by_customer.jst.eco @@ -0,0 +1,23 @@ +<% if !@rows.length: %> + +
<%- @T('No Entries') %> +
+<% else: %> + + + + + + <% for row in @rows: %> + + +
<%- @T('Customer') %> + <%- @T('Organization') %> + <%- @T('Time Units') %> +
<%= row.customer.email %> + <% if row.organization: %><%= row.organization.name %><% end %> + <%= row.time_unit %> + <% end %> +
+ +<% end %> \ No newline at end of file diff --git a/app/assets/javascripts/app/views/time_accounting/by_organization.jst.eco b/app/assets/javascripts/app/views/time_accounting/by_organization.jst.eco new file mode 100644 index 000000000..af060eda7 --- /dev/null +++ b/app/assets/javascripts/app/views/time_accounting/by_organization.jst.eco @@ -0,0 +1,21 @@ +<% if !@rows.length: %> + +
<%- @T('No Entries') %> +
+<% else: %> + + + + + + <% for row in @rows: %> + + +
<%- @T('Organization') %> + <%- @T('Time Units') %> +
<%= row.organization.name %> + <%= row.time_unit %> + <% end %> +
+ +<% end %> \ No newline at end of file diff --git a/app/assets/javascripts/app/views/time_accounting/by_ticket.jst.eco b/app/assets/javascripts/app/views/time_accounting/by_ticket.jst.eco new file mode 100644 index 000000000..143de9e84 --- /dev/null +++ b/app/assets/javascripts/app/views/time_accounting/by_ticket.jst.eco @@ -0,0 +1,31 @@ +<% if !@rows.length: %> + +
<%- @T('No Entries') %> +
+<% else: %> + + + + + + <% for row in @rows: %> + + +
<%- @T('Ticket#') %> + <%- @T('Title') %> + <%- @T('Customer') %> + <%- @T('Organization') %> + <%- @T('Agent') %> + <%- @T('Time Units') %> + <%- @T('Time Units Total') %> +
<%= row.ticket.number %> + <%= row.ticket.title %> + <%= row.customer %> + <%= row.organization %> + <%= row.agent %> + <%= row.time_unit %> + <%= row.ticket.time_unit %> + <% end %> +
+ +<% end %> \ No newline at end of file diff --git a/app/assets/javascripts/app/views/time_accounting/index.jst.eco b/app/assets/javascripts/app/views/time_accounting/index.jst.eco new file mode 100644 index 000000000..fb25f4d8c --- /dev/null +++ b/app/assets/javascripts/app/views/time_accounting/index.jst.eco @@ -0,0 +1,46 @@ + +
+ +
+
+

<%- @T('Selector') %>

+
+

<%- @T('Enable time accounting for following matching tickets.') %>

+
+
+ +
+ +

<%- @T('Overviews') %>

+
+
+ <% for item in @timeRangeYear: %> +
<%= item.display %>
+ <% end %> +
+ +
+ <% for item in @timeRangeMonth: %> +
<%= item.display %>
+ <% end %> +
+
+

<%- @T('Ticket') %>

+
+
+

<%- @T('Customer') %>

+
+
+

<%- @T('Organization') %>

+
+
+ +
\ No newline at end of file diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9e553125c..f45bb507b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -398,6 +398,9 @@ class ApplicationController < ActionController::Base params[:sender_id] = Ticket::Article::Sender.lookup(name: sender).id end + # remember time accounting + time_unit = params[:time_unit] + clean_params = Ticket::Article.param_association_lookup(params) clean_params = Ticket::Article.param_cleanup(clean_params, true) @@ -447,6 +450,15 @@ class ApplicationController < ActionController::Base end article.save! + # account time + if time_unit.present? + Ticket::TimeAccounting.create!( + ticket_id: article.ticket_id, + ticket_article_id: article.id, + time_unit: time_unit + ) + end + # remove attachments from upload cache return article if !form_id diff --git a/app/controllers/time_accountings_controller.rb b/app/controllers/time_accountings_controller.rb new file mode 100644 index 000000000..58dc0bd36 --- /dev/null +++ b/app/controllers/time_accountings_controller.rb @@ -0,0 +1,152 @@ +# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ + +class TimeAccountingsController < ApplicationController + before_action { authentication_check(permission: 'admin.time_accounting') } + + def by_ticket + + year = params[:year] || Time.zone.now.year + month = params[:month] || Time.zone.now.month + + start_periode = Date.parse("#{year}-#{month}-01") + end_periode = start_periode.end_of_month + + time_unit = {} + Ticket::TimeAccounting.where('created_at >= ? AND created_at <= ?', start_periode, end_periode).pluck(:ticket_id, :time_unit, :created_by_id).each { |record| + if !time_unit[record[0]] + time_unit[record[0]] = { + time_unit: 0, + agent_id: record[2], + } + end + time_unit[record[0]][:time_unit] += record[1] + } + customers = {} + organizations = {} + agents = {} + results = [] + time_unit.each { |ticket_id, local_time_unit| + ticket = Ticket.lookup(id: ticket_id) + next if !ticket + if !customers[ticket.customer_id] + customers[ticket.customer_id] = '-' + if ticket.customer_id + customer_user = User.lookup(id: ticket.customer_id) + if customer_user + customers[ticket.customer_id] = customer_user.fullname + end + end + end + if !organizations[ticket.organization_id] + organizations[ticket.organization_id] = '-' + if ticket.organization_id + organization = Organization.lookup(id: ticket.organization_id) + if organization + organizations[ticket.organization_id] = organization.name + end + end + end + if !customers[local_time_unit[:agent_id]] + agent_user = User.lookup(id: local_time_unit[:agent_id]) + agent = '-' + if agent_user + agents[local_time_unit[:agent_id]] = agent_user.fullname + end + end + result = { + ticket: ticket.attributes, + time_unit: local_time_unit[:time_unit], + customer: customers[ticket.customer_id], + organization: organizations[ticket.organization_id], + agent: agents[local_time_unit[:agent_id]], + } + results.push result + } + render json: results + end + + def by_customer + + year = params[:year] || Time.zone.now.year + month = params[:month] || Time.zone.now.month + + start_periode = Date.parse("#{year}-#{month}-01") + end_periode = start_periode.end_of_month + + time_unit = {} + Ticket::TimeAccounting.where('created_at >= ? AND created_at <= ?', start_periode, end_periode).pluck(:ticket_id, :time_unit, :created_by_id).each { |record| + if !time_unit[record[0]] + time_unit[record[0]] = { + time_unit: 0, + agent_id: record[2], + } + end + time_unit[record[0]][:time_unit] += record[1] + } + + customers = {} + time_unit.each { |ticket_id, local_time_unit| + ticket = Ticket.lookup(id: ticket_id) + next if !ticket + if !customers[ticket.customer_id] + organization = nil + if ticket.organization_id + organization = Organization.lookup(id: ticket.organization_id).attributes + end + customers[ticket.customer_id] = { + customer: User.lookup(id: ticket.customer_id).attributes, + organization: organization, + time_unit: local_time_unit[:time_unit], + } + next + end + customers[ticket.customer_id][:time_unit] += local_time_unit[:time_unit] + } + results = [] + customers.each { |_customer_id, content| + results.push content + } + render json: results + end + + def by_organization + + year = params[:year] || Time.zone.now.year + month = params[:month] || Time.zone.now.month + + start_periode = Date.parse("#{year}-#{month}-01") + end_periode = start_periode.end_of_month + + time_unit = {} + Ticket::TimeAccounting.where('created_at >= ? AND created_at <= ?', start_periode, end_periode).pluck(:ticket_id, :time_unit, :created_by_id).each { |record| + if !time_unit[record[0]] + time_unit[record[0]] = { + time_unit: 0, + agent_id: record[2], + } + end + time_unit[record[0]][:time_unit] += record[1] + } + + organizations = {} + time_unit.each { |ticket_id, local_time_unit| + ticket = Ticket.lookup(id: ticket_id) + next if !ticket + next if !ticket.organization_id + if !organizations[ticket.organization_id] + organizations[ticket.organization_id] = { + organization: Organization.lookup(id: ticket.organization_id).attributes, + time_unit: local_time_unit[:time_unit], + } + next + end + organizations[ticket.organization_id][:time_unit] += local_time_unit[:time_unit] + } + results = [] + organizations.each { |_customer_id, content| + results.push content + } + render json: results + end + +end diff --git a/app/models/ticket/time_accounting.rb b/app/models/ticket/time_accounting.rb new file mode 100644 index 000000000..8a2f39cb4 --- /dev/null +++ b/app/models/ticket/time_accounting.rb @@ -0,0 +1,23 @@ +# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ +class Ticket::TimeAccounting < ApplicationModel + + after_create :ticket_time_unit_update + after_update :ticket_time_unit_update + + def ticket_time_unit_update + exists = false + time_units = 0 + Ticket::TimeAccounting.where(ticket_id: ticket_id).each { |record| + time_units += record.time_unit + exists = true + } + return false if exists == false + ticket = Ticket.lookup(id: ticket_id) + return false if !ticket + return false if ticket.time_unit == time_units + ticket.time_unit = time_units + ticket.save! + true + end + +end diff --git a/config/routes/time_accounting.rb b/config/routes/time_accounting.rb new file mode 100644 index 000000000..6e19b13f1 --- /dev/null +++ b/config/routes/time_accounting.rb @@ -0,0 +1,8 @@ +Zammad::Application.routes.draw do + api_path = Rails.configuration.api_path + + match api_path + '/time_accounting/log/by_ticket/:year/:month', to: 'time_accountings#by_ticket', via: :get + match api_path + '/time_accounting/log/by_customer/:year/:month', to: 'time_accountings#by_customer', via: :get + match api_path + '/time_accounting/log/by_organization/:year/:month', to: 'time_accountings#by_organization', via: :get + +end diff --git a/db/migrate/20120101000010_create_ticket.rb b/db/migrate/20120101000010_create_ticket.rb index ad4578604..df93272d2 100644 --- a/db/migrate/20120101000010_create_ticket.rb +++ b/db/migrate/20120101000010_create_ticket.rb @@ -31,6 +31,7 @@ class CreateTicket < ActiveRecord::Migration t.timestamps limit: 3, null: false end add_index :ticket_priorities, [:name], unique: true + create_table :tickets do |t| t.references :group, null: false t.references :priority, null: false @@ -61,6 +62,7 @@ class CreateTicket < ActiveRecord::Migration t.column :escalation_at, :timestamp, limit: 3, null: true t.column :pending_time, :timestamp, limit: 3, null: true t.column :type, :string, limit: 100, null: true + t.column :time_unit, :decimal, precision: 6, scale: 2, null: false t.column :preferences, :text, limit: 500.kilobytes + 1, null: true t.column :updated_by_id, :integer, null: false t.column :created_by_id, :integer, null: false @@ -93,6 +95,7 @@ class CreateTicket < ActiveRecord::Migration add_index :tickets, [:created_by_id] add_index :tickets, [:pending_time] add_index :tickets, [:type] + add_index :tickets, [:time_unit] create_table :ticket_flags do |t| t.references :tickets, null: false @@ -106,16 +109,17 @@ class CreateTicket < ActiveRecord::Migration add_index :ticket_flags, [:tickets_id] add_index :ticket_flags, [:created_by_id] - create_table :ticket_time_accounting do |t| - t.references :tickets, null: false - t.references :ticket_articles, null: true + create_table :ticket_time_accountings do |t| + t.references :ticket, null: false + t.references :ticket_article, null: true t.column :time_unit, :decimal, precision: 6, scale: 2, null: false t.column :created_by_id, :integer, null: false t.timestamps limit: 3, null: false end - add_index :ticket_time_accounting, [:tickets_id] - add_index :ticket_time_accounting, [:ticket_articles_id] - add_index :ticket_time_accounting, [:created_by_id] + add_index :ticket_time_accountings, [:ticket_id] + add_index :ticket_time_accountings, [:ticket_article_id] + add_index :ticket_time_accountings, [:created_by_id] + add_index :ticket_time_accountings, [:time_unit] create_table :ticket_article_types do |t| t.column :name, :string, limit: 250, null: false diff --git a/db/migrate/20170116000001_add_ticket_time_accounting_373.rb b/db/migrate/20170116000001_add_ticket_time_accounting_373.rb new file mode 100644 index 000000000..afbb15dcd --- /dev/null +++ b/db/migrate/20170116000001_add_ticket_time_accounting_373.rb @@ -0,0 +1,25 @@ +class AddTicketTimeAccounting373 < ActiveRecord::Migration + def up + + # return if it's a new setup + return if !Setting.find_by(name: 'system_init_done') + + drop_table :ticket_time_accountings + create_table :ticket_time_accountings do |t| + t.references :ticket, null: false + t.references :ticket_article, null: true + t.column :time_unit, :decimal, precision: 6, scale: 2, null: false + t.column :created_by_id, :integer, null: false + t.timestamps limit: 3, null: false + end + add_index :ticket_time_accountings, [:ticket_id] + add_index :ticket_time_accountings, [:ticket_article_id] + add_index :ticket_time_accountings, [:created_by_id] + add_index :ticket_time_accountings, [:time_unit] + + add_column :tickets, :time_unit, :decimal, precision: 6, scale: 2, null: true + add_index :tickets, [:time_unit] + + Cache.clear + end +end diff --git a/db/seeds.rb b/db/seeds.rb index 0e07d00b8..a8be32b18 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -2034,6 +2034,51 @@ Setting.create_if_not_exists( frontend: false ) +Setting.create_if_not_exists( + title: 'Time Accounting', + name: 'time_accounting', + area: 'Web::Base', + description: 'Enable time accounting.', + options: { + form: [ + { + display: '', + null: true, + name: 'time_accounting', + tag: 'boolean', + options: { + true => 'yes', + false => 'no', + }, + }, + ], + }, + preferences: { + authentication: true, + permission: ['admin.time_accounting'], + }, + state: false, + frontend: true +) + +Setting.create_if_not_exists( + title: 'Time Accounting Selector', + name: 'time_accounting_selector', + area: 'Web::Base', + description: 'Enable time accounting for this tickets.', + options: { + form: [ + {}, + ], + }, + preferences: { + authentication: true, + permission: ['admin.time_accounting'], + }, + state: {}, + frontend: true +) + Setting.create_if_not_exists( title: 'New Tags', name: 'tag_new',