mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-18 17:31:59 +02:00
Initial commit: OCA Technical packages (595 packages)
This commit is contained in:
commit
2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions
|
|
@ -0,0 +1,5 @@
|
|||
from . import test_changeset_flow
|
||||
from . import test_changeset_field_type
|
||||
from . import test_changeset_origin
|
||||
from . import test_changeset_field_rule
|
||||
from . import test_changeset_security
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
# Copyright 2015-2017 Camptocamp SA
|
||||
# Copyright 2020 Onestein (<https://www.onestein.eu>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
|
||||
class ChangesetTestCommon(object):
|
||||
def assert_changeset(self, record, expected_source, expected_changes):
|
||||
"""Check if a changeset has been created according to expected values
|
||||
|
||||
The record should have no prior changeset than the one created in the
|
||||
test (so it has exactly 1 changeset).
|
||||
|
||||
The expected changes are tuples with (field, origin_value,
|
||||
new_value, state)
|
||||
|
||||
:param record: record of record having a changeset
|
||||
:param expected_changes: contains tuples with the changes
|
||||
:type expected_changes: list(tuple))
|
||||
"""
|
||||
changeset = self.env["record.changeset"].search(
|
||||
[("model", "=", record._name), ("res_id", "=", record.id)]
|
||||
)
|
||||
self.assertEqual(
|
||||
len(changeset), 1, "1 changeset expected, got {}".format(changeset)
|
||||
)
|
||||
self.assertEqual(changeset.source, expected_source)
|
||||
changes = changeset.change_ids
|
||||
missing = []
|
||||
for expected_change in expected_changes:
|
||||
for change in changes:
|
||||
if (
|
||||
change.field_id,
|
||||
change.get_origin_value(),
|
||||
change.get_new_value(),
|
||||
change.state,
|
||||
) == expected_change:
|
||||
changes -= change
|
||||
break
|
||||
else:
|
||||
missing.append(expected_change)
|
||||
message = ""
|
||||
for field, origin_value, new_value, state in missing:
|
||||
message += (
|
||||
"- field: '%s', origin_value: '%s', "
|
||||
"new_value: '%s', state: '%s'\n"
|
||||
% (field.name, origin_value, new_value, state)
|
||||
)
|
||||
for change in changes:
|
||||
message += (
|
||||
"+ field: '%s', origin_value: '%s', "
|
||||
"new_value: '%s', state: '%s'\n"
|
||||
% (
|
||||
change.field_id.name,
|
||||
change.get_origin_value(),
|
||||
change.get_new_value(),
|
||||
change.state,
|
||||
)
|
||||
)
|
||||
if message:
|
||||
raise AssertionError("Changes do not match\n\n:%s" % message)
|
||||
|
||||
def _create_changeset(self, record, changes):
|
||||
"""Create a changeset and its associated changes
|
||||
|
||||
:param record: 'record' record
|
||||
:param changes: list of changes [(field, new value, state)]
|
||||
:returns: 'record.changeset' record
|
||||
"""
|
||||
ChangesetChange = self.env["record.changeset.change"]
|
||||
get_field = ChangesetChange.get_field_for_type
|
||||
change_values = []
|
||||
for field, value, state in changes:
|
||||
change = {
|
||||
"field_id": field.id,
|
||||
# write in the field of the appropriate type for the
|
||||
# origin field (char, many2one, ...)
|
||||
get_field(field, "new"): value,
|
||||
"state": state,
|
||||
}
|
||||
change_values.append((0, 0, change))
|
||||
values = {
|
||||
"model": record._name,
|
||||
"res_id": record.id,
|
||||
"change_ids": change_values,
|
||||
}
|
||||
return self.env["record.changeset"].create(values)
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
# Copyright 2015-2017 Camptocamp SA
|
||||
# Copyright 2020 Onestein (<https://www.onestein.eu>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestChangesetFieldRule(common.TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.company_model_id = cls.env.ref("base.model_res_company").id
|
||||
cls.field_name = cls.env.ref("base.field_res_partner__name")
|
||||
cls.field_street = cls.env.ref("base.field_res_partner__street")
|
||||
|
||||
def test_get_rules(self):
|
||||
ChangesetFieldRule = self.env["changeset.field.rule"]
|
||||
ChangesetFieldRule.search([]).unlink()
|
||||
rule1 = ChangesetFieldRule.create(
|
||||
{"field_id": self.field_name.id, "action": "validate"}
|
||||
)
|
||||
rule2 = ChangesetFieldRule.create(
|
||||
{"field_id": self.field_street.id, "action": "never"}
|
||||
)
|
||||
get_rules = ChangesetFieldRule.get_rules(None, "res.partner")
|
||||
self.assertEqual(get_rules, {"name": rule1, "street": rule2})
|
||||
|
||||
def test_get_rules_source(self):
|
||||
ChangesetFieldRule = self.env["changeset.field.rule"]
|
||||
ChangesetFieldRule.search([]).unlink()
|
||||
rule1 = ChangesetFieldRule.create(
|
||||
{"field_id": self.field_name.id, "action": "validate"}
|
||||
)
|
||||
rule2 = ChangesetFieldRule.create(
|
||||
{"field_id": self.field_street.id, "action": "never"}
|
||||
)
|
||||
rule3 = ChangesetFieldRule.create(
|
||||
{
|
||||
"source_model_id": self.company_model_id,
|
||||
"field_id": self.field_street.id,
|
||||
"action": "never",
|
||||
}
|
||||
)
|
||||
model = ChangesetFieldRule
|
||||
rules = model.get_rules(None, "res.partner")
|
||||
self.assertEqual(rules, {"name": rule1, "street": rule2})
|
||||
rules = model.get_rules("res.company", "res.partner")
|
||||
self.assertEqual(rules, {"name": rule1, "street": rule3})
|
||||
|
||||
def test_get_rules_cache(self):
|
||||
ChangesetFieldRule = self.env["changeset.field.rule"]
|
||||
ChangesetFieldRule.search([]).unlink()
|
||||
rule = ChangesetFieldRule.create(
|
||||
{"field_id": self.field_name.id, "action": "validate"}
|
||||
)
|
||||
self.assertEqual(
|
||||
ChangesetFieldRule.get_rules(None, "res.partner")["name"].action, "validate"
|
||||
)
|
||||
# Write on cursor to bypass the cache invalidation for the
|
||||
# matter of the test
|
||||
self.env.cr.execute(
|
||||
"UPDATE changeset_field_rule " "SET action = 'never' " "WHERE id = %s",
|
||||
(rule.id,),
|
||||
)
|
||||
self.assertEqual(
|
||||
ChangesetFieldRule.get_rules(None, "res.partner")["name"].action, "validate"
|
||||
)
|
||||
rule.action = "auto"
|
||||
self.assertEqual(
|
||||
ChangesetFieldRule.get_rules(None, "res.partner")["name"].action, "auto"
|
||||
)
|
||||
rule.unlink()
|
||||
self.assertFalse(ChangesetFieldRule.get_rules(None, "res.partner"))
|
||||
|
|
@ -0,0 +1,301 @@
|
|||
# Copyright 2015-2017 Camptocamp SA
|
||||
# Copyright 2020 Onestein (<https://www.onestein.eu>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from markupsafe import Markup
|
||||
|
||||
from odoo import fields
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
from ..models.base import disable_changeset
|
||||
from .common import ChangesetTestCommon
|
||||
|
||||
|
||||
class TestChangesetFieldType(ChangesetTestCommon, TransactionCase):
|
||||
"""Check that changeset changes are stored expectingly to their types"""
|
||||
|
||||
@classmethod
|
||||
def _setup_rules(cls):
|
||||
ChangesetFieldRule = cls.env["changeset.field.rule"]
|
||||
ChangesetFieldRule.search([]).unlink()
|
||||
fields = (
|
||||
("char", "ref"),
|
||||
("text", "comment"),
|
||||
("boolean", "is_company"),
|
||||
("date", "date"),
|
||||
("integer", "color"),
|
||||
("float", "partner_latitude"),
|
||||
("selection", "type"),
|
||||
("many2one", "country_id"),
|
||||
("many2many", "category_id"),
|
||||
("one2many", "user_ids"),
|
||||
("binary", "image_1920"),
|
||||
)
|
||||
for field_type, field in fields:
|
||||
attr_name = "field_%s" % field_type
|
||||
field_record = cls.env["ir.model.fields"].search(
|
||||
[("model", "=", "res.partner"), ("name", "=", field)]
|
||||
)
|
||||
cls.assertTrue(field_record, "Field %s not available" % field)
|
||||
# set attribute such as 'self.field_char' is a
|
||||
# ir.model.fields record of the field res_partner.ref
|
||||
setattr(cls, attr_name, field_record)
|
||||
ChangesetFieldRule.create(
|
||||
{"field_id": field_record.id, "action": "validate"}
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls._setup_rules()
|
||||
cls.partner = cls.env["res.partner"].create(
|
||||
{"name": "Original Name", "street": "Original Street"}
|
||||
)
|
||||
# Add context for this test for compatibility with other modules' tests
|
||||
cls.partner = cls.partner.with_context(test_record_changeset=True)
|
||||
|
||||
def test_new_changeset_char(self):
|
||||
"""Add a new changeset on a Char field"""
|
||||
self.partner.write({self.field_char.name: "New value"})
|
||||
self.assert_changeset(
|
||||
self.partner,
|
||||
self.env.user,
|
||||
[
|
||||
(
|
||||
self.field_char,
|
||||
self.partner[self.field_char.name],
|
||||
"New value",
|
||||
"draft",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def test_new_changeset_text(self):
|
||||
"""Add a new changeset on a Text field"""
|
||||
self.partner.write({self.field_text.name: "New comment\non 2 lines"})
|
||||
self.assert_changeset(
|
||||
self.partner,
|
||||
self.env.user,
|
||||
[
|
||||
(
|
||||
self.field_text,
|
||||
self.partner[self.field_text.name],
|
||||
"New comment\non 2 lines",
|
||||
"draft",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def test_new_changeset_boolean(self):
|
||||
"""Add a new changeset on a Boolean field"""
|
||||
# ensure the changeset has to change the value
|
||||
self.partner.with_context(__no_changeset=disable_changeset).write(
|
||||
{self.field_boolean.name: False}
|
||||
)
|
||||
|
||||
self.partner.write({self.field_boolean.name: True})
|
||||
self.assert_changeset(
|
||||
self.partner,
|
||||
self.env.user,
|
||||
[
|
||||
(
|
||||
self.field_boolean,
|
||||
self.partner[self.field_boolean.name],
|
||||
True,
|
||||
"draft",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def test_new_changeset_date(self):
|
||||
"""Add a new changeset on a Date field"""
|
||||
self.partner.write({self.field_date.name: "2015-09-15"})
|
||||
self.assert_changeset(
|
||||
self.partner,
|
||||
self.env.user,
|
||||
[
|
||||
(
|
||||
self.field_date,
|
||||
self.partner[self.field_date.name],
|
||||
fields.Date.from_string("2015-09-15"),
|
||||
"draft",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def test_new_changeset_integer(self):
|
||||
"""Add a new changeset on a Integer field"""
|
||||
self.partner.write({self.field_integer.name: 42})
|
||||
self.assert_changeset(
|
||||
self.partner,
|
||||
self.env.user,
|
||||
[(self.field_integer, self.partner[self.field_integer.name], 42, "draft")],
|
||||
)
|
||||
|
||||
def test_new_changeset_float(self):
|
||||
"""Add a new changeset on a Float field"""
|
||||
self.partner.write({self.field_float.name: 3.1415})
|
||||
self.assert_changeset(
|
||||
self.partner,
|
||||
self.env.user,
|
||||
[(self.field_float, self.partner[self.field_float.name], 3.1415, "draft")],
|
||||
)
|
||||
|
||||
def test_new_changeset_selection(self):
|
||||
"""Add a new changeset on a Selection field"""
|
||||
self.partner.write({self.field_selection.name: "delivery"})
|
||||
self.assert_changeset(
|
||||
self.partner,
|
||||
self.env.user,
|
||||
[
|
||||
(
|
||||
self.field_selection,
|
||||
self.partner[self.field_selection.name],
|
||||
"delivery",
|
||||
"draft",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def test_new_changeset_many2one(self):
|
||||
"""Add a new changeset on a Many2one field"""
|
||||
self.partner.with_context(__no_changeset=disable_changeset).write(
|
||||
{self.field_many2one.name: self.env.ref("base.fr").id}
|
||||
)
|
||||
self.partner.write({self.field_many2one.name: self.env.ref("base.ch").id})
|
||||
self.assert_changeset(
|
||||
self.partner,
|
||||
self.env.user,
|
||||
[
|
||||
(
|
||||
self.field_many2one,
|
||||
self.partner[self.field_many2one.name],
|
||||
self.env.ref("base.ch"),
|
||||
"draft",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def test_new_changeset_many2many(self):
|
||||
"""Add a new changeset on a Many2many field is not supported"""
|
||||
with self.assertRaises(NotImplementedError):
|
||||
self.partner.write(
|
||||
{self.field_many2many.name: [self.env.ref("base.ch").id]}
|
||||
)
|
||||
|
||||
def test_new_changeset_one2many(self):
|
||||
"""Add a new changeset on a One2many field is not supported"""
|
||||
with self.assertRaises(NotImplementedError):
|
||||
self.partner.write(
|
||||
{self.field_one2many.name: [self.env.ref("base.user_root").id]}
|
||||
)
|
||||
|
||||
def test_new_changeset_binary(self):
|
||||
"""Add a new changeset on a Binary field is not supported"""
|
||||
with self.assertRaises(NotImplementedError):
|
||||
self.partner.write({self.field_binary.name: "xyz"})
|
||||
|
||||
def test_apply_char(self):
|
||||
"""Apply a change on a Char field"""
|
||||
changes = [(self.field_char, "New Ref", "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
changeset.change_ids.apply()
|
||||
self.assertEqual(self.partner[self.field_char.name], "New Ref")
|
||||
|
||||
def test_apply_text(self):
|
||||
"""Apply a change on a Text field"""
|
||||
changes = [(self.field_text, "New comment\non 2 lines", "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
changeset.change_ids.apply()
|
||||
self.assertEqual(
|
||||
self.partner[self.field_text.name], Markup("<p>New comment\non 2 lines</p>")
|
||||
)
|
||||
|
||||
def test_apply_boolean(self):
|
||||
"""Apply a change on a Boolean field"""
|
||||
# ensure the changeset has to change the value
|
||||
self.partner.write({self.field_boolean.name: False})
|
||||
|
||||
changes = [(self.field_boolean, True, "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
changeset.change_ids.apply()
|
||||
self.assertEqual(self.partner[self.field_boolean.name], True)
|
||||
|
||||
# Cannot do this while it is on the same transaction. The cache may not
|
||||
# be updated
|
||||
# changes = [(self.field_boolean, False, 'draft')]
|
||||
# changeset = self._create_changeset(self.partner, changes)
|
||||
# changeset.change_ids.apply()
|
||||
# self.assertEqual(self.partner[self.field_boolean.name], False)
|
||||
|
||||
def test_apply_date(self):
|
||||
"""Apply a change on a Date field"""
|
||||
changes = [(self.field_date, "2015-09-15", "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
changeset.change_ids.apply()
|
||||
self.assertAlmostEqual(
|
||||
self.partner[self.field_date.name], fields.Date.from_string("2015-09-15")
|
||||
)
|
||||
|
||||
def test_apply_integer(self):
|
||||
"""Apply a change on a Integer field"""
|
||||
changes = [(self.field_integer, 42, "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
changeset.change_ids.apply()
|
||||
self.assertAlmostEqual(self.partner[self.field_integer.name], 42)
|
||||
|
||||
def test_apply_float(self):
|
||||
"""Apply a change on a Float field"""
|
||||
changes = [(self.field_float, 52.47, "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
changeset.change_ids.apply()
|
||||
self.assertAlmostEqual(self.partner[self.field_float.name], 52.47)
|
||||
|
||||
def test_apply_selection(self):
|
||||
"""Apply a change on a Selection field"""
|
||||
changes = [(self.field_selection, "delivery", "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
changeset.change_ids.apply()
|
||||
self.assertAlmostEqual(self.partner[self.field_selection.name], "delivery")
|
||||
|
||||
def test_apply_many2one(self):
|
||||
"""Apply a change on a Many2one field"""
|
||||
self.partner.with_context(__no_changeset=disable_changeset).write(
|
||||
{self.field_many2one.name: self.env.ref("base.fr").id}
|
||||
)
|
||||
changes = [
|
||||
(
|
||||
self.field_many2one,
|
||||
"res.country,%d" % self.env.ref("base.ch").id,
|
||||
"draft",
|
||||
)
|
||||
]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
changeset.change_ids.apply()
|
||||
self.assertEqual(
|
||||
self.partner[self.field_many2one.name], self.env.ref("base.ch")
|
||||
)
|
||||
|
||||
def test_apply_many2many(self):
|
||||
"""Apply a change on a Many2many field is not supported"""
|
||||
changes = [(self.field_many2many, self.env.ref("base.ch").id, "draft")]
|
||||
with self.assertRaises(NotImplementedError):
|
||||
self._create_changeset(self.partner, changes)
|
||||
|
||||
def test_apply_one2many(self):
|
||||
"""Apply a change on a One2many field is not supported"""
|
||||
changes = [
|
||||
(
|
||||
self.field_one2many,
|
||||
[self.env.ref("base.user_root").id, self.env.ref("base.user_demo").id],
|
||||
"draft",
|
||||
)
|
||||
]
|
||||
with self.assertRaises(NotImplementedError):
|
||||
self._create_changeset(self.partner, changes)
|
||||
|
||||
def test_apply_binary(self):
|
||||
"""Apply a change on a Binary field is not supported"""
|
||||
changes = [(self.field_one2many, "", "draft")]
|
||||
with self.assertRaises(NotImplementedError):
|
||||
self._create_changeset(self.partner, changes)
|
||||
|
|
@ -0,0 +1,485 @@
|
|||
# Copyright 2015-2017 Camptocamp SA
|
||||
# Copyright 2020 Onestein (<https://www.onestein.eu>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from odoo import fields
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
from ..models.base import disable_changeset
|
||||
from .common import ChangesetTestCommon
|
||||
|
||||
|
||||
class TestChangesetFlow(ChangesetTestCommon, TransactionCase):
|
||||
"""Check how changeset are generated and applied based on the rules.
|
||||
|
||||
We do not really care about the types of the fields in this test
|
||||
suite, so we only use 'char' fields. We have to ensure that the
|
||||
general changeset flows work as expected, that is:
|
||||
|
||||
* create a changeset when a manual/system write is made on partner
|
||||
* create a changeset according to the changeset rules when a source model
|
||||
is specified
|
||||
* apply a changeset change writes the value on the partner
|
||||
* apply a whole changeset writes all the changes' values on the partner
|
||||
* changes in state 'cancel' or 'done' do not write on the partner
|
||||
* when all the changes are either 'cancel' or 'done', the changeset
|
||||
becomes 'done'
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def _setup_rules(cls):
|
||||
ChangesetFieldRule = cls.env["changeset.field.rule"]
|
||||
ChangesetFieldRule.search([]).unlink()
|
||||
cls.field_name = cls.env.ref("base.field_res_partner__name")
|
||||
cls.field_street = cls.env.ref("base.field_res_partner__street")
|
||||
cls.field_street2 = cls.env.ref("base.field_res_partner__street2")
|
||||
ChangesetFieldRule.create({"field_id": cls.field_name.id, "action": "auto"})
|
||||
ChangesetFieldRule.create(
|
||||
{"field_id": cls.field_street.id, "action": "validate"}
|
||||
)
|
||||
ChangesetFieldRule.create({"field_id": cls.field_street2.id, "action": "never"})
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls._setup_rules()
|
||||
cls.demo_user = cls.env.ref("base.user_demo")
|
||||
cls.partner = (
|
||||
cls.env["res.partner"]
|
||||
.with_user(cls.demo_user)
|
||||
.create({"name": "X", "street": "street X", "street2": "street2 X"})
|
||||
)
|
||||
# Add context for this test for compatibility with other modules' tests
|
||||
cls.partner = cls.partner.with_context(test_record_changeset=True)
|
||||
|
||||
def test_get_view(self):
|
||||
"""For privileged users, the smart button is present on the form"""
|
||||
view = self.env.ref("base.view_partner_form")
|
||||
|
||||
def get_nodes(user):
|
||||
arch = etree.XML(
|
||||
self.env["res.partner"]
|
||||
.with_user(user)
|
||||
.get_view(view_id=view.id)["arch"]
|
||||
)
|
||||
return len(
|
||||
arch.xpath(
|
||||
"//div[@name='button_box']"
|
||||
"/button[@name='action_record_changeset_change_view']"
|
||||
)
|
||||
)
|
||||
|
||||
self.assertTrue(get_nodes(self.env.ref("base.user_admin")))
|
||||
self.assertFalse(get_nodes(self.env.ref("base.user_demo")))
|
||||
|
||||
def test_new_changeset(self):
|
||||
"""Add a new changeset on a partner
|
||||
|
||||
A new changeset is created when we write on a partner
|
||||
"""
|
||||
self.partner.write({"name": "Y", "street": "street Y", "street2": "street2 Y"})
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
self.assertEqual(self.partner.count_pending_changeset_changes, 1)
|
||||
self.assert_changeset(
|
||||
self.partner,
|
||||
self.demo_user,
|
||||
[
|
||||
(self.field_name, "X", "Y", "done"),
|
||||
(self.field_street, "street X", "street Y", "draft"),
|
||||
(self.field_street2, "street2 X", "street2 Y", "cancel"),
|
||||
],
|
||||
)
|
||||
self.assertEqual(self.partner.name, "Y")
|
||||
self.assertEqual(self.partner.street, "street X")
|
||||
self.assertEqual(self.partner.street2, "street2 X")
|
||||
# Pending Changes widget can be rendered for the unprivileged user
|
||||
self.env.invalidate_all()
|
||||
self.env["record.changeset.change"].with_user(
|
||||
self.demo_user
|
||||
).get_changeset_changes_by_field(self.partner._name, self.partner.id)
|
||||
|
||||
def test_create_new_changeset(self):
|
||||
"""Create a new partner with a changeset"""
|
||||
new = (
|
||||
self.env["res.partner"]
|
||||
.with_context(test_record_changeset=True)
|
||||
.create(
|
||||
{
|
||||
"name": "partner",
|
||||
"street": "street",
|
||||
"street2": "street2",
|
||||
}
|
||||
)
|
||||
)
|
||||
new._compute_changeset_ids()
|
||||
new._compute_count_pending_changesets()
|
||||
self.assertEqual(new.count_pending_changesets, 1)
|
||||
self.assert_changeset(
|
||||
new,
|
||||
self.env.user,
|
||||
[
|
||||
(self.field_name, False, "partner", "done"),
|
||||
(self.field_street, False, "street", "draft"),
|
||||
(self.field_street2, False, "street2", "cancel"),
|
||||
],
|
||||
)
|
||||
self.assertEqual(new.name, "partner")
|
||||
self.assertFalse(new.street)
|
||||
self.assertFalse(new.street2)
|
||||
|
||||
def test_create_new_changeset_empty_value(self):
|
||||
"""No change is created for empty values on create"""
|
||||
new = (
|
||||
self.env["res.partner"]
|
||||
.with_context(test_record_changeset=True)
|
||||
.create(
|
||||
{
|
||||
"name": "partner",
|
||||
"street": "street",
|
||||
"street2": False,
|
||||
}
|
||||
)
|
||||
)
|
||||
new._compute_changeset_ids()
|
||||
new._compute_count_pending_changesets()
|
||||
self.assertEqual(new.count_pending_changesets, 1)
|
||||
self.assert_changeset(
|
||||
new,
|
||||
self.env.user,
|
||||
[
|
||||
(self.field_name, False, "partner", "done"),
|
||||
(self.field_street, False, "street", "draft"),
|
||||
],
|
||||
)
|
||||
self.assertEqual(new.name, "partner")
|
||||
self.assertFalse(new.street)
|
||||
self.assertFalse(new.street2)
|
||||
|
||||
def test_new_changeset_empty_value(self):
|
||||
"""Create a changeset change that empty a value"""
|
||||
self.partner.write({"street": False})
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
self.assert_changeset(
|
||||
self.partner,
|
||||
self.demo_user,
|
||||
[(self.field_street, "street X", False, "draft")],
|
||||
)
|
||||
|
||||
def test_no_changeset_empty_value_both_sides(self):
|
||||
"""No changeset created when both sides have an empty value"""
|
||||
# we have to ensure that even if we write '' to a False field, we won't
|
||||
# write a changeset
|
||||
self.partner.with_context(__no_changeset=disable_changeset).write(
|
||||
{"street": False}
|
||||
)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.partner.write({"street": ""})
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertFalse(self.partner.changeset_ids)
|
||||
|
||||
def test_apply_change(self):
|
||||
"""Apply a changeset change on a partner"""
|
||||
changes = [(self.field_name, "Y", "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
for change in changeset.change_ids:
|
||||
change.get_changeset_changes_by_field(changeset.model, changeset.res_id)
|
||||
changeset.change_ids.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(self.partner.name, "Y")
|
||||
self.assertEqual(changeset.change_ids.state, "done")
|
||||
# All computed fields are assigned
|
||||
changeset.change_ids.read()
|
||||
|
||||
def test_apply_change_with_prevent_self_validation(self):
|
||||
"""Don't apply a changeset change and prevent self validation"""
|
||||
self.partner.write({"street": "street Z"})
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
self.assertEqual(self.partner.count_pending_changeset_changes, 1)
|
||||
self.partner.changeset_ids.change_ids.rule_id.prevent_self_validation = True
|
||||
with self.assertRaises(
|
||||
UserError, msg="You don't have the rights to reject the changes."
|
||||
):
|
||||
self.partner.changeset_ids.change_ids.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
self.assertEqual(self.partner.count_pending_changeset_changes, 1)
|
||||
self.assertEqual(self.partner.street, "street X")
|
||||
self.assertEqual(self.partner.changeset_ids.change_ids.state, "draft")
|
||||
|
||||
# Copy the user to have another user with similar rights, so that
|
||||
# self validation prevention doesn't kick in.
|
||||
other_demo_user = self.demo_user.copy()
|
||||
other_demo_user.groups_id += self.env.ref("base_changeset.group_changeset_user")
|
||||
self.partner.changeset_ids.change_ids.with_user(other_demo_user).apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(self.partner.count_pending_changeset_changes, 0)
|
||||
self.assertEqual(self.partner.street, "street Z")
|
||||
self.assertEqual(self.partner.changeset_ids.change_ids.state, "done")
|
||||
|
||||
def test_apply_done_change(self):
|
||||
"""Done changes do not apply (already applied)"""
|
||||
changes = [(self.field_name, "Y", "done")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
with self.assertRaises(UserError):
|
||||
changeset.change_ids.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(self.partner.name, "X")
|
||||
changeset.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(self.partner.name, "X")
|
||||
|
||||
def test_apply_cancel_change(self):
|
||||
"""Cancel changes do not apply"""
|
||||
changes = [(self.field_name, "Y", "cancel")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
with self.assertRaises(UserError):
|
||||
changeset.change_ids.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(self.partner.name, "X")
|
||||
changeset.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(self.partner.name, "X")
|
||||
|
||||
def test_apply_empty_value(self):
|
||||
"""Apply a change that empty a value"""
|
||||
changes = [(self.field_street, False, "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
for change in changeset.change_ids:
|
||||
change.get_changeset_changes_by_field(changeset.model, changeset.res_id)
|
||||
changeset.change_ids.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertFalse(self.partner.street)
|
||||
|
||||
def test_apply_change_loop(self):
|
||||
"""Test multiple changes"""
|
||||
changes = [
|
||||
(self.field_name, "Y", "draft"),
|
||||
(self.field_street, "street Y", "draft"),
|
||||
(self.field_street2, "street2 Y", "draft"),
|
||||
]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
for change in changeset.change_ids:
|
||||
change.get_changeset_changes_by_field(changeset.model, changeset.res_id)
|
||||
changeset.change_ids.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(self.partner.name, "Y")
|
||||
self.assertEqual(self.partner.street, "street Y")
|
||||
self.assertEqual(self.partner.street2, "street2 Y")
|
||||
|
||||
def test_apply(self):
|
||||
"""Apply a full changeset on a partner"""
|
||||
changes = [
|
||||
(self.field_name, "Y", "draft"),
|
||||
(self.field_street, "street Y", "draft"),
|
||||
(self.field_street2, "street2 Y", "draft"),
|
||||
]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
self.assertEqual(self.partner.count_pending_changeset_changes, 3)
|
||||
for change in changeset.change_ids:
|
||||
change.get_changeset_changes_by_field(changeset.model, changeset.res_id)
|
||||
changeset.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(self.partner.count_pending_changeset_changes, 0)
|
||||
self.assertEqual(self.partner.name, "Y")
|
||||
self.assertEqual(self.partner.street, "street Y")
|
||||
self.assertEqual(self.partner.street2, "street2 Y")
|
||||
|
||||
def test_changeset_state_on_done(self):
|
||||
"""Check that changeset state becomes done when changes are done"""
|
||||
changes = [(self.field_name, "Y", "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
self.assertEqual(changeset.state, "draft")
|
||||
changeset.change_ids.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(changeset.state, "done")
|
||||
|
||||
def test_changeset_state_on_cancel(self):
|
||||
"""Check that rev. state becomes done when changes are canceled"""
|
||||
changes = [(self.field_name, "Y", "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
self.assertEqual(changeset.state, "draft")
|
||||
changeset.change_ids.cancel()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(changeset.state, "done")
|
||||
|
||||
def test_changeset_state(self):
|
||||
"""Check that changeset state becomes done with multiple changes"""
|
||||
changes = [
|
||||
(self.field_name, "Y", "draft"),
|
||||
(self.field_street, "street Y", "draft"),
|
||||
(self.field_street2, "street2 Y", "draft"),
|
||||
]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
self.assertEqual(self.partner.count_pending_changeset_changes, 3)
|
||||
self.assertEqual(changeset.state, "draft")
|
||||
changeset.apply()
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
self.assertEqual(self.partner.count_pending_changeset_changes, 0)
|
||||
self.assertEqual(changeset.state, "done")
|
||||
|
||||
def test_apply_changeset_with_other_pending(self):
|
||||
"""Error when applying when previous pending changesets exist"""
|
||||
changes = [(self.field_name, "Y", "draft")]
|
||||
old_changeset = self._create_changeset(self.partner, changes)
|
||||
# if the date is the same, both changeset can be applied
|
||||
to_string = fields.Datetime.to_string
|
||||
old_changeset.date = to_string(datetime.now() - timedelta(days=1))
|
||||
changes = [(self.field_name, "Z", "draft")]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
with self.assertRaises(UserError):
|
||||
changeset.change_ids.with_context(
|
||||
require_previous_changesets_done=True
|
||||
).apply()
|
||||
changeset.change_ids.apply()
|
||||
|
||||
def test_apply_different_changesets(self):
|
||||
"""Apply different changesets at once"""
|
||||
partner2 = self.env["res.partner"].create({"name": "P2"})
|
||||
changes = [
|
||||
(self.field_name, "Y", "draft"),
|
||||
(self.field_street, "street Y", "draft"),
|
||||
(self.field_street2, "street2 Y", "draft"),
|
||||
]
|
||||
changeset = self._create_changeset(self.partner, changes)
|
||||
self.partner._compute_changeset_ids()
|
||||
self.partner._compute_count_pending_changesets()
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
self.assertEqual(self.partner.count_pending_changeset_changes, 3)
|
||||
for change in changeset.change_ids:
|
||||
change.get_changeset_changes_by_field(changeset.model, changeset.res_id)
|
||||
changeset2 = self._create_changeset(partner2, changes)
|
||||
partner2._compute_changeset_ids()
|
||||
partner2._compute_count_pending_changesets()
|
||||
self.assertEqual(changeset.state, "draft")
|
||||
self.assertEqual(changeset2.state, "draft")
|
||||
self.assertEqual(partner2.count_pending_changesets, 1)
|
||||
self.assertEqual(partner2.count_pending_changeset_changes, 3)
|
||||
for change in changeset2.change_ids:
|
||||
change.get_changeset_changes_by_field(changeset2.model, changeset2.res_id)
|
||||
(changeset + changeset2).apply()
|
||||
self.assertEqual(self.partner.name, "Y")
|
||||
self.assertEqual(self.partner.street, "street Y")
|
||||
self.assertEqual(self.partner.street2, "street2 Y")
|
||||
self.assertEqual(partner2.name, "Y")
|
||||
self.assertEqual(partner2.street, "street Y")
|
||||
self.assertEqual(partner2.street2, "street2 Y")
|
||||
self.assertEqual(changeset.state, "done")
|
||||
self.assertEqual(changeset2.state, "done")
|
||||
|
||||
def test_new_changeset_source(self):
|
||||
"""Source is the user who made the change"""
|
||||
self.partner.write({"street": False})
|
||||
self.partner._compute_changeset_ids()
|
||||
changeset = self.partner.changeset_ids
|
||||
self.assertEqual(changeset.source, self.demo_user)
|
||||
|
||||
def test_new_changeset_source_other_model(self):
|
||||
"""Define source from another model"""
|
||||
company = self.env.ref("base.main_company")
|
||||
keys = {
|
||||
"force_changeset_for_partners": True,
|
||||
"__changeset_rules_source_model": "res.company",
|
||||
"__changeset_rules_source_id": company.id,
|
||||
}
|
||||
self.partner.with_context(**keys).write({"street": False})
|
||||
self.partner._compute_changeset_ids()
|
||||
changeset = self.partner.changeset_ids
|
||||
self.assertEqual(changeset.source, company)
|
||||
|
||||
def test_name_get(self):
|
||||
"""Test the name_get of a changeset for a model without name field"""
|
||||
self.env["changeset.field.rule"].create(
|
||||
{
|
||||
"field_id": self.env.ref("base.field_res_partner_bank__active").id,
|
||||
"action": "validate",
|
||||
}
|
||||
)
|
||||
bank = self.env.ref("base.bank_partner_demo").with_context(
|
||||
test_record_changeset=True
|
||||
)
|
||||
bank.active = False
|
||||
self.assertTrue(bank.changeset_ids)
|
||||
self.assertIn(bank.acc_number, bank.changeset_ids.name_get()[0][1])
|
||||
|
||||
def test_new_changeset_expression(self):
|
||||
"""Test that rules can be conditional"""
|
||||
self.env["changeset.field.rule"].search(
|
||||
[
|
||||
("field_id", "=", self.field_street.id),
|
||||
]
|
||||
).expression = "object.street != 'street X'"
|
||||
self.partner.street = "street Y"
|
||||
self.partner.invalidate_recordset()
|
||||
self.assertEqual(self.partner.street, "street Y")
|
||||
self.assertFalse(self.partner.changeset_ids)
|
||||
self.partner.street = "street Z"
|
||||
self.partner.invalidate_recordset()
|
||||
self.assertTrue(self.partner.changeset_ids)
|
||||
self.assertEqual(self.partner.street, "street Y")
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
# Copyright 2015-2017 Camptocamp SA
|
||||
# Copyright 2020 Onestein (<https://www.onestein.eu>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo.tests.common import Form, TransactionCase
|
||||
|
||||
from ..models.base import disable_changeset
|
||||
from .common import ChangesetTestCommon
|
||||
|
||||
|
||||
class TestChangesetOrigin(ChangesetTestCommon, TransactionCase):
|
||||
"""Check that origin - old fields are stored as expected.
|
||||
|
||||
'origin' fields dynamically read fields from the partner when the state
|
||||
of the change is 'draft'. Once a change becomes 'done' or 'cancel', the
|
||||
'old' field copies the value from the partner and then the 'origin' field
|
||||
displays the 'old' value.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def _setup_rules(cls):
|
||||
ChangesetFieldRule = cls.env["changeset.field.rule"]
|
||||
ChangesetFieldRule.search([]).unlink()
|
||||
cls.field_name = cls.env.ref("base.field_res_partner__name")
|
||||
ChangesetFieldRule.create({"field_id": cls.field_name.id, "action": "validate"})
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls._setup_rules()
|
||||
cls.partner = cls.env["res.partner"].create({"name": "X"})
|
||||
# Add context for this test for compatibility with other modules' tests
|
||||
cls.partner = cls.partner.with_context(test_record_changeset=True)
|
||||
|
||||
def test_origin_value_of_change_with_apply(self):
|
||||
"""Origin field is read from the parter or 'old' - with apply
|
||||
|
||||
According to the state of the change.
|
||||
"""
|
||||
with Form(self.partner) as partner_form:
|
||||
partner_form.name = "Y"
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
changeset = self.partner.changeset_ids
|
||||
change = changeset.change_ids
|
||||
self.assertEqual(self.partner.name, "X")
|
||||
self.assertEqual(change.origin_value_char, "X")
|
||||
self.assertEqual(change.origin_value_display, "X")
|
||||
with Form(
|
||||
self.partner.with_context(__no_changeset=disable_changeset)
|
||||
) as partner_form:
|
||||
partner_form.name = "A"
|
||||
self.assertEqual(change.origin_value_char, "A")
|
||||
self.assertEqual(change.origin_value_display, "A")
|
||||
change.apply()
|
||||
self.assertEqual(change.origin_value_char, "A")
|
||||
self.assertEqual(change.origin_value_display, "A")
|
||||
with Form(
|
||||
self.partner.with_context(__no_changeset=disable_changeset)
|
||||
) as partner_form:
|
||||
partner_form.name = "B"
|
||||
self.assertEqual(change.origin_value_char, "A")
|
||||
self.assertEqual(change.origin_value_display, "A")
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
|
||||
def test_origin_value_of_change_with_cancel(self):
|
||||
"""Origin field is read from the parter or 'old' - with cancel
|
||||
|
||||
According to the state of the change.
|
||||
"""
|
||||
with Form(self.partner) as partner_form:
|
||||
partner_form.name = "Y"
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
changeset = self.partner.changeset_ids
|
||||
change = changeset.change_ids
|
||||
self.assertEqual(self.partner.name, "X")
|
||||
self.assertEqual(change.origin_value_char, "X")
|
||||
self.assertEqual(change.origin_value_display, "X")
|
||||
with Form(
|
||||
self.partner.with_context(__no_changeset=disable_changeset)
|
||||
) as partner_form:
|
||||
partner_form.name = "A"
|
||||
self.assertEqual(change.origin_value_char, "A")
|
||||
self.assertEqual(change.origin_value_display, "A")
|
||||
change.cancel()
|
||||
self.assertEqual(change.origin_value_char, "A")
|
||||
self.assertEqual(change.origin_value_display, "A")
|
||||
with Form(
|
||||
self.partner.with_context(__no_changeset=disable_changeset)
|
||||
) as partner_form:
|
||||
partner_form.name = "B"
|
||||
self.assertEqual(change.origin_value_char, "A")
|
||||
self.assertEqual(change.origin_value_display, "A")
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
|
||||
def test_old_field_of_change_with_apply(self):
|
||||
"""Old field is stored when the change is applied"""
|
||||
with Form(self.partner) as partner_form:
|
||||
partner_form.name = "Y"
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
changeset = self.partner.changeset_ids
|
||||
change = changeset.change_ids
|
||||
self.assertEqual(self.partner.name, "X")
|
||||
self.assertFalse(change.old_value_char)
|
||||
with Form(
|
||||
self.partner.with_context(__no_changeset=disable_changeset)
|
||||
) as partner_form:
|
||||
partner_form.name = "A"
|
||||
self.assertFalse(change.old_value_char)
|
||||
change.apply()
|
||||
self.assertEqual(change.old_value_char, "A")
|
||||
with Form(
|
||||
self.partner.with_context(__no_changeset=disable_changeset)
|
||||
) as partner_form:
|
||||
partner_form.name = "B"
|
||||
self.assertEqual(change.old_value_char, "A")
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
|
||||
def test_old_field_of_change_with_cancel(self):
|
||||
"""Old field is stored when the change is canceled"""
|
||||
with Form(self.partner) as partner_form:
|
||||
partner_form.name = "Y"
|
||||
self.assertEqual(self.partner.count_pending_changesets, 1)
|
||||
changeset = self.partner.changeset_ids
|
||||
change = changeset.change_ids
|
||||
self.assertEqual(self.partner.name, "X")
|
||||
self.assertFalse(change.old_value_char)
|
||||
with Form(
|
||||
self.partner.with_context(__no_changeset=disable_changeset)
|
||||
) as partner_form:
|
||||
partner_form.name = "A"
|
||||
self.assertFalse(change.old_value_char)
|
||||
change.cancel()
|
||||
self.assertEqual(change.old_value_char, "A")
|
||||
with Form(
|
||||
self.partner.with_context(__no_changeset=disable_changeset)
|
||||
) as partner_form:
|
||||
partner_form.name = "B"
|
||||
self.assertEqual(change.old_value_char, "A")
|
||||
self.assertEqual(self.partner.count_pending_changesets, 0)
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright 2021 Hunki Enterprises BV (<https://hunki-enterprises.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
from .common import ChangesetTestCommon
|
||||
|
||||
|
||||
class TestChangesetFlow(ChangesetTestCommon, TransactionCase):
|
||||
"""Check that changesets don't leak information"""
|
||||
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
super().setUpClass()
|
||||
cls.env["changeset.field.rule"].search([]).unlink()
|
||||
cls.rule = cls.env["changeset.field.rule"].create(
|
||||
{
|
||||
"model_id": cls.env.ref("base.model_ir_config_parameter").id,
|
||||
"field_id": cls.env.ref("base.field_ir_config_parameter__key").id,
|
||||
"action": "auto",
|
||||
}
|
||||
)
|
||||
|
||||
def test_change_unprivileged_user(self):
|
||||
"""
|
||||
Check that unprivileged users can't see changesets they didn't create
|
||||
"""
|
||||
user = self.env.ref("base.user_demo")
|
||||
self.env["ir.config_parameter"].with_context(
|
||||
test_record_changeset=True,
|
||||
).set_param("hello", "world")
|
||||
changeset = self.env["record.changeset.change"].search(
|
||||
[
|
||||
("rule_id", "=", self.rule.id),
|
||||
]
|
||||
)
|
||||
self.assertTrue(changeset)
|
||||
self.assertFalse(changeset.with_user(user).search([("id", "=", changeset.id)]))
|
||||
Loading…
Add table
Add a link
Reference in a new issue