Sort WP lists by project identifier, not project_id, in semantic mode
The semantic-mode "ID" sort grouped projects by project_id (insertion
order) before the per-project sequence. Projects added after others
landed below them in the list even when their identifier sorted
alphabetically earlier. Sort by projects.identifier instead so the order
matches the visible "<project identifier>-<sequence>" column.
The projects table is already joined for every work-package list query,
so the new sort term costs no extra round-trip.
Sort work packages by sequence_number in semantic mode
In semantic mode the visible "ID" is `<project_identifier>-<sequence_number>`,
but the list sort key was the database primary key. A work package moved
between projects keeps its primary key and receives a new sequence number
in the target project, so it could appear above natively-created rows with
higher sequence numbers — e.g. `LARGE-3` above `LARGE-1` and `LARGE-2`.
The "ID" sortable on the work-package query select now resolves at request
time. In semantic mode it returns `(work_packages.project_id, work_packages
.sequence_number)`, backed by the existing partial unique index. In classic
mode it stays `work_packages.id`. The Proc resolution lives in
`WorkPackageSelect#sortable` so every consumer (`Query::SortCriteria`,
group-by composition, the HAL/API sortBy resource) sees the resolved value.
The factory for cost entries and time entries has changed, and it was
still using `work_package` instead of `entity`. This created additional work packages and made the test fail.
https://community.openproject.org/wp/63191
Before, % Complete sum was calculated based on work and remaining work
sums, meaning work packages with only % Complete is set are ignored.
Now, if "Calculation of % Complete hierarchy totals" is set to "Simple
average", the % Complete sum is calculated as an average of the %
Complete values of work packages having % Complete set.
If "Calculation of % Complete hierarchy totals" is set to "Weighted by
work", the calculation is not changed: it is still based on work and
remaining work sums.
Having the full `Costs::QueryCurrencySelect`,
`Queries::WorkPackages::Selects::CustomFieldSelect`, or
`Queries::WorkPackages::Selects::PropertySelect` instances displayed
when there is a failure makes it hard to spot the wrong value.
Converting the column to its string name makes it easier to read.
https://community.openproject.org/wp/55802
It's calculated based on work sum and remaining work sum.
The % Complete sums have also been added to the PDF export.
Formatting of done_ratio values in the PDF export has been slightly
improved: when value is not there, it displays nothing now. Before it
was displaying a "%".