86 lines
3.8 KiB
Python
86 lines
3.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
""" Odoo Radicale Storage Plugin """
|
|
|
|
from json import dumps
|
|
import threading
|
|
from contextlib import contextmanager
|
|
from odoorpc import ODOO
|
|
from odoorpc.error import RPCError
|
|
from radicale.storage import Collection as RadicaleCollection
|
|
|
|
|
|
class Collection(RadicaleCollection):
|
|
""" BaseCollection implementation for Odoo Radicale Storage """
|
|
|
|
odoo = False
|
|
|
|
def __init__(self, path, principal=None, folder=None, filesystem_path=None):
|
|
""" Init function """
|
|
super(Collection, self).__init__(path, principal, folder, filesystem_path)
|
|
if not self.odoo:
|
|
self.odoo_connect()
|
|
self.odoo_init()
|
|
|
|
@classmethod
|
|
def odoo_connect(cls):
|
|
""" Global Odoo connection : server and admin account """
|
|
host = cls.configuration.get('storage', 'odoo_host', fallback='127.0.0.1')
|
|
port = cls.configuration.get('storage', 'odoo_port', fallback=8069)
|
|
admin = cls.configuration.get('storage', 'odoo_admin_username')
|
|
password = cls.configuration.get('storage', 'odoo_admin_password')
|
|
database = cls.configuration.get('storage', 'odoo_database')
|
|
try:
|
|
cls.odoo = ODOO(host, port=port)
|
|
except RPCError as rpcerr:
|
|
cls.logger.error(rpcerr)
|
|
raise RuntimeError(rpcerr)
|
|
try:
|
|
cls.odoo.login(database, admin, password)
|
|
cls.logger.info('Login successfull for {} on database {}'.format(admin, database))
|
|
except RPCError as rpcerr:
|
|
cls.logger.error('Login problem for {} on database {}'.format(cls, database))
|
|
cls.logger.error(rpcerr)
|
|
raise RuntimeError(rpcerr)
|
|
return True
|
|
|
|
def odoo_init(self):
|
|
""" Init Odoo collections if not found """
|
|
# TODO: disallow collection deletion ?
|
|
user_ids = self.odoo.env['res.users'].search([])
|
|
users = self.odoo.execute('res.users', 'read', user_ids, ['login', 'email'])
|
|
for user in users:
|
|
principal_path = user.get('login')
|
|
self.logger.debug('Check collections from Odoo for %s' % principal_path)
|
|
contact_path = '%s/odoo-contact' % principal_path
|
|
calendar_path = '%s/odoo-calendar' % principal_path
|
|
collections = self.discover(principal_path, depth='1')
|
|
paths = [coll.path for coll in collections]
|
|
if contact_path not in paths:
|
|
props = {'tag': 'VADDRESSBOOK',
|
|
'D:displayname': 'Odoo contacts',
|
|
'C:calendar-description': 'Contacts form your Odoo account'}
|
|
self.create_collection(contact_path, props=props)
|
|
self.logger.info('Collection creation for Odoo Sync : %s' % contact_path)
|
|
if calendar_path not in paths:
|
|
props = {'tag': 'VCALENDAR',
|
|
'D:displayname': 'Odoo calendar',
|
|
'C:calendar-description': 'Events form your Odoo calendar'}
|
|
self.create_collection(calendar_path, props=props)
|
|
self.logger.info('Collection creation for Odoo Sync : %s' % calendar_path)
|