Cleanup code for duration / non working days (#11222)

* Remove work_packages_duration_field_active feature flag

  Duration is now globally active for 12.3.0.

* Remove `ignore_non_working_days: false` in tests

  Not needed anymore as it is now the default value. Keep it where the test explicitly refers to it, for clarity.

Co-authored-by: Christophe Bliard <c.bliard@openproject.com>
pull/11223/head
Oliver Günther 2 years ago committed by GitHub
parent e31fa64855
commit a6b7bee822
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      app/contracts/work_packages/base_contract.rb
  2. 3
      app/models/queries/work_packages/columns/property_column.rb
  3. 8
      app/services/work_packages/shared/all_days.rb
  4. 2
      app/services/work_packages/shared/days.rb
  5. 6
      app/services/work_packages/shared/working_days.rb
  6. 5
      lib/api/v3/work_packages/schema/work_package_schema_representer.rb
  7. 9
      lib/api/v3/work_packages/work_package_representer.rb
  8. 5
      lib/open_project/feature_decisions.rb
  9. 2
      lib_static/plugins/acts_as_journalized/lib/journal_changes.rb
  10. 3
      modules/bim/spec/seeders/demo_data_seeder_spec.rb
  11. 3
      modules/storages/spec/seeders/seeder_spec.rb
  12. 29
      spec/contracts/work_packages/base_contract_spec.rb
  13. 3
      spec/features/projects/template_spec.rb
  14. 5
      spec/features/work_packages/datepicker/datepicker_logic_spec.rb
  15. 1
      spec/features/work_packages/details/date_editor_spec.rb
  16. 1
      spec/features/work_packages/edit_work_package_spec.rb
  17. 1
      spec/features/work_packages/new/new_work_package_datepicker_spec.rb
  18. 1
      spec/features/work_packages/scheduling/scheduling_mode_spec.rb
  19. 1
      spec/features/work_packages/table/duration_field_spec.rb
  20. 16
      spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb
  21. 18
      spec/lib/api/v3/work_packages/work_package_representer_spec.rb
  22. 2
      spec/models/mail_handler_spec.rb
  23. 8
      spec/models/queries/work_packages/columns/property_column_spec.rb
  24. 20
      spec/models/type_spec.rb
  25. 30
      spec/models/work_package/work_package_acts_as_journalized_spec.rb
  26. 3
      spec/seeders/demo_data_seeder_spec.rb
  27. 4
      spec/services/work_packages/schedule_dependency/dependency_spec.rb
  28. 11
      spec/services/work_packages/set_attributes_service_spec.rb
  29. 100
      spec/services/work_packages/set_schedule_service_working_days_spec.rb
  30. 16
      spec/services/work_packages/shared/all_days_spec.rb
  31. 17
      spec/services/work_packages/shared/days_spec.rb
  32. 16
      spec/services/work_packages/shared/working_days_spec.rb
  33. 3
      spec/services/work_packages/update_service_integration_spec.rb
  34. 2
      spec/support_spec/schedule_helpers/chart_spec.rb

@ -80,10 +80,7 @@ module WorkPackages
end
attribute :schedule_manually
attribute :ignore_non_working_days,
writable: ->(*) {
OpenProject::FeatureDecisions.work_packages_duration_field_active?
}
attribute :ignore_non_working_days
attribute :start_date,
writable: ->(*) {
@ -99,10 +96,7 @@ module WorkPackages
validate_after_soonest_start(:due_date)
end
attribute :duration,
writable: ->(*) {
OpenProject::FeatureDecisions.work_packages_duration_field_active?
}
attribute :duration
attribute :budget
@ -337,7 +331,7 @@ module WorkPackages
end
def validate_duration_matches_dates
return unless calculated_duration && model.duration && OpenProject::FeatureDecisions.work_packages_duration_field_active?
return unless calculated_duration && model.duration
if calculated_duration > model.duration
errors.add :duration, :smaller_than_dates
@ -353,8 +347,6 @@ module WorkPackages
end
def validate_duration_and_dates_are_not_derivable
return unless OpenProject::FeatureDecisions.work_packages_duration_field_active?
%i[start_date due_date duration].each do |field|
if not_set_but_others_are_present?(field)
errors.add field, :cannot_be_null

@ -127,8 +127,7 @@ class Queries::WorkPackages::Columns::PropertyColumn < Queries::WorkPackages::Co
default_order: 'desc'
},
duration: {
sortable: "#{WorkPackage.table_name}.duration",
if: ->(*) { OpenProject::FeatureDecisions.work_packages_duration_field_active? }
sortable: "#{WorkPackage.table_name}.duration"
}
}

@ -31,7 +31,7 @@ module WorkPackages
class AllDays
# Returns number of days between two dates, inclusive.
def duration(start_date, due_date)
return no_duration if start_date.nil? || due_date.nil?
return nil unless start_date && due_date
(start_date..due_date).count
end
@ -65,12 +65,6 @@ module WorkPackages
def working?(_date)
true
end
private
def no_duration
OpenProject::FeatureDecisions.work_packages_duration_field_active? ? nil : 1
end
end
end
end

@ -31,8 +31,6 @@ module WorkPackages
class Days
# Returns the right day computation instance for the given instance.
def self.for(work_package)
return AllDays.new unless OpenProject::FeatureDecisions.work_packages_duration_field_active?
work_package.ignore_non_working_days ? AllDays.new : WorkingDays.new
end
end

@ -32,7 +32,7 @@ module WorkPackages
# Returns number of working days between two dates, excluding weekend days
# and non working days.
def duration(start_date, due_date)
return no_duration unless start_date && due_date
return nil unless start_date && due_date
(start_date..due_date).count { working?(_1) }
end
@ -106,10 +106,6 @@ module WorkPackages
private
def no_duration
OpenProject::FeatureDecisions.work_packages_duration_field_active? ? nil : 1
end
def assert_strictly_positive_duration(duration)
raise ArgumentError, 'duration must be strictly positive' if duration.is_a?(Integer) && duration <= 0
end

@ -120,7 +120,7 @@ module API
schema :duration,
type: 'Duration',
required: false,
show_if: ->(*) { !represented.milestone? && OpenProject::FeatureDecisions.work_packages_duration_field_active? }
show_if: ->(*) { !represented.milestone? }
schema :schedule_manually,
type: 'Boolean',
@ -129,8 +129,7 @@ module API
schema :ignore_non_working_days,
type: 'Boolean',
required: false,
show_if: ->(*) { OpenProject::FeatureDecisions.work_packages_duration_field_active? }
required: false
schema :start_date,
type: 'Date',

@ -396,19 +396,14 @@ module API
property :duration,
exec_context: :decorator,
if: ->(represented:, **) {
!represented.milestone? && OpenProject::FeatureDecisions.work_packages_duration_field_active?
},
if: ->(represented:, **) { !represented.milestone? },
getter: ->(*) do
datetime_formatter.format_duration_from_hours(represented.duration_in_hours,
allow_nil: true)
end,
render_nil: true
property :ignore_non_working_days,
if: ->(*) {
OpenProject::FeatureDecisions.work_packages_duration_field_active?
}
property :ignore_non_working_days
property :spent_time,
exec_context: :decorator,

@ -39,10 +39,5 @@ module OpenProject
# release_date = Date.new(2022,01,01)
# Setting.feature_your_module_active || Date.today > release_date
# end
# TODO: remove this feature flag
def self.work_packages_duration_field_active?
true
end
end
end

@ -37,8 +37,6 @@ module JournalChanges
subsequent_journal_data_changes
end
@changes.delete(:duration) unless OpenProject::FeatureDecisions.work_packages_duration_field_active?
@changes.merge!(get_association_changes(predecessor, 'attachable', 'attachments', :attachment_id, :filename))
@changes.merge!(get_association_changes(predecessor, 'customizable', 'custom_fields', :custom_field_id, :value))
end

@ -31,8 +31,7 @@ require 'spec_helper'
describe RootSeeder,
'BIM edition',
with_config: { edition: 'bim' },
with_settings: { journal_aggregation_time_minutes: 0 },
with_flag: { work_packages_duration_field_active: true } do
with_settings: { journal_aggregation_time_minutes: 0 } do
it 'create the demo data' do
expect { described_class.new.do_seed! }.not_to raise_error

@ -28,8 +28,7 @@
require 'spec_helper'
describe RootSeeder, 'Storage module',
with_flag: { work_packages_duration_field_active: true } do
describe RootSeeder, 'Storage module' do
it 'seeds role permissions for Storages' do
expect { described_class.new.do_seed! }.not_to raise_error

@ -451,8 +451,7 @@ describe WorkPackages::BaseContract do
end
end
context 'when setting due date and duration without start date',
with_flag: { work_packages_duration_field_active: true } do
context 'when setting due date and duration without start date' do
before do
work_package.duration = 1
work_package.start_date = nil
@ -514,8 +513,7 @@ describe WorkPackages::BaseContract do
end
end
context 'when setting start date and duration without due date',
with_flag: { work_packages_duration_field_active: true } do
context 'when setting start date and duration without due date' do
before do
work_package.duration = 1
work_package.start_date = Time.zone.today
@ -526,7 +524,7 @@ describe WorkPackages::BaseContract do
end
end
describe 'duration', with_flag: { work_packages_duration_field_active: true } do
describe 'duration' do
context 'when setting duration' do
before do
work_package.duration = 5
@ -565,14 +563,6 @@ describe WorkPackages::BaseContract do
it_behaves_like 'contract is valid'
end
context 'when setting duration with the feature disabled', with_flag: { work_packages_duration_field_active: false } do
before do
work_package.duration = 5
end
it_behaves_like 'contract is invalid', duration: :error_readonly
end
context 'when setting duration to 0' do
before do
work_package.duration = 0
@ -678,7 +668,7 @@ describe WorkPackages::BaseContract do
end
describe 'ignore_non_working_days' do
context 'when setting the value to true', with_flag: { work_packages_duration_field_active: true } do
context 'when setting the value to true' do
before do
work_package.ignore_non_working_days = true
end
@ -686,22 +676,13 @@ describe WorkPackages::BaseContract do
it_behaves_like 'contract is valid'
end
context 'when setting the value to false', with_flag: { work_packages_duration_field_active: true } do
context 'when setting the value to false' do
before do
work_package.ignore_non_working_days = false
end
it_behaves_like 'contract is valid'
end
context 'when setting the value to true and with the feature disabled',
with_flag: { work_packages_duration_field_active: false } do
before do
work_package.ignore_non_working_days = true
end
it_behaves_like 'contract is invalid', ignore_non_working_days: :error_readonly
end
end
describe 'percentage done' do

@ -86,8 +86,7 @@ describe 'Project templates', type: :feature, js: true do
login_as current_user
end
it 'can instantiate the project with the copy permission',
with_flag: { work_packages_duration_field_active: true } do
it 'can instantiate the project with the copy permission' do
visit new_project_path
name_field.set_value 'Foo bar'

@ -31,7 +31,6 @@ require 'support/edit_fields/edit_field'
describe 'Datepicker modal logic test cases (WP #43539)',
with_settings: { date_format: '%Y-%m-%d' },
with_flag: { work_packages_duration_field_active: true },
js: true do
shared_let(:user) { create :admin }
@ -39,8 +38,8 @@ describe 'Datepicker modal logic test cases (WP #43539)',
shared_let(:type_milestone) { create(:type_milestone) }
shared_let(:project) { create(:project, types: [type_bug, type_milestone]) }
shared_let(:bug_wp) { create :work_package, project:, type: type_bug, ignore_non_working_days: false }
shared_let(:milestone_wp) { create :work_package, project:, type: type_milestone, ignore_non_working_days: false }
shared_let(:bug_wp) { create :work_package, project:, type: type_bug }
shared_let(:milestone_wp) { create :work_package, project:, type: type_milestone }
# assume sat+sun are non working days
shared_let(:weekdays) { create :week_days }

@ -35,7 +35,6 @@ require 'features/work_packages/work_packages_page'
describe 'date inplace editor',
with_settings: { date_format: '%Y-%m-%d' },
with_flag: { work_packages_duration_field_active: true },
js: true, selenium: true do
let(:project) { create :project_with_types, public: true }
let(:work_package) { create :work_package, project:, start_date: Date.parse('2016-01-02'), duration: nil }

@ -2,7 +2,6 @@ require 'spec_helper'
require 'features/page_objects/notification'
describe 'edit work package',
with_flag: { work_packages_duration_field_active: true },
js: true do
let(:dev_role) do
create :role,

@ -35,7 +35,6 @@ require 'features/work_packages/work_packages_page'
describe 'New work package datepicker',
with_settings: { date_format: '%Y-%m-%d' },
with_flag: { work_packages_duration_field_active: true },
js: true, selenium: true do
let(:project) { create :project_with_types, public: true }
let(:user) { create :admin }

@ -34,7 +34,6 @@ require 'support/edit_fields/edit_field'
require 'features/work_packages/work_packages_page'
describe 'scheduling mode',
with_flag: { work_packages_duration_field_active: true },
js: true do
let(:project) { create :project_with_types, public: true }
# Constructing a work package graph that looks like this:

@ -1,7 +1,6 @@
require 'spec_helper'
describe 'Duration field in the work package table',
with_flag: { work_packages_duration_field_active: true },
js: true do
shared_let(:current_user) { create :admin }
shared_let(:work_package) do

@ -293,7 +293,7 @@ describe ::API::V3::WorkPackages::Schema::WorkPackageSchemaRepresenter do
end
end
describe 'duration', with_flag: { work_packages_duration_field_active: true } do
describe 'duration' do
let(:milestone?) { false }
before do
@ -317,12 +317,6 @@ describe ::API::V3::WorkPackages::Schema::WorkPackageSchemaRepresenter do
expect(subject).not_to have_json_path('duration')
end
end
context 'when the feature flag is off', with_flag: { work_packages_duration_field_active: false } do
it 'has no duration attribute' do
expect(subject).not_to have_json_path('duration')
end
end
end
describe 'scheduleManually' do
@ -336,7 +330,7 @@ describe ::API::V3::WorkPackages::Schema::WorkPackageSchemaRepresenter do
end
end
describe 'ignoreNonWorkingDays', with_flag: { work_packages_duration_field_active: true } do
describe 'ignoreNonWorkingDays' do
it_behaves_like 'has basic schema properties' do
let(:path) { 'ignoreNonWorkingDays' }
let(:type) { 'Boolean' }
@ -344,12 +338,6 @@ describe ::API::V3::WorkPackages::Schema::WorkPackageSchemaRepresenter do
let(:required) { false }
let(:writable) { true }
end
context 'when the feature flag is off', with_flag: { work_packages_duration_field_active: false } do
it 'has no ignoreNonWorkingDays attribute' do
expect(subject).not_to have_json_path('ignoreNonWorkingDays')
end
end
end
describe 'date' do

@ -298,7 +298,7 @@ describe ::API::V3::WorkPackages::WorkPackageRepresenter do
end
end
describe 'duration', with_flag: { work_packages_duration_field_active: true } do
describe 'duration' do
let(:duration) { 6 }
it { is_expected.to be_json_eql('P6D'.to_json).at_path('duration') }
@ -318,15 +318,9 @@ describe ::API::V3::WorkPackages::WorkPackageRepresenter do
expect(subject).not_to have_json_path('duration')
end
end
context 'when the feature flag is off', with_flag: { work_packages_duration_field_active: false } do
it 'with no duration' do
expect(subject).not_to have_json_path('duration')
end
end
end
describe 'ignoreNonWorkingDays', with_flag: { work_packages_duration_field_active: true } do
describe 'ignoreNonWorkingDays' do
let(:ignore_non_working_days) { true }
context 'with the value being `true`' do
@ -338,12 +332,6 @@ describe ::API::V3::WorkPackages::WorkPackageRepresenter do
it { is_expected.to be_json_eql(false.to_json).at_path('ignoreNonWorkingDays') }
end
context 'when the feature flag is off', with_flag: { work_packages_duration_field_active: false } do
it 'has no ignoreNonWorkingDays' do
expect(subject).not_to have_json_path('ignoreNonWorkingDays')
end
end
end
describe 'createdAt' do
@ -1388,7 +1376,7 @@ describe ::API::V3::WorkPackages::WorkPackageRepresenter do
end
describe 'parsing' do
describe 'duration', with_flag: { work_packages_duration_field_active: true } do
describe 'duration' do
subject { representer }
it 'parses form iso8601 format' do

@ -785,7 +785,7 @@ describe MailHandler, type: :model do
.to include 'The text of the reply.'
end
it 'alters the attributes', with_flag: { work_packages_duration_field_active: true } do
it 'alters the attributes' do
subject
expect(work_package.journals.reload.last.details)

@ -55,13 +55,7 @@ describe Queries::WorkPackages::Columns::PropertyColumn, type: :model do
end
end
context 'when duration feature flag disabled', with_flag: { work_packages_duration_field_active: false } do
it 'column does not exist' do
expect(described_class.instances.map(&:name)).not_to include :duration
end
end
context 'when duration feature flag enabled', with_flag: { work_packages_duration_field_active: true } do
context 'when duration feature flag enabled' do
it 'column exists' do
expect(described_class.instances.map(&:name)).to include :duration
end

@ -113,28 +113,16 @@ describe ::Type, type: :model do
describe '#work_package_attributes' do
subject { type.work_package_attributes }
context 'for the duration field', with_flag: { work_packages_duration_field_active: true } do
it 'does not return true field' do
context 'for the duration field' do
it 'does not return the field' do
expect(subject).not_to have_key("duration")
end
context 'when the feature flag is off', with_flag: { work_packages_duration_field_active: false } do
it 'does not return the field' do
expect(subject).not_to have_key("duration")
end
end
end
context 'for the ignore_non_working_days field', with_flag: { work_packages_duration_field_active: true } do
it 'does not return duration' do
context 'for the ignore_non_working_days field' do
it 'does not return the field' do
expect(subject).not_to have_key("ignore_non_working_days")
end
context 'when the feature flag is off', with_flag: { work_packages_duration_field_active: false } do
it 'does not return the duration field' do
expect(subject).not_to have_key("ignore_non_working_days")
end
end
end
end
end

@ -179,7 +179,7 @@ describe WorkPackage, type: :model do
work_package.save!
end
context 'for last created journal', with_flag: { work_packages_duration_field_active: true } do
context 'for last created journal' do
subject { work_package.journals.reload.last.details }
it 'contains all changes' do
@ -189,16 +189,6 @@ describe WorkPackage, type: :model do
expect(subject).to have_key(a.to_s), "Missing change for #{a}"
end
end
context 'when duration feature flag is inactive', with_flag: { work_packages_duration_field_active: false } do
it 'contains all changes' do
%i(subject description type_id status_id priority_id
start_date due_date estimated_hours assigned_to_id
responsible_id parent_id schedule_manually).each do |a|
expect(subject).to have_key(a.to_s), "Missing change for #{a}"
end
end
end
end
shared_examples_for 'old value' do
@ -246,7 +236,7 @@ describe WorkPackage, type: :model do
end
end
describe 'duration', with_flag: { work_packages_duration_field_active: true } do
describe 'duration' do
let(:property) { 'duration' }
context 'for old value' do
@ -260,22 +250,6 @@ describe WorkPackage, type: :model do
it_behaves_like 'new value'
end
context 'when duration feature flag is inactive', with_flag: { work_packages_duration_field_active: false } do
let(:property) { 'duration' }
context 'for old value' do
let(:expected_value) { nil }
it_behaves_like 'old value'
end
context 'for new value' do
let(:expected_value) { nil }
it_behaves_like 'new value'
end
end
end
end

@ -31,8 +31,7 @@ require 'spec_helper'
describe RootSeeder,
'standard edition',
with_config: { edition: 'standard' },
with_settings: { journal_aggregation_time_minutes: 0 },
with_flag: { work_packages_duration_field_active: true } do
with_settings: { journal_aggregation_time_minutes: 0 } do
before do
allow($stdout).to receive(:puts) { |msg| Rails.logger.info(msg) }
end

@ -233,11 +233,11 @@ RSpec.describe WorkPackages::ScheduleDependency::Dependency do
end
end
context 'with non working days', with_flag: { work_packages_duration_field_active: true } do
context 'with non working days' do
let!(:tomorrow_we_do_not_work!) { create(:non_working_day, date: Time.zone.tomorrow) }
it 'returns the soonest start date being a working day' do
follower = create_follower_of(work_package, ignore_non_working_days: false)
follower = create_follower_of(work_package)
expect(dependency_for(follower).soonest_start_date).to eq(work_package.due_date + 2.days)
end
end

@ -29,8 +29,7 @@
require 'spec_helper'
describe WorkPackages::SetAttributesService,
type: :model,
with_flag: { work_packages_duration_field_active: true } do
type: :model do
let(:today) { Time.zone.today }
let(:user) { build_stubbed(:user) }
let(:project) do
@ -1051,7 +1050,7 @@ describe WorkPackages::SetAttributesService,
context 'when start date changes' do
let(:work_package) do
build_stubbed(:work_package, start_date: monday, due_date: next_monday, ignore_non_working_days: false)
build_stubbed(:work_package, start_date: monday, due_date: next_monday)
end
let(:call_attributes) { { start_date: wednesday } }
@ -1067,7 +1066,7 @@ describe WorkPackages::SetAttributesService,
context 'when due date changes' do
let(:work_package) do
build_stubbed(:work_package, start_date: monday, due_date: next_monday, ignore_non_working_days: false)
build_stubbed(:work_package, start_date: monday, due_date: next_monday)
end
let(:call_attributes) { { due_date: monday + 14.days } }
@ -1083,7 +1082,7 @@ describe WorkPackages::SetAttributesService,
context 'when duration changes' do
let(:work_package) do
build_stubbed(:work_package, start_date: monday, due_date: next_monday, ignore_non_working_days: false)
build_stubbed(:work_package, start_date: monday, due_date: next_monday)
end
let(:call_attributes) { { duration: "13" } }
@ -1099,7 +1098,7 @@ describe WorkPackages::SetAttributesService,
context 'when duration and end_date both change' do
let(:work_package) do
build_stubbed(:work_package, start_date: monday, due_date: next_monday, ignore_non_working_days: false)
build_stubbed(:work_package, start_date: monday, due_date: next_monday)
end
let(:call_attributes) { { due_date: next_tuesday, duration: 4 } }

@ -28,7 +28,7 @@
require 'spec_helper'
describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_packages_duration_field_active: true } do
describe WorkPackages::SetScheduleService, 'working days' do
create_shared_association_defaults_for_work_package_factory
shared_let(:week_days) { create(:week_days) }
@ -42,7 +42,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'with a single successor' do
context 'when moving successor will cover non-working days' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | XX |
follower | XXX | follows work_package
@ -66,7 +66,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moved predecessor covers non-working days' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | XX |
follower | XXX | follows work_package
@ -91,7 +91,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'when predecessor moved forward' do
context 'on a day in the middle on working days with the follower having only start date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | X |
follower | [ | follows work_package
@ -114,7 +114,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'on a day just before non working days with the follower having only start date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | X |
follower | [ | follows work_package
@ -137,7 +137,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'on a day in the middle of working days with the follower having only due date and no space in between' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | ] | follows work_package
@ -160,7 +160,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'on a day in the middle of working days with the follower having only due date and much space in between' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSSmt |
work_package | ] |
follower | ] | follows work_package
@ -183,7 +183,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'on a day just before non-working day with the follower having only due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | ] | follows work_package
@ -206,7 +206,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with the follower having some space left' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | X |
follower | X..XX | follows work_package
@ -229,7 +229,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with the follower having enough space left to not be moved at all' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | X |
follower | XXX | follows work_package
@ -252,7 +252,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with the follower having some space left and a delay' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSSmtwtfss |
work_package | X |
follower | XXX | follows work_package with delay 3
@ -277,7 +277,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'when predecessor moved backwards' do
context 'on a day right before some non-working days' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | X |
follower | XX | follows work_package
@ -300,7 +300,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'on a day in the middle of working days' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | X |
follower | XX | follows work_package
@ -323,7 +323,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'on a day before non-working days the follower having space between' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | X |
follower | X | follows work_package
@ -346,7 +346,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with the follower having another relation limiting movement' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | mtwtfssmtwtfssMTWTFSS |
work_package | X |
follower | XX | follows work_package, follows annoyer with delay 2
@ -370,7 +370,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with the follower having another relation limiting movement and only due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | mtwtfssmtwtfssMTWTFSS |
work_package | X |
follower | ] | follows work_package, follows annoyer with delay 2
@ -396,7 +396,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'when removing the dates on the moved predecessor' do
context 'with the follower having start and due dates' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | XX |
follower | XXX | follows work_package
@ -419,7 +419,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with the follower having only a due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | XX |
follower | ] | follows work_package
@ -444,7 +444,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'when only creating the relation between predecessor and follower' do
context 'with follower having no dates' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | XX |
follower | |
@ -464,7 +464,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with follower having only due date before predecessor due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | XX |
follower | ] |
@ -484,7 +484,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with follower having only start date before predecessor due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | XX |
follower | [ |
@ -504,7 +504,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with follower having both start and due dates before predecessor due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | mtwtfssMTWTFSS |
work_package | XX |
follower | X..XXX |
@ -524,7 +524,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with follower having due date long after predecessor due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | XX |
follower | ] |
@ -544,7 +544,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with predecessor and follower having no dates' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | |
follower | |
@ -565,7 +565,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'with the successor having another predecessor which has no dates' do
context 'when moved forward' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | XXX | follows work_package, follows other_predecessor
@ -589,7 +589,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moved backwards' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | XXX | follows work_package, follows other_predecessor
@ -615,7 +615,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with a parent' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
parent | |
work_package | ] | child of parent
@ -638,7 +638,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with a parent having a follower' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
parent | XX |
work_package | ] | child of parent
@ -664,7 +664,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'with a single successor having a parent' do
context 'when moving forward' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | XX | follows work_package, child of follower_parent
@ -689,7 +689,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moving forward with the parent having another child not being moved' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | XX | follows work_package, child of follower_parent
@ -715,7 +715,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moving backwards' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | XX | follows work_package, child of follower_parent
@ -740,7 +740,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moving backwards with the parent having a predecessor limiting movement' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | mtwtfssMTWTFSS |
work_package | ] |
follower | XX | follows work_package, child of follower_parent
@ -766,7 +766,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moving backwards with the parent having another relation not limiting movement' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | mtwtfssMTWTFSS |
work_package | ] |
follower | XXXX | follows work_package, child of follower_parent
@ -792,7 +792,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moving backwards with the parent having another child not being moved' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | mtwtfssMTWTFSS |
work_package | ] |
follower | XX | follows work_package, child of follower_parent
@ -820,7 +820,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'with a single successor having a child' do
context 'when moving forward' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | XX | follows work_package
@ -847,7 +847,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'with a single successor having two children' do
context 'when creating the follows relation while follower starts 1 day after moved due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | XXXX..XXXXX..XX |
@ -868,7 +868,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when creating the follows relation while follower starts 3 days after moved due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | XX..XXXXX..XXXX |
@ -889,7 +889,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when creating the follows relation and follower first child starts before moved due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | X..XXXXX..XXXX |
@ -912,7 +912,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when creating the follows relation and both follower children start before moved due date' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
follower | XXX..XXXXX..X |
@ -938,7 +938,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'with a chain of followers' do
context 'when moving forward' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSSm sm sm |
work_package | ] |
follower1 | XXX | follows work_package
@ -967,7 +967,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moving forward with some space between the followers' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSSm sm sm |
work_package | ] |
follower1 | XXX | follows work_package
@ -994,7 +994,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moving forward with some delay and spaces between the followers' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSSm sm sm |
work_package | ] |
follower1 | XXX | follows work_package
@ -1023,7 +1023,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moving backwards' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSSm sm sm |
work_package | ] |
follower1 | XXX | follows work_package
@ -1054,7 +1054,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
context 'with a chain of followers with two paths leading to the same follower in the end' do
context 'when moving forward' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSSm sm |
work_package | ] |
follower1 | XXX | follows work_package
@ -1083,7 +1083,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'when moving backwards' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSSm sm |
work_package | ] |
follower1 | XXX | follows work_package
@ -1116,7 +1116,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
let(:changed_attributes) { [:parent] }
context 'without dates and with the parent being restricted in its ability to be moved' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | |
new_parent | | follows new_parent_predecessor with delay 3
@ -1138,7 +1138,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'without dates, with a duration and with the parent being restricted in its ability to be moved' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | | duration 4
new_parent | | follows new_parent_predecessor with delay 3
@ -1161,7 +1161,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with the parent being restricted in its ability to be moved and with a due date before parent constraint' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
new_parent | | follows new_parent_predecessor with delay 3
@ -1183,7 +1183,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with the parent being restricted in its ability to be moved and with a due date after parent constraint' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | ] |
new_parent | | follows new_parent_predecessor with delay 3
@ -1205,7 +1205,7 @@ describe WorkPackages::SetScheduleService, 'working days', with_flag: { work_pac
end
context 'with the parent being restricted but work package already has both dates set' do
let_schedule(<<~CHART, ignore_non_working_days: false)
let_schedule(<<~CHART)
days | MTWTFSS |
work_package | XX |
new_parent | | follows new_parent_predecessor with delay 3

@ -54,28 +54,16 @@ RSpec.describe WorkPackages::Shared::AllDays do
include_examples 'it returns duration', 365 * 2, Date.new(2022, 1, 1), Date.new(2023, 12, 31)
end
context 'without start date', with_flag: { work_packages_duration_field_active: true } do
context 'without start date' do
it 'returns nil' do
expect(subject.duration(nil, sunday_2022_07_31)).to be_nil
end
context 'when work packages duration field is inactive', with_flag: { work_packages_duration_field_active: false } do
it 'returns 1' do
expect(subject.duration(nil, sunday_2022_07_31)).to eq(1)
end
end
end
context 'without due date', with_flag: { work_packages_duration_field_active: true } do
context 'without due date' do
it 'returns nil' do
expect(subject.duration(sunday_2022_07_31, nil)).to be_nil
end
context 'when work packages duration field is inactive', with_flag: { work_packages_duration_field_active: false } do
it 'returns 1' do
expect(subject.duration(sunday_2022_07_31, nil)).to eq(1)
end
end
end
end

@ -31,7 +31,7 @@ require 'rails_helper'
RSpec.describe WorkPackages::Shared::Days do
subject { described_class.new }
describe '.for', with_flag: { work_packages_duration_field_active: true } do
describe '.for' do
context 'for a work_package ignoring non working days' do
let(:work_package) { build_stubbed(:work_package, ignore_non_working_days: true) }
@ -41,24 +41,11 @@ RSpec.describe WorkPackages::Shared::Days do
end
context 'for a work_package respecting non working days' do
let(:work_package) { build_stubbed(:work_package, ignore_non_working_days: false) }
let(:work_package) { build_stubbed(:work_package) }
it 'returns a WorkingDays instance' do
expect(described_class.for(work_package)).to be_an_instance_of(WorkPackages::Shared::WorkingDays)
end
end
context 'when work packages duration field is inactive', with_flag: { work_packages_duration_field_active: false } do
it 'always returns an AllDays instance' do
work_package = build_stubbed(:work_package)
expect(described_class.for(work_package)).to be_an_instance_of(WorkPackages::Shared::AllDays)
work_package = build_stubbed(:work_package, ignore_non_working_days: true)
expect(described_class.for(work_package)).to be_an_instance_of(WorkPackages::Shared::AllDays)
work_package = build_stubbed(:work_package, ignore_non_working_days: false)
expect(described_class.for(work_package)).to be_an_instance_of(WorkPackages::Shared::AllDays)
end
end
end
end

@ -78,28 +78,16 @@ RSpec.describe WorkPackages::Shared::WorkingDays do
include_examples 'it returns duration', 8, Date.new(2022, 12, 24), Date.new(2023, 1, 2)
end
context 'without start date', with_flag: { work_packages_duration_field_active: true } do
context 'without start date' do
it 'returns nil' do
expect(subject.duration(nil, sunday_2022_07_31)).to be_nil
end
context 'when work packages duration field is inactive', with_flag: { work_packages_duration_field_active: false } do
it 'returns 1' do
expect(subject.duration(nil, sunday_2022_07_31)).to eq(1)
end
end
end
context 'without due date', with_flag: { work_packages_duration_field_active: true } do
context 'without due date' do
it 'returns nil' do
expect(subject.duration(sunday_2022_07_31, nil)).to be_nil
end
context 'when work packages duration field is inactive', with_flag: { work_packages_duration_field_active: false } do
it 'returns 1' do
expect(subject.duration(sunday_2022_07_31, nil)).to eq(1)
end
end
end
end

@ -901,8 +901,7 @@ describe WorkPackages::UpdateService, 'integration tests', type: :model, with_ma
# rubocop:enable RSpec/ExampleLength
end
describe 'rescheduling work packages with a parent having a follows relation (Regression #43220)',
with_flag: { work_packages_duration_field_active: true } do
describe 'rescheduling work packages with a parent having a follows relation (Regression #43220)' do
let(:predecessor_work_package_attributes) do
work_package_attributes.merge(
start_date: Time.zone.today + 1.day,

@ -156,7 +156,7 @@ describe ScheduleHelpers::Chart do
end
end
describe '#to_s', with_flag: { work_packages_duration_field_active: true } do
describe '#to_s' do
let!(:week_days) { create(:week_days) }
context 'with a chart built from ascii representation' do

Loading…
Cancel
Save