-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from coopdevs/14.0-feature/sync
Sync updated and deleted events with external calendars
- Loading branch information
Showing
11 changed files
with
230 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.devenv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<odoo> | ||
<data noupdate="1"> | ||
<!-- Automated Actions --> | ||
<record id="calendar_event_update_rule" model="base.automation"> | ||
<field name="name">Update Event in External Calendar</field> | ||
<field name="model_id" ref="calendar.model_calendar_event" /> | ||
<field name="trigger">on_write</field> | ||
<field name="state">code</field> | ||
<field name="code"> | ||
for record in records: | ||
if record.external_uuid: | ||
record.update_event_in_external_calendar() | ||
</field> | ||
<field name="active" eval="True" /> | ||
</record> | ||
|
||
<record id="calendar_event_delete_rule" model="base.automation"> | ||
<field name="name">Delete Event in External Calendar</field> | ||
<field name="model_id" ref="calendar.model_calendar_event" /> | ||
<field name="trigger">on_unlink</field> | ||
<field name="state">code</field> | ||
<field name="code"> | ||
for record in records: | ||
if record.external_uuid: | ||
record.delete_event_in_external_calendar() | ||
</field> | ||
<field name="active" eval="True" /> | ||
</record> | ||
|
||
</data> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
from . import res_users | ||
from . import calendar_event |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import requests | ||
import caldav | ||
import logging | ||
|
||
from calendar import Calendar | ||
from requests.auth import HTTPBasicAuth | ||
from odoo import models, fields, api | ||
from datetime import datetime | ||
from pytz import timezone | ||
from icalendar import Calendar, vDatetime | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
class CalendarEvent(models.Model): | ||
_inherit = 'calendar.event' | ||
|
||
external_uuid = fields.Char(string='External UUID') | ||
|
||
def add_unsynced_tag(self): | ||
unsynced_tag_name = '#unsynced' | ||
category = self.env['calendar.event.type'] | ||
unsynced_tag = category.search([('name', '=', unsynced_tag_name)]) | ||
if not unsynced_tag: | ||
unsynced_tag = category.create({'name': unsynced_tag_name}) | ||
self.categ_ids = [(4, unsynced_tag.id)] | ||
|
||
def update_event_in_external_calendar(self): | ||
for event in self: | ||
# Obtén los asistentes al evento antes y después de la actualización | ||
partner_before_update = event._origin.partner_id | ||
partner_after_update = event.partner_id | ||
all_partners = partner_before_update | partner_after_update | ||
|
||
for partner in all_partners: | ||
user = self.env['res.users'].search( | ||
[('partner_id', '=', partner.id)], limit=1) | ||
if not user or not user.calendar_credentials_verified: | ||
continue | ||
client = caldav.DAVClient( | ||
url=user.calendar_url, username=user.calendar_user, password=user.calendar_password) | ||
principal = client.principal() | ||
calendars = principal.calendars() | ||
|
||
if calendars: | ||
calendar = calendars[0] | ||
|
||
external_event = calendar.event_by_uid(event.external_uuid) | ||
if external_event: | ||
ical = Calendar.from_ical(external_event.data) | ||
ical_event = ical.walk('VEVENT')[0] | ||
ical_event['SUMMARY'] = event.name | ||
ical_event['DTSTART'] = vDatetime(event.start.replace(tzinfo=timezone('UTC'))) | ||
ical_event['DTEND'] = vDatetime(event.stop.replace(tzinfo=timezone('UTC'))) | ||
ical_event['LOCATION'] = event.location or '' | ||
ical_event['DESCRIPTION'] = event.description or '' # Update the event in the external calendar | ||
external_event.data = ical.to_ical() | ||
external_event.save(no_overwrite=False) | ||
|
||
def delete_event_in_external_calendar(self): | ||
for event in self: | ||
if not event.external_uuid: | ||
continue | ||
|
||
partner = event.partner_id | ||
user = self.env['res.users'].search( | ||
[('partner_id', '=', partner.id)], limit=1) | ||
|
||
if not user or not user.calendar_credentials_verified: | ||
continue | ||
base_url = user.calendar_url | ||
calendar_user = user.calendar_user | ||
calendar_password = user.calendar_password | ||
user_sync = user.calendar_credentials_verified | ||
|
||
if base_url and calendar_user and calendar_password and user_sync: | ||
event_url = base_url + event.external_uuid + ".ics" | ||
try: | ||
self._delete_ical_event( | ||
event_url, calendar_user, calendar_password) | ||
except Exception as e: | ||
_logger.error( | ||
"Error deleting event from external calendar: %s", str(e)) | ||
event.add_unsynced_tag() | ||
|
||
def _delete_ical_event(self, event_url, calendar_user, calendar_password): | ||
try: | ||
response = requests.request( | ||
'DELETE', event_url, auth=HTTPBasicAuth(calendar_user, calendar_password), timeout=10 | ||
) | ||
_logger.debug("Response: %s %s" % | ||
(response.status_code, response.reason)) | ||
if response.status_code not in (204, 404): | ||
response.raise_for_status() | ||
except requests.exceptions.RequestException as e: | ||
_logger.error("Error deleting event: %s %s" % | ||
(response.status_code, response.reason)) | ||
raise e |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
This module allows you to export Odoo calendar events to an external webcal (such as Nextcloud) for each user. Users can provide their webcal URL and credentials in their user profile, and the module will automatically export events created within the last hour. A scheduled action runs hourly to check for recent events and export them to the corresponding user's webcal. | ||
|
||
Updated or deleted events trigger an update or deletion in the webcal. | ||
|
||
**Note:** This module is not really synchronizing events, but rather exporting them to a webcal. This means that events created in the webcal will not be imported back into Odoo. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.