diff --git a/app/assets/javascripts/app/controllers/_ui_element/time_range.coffee b/app/assets/javascripts/app/controllers/_ui_element/time_range.coffee index 1f8e8dbeb..e831fab05 100644 --- a/app/assets/javascripts/app/controllers/_ui_element/time_range.coffee +++ b/app/assets/javascripts/app/controllers/_ui_element/time_range.coffee @@ -5,8 +5,10 @@ class App.UiElement.time_range minute: __('Minute(s)') hour: __('Hour(s)') day: __('Day(s)') + week: __('Week(s)'), month: __('Month(s)') year: __('Year(s)') + for key, value of ranges ranges[key] = App.i18n.translateInline(value) @@ -17,6 +19,7 @@ class App.UiElement.time_range minute: [1..120] hour: [1..48] day: [1..31] + week: [1..53] month: [1..12] year: [1..20] diff --git a/app/models/ticket.rb b/app/models/ticket.rb index f3acb412e..32546cb6c 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -846,113 +846,29 @@ condition example bind_params.push selector['value'] elsif selector['operator'] == 'within last (relative)' query += "#{attribute} BETWEEN ? AND ?" - time = nil - case selector['range'] - when 'minute' - time = selector['value'].to_i.minutes.ago - when 'hour' - time = selector['value'].to_i.hours.ago - when 'day' - time = selector['value'].to_i.days.ago - when 'month' - time = selector['value'].to_i.months.ago - when 'year' - time = selector['value'].to_i.years.ago - else - raise "Unknown selector attributes '#{selector.inspect}'" - end + time = range(selector).ago bind_params.push time bind_params.push Time.zone.now elsif selector['operator'] == 'within next (relative)' query += "#{attribute} BETWEEN ? AND ?" - time = nil - case selector['range'] - when 'minute' - time = selector['value'].to_i.minutes.from_now - when 'hour' - time = selector['value'].to_i.hours.from_now - when 'day' - time = selector['value'].to_i.days.from_now - when 'month' - time = selector['value'].to_i.months.from_now - when 'year' - time = selector['value'].to_i.years.from_now - else - raise "Unknown selector attributes '#{selector.inspect}'" - end + time = range(selector).from_now bind_params.push Time.zone.now bind_params.push time elsif selector['operator'] == 'before (relative)' query += "#{attribute} <= ?" - time = nil - case selector['range'] - when 'minute' - time = selector['value'].to_i.minutes.ago - when 'hour' - time = selector['value'].to_i.hours.ago - when 'day' - time = selector['value'].to_i.days.ago - when 'month' - time = selector['value'].to_i.months.ago - when 'year' - time = selector['value'].to_i.years.ago - else - raise "Unknown selector attributes '#{selector.inspect}'" - end + time = range(selector).ago bind_params.push time elsif selector['operator'] == 'after (relative)' query += "#{attribute} >= ?" - time = nil - case selector['range'] - when 'minute' - time = selector['value'].to_i.minutes.from_now - when 'hour' - time = selector['value'].to_i.hours.from_now - when 'day' - time = selector['value'].to_i.days.from_now - when 'month' - time = selector['value'].to_i.months.from_now - when 'year' - time = selector['value'].to_i.years.from_now - else - raise "Unknown selector attributes '#{selector.inspect}'" - end + time = range(selector).from_now bind_params.push time elsif selector['operator'] == 'till (relative)' query += "#{attribute} <= ?" - time = nil - case selector['range'] - when 'minute' - time = selector['value'].to_i.minutes.from_now - when 'hour' - time = selector['value'].to_i.hours.from_now - when 'day' - time = selector['value'].to_i.days.from_now - when 'month' - time = selector['value'].to_i.months.from_now - when 'year' - time = selector['value'].to_i.years.from_now - else - raise "Unknown selector attributes '#{selector.inspect}'" - end + time = range(selector).from_now bind_params.push time elsif selector['operator'] == 'from (relative)' query += "#{attribute} >= ?" - time = nil - case selector['range'] - when 'minute' - time = selector['value'].to_i.minutes.ago - when 'hour' - time = selector['value'].to_i.hours.ago - when 'day' - time = selector['value'].to_i.days.ago - when 'month' - time = selector['value'].to_i.months.ago - when 'year' - time = selector['value'].to_i.years.ago - else - raise "Unknown selector attributes '#{selector.inspect}'" - end + time = range(selector).ago bind_params.push time else raise "Invalid operator '#{selector['operator']}' for '#{selector['value'].inspect}'" @@ -1349,6 +1265,12 @@ perform active triggers on ticket [true, ticket, local_options] end + def self.range(selector) + selector['value'].to_i.send(selector['range'].pluralize) + rescue + raise 'unknown selector' + end + =begin get all email references headers of a ticket, to exclude some, parse it as array into method @@ -1883,4 +1805,5 @@ result # blocked for 60 full days (user.preferences[:mail_delivery_failed_data].to_date - Time.zone.now.to_date).to_i + 61 end + end diff --git a/i18n/zammad.pot b/i18n/zammad.pot index fd47d198e..f61078282 100644 --- a/i18n/zammad.pot +++ b/i18n/zammad.pot @@ -10318,6 +10318,10 @@ msgstr "" msgid "Week" msgstr "" +#: app/assets/javascripts/app/controllers/_ui_element/time_range.coffee +msgid "Week(s)" +msgstr "" + #: app/assets/javascripts/app/controllers/_profile/linked_accounts.coffee msgid "Weibo" msgstr "" diff --git a/spec/models/ticket/selector_2_sql_examples.rb b/spec/models/ticket/selector_2_sql_examples.rb new file mode 100644 index 000000000..d3995a47c --- /dev/null +++ b/spec/models/ticket/selector_2_sql_examples.rb @@ -0,0 +1,69 @@ +# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/ + +require 'rails_helper' + +RSpec.shared_examples 'TicketSelector2Sql' do + context 'when relative time range is selected in ticket selector' do + def get_condition(operator, range) + { + 'ticket.created_at' => { + operator: operator, + range: range, # minute|hour|day|month| + value: '10', + }, + } + end + + before do + freeze_time + end + + it 'calculates proper time interval, when operator is within last relative' do + condition = get_condition('within last (relative)', 'minute') + + _, bind_params = Ticket.selector2sql(condition) + + expect(bind_params).to eq([10.minutes.ago, Time.zone.now]) + end + + it 'calculates proper time interval, when operator is within next relative' do + condition = get_condition('within next (relative)', 'hour') + + _, bind_params = Ticket.selector2sql(condition) + + expect(bind_params).to eq([Time.zone.now, 10.hours.from_now]) + end + + it 'calculates proper time interval, when operator is before (relative)' do + condition = get_condition('before (relative)', 'day') + + _, bind_params = Ticket.selector2sql(condition) + + expect(bind_params).to eq([10.days.ago]) + end + + it 'calculates proper time interval, when operator is after (relative)' do + condition = get_condition('after (relative)', 'week') + + _, bind_params = Ticket.selector2sql(condition) + + expect(bind_params).to eq([10.weeks.from_now]) + end + + it 'calculates proper time interval, when operator is till (relative)' do + condition = get_condition('till (relative)', 'month') + + _, bind_params = Ticket.selector2sql(condition) + + expect(bind_params).to eq([10.months.from_now]) + end + + it 'calculates proper time interval, when operator is from (relative)' do + condition = get_condition('from (relative)', 'year') + + _, bind_params = Ticket.selector2sql(condition) + + expect(bind_params).to eq([10.years.ago]) + end + end +end diff --git a/spec/models/ticket_spec.rb b/spec/models/ticket_spec.rb index e98d52257..4a9b3c9d5 100644 --- a/spec/models/ticket_spec.rb +++ b/spec/models/ticket_spec.rb @@ -17,6 +17,7 @@ require 'models/ticket/escalation_examples' require 'models/ticket/resets_pending_time_seconds_examples' require 'models/ticket/sets_close_time_examples' require 'models/ticket/sets_last_owner_update_time_examples' +require 'models/ticket/selector_2_sql_examples' RSpec.describe Ticket, type: :model do subject(:ticket) { create(:ticket) } @@ -37,6 +38,7 @@ RSpec.describe Ticket, type: :model do it_behaves_like 'TicketResetsPendingTimeSeconds' it_behaves_like 'TicketSetsCloseTime' it_behaves_like 'TicketSetsLastOwnerUpdateTime' + it_behaves_like 'TicketSelector2Sql' describe 'Class methods:' do describe '.selectors' do