Пример #1
0
    def _sync_microsoft2odoo(self, microsoft_events: MicrosoftEvent, default_reminders=()):
        """Synchronize Microsoft recurrences in Odoo. Creates new recurrences, updates
        existing ones.

        :return: synchronized odoo
        """
        existing = microsoft_events.exists(self.env)
        new = microsoft_events - existing - microsoft_events.cancelled()
        new_recurrent = new.filter(lambda e: e.is_recurrent())

        default_values = {}

        odoo_values = [
            dict(self._microsoft_to_odoo_values(e, default_reminders, default_values), need_sync_m=False)
            for e in (new - new_recurrent)
        ]
        new_odoo = self.with_context(dont_notify=True).create(odoo_values)

        synced_recurrent_records = self.with_context(dont_notify=True)._sync_recurrence_microsoft2odoo(new_recurrent)
        if not self._context.get("dont_notify"):
            new_odoo._notify_attendees()
            synced_recurrent_records._notify_attendees()

        cancelled = existing.cancelled()
        cancelled_odoo = self.browse(cancelled.odoo_ids(self.env))
        cancelled_odoo._cancel_microsoft()

        recurrent_cancelled = self.env['calendar.recurrence'].search([
            ('microsoft_id', 'in', (microsoft_events.cancelled() - cancelled).microsoft_ids())])
        recurrent_cancelled._cancel_microsoft()

        synced_records = new_odoo + cancelled_odoo + synced_recurrent_records.calendar_event_ids

        for mevent in (existing - cancelled).filter(lambda e: e.lastModifiedDateTime and not e.seriesMasterId):
            # Last updated wins.
            # This could be dangerous if microsoft server time and odoo server time are different
            if mevent.is_recurrence():
                odoo_record = self.env['calendar.recurrence'].browse(mevent.odoo_id(self.env))
            else:
                odoo_record = self.browse(mevent.odoo_id(self.env))
            odoo_record_updated = pytz.utc.localize(odoo_record.write_date)
            updated = parse(mevent.lastModifiedDateTime or str(odoo_record_updated))
            if updated >= odoo_record_updated:
                vals = dict(odoo_record._microsoft_to_odoo_values(mevent, default_reminders), need_sync_m=False)
                odoo_record.write(vals)
                if odoo_record._name == 'calendar.recurrence':
                    odoo_record._update_microsoft_recurrence(mevent, microsoft_events)
                    synced_recurrent_records |= odoo_record
                else:
                    synced_records |= odoo_record

        return synced_records, synced_recurrent_records
Пример #2
0
    def _sync_recurrence_microsoft2odoo(self, microsoft_events: MicrosoftEvent):
        recurrent_masters = microsoft_events.filter(lambda e: e.is_recurrence())
        recurrents = microsoft_events.filter(lambda e: e.is_recurrent_not_master())
        default_values = {'need_sync_m': False}

        new_recurrence = self.env['calendar.recurrence']

        for recurrent_master in recurrent_masters:
            new_calendar_recurrence = dict(self.env['calendar.recurrence']._microsoft_to_odoo_values(recurrent_master, (), default_values), need_sync_m=False)
            to_create = recurrents.filter(lambda e: e.seriesMasterId == new_calendar_recurrence['microsoft_id'])
            recurrents -= to_create
            base_values = dict(self.env['calendar.event']._microsoft_to_odoo_values(recurrent_master, (), default_values), need_sync_m=False)
            to_create_values = []
            if new_calendar_recurrence.get('end_type', False) in ['count', 'forever']:
                to_create = list(to_create)[:MAX_RECURRENT_EVENT]
            for recurrent_event in to_create:
                if recurrent_event.type == 'occurrence':
                    value = self.env['calendar.event']._microsoft_to_odoo_recurrence_values(recurrent_event, (), base_values)
                else:
                    value = self.env['calendar.event']._microsoft_to_odoo_values(recurrent_event, (), default_values)

                to_create_values += [dict(value, need_sync_m=False)]

            new_calendar_recurrence['calendar_event_ids'] = [(0, 0, to_create_value) for to_create_value in to_create_values]
            new_recurrence_odoo = self.env['calendar.recurrence'].create(new_calendar_recurrence)
            new_recurrence_odoo.base_event_id = new_recurrence_odoo.calendar_event_ids[0] if new_recurrence_odoo.calendar_event_ids else False
            new_recurrence |= new_recurrence_odoo

        microsoft_ids = [x.seriesMasterId for x in recurrents]
        recurrences = self.env['calendar.recurrence'].search([('microsoft_id', 'in', microsoft_ids)])
        for recurrent_master_id in set([x.seriesMasterId for x in recurrents]):
            recurrence_id = recurrences.filtered(lambda ev: ev.microsoft_id == recurrent_master_id)
            to_update = recurrents.filter(lambda e: e.seriesMasterId == recurrent_master_id)
            for recurrent_event in to_update:
                if recurrent_event.type == 'occurrence':
                    value = self.env['calendar.event']._microsoft_to_odoo_recurrence_values(recurrent_event, (), {'need_sync_m': False})
                else:
                    value = self.env['calendar.event']._microsoft_to_odoo_values(recurrent_event, (), default_values)
                existing_event = recurrence_id.calendar_event_ids.filtered(lambda e: e._range() == (value['start'], value['stop']))
                if not existing_event:
                    continue
                value.pop('start')
                value.pop('stop')
                existing_event._write_from_microsoft(recurrent_event, value)
            new_recurrence |= recurrence_id
        return new_recurrence
Пример #3
0
    def get_events(self, sync_token=None, token=None, timeout=TIMEOUT):
        url = "/v1.0/me/calendarView/delta"
        headers = {
            'Content-type': 'application/json',
            'Authorization': 'Bearer %s' % token,
            'Prefer': 'odata.maxpagesize=50,outlook.body-content-type="text"'
        }
        params = {}
        if sync_token:
            params['$deltatoken'] = sync_token
        else:
            params['startDateTime'] = fields.Datetime.subtract(
                fields.Datetime.now(), years=3).strftime("%Y-%m-%dT00:00:00Z")
            params['endDateTime'] = fields.Datetime.add(
                fields.Datetime.now(), years=3).strftime("%Y-%m-%dT00:00:00Z")
        try:
            status, data, time = self.microsoft_service._do_request(
                url, params, headers, method='GET', timeout=timeout)
        except requests.HTTPError as e:
            if e.response.status_code == 410 and 'fullSyncRequired' in str(
                    e.response.content):
                raise InvalidSyncToken(
                    "Invalid sync token. Full sync required")
            raise e

        events = data.get('value', [])
        next_page_token = data.get('@odata.nextLink')
        while next_page_token:
            status, data, time = self.microsoft_service._do_request(
                next_page_token, {},
                headers,
                preuri='',
                method='GET',
                timeout=timeout)
            next_page_token = data.get('@odata.nextLink')
            events += data.get('value', [])

        next_sync_token_url = data.get('@odata.deltaLink')
        next_sync_token = urls.url_parse(
            next_sync_token_url).decode_query().get('$deltatoken', False)

        default_reminders = data.get('defaultReminders')

        return MicrosoftEvent(events), next_sync_token, default_reminders