102 lines
4.0 KiB
Python
102 lines
4.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import logging
|
|
import secrets
|
|
|
|
from odoo import api, fields, models
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class CalendarEvent(models.Model):
|
|
_inherit = 'calendar.event'
|
|
|
|
x_fc_source_account_id = fields.Many2one(
|
|
'fusion.calendar.account', string='Source Calendar Account',
|
|
help='The external calendar account that originally synced this event.',
|
|
)
|
|
x_fc_is_external = fields.Boolean(
|
|
string='External Event', compute='_compute_is_external', store=True,
|
|
)
|
|
x_fc_link_ids = fields.One2many(
|
|
'fusion.calendar.event.link', 'x_fc_event_id', string='External Links',
|
|
)
|
|
x_fc_manage_token = fields.Char(
|
|
string='Manage Token', index=True, copy=False,
|
|
help='Random token allowing public visitors to manage their booking.',
|
|
)
|
|
x_fc_client_email = fields.Char(string='Client Email')
|
|
x_fc_client_phone = fields.Char(string='Client Phone')
|
|
x_fc_address_lat = fields.Float(string='Location Latitude', digits=(10, 7))
|
|
x_fc_address_lng = fields.Float(string='Location Longitude', digits=(10, 7))
|
|
x_fc_travel_minutes_before = fields.Integer(
|
|
string='Travel Time Before (min)',
|
|
help='Estimated travel time to reach this appointment from the previous one.',
|
|
)
|
|
x_fc_is_travel_block = fields.Boolean(
|
|
string='Travel Block',
|
|
help='Auto-generated travel time placeholder event.',
|
|
)
|
|
|
|
@api.depends('x_fc_source_account_id')
|
|
def _compute_is_external(self):
|
|
for event in self:
|
|
event.x_fc_is_external = bool(event.x_fc_source_account_id)
|
|
|
|
def _skip_fc_sync(self):
|
|
"""Check if Fusion Schedule should skip syncing (native Odoo sync active)."""
|
|
ctx = self.env.context
|
|
return ctx.get('no_calendar_sync') or ctx.get('dont_notify')
|
|
|
|
def unlink(self):
|
|
"""On delete, also remove from all linked external calendars."""
|
|
if not self._skip_fc_sync():
|
|
for event in self:
|
|
if not event.x_fc_link_ids:
|
|
continue
|
|
for link in event.x_fc_link_ids:
|
|
account = link.x_fc_account_id
|
|
if not account.x_fc_active or not account.sudo().x_fc_rtoken:
|
|
continue
|
|
try:
|
|
token = account._get_valid_token()
|
|
if not token:
|
|
continue
|
|
if account.x_fc_provider == 'google':
|
|
account._google_delete_event(link.x_fc_external_id, token)
|
|
elif account.x_fc_provider == 'microsoft':
|
|
account._microsoft_delete_event(link.x_fc_external_id, token)
|
|
except Exception as e:
|
|
_logger.warning(
|
|
"Failed to delete external event %s from account %s: %s",
|
|
link.x_fc_external_id, account.id, e,
|
|
)
|
|
return super().unlink()
|
|
|
|
def write(self, vals):
|
|
"""On update, push changes to all linked external calendars."""
|
|
res = super().write(vals)
|
|
if self._skip_fc_sync():
|
|
return res
|
|
|
|
sync_fields = {'name', 'description', 'location', 'start', 'stop', 'allday',
|
|
'start_date', 'stop_date', 'privacy', 'show_as', 'active'}
|
|
if not sync_fields.intersection(vals.keys()):
|
|
return res
|
|
|
|
for event in self:
|
|
if not event.x_fc_link_ids:
|
|
continue
|
|
for link in event.x_fc_link_ids:
|
|
account = link.x_fc_account_id
|
|
if not account.x_fc_active or account.x_fc_sync_status != 'active':
|
|
continue
|
|
try:
|
|
account._sync_push_event(event)
|
|
except Exception as e:
|
|
_logger.warning(
|
|
"Failed to push event update %s to account %s: %s",
|
|
event.id, account.id, e,
|
|
)
|
|
return res
|