From 810ba38fd9a779cd8937aa664ab1050d04410c1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Thu, 19 May 2016 08:57:22 +0200 Subject: [PATCH 01/15] add base_jsonify module --- base_jsonify/README.rst | 93 +++++++++++++++++++++++++++ base_jsonify/__init__.py | 7 ++ base_jsonify/__openerp__.py | 29 +++++++++ base_jsonify/demo/export_demo.xml | 11 ++++ base_jsonify/demo/ir.exports.line.csv | 16 +++++ base_jsonify/models/__init__.py | 8 +++ base_jsonify/models/ir_export.py | 40 ++++++++++++ base_jsonify/models/models.py | 49 ++++++++++++++ base_jsonify/tests/__init__.py | 6 ++ base_jsonify/tests/test_get_parser.py | 78 ++++++++++++++++++++++ 10 files changed, 337 insertions(+) create mode 100644 base_jsonify/README.rst create mode 100644 base_jsonify/__init__.py create mode 100644 base_jsonify/__openerp__.py create mode 100644 base_jsonify/demo/export_demo.xml create mode 100644 base_jsonify/demo/ir.exports.line.csv create mode 100644 base_jsonify/models/__init__.py create mode 100644 base_jsonify/models/ir_export.py create mode 100644 base_jsonify/models/models.py create mode 100644 base_jsonify/tests/__init__.py create mode 100644 base_jsonify/tests/test_get_parser.py diff --git a/base_jsonify/README.rst b/base_jsonify/README.rst new file mode 100644 index 000000000..dc0b04ad1 --- /dev/null +++ b/base_jsonify/README.rst @@ -0,0 +1,93 @@ +.. 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 + +============== +Base Jsonify +============== + +This module add the jsonify method to the ORM. This method take as argument +the browse record and the "parser" that specify the field to extract. + +Example of parser: + + +.. code-block:: python + + parser = [ + 'name', + 'number', + 'create_date', + ('partner_id', ['id', 'display_name', 'ref']) + ('line_id', ['id', ('product_id', ['name']), 'price_unit']) + ] + +In order to be consitent with the odoo api the jsonify method always +return a list of object even if there is only one element in input + +Also the module provide a method "get_json_parser" on the ir.exports object +that generate a parser from an ir.exports configuration + + +Installation +============ + +To install this module, you need to install it + +Configuration +============= + +No configuration required + +Usage +===== + +This is a technical module not function feature is added + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} + +.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt +.. branch is "8.0" for example + +Known issues / Roadmap +====================== + +Nothing yet + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* BEAU Sébastien + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/base_jsonify/__init__.py b/base_jsonify/__init__.py new file mode 100644 index 000000000..d34d08cb1 --- /dev/null +++ b/base_jsonify/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion (http://www.akretion.com) +# Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from . import models diff --git a/base_jsonify/__openerp__.py b/base_jsonify/__openerp__.py new file mode 100644 index 000000000..ad47b797d --- /dev/null +++ b/base_jsonify/__openerp__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion (http://www.akretion.com) +# Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Base Jsonify", + "summary": "Base module that provide the jsonify method on all object", + "version": "8.0.1.0.0", + "category": "Uncategorized", + "website": "https://odoo-community.org/", + "author": "Akretion, Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "external_dependencies": { + "python": [], + "bin": [], + }, + "depends": [ + "base", + ], + "data": [ + ], + "demo": [ + 'demo/export_demo.xml', + 'demo/ir.exports.line.csv', + ], +} diff --git a/base_jsonify/demo/export_demo.xml b/base_jsonify/demo/export_demo.xml new file mode 100644 index 000000000..4501b77d3 --- /dev/null +++ b/base_jsonify/demo/export_demo.xml @@ -0,0 +1,11 @@ + + + + + + Partner Export + res.partner + + + + diff --git a/base_jsonify/demo/ir.exports.line.csv b/base_jsonify/demo/ir.exports.line.csv new file mode 100644 index 000000000..476de3937 --- /dev/null +++ b/base_jsonify/demo/ir.exports.line.csv @@ -0,0 +1,16 @@ +id,export_id/id,name +name,ir_exp_partner,name +active,ir_exp_partner,active +credit_limit,ir_exp_partner,credit_limit +color,ir_exp_partner,color +category_id_name,ir_exp_partner,category_id/name +country_id_name,ir_exp_partner,country_id/name +country_id_code,ir_exp_partner,country_id/code +child_ids_name,ir_exp_partner,child_ids/name +child_ids_id,ir_exp_partner,child_ids/id +child_ids_email,ir_exp_partner,child_ids/email +child_ids_country_id_name,ir_exp_partner,child_ids/country_id/name +child_ids_country_id_code,ir_exp_partner,child_ids/country_id/code +child_ids_child_ids_name,ir_exp_partner,child_ids/child_ids/name +lang,ir_exp_partner,lang +comment,ir_exp_partner,comment diff --git a/base_jsonify/models/__init__.py b/base_jsonify/models/__init__.py new file mode 100644 index 000000000..15dcb2f3d --- /dev/null +++ b/base_jsonify/models/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion (http://www.akretion.com) +# Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from . import models +from . import ir_export diff --git a/base_jsonify/models/ir_export.py b/base_jsonify/models/ir_export.py new file mode 100644 index 000000000..e1ac0ccc4 --- /dev/null +++ b/base_jsonify/models/ir_export.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion (http://www.akretion.com) +# Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, models + + +def update_dict(data, fields): + field = fields[0] + if len(fields) == 1: + if field == '.id': + field = 'id' + data[field] = True + else: + if field not in data: + data[field] = {} + update_dict(data[field], fields[1:]) + + +def convert_dict(dict_parser): + parser = [] + for field, value in dict_parser.iteritems(): + if value is True: + parser.append(field) + else: + parser.append((field, convert_dict(value))) + return parser + + +class IrExport(models.Model): + _inherit = 'ir.exports' + + @api.multi + def get_json_parser(self): + self.ensure_one() + dict_parser = {} + for line in self.export_fields: + update_dict(dict_parser, line.name.split('/')) + return convert_dict(dict_parser) diff --git a/base_jsonify/models/models.py b/base_jsonify/models/models.py new file mode 100644 index 000000000..3c9834d0b --- /dev/null +++ b/base_jsonify/models/models.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion (http://www.akretion.com) +# Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, models +from openerp.exceptions import Warning as UserError +from openerp.tools.translate import _ + + +@api.multi +def jsonify(self, parser): + """ Convert the record according to the parser given + Example of parser: + parser = [ + 'name', + 'number', + 'create_date', + ('partner_id', ['id', 'display_name', 'ref']) + ('line_id', ['id', ('product_id', ['name']), 'price_unit']) + ] + + In order to be consitent with the odoo api the jsonify method always + return a list of object even if there is only one element in input + """ + result = [] + for rec in self: + res = {} + for field in parser: + if isinstance(field, tuple): + field_name, subparser = field + field_type = rec._fields[field_name].type + if field_type in ('one2many', 'many2many'): + res[field_name] = rec[field_name].jsonify(subparser) + elif field_type == 'many2one': + data = rec[field_name].jsonify(subparser) + if data: + res[field_name] = data[0] + else: + res[field_name] = None + else: + raise UserError(_('Wrong parser configuration')) + else: + res[field] = rec[field] + result.append(res) + return result + + +models.Model.jsonify = jsonify diff --git a/base_jsonify/tests/__init__.py b/base_jsonify/tests/__init__.py new file mode 100644 index 000000000..8ed730c5e --- /dev/null +++ b/base_jsonify/tests/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion (http://www.akretion.com) +# Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import test_get_parser diff --git a/base_jsonify/tests/test_get_parser.py b/base_jsonify/tests/test_get_parser.py new file mode 100644 index 000000000..a99eb6e7a --- /dev/null +++ b/base_jsonify/tests/test_get_parser.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# © +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp.tests.common import TransactionCase + + +class TestParser(TransactionCase): + + def setUp(self): + super(TestParser, self).setUp() + self.expected_parser = [ + u'lang', + u'comment', + u'credit_limit', + u'name', + u'color', + (u'child_ids', [ + (u'child_ids', [u'name']), + u'email', + (u'country_id', [u'code', u'name']), + u'name', + u'id', + ]), + (u'country_id', [u'code', u'name']), + u'active', + (u'category_id', [u'name']) + ] + + # TODO adapt data for 8.0 + def fixme_test_getting_parser(self): + exporter = self.env.ref('base_jsonify.ir_exp_partner') + parser = exporter.get_json_parser() + self.assertEqual(parser, self.expected_parser) + + def fixme_test_json_export(self): + expected_json = [{ + u'lang': False, + u'comment': False, + u'credit_limit': 0.0, + u'name': u'Camptocamp', + u'color': 0, + u'country_id': {u'code': u'FR', u'name': u'France'}, + u'child_ids': [{ + u'id': 29, + u'country_id': { + u'code': u'FR', + u'name': u'France' + }, + u'child_ids': [], + u'email': u'ayaan.agarwal@bestdesigners.example.com', + u'name': u'Ayaan Agarwal' + }, { + u'id': 35, + u'country_id': { + u'code': u'FR', + u'name': u'France'}, + u'child_ids': [], + u'email': u'benjamin.flores@nebula.example.com', + u'name': u'Benjamin Flores' + }, { + u'id': 28, + u'country_id': { + u'code': u'FR', + u'name': u'France'}, + u'child_ids': [], + u'email': u'phillipp.miller@mediapole.example.com', + u'name': u'Phillipp Miller' + }], + u'active': True, + u'category_id': [ + {u'name': u'Gold'}, + {u'name': u'Services'} + ] + }] + partner = self.env.ref('base.res_partner_12') + json_partner = partner.jsonify(self.expected_parser) + self.assertEqual(json_partner, expected_json) From 32dfb8efe59545d98ba040803c47f73821f38dac Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Wed, 31 May 2017 21:45:10 +0200 Subject: [PATCH 02/15] base_jsonify: Allow fields aliasing in jsonify --- base_jsonify/README.rst | 23 ++++ base_jsonify/models/__init__.py | 1 + base_jsonify/models/ir_export.py | 10 +- base_jsonify/models/ir_exports_line.py | 35 +++++++ base_jsonify/models/models.py | 32 ++++-- base_jsonify/tests/__init__.py | 1 + base_jsonify/tests/test_get_parser.py | 116 ++++++++++++--------- base_jsonify/tests/test_ir_exports_line.py | 45 ++++++++ 8 files changed, 204 insertions(+), 59 deletions(-) create mode 100644 base_jsonify/models/ir_exports_line.py create mode 100644 base_jsonify/tests/test_ir_exports_line.py diff --git a/base_jsonify/README.rst b/base_jsonify/README.rst index dc0b04ad1..654d627e6 100644 --- a/base_jsonify/README.rst +++ b/base_jsonify/README.rst @@ -25,10 +25,32 @@ Example of parser: In order to be consitent with the odoo api the jsonify method always return a list of object even if there is only one element in input +By default the key into the json is the name of the field extracted +from the model. If you need to specify an alternate name to use as key, you +can definne your mapping as follow into the parser definition: + +.. code-block:: python + + parser = [ + 'field_name:json_key' + ] + +.. code-block:: python + + + parser = [ + 'name', + 'number', + 'create_date:creationDate', + ('partner_id:partners', ['id', 'display_name', 'ref']) + ('line_id:lines', ['id', ('product_id', ['name']), 'price_unit']) + ] + Also the module provide a method "get_json_parser" on the ir.exports object that generate a parser from an ir.exports configuration + Installation ============ @@ -76,6 +98,7 @@ Contributors ------------ * BEAU Sébastien +* Laurent Mignon Maintainer ---------- diff --git a/base_jsonify/models/__init__.py b/base_jsonify/models/__init__.py index 15dcb2f3d..c6621497b 100644 --- a/base_jsonify/models/__init__.py +++ b/base_jsonify/models/__init__.py @@ -6,3 +6,4 @@ from . import models from . import ir_export +from . import ir_exports_line diff --git a/base_jsonify/models/ir_export.py b/base_jsonify/models/ir_export.py index e1ac0ccc4..810c79087 100644 --- a/base_jsonify/models/ir_export.py +++ b/base_jsonify/models/ir_export.py @@ -3,6 +3,7 @@ # Sébastien BEAU # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from collections import OrderedDict from openerp import api, models @@ -14,7 +15,7 @@ def update_dict(data, fields): data[field] = True else: if field not in data: - data[field] = {} + data[field] = OrderedDict() update_dict(data[field], fields[1:]) @@ -34,7 +35,10 @@ class IrExport(models.Model): @api.multi def get_json_parser(self): self.ensure_one() - dict_parser = {} + dict_parser = OrderedDict() for line in self.export_fields: - update_dict(dict_parser, line.name.split('/')) + names = line.name.split('/') + if line.alias: + names = line.alias.split('/') + update_dict(dict_parser, names) return convert_dict(dict_parser) diff --git a/base_jsonify/models/ir_exports_line.py b/base_jsonify/models/ir_exports_line.py new file mode 100644 index 000000000..a1e2cd6c3 --- /dev/null +++ b/base_jsonify/models/ir_exports_line.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp.exceptions import ValidationError +from openerp import api, fields, models, _ + + +class IrExportsLine(models.Model): + _inherit = 'ir.exports.line' + _order = 'name' + + alias = fields.Char( + 'Alias', + help=_('The complete path to the field where you can specify an ' + 'alias on the a step as field:alias') + ) + + @api.constrains('alias', 'name') + def _check_alias(self): + for rec in self: + if not rec.alias: + continue + names = rec.name.split('/') + names_with_alias = rec.alias.split('/') + if len(names) != len(names_with_alias): + raise ValidationError( + _("Name and Alias must have the same hierarchy depth")) + for name, name_with_alias in zip(names, names_with_alias): + field_name = name_with_alias.split(':')[0] + if name != field_name: + raise ValidationError( + _("The alias must reference the same field as in " + "name '%s' not in '%s'") % (name, name_with_alias) + ) diff --git a/base_jsonify/models/models.py b/base_jsonify/models/models.py index 3c9834d0b..bcee877dc 100644 --- a/base_jsonify/models/models.py +++ b/base_jsonify/models/models.py @@ -8,6 +8,17 @@ from openerp.exceptions import Warning as UserError from openerp.tools.translate import _ +def __parse_field(parser_field): + field_name = parser_field + subparser = None + if isinstance(parser_field, tuple): + field_name, subparser = parser_field + json_key = field_name + if ':' in field_name: + field_name, json_key = field_name.split(':') + return field_name, json_key, subparser + + @api.multi def jsonify(self, parser): """ Convert the record according to the parser given @@ -22,26 +33,35 @@ def jsonify(self, parser): In order to be consitent with the odoo api the jsonify method always return a list of object even if there is only one element in input + + By default the key into the json is the name of the field extracted + from the model. If you need to specify an alternate name to use as key, you + can definne your mapping as follow into the parser definition: + + parser = [ + 'field_name:json_key' + ] + """ result = [] for rec in self: res = {} for field in parser: - if isinstance(field, tuple): - field_name, subparser = field + field_name, json_key, subparser = __parse_field(field) + if subparser: field_type = rec._fields[field_name].type if field_type in ('one2many', 'many2many'): - res[field_name] = rec[field_name].jsonify(subparser) + res[json_key] = rec[field_name].jsonify(subparser) elif field_type == 'many2one': data = rec[field_name].jsonify(subparser) if data: - res[field_name] = data[0] + res[json_key] = data[0] else: - res[field_name] = None + res[json_key] = None else: raise UserError(_('Wrong parser configuration')) else: - res[field] = rec[field] + res[json_key] = rec[field_name] result.append(res) return result diff --git a/base_jsonify/tests/__init__.py b/base_jsonify/tests/__init__.py index 8ed730c5e..837c1145d 100644 --- a/base_jsonify/tests/__init__.py +++ b/base_jsonify/tests/__init__.py @@ -4,3 +4,4 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import test_get_parser +from . import test_ir_exports_line diff --git a/base_jsonify/tests/test_get_parser.py b/base_jsonify/tests/test_get_parser.py index a99eb6e7a..76db9f3dc 100644 --- a/base_jsonify/tests/test_get_parser.py +++ b/base_jsonify/tests/test_get_parser.py @@ -7,72 +7,88 @@ from openerp.tests.common import TransactionCase class TestParser(TransactionCase): - def setUp(self): - super(TestParser, self).setUp() - self.expected_parser = [ + def test_getting_parser(self): + expected_parser = [ + u'active', + (u'category_id', [u'name']), + (u'child_ids', [( + u'child_ids', [u'name']), + (u'country_id', [u'code', u'name']), + u'email', u'id', + u'name' + ]), + u'color', + u'comment', + (u'country_id', [u'code', u'name']), + u'credit_limit', + u'lang', + u'name'] + + exporter = self.env.ref('base_jsonify.ir_exp_partner') + parser = exporter.get_json_parser() + self.assertEqual(parser, expected_parser) + + # modify an ir.exports_line to put an alias for a field + self.env.ref('base_jsonify.category_id_name').write({ + 'alias': 'category_id:category/name' + }) + expected_parser[1] = (u'category_id:category', [u'name']) + parser = exporter.get_json_parser() + self.assertEqual(parser, expected_parser) + + def test_json_export(self): + parser = [ u'lang', u'comment', u'credit_limit', u'name', u'color', - (u'child_ids', [ - (u'child_ids', [u'name']), + (u'child_ids:children', [ + (u'child_ids:children', [u'name']), u'email', - (u'country_id', [u'code', u'name']), + (u'country_id:country', [u'code', u'name']), u'name', u'id', - ]), - (u'country_id', [u'code', u'name']), + ]), + (u'country_id:country', [u'code', u'name']), u'active', (u'category_id', [u'name']) ] - - # TODO adapt data for 8.0 - def fixme_test_getting_parser(self): - exporter = self.env.ref('base_jsonify.ir_exp_partner') - parser = exporter.get_json_parser() - self.assertEqual(parser, self.expected_parser) - - def fixme_test_json_export(self): + partner = self.env['res.partner'].create({ + 'name': 'Akretion', + 'country_id': self.env.ref('base.fr').id, + 'category_id': [(0, 0, {'name': 'Inovator'})], + 'child_ids': [ + (0, 0, { + 'name': 'Sebatien Beau', + 'country_id': self.env.ref('base.fr').id + }) + ] + }) expected_json = [{ u'lang': False, u'comment': False, u'credit_limit': 0.0, - u'name': u'Camptocamp', + u'name': u'Akretion', u'color': 0, - u'country_id': {u'code': u'FR', u'name': u'France'}, - u'child_ids': [{ - u'id': 29, - u'country_id': { - u'code': u'FR', - u'name': u'France' - }, - u'child_ids': [], - u'email': u'ayaan.agarwal@bestdesigners.example.com', - u'name': u'Ayaan Agarwal' - }, { - u'id': 35, - u'country_id': { - u'code': u'FR', - u'name': u'France'}, - u'child_ids': [], - u'email': u'benjamin.flores@nebula.example.com', - u'name': u'Benjamin Flores' - }, { - u'id': 28, - u'country_id': { - u'code': u'FR', - u'name': u'France'}, - u'child_ids': [], - u'email': u'phillipp.miller@mediapole.example.com', - u'name': u'Phillipp Miller' - }], + u'country': { + u'code': u'FR', + u'name': u'France' + }, u'active': True, u'category_id': [ - {u'name': u'Gold'}, - {u'name': u'Services'} - ] + {u'name': u'Inovator'} + ], + u'children': [{ + u'id': partner.child_ids.id, + u'country': { + u'code': u'FR', + u'name': u'France' + }, + u'children': [], + u'name': u'Sebatien Beau', + u'email': False + }] }] - partner = self.env.ref('base.res_partner_12') - json_partner = partner.jsonify(self.expected_parser) - self.assertEqual(json_partner, expected_json) + json_partner = partner.jsonify(parser) + self.assertDictEqual(json_partner[0], expected_json[0]) diff --git a/base_jsonify/tests/test_ir_exports_line.py b/base_jsonify/tests/test_ir_exports_line.py new file mode 100644 index 000000000..3622ced8c --- /dev/null +++ b/base_jsonify/tests/test_ir_exports_line.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# © 2017 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp.exceptions import ValidationError +from openerp.tests.common import TransactionCase + + +class TestIrExportsLine(TransactionCase): + + def setUp(self): + super(TestIrExportsLine, self).setUp() + self.ir_export = self.env.ref('base_jsonify.ir_exp_partner') + + def test_alias_contrains(self): + ir_export_lines_model = self.env['ir.exports.line'] + with self.assertRaises(ValidationError): + # The field into the name must be also into the alias + ir_export_lines_model.create({ + 'export_id': self.ir_export.id, + 'name': 'name', + 'alias': 'toto:my_alias' + }) + with self.assertRaises(ValidationError): + # The hierarchy into the alias must be the same as the one into + # the name + ir_export_lines_model.create({ + 'export_id': self.ir_export.id, + 'name': 'child_ids/child_ids/name', + 'alias': 'child_ids:children/name' + }) + with self.assertRaises(ValidationError): + # The hierarchy into the alias must be the same as the one into + # the name and must contains the same fields as into the name + ir_export_lines_model.create({ + 'export_id': self.ir_export.id, + 'name': 'child_ids/child_ids/name', + 'alias': 'child_ids:children/category_id:category/name' + }) + line = ir_export_lines_model.create({ + 'export_id': self.ir_export.id, + 'name': 'child_ids/child_ids/name', + 'alias': 'child_ids:children/child_ids:children/name' + }) + self.assertTrue(line) From f16eb48bf177286ddfa1942aaca42064bf90e5d4 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Fri, 2 Jun 2017 10:21:22 +0200 Subject: [PATCH 03/15] base_jsonify: typo --- base_jsonify/README.rst | 2 +- base_jsonify/models/models.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base_jsonify/README.rst b/base_jsonify/README.rst index 654d627e6..55e0e61db 100644 --- a/base_jsonify/README.rst +++ b/base_jsonify/README.rst @@ -27,7 +27,7 @@ return a list of object even if there is only one element in input By default the key into the json is the name of the field extracted from the model. If you need to specify an alternate name to use as key, you -can definne your mapping as follow into the parser definition: +can define your mapping as follow into the parser definition: .. code-block:: python diff --git a/base_jsonify/models/models.py b/base_jsonify/models/models.py index bcee877dc..08ba30a4a 100644 --- a/base_jsonify/models/models.py +++ b/base_jsonify/models/models.py @@ -36,7 +36,7 @@ def jsonify(self, parser): By default the key into the json is the name of the field extracted from the model. If you need to specify an alternate name to use as key, you - can definne your mapping as follow into the parser definition: + can define your mapping as follow into the parser definition: parser = [ 'field_name:json_key' From 1568e65c5b6184760de021118585d24f82d658b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Thu, 22 Jun 2017 12:46:43 +0200 Subject: [PATCH 04/15] base_jsonify: add support of reference fields --- base_jsonify/models/models.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/base_jsonify/models/models.py b/base_jsonify/models/models.py index 08ba30a4a..e6d651e02 100644 --- a/base_jsonify/models/models.py +++ b/base_jsonify/models/models.py @@ -52,10 +52,9 @@ def jsonify(self, parser): field_type = rec._fields[field_name].type if field_type in ('one2many', 'many2many'): res[json_key] = rec[field_name].jsonify(subparser) - elif field_type == 'many2one': - data = rec[field_name].jsonify(subparser) - if data: - res[json_key] = data[0] + elif field_type in ('many2one', 'reference'): + if rec[field_name]: + res[json_key] = rec[field_name].jsonify(subparser)[0] else: res[json_key] = None else: From d632e08c1ca4d96fb6b905fdb2f56bd0f8465334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Fri, 23 Jun 2017 15:46:44 +0200 Subject: [PATCH 05/15] base_jsonify: remove False for int, float, string --- base_jsonify/models/models.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/base_jsonify/models/models.py b/base_jsonify/models/models.py index e6d651e02..60b41ccb2 100644 --- a/base_jsonify/models/models.py +++ b/base_jsonify/models/models.py @@ -44,12 +44,18 @@ def jsonify(self, parser): """ result = [] + empty_value = { + 'char': '', + 'int': 0, + 'float': 0, + } + for rec in self: res = {} for field in parser: field_name, json_key, subparser = __parse_field(field) + field_type = rec._fields[field_name].type if subparser: - field_type = rec._fields[field_name].type if field_type in ('one2many', 'many2many'): res[json_key] = rec[field_name].jsonify(subparser) elif field_type in ('many2one', 'reference'): @@ -61,6 +67,8 @@ def jsonify(self, parser): raise UserError(_('Wrong parser configuration')) else: res[json_key] = rec[field_name] + if not res[json_key] and field_type in empty_value: + res[json_key] = empty_value[field_type] result.append(res) return result From 312ae42ccaeae8bb11632b625f606967d9e738dc Mon Sep 17 00:00:00 2001 From: hpar Date: Mon, 2 Oct 2017 12:08:12 +0200 Subject: [PATCH 06/15] base_jsonify: cleanups remove copyrights from init and update copyrights --- base_jsonify/README.rst | 7 +- base_jsonify/__init__.py | 5 - .../{__openerp__.py => __manifest__.py} | 5 +- base_jsonify/demo/export_demo.xml | 16 +-- base_jsonify/models/__init__.py | 5 - base_jsonify/models/ir_export.py | 4 +- base_jsonify/models/ir_exports_line.py | 4 +- base_jsonify/models/models.py | 126 +++++++++--------- base_jsonify/tests/__init__.py | 4 - base_jsonify/tests/test_get_parser.py | 12 +- base_jsonify/tests/test_ir_exports_line.py | 4 +- 11 files changed, 91 insertions(+), 101 deletions(-) rename base_jsonify/{__openerp__.py => __manifest__.py} (84%) diff --git a/base_jsonify/README.rst b/base_jsonify/README.rst index 55e0e61db..d50eb10ba 100644 --- a/base_jsonify/README.rst +++ b/base_jsonify/README.rst @@ -2,9 +2,9 @@ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 -============== +============ Base Jsonify -============== +============ This module add the jsonify method to the ORM. This method take as argument the browse record and the "parser" that specify the field to extract. @@ -76,7 +76,7 @@ This is a technical module not function feature is added Known issues / Roadmap ====================== -Nothing yet +No distinction between float 0.0L and no value Bug Tracker =========== @@ -98,6 +98,7 @@ Contributors ------------ * BEAU Sébastien +* Raphaël Reverdy * Laurent Mignon Maintainer diff --git a/base_jsonify/__init__.py b/base_jsonify/__init__.py index d34d08cb1..a0fdc10fe 100644 --- a/base_jsonify/__init__.py +++ b/base_jsonify/__init__.py @@ -1,7 +1,2 @@ # -*- coding: utf-8 -*- -# © 2016 Akretion (http://www.akretion.com) -# Sébastien BEAU -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - - from . import models diff --git a/base_jsonify/__openerp__.py b/base_jsonify/__manifest__.py similarity index 84% rename from base_jsonify/__openerp__.py rename to base_jsonify/__manifest__.py index ad47b797d..c0d746be7 100644 --- a/base_jsonify/__openerp__.py +++ b/base_jsonify/__manifest__.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- -# © 2016 Akretion (http://www.akretion.com) +# © 2017 Akretion (http://www.akretion.com) # Sébastien BEAU +# Raphaël Reverdy # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "Base Jsonify", "summary": "Base module that provide the jsonify method on all object", - "version": "8.0.1.0.0", + "version": "10.0.1.0.0", "category": "Uncategorized", "website": "https://odoo-community.org/", "author": "Akretion, Odoo Community Association (OCA)", diff --git a/base_jsonify/demo/export_demo.xml b/base_jsonify/demo/export_demo.xml index 4501b77d3..a9030c6de 100644 --- a/base_jsonify/demo/export_demo.xml +++ b/base_jsonify/demo/export_demo.xml @@ -1,11 +1,7 @@ - - - - - Partner Export - res.partner - - - - + + + Partner Export + res.partner + + \ No newline at end of file diff --git a/base_jsonify/models/__init__.py b/base_jsonify/models/__init__.py index c6621497b..635654e95 100644 --- a/base_jsonify/models/__init__.py +++ b/base_jsonify/models/__init__.py @@ -1,9 +1,4 @@ # -*- coding: utf-8 -*- -# © 2016 Akretion (http://www.akretion.com) -# Sébastien BEAU -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - - from . import models from . import ir_export from . import ir_exports_line diff --git a/base_jsonify/models/ir_export.py b/base_jsonify/models/ir_export.py index 810c79087..feae5cddf 100644 --- a/base_jsonify/models/ir_export.py +++ b/base_jsonify/models/ir_export.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -# © 2016 Akretion (http://www.akretion.com) +# © 2017 Akretion (http://www.akretion.com) # Sébastien BEAU # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from collections import OrderedDict -from openerp import api, models +from odoo import api, models def update_dict(data, fields): diff --git a/base_jsonify/models/ir_exports_line.py b/base_jsonify/models/ir_exports_line.py index a1e2cd6c3..6e27a844a 100644 --- a/base_jsonify/models/ir_exports_line.py +++ b/base_jsonify/models/ir_exports_line.py @@ -2,8 +2,8 @@ # Copyright 2017 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp.exceptions import ValidationError -from openerp import api, fields, models, _ +from odoo.exceptions import ValidationError +from odoo import api, fields, models, _ class IrExportsLine(models.Model): diff --git a/base_jsonify/models/models.py b/base_jsonify/models/models.py index 60b41ccb2..5a6afc7a2 100644 --- a/base_jsonify/models/models.py +++ b/base_jsonify/models/models.py @@ -1,76 +1,80 @@ # -*- coding: utf-8 -*- -# © 2016 Akretion (http://www.akretion.com) +# © 2017 Akretion (http://www.akretion.com) # Sébastien BEAU +# Raphaël Reverdy # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import api, models -from openerp.exceptions import Warning as UserError -from openerp.tools.translate import _ +from odoo import api, models +from odoo.exceptions import UserError +from odoo.tools.translate import _ -def __parse_field(parser_field): - field_name = parser_field - subparser = None - if isinstance(parser_field, tuple): - field_name, subparser = parser_field - json_key = field_name - if ':' in field_name: - field_name, json_key = field_name.split(':') - return field_name, json_key, subparser +class Base(models.AbstractModel): + _inherit = 'base' -@api.multi -def jsonify(self, parser): - """ Convert the record according to the parser given - Example of parser: - parser = [ - 'name', - 'number', - 'create_date', - ('partner_id', ['id', 'display_name', 'ref']) - ('line_id', ['id', ('product_id', ['name']), 'price_unit']) - ] + @api.model + def __parse_field(self, parser_field): + field_name = parser_field + subparser = None + if isinstance(parser_field, tuple): + field_name, subparser = parser_field + json_key = field_name + if ':' in field_name: + field_name, json_key = field_name.split(':') + return field_name, json_key, subparser - In order to be consitent with the odoo api the jsonify method always - return a list of object even if there is only one element in input - By default the key into the json is the name of the field extracted - from the model. If you need to specify an alternate name to use as key, you - can define your mapping as follow into the parser definition: + @api.multi + def jsonify(self, parser): + """ Convert the record according to the parser given + Example of parser: + parser = [ + 'name', + 'number', + 'create_date', + ('partner_id', ['id', 'display_name', 'ref']) + ('line_id', ['id', ('product_id', ['name']), 'price_unit']) + ] - parser = [ - 'field_name:json_key' - ] + In order to be consitent with the odoo api the jsonify method always + return a list of object even if there is only one element in input - """ - result = [] - empty_value = { - 'char': '', - 'int': 0, - 'float': 0, - } + By default the key into the json is the name of the field extracted + from the model. If you need to specify an alternate name to use as key, you + can define your mapping as follow into the parser definition: - for rec in self: - res = {} - for field in parser: - field_name, json_key, subparser = __parse_field(field) - field_type = rec._fields[field_name].type - if subparser: - if field_type in ('one2many', 'many2many'): - res[json_key] = rec[field_name].jsonify(subparser) - elif field_type in ('many2one', 'reference'): - if rec[field_name]: - res[json_key] = rec[field_name].jsonify(subparser)[0] - else: - res[json_key] = None - else: - raise UserError(_('Wrong parser configuration')) - else: - res[json_key] = rec[field_name] - if not res[json_key] and field_type in empty_value: - res[json_key] = empty_value[field_type] - result.append(res) - return result + parser = [ + 'field_name:json_key' + ] + """ + result = [] + empty_value = { + 'char': None, + 'int': None, + # 'float': None, TODO: 0.0 != False + 'text': None, + } -models.Model.jsonify = jsonify + for rec in self: + res = {} + for field in parser: + field_name, json_key, subparser = self.__parse_field(field) + field_type = rec._fields[field_name].type + if subparser: + if field_type in ('one2many', 'many2many'): + res[json_key] = rec[field_name].jsonify(subparser) + elif field_type in ('many2one', 'reference'): + if rec[field_name]: + res[json_key] = rec[field_name].jsonify(subparser)[0] + else: + res[json_key] = None + else: + raise UserError(_('Wrong parser configuration')) + else: + res[json_key] = rec[field_name] + if not res[json_key] and field_type in empty_value: + res[json_key] = empty_value[field_type] + result.append(res) + return result diff --git a/base_jsonify/tests/__init__.py b/base_jsonify/tests/__init__.py index 837c1145d..bf58ee4e9 100644 --- a/base_jsonify/tests/__init__.py +++ b/base_jsonify/tests/__init__.py @@ -1,7 +1,3 @@ # -*- coding: utf-8 -*- -# © 2016 Akretion (http://www.akretion.com) -# Sébastien BEAU -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - from . import test_get_parser from . import test_ir_exports_line diff --git a/base_jsonify/tests/test_get_parser.py b/base_jsonify/tests/test_get_parser.py index 76db9f3dc..e73267fb2 100644 --- a/base_jsonify/tests/test_get_parser.py +++ b/base_jsonify/tests/test_get_parser.py @@ -2,7 +2,7 @@ # © # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp.tests.common import TransactionCase +from odoo.tests.common import TransactionCase class TestParser(TransactionCase): @@ -57,17 +57,18 @@ class TestParser(TransactionCase): partner = self.env['res.partner'].create({ 'name': 'Akretion', 'country_id': self.env.ref('base.fr').id, + 'lang': 'en_US', # default 'category_id': [(0, 0, {'name': 'Inovator'})], 'child_ids': [ (0, 0, { 'name': 'Sebatien Beau', 'country_id': self.env.ref('base.fr').id }) - ] + ], }) expected_json = [{ - u'lang': False, - u'comment': False, + u'lang': u'en_US', + u'comment': None, u'credit_limit': 0.0, u'name': u'Akretion', u'color': 0, @@ -87,8 +88,9 @@ class TestParser(TransactionCase): }, u'children': [], u'name': u'Sebatien Beau', - u'email': False + u'email': None }] }] json_partner = partner.jsonify(parser) + self.assertDictEqual(json_partner[0], expected_json[0]) diff --git a/base_jsonify/tests/test_ir_exports_line.py b/base_jsonify/tests/test_ir_exports_line.py index 3622ced8c..020f9b25c 100644 --- a/base_jsonify/tests/test_ir_exports_line.py +++ b/base_jsonify/tests/test_ir_exports_line.py @@ -2,8 +2,8 @@ # © 2017 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp.exceptions import ValidationError -from openerp.tests.common import TransactionCase +from odoo.exceptions import ValidationError +from odoo.tests.common import TransactionCase class TestIrExportsLine(TransactionCase): From 2b93884e9d8b9b00176b43c0fcf1a81f1910f3ae Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Wed, 22 Aug 2018 12:02:35 +0200 Subject: [PATCH 07/15] base_jsonify: Output 'false' into json only for boolean fields --- base_jsonify/models/models.py | 13 ++++--------- base_jsonify/tests/test_get_parser.py | 22 +++++++++++++++++++--- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/base_jsonify/models/models.py b/base_jsonify/models/models.py index 5a6afc7a2..d4b9b678d 100644 --- a/base_jsonify/models/models.py +++ b/base_jsonify/models/models.py @@ -50,12 +50,6 @@ class Base(models.AbstractModel): """ result = [] - empty_value = { - 'char': None, - 'int': None, - # 'float': None, TODO: 0.0 != False - 'text': None, - } for rec in self: res = {} @@ -73,8 +67,9 @@ class Base(models.AbstractModel): else: raise UserError(_('Wrong parser configuration')) else: - res[json_key] = rec[field_name] - if not res[json_key] and field_type in empty_value: - res[json_key] = empty_value[field_type] + value = rec[field_name] + if value is False and field_type != 'boolean': + value = None + res[json_key] = value result.append(res) return result diff --git a/base_jsonify/tests/test_get_parser.py b/base_jsonify/tests/test_get_parser.py index e73267fb2..80d5b354a 100644 --- a/base_jsonify/tests/test_get_parser.py +++ b/base_jsonify/tests/test_get_parser.py @@ -66,7 +66,7 @@ class TestParser(TransactionCase): }) ], }) - expected_json = [{ + expected_json = { u'lang': u'en_US', u'comment': None, u'credit_limit': 0.0, @@ -90,7 +90,23 @@ class TestParser(TransactionCase): u'name': u'Sebatien Beau', u'email': None }] - }] + } json_partner = partner.jsonify(parser) - self.assertDictEqual(json_partner[0], expected_json[0]) + self.assertDictEqual(json_partner[0], expected_json) + + json_partner = partner.jsonify(parser) + + self.assertDictEqual(json_partner[0], expected_json) + + # Check that only boolean fields have boolean values into json + # By default if a field is not set into Odoo, the value is always False + # This value is not the expected one into the json + partner.write({'child_ids': [(6, 0, [])], + 'active': False, + 'lang': False}) + json_partner = partner.jsonify(parser) + expected_json['active'] = False + expected_json['lang'] = None + expected_json['children'] = [] + self.assertDictEqual(json_partner[0], expected_json) From 3b07e01ef7a3f6c7416819d1c2c0ac08df0b5f74 Mon Sep 17 00:00:00 2001 From: beau sebastien Date: Mon, 27 Aug 2018 18:31:57 +0200 Subject: [PATCH 08/15] base_jsonify: restore travis configuration (#112) * [ADD] restore travis configuration * [PEP] fix pep8 * [REF] exclude product_categ_available_pos of testing due to issue https://github.com/odoo/odoo/pull/23749 --- base_jsonify/demo/export_demo.xml | 2 +- base_jsonify/models/ir_exports_line.py | 4 ++-- base_jsonify/models/models.py | 8 ++++---- base_jsonify/tests/test_get_parser.py | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/base_jsonify/demo/export_demo.xml b/base_jsonify/demo/export_demo.xml index a9030c6de..de8566b76 100644 --- a/base_jsonify/demo/export_demo.xml +++ b/base_jsonify/demo/export_demo.xml @@ -4,4 +4,4 @@ Partner Export res.partner - \ No newline at end of file + diff --git a/base_jsonify/models/ir_exports_line.py b/base_jsonify/models/ir_exports_line.py index 6e27a844a..3d4b047ca 100644 --- a/base_jsonify/models/ir_exports_line.py +++ b/base_jsonify/models/ir_exports_line.py @@ -12,8 +12,8 @@ class IrExportsLine(models.Model): alias = fields.Char( 'Alias', - help=_('The complete path to the field where you can specify an ' - 'alias on the a step as field:alias') + help='The complete path to the field where you can specify an ' + 'alias on the a step as field:alias' ) @api.constrains('alias', 'name') diff --git a/base_jsonify/models/models.py b/base_jsonify/models/models.py index d4b9b678d..7a2df40cb 100644 --- a/base_jsonify/models/models.py +++ b/base_jsonify/models/models.py @@ -24,7 +24,6 @@ class Base(models.AbstractModel): field_name, json_key = field_name.split(':') return field_name, json_key, subparser - @api.multi def jsonify(self, parser): """ Convert the record according to the parser given @@ -41,8 +40,8 @@ class Base(models.AbstractModel): return a list of object even if there is only one element in input By default the key into the json is the name of the field extracted - from the model. If you need to specify an alternate name to use as key, you - can define your mapping as follow into the parser definition: + from the model. If you need to specify an alternate name to use as + key, you can define your mapping as follow into the parser definition: parser = [ 'field_name:json_key' @@ -61,7 +60,8 @@ class Base(models.AbstractModel): res[json_key] = rec[field_name].jsonify(subparser) elif field_type in ('many2one', 'reference'): if rec[field_name]: - res[json_key] = rec[field_name].jsonify(subparser)[0] + res[json_key] =\ + rec[field_name].jsonify(subparser)[0] else: res[json_key] = None else: diff --git a/base_jsonify/tests/test_get_parser.py b/base_jsonify/tests/test_get_parser.py index 80d5b354a..2527d7be0 100644 --- a/base_jsonify/tests/test_get_parser.py +++ b/base_jsonify/tests/test_get_parser.py @@ -57,7 +57,7 @@ class TestParser(TransactionCase): partner = self.env['res.partner'].create({ 'name': 'Akretion', 'country_id': self.env.ref('base.fr').id, - 'lang': 'en_US', # default + 'lang': 'en_US', # default 'category_id': [(0, 0, {'name': 'Inovator'})], 'child_ids': [ (0, 0, { From 53133a6eeb7f66d22628503403abdaba4a48b21d Mon Sep 17 00:00:00 2001 From: Pierrick Brun Date: Mon, 8 Oct 2018 10:57:51 +0200 Subject: [PATCH 09/15] base_jsonify: Use readme fragment mechanism --- base_jsonify/README.rst | 87 ++--- base_jsonify/readme/CONTRIBUTORS.rst | 3 + base_jsonify/readme/DESCRIPTION.rst | 42 ++ base_jsonify/static/description/index.html | 431 +++++++++++++++++++++ 4 files changed, 519 insertions(+), 44 deletions(-) create mode 100644 base_jsonify/readme/CONTRIBUTORS.rst create mode 100644 base_jsonify/readme/DESCRIPTION.rst create mode 100644 base_jsonify/static/description/index.html diff --git a/base_jsonify/README.rst b/base_jsonify/README.rst index d50eb10ba..65ffe69ef 100644 --- a/base_jsonify/README.rst +++ b/base_jsonify/README.rst @@ -1,11 +1,30 @@ -.. 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 - ============ Base Jsonify ============ +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/10.0/base_jsonify + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-10-0/server-tools-10-0-base_jsonify + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/149/10.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + This module add the jsonify method to the ORM. This method take as argument the browse record and the "parser" that specify the field to extract. @@ -49,69 +68,49 @@ can define your mapping as follow into the parser definition: Also the module provide a method "get_json_parser" on the ir.exports object that generate a parser from an ir.exports configuration +**Table of contents** - -Installation -============ - -To install this module, you need to install it - -Configuration -============= - -No configuration required - -Usage -===== - -This is a technical module not function feature is added - -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas - :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} - -.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt -.. branch is "8.0" for example - -Known issues / Roadmap -====================== - -No distinction between float 0.0L and no value +.. contents:: + :local: Bug Tracker =========== -Bugs are tracked on `GitHub 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. +Bugs are tracked on `GitHub 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 `_. + +Do not contact contributors directly about support or help with technical issues. Credits ======= -Images ------- +Authors +~~~~~~~ -* Odoo Community Association: `Icon `_. +* Akretion Contributors ------------- +~~~~~~~~~~~~ * BEAU Sébastien * Raphaël Reverdy * Laurent Mignon -Maintainer ----------- +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. .. image:: https://odoo-community.org/logo.png :alt: Odoo Community Association :target: https://odoo-community.org -This module is maintained by the OCA. - OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit https://odoo-community.org. +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_jsonify/readme/CONTRIBUTORS.rst b/base_jsonify/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..717c76041 --- /dev/null +++ b/base_jsonify/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* BEAU Sébastien +* Raphaël Reverdy +* Laurent Mignon diff --git a/base_jsonify/readme/DESCRIPTION.rst b/base_jsonify/readme/DESCRIPTION.rst new file mode 100644 index 000000000..25c62fbb3 --- /dev/null +++ b/base_jsonify/readme/DESCRIPTION.rst @@ -0,0 +1,42 @@ +This module add the jsonify method to the ORM. This method take as argument +the browse record and the "parser" that specify the field to extract. + +Example of parser: + + +.. code-block:: python + + parser = [ + 'name', + 'number', + 'create_date', + ('partner_id', ['id', 'display_name', 'ref']) + ('line_id', ['id', ('product_id', ['name']), 'price_unit']) + ] + +In order to be consitent with the odoo api the jsonify method always +return a list of object even if there is only one element in input + +By default the key into the json is the name of the field extracted +from the model. If you need to specify an alternate name to use as key, you +can define your mapping as follow into the parser definition: + +.. code-block:: python + + parser = [ + 'field_name:json_key' + ] + +.. code-block:: python + + + parser = [ + 'name', + 'number', + 'create_date:creationDate', + ('partner_id:partners', ['id', 'display_name', 'ref']) + ('line_id:lines', ['id', ('product_id', ['name']), 'price_unit']) + ] + +Also the module provide a method "get_json_parser" on the ir.exports object +that generate a parser from an ir.exports configuration diff --git a/base_jsonify/static/description/index.html b/base_jsonify/static/description/index.html new file mode 100644 index 000000000..a4065b092 --- /dev/null +++ b/base_jsonify/static/description/index.html @@ -0,0 +1,431 @@ + + + + + + +Base Jsonify + + + +
+

Base Jsonify

+ + +

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runbot

+

This module add the jsonify method to the ORM. This method take as argument +the browse record and the “parser” that specify the field to extract.

+

Example of parser:

+
+parser = [
+    'name',
+    'number',
+    'create_date',
+    ('partner_id', ['id', 'display_name', 'ref'])
+    ('line_id', ['id', ('product_id', ['name']), 'price_unit'])
+]
+
+

In order to be consitent with the odoo api the jsonify method always +return a list of object even if there is only one element in input

+

By default the key into the json is the name of the field extracted +from the model. If you need to specify an alternate name to use as key, you +can define your mapping as follow into the parser definition:

+
+parser = [
+     'field_name:json_key'
+]
+
+
+parser = [
+    'name',
+    'number',
+    'create_date:creationDate',
+    ('partner_id:partners', ['id', 'display_name', 'ref'])
+    ('line_id:lines', ['id', ('product_id', ['name']), 'price_unit'])
+]
+
+

Also the module provide a method “get_json_parser” on the ir.exports object +that generate a parser from an ir.exports configuration

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub 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.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/server-tools project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + From 101c5048600841e665f28ac922b7c4f017b99c05 Mon Sep 17 00:00:00 2001 From: Sylvain Le Gal Date: Mon, 10 Dec 2018 19:14:01 +0100 Subject: [PATCH 10/15] base_jsonify: add view for ir.exports --- base_jsonify/__manifest__.py | 1 + base_jsonify/views/ir_exports_view.xml | 38 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 base_jsonify/views/ir_exports_view.xml diff --git a/base_jsonify/__manifest__.py b/base_jsonify/__manifest__.py index c0d746be7..c3cbcec87 100644 --- a/base_jsonify/__manifest__.py +++ b/base_jsonify/__manifest__.py @@ -22,6 +22,7 @@ "base", ], "data": [ + 'views/ir_exports_view.xml', ], "demo": [ 'demo/export_demo.xml', diff --git a/base_jsonify/views/ir_exports_view.xml b/base_jsonify/views/ir_exports_view.xml new file mode 100644 index 000000000..1762eff08 --- /dev/null +++ b/base_jsonify/views/ir_exports_view.xml @@ -0,0 +1,38 @@ + + + + + ir.exports + 50 + +
+ + + + + + + + + + + + + + + + +
+
+
+ + + Export Fields + ir.exports + tree,form + + + + +
From d03284db970735ce90fac25e8852cdecb5e75550 Mon Sep 17 00:00:00 2001 From: Pierrick brun Date: Tue, 11 Dec 2018 16:51:46 +0100 Subject: [PATCH 11/15] base_jsonify: misc fixes on comments/docstrings --- base_jsonify/__manifest__.py | 10 +++------- base_jsonify/models/ir_export.py | 18 ++++++++++++++++++ base_jsonify/models/models.py | 5 ++++- base_jsonify/readme/DESCRIPTION.rst | 5 +++-- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/base_jsonify/__manifest__.py b/base_jsonify/__manifest__.py index c3cbcec87..33c626d4c 100644 --- a/base_jsonify/__manifest__.py +++ b/base_jsonify/__manifest__.py @@ -1,23 +1,19 @@ # -*- coding: utf-8 -*- -# © 2017 Akretion (http://www.akretion.com) +# Copyright 2017-2018 Akretion (http://www.akretion.com) # Sébastien BEAU # Raphaël Reverdy # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "Base Jsonify", - "summary": "Base module that provide the jsonify method on all object", + "summary": "Base module that provide the jsonify method on all models", "version": "10.0.1.0.0", "category": "Uncategorized", - "website": "https://odoo-community.org/", + "website": "https://github.com/OCA/server-tools", "author": "Akretion, Odoo Community Association (OCA)", "license": "AGPL-3", "application": False, "installable": True, - "external_dependencies": { - "python": [], - "bin": [], - }, "depends": [ "base", ], diff --git a/base_jsonify/models/ir_export.py b/base_jsonify/models/ir_export.py index feae5cddf..4e71c1d7c 100644 --- a/base_jsonify/models/ir_export.py +++ b/base_jsonify/models/ir_export.py @@ -8,6 +8,14 @@ from odoo import api, models def update_dict(data, fields): + """ + Contruct a tree of fields. + ie: { + "name": True, + "resource": True, + } + Order of keys is important. + """ field = fields[0] if len(fields) == 1: if field == '.id': @@ -20,6 +28,11 @@ def update_dict(data, fields): def convert_dict(dict_parser): + """ + Converts the dict returned by update_dict to a list consistent with the + Odoo API. The list is composed of strings (field names or aliases) or + tuples. + """ parser = [] for field, value in dict_parser.iteritems(): if value is True: @@ -34,6 +47,10 @@ class IrExport(models.Model): @api.multi def get_json_parser(self): + """ + Creates a parser from a ir_exports record and returns it. This parser + can then be used to "jsonify" records of the ir_export's model. + """ self.ensure_one() dict_parser = OrderedDict() for line in self.export_fields: @@ -41,4 +58,5 @@ class IrExport(models.Model): if line.alias: names = line.alias.split('/') update_dict(dict_parser, names) + return convert_dict(dict_parser) diff --git a/base_jsonify/models/models.py b/base_jsonify/models/models.py index 7a2df40cb..3fd8b9815 100644 --- a/base_jsonify/models/models.py +++ b/base_jsonify/models/models.py @@ -15,6 +15,9 @@ class Base(models.AbstractModel): @api.model def __parse_field(self, parser_field): + """ + Deducts how to handle a field from its parser + """ field_name = parser_field subparser = None if isinstance(parser_field, tuple): @@ -36,7 +39,7 @@ class Base(models.AbstractModel): ('line_id', ['id', ('product_id', ['name']), 'price_unit']) ] - In order to be consitent with the odoo api the jsonify method always + In order to be consistent with the odoo api the jsonify method always return a list of object even if there is only one element in input By default the key into the json is the name of the field extracted diff --git a/base_jsonify/readme/DESCRIPTION.rst b/base_jsonify/readme/DESCRIPTION.rst index 25c62fbb3..ff92efef6 100644 --- a/base_jsonify/readme/DESCRIPTION.rst +++ b/base_jsonify/readme/DESCRIPTION.rst @@ -1,5 +1,6 @@ -This module add the jsonify method to the ORM. This method take as argument -the browse record and the "parser" that specify the field to extract. +This module adds a 'jsonify' method to every model of the ORM. +It works on the current recordset and requires a single argument 'parser' +that specify the field to extract. Example of parser: From d139173ae5f808f5786901d07d5cdbbf439140b1 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 13 Dec 2018 08:15:53 +0000 Subject: [PATCH 12/15] [UPD] README.rst --- base_jsonify/README.rst | 5 +- base_jsonify/static/description/index.html | 57 +++++++++++++++------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/base_jsonify/README.rst b/base_jsonify/README.rst index 65ffe69ef..7d5542ec6 100644 --- a/base_jsonify/README.rst +++ b/base_jsonify/README.rst @@ -25,8 +25,9 @@ Base Jsonify |badge1| |badge2| |badge3| |badge4| |badge5| -This module add the jsonify method to the ORM. This method take as argument -the browse record and the "parser" that specify the field to extract. +This module adds a 'jsonify' method to every model of the ORM. +It works on the current recordset and requires a single argument 'parser' +that specify the field to extract. Example of parser: diff --git a/base_jsonify/static/description/index.html b/base_jsonify/static/description/index.html index a4065b092..7efb46853 100644 --- a/base_jsonify/static/description/index.html +++ b/base_jsonify/static/description/index.html @@ -3,13 +3,13 @@ - + Base Jsonify