Steps to reproduce:
- install sale_management module;
- go to settings of sale_management and check "Automatic invoice" parameter;
- in debug mode, we can see the template selected (do not change it);
- save the settings;
(This is just one example)
Issue:
The parameter is not added to the "ir_config_parameter" table.
Cause:
The improvement which consists in comparing the settings which one wishes to record with those which already exist in order to set the parameters which are different creates a problem.
Indeed, the current settings are retrieved directly from the model with their default value if there is one.
These are the values that will be used for the comparison.
Because of this, when we want to save a parameter which is set to its default value (on first save), the logic will not notice a difference.
Therefore, the parameter will not be saved in the "ir_config_parameter" table.
Consequence:
In the code, when we wanted to look up the value of a parameter, if it is not saved, we use its default value instead of saving it with its default value.
Example:
```
field_example = fields.Integer(string='Example', default=1000, config_parameter='model.field_example')
value_field_example = params.get_param('model.field_example', default=1000)
```
The default value is repeated.
Solution:
To know whether or not we add a new parameter in the "ir_config_parameter" table, we must look at what already exists in the table and not in the settings defined in the model.
opw-3057306
closes odoo/odoo#106188
X-original-commit: d881dfaaa163b409a94494e35afa2cbda7cf2aa2
Related: odoo/enterprise#34258
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
332 lines
9.5 KiB
Python
332 lines
9.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import division
|
|
|
|
from itertools import count, zip_longest
|
|
|
|
from odoo import api, fields, models, Command
|
|
|
|
class A(models.Model):
|
|
_name = 'test_testing_utilities.a'
|
|
_description = 'Testing Utilities A'
|
|
|
|
f1 = fields.Char(required=True)
|
|
f2 = fields.Integer(default=42)
|
|
f3 = fields.Integer()
|
|
f4 = fields.Integer(compute='_compute_f4')
|
|
f5 = fields.Integer()
|
|
f6 = fields.Integer()
|
|
|
|
@api.onchange('f2')
|
|
def _on_change_f2(self):
|
|
self.f3 = int(self.f2 / 2)
|
|
self.f5 = self.f2
|
|
self.f6 = self.f2
|
|
|
|
@api.depends('f1', 'f2')
|
|
def _compute_f4(self):
|
|
for r in self:
|
|
r.f4 = r.f2 / (int(r.f1) or 1)
|
|
|
|
class B(models.Model):
|
|
_name = 'test_testing_utilities.readonly'
|
|
_description = 'Testing Utilities Readonly'
|
|
|
|
f1 = fields.Integer(default=1, readonly=True)
|
|
f2 = fields.Integer(compute='_compute_f2')
|
|
|
|
@api.depends('f1')
|
|
def _compute_f2(self):
|
|
for r in self:
|
|
r.f2 = 2 * r.f1
|
|
|
|
class C(models.Model):
|
|
_name = 'test_testing_utilities.c'
|
|
_description = 'Testing Utilities C'
|
|
|
|
name = fields.Char("name", required=True)
|
|
f2 = fields.Many2one('test_testing_utilities.m2o')
|
|
|
|
@api.onchange('f2')
|
|
def _on_change_f2(self):
|
|
self.name = self.f2.name
|
|
|
|
class M2O(models.Model):
|
|
_name = 'test_testing_utilities.m2o'
|
|
_description = 'Testing Utilities Many To One'
|
|
|
|
name = fields.Char(required=True)
|
|
|
|
class M2Onchange(models.Model):
|
|
_name = 'test_testing_utilities.d'
|
|
_description = 'Testing Utilities D'
|
|
|
|
# used to check that defaults & onchange to m2o work
|
|
f = fields.Many2one(
|
|
'test_testing_utilities.m2o',
|
|
required=True,
|
|
default=lambda self: self.env['test_testing_utilities.m2o'].search(
|
|
[], limit=1
|
|
)
|
|
)
|
|
f2 = fields.Char()
|
|
|
|
@api.onchange('f2')
|
|
def _on_change_f2(self):
|
|
self.f = self.env['test_testing_utilities.m2o'].search([
|
|
('name', 'ilike', self.f2),
|
|
], limit=1) if self.f2 else False
|
|
|
|
class M2MChange(models.Model):
|
|
_name = 'test_testing_utilities.e'
|
|
_description = 'Testing Utilities E'
|
|
|
|
m2m = fields.Many2many('test_testing_utilities.sub2')
|
|
count = fields.Integer(compute='_m2m_count', inverse='_set_count')
|
|
|
|
@api.depends('m2m')
|
|
def _m2m_count(self):
|
|
for r in self:
|
|
r.count = len(r.m2m)
|
|
|
|
def _set_count(self):
|
|
for r in self:
|
|
r.write({
|
|
'm2m': [
|
|
Command.create({'name': str(n)})
|
|
for n, v in zip_longest(range(r.count), r.m2m or [])
|
|
if v is None
|
|
]
|
|
})
|
|
|
|
class M2MSub(models.Model):
|
|
_name = 'test_testing_utilities.sub2'
|
|
_description = 'Testing Utilities Subtraction 2'
|
|
|
|
name = fields.Char()
|
|
m2o_ids = fields.Many2many('test_testing_utilities.m2o')
|
|
|
|
class M2MChange2(models.Model):
|
|
_name = 'test_testing_utilities.f'
|
|
_description = 'Testing Utilities F'
|
|
|
|
def _get_some(self):
|
|
r = self.env['test_testing_utilities.sub2'].search([], limit=2)
|
|
return r
|
|
|
|
m2m = fields.Many2many(
|
|
'test_testing_utilities.sub2',
|
|
default=_get_some,
|
|
)
|
|
m2o = fields.Many2one('test_testing_utilities.sub2')
|
|
|
|
@api.onchange('m2o')
|
|
def _on_change_m2o(self):
|
|
self.m2m = self.m2m | self.m2o
|
|
|
|
class M2MReadonly(models.Model):
|
|
_name = 'test_testing_utilities.g'
|
|
_description = 'Testing Utilities G'
|
|
|
|
m2m = fields.Many2many('test_testing_utilities.sub3', readonly=True)
|
|
|
|
class M2MSub3(models.Model):
|
|
_name = 'test_testing_utilities.sub3'
|
|
_description = 'Testing Utilities Subtraction 3'
|
|
|
|
name = fields.Char()
|
|
|
|
class O2MChange(models.Model):
|
|
_name = 'test_testing_utilities.parent'
|
|
_description = 'Testing Utilities Parent'
|
|
|
|
value = fields.Integer(default=1)
|
|
v = fields.Integer()
|
|
subs = fields.One2many('test_testing_utilities.sub', 'parent_id')
|
|
|
|
@api.onchange('value', 'subs')
|
|
def _onchange_values(self):
|
|
self.v = self.value + sum(s.value for s in self.subs)
|
|
|
|
class O2MSub(models.Model):
|
|
_name = 'test_testing_utilities.sub'
|
|
_description = 'Testing Utilities Subtraction'
|
|
|
|
name = fields.Char(compute='_compute_name')
|
|
value = fields.Integer(default=2)
|
|
v = fields.Integer()
|
|
parent_id = fields.Many2one('test_testing_utilities.parent')
|
|
has_parent = fields.Boolean()
|
|
|
|
@api.onchange('value')
|
|
def _onchange_value(self):
|
|
self.v = self.value
|
|
|
|
@api.depends('v')
|
|
def _compute_name(self):
|
|
for r in self:
|
|
r.name = str(r.v)
|
|
|
|
@api.onchange('has_parent')
|
|
def _onchange_has_parent(self):
|
|
if self.has_parent:
|
|
self.value = self.parent_id.value
|
|
|
|
class O2MDefault(models.Model):
|
|
_name = 'test_testing_utilities.default'
|
|
_description = 'Testing Utilities Default'
|
|
|
|
def _default_subs(self):
|
|
return [
|
|
Command.create({'v': 5})
|
|
]
|
|
value = fields.Integer(default=1)
|
|
v = fields.Integer()
|
|
subs = fields.One2many('test_testing_utilities.sub3', 'parent_id', default=_default_subs)
|
|
|
|
class O2MSub3(models.Model):
|
|
_name = 'test_testing_utilities.sub3'
|
|
_description = 'Testing Utilities Subtraction 3'
|
|
|
|
name = fields.Char(compute='_compute_name')
|
|
value = fields.Integer(default=2)
|
|
v = fields.Integer(default=6)
|
|
parent_id = fields.Many2one('test_testing_utilities.default')
|
|
|
|
@api.onchange('value')
|
|
def _onchange_value(self):
|
|
self.v = self.value
|
|
|
|
@api.depends('v')
|
|
def _compute_name(self):
|
|
for r in self:
|
|
r.name = str(r.v)
|
|
|
|
|
|
class O2MRecursive(models.Model):
|
|
_name = _description = 'test_testing_utilities.recursive'
|
|
|
|
one_to_many_id = fields.Many2one('test_testing_utilities.recursive', readonly=True)
|
|
many_to_one_ids = fields.One2many('test_testing_utilities.recursive', 'one_to_many_id', readonly=True)
|
|
|
|
|
|
class O2MOnchangeParent(models.Model):
|
|
_name = 'test_testing_utilities.onchange_parent'
|
|
_description = 'Testing Utilities Onchange Parent'
|
|
|
|
line_ids = fields.One2many('test_testing_utilities.onchange_line', 'parent')
|
|
|
|
@api.onchange('line_ids')
|
|
def _onchange_line_ids(self):
|
|
for line in self.line_ids.filtered(lambda l: l.flag):
|
|
self.env['test_testing_utilities.onchange_line'].new({'parent': self.id})
|
|
|
|
|
|
class M2OOnchangeLine(models.Model):
|
|
_name = 'test_testing_utilities.onchange_line'
|
|
_description = 'Testing Utilities Onchange Line'
|
|
|
|
parent = fields.Many2one('test_testing_utilities.onchange_parent')
|
|
dummy = fields.Float()
|
|
flag = fields.Boolean(store=False)
|
|
|
|
@api.onchange('dummy')
|
|
def _onchange_flag(self):
|
|
self.flag = True
|
|
|
|
class O2MChangeCount(models.Model):
|
|
_name = 'test_testing_utilities.onchange_count'
|
|
_description = _name
|
|
|
|
count = fields.Integer()
|
|
line_ids = fields.One2many('test_testing_utilities.onchange_count_sub', 'parent')
|
|
|
|
@api.onchange('count')
|
|
def _onchange_count(self):
|
|
Sub = self.env['test_testing_utilities.onchange_count_sub']
|
|
recs = Sub
|
|
for i in range(self.count):
|
|
recs |= Sub.new({'name': str(i)})
|
|
self.line_ids = recs
|
|
|
|
class O2MChangeSub(models.Model):
|
|
_name = 'test_testing_utilities.onchange_count_sub'
|
|
_description = _name
|
|
|
|
parent = fields.Many2one('test_testing_utilities.onchange_count')
|
|
name = fields.Char()
|
|
|
|
class O2MReadonlySubfield(models.Model):
|
|
_name = 'o2m_readonly_subfield_parent'
|
|
_description = _name
|
|
|
|
line_ids = fields.One2many('o2m_readonly_subfield_child', 'parent_id')
|
|
|
|
class O2MReadonlySubfieldChild(models.Model):
|
|
_name = _description = 'o2m_readonly_subfield_child'
|
|
|
|
name = fields.Char()
|
|
parent_id = fields.Many2one('o2m_readonly_subfield_parent')
|
|
f = fields.Integer(compute='_compute_f', inverse='_inverse_f', readonly=True)
|
|
|
|
@api.depends('name')
|
|
def _compute_f(self):
|
|
for r in self:
|
|
r.f = len(r.name) if r.name else 0
|
|
|
|
def _inverse_f(self):
|
|
raise AssertionError("Inverse of f should not be called")
|
|
|
|
class ReqBool(models.Model):
|
|
_name = _description = 'test_testing_utilities.req_bool'
|
|
|
|
f_bool = fields.Boolean(required=True)
|
|
|
|
class O2MChangesParent(models.Model):
|
|
_name = _description = 'o2m_changes_parent'
|
|
|
|
name = fields.Char()
|
|
line_ids = fields.One2many('o2m_changes_children', 'parent_id')
|
|
|
|
@api.onchange('name')
|
|
def _onchange_name(self):
|
|
for line in self.line_ids:
|
|
line.line_ids = [Command.delete(l.id) for l in line.line_ids] + [
|
|
Command.create({'v': 0, 'vv': 0})
|
|
]
|
|
|
|
class O2MChangesChildren(models.Model):
|
|
_name = _description = 'o2m_changes_children'
|
|
|
|
name = fields.Char()
|
|
v = fields.Integer()
|
|
line_ids = fields.One2many('o2m_changes_children.lines', 'parent_id')
|
|
parent_id = fields.Many2one('o2m_changes_parent')
|
|
|
|
@api.onchange('v')
|
|
def _onchange_v(self):
|
|
for record in self:
|
|
for line in record.line_ids:
|
|
line.v = record.v
|
|
|
|
class O2MChangesChildrenLines(models.Model):
|
|
_name = _description = 'o2m_changes_children.lines'
|
|
|
|
parent_id = fields.Many2one('o2m_changes_children')
|
|
v = fields.Integer()
|
|
vv = fields.Integer()
|
|
|
|
class ResConfigTest(models.Model):
|
|
_inherit = 'res.config.settings'
|
|
|
|
_name = 'res.config.test'
|
|
_description = 'Config test'
|
|
|
|
param1 = fields.Integer(
|
|
string='Test parameter 1',
|
|
config_parameter='resConfigTest.parameter1',
|
|
default=1000)
|
|
|
|
param2 = fields.Many2one(
|
|
'res.config',
|
|
config_parameter="resConfigTest.parameter2")
|