Defect #43625
openDuration is shortened by one day when adding a relation and the following issue starts on a non-working day
0%
Description
Overview
When adding a relation between issues,
if the start date of the following issue falls on a non-working day,
the issue’s Duration is shortened by one day.
Duration is expected to be calculated based on working days only.
However, when a relation is added and the following issue is rescheduled,
an unintended reduction of Duration occurs when the original start date is a non-working day.
Steps to reproduce
1. Configure the working calendar so that a specific date is marked as a non-working day
2. Create Issue A (preceding issue) with start date and due date set
3. Create Issue B (following issue) with its start date set to a non-working day
4. Add a relation between Issue A and Issue B (e.g. precedes / follows)
Expected result
- The Duration of the following issue remains correct, based on working days
- The Duration is not automatically reduced when the start date is a non-working day
Actual result
- After adding the relation, the Duration of the following issue is shortened by one day
- This occurs when the original start date of the following issue is a non-working day
Environment (tested)
- Redmine: 5.1.2
- Ruby: 3.2.3
- Database: PostgreSQL 16
Possible cause
In `Issue#reschedule_on`, the working duration is calculated before the start date is shifted to the next working day.
If the original start date is a non-working day, `working_duration` is already reduced by one day, and that value is then used to calculate the due date.
# app/models/issue.rb
def reschedule_on(date)
wd = working_duration
date = next_working_date(date)
self.start_date = date
self.due_date = add_working_days(date, wd)
end
As a result, the shortened `wd` is passed to `add_working_days`, and the Duration becomes shorter than intended.
Proposed improvement
If the difference (in days) between the original start date and the first working day is added to `wd` before rescheduling,
a start date on a non-working day can still be treated as one working day, and the original Duration can be preserved.
Example implementation:
# app/models/issue.rb
def reschedule_on(date)
wd = working_duration
if start_date
carry = (next_working_date(start_date) - start_date).to_i
wd += carry if carry > 0
end
date = next_working_date(date)
self.start_date = date
self.due_date = add_working_days(date, wd)
end
No data to display