Availability |
Odoo Online
Odoo.sh
On Premise
|
Odoo Apps Dependencies |
•
Calendar (calendar)
• Discuss (mail) |
Lines of code | 829 |
Technical Name |
caldav_sync |
License | LGPL-3 |
Website | https://www.bemade.org |
Versions | 17.0 |
Availability |
Odoo Online
Odoo.sh
On Premise
|
Odoo Apps Dependencies |
•
Calendar (calendar)
• Discuss (mail) |
Lines of code | 829 |
Technical Name |
caldav_sync |
License | LGPL-3 |
Website | https://www.bemade.org |
Versions | 17.0 |
CalDAV Synchronization

Author: Bemade Inc. (Marc Durepos)
Website: www.bemade.org
License: GNU Lesser General Public License (LGPL-3)
Overview
The CalDAV Synchronization module for Odoo allows users to synchronize their calendar events with CalDAV servers. This enables seamless integration of Odoo calendar with external applications like Apple Calendar or Thunderbird.
Warning
This module is in early development stages and should not be considered stable. Please test it on an unimportant calendar before using it with your important data. We are working hard to make improvements based on user feedback, so please reach out if you run into any issues or need a specific feature.
Features
- Synchronize Odoo calendar events with CalDAV servers.
- Create, update, and delete events in Odoo and reflect changes on the CalDAV server.
- Poll CalDAV server for changes and update Odoo calendar accordingly.
Configuration
- Install the module in Odoo.
- Go to the User settings in Odoo.
- Enter the CalDAV calendar URL, username, and password on the user settings. In some cases, the calendar URL to use is not evident. For Apple iCloud calendars, for example, we recommend starting with the base server url at https://caldav.icloud.com/ and then selecting a specific calendar url from the error given in the server logs.
Note: Some calendar service providers such as Apple iCloud require app-specific passwords to be set so that the calendar API can bypass 2-factor authentication. Please look into setting up app-specific passwords for your cloud calendar provider if you're faced with authentication errors.
Usage
- Create a calendar event in Odoo and it will be synchronized with the CalDAV calendar.
- Update the event in Odoo and the changes will reflect on the CalDAV server.
- Delete the event in Odoo and it will be removed from the CalDAV server.
- Changes made to the calendar on the CalDAV server will be polled and updated in Odoo.
Technical Details
The module extends the calendar.event
model to add CalDAV synchronization functionality. It uses the icalendar
library to format events and the caldav
library to interact with CalDAV servers. Polling for changes on the CalDAV server can be triggered manually by triggering the scheduled action in Odoo.
Support
If you have any issues with the module or feature requests, please reach out to us by creating an issue on our Gitlab at https://git.bemade.org/bemade/bemade-addons or by submitting a request on our website at https://www.bemade.org
Please log in to comment on this module
Report comment
Any abuse of this reporting system will be penalizedGreat Developer!!!
Thank you Marc for all of the support. I hope this helps balance out the review I did earlier. I truly thought I could go back and update my review as we worked on things.
For everyone else, The developer has reached out to me and worked with me one on one so we can get things built out correctly. His dedication to his product and user alone deserve 5 stars. Thank you for your time and I hope to see your offering grow and become perfected!
Thank You!
Awesome! (And a bug report)
Thanks you very much! Indeed this is the missing puzzle piece in our odoo.
And it now already works much better than before!
However there is one bug:
If an event was moved once (in odoo or from external) the next move will throw this error:
odoo.addons.caldav_sync.models.calendar_event: Failed to sync event to CalDAV server: PutError at '409 Conflict b''', reason no reason
Thanks you !!
Thank you so much for this feature that was missing in Odoo!
However, when creating a video meeting, the invitation and the link are sent by Nextcloud. Is it possible to let Odoo manage the meeting links as well as the invitations?
Thank you.
Re: Thanks you !!
Thanks for your kind note, Nourdine. If you create the meeting in the Odoo calendar you should be able to add the video call from there. I haven't tested with NextCloud so I don't know if it overwrites the iCal field for the video call URL. If not, you should even be able to head to your Odoo calendar and use the "clear meeting" button to remove the NextCloud URL and then add the Odoo Discuss call.
Excellent. but it has a few bugs.
My first attempt was on 17 community - which did not work at all. I then tested on a 17 Enterprise and it seemed to work really well. But...
- As others have mentioned, changing the appointment on the caldav server did not update Odoo.
- Later I created another appointment in Odoo which replicated to the caldav server fine. Then I tried to change the time of the appointment in Odoo which replicated but this time it change the time of the appointment on the caldav and treated it as if were UTC time instead of my timezone. Naturally, the appointment is now offset.
- When I tried to delete an appointment from Odoo, the appointment remained on the caldav server.
I'm sure all these little issue can be quickly fixed pretty easily for these talented guys.
Sincerely, keep up the awesome work bemade.org!!! Hanging out for the updates.
Re: Excellent. but it has a few bugs.
Thanks for your comment. I've recently updated the module with some pretty major fixes and a boatload of test cases. Give it a whirl and let me know what works and what doesn't.
Sorta working, but needs some fixes....
Adding a calendar item in to the Odoo calendar works and the entry appears on the remote Caldav calendar. But deleting it from Odoo, or even deleting it from the calendar, results in various errors:
2024-07-04 00:09:26,461 18113 ERROR com odoo.addons.base.models.ir_cron: Call from cron CalDAV Sync for server action #716 failed in Job #38
Traceback (most recent call last):
File "/odoo/odoo/tools/safe_eval.py", line 367, in safe_eval
return unsafe_eval(c, globals_dict, locals_dict)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "ir.actions.server(716,)", line 1, in
File "/odoo_addons/caldav_sync/models/calendar_event.py", line 203, in poll_caldav_server
self.with_user(user).poll_user_caldav_server()
File "/odoo_addons/caldav_sync/models/calendar_event.py", line 235, in poll_user_caldav_server
ical_event = caldav_event.icalendar_instance
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/caldav/objects.py", line 2403, in _get_icalendar_instance
self.icalendar_instance = icalendar.Calendar.from_ical(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/icalendar/cal.py", line 414, in from_ical
raise ValueError(cls._format_error(
ValueError: Found no components where exactly one is required:
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/odoo/odoo/addons/base/models/ir_cron.py", line 392, in _callback
self.env['ir.actions.server'].browse(server_action_id).run()
File "/odoo/odoo/addons/base/models/ir_actions.py", line 942, in run
res = runner(run_self, eval_context=eval_context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/odoo/addons/website/models/ir_actions_server.py", line 61, in _run_action_code_multi
res = super(ServerAction, self)._run_action_code_multi(eval_context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/odoo/odoo/addons/base/models/ir_actions.py", line 772, in _run_action_code_multi
safe_eval(self.code.strip(), eval_context, mode="exec", nocopy=True, filename=str(self)) # nocopy allows to return 'action'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/odoo/odoo/tools/safe_eval.py", line 381, in safe_eval
raise ValueError('%s: "%s" while evaluating\n%r' % (ustr(type(e)), ustr(e), expr))
ValueError: : "Found no components where exactly one is required:
" while evaluating
'model.poll_caldav_server()'
In addition to:
2024-07-03 23:57:04,296 18185 WARNING crm root: Error ReportError at '412 Precondition Failed
b''', reason no reason from server when doing an object_by_uid(40cfad99-9993-4125-a1b0-b044879682a3). search without compfilter set is not compatible with all server implementations, trying event_by_uid + todo_by_uid + journal_by_uid instead
2024-07-03 23:57:04,538 18185 ERROR crm odoo.addons.caldav_sync.models.calendar_event: Failed to remove event from CalDAV server: ReportError at '412 Precondition Failed
Re: Sorta working, but needs some fixes....
Hi, thanks for your comment and your patience with this still very early-stages module. I've just uploaded a major update with significantly more automated tests. Please give it a try and let me know if you're still having any issues.
Very good idea, though a bit complicated to setup.
Hello,
I am receiving the following error after having created an App Specific password in Apple ID.
caldav.lib.error.AuthorizationError: AuthorizationError at 'https://caldav.icloud.com/', reason Forbidden
What can I be doing wrong?
Thanks,
Re: Very good idea, though a bit complicated to setup.
Thanks for your comment, Peter. I have not personally tried with iCloud but from the URL you've posted it looks to me like the calendar-specific part of the URL is missing. When I share a calendar from Apple's Calendar app, I can right-click on the calendar and "Get Info" or "Copy URL to Clipboard". I'd suggest trying that URL instead. Please feel free to let me know how it goes and if you run into other issues at marc@bemade.org.
Issues
Every time I try to connect it to Odoo I get an error. I even tried to download the new code from GitHub and getting the same issue.
Invalid Operation
Error while importing module 'caldav_sync'. while parsing /tmp/tmpyb5lzcg9/caldav_sync/views/res_users_views.xml:3 Error while validating view near: <header> <button string="Re-send Invitation Email" type="object" name="action_reset_password" invisible="state != 'active'"/> <button string="Send an Invitation Email" type="object" name="action_reset_password" context="{'create_user': 1}" invisible="state != 'new'"/> <field name="state" widget="statusbar"/> </header> Field "caldav_calendar_url" does not exist in model "res.users" View error context: {'file': '/tmp/tmpyb5lzcg9/caldav_sync/views/res_users_views.xml', 'line': 4, 'name': 'res.users.form.inherit', 'view': ir.ui.view(2959,), 'view.model': 'res.users', 'view.parent': ir.ui.view(164,), 'xmlid': 'view_users_form_inherit'}
Re: Issues
This looks like your module is simply out of sync between the JS code running in the browser and what’s on the server. Try this:
Good luck! Feel free to reach out at marc@bemade.org if this doesn’t work for you.
Request for Odoo version 18
Hello,
I would very much appreciate it if this app would be updated for Odoo version 18.
Many thanks in advance! :)
Re: Request for Odoo version 18
Hello Andreas,
our 18.0 repo is not yet available on apps.odoo.com but you can get jt at git.bemade.org/bemade/bemade-addons .
Community edition
In the ratings section, someone noted it won't work with the community edition.
Currently, I exactly have this issue as the sync doesn't work.
I get "CalDav Sync started" and "CalDav Sync ended" in the log files (Odoo 17, on-premise), but no sync occurs in either ways.
After looking through the sources, my impression is that it neither enters the poo nor the push event section.
Can someone confirm or deny this and if this is true, why that is the case?
I want to give more stars
I would very much like to give this more stars ad it is a much needed feature in Odoo but this module continuously added the same events over and over from my caldav server to Odoo that it grind the entire DB to a halt. It was almost unusable.
I very much want to help improve this module so please let me know what you need and I will provide whatever is needed to get this working.
A two way sync with my CalDAV server would be great, as of right now it is a manual process.
Re: I want to give more stars
Hi Richard,
Thanks for the report. That’s a new one for me. If you have a calendar server to which you can set up a test user and give me access, I could try to debug from a dev server.
Please write me directly at marc@bemade.org and I’ll see what I can do. The more people who use this module the more bugs we’ll be able to catch and fix!
Will this module be available for v18 soon?
Thanks a lot !!
Thank you so much for this feature that was missing in Odoo!
However, when creating a video meeting, the invitation and the link are sent by Nextcloud. Is it possible to let Odoo manage the meeting links as well as the invitations?
Thank you.
Fixed an issue with recurring together with Nextcloud/emClient
Hi,
When syncing recurring events from my Nextcloud-instance (where event is created from emClient, I experienced following error:
`ValueError: RRULE UNTIL values must be specified in UTC when DTSTART is timezone-aware`
Startdate was given with timezone, and UNTIL was like `FREQ=WEEKLY;UNTIL=20250429T173000;BYDAY=MO;WKST=SU`
Odoo's internal datetime handling for recurring events strubbled with this.
I've fixed it in my instance, in calendar_event.py:
1. add method:
```
def _rrule_until_contains_tzinfo(self, rrule_str):
match = re.search(r'UNTIL=([0-9T]+)', rrule_str)
if match:
until_str = match.group(1)
contains_timezone = '+' in until_str or bool(re.search(r'[A-Z]{3}', until_str))
if not contains_timezone:
return True
else:
return False
else:
return False
```
2. before passing dtstart to _rrule_parse, check for this and eventually remove tzinfo from dtstart after converting it to UTC (don't forget `from zoneinfo import ZoneInfo`) :
```
dtstart = component.decoded("dtstart")
if self._rrule_until_contains_tzinfo(rrule_str):
dtstart = dtstart.astimezone(ZoneInfo("UTC")).replace(tzinfo=None)
rrule_params = self.env["calendar.recurrence"]._rrule_parse(
rrule_str, dtstart
)
```
some more details
2024-07-04 10:59:55,475 18321 WARNING crm odoo.api.create: The model odoo.addons.caldav_sync.models.calendar_event is not overriding the create method in batch
2024-07-04 10:59:57,207 18321 WARNING crm odoo.fields: Field res.users.caldav_password: unknown parameter 'password', if this is an actual parameter you may want to override the method _valid_field_parameter on the relevant model in order to allow it
2024-07-04 10:59:57,234 18321 WARNING crm py.warnings: /odoo/odoo/fields.py:542: UserWarning: Since Odoo 17, property calendar.event.description.states is no longer supported.
Looks to have a few bugs... Adding a calendar item in to the Odoo calendar works and the entry appears on the remote Caldav calendar. But deleting it from Odoo, or even deleting it from the calendar, results in various errors:
2024-07-04 00:09:26,461 18113 ERROR com odoo.addons.base.models.ir_cron: Call from cron CalDAV Sync for server action #716 failed in Job #38
Traceback (most recent call last):
File "/odoo/odoo/tools/safe_eval.py", line 367, in safe_eval
return unsafe_eval(c, globals_dict, locals_dict)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "ir.actions.server(716,)", line 1, in
File "/odoo_addons/caldav_sync/models/calendar_event.py", line 203, in poll_caldav_server
self.with_user(user).poll_user_caldav_server()
File "/odoo_addons/caldav_sync/models/calendar_event.py", line 235, in poll_user_caldav_server
ical_event = caldav_event.icalendar_instance
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/caldav/objects.py", line 2403, in _get_icalendar_instance
self.icalendar_instance = icalendar.Calendar.from_ical(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/icalendar/cal.py", line 414, in from_ical
raise ValueError(cls._format_error(
ValueError: Found no components where exactly one is required:
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/odoo/odoo/addons/base/models/ir_cron.py", line 392, in _callback
self.env['ir.actions.server'].browse(server_action_id).run()
File "/odoo/odoo/addons/base/models/ir_actions.py", line 942, in run
res = runner(run_self, eval_context=eval_context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/odoo/addons/website/models/ir_actions_server.py", line 61, in _run_action_code_multi
res = super(ServerAction, self)._run_action_code_multi(eval_context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/odoo/odoo/addons/base/models/ir_actions.py", line 772, in _run_action_code_multi
safe_eval(self.code.strip(), eval_context, mode="exec", nocopy=True, filename=str(self)) # nocopy allows to return 'action'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/odoo/odoo/tools/safe_eval.py", line 381, in safe_eval
raise ValueError('%s: "%s" while evaluating\n%r' % (ustr(type(e)), ustr(e), expr))
ValueError: : "Found no components where exactly one is required:
" while evaluating
'model.poll_caldav_server()'
In addition to:
2024-07-03 23:57:04,296 18185 WARNING crm root: Error ReportError at '412 Precondition Failed
b''', reason no reason from server when doing an object_by_uid(40cfad99-9993-4125-a1b0-b044879682a3). search without compfilter set is not compatible with all server implementations, trying event_by_uid + todo_by_uid + journal_by_uid instead
2024-07-03 23:57:04,538 18185 ERROR growthmeta_crm odoo.addons.caldav_sync.models.calendar_event: Failed to remove event from CalDAV server: ReportError at '412 Precondition Failed
Error connecting
RPC_ERROR
Odoo Server Error
Traceback (most recent call last):
File "/opt/odoosrc/17.0/odoo/odoo/tools/safe_eval.py", line 390, in safe_eval
return unsafe_eval(c, globals_dict, locals_dict)
File "ir.actions.server(293,)", line 1, in
File "/opt/cyder/clients/cal/cal_addons/caldav_sync/models/calendar_event.py", line 203, in poll_caldav_server
self.with_user(user).poll_user_caldav_server()
File "/opt/cyder/clients/cal/cal_addons/caldav_sync/models/calendar_event.py", line 236, in poll_user_caldav_server
self.sync_event_from_ical(ical_event)
File "/opt/cyder/clients/cal/cal_addons/caldav_sync/models/calendar_event.py", line 380, in sync_event_from_ical
recurrency_vals = self._get_recurrency_values_from_ical_event(component)
File "/opt/cyder/clients/cal/cal_addons/caldav_sync/models/calendar_event.py", line 318, in _get_recurrency_values_from_ical_event
vals.update(rrule_params.get("weekday"))
ValueError: dictionary update sequence element #0 has length 1; 2 is required
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/odoosrc/17.0/odoo/odoo/http.py", line 1764, in _serve_db
return service_model.retrying(self._serve_ir_http, self.env)
File "/opt/odoosrc/17.0/odoo/odoo/service/model.py", line 133, in retrying
result = func()
File "/opt/odoosrc/17.0/odoo/odoo/http.py", line 1791, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
File "/opt/odoosrc/17.0/odoo/odoo/http.py", line 1995, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
File "/opt/odoosrc/17.0/odoo/odoo/addons/base/models/ir_http.py", line 222, in _dispatch
result = endpoint(**request.params)
File "/opt/odoosrc/17.0/odoo/odoo/http.py", line 741, in route_wrapper
result = endpoint(self, *args, **params_ok)
File "/opt/odoosrc/17.0/odoo/addons/web/controllers/dataset.py", line 28, in call_button
action = self._call_kw(model, method, args, kwargs)
File "/opt/odoosrc/17.0/odoo/addons/web/controllers/dataset.py", line 20, in _call_kw
return call_kw(request.env[model], method, args, kwargs)
File "/opt/odoosrc/17.0/odoo/odoo/api.py", line 468, in call_kw
result = _call_kw_multi(method, model, args, kwargs)
File "/opt/odoosrc/17.0/odoo/odoo/api.py", line 453, in _call_kw_multi
result = method(recs, *args, **kwargs)
File "/opt/odoosrc/17.0/odoo/odoo/addons/base/models/ir_cron.py", line 107, in method_direct_trigger
cron.with_user(cron.user_id).with_context({'lastcall': cron.lastcall}).ir_actions_server_id.run()
File "/opt/odoosrc/17.0/odoo/odoo/addons/base/models/ir_actions.py", line 943, in run
res = runner(run_self, eval_context=eval_context)
File "/opt/odoosrc/17.0/odoo/odoo/addons/base/models/ir_actions.py", line 773, in _run_action_code_multi
safe_eval(self.code.strip(), eval_context, mode="exec", nocopy=True, filename=str(self)) # nocopy allows to return 'action'
File "/opt/odoosrc/17.0/odoo/odoo/tools/safe_eval.py", line 404, in safe_eval
raise ValueError('%s: "%s" while evaluating\n%r' % (ustr(type(e)), ustr(e), expr))
ValueError: : "dictionary update sequence element #0 has length 1; 2 is required" while evaluating
'model.poll_caldav_server()'
The above server error caused the following client error:
RPC_ERROR: Odoo Server Error
RPCError@https://cal.cyder.com.au/web/assets/0717d44/web.assets_web.min.js:2871:319
makeErrorFromResponse@https://cal.cyder.com.au/web/assets/0717d44/web.assets_web.min.js:2874:163
jsonrpc/promisehttps://cal.cyder.com.au/web/assets/0717d44/web.assets_web.min.js:2878:34
Installed now
Got it to install: pip install --force-reinstall -v caldav==1.3.8
Install errors
Hi tried to install but now get this message: Unable to install module "caldav_sync" because an external dependency is not met: Python library version conflict: caldav
I have "pip install caldav" in the environment which installed 1.3.9.