Compare commits
1 Commits
14.0
...
14.0-dav_c
Author | SHA1 | Date | |
---|---|---|---|
|
72e7ebe769 |
@@ -14,7 +14,7 @@ class DavServer(models.Model):
|
|||||||
status = fields.Char(compute='_compute_status', string='Status', store=True)
|
status = fields.Char(compute='_compute_status', string='Status', store=True)
|
||||||
|
|
||||||
@api.depends("url", "username", "password")
|
@api.depends("url", "username", "password")
|
||||||
def _compute_status(self):
|
def compute_status(self):
|
||||||
try:
|
try:
|
||||||
self.get_principal()
|
self.get_principal()
|
||||||
self.write({"status": "OK"})
|
self.write({"status": "OK"})
|
||||||
|
@@ -19,6 +19,9 @@
|
|||||||
<field name="model">dav.server</field>
|
<field name="model">dav.server</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Dav Server">
|
<form string="Dav Server">
|
||||||
|
<header>
|
||||||
|
<button string="Test connection" name="compute_status" type="object" class="oe_highlight" />
|
||||||
|
</header>
|
||||||
<sheet>
|
<sheet>
|
||||||
<group>
|
<group>
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
|
7
dav_calendar_sync/README.rst
Normal file
7
dav_calendar_sync/README.rst
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
=====================
|
||||||
|
dav_calendar_sync
|
||||||
|
=====================
|
||||||
|
|
||||||
|
This module adds dav calendar synchronization
|
||||||
|
|
||||||
|
This is an Odoo addon.
|
5
dav_calendar_sync/__init__.py
Normal file
5
dav_calendar_sync/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
# from . import controllers
|
||||||
|
# from . import wizard
|
91
dav_calendar_sync/__manifest__.py
Normal file
91
dav_calendar_sync/__manifest__.py
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# Copyright 2022 Stéphan Sainléger (Elabore)
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "dav_calendar_sync",
|
||||||
|
"version": "14.0",
|
||||||
|
"author": "Elabore",
|
||||||
|
"website": "https://elabore.coop",
|
||||||
|
"maintainer": "Stéphan Sainléger",
|
||||||
|
"license": "AGPL-3",
|
||||||
|
"category": "Tools",
|
||||||
|
"summary": "This module adds dav calendar synchronization",
|
||||||
|
"description": """
|
||||||
|
:image: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||||
|
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||||
|
:alt: License: AGPL-3
|
||||||
|
===============
|
||||||
|
dav_calendar_sync
|
||||||
|
===============
|
||||||
|
|
||||||
|
This module adds dav calendar synchronization
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
Use Odoo normal module installation procedure to install
|
||||||
|
``dav_calendar_sync``.
|
||||||
|
|
||||||
|
Known issues / Roadmap
|
||||||
|
======================
|
||||||
|
|
||||||
|
None yet.
|
||||||
|
Bug Tracker
|
||||||
|
===========
|
||||||
|
|
||||||
|
Bugs are tracked on `our issues website <https://github.com/elabore-coop/dav-tools/issues>`_. In case of
|
||||||
|
trouble, please check there if your issue has already been
|
||||||
|
reported. If you spotted it first, help us smashing it by providing a
|
||||||
|
detailed and welcomed feedback.
|
||||||
|
|
||||||
|
Credits
|
||||||
|
=======
|
||||||
|
|
||||||
|
Contributors
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Stéphan Sainléger
|
||||||
|
|
||||||
|
Funders
|
||||||
|
-------
|
||||||
|
|
||||||
|
The development of this module has been financially supported by:
|
||||||
|
* Elabore (https://elabore.coop)
|
||||||
|
|
||||||
|
|
||||||
|
Maintainer
|
||||||
|
----------
|
||||||
|
|
||||||
|
This module is maintained by Elabore.
|
||||||
|
|
||||||
|
""",
|
||||||
|
# any module necessary for this one to work correctly
|
||||||
|
"depends": [
|
||||||
|
"base",
|
||||||
|
"calendar",
|
||||||
|
],
|
||||||
|
"qweb": [
|
||||||
|
# "static/src/xml/*.xml",
|
||||||
|
],
|
||||||
|
"external_dependencies": {
|
||||||
|
"python": [],
|
||||||
|
},
|
||||||
|
# always loaded
|
||||||
|
"data": [
|
||||||
|
# "security/security.xml",
|
||||||
|
"security/ir.model.access.csv",
|
||||||
|
"views/dav_server.xml",
|
||||||
|
"views/dav_calendar.xml",
|
||||||
|
# "views/menu.xml",
|
||||||
|
# "data/data.xml",
|
||||||
|
],
|
||||||
|
# only loaded in demonstration mode
|
||||||
|
"demo": [],
|
||||||
|
"js": [],
|
||||||
|
"css": [],
|
||||||
|
"installable": True,
|
||||||
|
# Install this module automatically if all dependency have been previously
|
||||||
|
# and independently installed. Used for synergetic or glue modules.
|
||||||
|
"auto_install": False,
|
||||||
|
"application": False,
|
||||||
|
}
|
1
dav_calendar_sync/controllers/__init__.py
Normal file
1
dav_calendar_sync/controllers/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
1
dav_calendar_sync/i18n/README
Normal file
1
dav_calendar_sync/i18n/README
Normal file
@@ -0,0 +1 @@
|
|||||||
|
This directory should contain the *.po for Odoo translation.
|
4
dav_calendar_sync/models/__init__.py
Normal file
4
dav_calendar_sync/models/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from . import dav_server
|
||||||
|
from . import dav_calendar
|
||||||
|
from . import res_users
|
||||||
|
from . import calendar_event
|
8
dav_calendar_sync/models/calendar_event.py
Normal file
8
dav_calendar_sync/models/calendar_event.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from odoo import _, api, fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class Meeting(models.Model):
|
||||||
|
_inherit = 'calendar.event'
|
||||||
|
|
||||||
|
dav_calendar_id = fields.Many2one('dav.calendar', string='Dav Calendar')
|
||||||
|
dav_uid = fields.Char('Dav Uid', index=True)
|
83
dav_calendar_sync/models/dav_calendar.py
Normal file
83
dav_calendar_sync/models/dav_calendar.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import logging
|
||||||
|
from odoo import fields, models
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DavCalendar(models.Model):
|
||||||
|
_name = "dav.calendar"
|
||||||
|
_description = "Dav calendar"
|
||||||
|
|
||||||
|
name = fields.Char('name')
|
||||||
|
url = fields.Char('url')
|
||||||
|
dav_server_id = fields.Many2one('dav.server', string='Dav Server')
|
||||||
|
|
||||||
|
sync_token = fields.Char("Synchronization Token")
|
||||||
|
|
||||||
|
active_sync_event = fields.Boolean('active_sync_event')
|
||||||
|
active_sync_todo = fields.Boolean('active_sync_todo')
|
||||||
|
|
||||||
|
def _manage_timezones(self, ical_event):
|
||||||
|
start = ical_event.get("DTSTART").dt
|
||||||
|
end = ical_event.get("DTEND").dt
|
||||||
|
# Odoo only uses naive dates, timezone data must be removed
|
||||||
|
# TODO: removing timezone data is not enough, naive dates must match the user timezone
|
||||||
|
if hasattr(start, "tzinfo"):
|
||||||
|
start = start.replace(tzinfo=None)
|
||||||
|
if hasattr(end, "tzinfo"):
|
||||||
|
end = start.replace(tzinfo=None)
|
||||||
|
return start, end
|
||||||
|
|
||||||
|
def _existing_event(self,ical_event):
|
||||||
|
calendar_events = self.env["calendar.event"].search([("dav_uid", "=", str(ical_event.get("UID")))])
|
||||||
|
if len(calendar_events) > 0:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _create_calendar_event(self, ical_event):
|
||||||
|
start, end = self._manage_timezones(ical_event)
|
||||||
|
values = {
|
||||||
|
"name":str(ical_event.get("SUMMARY")),
|
||||||
|
"start": start,
|
||||||
|
"stop": end,
|
||||||
|
"dav_calendar_id": self.id,
|
||||||
|
"dav_uid" : str(ical_event.get("UID")),
|
||||||
|
}
|
||||||
|
self.env["calendar.event"].create(values)
|
||||||
|
|
||||||
|
def _update_calendar_event(self, ical_event):
|
||||||
|
calendar_event = self.env["calendar.event"].search([("dav_uid", "=", str(ical_event.get("UID")))])[0]
|
||||||
|
start, end = self._manage_timezones(ical_event)
|
||||||
|
values = {
|
||||||
|
"name":str(ical_event.get("SUMMARY")),
|
||||||
|
"start": start,
|
||||||
|
"stop": end,
|
||||||
|
}
|
||||||
|
calendar_event.write(values)
|
||||||
|
|
||||||
|
def _delete_calendar_event(self, ical_event):
|
||||||
|
calendar_event = self.env["calendar.event"].search([("dav_uid", "=", str(ical_event.get("UID")))])[0]
|
||||||
|
calendar_event.unlink()
|
||||||
|
|
||||||
|
def sync_dav_events(self):
|
||||||
|
calendar = self.dav_server_id.get_principal().calendar(self.name)
|
||||||
|
if self.sync_token:
|
||||||
|
dav_events = calendar.objects_by_sync_token(self.sync_token, True)
|
||||||
|
else:
|
||||||
|
dav_events = calendar.objects_by_sync_token(load_objects=True)
|
||||||
|
event_created = 0
|
||||||
|
for dav_event in dav_events:
|
||||||
|
try:
|
||||||
|
ical_event = dav_event.icalendar_instance.subcomponents[0]
|
||||||
|
if dav_event.data is None:
|
||||||
|
self._delete_calendar_event(ical_event)
|
||||||
|
elif self._existing_event(ical_event):
|
||||||
|
self._update_calendar_event(ical_event)
|
||||||
|
else:
|
||||||
|
self._create_calendar_event(ical_event)
|
||||||
|
event_created += 1
|
||||||
|
except Exception as e:
|
||||||
|
_logger.exception("SYNC FAILURE on following event: %s", dav_event.data)
|
||||||
|
continue
|
||||||
|
self.sync_token = dav_events.sync_token
|
||||||
|
_logger.debug("NB EVENT CREATED: %s", event_created)
|
19
dav_calendar_sync/models/dav_server.py
Normal file
19
dav_calendar_sync/models/dav_server.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import caldav
|
||||||
|
from odoo import _, api, fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class DavServer(models.Model):
|
||||||
|
_inherit = "dav.server"
|
||||||
|
|
||||||
|
dav_calendar_ids = fields.One2many('dav.calendar', 'dav_server_id', string='Dav Calendars')
|
||||||
|
|
||||||
|
def compute_dav_calendar_ids(self):
|
||||||
|
calendars = self.get_principal().calendars()
|
||||||
|
for calendar in calendars:
|
||||||
|
values = {
|
||||||
|
"name": calendar.name,
|
||||||
|
"url": calendar.url,
|
||||||
|
"dav_server_id": self.id,
|
||||||
|
}
|
||||||
|
self.env["dav.calendar"].create(values)
|
||||||
|
|
7
dav_calendar_sync/models/res_users.py
Normal file
7
dav_calendar_sync/models/res_users.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from odoo import _, api, fields, models
|
||||||
|
|
||||||
|
class Users(models.Model):
|
||||||
|
_inherit="res.users"
|
||||||
|
|
||||||
|
calendar_event_ids = fields.Many2many('dav.calendar', 'dav_calendar_event_user_rel', string='Dav Calendars Events')
|
||||||
|
calendar_todo_ids = fields.Many2many('dav.calendar', 'dav_calendar_todo_user_rel', string='Dav Calendars Todo')
|
2
dav_calendar_sync/security/ir.model.access.csv
Normal file
2
dav_calendar_sync/security/ir.model.access.csv
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_dav_calendar_user,access_dav_calendar_user,model_dav_calendar,,1,1,1,1
|
|
44
dav_calendar_sync/views/dav_calendar.xml
Normal file
44
dav_calendar_sync/views/dav_calendar.xml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<record id="dav_calendar_view_tree" model="ir.ui.view">
|
||||||
|
<field name="name">dav.calendar.view.tree</field>
|
||||||
|
<field name="model">dav.calendar</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<tree string="Dav Calendars">
|
||||||
|
<field name="name" readonly="1" />
|
||||||
|
<field name="url" readonly="1" />
|
||||||
|
<field name="dav_server_id" readonly="1" />
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="dav_calendar_view_form" model="ir.ui.view">
|
||||||
|
<field name="name">dav.calendar.view.form</field>
|
||||||
|
<field name="model">dav.calendar</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Dav Calendar">
|
||||||
|
<header>
|
||||||
|
<button string="Sync Events" name="sync_dav_events" type="object" class="oe_highlight" />
|
||||||
|
</header>
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="name" readonly="1" />
|
||||||
|
<field name="url" readonly="1" />
|
||||||
|
<field name="dav_server_id" readonly="1" />
|
||||||
|
<field name="sync_token" />
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="act_dav_calendar_list" model="ir.actions.act_window">
|
||||||
|
<field name="name">Dav Calendars</field>
|
||||||
|
<field name="res_model">dav.calendar</field>
|
||||||
|
<field name="view_mode">tree,form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem id="menu_dav_calendars" action="act_dav_calendar_list" parent="dav_account.menu_dav" sequence="2" name="Dav Calendars" />
|
||||||
|
|
||||||
|
</odoo>
|
13
dav_calendar_sync/views/dav_server.xml
Normal file
13
dav_calendar_sync/views/dav_server.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="dav_server_view_form_inherit_calendar" model="ir.ui.view">
|
||||||
|
<field name="name">dav.server.view.form.inherit.calendar</field>
|
||||||
|
<field name="model">dav.server</field>
|
||||||
|
<field name="inherit_id" ref="dav_account.dav_server_view_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<header>
|
||||||
|
<button string="List Calendars" name="compute_dav_calendar_ids" type="object" class="oe_highlight" />
|
||||||
|
</header>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
0
dav_calendar_sync/wizard/__init__.py
Normal file
0
dav_calendar_sync/wizard/__init__.py
Normal file
Reference in New Issue
Block a user