You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
9.9 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. #
  4. # Authors: Guewen Baconnier
  5. # Copyright 2015 Camptocamp SA
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU Affero General Public License as
  9. # published by the Free Software Foundation, either version 3 of the
  10. # License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Affero General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. #
  21. from datetime import datetime, timedelta
  22. from openerp import fields, exceptions
  23. from openerp.tests import common
  24. from .common import ChangesetMixin
  25. class TestChangesetFlow(ChangesetMixin, common.TransactionCase):
  26. """ Check how changeset are generated and applied based on the rules.
  27. We do not really care about the types of the fields in this test
  28. suite, so we only use 'char' fields. We have to ensure that the
  29. general changeset flows work as expected, that is:
  30. * create a 'done' changeset when a manual/system write is made on partner
  31. * create a changeset according to the changeset rules when the key
  32. '__changeset_rules' is passed in the context
  33. * apply a changeset change writes the value on the partner
  34. * apply a whole changeset writes all the changes' values on the partner
  35. * changes in state 'cancel' or 'done' do not write on the partner
  36. * when all the changes are either 'cancel' or 'done', the changeset
  37. becomes 'done'
  38. """
  39. def _setup_rules(self):
  40. ChangesetFieldRule = self.env['changeset.field.rule']
  41. partner_model_id = self.env.ref('base.model_res_partner').id
  42. self.field_name = self.env.ref('base.field_res_partner_name')
  43. self.field_street = self.env.ref('base.field_res_partner_street')
  44. self.field_street2 = self.env.ref('base.field_res_partner_street2')
  45. ChangesetFieldRule.create({
  46. 'model_id': partner_model_id,
  47. 'field_id': self.field_name.id,
  48. 'action': 'auto',
  49. })
  50. ChangesetFieldRule.create({
  51. 'model_id': partner_model_id,
  52. 'field_id': self.field_street.id,
  53. 'action': 'validate',
  54. })
  55. ChangesetFieldRule.create({
  56. 'model_id': partner_model_id,
  57. 'field_id': self.field_street2.id,
  58. 'action': 'never',
  59. })
  60. def setUp(self):
  61. super(TestChangesetFlow, self).setUp()
  62. self._setup_rules()
  63. self.partner = self.env['res.partner'].create({
  64. 'name': 'X',
  65. 'street': 'street X',
  66. 'street2': 'street2 X',
  67. })
  68. def test_new_changeset(self):
  69. """ Add a new changeset on a partner
  70. A new changeset is created when we write on a partner with
  71. ``__changeset_rules`` in the context.
  72. """
  73. self.partner.with_context(__changeset_rules=True).write({
  74. 'name': 'Y',
  75. 'street': 'street Y',
  76. 'street2': 'street2 Y',
  77. })
  78. self.assert_changeset(
  79. self.partner,
  80. [(self.field_name, 'X', 'Y', 'done'),
  81. (self.field_street, 'street X', 'street Y', 'draft'),
  82. (self.field_street2, 'street2 X', 'street2 Y', 'cancel'),
  83. ],
  84. )
  85. self.assertEqual(self.partner.name, 'Y')
  86. self.assertEqual(self.partner.street, 'street X')
  87. self.assertEqual(self.partner.street2, 'street2 X')
  88. def test_new_changeset_empty_value(self):
  89. """ Create a changeset change that empty a value """
  90. self.partner.with_context(__changeset_rules=True).write({
  91. 'street': False,
  92. })
  93. self.assert_changeset(
  94. self.partner,
  95. [(self.field_street, 'street X', False, 'draft')]
  96. )
  97. def test_manual_edition(self):
  98. """ A manual edition of a partner should always be applied
  99. But should create a 'done' changeset
  100. """
  101. self.partner.write({
  102. 'name': 'Y',
  103. 'street': 'street Y',
  104. 'street2': 'street2 Y',
  105. })
  106. self.assert_changeset(
  107. self.partner,
  108. [(self.field_name, 'X', 'Y', 'done'),
  109. (self.field_street, 'street X', 'street Y', 'done'),
  110. (self.field_street2, 'street2 X', 'street2 Y', 'done'),
  111. ],
  112. )
  113. self.assertEqual(self.partner.name, 'Y')
  114. self.assertEqual(self.partner.street, 'street Y')
  115. self.assertEqual(self.partner.street2, 'street2 Y')
  116. def test_apply_change(self):
  117. """ Apply a changeset change on a partner """
  118. changes = [
  119. (self.field_name, 'Y', 'draft'),
  120. ]
  121. changeset = self._create_changeset(self.partner, changes)
  122. changeset.change_ids.apply()
  123. self.assertEqual(self.partner.name, 'Y')
  124. self.assertEqual(changeset.change_ids.state, 'done')
  125. def test_apply_done_change(self):
  126. """ Done changes do not apply (already applied) """
  127. changes = [
  128. (self.field_name, 'Y', 'done'),
  129. ]
  130. changeset = self._create_changeset(self.partner, changes)
  131. changeset.change_ids.apply()
  132. self.assertEqual(self.partner.name, 'X')
  133. def test_apply_cancel_change(self):
  134. """ Cancel changes do not apply """
  135. changes = [
  136. (self.field_name, 'Y', 'cancel'),
  137. ]
  138. changeset = self._create_changeset(self.partner, changes)
  139. changeset.change_ids.apply()
  140. self.assertEqual(self.partner.name, 'X')
  141. def test_apply_empty_value(self):
  142. """ Apply a change that empty a value """
  143. changes = [
  144. (self.field_street, False, 'draft'),
  145. ]
  146. changeset = self._create_changeset(self.partner, changes)
  147. changeset.change_ids.apply()
  148. self.assertFalse(self.partner.street)
  149. def test_apply_change_loop(self):
  150. """ Test @api.multi on the changes """
  151. changes = [
  152. (self.field_name, 'Y', 'draft'),
  153. (self.field_street, 'street Y', 'draft'),
  154. (self.field_street2, 'street2 Y', 'draft'),
  155. ]
  156. changeset = self._create_changeset(self.partner, changes)
  157. changeset.change_ids.apply()
  158. self.assertEqual(self.partner.name, 'Y')
  159. self.assertEqual(self.partner.street, 'street Y')
  160. self.assertEqual(self.partner.street2, 'street2 Y')
  161. def test_apply(self):
  162. """ Apply a full changeset on a partner """
  163. changes = [
  164. (self.field_name, 'Y', 'draft'),
  165. (self.field_street, 'street Y', 'draft'),
  166. (self.field_street2, 'street2 Y', 'draft'),
  167. ]
  168. changeset = self._create_changeset(self.partner, changes)
  169. changeset.apply()
  170. self.assertEqual(self.partner.name, 'Y')
  171. self.assertEqual(self.partner.street, 'street Y')
  172. self.assertEqual(self.partner.street2, 'street2 Y')
  173. def test_changeset_state_on_done(self):
  174. """ Check that changeset state becomes done when changes are done """
  175. changes = [(self.field_name, 'Y', 'draft')]
  176. changeset = self._create_changeset(self.partner, changes)
  177. self.assertEqual(changeset.state, 'draft')
  178. changeset.change_ids.apply()
  179. self.assertEqual(changeset.state, 'done')
  180. def test_changeset_state_on_cancel(self):
  181. """ Check that rev. state becomes done when changes are canceled """
  182. changes = [(self.field_name, 'Y', 'draft')]
  183. changeset = self._create_changeset(self.partner, changes)
  184. self.assertEqual(changeset.state, 'draft')
  185. changeset.change_ids.cancel()
  186. self.assertEqual(changeset.state, 'done')
  187. def test_changeset_state(self):
  188. """ Check that changeset state becomes done with multiple changes """
  189. changes = [
  190. (self.field_name, 'Y', 'draft'),
  191. (self.field_street, 'street Y', 'draft'),
  192. (self.field_street2, 'street2 Y', 'draft'),
  193. ]
  194. changeset = self._create_changeset(self.partner, changes)
  195. self.assertEqual(changeset.state, 'draft')
  196. changeset.apply()
  197. self.assertEqual(changeset.state, 'done')
  198. def test_apply_changeset_with_other_pending(self):
  199. """ Error when applying when previous pending changesets exist """
  200. changes = [(self.field_name, 'Y', 'draft')]
  201. old_changeset = self._create_changeset(self.partner, changes)
  202. # if the date is the same, both changeset can be applied
  203. to_string = fields.Datetime.to_string
  204. old_changeset.date = to_string(datetime.now() - timedelta(days=1))
  205. changes = [(self.field_name, 'Z', 'draft')]
  206. changeset = self._create_changeset(self.partner, changes)
  207. with self.assertRaises(exceptions.Warning):
  208. changeset.change_ids.apply()
  209. def test_apply_different_changesets(self):
  210. """ Apply different changesets at once """
  211. partner2 = self.env['res.partner'].create({'name': 'P2'})
  212. changes = [
  213. (self.field_name, 'Y', 'draft'),
  214. (self.field_street, 'street Y', 'draft'),
  215. (self.field_street2, 'street2 Y', 'draft'),
  216. ]
  217. changeset = self._create_changeset(self.partner, changes)
  218. changeset2 = self._create_changeset(partner2, changes)
  219. self.assertEqual(changeset.state, 'draft')
  220. self.assertEqual(changeset2.state, 'draft')
  221. (changeset + changeset2).apply()
  222. self.assertEqual(self.partner.name, 'Y')
  223. self.assertEqual(self.partner.street, 'street Y')
  224. self.assertEqual(self.partner.street2, 'street2 Y')
  225. self.assertEqual(partner2.name, 'Y')
  226. self.assertEqual(partner2.street, 'street Y')
  227. self.assertEqual(partner2.street2, 'street2 Y')
  228. self.assertEqual(changeset.state, 'done')
  229. self.assertEqual(changeset2.state, 'done')