From e3368b79edece458c78471045f3ceb6cde54b9ed Mon Sep 17 00:00:00 2001 From: Martin Artnik Date: Thu, 30 Jan 2025 15:31:05 +0100 Subject: [PATCH] Fix RepositoryItemReminderJob to properly take into account the buffer [SCI-11520] --- app/jobs/repository_item_date_reminder_job.rb | 46 +++++----- .../repository_item_date_reminder_job_spec.rb | 87 +++++++++++++++++++ 2 files changed, 113 insertions(+), 20 deletions(-) create mode 100644 spec/jobs/repository_item_date_reminder_job_spec.rb diff --git a/app/jobs/repository_item_date_reminder_job.rb b/app/jobs/repository_item_date_reminder_job.rb index 555ca1e74..19b5fbc0e 100644 --- a/app/jobs/repository_item_date_reminder_job.rb +++ b/app/jobs/repository_item_date_reminder_job.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class RepositoryItemDateReminderJob < ApplicationJob + BUFFER_DAYS = 2 + queue_as :default def perform @@ -11,33 +13,37 @@ class RepositoryItemDateReminderJob < ApplicationJob private - def process_repository_values(model, comparison_value) + def repository_values_due(model, comparison_value) model .joins(repository_cell: [:repository_row, { repository_column: :repository }]) .where( notification_sent: false, repositories: { type: 'Repository', archived: false }, repository_rows: { archived: false } - ).where('repository_date_time_values.updated_at >= ?', 2.days.ago) - .where( # date(time) values that are within the reminder range - "data <= " \ - "(?::timestamp + CAST(((repository_columns.metadata->>'reminder_unit')::int * " \ + ).where( # date(time) values that are within the reminder range including buffer + "(data > (:comparison_value::timestamp - (INTERVAL ':buffer_days DAY'))) AND data <= " \ + "(:comparison_value::timestamp + CAST(((repository_columns.metadata->>'reminder_unit')::int * " \ "(repository_columns.metadata->>'reminder_value')::int) || ' seconds' AS Interval))", - comparison_value - ).find_each do |value| - repository_row = RepositoryRow.find(value.repository_cell.repository_row_id) - repository_column = RepositoryColumn.find(value.repository_cell.repository_column_id) + buffer_days: BUFFER_DAYS, + comparison_value: comparison_value + ) + end - RepositoryItemDateNotification - .send_notifications({ - "#{value.class.name.underscore}_id": value.id, - repository_row_id: repository_row.id, - repository_row_name: repository_row.name, - repository_column_id: repository_column.id, - repository_column_name: repository_column.name, - reminder_unit: repository_column.metadata['reminder_unit'], - reminder_value: repository_column.metadata['reminder_value'] - }) - end + def process_repository_values(model, comparison_value) + repository_values_due(model, comparison_value).find_each do |value| + repository_row = RepositoryRow.find(value.repository_cell.repository_row_id) + repository_column = RepositoryColumn.find(value.repository_cell.repository_column_id) + + RepositoryItemDateNotification + .send_notifications({ + "#{value.class.name.underscore}_id": value.id, + repository_row_id: repository_row.id, + repository_row_name: repository_row.name, + repository_column_id: repository_column.id, + repository_column_name: repository_column.name, + reminder_unit: repository_column.metadata['reminder_unit'], + reminder_value: repository_column.metadata['reminder_value'] + }) + end end end diff --git a/spec/jobs/repository_item_date_reminder_job_spec.rb b/spec/jobs/repository_item_date_reminder_job_spec.rb new file mode 100644 index 000000000..3a66d6587 --- /dev/null +++ b/spec/jobs/repository_item_date_reminder_job_spec.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe RepositoryItemDateReminderJob, type: :job do + around do |example| + Timecop.freeze(Time.utc(2025, 1, 15, 0, 0, 0)) do + example.run + end + end + + let(:user) { create :user } + let(:team) { create :team, created_by: user } + let!(:owner_role) { UserRole.find_by(name: I18n.t('user_roles.predefined.owner')) } + let!(:team_assignment) { create_user_assignment(team, owner_role, user) } + let(:repository) { create :repository, team: team, created_by: user } + + let!(:date_column_with_reminder) do + create :repository_column, repository: repository, + created_by: user, + name: 'Custom items', + data_type: 'RepositoryDateValue', + metadata: {"reminder_unit"=>"86400", "reminder_value"=>"5", "reminder_message"=>""} + end + + let!(:repository_date_value_due) do + row = create :repository_row, name: "row 1", + repository: repository, + created_by: user, + last_modified_by: user + + create( + :repository_date_value, + data: Date.parse('20-1-2025'), + repository_cell_attributes: { repository_row: row, repository_column: date_column_with_reminder } + ) + end + + let!(:repository_date_value_due_outside_buffer) do + row = create :repository_row, name: "row 1", + repository: repository, + created_by: user, + last_modified_by: user + + create( + :repository_date_value, + data: Date.parse('15-1-2025') - (RepositoryItemDateReminderJob::BUFFER_DAYS + 1).days, + repository_cell_attributes: { repository_row: row, repository_column: date_column_with_reminder } + ) + end + + let!(:repository_date_value_due_inside_buffer) do + row = create :repository_row, name: "row 1", + repository: repository, + created_by: user, + last_modified_by: user + + create( + :repository_date_value, + data: Date.parse('15-1-2025') - (RepositoryItemDateReminderJob::BUFFER_DAYS - 1).days, + repository_cell_attributes: { repository_row: row, repository_column: date_column_with_reminder } + ) + end + + let!(:repository_date_value_not_due) do + row = create :repository_row, name: "row 1", + repository: repository, + created_by: user, + last_modified_by: user + + create( + :repository_date_value, + data: Date.parse('10-10-2025'), + repository_cell_attributes: { repository_row: row, repository_column: date_column_with_reminder } + ) + end + + describe '#repository_values_due' do + it "returns repository values that are due with a #{RepositoryItemDateReminderJob::BUFFER_DAYS} day buffer" do + values = described_class.new.send(:repository_values_due, RepositoryDateValue, Date.current) + expect(values).to include(repository_date_value_due) + expect(values).to_not include(repository_date_value_not_due) + expect(values).to include(repository_date_value_due_inside_buffer) + expect(values).to_not include(repository_date_value_due_outside_buffer) + end + end +end