123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- require 'rails_helper'
- require 'lib/report_examples'
- RSpec.describe Report::TicketGenericTime, searchindex: true do
- include_examples 'with report examples'
- describe '.aggs' do
- it 'gets monthly aggregated results by created_at' do
- result = described_class.aggs(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- interval: 'month', # year, quarter, month, week, day, hour, minute, second
- selector: {}, # ticket selector to get only a collection of tickets
- params: { field: 'created_at' },
- )
- expect(result).to eq [0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0]
- end
- it 'gets monthly aggregated results by created_at not merged' do
- result = described_class.aggs(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- interval: 'month', # year, quarter, month, week, day, hour, minute, second
- selector: {
- 'state' => {
- 'operator' => 'is not',
- 'value' => 'merged'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to eq [0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0]
- end
- context 'when report profile has a ticket tag condition' do
- shared_examples 'getting the correct aggregated results' do
- it { expect(result).to eq expected_result }
- end
- # With tag1
- let(:ticket_1) do
- travel_to DateTime.new 2015, 1, 28, 9, 30
- ticket = create(:ticket,
- group: group_2,
- customer: customer)
- ticket.tag_add('tag1', 1)
- travel_back
- ticket
- end
- # With tag2
- let(:ticket_2) do
- travel_to DateTime.new 2015, 2, 28, 9, 30
- ticket = create(:ticket,
- group: group_1,
- customer: customer)
- ticket.tag_add('tag2', 1)
- travel_back
- ticket
- end
- # Without tag1 or tag2, but article with tag1
- let(:ticket_3) do
- travel_to DateTime.new 2015, 3, 28, 9, 30
- ticket = create(:ticket,
- group: group_1,
- customer: customer)
- create(:ticket_article, ticket: ticket, body: 'tag1')
- travel_back
- ticket
- end
- # Without tag1 or tag2, but article with tag2
- let(:ticket_4) do
- travel_to DateTime.new 2015, 4, 28, 9, 30
- ticket = create(:ticket,
- group: group_1,
- customer: customer)
- create(:ticket_article, ticket: ticket, body: 'tag2')
- travel_back
- ticket
- end
- # With tag1 and tag2
- let(:ticket_5) do
- travel_to DateTime.new 2015, 5, 28, 9, 30
- ticket = create(:ticket,
- group: group_1,
- customer: customer)
- create(:ticket_article, ticket: ticket)
- ticket.tag_add('tag1', 1)
- ticket.tag_add('tag2', 1)
- travel_back
- ticket
- end
- # With tag1 and tag2, with article body tag1
- let(:ticket_6) do
- travel_to DateTime.new 2015, 6, 28, 9, 30
- ticket = create(:ticket,
- group: group_1,
- customer: customer)
- create(:ticket_article, ticket: ticket, body: 'tag1')
- ticket.tag_add('tag1', 1)
- ticket.tag_add('tag2', 1)
- travel_back
- ticket
- end
- # With tag1 and tag2, with article body tag2
- let(:ticket_7) do
- travel_to DateTime.new 2015, 7, 28, 9, 30
- ticket = create(:ticket,
- group: group_1,
- customer: customer)
- create(:ticket_article, ticket: ticket, body: 'tag1')
- ticket.tag_add('tag1', 1)
- ticket.tag_add('tag2', 1)
- travel_back
- ticket
- end
- # With tag1 and tag2, with article body tag1 and tag2
- let(:ticket_8) do
- travel_to DateTime.new 2015, 8, 28, 9, 30
- ticket = create(:ticket,
- group: group_1,
- customer: customer)
- create(:ticket_article, ticket: ticket, body: 'tag1')
- create(:ticket_article, ticket: ticket, body: 'tag2')
- ticket.tag_add('tag1', 1)
- ticket.tag_add('tag2', 1)
- travel_back
- ticket
- end
- # Without tag1 or tag2, and without article with tag1 or tag2
- let(:ticket_9) do
- travel_to DateTime.new 2015, 4, 28, 9, 30
- ticket = create(:ticket,
- group: group_1,
- customer: customer)
- travel_back
- ticket
- end
- let(:result) do
- described_class.aggs(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- interval: 'month',
- selector: selector,
- params: { field: 'created_at' },
- )
- end
- context 'with contains all' do
- let(:selector) do
- {
- 'ticket.tags' => {
- 'operator' => 'contains all',
- 'value' => 'tag1, tag2'
- }
- }
- end
- let(:expected_result) { [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0] }
- it_behaves_like 'getting the correct aggregated results'
- end
- context 'with contains one not' do
- let(:selector) do
- {
- 'ticket.tags' => {
- 'operator' => 'contains one not',
- 'value' => 'tag1, tag2'
- }
- }
- end
- let(:expected_result) { [0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0] }
- it_behaves_like 'getting the correct aggregated results'
- end
- context 'with contains one' do
- let(:selector) do
- {
- 'ticket.tags' => {
- 'operator' => 'contains one',
- 'value' => 'tag1, tag2'
- }
- }
- end
- let(:expected_result) { [1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0] }
- it_behaves_like 'getting the correct aggregated results'
- end
- context 'with contains all not' do
- let(:selector) do
- {
- 'ticket.tags' => {
- 'operator' => 'contains all not',
- 'value' => 'tag1, tag2'
- }
- }
- end
- let(:expected_result) { [1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0] }
- it_behaves_like 'getting the correct aggregated results'
- end
- end
- end
- describe '.items' do
- it 'gets items in year range by created_at' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {}, # ticket selector to get only a collection of tickets
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3, ticket_2, ticket_1
- end
- it 'gets items in year range by created_at not merged' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'state' => {
- 'operator' => 'is not',
- 'value' => 'merged'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3, ticket_2, ticket_1
- end
- it 'gets items in year range by created_at before oct 31st' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'created_at' => {
- 'operator' => 'before (absolute)',
- 'value' => '2015-10-31T00:00:00Z'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_5, ticket_4, ticket_3, ticket_2, ticket_1
- end
- it 'gets items in year range by created_at after oct 31st' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'created_at' => {
- 'operator' => 'after (absolute)',
- 'value' => '2015-10-31T00:00:00Z'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_7, ticket_6
- end
- it 'gets items in 1 day from now' do
- result = described_class.items(
- range_start: 1.year.ago.beginning_of_year,
- range_end: 1.year.from_now.at_end_of_year,
- selector: {
- 'created_at' => {
- 'operator' => 'after (relative)',
- 'range' => 'day',
- 'value' => '1'
- }
- }, # ticket selector to get only a collection of tickets
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_after_72h
- end
- it 'gets items in 1 month from now' do
- result = described_class.items(
- range_start: 1.year.ago.beginning_of_year,
- range_end: 1.year.from_now.at_end_of_year,
- selector: {
- 'created_at' => {
- 'operator' => 'after (relative)',
- 'range' => 'month',
- 'value' => '1'
- }
- }, # ticket selector to get only a collection of tickets
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets []
- end
- it 'gets items in 1 month ago' do
- result = described_class.items(
- range_start: 1.year.ago.beginning_of_year,
- range_end: 1.year.from_now.at_end_of_year,
- selector: {
- 'created_at' => {
- 'operator' => 'before (relative)',
- 'range' => 'month',
- 'value' => '1'
- }
- }, # ticket selector to get only a collection of tickets
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_before_40d
- end
- it 'gets items in 5 months ago' do
- result = described_class.items(
- range_start: 1.year.ago.beginning_of_year,
- range_end: 1.year.from_now.at_end_of_year,
- selector: {
- 'created_at' => {
- 'operator' => 'before (relative)',
- 'range' => 'month',
- 'value' => '5'
- }
- }, # ticket selector to get only a collection of tickets
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets []
- end
- it 'gets items with aaa+bbb' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'tags' => {
- 'operator' => 'contains all',
- 'value' => 'aaa, bbb'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_1
- end
- it 'gets items with not aaa+bbb' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'tags' => {
- 'operator' => 'contains all not',
- 'value' => 'aaa, bbb'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3, ticket_2
- end
- it 'gets items with aaa' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'tags' => {
- 'operator' => 'contains all',
- 'value' => 'aaa'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_2, ticket_1
- end
- it 'gets items with not aaa' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'tags' => {
- 'operator' => 'contains all not',
- 'value' => 'aaa'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3
- end
- it 'gets items with one not aaa' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'tags' => {
- 'operator' => 'contains one not',
- 'value' => 'aaa'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3
- end
- it 'gets items with one not aaa+bbb' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'tags' => {
- 'operator' => 'contains one not',
- 'value' => 'aaa, bbb'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_7, ticket_6, ticket_4, ticket_3
- end
- it 'gets items with one aaa' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'tags' => {
- 'operator' => 'contains one',
- 'value' => 'aaa'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_2, ticket_1
- end
- it 'gets items with one aaa+bbb' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'tags' => {
- 'operator' => 'contains one',
- 'value' => 'aaa, bbb'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_5, ticket_2, ticket_1
- end
- it 'gets items with test' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'title' => {
- 'operator' => 'contains',
- 'value' => 'Test'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3, ticket_2, ticket_1
- end
- it 'gets items with not test' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'title' => {
- 'operator' => 'contains not',
- 'value' => 'Test'
- }
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets []
- end
- # Regression test for issue #2246 - Records in Reporting not updated when single ActiveRecord can not be found
- it 'correctly handles missing tickets', searchindex: false do
- class_double(SearchIndexBackend, selectors: { object_ids: [-1] }, drop_index: nil, drop_pipeline: nil).as_stubbed_const
- expect do
- described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {}, # ticket selector to get only a collection of tickets
- params: { field: 'created_at' },
- )
- end.not_to raise_error
- end
- end
- context 'when additional attribute exists', db_strategy: :reset do
- before do
- ObjectManager::Attribute.add(
- object: 'Ticket',
- name: 'test_category',
- display: 'Test 1',
- data_type: 'tree_select',
- data_option: {
- maxlength: 200,
- null: false,
- default: '',
- options: [
- { 'name' => 'aa', 'value' => 'aa', 'children' => [{ 'name' => 'aa', 'value' => 'aa::aa' }, { 'name' => 'bb', 'value' => 'aa::bb' }, { 'name' => 'cc', 'value' => 'aa::cc' }] },
- { 'name' => 'bb', 'value' => 'bb', 'children' => [{ 'name' => 'aa', 'value' => 'bb::aa' }, { 'name' => 'bb', 'value' => 'bb::bb' }, { 'name' => 'cc', 'value' => 'bb::cc' }] },
- { 'name' => 'cc', 'value' => 'cc', 'children' => [{ 'name' => 'aa', 'value' => 'cc::aa' }, { 'name' => 'bb', 'value' => 'cc::bb' }, { 'name' => 'cc', 'value' => 'cc::cc' }] },
- ]
- },
- active: true,
- screens: {},
- position: 20,
- created_by_id: 1,
- updated_by_id: 1,
- editable: false,
- to_migrate: false,
- )
- ObjectManager::Attribute.migration_execute
- ticket_with_category
- searchindex_model_reload([Ticket])
- end
- let(:ticket_with_category) do
- travel_to DateTime.new 2015, 10, 28, 9, 30
- ticket = create(:ticket,
- group: group_2,
- customer: customer,
- test_category: 'cc::bb',
- state_name: 'new',
- priority_name: '2 normal')
- ticket.tag_add('aaa', 1)
- ticket.tag_add('bbb', 1)
- create(:ticket_article,
- :inbound_email,
- ticket: ticket)
- travel 5.hours
- ticket.update! group: group_1
- travel_back
- ticket
- end
- describe '.items' do
- it 'gets items with test_category cc:bb' do
- result = described_class.items(
- range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
- range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
- selector: {
- 'test_category' => {
- 'operator' => 'is',
- 'value' => 'cc::bb'
- },
- },
- params: { field: 'created_at' },
- )
- expect(result).to match_tickets ticket_with_category
- end
- end
- end
- end
|