Merge pull request #11854 from opf/implementation/45473-update-the-workpackagesapplyworkingdayschangejob-to-take-nonworkingdays-into-account
Implementation/45473 update the WorkpackagesApplyWorkingdaysChangeJob to take NonWorkingDays into accountpull/11980/head
commit
efe41a9139
@ -0,0 +1,192 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2022 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. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'rails_helper' |
||||||
|
|
||||||
|
RSpec.describe WorkPackages::Scopes::CoveringDatesAndDaysOfWeek do |
||||||
|
create_shared_association_defaults_for_work_package_factory |
||||||
|
|
||||||
|
shared_let(:next_monday) { Date.current.next_occurring(:monday) } |
||||||
|
|
||||||
|
shared_examples_for 'covering days' do |
||||||
|
# Construct the keyword arguments for the `#covering_dates_and_days_of_week` method. |
||||||
|
# It builds the expected day values based on the argument type provided (`:dates`, `:days_of_week`) |
||||||
|
# and based on the day values provided. |
||||||
|
# By providing the `expected_days`, the specific tetscase can decide which days are expected. |
||||||
|
let(:day_args) do |
||||||
|
->(*expected_days) do |
||||||
|
days.keys.reduce(Hash.new { |hsh, key| hsh[key] = [] }) do |day_args, dt| |
||||||
|
Array(expected_days).each do |day| |
||||||
|
day_args[dt] << days[dt][day] if days[dt][day] |
||||||
|
end |
||||||
|
day_args |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
it 'returns work packages having start date or due date being in the given days of week' do |
||||||
|
schedule = |
||||||
|
create_schedule(<<~CHART) |
||||||
|
days | MTWTFSS | |
||||||
|
covered1 | XX | |
||||||
|
covered2 | XX | |
||||||
|
covered3 | X | |
||||||
|
covered4 | [ | |
||||||
|
covered5 | ] | |
||||||
|
not_covered1 | X | |
||||||
|
not_covered2 | X | |
||||||
|
not_covered3 | XX | |
||||||
|
not_covered4 | | |
||||||
|
CHART |
||||||
|
|
||||||
|
expect(WorkPackage.covering_dates_and_days_of_week(**day_args[:tuesday])) |
||||||
|
.to contain_exactly( |
||||||
|
schedule.work_package("covered1"), |
||||||
|
schedule.work_package("covered2"), |
||||||
|
schedule.work_package("covered3"), |
||||||
|
schedule.work_package("covered4"), |
||||||
|
schedule.work_package("covered5") |
||||||
|
) |
||||||
|
end |
||||||
|
|
||||||
|
it 'returns work packages having days between start date and due date being in the given days of week' do |
||||||
|
schedule = |
||||||
|
create_schedule(<<~CHART) |
||||||
|
days | MTWTFSS | |
||||||
|
covered1 | XXXX | |
||||||
|
covered2 | XXX | |
||||||
|
not_covered1 | XX | |
||||||
|
not_covered2 | X | |
||||||
|
CHART |
||||||
|
|
||||||
|
expect(WorkPackage.covering_dates_and_days_of_week(**day_args[:tuesday, :wednesday])) |
||||||
|
.to contain_exactly( |
||||||
|
schedule.work_package("covered1"), |
||||||
|
schedule.work_package("covered2") |
||||||
|
) |
||||||
|
end |
||||||
|
|
||||||
|
context 'if work package ignores non working days' do |
||||||
|
it 'does not returns it' do |
||||||
|
create_schedule(<<~CHART) |
||||||
|
days | MTWTFSS | |
||||||
|
not_covered | XXXXXXX | working days include weekends |
||||||
|
CHART |
||||||
|
|
||||||
|
expect(WorkPackage.covering_dates_and_days_of_week(**day_args[:wednesday])) |
||||||
|
.to eq([]) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
it 'does not return work packages having follows relation covering the given days of week' do |
||||||
|
create_schedule(<<~CHART) |
||||||
|
days | MTWTFSS | |
||||||
|
not_covered1 | X | |
||||||
|
follower1 | X | follows not_covered1 |
||||||
|
not_covered2 | X | |
||||||
|
follower2 | X | follows not_covered2 |
||||||
|
CHART |
||||||
|
|
||||||
|
expect(WorkPackage.covering_dates_and_days_of_week(**day_args[:tuesday, :thursday])) |
||||||
|
.to eq([]) |
||||||
|
end |
||||||
|
|
||||||
|
it 'does not return work packages having follows relation with delay covering the given days of week' do |
||||||
|
create_schedule(<<~CHART) |
||||||
|
days | MTWTFSS | |
||||||
|
not_covered1 | X | |
||||||
|
follower1 | X | follows not_covered1 with delay 3 |
||||||
|
not_covered2 | X | |
||||||
|
follower2 | X | follows not_covered2 with delay 1 |
||||||
|
CHART |
||||||
|
|
||||||
|
expect(WorkPackage.covering_dates_and_days_of_week(**day_args[:tuesday, :thursday])) |
||||||
|
.to eq([]) |
||||||
|
end |
||||||
|
|
||||||
|
it 'accepts a single day of week or an array of days' do |
||||||
|
schedule = |
||||||
|
create_schedule(<<~CHART) |
||||||
|
days | MTWTFSS | |
||||||
|
covered | X | |
||||||
|
not_covered | X | |
||||||
|
CHART |
||||||
|
|
||||||
|
single_value = day_args[:tuesday].transform_values { |v| Array(v).first } |
||||||
|
|
||||||
|
expect(WorkPackage.covering_dates_and_days_of_week(**single_value)) |
||||||
|
.to eq([schedule.work_package("covered")]) |
||||||
|
expect(WorkPackage.covering_dates_and_days_of_week(**day_args[:tuesday])) |
||||||
|
.to eq([schedule.work_package("covered")]) |
||||||
|
expect(WorkPackage.covering_dates_and_days_of_week(**day_args[:tuesday, :wednesday])) |
||||||
|
.to eq([schedule.work_package("covered")]) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
context 'with the days of week' do |
||||||
|
let(:days) do |
||||||
|
{ |
||||||
|
days_of_week: { |
||||||
|
tuesday: 2, |
||||||
|
wednesday: 3, |
||||||
|
thursday: 4 |
||||||
|
} |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
it_behaves_like 'covering days' |
||||||
|
end |
||||||
|
|
||||||
|
context 'with specific dates' do |
||||||
|
let(:days) do |
||||||
|
{ |
||||||
|
dates: { |
||||||
|
tuesday: next_monday.next_occurring(:tuesday), |
||||||
|
wednesday: next_monday.next_occurring(:wednesday), |
||||||
|
thursday: next_monday.next_occurring(:thursday) |
||||||
|
} |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
it_behaves_like 'covering days' |
||||||
|
end |
||||||
|
|
||||||
|
context 'with days of week and specific dates mixed' do |
||||||
|
let(:days) do |
||||||
|
{ |
||||||
|
days_of_week: { wednesday: 3 }, |
||||||
|
dates: { |
||||||
|
tuesday: next_monday.next_occurring(:tuesday), |
||||||
|
thursday: next_monday.next_occurring(:thursday) |
||||||
|
} |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
it_behaves_like 'covering days' |
||||||
|
end |
||||||
|
end |
@ -1,129 +0,0 @@ |
|||||||
#-- copyright |
|
||||||
# OpenProject is an open source project management software. |
|
||||||
# Copyright (C) 2012-2023 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. |
|
||||||
#++ |
|
||||||
|
|
||||||
require 'rails_helper' |
|
||||||
|
|
||||||
RSpec.describe WorkPackages::Scopes::CoveringDaysOfWeek do |
|
||||||
create_shared_association_defaults_for_work_package_factory |
|
||||||
|
|
||||||
it 'returns work packages having start date or due date being in the given days of week' do |
|
||||||
schedule = |
|
||||||
create_schedule(<<~CHART) |
|
||||||
days | MTWTFSS | |
|
||||||
covered1 | XX | |
|
||||||
covered2 | XX | |
|
||||||
covered3 | X | |
|
||||||
covered4 | [ | |
|
||||||
covered5 | ] | |
|
||||||
not_covered1 | X | |
|
||||||
not_covered2 | X | |
|
||||||
not_covered3 | XX | |
|
||||||
not_covered4 | | |
|
||||||
CHART |
|
||||||
|
|
||||||
expect(WorkPackage.covering_days_of_week(2)) |
|
||||||
.to contain_exactly( |
|
||||||
schedule.work_package("covered1"), |
|
||||||
schedule.work_package("covered2"), |
|
||||||
schedule.work_package("covered3"), |
|
||||||
schedule.work_package("covered4"), |
|
||||||
schedule.work_package("covered5") |
|
||||||
) |
|
||||||
end |
|
||||||
|
|
||||||
it 'returns work packages having days between start date and due date being in the given days of week' do |
|
||||||
schedule = |
|
||||||
create_schedule(<<~CHART) |
|
||||||
days | MTWTFSS | |
|
||||||
covered1 | XXXX | |
|
||||||
covered2 | XXX | |
|
||||||
not_covered1 | XX | |
|
||||||
not_covered2 | X | |
|
||||||
CHART |
|
||||||
|
|
||||||
expect(WorkPackage.covering_days_of_week([2, 3])) |
|
||||||
.to contain_exactly( |
|
||||||
schedule.work_package("covered1"), |
|
||||||
schedule.work_package("covered2") |
|
||||||
) |
|
||||||
end |
|
||||||
|
|
||||||
context 'if work package ignores non working days' do |
|
||||||
it 'does not returns it' do |
|
||||||
create_schedule(<<~CHART) |
|
||||||
days | MTWTFSS | |
|
||||||
not_covered | XXXXXXX | working days include weekends |
|
||||||
CHART |
|
||||||
|
|
||||||
expect(WorkPackage.covering_days_of_week(3)) |
|
||||||
.to eq([]) |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
it 'does not return work packages having follows relation covering the given days of week' do |
|
||||||
create_schedule(<<~CHART) |
|
||||||
days | MTWTFSS | |
|
||||||
not_covered1 | X | |
|
||||||
follower1 | X | follows not_covered1 |
|
||||||
not_covered2 | X | |
|
||||||
follower2 | X | follows not_covered2 |
|
||||||
CHART |
|
||||||
|
|
||||||
expect(WorkPackage.covering_days_of_week([2, 4])) |
|
||||||
.to eq([]) |
|
||||||
end |
|
||||||
|
|
||||||
it 'does not return work packages having follows relation with delay covering the given days of week' do |
|
||||||
create_schedule(<<~CHART) |
|
||||||
days | MTWTFSS | |
|
||||||
not_covered1 | X | |
|
||||||
follower1 | X | follows not_covered1 with delay 3 |
|
||||||
not_covered2 | X | |
|
||||||
follower2 | X | follows not_covered2 with delay 1 |
|
||||||
CHART |
|
||||||
|
|
||||||
expect(WorkPackage.covering_days_of_week([2, 4])) |
|
||||||
.to eq([]) |
|
||||||
end |
|
||||||
|
|
||||||
it 'accepts a single day of week or an array of days' do |
|
||||||
schedule = |
|
||||||
create_schedule(<<~CHART) |
|
||||||
days | MTWTFSS | |
|
||||||
covered | X | |
|
||||||
not_covered | X | |
|
||||||
CHART |
|
||||||
|
|
||||||
expect(WorkPackage.covering_days_of_week(2)) |
|
||||||
.to eq([schedule.work_package("covered")]) |
|
||||||
expect(WorkPackage.covering_days_of_week([2])) |
|
||||||
.to eq([schedule.work_package("covered")]) |
|
||||||
expect(WorkPackage.covering_days_of_week([2, 3])) |
|
||||||
.to eq([schedule.work_package("covered")]) |
|
||||||
end |
|
||||||
end |
|
@ -0,0 +1,48 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2023 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. |
||||||
|
#++ |
||||||
|
|
||||||
|
def week_with_saturday_and_sunday_as_non_working_day(monday: Date.current.monday, weeks_size: 4) |
||||||
|
weeks_size.times.map do |week_count| |
||||||
|
[ |
||||||
|
create(:non_working_day, date: monday.next_occurring(:saturday) + week_count.weeks), |
||||||
|
create(:non_working_day, date: monday.next_occurring(:sunday) + week_count.weeks) |
||||||
|
] |
||||||
|
end.flatten.pluck(:date) |
||||||
|
end |
||||||
|
|
||||||
|
def week_without_non_working_days(monday: Date.current.monday, weeks_size: 4) |
||||||
|
NonWorkingDay.where(date: monday...monday + weeks_size.weeks).destroy_all |
||||||
|
end |
||||||
|
|
||||||
|
def set_non_working_days(*dates) |
||||||
|
dates.map { |date| create(:non_working_day, date:) } |
||||||
|
end |
||||||
|
|
||||||
|
def set_working_days(*dates) |
||||||
|
NonWorkingDay.where(date: dates).destroy_all |
||||||
|
end |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue