781 lines
33 KiB
Python
781 lines
33 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from datetime import datetime
|
|
from dateutil.relativedelta import relativedelta
|
|
from unittest.mock import patch
|
|
|
|
from odoo.addons.google_calendar.utils.google_calendar import GoogleCalendarService
|
|
from odoo.addons.google_account.models.google_service import GoogleService
|
|
from odoo.addons.google_calendar.models.res_users import User
|
|
from odoo.addons.google_calendar.tests.test_sync_common import TestSyncGoogle, patch_api
|
|
from odoo.tests.common import users, warmup
|
|
from odoo.tests import tagged
|
|
from odoo import tools
|
|
|
|
@tagged('odoo2google')
|
|
@patch.object(User, '_get_google_calendar_token', lambda user: 'dummy-token')
|
|
class TestSyncOdoo2Google(TestSyncGoogle):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.env.user.partner_id.tz = "Europe/Brussels"
|
|
self.google_service = GoogleCalendarService(self.env['google.service'])
|
|
# Make sure this test will work for the next 30 years
|
|
self.env['ir.config_parameter'].set_param('google_calendar.sync.range_days', 10000)
|
|
|
|
@patch_api
|
|
def test_event_creation(self):
|
|
partner = self.env['res.partner'].create({'name': 'Jean-Luc', 'email': 'jean-luc@opoo.com'})
|
|
alarm = self.env['calendar.alarm'].create({
|
|
'name': 'Notif',
|
|
'alarm_type': 'notification',
|
|
'interval': 'minutes',
|
|
'duration': 18,
|
|
})
|
|
description = '<script>alert("boom")</script><p style="white-space: pre"><h1>HELLO</h1></p><ul><li>item 1</li><li>item 2</li></ul>'
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15, 8, 0),
|
|
'stop': datetime(2020, 1, 15, 18, 0),
|
|
'partner_ids': [(4, partner.id)],
|
|
'alarm_ids': [(4, alarm.id)],
|
|
'privacy': 'private',
|
|
'need_sync': False,
|
|
'description': description,
|
|
})
|
|
event._sync_odoo2google(self.google_service)
|
|
self.assertGoogleEventInserted({
|
|
'id': False,
|
|
'start': {'dateTime': '2020-01-15T08:00:00+00:00'},
|
|
'end': {'dateTime': '2020-01-15T18:00:00+00:00'},
|
|
'summary': 'Event',
|
|
'description': tools.html_sanitize(description),
|
|
'location': '',
|
|
'visibility': 'private',
|
|
'guestsCanModify': True,
|
|
'reminders': {'useDefault': False, 'overrides': [{'method': 'popup', 'minutes': alarm.duration_minutes}]},
|
|
'organizer': {'email': 'odoobot@example.com', 'self': True},
|
|
'attendees': [{'email': 'jean-luc@opoo.com', 'responseStatus': 'needsAction'}],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: event.id}}
|
|
})
|
|
|
|
@patch_api
|
|
@users('__system__')
|
|
@warmup
|
|
def test_event_creation_perf(self):
|
|
EVENT_COUNT = 100
|
|
partners = self.env['res.partner'].create([
|
|
{'name': 'Jean-Luc %s' % (i), 'email': 'jean-luc-%s@opoo.com' % (i)} for i in range(EVENT_COUNT)])
|
|
alarm = self.env['calendar.alarm'].create({
|
|
'name': 'Notif',
|
|
'alarm_type': 'notification',
|
|
'interval': 'minutes',
|
|
'duration': 18,
|
|
})
|
|
partner_model = self.env.ref('base.model_res_partner')
|
|
partner = self.env['res.partner'].search([], limit=1)
|
|
with self.assertQueryCount(__system__=615):
|
|
events = self.env['calendar.event'].create([{
|
|
'name': "Event %s" % (i),
|
|
'start': datetime(2020, 1, 15, 8, 0),
|
|
'stop': datetime(2020, 1, 15, 18, 0),
|
|
'partner_ids': [(4, partners[i].id), (4, self.env.user.partner_id.id)],
|
|
'alarm_ids': [(4, alarm.id)],
|
|
'privacy': 'private',
|
|
'need_sync': False,
|
|
'res_model_id': partner_model.id,
|
|
'res_id': partner.id,
|
|
} for i in range(EVENT_COUNT)])
|
|
|
|
events._sync_odoo2google(self.google_service)
|
|
|
|
with self.assertQueryCount(__system__=27):
|
|
events.unlink()
|
|
|
|
|
|
@patch_api
|
|
@users('__system__')
|
|
@warmup
|
|
def test_recurring_event_creation_perf(self):
|
|
partner = self.env['res.partner'].create({'name': 'Jean-Luc', 'email': 'jean-luc@opoo.com'})
|
|
alarm = self.env['calendar.alarm'].create({
|
|
'name': 'Notif',
|
|
'alarm_type': 'notification',
|
|
'interval': 'minutes',
|
|
'duration': 18,
|
|
})
|
|
partner_model = self.env.ref('base.model_res_partner')
|
|
partner = self.env['res.partner'].search([], limit=1)
|
|
with self.assertQueryCount(__system__=86):
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15, 8, 0),
|
|
'stop': datetime(2020, 1, 15, 18, 0),
|
|
'partner_ids': [(4, partner.id)],
|
|
'alarm_ids': [(4, alarm.id)],
|
|
'privacy': 'private',
|
|
'need_sync': False,
|
|
'interval': 1,
|
|
'recurrency': True,
|
|
'rrule_type': 'daily',
|
|
'end_type': 'forever',
|
|
'res_model_id': partner_model.id,
|
|
'res_id': partner.id,
|
|
})
|
|
|
|
with self.assertQueryCount(__system__=37):
|
|
event.unlink()
|
|
|
|
def test_event_without_user(self):
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15, 8, 0),
|
|
'stop': datetime(2020, 1, 15, 18, 0),
|
|
'user_id': False,
|
|
'privacy': 'private',
|
|
'need_sync': False,
|
|
})
|
|
values = event._google_values()
|
|
self.assertFalse('%s_owner_id' % self.env.cr.dbname in values.get('extendedProperties', {}).get('shared', {}))
|
|
|
|
@patch_api
|
|
def test_event_without_attendee_state(self):
|
|
partner_1 = self.env['res.partner'].create({'name': 'Jean-Luc', 'email': 'jean-luc@opoo.com'})
|
|
partner_2 = self.env['res.partner'].create({'name': 'Phineas', 'email': 'phineas@opoo.com'})
|
|
partner_3 = self.env['res.partner'].create({'name': 'Ferb'})
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15, 8, 0),
|
|
'stop': datetime(2020, 1, 15, 18, 0),
|
|
'partner_ids': [(4, partner_1.id), (4, partner_2.id), (4, partner_3.id)],
|
|
'privacy': 'private',
|
|
'need_sync': False,
|
|
})
|
|
attendee_2 = event.attendee_ids.filtered(lambda a: a.partner_id.id == partner_2.id)
|
|
attendee_2.write({
|
|
'state': False,
|
|
})
|
|
event._sync_odoo2google(self.google_service)
|
|
self.assertGoogleEventInserted({
|
|
'id': False,
|
|
'start': {'dateTime': '2020-01-15T08:00:00+00:00'},
|
|
'end': {'dateTime': '2020-01-15T18:00:00+00:00'},
|
|
'summary': 'Event',
|
|
'description': '',
|
|
'location': '',
|
|
'visibility': 'private',
|
|
'guestsCanModify': True,
|
|
'reminders': {'useDefault': False, 'overrides': []},
|
|
'organizer': {'email': 'odoobot@example.com', 'self': True},
|
|
'attendees': [{'email': 'jean-luc@opoo.com', 'responseStatus': 'needsAction'},
|
|
{'email': 'phineas@opoo.com', 'responseStatus': 'needsAction'}],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: event.id}}
|
|
})
|
|
|
|
@patch_api
|
|
def test_event_allday_creation(self):
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'allday': True,
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'need_sync': False,
|
|
})
|
|
event._sync_odoo2google(self.google_service)
|
|
self.assertGoogleEventInserted({
|
|
'id': False,
|
|
'start': {'date': '2020-01-15'},
|
|
'end': {'date': '2020-01-16'},
|
|
'summary': 'Event',
|
|
'description': '',
|
|
'location': '',
|
|
'visibility': 'public',
|
|
'guestsCanModify': True,
|
|
'reminders': {'overrides': [], 'useDefault': False},
|
|
'organizer': {'email': 'odoobot@example.com', 'self': True},
|
|
'attendees': [{'email': 'odoobot@example.com', 'responseStatus': 'accepted'}],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: event.id}}
|
|
})
|
|
|
|
@patch_api
|
|
def test_inactive_event(self):
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'active': False,
|
|
'need_sync': False,
|
|
})
|
|
event._sync_odoo2google(self.google_service)
|
|
self.assertGoogleEventNotInserted()
|
|
self.assertGoogleEventNotDeleted()
|
|
|
|
@patch_api
|
|
def test_synced_inactive_event(self):
|
|
google_id = 'aaaaaaaaa'
|
|
# writing on synced event will put it in a need_sync state.
|
|
# Delete api will not be called but the state of the event will be set as 'cancelled'
|
|
event = self.env['calendar.event'].create({
|
|
'google_id': google_id,
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'active': False,
|
|
'need_sync': True,
|
|
})
|
|
event._sync_odoo2google(self.google_service)
|
|
self.assertGoogleEventDeleted(google_id)
|
|
|
|
@patch_api
|
|
def test_recurrence(self):
|
|
google_id = 'aaaaaaaaa'
|
|
event = self.env['calendar.event'].create({
|
|
'google_id': google_id,
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'allday': True,
|
|
'need_sync': False,
|
|
})
|
|
recurrence = self.env['calendar.recurrence'].create({
|
|
'rrule': 'FREQ=WEEKLY;COUNT=2;BYDAY=WE',
|
|
'calendar_event_ids': [(4, event.id)],
|
|
'need_sync': False,
|
|
})
|
|
recurrence._sync_odoo2google(self.google_service)
|
|
self.assertGoogleEventInserted({
|
|
'id': False,
|
|
'start': {'date': '2020-01-15'},
|
|
'end': {'date': '2020-01-16'},
|
|
'summary': 'Event',
|
|
'description': '',
|
|
'location': '',
|
|
'visibility': 'public',
|
|
'guestsCanModify': True,
|
|
'reminders': {'overrides': [], 'useDefault': False},
|
|
'organizer': {'email': 'odoobot@example.com', 'self': True},
|
|
'attendees': [{'email': 'odoobot@example.com', 'responseStatus': 'accepted'}],
|
|
'recurrence': ['RRULE:FREQ=WEEKLY;COUNT=2;BYDAY=WE'],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: recurrence.id}}
|
|
})
|
|
|
|
@patch_api
|
|
def test_event_added_to_recurrence(self):
|
|
google_id = 'aaaaaaaaa'
|
|
event = self.env['calendar.event'].create({
|
|
'google_id': google_id,
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'allday': True,
|
|
'need_sync': False,
|
|
})
|
|
event.write({
|
|
'recurrency': True,
|
|
'rrule': 'FREQ=WEEKLY;COUNT=2;BYDAY=WE',
|
|
})
|
|
to_delete = self.env['calendar.event'].with_context(active_test=False).search([('google_id', '=', google_id)])
|
|
self.assertTrue(to_delete)
|
|
self.assertFalse(to_delete.active)
|
|
self.assertFalse(event.google_id, "The google id will be set after the API call")
|
|
self.assertGoogleEventInserted({
|
|
'id': False,
|
|
'start': {'date': '2020-01-15'},
|
|
'end': {'date': '2020-01-16'},
|
|
'summary': 'Event',
|
|
'description': '',
|
|
'location': '',
|
|
'visibility': 'public',
|
|
'guestsCanModify': True,
|
|
'reminders': {'overrides': [], 'useDefault': False},
|
|
'organizer': {'email': 'odoobot@example.com', 'self': True},
|
|
'attendees': [{'email': 'odoobot@example.com', 'responseStatus': 'accepted'}],
|
|
'recurrence': ['RRULE:FREQ=WEEKLY;COUNT=2;BYDAY=WE'],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: event.recurrence_id.id}}
|
|
}, timeout=3)
|
|
|
|
self.assertGoogleEventDeleted(google_id)
|
|
|
|
@patch_api
|
|
def test_following_event_updated(self):
|
|
google_id = 'aaaaaaaaa'
|
|
event_1 = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'allday': True,
|
|
'need_sync': False,
|
|
})
|
|
event_2 = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 22),
|
|
'stop': datetime(2020, 1, 22),
|
|
'allday': True,
|
|
'need_sync': False,
|
|
})
|
|
self.env['calendar.recurrence'].create({
|
|
'google_id': google_id,
|
|
'rrule': 'FREQ=WEEKLY;COUNT=2;BYDAY=WE',
|
|
'calendar_event_ids': [(4, event_1.id), (4, event_2.id)],
|
|
'need_sync': False,
|
|
})
|
|
event = event_2
|
|
|
|
# Update only some events in the recurrence
|
|
event.write({
|
|
'name': 'New name',
|
|
'recurrence_update': 'future_events',
|
|
})
|
|
self.assertGoogleEventInserted({
|
|
'id': False,
|
|
'start': {'date': str(event.start_date)},
|
|
'end': {'date': str(event.stop_date + relativedelta(days=1))},
|
|
'summary': 'New name',
|
|
'description': '',
|
|
'location': '',
|
|
'guestsCanModify': True,
|
|
'organizer': {'email': 'odoobot@example.com', 'self': True},
|
|
'attendees': [{'email': 'odoobot@example.com', 'responseStatus': 'accepted'}],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: event.recurrence_id.id}},
|
|
'reminders': {'overrides': [], 'useDefault': False},
|
|
'visibility': 'public',
|
|
'recurrence': ['RRULE:FREQ=WEEKLY;WKST=SU;COUNT=1;BYDAY=WE']
|
|
}, timeout=3)
|
|
|
|
@patch_api
|
|
def test_stop_synchronization(self):
|
|
self.env.user.stop_google_synchronization()
|
|
self.assertTrue(self.env.user.google_synchronization_stopped, "The google synchronization flag should be switched on")
|
|
self.assertFalse(self.env.user._sync_google_calendar(self.google_service), "The google synchronization should be stopped")
|
|
|
|
# If synchronization stopped, creating a new event should not call _google_insert.
|
|
self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15, 8, 0),
|
|
'stop': datetime(2020, 1, 15, 18, 0),
|
|
'privacy': 'private',
|
|
})
|
|
self.assertGoogleEventNotInserted()
|
|
|
|
@patch_api
|
|
def test_restart_synchronization(self):
|
|
# Test new event created after stopping synchronization are correctly patched when restarting sync.
|
|
google_id = 'aaaaaaaaa'
|
|
partner = self.env['res.partner'].create({'name': 'Jean-Luc', 'email': 'jean-luc@opoo.com'})
|
|
user = self.env['res.users'].create({
|
|
'name': 'Test user Calendar',
|
|
'login': 'jean-luc@opoo.com',
|
|
'partner_id': partner.id,
|
|
})
|
|
user.stop_google_synchronization()
|
|
event = self.env['calendar.event'].with_user(user).create({
|
|
'google_id': google_id,
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15, 8, 0),
|
|
'stop': datetime(2020, 1, 15, 18, 0),
|
|
'partner_ids': [(4, partner.id)],
|
|
})
|
|
|
|
user.with_user(user).restart_google_synchronization()
|
|
self.assertGoogleEventPatched(event.google_id, {
|
|
'id': event.google_id,
|
|
'start': {'dateTime': '2020-01-15T08:00:00+00:00'},
|
|
'end': {'dateTime': '2020-01-15T18:00:00+00:00'},
|
|
'summary': 'Event',
|
|
'description': '',
|
|
'location': '',
|
|
'visibility': 'public',
|
|
'guestsCanModify': True,
|
|
'reminders': {'overrides': [], 'useDefault': False},
|
|
'organizer': {'email': 'jean-luc@opoo.com', 'self': True},
|
|
'attendees': [{'email': 'jean-luc@opoo.com', 'responseStatus': 'accepted'}],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: event.id}}
|
|
}, timeout=3)
|
|
|
|
@patch_api
|
|
def test_all_event_updated(self):
|
|
google_id = 'aaaaaaaaa'
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'allday': True,
|
|
'need_sync': False,
|
|
})
|
|
recurrence = self.env['calendar.recurrence'].create({
|
|
'google_id': google_id,
|
|
'rrule': 'FREQ=WEEKLY;COUNT=2;BYDAY=WE',
|
|
'base_event_id': event.id,
|
|
'need_sync': False,
|
|
})
|
|
recurrence._apply_recurrence()
|
|
event.write({
|
|
'name': 'New name',
|
|
'recurrence_update': 'all_events',
|
|
})
|
|
new_recurrence = self.env['calendar.recurrence'].search([('id', '>', recurrence.id)])
|
|
self.assertGoogleEventInserted({
|
|
'id': False,
|
|
'start': {'date': str(event.start_date)},
|
|
'end': {'date': str(event.stop_date + relativedelta(days=1))},
|
|
'summary': 'New name',
|
|
'description': '',
|
|
'location': '',
|
|
'guestsCanModify': True,
|
|
'organizer': {'email': 'odoobot@example.com', 'self': True},
|
|
'attendees': [{'email': 'odoobot@example.com', 'responseStatus': 'accepted'}],
|
|
'recurrence': ['RRULE:FREQ=WEEKLY;WKST=SU;COUNT=2;BYDAY=WE'],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: new_recurrence.id}},
|
|
'reminders': {'overrides': [], 'useDefault': False},
|
|
'visibility': 'public',
|
|
}, timeout=3)
|
|
|
|
@patch_api
|
|
def test_event_need_sync(self):
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'allday': True,
|
|
'recurrence_id': False,
|
|
'recurrency': True,
|
|
})
|
|
self.assertFalse(event.need_sync,
|
|
"Event created with True recurrency should not be synched to avoid "
|
|
"duplicate event on google")
|
|
|
|
recurrence = self.env['calendar.recurrence'].create({
|
|
'google_id': False,
|
|
'rrule': 'FREQ=WEEKLY;COUNT=2;BYDAY=WE',
|
|
'base_event_id': event.id,
|
|
'need_sync': False,
|
|
})
|
|
event_2 = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'allday': True,
|
|
'recurrence_id': recurrence.id,
|
|
})
|
|
self.assertFalse(event_2.need_sync,
|
|
"Event created with recurrence_id should not be synched to avoid "
|
|
"duplicate event on google")
|
|
|
|
self.assertGoogleEventNotInserted()
|
|
self.assertGoogleEventNotDeleted()
|
|
|
|
|
|
@patch_api
|
|
def test_event_until_utc(self):
|
|
""" UNTIl rrule value must be in UTC: ending with a 'Z """
|
|
google_id = 'aaaaaaaaa'
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'allday': True,
|
|
'need_sync': False,
|
|
})
|
|
recurrence = self.env['calendar.recurrence'].create({
|
|
'google_id': google_id,
|
|
'rrule': 'FREQ=DAILY;UNTIL=20200117T235959',
|
|
'base_event_id': event.id,
|
|
'need_sync': False,
|
|
})
|
|
recurrence._apply_recurrence()
|
|
self.assertEqual(recurrence._google_values()['recurrence'][0], 'RRULE:FREQ=DAILY;UNTIL=20200117T235959Z',
|
|
"The rrule sent to google should be in UTC: end with Z")
|
|
# Add it even if it is not the end of the string
|
|
recurrence.write({'rrule': 'FREQ=DAILY;UNTIL=20200118T235959;INTERVAL=3'})
|
|
recurrence._apply_recurrence()
|
|
self.assertEqual(recurrence._google_values()['recurrence'][0],
|
|
'RRULE:FREQ=DAILY;UNTIL=20200118T235959Z;INTERVAL=3',
|
|
"The rrule sent to google should be in UTC: end with Z and preserve the following parameters")
|
|
# Don't add two Z at the end of the UNTIL value
|
|
recurrence.write({'rrule': 'FREQ=DAILY;UNTIL=20200119T235959Z'})
|
|
recurrence._apply_recurrence()
|
|
self.assertEqual(recurrence._google_values()['recurrence'][0], 'RRULE:FREQ=DAILY;UNTIL=20200119T235959Z',
|
|
"The rrule sent to google should be in UTC: end with one Z")
|
|
|
|
@patch_api
|
|
def test_write_unsynced_field(self):
|
|
google_id = 'aaaaaaaaa'
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2021, 3, 10),
|
|
'stop': datetime(2021, 3, 10),
|
|
'allday': True,
|
|
'need_sync': False,
|
|
})
|
|
recurrence = self.env['calendar.recurrence'].create({
|
|
'google_id': google_id,
|
|
'rrule': 'FREQ=WEEKLY;COUNT=2;BYDAY=WE',
|
|
'base_event_id': event.id,
|
|
'need_sync': False,
|
|
})
|
|
recurrence._apply_recurrence()
|
|
event.write({
|
|
'start': datetime(2021, 3, 11),
|
|
'stop': datetime(2021, 3, 11),
|
|
'need_sync': False,
|
|
})
|
|
event_type = self.env['calendar.event.type'].create({'name': 'type'})
|
|
event.write({
|
|
'recurrence_update': 'all_events',
|
|
'categ_ids': [(4, event_type.id)]
|
|
})
|
|
self.assertTrue(all(e.categ_ids == event_type for e in recurrence.calendar_event_ids))
|
|
self.assertGoogleAPINotCalled()
|
|
|
|
@patch_api
|
|
def test_attendee_state(self):
|
|
""" Sync attendee state immediately """
|
|
partner = self.env['res.partner'].create({'name': 'Jean-Luc', 'email': 'jean-luc@opoo.com'})
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event with attendees",
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'allday': True,
|
|
'need_sync': False,
|
|
'partner_ids': [(4, partner.id)],
|
|
'google_id': 'aaaaaaaaa',
|
|
})
|
|
self.assertEqual(event.attendee_ids.state, 'needsAction',
|
|
"The attendee state should be 'needsAction")
|
|
|
|
event.attendee_ids.do_decline()
|
|
self.assertGoogleEventPatched(event.google_id, {
|
|
'id': event.google_id,
|
|
'start': {'date': str(event.start_date)},
|
|
'end': {'date': str(event.stop_date + relativedelta(days=1))},
|
|
'summary': 'Event with attendees',
|
|
'description': '',
|
|
'location': '',
|
|
'guestsCanModify': True,
|
|
'organizer': {'email': 'odoobot@example.com', 'self': True},
|
|
'attendees': [{'email': 'jean-luc@opoo.com', 'responseStatus': 'declined'}],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: event.id}},
|
|
'reminders': {'overrides': [], 'useDefault': False},
|
|
'visibility': 'public',
|
|
})
|
|
|
|
|
|
@patch_api
|
|
def test_all_event_with_tz_updated(self):
|
|
google_id = 'aaaaaaaaa'
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15, 8, 0),
|
|
'stop': datetime(2020, 1, 15, 9, 0),
|
|
'need_sync': False,
|
|
})
|
|
recurrence = self.env['calendar.recurrence'].create({
|
|
'google_id': google_id,
|
|
'rrule': 'FREQ=WEEKLY;COUNT=2;BYDAY=WE',
|
|
'base_event_id': event.id,
|
|
'need_sync': False,
|
|
})
|
|
recurrence._apply_recurrence()
|
|
event.write({
|
|
'name': 'New name',
|
|
'recurrence_update': 'all_events',
|
|
})
|
|
new_recurrence = self.env['calendar.recurrence'].search([('id', '>', recurrence.id)])
|
|
self.assertGoogleEventInserted({
|
|
'id': False,
|
|
'start': {'dateTime': "2020-01-15T08:00:00+00:00", 'timeZone': 'Europe/Brussels'},
|
|
'end': {'dateTime': "2020-01-15T09:00:00+00:00", 'timeZone': 'Europe/Brussels'},
|
|
'summary': 'New name',
|
|
'description': '',
|
|
'location': '',
|
|
'guestsCanModify': True,
|
|
'organizer': {'email': 'odoobot@example.com', 'self': True},
|
|
'attendees': [{'email': 'odoobot@example.com', 'responseStatus': 'accepted'}],
|
|
'recurrence': ['RRULE:FREQ=WEEKLY;WKST=SU;COUNT=2;BYDAY=WE'],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: new_recurrence.id}},
|
|
'reminders': {'overrides': [], 'useDefault': False},
|
|
'visibility': 'public',
|
|
}, timeout=3)
|
|
|
|
@patch.object(GoogleService, '_do_request')
|
|
def test_send_update_do_request(self, mock_do_request):
|
|
self.env.cr.postcommit.clear()
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'allday': True,
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'need_sync': False,
|
|
})
|
|
|
|
event.with_context(send_updates=True)._sync_odoo2google(self.google_service)
|
|
self.call_post_commit_hooks()
|
|
self.assertGoogleEventSendUpdates('all')
|
|
|
|
@patch.object(GoogleService, '_do_request')
|
|
def test_not_send_update_do_request(self, mock_do_request):
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'allday': True,
|
|
'start': datetime(2020, 1, 15),
|
|
'stop': datetime(2020, 1, 15),
|
|
'need_sync': False,
|
|
})
|
|
|
|
event.with_context(send_updates=False)._sync_odoo2google(self.google_service)
|
|
self.call_post_commit_hooks()
|
|
self.assertGoogleEventSendUpdates('none')
|
|
|
|
@patch_api
|
|
def test_recurrence_delete_single_events(self):
|
|
"""
|
|
Creates a recurrence with two events, deletes the events and assert that the recurrence was updated.
|
|
"""
|
|
# Setup recurrence with two recurrences (event_1 as the recurrence base_event).
|
|
google_id = 'aaaaaaaaa'
|
|
event_1 = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2023, 6, 15, 10, 0),
|
|
'stop': datetime(2023, 6, 15, 10, 0),
|
|
'need_sync': False,
|
|
})
|
|
event_2 = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2023, 6, 22, 10, 0),
|
|
'stop': datetime(2023, 6, 22, 10, 0),
|
|
'need_sync': False,
|
|
})
|
|
recurrence = self.env['calendar.recurrence'].create({
|
|
'google_id': google_id,
|
|
'rrule': 'FREQ=WEEKLY;COUNT=2;BYDAY=TH',
|
|
'base_event_id': event_1.id,
|
|
'calendar_event_ids': [(4, event_1.id), (4, event_2.id)],
|
|
'need_sync': False,
|
|
})
|
|
# Delete base_event and assert that patch was called.
|
|
event_1.action_mass_archive('self_only')
|
|
self.assertGoogleEventPatched(event_1.google_id, {
|
|
'id': event_1.google_id,
|
|
'start': {'dateTime': '2023-06-15T10:00:00+00:00'},
|
|
'end': {'dateTime': '2023-06-15T10:00:00+00:00'},
|
|
'summary': 'Event',
|
|
'description': '',
|
|
'location': '',
|
|
'guestsCanModify': True,
|
|
'organizer': {'email': 'odoobot@example.com', 'self': True},
|
|
'attendees': [{'email': 'odoobot@example.com', 'responseStatus': 'accepted'}],
|
|
'extendedProperties': {'shared': {'%s_odoo_id' % self.env.cr.dbname: event_1.id}},
|
|
'reminders': {'overrides': [], 'useDefault': False},
|
|
'visibility': 'public',
|
|
'status': 'cancelled'
|
|
}, timeout=3)
|
|
# Assert that deleted event is not active anymore and the recurrence updated its calendar_event_ids.
|
|
self.assertFalse(event_1.active)
|
|
self.assertEqual(recurrence.base_event_id.id, event_2.id)
|
|
self.assertEqual(recurrence.calendar_event_ids.ids, [event_2.id])
|
|
# Delete last event and assert that the recurrence and event were archived after the last event deletion.
|
|
event_2.action_mass_archive('self_only')
|
|
self.assertFalse(event_2.active)
|
|
self.assertFalse(recurrence.active)
|
|
|
|
@patch_api
|
|
def test_create_event_with_sync_config_paused(self):
|
|
"""
|
|
Creates an event with the synchronization paused, its field 'need_sync'
|
|
must be True for later synchronizing it with Google Calendar.
|
|
"""
|
|
# Set synchronization as active and unpause the synchronization.
|
|
self.env.user.google_synchronization_stopped = False
|
|
self.env.user.sudo().pause_google_synchronization()
|
|
|
|
# Create record and call synchronization method.
|
|
record = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2023, 6, 29, 8, 0),
|
|
'stop': datetime(2023, 6, 29, 18, 0),
|
|
'need_sync': True
|
|
})
|
|
record._sync_odoo2google(self.google_service)
|
|
|
|
# Assert that synchronization is paused, insert wasn't called and record is waiting to be synced.
|
|
self.assertFalse(self.env.user.google_synchronization_stopped)
|
|
self.assertEqual(self.env.user._get_google_sync_status(), "sync_paused")
|
|
self.assertTrue(record.need_sync, "Sync variable must be true for updating event when sync re-activates")
|
|
self.assertGoogleEventNotInserted()
|
|
|
|
@patch_api
|
|
def test_update_synced_event_with_sync_config_paused(self):
|
|
"""
|
|
Updates a synced event with synchronization paused, event must be modified and have its
|
|
field 'need_sync' as True for later synchronizing it with Google Calendar.
|
|
"""
|
|
# Set synchronization as active and unpause it.
|
|
self.env.user.google_synchronization_stopped = False
|
|
self.env.user.sudo().unpause_google_synchronization()
|
|
|
|
# Setup synced record in Calendar.
|
|
record = self.env['calendar.event'].create({
|
|
'google_id': 'aaaaaaaaa',
|
|
'name': "Event",
|
|
'start': datetime(2023, 6, 29, 8, 0),
|
|
'stop': datetime(2023, 6, 29, 18, 0),
|
|
'need_sync': False
|
|
})
|
|
|
|
# Pause synchronization and update synced event. It will only update it locally.
|
|
self.env.user.sudo().pause_google_synchronization()
|
|
record.write({'name': "Updated Event"})
|
|
record._sync_odoo2google(self.google_service)
|
|
|
|
# Assert that synchronization is paused, patch wasn't called and record is waiting to be synced.
|
|
self.assertFalse(self.env.user.google_synchronization_stopped)
|
|
self.assertEqual(self.env.user._get_google_sync_status(), "sync_paused")
|
|
self.assertEqual(record.name, "Updated Event", "Assert that event name was updated in Odoo Calendar")
|
|
self.assertTrue(record.need_sync, "Sync variable must be true for updating event when sync re-activates")
|
|
self.assertGoogleEventNotPatched()
|
|
|
|
@patch_api
|
|
def test_delete_synced_event_with_sync_config_paused(self):
|
|
"""
|
|
Deletes a synced event with synchronization paused, event must be archived in Odoo and
|
|
have its field 'need_sync' as True for later synchronizing it with Google Calendar.
|
|
"""
|
|
# Set synchronization as active and then pause synchronization.
|
|
self.env.user.google_synchronization_stopped = False
|
|
self.env.user.sudo().unpause_google_synchronization()
|
|
|
|
# Setup synced record in Calendar.
|
|
record = self.env['calendar.event'].create({
|
|
'google_id': 'aaaaaaaaa',
|
|
'name': "Event",
|
|
'start': datetime(2023, 6, 29, 8, 0),
|
|
'stop': datetime(2023, 6, 29, 18, 0),
|
|
'need_sync': False
|
|
})
|
|
|
|
# Pause synchronization and delete synced event.
|
|
self.env.user.sudo().pause_google_synchronization()
|
|
record.unlink()
|
|
|
|
# Assert that synchronization is paused, delete wasn't called and record was archived in Odoo.
|
|
self.assertFalse(self.env.user.google_synchronization_stopped)
|
|
self.assertEqual(self.env.user._get_google_sync_status(), "sync_paused")
|
|
self.assertFalse(record.active, "Event must be archived in Odoo after unlinking it")
|
|
self.assertTrue(record.need_sync, "Sync variable must be true for updating event in Google when sync re-activates")
|
|
self.assertGoogleEventNotDeleted()
|
|
|
|
@patch_api
|
|
def test_videocall_location_on_location_set(self):
|
|
partner = self.env['res.partner'].create({'name': 'Jean-Luc', 'email': 'jean-luc@opoo.com'})
|
|
event = self.env['calendar.event'].create({
|
|
'name': "Event",
|
|
'start': datetime(2020, 1, 15, 8, 0),
|
|
'stop': datetime(2020, 1, 15, 18, 0),
|
|
'partner_ids': [(4, partner.id)],
|
|
'need_sync': False,
|
|
'location' : 'Event Location'
|
|
})
|
|
event._sync_odoo2google(self.google_service)
|
|
self.assertGoogleEventHasNoConferenceData()
|