From cde4bba693c519ffd72d1497bb4f9fc60e72ab5d Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Mon, 12 May 2025 18:38:21 +0200 Subject: [PATCH] extract common parts of ApplyWorkingDaysChangeJobs --- .../apply_working_days_change_job_base.rb | 82 +++++++++++++++++++ .../phases/apply_working_days_change_job.rb | 26 ++---- .../apply_working_days_change_job.rb | 58 ++----------- 3 files changed, 97 insertions(+), 69 deletions(-) create mode 100644 app/workers/apply_working_days_change_job_base.rb diff --git a/app/workers/apply_working_days_change_job_base.rb b/app/workers/apply_working_days_change_job_base.rb new file mode 100644 index 00000000000..5783235cf67 --- /dev/null +++ b/app/workers/apply_working_days_change_job_base.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +# Common methods for ApplyWorkingDaysChangeJobs +class ApplyWorkingDaysChangeJobBase < ApplicationJob + include JobConcurrency + queue_with_priority :above_normal + + good_job_control_concurrency_with( + total_limit: 1 + ) + + attr_reader :previous_working_days, :previous_non_working_days + + def perform(user_id:, previous_working_days:, previous_non_working_days:) + @previous_working_days = previous_working_days + @previous_non_working_days = previous_non_working_days + + user = User.find(user_id) + + User.execute_as user do + apply_working_days_change + end + end + + private + + def apply_working_days_change + fail NoMethodError, "Must be overridden in subclass" + end + + def journal_cause + @journal_cause ||= Journal::CausedByWorkingDayChanges.new( + working_days: changed_days, + non_working_days: changed_non_working_dates + ) + end + + def changed_days + # reverse order, so new working days map to true + @changed_days ||= changes_between(previous_working_days, Setting.working_days) + end + + def changed_non_working_dates + # reverse order, as new non working dates map to false + @changed_non_working_dates ||= changes_between(NonWorkingDay.pluck(:date), previous_non_working_days) + end + + def changes_between(list_a, list_b) + deleted = (list_a - list_b).index_with(false) + added = (list_b - list_a).index_with(true) + + deleted.merge(added) + end +end diff --git a/app/workers/projects/phases/apply_working_days_change_job.rb b/app/workers/projects/phases/apply_working_days_change_job.rb index a1378033e83..d6fa90ae4bc 100644 --- a/app/workers/projects/phases/apply_working_days_change_job.rb +++ b/app/workers/projects/phases/apply_working_days_change_job.rb @@ -28,26 +28,12 @@ # See COPYRIGHT and LICENSE files for more details. #++ -class Projects::Phases::ApplyWorkingDaysChangeJob < ApplicationJob - include JobConcurrency - queue_with_priority :above_normal +class Projects::Phases::ApplyWorkingDaysChangeJob < ApplyWorkingDaysChangeJobBase + private - good_job_control_concurrency_with( - total_limit: 1 - ) - - attr_reader :previous_working_days, :previous_non_working_days - - def perform(user_id:, previous_working_days:, previous_non_working_days:) - @previous_working_days = previous_working_days - @previous_non_working_days = previous_non_working_days - - user = User.find(user_id) - - User.execute_as user do - # TODO: find all active phases with date range affected by changes - # TODO: group by project - # TODO: call RescheduleService on phases of that project starting with the one with smallest definition position - end + def apply_working_days_change + # TODO: find all active phases with date range affected by changes + # TODO: group by project + # TODO: call RescheduleService on phases of that project starting with the one with smallest definition position end end diff --git a/app/workers/work_packages/apply_working_days_change_job.rb b/app/workers/work_packages/apply_working_days_change_job.rb index d74265faacc..eada444dc68 100644 --- a/app/workers/work_packages/apply_working_days_change_job.rb +++ b/app/workers/work_packages/apply_working_days_change_job.rb @@ -26,40 +26,17 @@ # See COPYRIGHT and LICENSE files for more details. #++ -class WorkPackages::ApplyWorkingDaysChangeJob < ApplicationJob - include JobConcurrency - queue_with_priority :above_normal - - good_job_control_concurrency_with( - total_limit: 1 - ) - - attr_reader :previous_working_days, :previous_non_working_days - - def perform(user_id:, previous_working_days:, previous_non_working_days:) - @previous_working_days = previous_working_days - @previous_non_working_days = previous_non_working_days - - user = User.find(user_id) - - User.execute_as user do - for_each_work_package(applicable_work_packages) do |work_package| - apply_change_to_work_package(work_package) - end - - applicable_predecessors.find_each do |predecessor| - apply_change_to_predecessor(predecessor) - end - end - end - +class WorkPackages::ApplyWorkingDaysChangeJob < ApplyWorkingDaysChangeJobBase private - def journal_cause - @journal_cause ||= Journal::CausedByWorkingDayChanges.new( - working_days: changed_days, - non_working_days: changed_non_working_dates - ) + def apply_working_days_change + for_each_work_package(applicable_work_packages) do |work_package| + apply_change_to_work_package(work_package) + end + + applicable_predecessors.find_each do |predecessor| + apply_change_to_predecessor(predecessor) + end end def apply_change_to_work_package(work_package) @@ -87,23 +64,6 @@ class WorkPackages::ApplyWorkingDaysChangeJob < ApplicationJob WorkPackage.arel_table[:due_date].asc) end - def changed_days - # reverse order, so new working days map to true - @changed_days ||= change_between(previous_working_days, Setting.working_days) - end - - def changed_non_working_dates - # reverse order, as new non working dates map to false - @changed_non_working_dates ||= change_between(NonWorkingDay.pluck(:date), previous_non_working_days) - end - - def change_between(list_a, list_b) - deleted = (list_a - list_b).index_with(false) - added = (list_b - list_a).index_with(true) - - deleted.merge(added) - end - def applicable_predecessors days_of_week = changed_days.keys dates = changed_non_working_dates.keys