Browse Source

Merge pull request #1472 from simahawk/12-base_jsonify

[12.0][MIG] base_jsonify
pull/1533/head
beau sebastien 6 years ago
committed by GitHub
parent
commit
7d39972782
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 117
      base_jsonify/README.rst
  2. 1
      base_jsonify/__init__.py
  3. 25
      base_jsonify/__manifest__.py
  4. 7
      base_jsonify/demo/export_demo.xml
  5. 16
      base_jsonify/demo/ir.exports.line.csv
  6. 74
      base_jsonify/i18n/base_jsonify.pot
  7. 3
      base_jsonify/models/__init__.py
  8. 63
      base_jsonify/models/ir_export.py
  9. 34
      base_jsonify/models/ir_exports_line.py
  10. 76
      base_jsonify/models/models.py
  11. 3
      base_jsonify/readme/CONTRIBUTORS.rst
  12. 43
      base_jsonify/readme/DESCRIPTION.rst
  13. 454
      base_jsonify/static/description/index.html
  14. 2
      base_jsonify/tests/__init__.py
  15. 111
      base_jsonify/tests/test_get_parser.py
  16. 44
      base_jsonify/tests/test_ir_exports_line.py
  17. 38
      base_jsonify/views/ir_exports_view.xml

117
base_jsonify/README.rst

@ -0,0 +1,117 @@
============
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 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:
.. 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
**Table of contents**
.. contents::
:local:
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-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 <https://github.com/OCA/server-tools/issues/new?body=module:%20base_jsonify%0Aversion:%2010.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Akretion
Contributors
~~~~~~~~~~~~
* BEAU Sébastien <sebastien.beau@akretion.com>
* Raphaël Reverdy <raphael.reverdy@akretion.com>
* Laurent Mignon <laurent.mignon@acsone.eu>
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
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 <https://github.com/OCA/server-tools/tree/10.0/base_jsonify>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

1
base_jsonify/__init__.py

@ -0,0 +1 @@
from . import models

25
base_jsonify/__manifest__.py

@ -0,0 +1,25 @@
# Copyright 2017-2018 Akretion (http://www.akretion.com)
# Sébastien BEAU <sebastien.beau@akretion.com>
# Raphaël Reverdy <raphael.reverdy@akretion.com>
# 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 models",
"version": "12.0.1.0.0",
"category": "Uncategorized",
"website": "https://github.com/OCA/server-tools",
"author": "Akretion, Odoo Community Association (OCA)",
"license": "AGPL-3",
"installable": True,
"depends": [
"base",
],
"data": [
'views/ir_exports_view.xml',
],
"demo": [
'demo/export_demo.xml',
'demo/ir.exports.line.csv',
],
}

7
base_jsonify/demo/export_demo.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="ir_exp_partner" model="ir.exports">
<field name="name">Partner Export</field>
<field name="resource">res.partner</field>
</record>
</odoo>

16
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

74
base_jsonify/i18n/base_jsonify.pot

@ -0,0 +1,74 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * base_jsonify
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: base_jsonify
#: model:ir.model.fields,field_description:base_jsonify.field_ir_exports_line_alias
msgid "Alias"
msgstr ""
#. module: base_jsonify
#: model:ir.ui.view,arch_db:base_jsonify.view_ir_exports
msgid "Configuration"
msgstr ""
#. module: base_jsonify
#: model:ir.actions.act_window,name:base_jsonify.act_ui_exports_view
#: model:ir.ui.menu,name:base_jsonify.ui_exports
msgid "Export Fields"
msgstr ""
#. module: base_jsonify
#: model:ir.ui.view,arch_db:base_jsonify.view_ir_exports
msgid "Index"
msgstr ""
#. module: base_jsonify
#: code:addons/base_jsonify/models/ir_exports_line.py:28
#, python-format
msgid "Name and Alias must have the same hierarchy depth"
msgstr ""
#. module: base_jsonify
#: code:addons/base_jsonify/models/ir_exports_line.py:33
#, python-format
msgid "The alias must reference the same field as in name '%s' not in '%s'"
msgstr ""
#. module: base_jsonify
#: model:ir.model.fields,help:base_jsonify.field_ir_exports_line_alias
msgid "The complete path to the field where you can specify an alias on the a step as field:alias"
msgstr ""
#. module: base_jsonify
#: code:addons/base_jsonify/models/models.py:71
#, python-format
msgid "Wrong parser configuration"
msgstr ""
#. module: base_jsonify
#: model:ir.model,name:base_jsonify.model_base
msgid "base"
msgstr ""
#. module: base_jsonify
#: model:ir.model,name:base_jsonify.model_ir_exports
msgid "ir.exports"
msgstr ""
#. module: base_jsonify
#: model:ir.model,name:base_jsonify.model_ir_exports_line
msgid "ir.exports.line"
msgstr ""

3
base_jsonify/models/__init__.py

@ -0,0 +1,3 @@
from . import models
from . import ir_export
from . import ir_exports_line

63
base_jsonify/models/ir_export.py

@ -0,0 +1,63 @@
# © 2017 Akretion (http://www.akretion.com)
# Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from collections import OrderedDict
from odoo import api, models
def update_dict(data, fields):
"""Contruct a tree of fields.
Example:
{
"name": True,
"resource": True,
}
Order of keys is important.
"""
field = fields[0]
if len(fields) == 1:
if field == '.id':
field = 'id'
data[field] = True
else:
if field not in data:
data[field] = OrderedDict()
update_dict(data[field], fields[1:])
def convert_dict(dict_parser):
"""Convert dict returned by update_dict to list consistent w/ Odoo API.
The list is composed of strings (field names or aliases) or tuples.
"""
parser = []
for field, value in dict_parser.items():
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):
"""Creates a parser from ir.exports record and return it.
The final parser can be used to "jsonify" records of ir.export's model.
"""
self.ensure_one()
dict_parser = OrderedDict()
for line in self.export_fields:
names = line.name.split('/')
if line.alias:
names = line.alias.split('/')
update_dict(dict_parser, names)
return convert_dict(dict_parser)

34
base_jsonify/models/ir_exports_line.py

@ -0,0 +1,34 @@
# Copyright 2017 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.exceptions import ValidationError
from odoo 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)
)

76
base_jsonify/models/models.py

@ -0,0 +1,76 @@
# © 2017 Akretion (http://www.akretion.com)
# Sébastien BEAU <sebastien.beau@akretion.com>
# Raphaël Reverdy <raphael.reverdy@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, models
from odoo.exceptions import UserError
from odoo.tools.translate import _
class Base(models.AbstractModel):
_inherit = 'base'
@api.model
def __parse_field(self, parser_field):
"""Deduct how to handle a field from its parser."""
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 given parser.
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 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
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'
]
"""
result = []
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:
value = rec[field_name]
if value is False and field_type != 'boolean':
value = None
res[json_key] = value
result.append(res)
return result

3
base_jsonify/readme/CONTRIBUTORS.rst

@ -0,0 +1,3 @@
* BEAU Sébastien <sebastien.beau@akretion.com>
* Raphaël Reverdy <raphael.reverdy@akretion.com>
* Laurent Mignon <laurent.mignon@acsone.eu>

43
base_jsonify/readme/DESCRIPTION.rst

@ -0,0 +1,43 @@
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:
.. 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.

454
base_jsonify/static/description/index.html

@ -0,0 +1,454 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" />
<title>Base Jsonify</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="base-jsonify">
<h1 class="title">Base Jsonify</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/server-tools/tree/10.0/base_jsonify"><img alt="OCA/server-tools" src="https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/server-tools-10-0/server-tools-10-0-base_jsonify"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/149/10.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>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.</p>
<p>Example of parser:</p>
<pre class="code python literal-block">
<span class="n">parser</span> <span class="o">=</span> <span class="p">[</span>
<span class="s1">'name'</span><span class="p">,</span>
<span class="s1">'number'</span><span class="p">,</span>
<span class="s1">'create_date'</span><span class="p">,</span>
<span class="p">(</span><span class="s1">'partner_id'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'id'</span><span class="p">,</span> <span class="s1">'display_name'</span><span class="p">,</span> <span class="s1">'ref'</span><span class="p">])</span>
<span class="p">(</span><span class="s1">'line_id'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'id'</span><span class="p">,</span> <span class="p">(</span><span class="s1">'product_id'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'name'</span><span class="p">]),</span> <span class="s1">'price_unit'</span><span class="p">])</span>
<span class="p">]</span>
</pre>
<p>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</p>
<p>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:</p>
<pre class="code python literal-block">
<span class="n">parser</span> <span class="o">=</span> <span class="p">[</span>
<span class="s1">'field_name:json_key'</span>
<span class="p">]</span>
</pre>
<pre class="code python literal-block">
<span class="n">parser</span> <span class="o">=</span> <span class="p">[</span>
<span class="s1">'name'</span><span class="p">,</span>
<span class="s1">'number'</span><span class="p">,</span>
<span class="s1">'create_date:creationDate'</span><span class="p">,</span>
<span class="p">(</span><span class="s1">'partner_id:partners'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'id'</span><span class="p">,</span> <span class="s1">'display_name'</span><span class="p">,</span> <span class="s1">'ref'</span><span class="p">])</span>
<span class="p">(</span><span class="s1">'line_id:lines'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'id'</span><span class="p">,</span> <span class="p">(</span><span class="s1">'product_id'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'name'</span><span class="p">]),</span> <span class="s1">'price_unit'</span><span class="p">])</span>
<span class="p">]</span>
</pre>
<p>Also the module provide a method “get_json_parser” on the ir.exports object
that generate a parser from an ir.exports configuration</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/server-tools/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/server-tools/issues/new?body=module:%20base_jsonify%0Aversion:%2010.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id2">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id3">Authors</a></h2>
<ul class="simple">
<li>Akretion</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
<ul class="simple">
<li>BEAU Sébastien &lt;<a class="reference external" href="mailto:sebastien.beau&#64;akretion.com">sebastien.beau&#64;akretion.com</a>&gt;</li>
<li>Raphaël Reverdy &lt;<a class="reference external" href="mailto:raphael.reverdy&#64;akretion.com">raphael.reverdy&#64;akretion.com</a>&gt;</li>
<li>Laurent Mignon &lt;<a class="reference external" href="mailto:laurent.mignon&#64;acsone.eu">laurent.mignon&#64;acsone.eu</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/server-tools/tree/10.0/base_jsonify">OCA/server-tools</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

2
base_jsonify/tests/__init__.py

@ -0,0 +1,2 @@
from . import test_get_parser
from . import test_ir_exports_line

111
base_jsonify/tests/test_get_parser.py

@ -0,0 +1,111 @@
# Copyright 2017 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
class TestParser(TransactionCase):
def test_getting_parser(self):
expected_parser = [
'active',
('category_id', ['name']),
('child_ids', [(
'child_ids', ['name']),
('country_id', ['code', 'name']),
'email', 'id',
'name'
]),
'color',
'comment',
('country_id', ['code', 'name']),
'credit_limit',
'lang',
'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] = ('category_id:category', ['name'])
parser = exporter.get_json_parser()
self.assertEqual(parser, expected_parser)
def test_json_export(self):
parser = [
'lang',
'comment',
'credit_limit',
'name',
'color',
('child_ids:children', [
('child_ids:children', ['name']),
'email',
('country_id:country', ['code', 'name']),
'name',
'id',
]),
('country_id:country', ['code', 'name']),
'active',
('category_id', ['name'])
]
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 = {
'lang': 'en_US',
'comment': None,
'credit_limit': 0.0,
'name': 'Akretion',
'color': 0,
'country': {
'code': 'FR',
'name': 'France'
},
'active': True,
'category_id': [
{'name': 'Inovator'}
],
'children': [{
'id': partner.child_ids.id,
'country': {
'code': 'FR',
'name': 'France'
},
'children': [],
'name': 'Sebatien Beau',
'email': None
}]
}
json_partner = partner.jsonify(parser)
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)

44
base_jsonify/tests/test_ir_exports_line.py

@ -0,0 +1,44 @@
# Copyright 2017 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.exceptions import ValidationError
from odoo.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)

38
base_jsonify/views/ir_exports_view.xml

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record model="ir.ui.view" id="view_ir_exports">
<field name="model">ir.exports</field>
<field name="priority">50</field>
<field name="arch" type="xml">
<form>
<sheet>
<group name="se" string="Configuration">
<group colspan="4" col="4" name="se-main">
<field name="name"/>
<field name="resource"/>
</group>
</group>
<group name="index" string="Index">
<field name="export_fields" nolabel="1">
<tree editable="bottom">
<field name="name"/>
<field name="alias"/>
</tree>
</field>
</group>
</sheet>
</form>
</field>
</record>
<record id="act_ui_exports_view" model="ir.actions.act_window">
<field name="name">Export Fields</field>
<field name="res_model">ir.exports</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="ui_exports" action="act_ui_exports_view"
parent="base.next_id_2"/>
</odoo>
Loading…
Cancel
Save