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.

246 lines
9.6 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2015-2016 Camptocamp SA
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from datetime import datetime, timedelta
  5. from openerp import fields, exceptions
  6. from openerp.tests import common
  7. from .common import ChangesetMixin
  8. class TestChangesetFlow(ChangesetMixin, common.TransactionCase):
  9. """ Check how changeset are generated and applied based on the rules.
  10. We do not really care about the types of the fields in this test
  11. suite, so we only use 'char' fields. We have to ensure that the
  12. general changeset flows work as expected, that is:
  13. * create a changeset when a manual/system write is made on partner
  14. * create a changeset according to the changeset rules when a source model
  15. is specified
  16. * apply a changeset change writes the value on the partner
  17. * apply a whole changeset writes all the changes' values on the partner
  18. * changes in state 'cancel' or 'done' do not write on the partner
  19. * when all the changes are either 'cancel' or 'done', the changeset
  20. becomes 'done'
  21. """
  22. def _setup_rules(self):
  23. ChangesetFieldRule = self.env['changeset.field.rule']
  24. ChangesetFieldRule.search([]).unlink()
  25. self.field_name = self.env.ref('base.field_res_partner_name')
  26. self.field_street = self.env.ref('base.field_res_partner_street')
  27. self.field_street2 = self.env.ref('base.field_res_partner_street2')
  28. ChangesetFieldRule.create({
  29. 'field_id': self.field_name.id,
  30. 'action': 'auto',
  31. })
  32. ChangesetFieldRule.create({
  33. 'field_id': self.field_street.id,
  34. 'action': 'validate',
  35. })
  36. ChangesetFieldRule.create({
  37. 'field_id': self.field_street2.id,
  38. 'action': 'never',
  39. })
  40. def setUp(self):
  41. super(TestChangesetFlow, self).setUp()
  42. self._setup_rules()
  43. self.partner = self.env['res.partner'].create({
  44. 'name': 'X',
  45. 'street': 'street X',
  46. 'street2': 'street2 X',
  47. })
  48. def test_new_changeset(self):
  49. """ Add a new changeset on a partner
  50. A new changeset is created when we write on a partner
  51. """
  52. self.partner.write({
  53. 'name': 'Y',
  54. 'street': 'street Y',
  55. 'street2': 'street2 Y',
  56. })
  57. self.assert_changeset(
  58. self.partner,
  59. self.env.user,
  60. [(self.field_name, 'X', 'Y', 'done'),
  61. (self.field_street, 'street X', 'street Y', 'draft'),
  62. (self.field_street2, 'street2 X', 'street2 Y', 'cancel'),
  63. ],
  64. )
  65. self.assertEqual(self.partner.name, 'Y')
  66. self.assertEqual(self.partner.street, 'street X')
  67. self.assertEqual(self.partner.street2, 'street2 X')
  68. def test_new_changeset_empty_value(self):
  69. """ Create a changeset change that empty a value """
  70. self.partner.write({
  71. 'street': False,
  72. })
  73. self.assert_changeset(
  74. self.partner,
  75. self.env.user,
  76. [(self.field_street, 'street X', False, 'draft')]
  77. )
  78. def test_no_changeset_empty_value_both_sides(self):
  79. """ No changeset created when both sides have an empty value """
  80. # we have to ensure that even if we write '' to a False field, we won't
  81. # write a changeset
  82. self.partner.with_context(__no_changeset=True).write({
  83. 'street': False,
  84. })
  85. self.partner.write({
  86. 'street': '',
  87. })
  88. self.assertFalse(self.partner.changeset_ids)
  89. def test_apply_change(self):
  90. """ Apply a changeset change on a partner """
  91. changes = [
  92. (self.field_name, 'Y', 'draft'),
  93. ]
  94. changeset = self._create_changeset(self.partner, changes)
  95. changeset.change_ids.apply()
  96. self.assertEqual(self.partner.name, 'Y')
  97. self.assertEqual(changeset.change_ids.state, 'done')
  98. def test_apply_done_change(self):
  99. """ Done changes do not apply (already applied) """
  100. changes = [
  101. (self.field_name, 'Y', 'done'),
  102. ]
  103. changeset = self._create_changeset(self.partner, changes)
  104. changeset.change_ids.apply()
  105. self.assertEqual(self.partner.name, 'X')
  106. def test_apply_cancel_change(self):
  107. """ Cancel changes do not apply """
  108. changes = [
  109. (self.field_name, 'Y', 'cancel'),
  110. ]
  111. changeset = self._create_changeset(self.partner, changes)
  112. changeset.change_ids.apply()
  113. self.assertEqual(self.partner.name, 'X')
  114. def test_apply_empty_value(self):
  115. """ Apply a change that empty a value """
  116. changes = [
  117. (self.field_street, False, 'draft'),
  118. ]
  119. changeset = self._create_changeset(self.partner, changes)
  120. changeset.change_ids.apply()
  121. self.assertFalse(self.partner.street)
  122. def test_apply_change_loop(self):
  123. """ Test @api.multi on the changes """
  124. changes = [
  125. (self.field_name, 'Y', 'draft'),
  126. (self.field_street, 'street Y', 'draft'),
  127. (self.field_street2, 'street2 Y', 'draft'),
  128. ]
  129. changeset = self._create_changeset(self.partner, changes)
  130. changeset.change_ids.apply()
  131. self.assertEqual(self.partner.name, 'Y')
  132. self.assertEqual(self.partner.street, 'street Y')
  133. self.assertEqual(self.partner.street2, 'street2 Y')
  134. def test_apply(self):
  135. """ Apply a full changeset on a partner """
  136. changes = [
  137. (self.field_name, 'Y', 'draft'),
  138. (self.field_street, 'street Y', 'draft'),
  139. (self.field_street2, 'street2 Y', 'draft'),
  140. ]
  141. changeset = self._create_changeset(self.partner, changes)
  142. changeset.apply()
  143. self.assertEqual(self.partner.name, 'Y')
  144. self.assertEqual(self.partner.street, 'street Y')
  145. self.assertEqual(self.partner.street2, 'street2 Y')
  146. def test_changeset_state_on_done(self):
  147. """ Check that changeset state becomes done when changes are done """
  148. changes = [(self.field_name, 'Y', 'draft')]
  149. changeset = self._create_changeset(self.partner, changes)
  150. self.assertEqual(changeset.state, 'draft')
  151. changeset.change_ids.apply()
  152. self.assertEqual(changeset.state, 'done')
  153. def test_changeset_state_on_cancel(self):
  154. """ Check that rev. state becomes done when changes are canceled """
  155. changes = [(self.field_name, 'Y', 'draft')]
  156. changeset = self._create_changeset(self.partner, changes)
  157. self.assertEqual(changeset.state, 'draft')
  158. changeset.change_ids.cancel()
  159. self.assertEqual(changeset.state, 'done')
  160. def test_changeset_state(self):
  161. """ Check that changeset state becomes done with multiple changes """
  162. changes = [
  163. (self.field_name, 'Y', 'draft'),
  164. (self.field_street, 'street Y', 'draft'),
  165. (self.field_street2, 'street2 Y', 'draft'),
  166. ]
  167. changeset = self._create_changeset(self.partner, changes)
  168. self.assertEqual(changeset.state, 'draft')
  169. changeset.apply()
  170. self.assertEqual(changeset.state, 'done')
  171. def test_apply_changeset_with_other_pending(self):
  172. """ Error when applying when previous pending changesets exist """
  173. changes = [(self.field_name, 'Y', 'draft')]
  174. old_changeset = self._create_changeset(self.partner, changes)
  175. # if the date is the same, both changeset can be applied
  176. to_string = fields.Datetime.to_string
  177. old_changeset.date = to_string(datetime.now() - timedelta(days=1))
  178. changes = [(self.field_name, 'Z', 'draft')]
  179. changeset = self._create_changeset(self.partner, changes)
  180. with self.assertRaises(exceptions.Warning):
  181. changeset.change_ids.apply()
  182. def test_apply_different_changesets(self):
  183. """ Apply different changesets at once """
  184. partner2 = self.env['res.partner'].create({'name': 'P2'})
  185. changes = [
  186. (self.field_name, 'Y', 'draft'),
  187. (self.field_street, 'street Y', 'draft'),
  188. (self.field_street2, 'street2 Y', 'draft'),
  189. ]
  190. changeset = self._create_changeset(self.partner, changes)
  191. self.assertEqual(self.partner.count_pending_changesets, 1)
  192. changeset2 = self._create_changeset(partner2, changes)
  193. self.assertEqual(changeset.state, 'draft')
  194. self.assertEqual(changeset2.state, 'draft')
  195. (changeset + changeset2).apply()
  196. self.assertEqual(self.partner.name, 'Y')
  197. self.assertEqual(self.partner.street, 'street Y')
  198. self.assertEqual(self.partner.street2, 'street2 Y')
  199. self.assertEqual(partner2.name, 'Y')
  200. self.assertEqual(partner2.street, 'street Y')
  201. self.assertEqual(partner2.street2, 'street2 Y')
  202. self.assertEqual(changeset.state, 'done')
  203. self.assertEqual(changeset2.state, 'done')
  204. def test_new_changeset_source(self):
  205. """ Source is the user who made the change """
  206. self.partner.write({
  207. 'street': False,
  208. })
  209. changeset = self.partner.changeset_ids
  210. self.assertEqual(changeset.source, self.env.user)
  211. def test_new_changeset_source_other_model(self):
  212. """ Define source from another model """
  213. company = self.env.ref('base.main_company')
  214. keys = {
  215. '__changeset_rules_source_model': 'res.company',
  216. '__changeset_rules_source_id': company.id,
  217. }
  218. self.partner.with_context(**keys).write({
  219. 'street': False,
  220. })
  221. changeset = self.partner.changeset_ids
  222. self.assertEqual(changeset.source, company)