You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
5.4 KiB
174 lines
5.4 KiB
# Copyright 2019 Therp BV <https://therp.nl>
|
|
# Copyright 2019-2020 initOS GmbH <https://initos.com>
|
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
|
|
|
import datetime
|
|
|
|
from odoo import api, fields, models, tools
|
|
from odoo.tools.safe_eval import safe_eval
|
|
|
|
import dateutil
|
|
import vobject
|
|
from dateutil import tz
|
|
|
|
|
|
class DavCollectionFieldMapping(models.Model):
|
|
_name = "dav.collection.field_mapping"
|
|
_description = "A field mapping for a WebDAV collection"
|
|
|
|
collection_id = fields.Many2one(
|
|
"dav.collection",
|
|
required=True,
|
|
ondelete="cascade",
|
|
)
|
|
name = fields.Char(
|
|
required=True,
|
|
help="Attribute name in the vobject",
|
|
)
|
|
mapping_type = fields.Selection(
|
|
[
|
|
("simple", "Simple"),
|
|
("code", "Code"),
|
|
],
|
|
default="simple",
|
|
required=True,
|
|
)
|
|
field_id = fields.Many2one(
|
|
"ir.model.fields",
|
|
required=True,
|
|
ondelete="cascade",
|
|
help="Field of the model the values are mapped to",
|
|
)
|
|
model_id = fields.Many2one(
|
|
"ir.model",
|
|
related="collection_id.model_id",
|
|
)
|
|
import_code = fields.Text(
|
|
help="Code to import the value from a vobject. Use the variable "
|
|
"result for the output of the value and item as input"
|
|
)
|
|
export_code = fields.Text(
|
|
help="Code to export the value to a vobject. Use the variable "
|
|
"result for the output of the value and record as input"
|
|
)
|
|
|
|
def from_vobject(self, child):
|
|
self.ensure_one()
|
|
if self.mapping_type == "code":
|
|
return self._from_vobject_code(child)
|
|
return self._from_vobject_simple(child)
|
|
|
|
def _from_vobject_code(self, child):
|
|
self.ensure_one()
|
|
context = {
|
|
"datetime": datetime,
|
|
"dateutil": dateutil,
|
|
"item": child,
|
|
"result": None,
|
|
"tools": tools,
|
|
"tz": tz,
|
|
"vobject": vobject,
|
|
}
|
|
safe_eval(self.import_code, context, mode="exec", nocopy=True)
|
|
return context.get("result", {})
|
|
|
|
def _from_vobject_simple(self, child):
|
|
self.ensure_one()
|
|
name = self.name.lower()
|
|
conversion_funcs = [
|
|
"_from_vobject_%s_%s" % (self.field_id.ttype, name),
|
|
"_from_vobject_%s" % self.field_id.ttype,
|
|
]
|
|
|
|
for conversion_func in conversion_funcs:
|
|
if hasattr(self, conversion_func):
|
|
value = getattr(self, conversion_func)(child)
|
|
if value:
|
|
return value
|
|
|
|
return child.value
|
|
|
|
@api.model
|
|
def _from_vobject_datetime(self, item):
|
|
if isinstance(item.value, datetime.datetime):
|
|
value = item.value.astimezone(dateutil.tz.UTC)
|
|
return value.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
|
elif isinstance(item.value, datetime.date):
|
|
return item.value.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
|
return None
|
|
|
|
@api.model
|
|
def _from_vobject_date(self, item):
|
|
if isinstance(item.value, datetime.datetime):
|
|
value = item.value.astimezone(dateutil.tz.UTC)
|
|
return value.strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
|
elif isinstance(item.value, datetime.date):
|
|
return item.value.strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
|
return None
|
|
|
|
@api.model
|
|
def _from_vobject_binary(self, item):
|
|
return item.value.encode("ascii")
|
|
|
|
@api.model
|
|
def _from_vobject_char_n(self, item):
|
|
return item.family
|
|
|
|
def to_vobject(self, record):
|
|
self.ensure_one()
|
|
if self.mapping_type == "code":
|
|
result = self._to_vobject_code(record)
|
|
else:
|
|
result = self._to_vobject_simple(record)
|
|
|
|
if isinstance(result, datetime.datetime) and not result.tzinfo:
|
|
return result.replace(tzinfo=tz.UTC)
|
|
return result
|
|
|
|
def _to_vobject_code(self, record):
|
|
self.ensure_one()
|
|
context = {
|
|
"datetime": datetime,
|
|
"dateutil": dateutil,
|
|
"record": record,
|
|
"result": None,
|
|
"tools": tools,
|
|
"tz": tz,
|
|
"vobject": vobject,
|
|
}
|
|
safe_eval(self.export_code, context, mode="exec", nocopy=True)
|
|
return context.get("result", None)
|
|
|
|
def _to_vobject_simple(self, record):
|
|
self.ensure_one()
|
|
conversion_funcs = [
|
|
"_to_vobject_%s_%s" % (self.field_id.ttype, self.name.lower()),
|
|
"_to_vobject_%s" % self.field_id.ttype,
|
|
]
|
|
value = record[self.field_id.name]
|
|
for conversion_func in conversion_funcs:
|
|
if hasattr(self, conversion_func):
|
|
return getattr(self, conversion_func)(value)
|
|
return value
|
|
|
|
@api.model
|
|
def _to_vobject_datetime(self, value):
|
|
result = fields.Datetime.from_string(value)
|
|
return result.replace(tzinfo=tz.UTC)
|
|
|
|
@api.model
|
|
def _to_vobject_datetime_rev(self, value):
|
|
return value and value.replace("-", "").replace(" ", "T").replace(":", "") + "Z"
|
|
|
|
@api.model
|
|
def _to_vobject_date(self, value):
|
|
return fields.Date.from_string(value)
|
|
|
|
@api.model
|
|
def _to_vobject_binary(self, value):
|
|
return value and value.decode("ascii")
|
|
|
|
@api.model
|
|
def _to_vobject_char_n(self, value):
|
|
# TODO: how are we going to handle compound types like this?
|
|
return vobject.vcard.Name(family=value)
|