diff options
| author | xmo-odoo <xmo@odoo.com> | 2017-10-02 10:55:15 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-10-02 10:55:15 +0200 |
| commit | 82ef2f1b8e164362417a842dd9c28145fef6e544 (patch) | |
| tree | 53cc9c37df6e872c63030f21a5db09e3f29a11cd /addons | |
| parent | 77d49999400882ef70415083aed9ef6f626efc9b (diff) | |
[FIX] calendar: validation error when moving some events back
Observed via google sync, for some events being moved around during
sync the stop_datetime ends up being before the start_datetime failing
the sync. Not (explicitly) reading the computed fields from the old
record properly recomputes them during copy.
Underlying issue linked to (stored) computed fields when multiple
fields are computed by the same method *and* the creation provides a
subset of these fields explicitly: depending on the order in
which *recompute* iterates the fields, it's possible that some of the
fields provided explicitly get extracted (from the cache) before
fields not-provided trigger a recomputation (and overwrite) of
computed fields.
In this case `recompute` iterates [start_datetime, start_date,
stop_date, stop_datetime], if `start_datetime` and `stop_datetime` are
provided explicitly to create, first recompute will check for
`start_datetime`, find it in the cache and extract it, then it checks
for `start_date`, does not find it in the cache, calls
`_compute_dates` which writes all four fields, then it extracts the
recomputed `start_datetime`, creating an incoherence: `start_datetime`
is the one from the old event while `stop_datetime` is the one from
the update/computation. This may lead to invisible corruption if the
event is moved forwards (e.g. creates a multi-day event) and triggers
a validation error if the event is moved backwards (stop_datetime is
now before start_datetime).
ping @rco-odoo multi-field computes may need some special handling
with respect to invalidations & sequencing & the like (e.g. check
their caching as a unit or something).
OPW-771886
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/calendar/models/calendar.py | 2 | ||||
| -rw-r--r-- | addons/calendar/tests/test_calendar.py | 44 |
2 files changed, 44 insertions, 2 deletions
diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 71125e76253..c32c332d5bb 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -1249,8 +1249,6 @@ class Meeting(models.Model): meeting_origin = self.browse(real_id) data = self.read(['allday', 'start', 'stop', 'rrule', 'duration'])[0] - data['start_date' if data['allday'] else 'start_datetime'] = data['start'] - data['stop_date' if data['allday'] else 'stop_datetime'] = data['stop'] if data.get('rrule'): data.update( values, diff --git a/addons/calendar/tests/test_calendar.py b/addons/calendar/tests/test_calendar.py index 3604352ace5..6a2a035865e 100644 --- a/addons/calendar/tests/test_calendar.py +++ b/addons/calendar/tests/test_calendar.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +import datetime from odoo import fields from odoo.tests.common import TransactionCase @@ -97,3 +98,46 @@ class TestCalendar(TransactionCase): self.assertEqual(calendar_event_sprint_review.month_by, 'day', 'rrule_type should be mothly') self.assertEqual(calendar_event_sprint_review.byday, '1', 'rrule_type should be mothly') self.assertEqual(calendar_event_sprint_review.week_list, 'MO', 'rrule_type should be mothly') + + def test_validation_error(self): + """ + Ideally this should build the base event in such a way that calling + write() triggers detach_recurring_event, but I've no idea how that + actually works so just calling it directly for now + """ + m = self.CalendarEvent.create({ + 'name': "wheee", + 'start': '2017-07-12 14:30:00', + 'allday': False, + 'rrule': u'FREQ=WEEKLY;BYDAY=WE;INTERVAL=1;COUNT=100', + 'duration': 0.5, + 'stop': '2017-07-12 15:00:00', + }) + + values = { + 'allday': False, + 'name': u'wheee', + 'attendee_ids': [ + (0, 0, {'state': u'needsAction', 'partner_id': 8, 'email': u'bob@example.com'}), + (0, 0, {'state': u'needsAction', 'partner_id': 10, 'email': u'ed@example.com'}), + ], + 'recurrency': True, + 'privacy': u'public', + 'stop': '2017-07-10 16:00:00', + 'alarm_ids': [(6, 0, [])], + 'start': '2017-07-10 15:30:00', + 'location': u"XXX", + 'duration': 0.5, + 'partner_ids': [(4, 10), (4, 8)], + 'description': u"A thing" + } + + records = m.detach_recurring_event(values) + self.assertEqual( + (m.start_datetime, m.stop_datetime), + (u'2017-07-12 14:30:00', u'2017-07-12 15:00:00'), + ) + self.assertEquals( + (records.start_datetime, records.stop_datetime), + (u'2017-07-10 15:30:00', u'2017-07-10 16:00:00'), + ) |
