Skip to content

Commit

Permalink
Trigger the recalculation job when changing to work weighted mode
Browse files Browse the repository at this point in the history
* Triggers job
* Adds journal entries with specs and translations
  • Loading branch information
aaron-contreras committed Sep 23, 2024
1 parent ebb5177 commit 424a2b8
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 33 deletions.
1 change: 1 addition & 0 deletions app/models/journal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class Journal < ApplicationRecord
progress_mode_changed_to_status_based
status_changed
system_update
total_percent_complete_mode_changed_to_work_weighted_average
work_package_children_changed_times
work_package_parent_changed_times
work_package_predecessor_changed_times
Expand Down
4 changes: 4 additions & 0 deletions app/services/settings/update_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ def set_setting_value(name, value)
Setting[name] = new_value
if name == :work_package_done_ratio && old_value != "status" && new_value == "status"
WorkPackages::Progress::ApplyStatusesChangeJob.perform_later(cause_type: "progress_mode_changed_to_status_based")
elsif name == :total_percent_complete_mode && old_value != "work_weighted_average" && new_value == "work_weighted_average"
WorkPackages::Progress::ApplyTotalPercentCompleteModeChangeJob
.perform_later(mode: new_value,
cause_type: "total_percent_complete_mode_changed_to_work_weighted_average")
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class WorkPackages::Progress::ApplyTotalPercentCompleteModeChangeJob < WorkPacka
total_percent_complete_mode_changed_to_simple_average
].freeze

attr_reader :cause_type, :old_mode, :new_mode
attr_reader :cause_type, :mode

# Updates the total % complete of all work packages after the total
# percent complete mode has been changed.
Expand All @@ -45,13 +45,12 @@ class WorkPackages::Progress::ApplyTotalPercentCompleteModeChangeJob < WorkPacka
#
# It creates a journal entry with the System user describing the changes.
#
# @param [String] old_mode The previous total percent complete mode
# @param [String] new_mode The new total percent complete mode
# @param [String] cause_type The cause type of the change
# @param [String] mode The new total percent complete mode
# @return [void]
def perform(cause_type:, old_mode:, new_mode:)
def perform(cause_type:, mode:)
@cause_type = cause_type
@old_mode = old_mode
@new_mode = new_mode
@mode = mode

with_temporary_total_percent_complete_table do
update_total_percent_complete
Expand All @@ -62,17 +61,17 @@ def perform(cause_type:, old_mode:, new_mode:)
private

def update_total_percent_complete
case new_mode
case mode
when "work_weighted_average"
update_work_weighted_average
update_to_work_weighted_average
when "simple_average"
update_simple_average
update_to_simple_average
else
raise ArgumentError, "Invalid total percent complete mode: #{new_mode}"
raise ArgumentError, "Invalid total percent complete mode: #{mode}"
end
end

def update_work_weighted_average
def update_to_work_weighted_average
execute(<<~SQL.squish)
UPDATE temp_wp_progress_values
SET total_p_complete = CASE
Expand All @@ -91,7 +90,7 @@ def update_work_weighted_average
SQL
end

def update_simple_average
def update_to_simple_average
execute(<<~SQL.squish)
UPDATE temp_wp_progress_values
SET derived_done_ratio = CASE
Expand Down
4 changes: 2 additions & 2 deletions app/workers/work_packages/progress/sql_commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ def drop_temporary_progress_table

def with_temporary_total_percent_complete_table
WorkPackage.transaction do
case new_mode
case mode
when "work_weighted_average"
create_temporary_total_percent_complete_table_for_work_weighted_average_mode
when "simple_average"
create_temporary_total_percent_complete_table_for_simple_average_mode
else
raise ArgumentError, "Invalid total percent complete mode: #{new_mode}"
raise ArgumentError, "Invalid total percent complete mode: #{mode}"
end

yield
Expand Down
3 changes: 3 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,7 @@ en:
progress_mode_changed_to_status_based: "Progress calculation updated"
status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
total_percent_complete_mode_changed_to_work_weighted_average: "Calculation of % Complete totals now weighted by Work."

cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
Expand Down Expand Up @@ -1943,6 +1944,8 @@ en:
totals_removed_from_childless_work_packages: >-
Work and progress totals automatically removed for non-parent work packages with <a href="%{href}" target="_blank">version update</a>.
This is a maintenance task and can be safely ignored.
total_percent_complete_mode_changed_to_work_weighted_average: >-
Child work packages without Work are ignored.
links:
configuration_guide: "Configuration guide"
Expand Down
6 changes: 6 additions & 0 deletions lib/open_project/journal_formatter/cause.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ def cause_description
status_changed_message
when "progress_mode_changed_to_status_based"
progress_mode_changed_to_status_based_message
when "total_percent_complete_mode_changed_to_work_weighted_average"
total_percent_complete_mode_changed_to_work_weighted_average_message
else
related_work_package_changed_message
end
Expand Down Expand Up @@ -143,6 +145,10 @@ def progress_mode_changed_to_status_based_message
I18n.t("journals.cause_descriptions.progress_mode_changed_to_status_based")
end

def total_percent_complete_mode_changed_to_work_weighted_average_message
I18n.t("journals.cause_descriptions.total_percent_complete_mode_changed_to_work_weighted_average")
end

def related_work_package_changed_message
related_work_package = WorkPackage.includes(:project).visible(User.current).find_by(id: cause["work_package_id"])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
end
end

context "when sending path request to change progress calculation from status-based to status-based" do
context "when sending patch request to change progress calculation from status-based to status-based" do
before do
Setting.work_package_done_ratio = "status"
end
Expand Down Expand Up @@ -97,4 +97,27 @@
.not_to have_been_enqueued
end
end

context "when changing total percent complete mode from simple average to work-weighted average" do
before do
Setting.total_percent_complete_mode = "simple_average"
end

it "starts a job to update work packages' total % complete values" do
patch "update",
params: {
settings: {
total_percent_complete_mode: "work_weighted_average"
}
}
expect(WorkPackages::Progress::ApplyTotalPercentCompleteModeChangeJob)
.to have_been_enqueued.with(old_mode: "simple_average",
new_mode: "work_weighted_average",
cause_type: "total_percent_complete_mode_changed_to_work_weighted_average")

perform_enqueued_jobs

expect(Setting.total_percent_complete_mode).to eq("work_weighted_average")
end
end
end
16 changes: 16 additions & 0 deletions spec/lib/journal_formatter/cause_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,22 @@ def render(cause, html:)
end
end

context "when a change of total percent complete mode from " \
"simple average to work-weighted average is the cause" do
subject(:cause) do
{
"type" => "total_percent_complete_mode_changed_to_work_weighted_average"
}
end

it do
expect(cause).to render_html_variant(
"<strong>Calculation of % Complete totals now weighted by Work.</strong> " \
"Child work packages without Work are ignored."
)
end
end

context "when both a change of status % complete and excluded from totals is the cause" do
shared_let(:status) { create(:status, name: "In progress", default_done_ratio: 40) }
subject(:cause) do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,10 @@

def expect_performing_job_changes(from:, to:,
cause_type: "total_percent_complete_mode_changed_to_work_weighted_average",
old_mode: "simple_average",
new_mode: "work_weighted_average")
mode: "work_weighted_average")
table = create_table(from)

job.perform_now(cause_type:, old_mode:, new_mode:)
job.perform_now(cause_type:, mode:)

table.work_packages.map(&:reload)
expect_work_packages(table.work_packages, to)
Expand All @@ -75,8 +74,7 @@ def expect_performing_job_changes(from:, to:,
context "on a single-level hierarchy" do
it "updates the total % complete of the work packages" do
expect_performing_job_changes(
old_mode: "simple_average",
new_mode: "work_weighted_average",
mode: "work_weighted_average",
from: <<~TABLE,
hierarchy | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
flat_wp_1 | 10h | | 6h | | 40% |
Expand All @@ -94,8 +92,7 @@ def expect_performing_job_changes(from:, to:,
context "on a two-level hierarchy with parents having total values" do
it "updates the total % complete of parent work packages" do
expect_performing_job_changes(
old_mode: "simple_average",
new_mode: "work_weighted_average",
mode: "work_weighted_average",
from: <<~TABLE,
hierarchy | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
parent | 10h | 30h | 6h | 6h | 40% | 70%
Expand All @@ -117,8 +114,7 @@ def expect_performing_job_changes(from:, to:,
context "on a two-level hierarchy with only % complete values set" do
it "unsets the % complete value from parents" do
expect_performing_job_changes(
old_mode: "simple_average",
new_mode: "work_weighted_average",
mode: "work_weighted_average",
from: <<~TABLE,
hierarchy | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
parent | | | | | 40% | 70%
Expand All @@ -140,8 +136,7 @@ def expect_performing_job_changes(from:, to:,
context "on a multi-level hierarchy with only % complete values set" do
it "unsets the % complete value from parents" do
expect_performing_job_changes(
old_mode: "simple_average",
new_mode: "work_weighted_average",
mode: "work_weighted_average",
from: <<~TABLE,
hierarchy | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
parent | | | | | 40% | 63%
Expand All @@ -167,8 +162,7 @@ def expect_performing_job_changes(from:, to:,
context "on a multi-level hierarchy with work and remaining work values set" do
it "updates the total % complete of parent work packages" do
expect_performing_job_changes(
old_mode: "simple_average",
new_mode: "work_weighted_average",
mode: "work_weighted_average",
from: <<~TABLE,
hierarchy | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
parent | 10h | 50h | 6h | 6h | 40% | 63%
Expand All @@ -192,10 +186,42 @@ def expect_performing_job_changes(from:, to:,
end

describe "journal entries" do
it "is still not done" do
pending "TODO: Add specs for the journal entries created"
raise StandardError, "Not implemented"
# rubocop:disable RSpec/ExampleLength
it "creates journal entries for the modified work packages" do
parent, child1, child2, child3, grandchild1, grandchild2 = expect_performing_job_changes(
mode: "work_weighted_average",
from: <<~TABLE,
hierarchy | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
parent | 10h | 50h | 6h | 6h | 40% | 63%
child1 | 15h | | 0h | | 100% |
child2 | | | | | 40% |
child3 | 5h | 25h | 0h | 0h | 100% | 70%
grandchild1 | | | | | 40% |
grandchild2 | 20h | | 0h | | 100% |
TABLE
to: <<~TABLE
subject | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
parent | 10h | 50h | 6h | 6h | 40% | 88%
child1 | 15h | | 0h | | 100% |
child2 | | | | | 40% |
child3 | 5h | 25h | 0h | 0h | 100% | 100%
grandchild1 | | | | | 40% |
grandchild2 | 20h | | 0h | | 100% |
TABLE
)
[parent, child3].each do |work_package|
expect(work_package.journals.count).to eq 2
last_journal = work_package.last_journal
expect(last_journal.user).to eq(User.system)
expect(last_journal.cause_type).to eq("total_percent_complete_mode_changed_to_work_weighted_average")
end

# unchanged => no new journals
[child1, child2, grandchild1, grandchild2].each do |work_package|
expect(work_package.journals.count).to eq 1
end
end
# rubocop:enable RSpec/ExampleLength
end
end

Expand All @@ -210,8 +236,7 @@ def expect_performing_job_changes(from:, to:,

before do
job.perform_now(cause_type: "should make it blow up!",
old_mode: "simple_average",
new_mode: "work_weighted_average")
mode: "work_weighted_average")
rescue StandardError
# Catch the error to continue the test
end
Expand Down

0 comments on commit 424a2b8

Please sign in to comment.