From b844f3bfd5e830b076e3017125993c3bfee2825f Mon Sep 17 00:00:00 2001 From: Giang Manh Date: Wed, 18 Oct 2017 20:52:04 +0900 Subject: [PATCH] [FIX] calendar: sorting error (P3) When showing a list in Calendar, it is always sorted at least by id. If the recordset mixes real and virtual (recurrent) events, this will blow up as sort() will try to compare the int-typed real event ids and the string-typed virtual event ids. Generate a type-compatible id key for both real and virtual events in order to properly sort. Closes #20278 --- addons/calendar/models/calendar.py | 27 +++++++++++++++++++++++++-- doc/cla/individual/manhg.md | 11 +++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 doc/cla/individual/manhg.md diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 3c7e24c9187..fc296be5abc 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -58,6 +58,23 @@ def get_real_ids(ids): def real_id2calendar_id(record_id, date): return '%s-%s' % (record_id, date.strftime(VIRTUALID_DATETIME_FORMAT)) +def any_id2key(record_id): + """ Creates a (real_id: int, thing: str) pair which allows ordering mixed + collections of real and virtual events. + + The first item of the pair is the event's real id, the second one is + either an empty string (for real events) or the datestring (for virtual + ones) + + :param record_id: + :type record_id: int | str + :rtype: (int, str) + """ + if isinstance(record_id, pycompat.integer_types): + return record_id, u'' + + (real_id, virtual_id) = record_id.split('-') + return int(real_id), virtual_id def is_calendar_id(record_id): return len(str(record_id).split('-')) != 1 @@ -1124,9 +1141,15 @@ class Meeting(models.Model): for key in (order or self._order).split(',') )) def key(record): - return [ - tools.Reverse(record[name]) if desc else record[name] + # first extract the values for each key column (ids need special treatment) + vals_spec = ( + (any_id2key(record[name]) if name == 'id' else record[name], desc) for name, desc in sort_spec + ) + # then Reverse if the value matches a "desc" column + return [ + (tools.Reverse(v) if desc else v) + for v, desc in vals_spec ] return [r['id'] for r in sorted(result_data, key=key)] diff --git a/doc/cla/individual/manhg.md b/doc/cla/individual/manhg.md new file mode 100644 index 00000000000..d15e6e91fe9 --- /dev/null +++ b/doc/cla/individual/manhg.md @@ -0,0 +1,11 @@ +Japan, 2017-10-19 + +I hereby agree to the terms of the Odoo Individual Contributor License +Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this +declaration. + +Signed, + +Giang Manh manhg@users.noreply.github.com https://github.com/manhg \ No newline at end of file