131 Commits

Author SHA1 Message Date
Oliver Günther 2a6412d5ae Merge remote-tracking branch 'origin/release/17.3' into release/17.4 2026-06-02 16:22:05 +02:00
Oliver Günther bef69b6aaf Parse query params as a separate options hash, not kwargs 2026-06-02 16:21:14 +02:00
Tomas Hykel cc475e6c2e [#71645] Improve interface of WP identifier setting controller 2026-04-16 20:35:34 +02:00
Jan Sandbrink f9d8bc6614 Introduce SubclassResponsibility error
This error is intended for cases when a method is
intentionally not implemented, because the module/class defining
it expects a subclass (or class including the module) to implement
the method.

This is intended to distinguish it from other cases, such as:
* feature not implemented yet
* edge case of a method call not yet supported

Notably it avoids the misuse of the Ruby-defined NotImplementedError,
which is only intended for much more specific scenarios:

> Raised when a feature is not implemented on the current platform. For example, methods depending on the fsync or fork system calls may raise this exception [...]

Also see https://docs.ruby-lang.org/en/master/NotImplementedError.html
2026-03-27 08:14:56 +01:00
Kabiru Mwenja 45b61771a7 Document single-job assumption on ApplyHandlesJob
The status polling UI assumes at most one active instance of this job
at a time. Add a FIXME to enforce this with GoodJob concurrency
control once the real migration body is implemented.
2026-03-07 12:54:27 +03:00
Kabiru Mwenja a5ea92db04 Unify identifier settings form into single state-machine component
Replace the two-component approach (IdentifierSettingsFormComponent +
IdentifierChangeInProgressComponent) with a single component cycling
through three lifecycle states: :edit, :change_in_progress, :completed.
2026-03-06 09:21:17 +03:00
Oliver Günther 80e6aa4657 Do not update the attachment on initial journals
https://community.openproject.org/work_packages/71403
2026-02-10 14:39:23 +01:00
Oliver Günther 3aa5275567 Merge pull request #21214 from opf/feat/workflow-work-package
Recreate artifact on status change
2025-12-08 14:08:55 +01:00
Klaus Zanders 8c0241f567 Aggregate migration 20241120095318_update_scheduling_mode_and_lags 2025-11-24 14:19:33 +01:00
ulferts 7b2fde2eb1 remove job no longer referenced 2025-07-22 14:54:30 +02:00
ulferts 2b68eb08ad squash migrations below 15.0 2025-07-22 14:54:28 +02:00
Alexander Brandon Coles bc693e02ea Fix missing copyright notices in app/workers 2025-07-18 18:10:42 +01:00
Alexander Brandon Coles 03572f4444 Freeze string literals in app/workers
rubocop -A --only Style/FrozenStringLiteralComment,Layout/EmptyLineAfterMagicComment,Style/RedundantFreeze app/workers
2025-07-18 17:42:42 +01:00
Christophe Bliard 4b6056b333 refactor: Extract methods to deal with % complete modes
To keep all future usages of "work_weighted_average" and
"simple_average" magic strings at the same place.
2025-07-08 18:20:05 +02:00
Ivan Kuchin a637335fe2 rename covering_dates_and_days_of_week to covering_dates_or_days_of_week 2025-06-04 18:33:32 +02:00
Ivan Kuchin cde4bba693 extract common parts of ApplyWorkingDaysChangeJobs 2025-06-04 18:33:24 +02:00
Ivan Kuchin 54921b00d4 cache changed_days and changed_non_working_dates 2025-06-04 18:33:23 +02:00
Ivan Kuchin 3e8763173b refactor method for producing a hash with differenc between two lists
Choosing combination of speed and clarity of intent:
```rb
require 'benchmark/ips'

require 'active_support/core_ext/enumerable'

def change_between(list_a, list_b)
  set_a = Set.new(list_a)
  set_b = Set.new(list_b)

  (set_a ^ set_b).index_with { set_b.include?(it) }
end

def change_between1(list_a, list_b)
  was = list_a.to_h { [it, false] }
  now = list_b.to_h { [it, true] }

  now.merge(was){ nil }.compact
end

def change_between2(list_a, list_b)
  deleted = (list_a - list_b).to_h { [it, false] }
  added = (list_b - list_a).to_h { [it, true] }

  deleted.merge(added)
end

def change_between3(list_a, list_b)
  set_a = Set.new(list_a)
  set_b = Set.new(list_b)
  deleted = (set_a - set_b).to_h { [it, false] }
  added = (set_b - set_a).to_h { [it, true] }
  deleted.merge(added)
end

def change_between4(list_a, list_b)
  was = list_a.index_with(false)
  now = list_b.index_with(true)

  now.merge(was){ nil }.compact
end

def change_between5(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 change_between6(list_a, list_b)
  set_a = Set.new(list_a)
  set_b = Set.new(list_b)
  deleted = (set_a - set_b).index_with(false)
  added = (set_b - set_a).index_with(true)
  deleted.merge(added)
end

def compare(list)
  as_and_bs = 1000.times.map do
    [list.sample(rand(list.length)), list.sample(rand(list.length))]
  end

  change_between_methods = private_methods.grep(/^change_between\d?$/)

  as_and_bs.each do |a, b|
    d = change_between(a, b)
    change_between_methods.each do |change_between_method|
      fail "#{change_between_method} returned different result" unless d
== send(change_between_method, a, b)
    end
  end

  Benchmark.ips do |x|
    change_between_methods.each do |change_between_method|
      x.report(change_between_method) { as_and_bs.map{
send(change_between_method, _1, _2) } }
    end

    x.compare!
  end
end

compare(7.times.to_a)
compare(100.times.to_a)
```

```
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [arm64-darwin23]
Warming up --------------------------------------
      change_between    40.000 i/100ms
     change_between1   158.000 i/100ms
     change_between2   170.000 i/100ms
     change_between3    32.000 i/100ms
     change_between4   152.000 i/100ms
     change_between5   148.000 i/100ms
     change_between6    33.000 i/100ms
Calculating -------------------------------------
      change_between    408.732 (± 2.7%) i/s    (2.45 ms/i) -      2.080k in   5.093365s
     change_between1      1.588k (± 0.7%) i/s  (629.69 μs/i) -      8.058k in   5.074251s
     change_between2      1.645k (±12.2%) i/s  (607.90 μs/i) -      8.160k in   5.048118s
     change_between3    318.922 (± 2.8%) i/s    (3.14 ms/i) -      1.600k in   5.021512s
     change_between4      1.477k (± 1.3%) i/s  (676.94 μs/i) -      7.448k in   5.042753s
     change_between5      1.608k (± 8.5%) i/s  (621.98 μs/i) -      7.992k in   5.012654s
     change_between6    331.757 (± 1.8%) i/s    (3.01 ms/i) -      1.683k in   5.074711s

Comparison:
     change_between2:     1645.0 i/s
     change_between5:     1607.8 i/s - same-ish: difference falls within error
     change_between1:     1588.1 i/s - same-ish: difference falls within error
     change_between4:     1477.2 i/s - same-ish: difference falls within error
      change_between:      408.7 i/s - 4.02x  slower
     change_between6:      331.8 i/s - 4.96x  slower
     change_between3:      318.9 i/s - 5.16x  slower

ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [arm64-darwin23]
Warming up --------------------------------------
      change_between     4.000 i/100ms
     change_between1    10.000 i/100ms
     change_between2    10.000 i/100ms
     change_between3     4.000 i/100ms
     change_between4     9.000 i/100ms
     change_between5    11.000 i/100ms
     change_between6     4.000 i/100ms
Calculating -------------------------------------
      change_between     45.431 (± 4.4%) i/s   (22.01 ms/i) -    228.000 in   5.029300s
     change_between1    112.354 (± 7.1%) i/s    (8.90 ms/i) -    560.000 in   5.013557s
     change_between2    133.466 (± 4.5%) i/s    (7.49 ms/i) -    670.000 in   5.031395s
     change_between3     44.247 (± 2.3%) i/s   (22.60 ms/i) -    224.000 in   5.065967s
     change_between4    104.443 (± 4.8%) i/s    (9.57 ms/i) -    522.000 in   5.011400s
     change_between5    114.941 (± 6.1%) i/s    (8.70 ms/i) -    583.000 in   5.094324s
     change_between6     46.083 (± 4.3%) i/s   (21.70 ms/i) -    232.000 in   5.047312s

Comparison:
     change_between2:      133.5 i/s
     change_between5:      114.9 i/s - 1.16x  slower
     change_between1:      112.4 i/s - 1.19x  slower
     change_between4:      104.4 i/s - 1.28x  slower
     change_between6:       46.1 i/s - 2.90x  slower
      change_between:       45.4 i/s - 2.94x  slower
     change_between3:       44.2 i/s - 3.02x  slower
```
2025-06-04 18:33:23 +02:00
Ivan Kuchin c8bd1678b0 extract commond code for changed_days and changed_non_working_dates 2025-06-04 18:33:22 +02:00
Ivan Kuchin 3d673294c3 attr readers instead of accessors in WorkPackages::ApplyWorkingDaysChangeJob 2025-05-05 12:10:28 +02:00
Christophe Bliard 6daf60e70e Add missing magic comment # frozen_string_literal: true 2025-02-25 09:12:27 +01:00
Christophe Bliard b4d2f5dc9c [59539] Correctly reschedule predecessors needing relations rescheduling
Edge case not detected by the previous algorithm: relation has no lag
but covers non-working days changed into working days. The successors
need to be rescheduled, which is done by rescheduling from the
predecessor.
2025-02-25 09:12:24 +01:00
Christophe Bliard 3b5562fc5e Simplify method calls
State is stored in instance variables instead of being passed around as parameters and return values.
2025-02-25 09:12:23 +01:00
Christophe Bliard 4034896420 [59539] Keep manual scheduling mode in migration
The rule is: it never switches from manual to automatic scheduling mode.
It only switches from automatic to manual, and only if keeping automatic
is not possible because it would mean losing the dates.

The code and specs have been updated to reflect this.

A materialized view is used to reuse the data in multiple different
queries.
2025-02-25 09:12:21 +01:00
Christophe Bliard afdf4308b5 [59539] Only set lag for the closest relation in the migration 2025-02-25 09:12:21 +01:00
Christophe Bliard 04d3f6651b [59539] Respect non-working days when computing lags in migration
`lag` is the number of _working_ days between predecessor and successor
dates.
2025-02-25 09:12:21 +01:00
Christophe Bliard 35f463f4bd [59539] Migration: set lag for follows relations
To preserve dates, a lag is set for follows relations when both the
predecessor and the follower have dates.
2025-02-25 09:12:20 +01:00
Christophe Bliard dcaf5aa892 [59539] Migration: followers and parents have automatic scheduling mode
https://community.openproject.org/wp/59539
2025-02-25 09:12:20 +01:00
Christophe Bliard 06f596cdf3 [42388] Migrate scheduling mode and lags
https://community.openproject.org/wp/42388

Scheduling mode is now manual by default. Only successors will be in
automatic mode.

WIP
2025-02-25 09:12:19 +01:00
Christophe Bliard 381e2f4b09 [57990] Make migration work with database from before 14.0 version
https://community.openproject.org/wp/57990

The code to create the temporary table in common between the migration
and the job to update status and % complete values. It has recently
changed to get the `excluded_from_totals` value from the `statuses`
table, but this field has been created in 14.2, and does not exist yet
in 14.0 when this migration is run.

This commit adds the previous version of the code to create the
temporary table, that does not require the `excluded_from_totals` field.
It also avoids creating the depths table which is not necessary in this
case.
2024-09-26 15:11:51 +02:00
Aaron Contreras de86221361 Extract common operations to sql_commands 2024-09-25 13:54:31 -05:00
Aaron Contreras 95cda6de29 Remove unnecessary update 2024-09-25 13:49:09 -05:00
Aaron Contreras 946b57d9e5 Merge branch 'dev' into implementation/57529-options-for-total-calculation-sum-mode 2024-09-25 13:20:38 -05:00
Christophe Bliard 3250f5104a Compute total % complete according to mode in update status job
Reuse and duplicate a lot of logic from the other job. It needs to be
reworked, but it works
2024-09-25 17:13:35 +02:00
Christophe Bliard 3f97171b79 Use work_package_hierarchies to create depth table
Simpler.
2024-09-25 17:12:34 +02:00
Christophe Bliard 4ac1b1ca7a Remove :percent_complete_edition feature flag
% complete edition will be released in 14.6
2024-09-25 15:31:11 +02:00
Aaron Contreras 1f12393880 Account for status exclusion from total calculations in simple average mode 2024-09-24 16:56:36 -05:00
Aaron Contreras 2f2561c08f Add in simple average calculation mode job
* Adds temporary depth table - Could be cleaned up down thie line with
  the `work_package_hierarchies` table.
2024-09-24 16:35:58 -05:00
Aaron Contreras 6cbfdc8e78 Trigger the recalculation job when changing to work weighted mode
* Triggers job
* Adds journal entries with specs and translations
2024-09-24 11:10:22 -05:00
Aaron Contreras 503ad154ca Add recalculation in job when switching to work weighted mode
* Missing to add journal entries
2024-09-24 11:10:21 -05:00
Christophe Bliard 0368f40b66 Fix rubocop Metrics/AbcSize warning 2024-09-23 16:38:04 +02:00
Christophe Bliard 35b583bc35 refactor: rename methods to avoid abbreviations 2024-09-23 14:34:03 +02:00
Christophe Bliard eb9283507f [57990] Preserve % Complete over Remaining work when migrating
https://community.openproject.org/wp/57990

In 14.0, Work and Remaining work were deemed more important than
% Complete. Now in 14.6, as % Complete becomes editable and more
important, we want to preserve it over Remaining work for users having
not yet migrated to version 14.0.
2024-09-23 14:34:03 +02:00
Christophe Bliard f0f1e9eca6 Clear % complete when work is 0h when switching to work-based mode
That prevent having something like W=0h RW=0h %C=60% which leads to an
error being displayed when the popover is open.
2024-08-23 15:49:16 +02:00
Christophe Bliard 4647786916 Fix missed work derivation when switching progress calculation modes
If a work package has only remaining work being set and progress
calculation mode is changed from work-based to status-based, then work
package gets a % complete value.

Remaining work and % complete being both present, work has to be
derived.
2024-08-23 15:26:04 +02:00
Ivan Kuchin 4911b8a149 remove years from copyrights (except for COPYRIGHT file) 2024-07-31 15:02:49 +02:00
Christophe Bliard 8c82acdccd Update app/workers/work_packages/progress/apply_statuses_change_job.rb
Co-authored-by: Aaron Contreras <61627014+aaron-contreras@users.noreply.github.com>
2024-06-03 17:59:10 +02:00
Christophe Bliard 5e4766f072 Merge branch 'dev' into feature/49409-status-exclude-from-totals 2024-06-03 17:56:41 +02:00
Marcello Rocha 36108c86c0 Apply @ulferts feedback 2024-05-27 11:24:07 +02:00
Marcello Rocha 42dce573e2 Makes sure jobs are eventually discarded when concurrency happens 2024-05-27 11:24:05 +02:00