74 lines
2.2 KiB
Python
74 lines
2.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
# copyright 2016 Camptocamp
|
|
# license agpl-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
|
|
|
import json
|
|
from datetime import datetime, date
|
|
|
|
import dateutil
|
|
|
|
from odoo import fields, models
|
|
|
|
|
|
class JobSerialized(fields.Field):
|
|
""" Serialized fields provide the storage for sparse fields. """
|
|
type = 'job_serialized'
|
|
column_type = ('text', 'text')
|
|
|
|
def convert_to_column(self, value, record, values=None):
|
|
return json.dumps(value, cls=JobEncoder)
|
|
|
|
def convert_to_cache(self, value, record, validate=True):
|
|
# cache format: dict
|
|
value = value or {}
|
|
if isinstance(value, dict):
|
|
return value
|
|
else:
|
|
return json.loads(value, cls=JobDecoder, env=record.env)
|
|
|
|
|
|
class JobEncoder(json.JSONEncoder):
|
|
""" Encode Odoo recordsets so that we can later recompose them """
|
|
|
|
def default(self, obj):
|
|
if isinstance(obj, models.BaseModel):
|
|
return {'_type': 'odoo_recordset',
|
|
'model': obj._name,
|
|
'ids': obj.ids,
|
|
'uid': obj.env.uid,
|
|
}
|
|
elif isinstance(obj, datetime):
|
|
return {'_type': 'datetime_isoformat',
|
|
'value': obj.isoformat()}
|
|
elif isinstance(obj, date):
|
|
return {'_type': 'date_isoformat',
|
|
'value': obj.isoformat()}
|
|
return json.JSONEncoder.default(self, obj)
|
|
|
|
|
|
class JobDecoder(json.JSONDecoder):
|
|
""" Decode json, recomposing recordsets """
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
env = kwargs.pop('env')
|
|
super(JobDecoder, self).__init__(
|
|
object_hook=self.object_hook, *args, **kwargs
|
|
)
|
|
assert env
|
|
self.env = env
|
|
|
|
def object_hook(self, obj):
|
|
if '_type' not in obj:
|
|
return obj
|
|
type_ = obj['_type']
|
|
if type_ == 'odoo_recordset':
|
|
model = self.env[obj['model']]
|
|
if obj.get('uid'):
|
|
model = model.sudo(obj['uid'])
|
|
return model.browse(obj['ids'])
|
|
elif type_ == 'datetime_isoformat':
|
|
return dateutil.parser.parse(obj['value'])
|
|
elif type_ == 'date_isoformat':
|
|
return dateutil.parser.parse(obj['value']).date()
|
|
return obj
|