bug/74156 Sort WP lists by project identifier, not project_id, in semantic mode (#23400)

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.
This commit is contained in:
Kabiru Mwenja
2026-05-28 12:05:24 +03:00
committed by GitHub
parent 4c0559242c
commit 58a5e19669
2 changed files with 25 additions and 7 deletions
@@ -37,15 +37,9 @@ class Queries::WorkPackages::Selects::PropertySelect < Queries::WorkPackages::Se
self.property_selects = {
id: {
# Sorting by "ID" follows the displayed identifier. In semantic mode, the
# visible ID is `<project_identifier>-<sequence_number>`, so the database
# primary key is the wrong sort key — a work package moved between projects
# keeps its PK but receives a new sequence in the target project. Order by
# (project_id, sequence_number) keeps each project's rows monotone in their
# visible numbering and is backed by an existing partial unique index.
sortable: -> {
if Setting::WorkPackageIdentifier.semantic?
["#{WorkPackage.table_name}.project_id", "#{WorkPackage.table_name}.sequence_number"]
["#{Project.table_name}.identifier", "#{WorkPackage.table_name}.sequence_number"]
else
"#{WorkPackage.table_name}.id"
end
@@ -106,6 +106,30 @@ RSpec.describe Query::Results, "sort by id" do
end
end
context "with rows from two projects whose identifiers invert the creation order" do
let(:np_project) { create(:project, identifier: "ABC") }
let!(:np_wp) do
wp = create(:work_package, project: np_project, subject: "First in ABC", skip_semantic_id_allocation: true)
wp.update_columns(sequence_number: 1, identifier: "ABC-1")
wp
end
let(:query) do
build_stubbed(:query,
user:,
project: nil,
show_hierarchies: false,
sort_criteria: [%w[id asc]],
column_names: %i[id subject])
end
it "orders rows by the project identifier prefix, not by project_id" do
identifiers = described_class.new(query).work_packages.pluck(:identifier)
expect(identifiers).to eq(%w[ABC-1 LARGE-1 LARGE-2 LARGE-3])
end
end
context "with a non-ID primary sort and a tie" do
before do
WorkPackage.where(id: wps.map(&:id)).update_all(subject: "Same subject")