Commit d120c7b4 authored by Jan Reimes's avatar Jan Reimes
Browse files

Sort TDoc queries by meeting start_date, then case-insensitive tdoc_id

Default order changed from DESC to ASC (earliest-first). Sort key now
uses meeting start_date (from meetings table) instead of the TDoc's
reservation date. TDoc ID sort is case-insensitive via .upper().

Added _meeting_start_date helper for the sort key to keep line length
under 160 chars.
parent 6d15352f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ def query_tdocs(
    start_date: StartDateOption = None,
    end_date: EndDateOption = None,
    limit: LimitOption = None,
    order: OrderOption = SortOrder.DESC.value,
    order: OrderOption = SortOrder.ASC.value,
    output_format: OutputFormatOption = OutputFormat.TABLE.value,
    checkout: CheckoutOption = False,
    fetch: FetchOption = True,
+1 −1
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ def query_tdocs(
    start_date: StartDateOption = None,
    end_date: EndDateOption = None,
    limit: LimitOption = None,
    order: OrderOption = SortOrder.DESC.value,
    order: OrderOption = SortOrder.ASC.value,
    output_format: OutputFormatOption = OutputFormat.TABLE.value,
    checkout: CheckoutOption = False,
    fetch: FetchOption = True,
+18 −2
Original line number Diff line number Diff line
@@ -147,6 +147,9 @@ class TDocDatabase(MeetingDatabase):
        still require in-memory processing because they span multiple tables
        or use fnmatch.

        Sort order: meeting start_date, then tdoc_id (case-insensitive).
        Direction controlled by ``config.order``.

        Args:
            config: Query configuration with filters and options

@@ -178,11 +181,14 @@ class TDocDatabase(MeetingDatabase):

        records = self._apply_pattern_filters(records, config)

        # Build meeting map for sort (need start_date from meetings)
        meeting_map = {meeting.meeting_id: meeting for meeting in await self._table_rows(MeetingMetadata)}
        descending = config.order.value.lower() == "desc"
        fallback = date.max if descending else date.min
        records.sort(
            key=lambda record: (
                record.date_created or datetime.min.replace(tzinfo=UTC),
                record.tdoc_id,
                self._meeting_start_date(record, meeting_map, fallback),
                record.tdoc_id.upper(),
            ),
            reverse=descending,
        )
@@ -192,6 +198,16 @@ class TDocDatabase(MeetingDatabase):

        return records

    @staticmethod
    def _meeting_start_date(record: TDocMetadata, meeting_map: dict[int, MeetingMetadata], fallback: date) -> date:
        """Return the meeting start_date for sorting, or fallback if unavailable."""
        if not record.meeting_id:
            return fallback
        meeting = meeting_map.get(record.meeting_id)
        if meeting is None or meeting.start_date is None:
            return fallback
        return meeting.start_date

    async def get_existing_tdoc_ids(self, working_groups: Iterable[WorkingGroup] | None = None) -> set[str]:
        """Get set of existing TDoc IDs, optionally filtered by working group.

+1 −1
Original line number Diff line number Diff line
@@ -161,7 +161,7 @@ class TDocQueryConfig(BaseModel):
    agenda_pattern: list[str] | None = Field(None, description="Glob pattern(s) for agenda_item_text field; multiple values are OR'd")
    agenda_pattern_exclude: list[str] | None = Field(None, description="Glob pattern(s) to exclude agenda_item_text field; multiple values are OR'd")
    limit: int | None = Field(None, ge=1, description="Maximum results")
    order: SortOrder = Field(SortOrder.DESC, description="Sort order applied to date_retrieved")
    order: SortOrder = Field(SortOrder.ASC, description="Sort order (asc|desc) applied to meeting start_date, then tdoc_id")

    @field_validator("tdoc_ids", mode="before")
    @classmethod