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.

295 lines
13 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2016-2017 Therp BV
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from datetime import date
  5. from dateutil.relativedelta import relativedelta
  6. from psycopg2 import IntegrityError
  7. from openerp import fields
  8. from openerp.exceptions import ValidationError
  9. from .test_partner_relation_common import TestPartnerRelationCommon
  10. class TestPartnerRelation(TestPartnerRelationCommon):
  11. post_install = True
  12. def test_selection_name_search(self):
  13. """Test wether we can find type selection on reverse name."""
  14. selection_types = self.selection_model.name_search(
  15. name=self.selection_person2company.name)
  16. self.assertTrue(selection_types)
  17. self.assertTrue(
  18. (self.selection_person2company.id,
  19. self.selection_person2company.name) in selection_types)
  20. def test_self_allowed(self):
  21. """Test creation of relation to same partner when type allows."""
  22. type_allow = self.type_model.create({
  23. 'name': 'allow',
  24. 'name_inverse': 'allow_inverse',
  25. 'contact_type_left': 'p',
  26. 'contact_type_right': 'p',
  27. 'allow_self': True})
  28. self.assertTrue(type_allow)
  29. reflexive_relation = self.relation_model.create({
  30. 'type_id': type_allow.id,
  31. 'left_partner_id': self.partner_01_person.id,
  32. 'right_partner_id': self.partner_01_person.id})
  33. self.assertTrue(reflexive_relation)
  34. def test_self_disallowed(self):
  35. """Test creating relation to same partner when disallowed.
  36. Attempt to create a relation of a partner to the same partner should
  37. raise an error when the type of relation explicitly disallows this.
  38. """
  39. type_disallow = self.type_model.create({
  40. 'name': 'disallow',
  41. 'name_inverse': 'disallow_inverse',
  42. 'contact_type_left': 'p',
  43. 'contact_type_right': 'p',
  44. 'allow_self': False})
  45. self.assertTrue(type_disallow)
  46. with self.assertRaises(ValidationError):
  47. self.relation_model.create({
  48. 'type_id': type_disallow.id,
  49. 'left_partner_id': self.partner_01_person.id,
  50. 'right_partner_id': self.partner_01_person.id})
  51. def test_self_default(self):
  52. """Test default not to allow relation with same partner.
  53. Attempt to create a relation of a partner to the same partner
  54. raise an error when the type of relation does not explicitly allow
  55. this.
  56. """
  57. type_default = self.type_model.create({
  58. 'name': 'default',
  59. 'name_inverse': 'default_inverse',
  60. 'contact_type_left': 'p',
  61. 'contact_type_right': 'p'})
  62. self.assertTrue(type_default)
  63. with self.assertRaises(ValidationError):
  64. self.relation_model.create({
  65. 'type_id': type_default.id,
  66. 'left_partner_id': self.partner_01_person.id,
  67. 'right_partner_id': self.partner_01_person.id})
  68. def test_self_mixed(self):
  69. """Test creation of relation with wrong types.
  70. Trying to create a relation between partners with an inappropiate
  71. type should raise an error.
  72. """
  73. with self.assertRaises(ValidationError):
  74. self.relation_model.create({
  75. 'type_id': self.type_company2person.id,
  76. 'left_partner_id': self.partner_01_person.id,
  77. 'right_partner_id': self.partner_02_company.id})
  78. def test_symmetric(self):
  79. """Test creating symmetric relation."""
  80. # Start out with non symmetric relation:
  81. type_symmetric = self.type_model.create({
  82. 'name': 'not yet symmetric',
  83. 'name_inverse': 'the other side of not symmetric',
  84. 'is_symmetric': False,
  85. 'contact_type_left': False,
  86. 'contact_type_right': 'p'})
  87. # not yet symmetric relation should result in two records in
  88. # selection:
  89. selection_symmetric = self.selection_model.search([
  90. ('type_id', '=', type_symmetric.id)])
  91. self.assertEqual(len(selection_symmetric), 2)
  92. # Now change to symmetric and test name and inverse name:
  93. with self.env.do_in_draft():
  94. type_symmetric.write({
  95. 'name': 'sym',
  96. 'is_symmetric': True})
  97. self.assertEqual(type_symmetric.is_symmetric, True)
  98. self.assertEqual(
  99. type_symmetric.name_inverse,
  100. type_symmetric.name)
  101. self.assertEqual(
  102. type_symmetric.contact_type_right,
  103. type_symmetric.contact_type_left)
  104. # now update the database:
  105. type_symmetric.write({
  106. 'name': type_symmetric.name,
  107. 'is_symmetric': type_symmetric.is_symmetric,
  108. 'name_inverse': type_symmetric.name_inverse,
  109. 'contact_type_right': type_symmetric.contact_type_right})
  110. # symmetric relation should result in only one record in
  111. # selection:
  112. selection_symmetric = self.selection_model.search([
  113. ('type_id', '=', type_symmetric.id)])
  114. self.assertEqual(len(selection_symmetric), 1)
  115. relation = self.relation_all_model.create({
  116. 'type_selection_id': selection_symmetric.id,
  117. 'this_partner_id': self.partner_02_company.id,
  118. 'other_partner_id': self.partner_01_person.id})
  119. partners = self.partner_model.search([
  120. ('search_relation_type_id', '=', relation.type_selection_id.id)])
  121. self.assertTrue(self.partner_01_person in partners)
  122. self.assertTrue(self.partner_02_company in partners)
  123. def test_category_domain(self):
  124. """Test check on category in relations."""
  125. # Check on left side:
  126. with self.assertRaises(ValidationError):
  127. self.relation_model.create({
  128. 'type_id': self.type_ngo2volunteer.id,
  129. 'left_partner_id': self.partner_02_company.id,
  130. 'right_partner_id': self.partner_04_volunteer.id})
  131. # Check on right side:
  132. with self.assertRaises(ValidationError):
  133. self.relation_model.create({
  134. 'type_id': self.type_ngo2volunteer.id,
  135. 'left_partner_id': self.partner_03_ngo.id,
  136. 'right_partner_id': self.partner_01_person.id})
  137. def test_relation_type_change(self):
  138. """Test change in relation type conditions."""
  139. # First create a relation type having no particular conditions.
  140. (type_school2student,
  141. school2student,
  142. school2student_inverse) = \
  143. self._create_relation_type_selection({
  144. 'name': 'school has student',
  145. 'name_inverse': 'studies at school'})
  146. # Second create relations based on those conditions.
  147. partner_school = self.partner_model.create({
  148. 'name': 'Test School',
  149. 'is_company': True,
  150. 'ref': 'TS'})
  151. partner_bart = self.partner_model.create({
  152. 'name': 'Bart Simpson',
  153. 'is_company': False,
  154. 'ref': 'BS'})
  155. partner_lisa = self.partner_model.create({
  156. 'name': 'Lisa Simpson',
  157. 'is_company': False,
  158. 'ref': 'LS'})
  159. relation_school2bart = self.relation_all_model.create({
  160. 'this_partner_id': partner_school.id,
  161. 'type_selection_id': school2student.id,
  162. 'other_partner_id': partner_bart.id})
  163. self.assertTrue(relation_school2bart)
  164. relation_school2lisa = self.relation_all_model.create({
  165. 'this_partner_id': partner_school.id,
  166. 'type_selection_id': school2student.id,
  167. 'other_partner_id': partner_lisa.id})
  168. self.assertTrue(relation_school2lisa)
  169. relation_bart2lisa = self.relation_all_model.create({
  170. 'this_partner_id': partner_bart.id,
  171. 'type_selection_id': school2student.id,
  172. 'other_partner_id': partner_lisa.id})
  173. self.assertTrue(relation_bart2lisa)
  174. # Third creata a category and make it a condition for the
  175. # relation type.
  176. # - Test restriction
  177. # - Test ignore
  178. category_student = self.category_model.create({'name': 'Student'})
  179. with self.assertRaises(ValidationError):
  180. type_school2student.write({
  181. 'partner_category_right': category_student.id})
  182. self.assertFalse(type_school2student.partner_category_right.id)
  183. type_school2student.write({
  184. 'handle_invalid_onchange': 'ignore',
  185. 'partner_category_right': category_student.id})
  186. self.assertEqual(
  187. type_school2student.partner_category_right.id,
  188. category_student.id)
  189. # Fourth make company type a condition for left partner
  190. # - Test ending
  191. # - Test deletion
  192. partner_bart.write({
  193. 'category_id': [(4, category_student.id)]})
  194. partner_lisa.write({
  195. 'category_id': [(4, category_student.id)]})
  196. # Future student to be deleted by end action:
  197. partner_homer = self.partner_model.create({
  198. 'name': 'Homer Simpson',
  199. 'is_company': False,
  200. 'ref': 'HS',
  201. 'category_id': [(4, category_student.id)]})
  202. relation_lisa2homer = self.relation_all_model.create({
  203. 'this_partner_id': partner_lisa.id,
  204. 'type_selection_id': school2student.id,
  205. 'other_partner_id': partner_homer.id,
  206. 'date_start': fields.Date.to_string(
  207. date.today() + relativedelta(months=+6))})
  208. self.assertTrue(relation_lisa2homer)
  209. type_school2student.write({
  210. 'handle_invalid_onchange': 'end',
  211. 'contact_type_left': 'c'})
  212. self.assertEqual(
  213. relation_bart2lisa.date_end,
  214. fields.Date.today())
  215. self.assertFalse(relation_lisa2homer.exists())
  216. type_school2student.write({
  217. 'handle_invalid_onchange': 'delete',
  218. 'contact_type_left': 'c',
  219. 'contact_type_right': 'p'})
  220. self.assertFalse(relation_bart2lisa.exists())
  221. def test_relation_type_unlink_dberror(self):
  222. """Test deleting relation type when not possible.
  223. This test will catch a DB Integrity error. Because of that the
  224. cursor will be invalidated, and further tests using the objects
  225. will not be possible.
  226. """
  227. # First create a relation type having restrict particular conditions.
  228. type_model = self.env['res.partner.relation.type']
  229. relation_model = self.env['res.partner.relation']
  230. partner_model = self.env['res.partner']
  231. type_school2student = type_model.create({
  232. 'name': 'school has student',
  233. 'name_inverse': 'studies at school',
  234. 'handle_invalid_onchange': 'restrict'})
  235. # Second create relation based on those conditions.
  236. partner_school = partner_model.create({
  237. 'name': 'Test School',
  238. 'is_company': True,
  239. 'ref': 'TS'})
  240. partner_bart = partner_model.create({
  241. 'name': 'Bart Simpson',
  242. 'is_company': False,
  243. 'ref': 'BS'})
  244. relation_model.create({
  245. 'left_partner_id': partner_school.id,
  246. 'type_id': type_school2student.id,
  247. 'right_partner_id': partner_bart.id})
  248. # Unlink should for the moment lead to error because of restrict:
  249. with self.assertRaises(IntegrityError):
  250. type_school2student.unlink()
  251. def test_relation_type_unlink(self):
  252. """Test delete of relation type, including deleting relations."""
  253. # First create a relation type having restrict particular conditions.
  254. type_model = self.env['res.partner.relation.type']
  255. relation_model = self.env['res.partner.relation']
  256. partner_model = self.env['res.partner']
  257. type_school2student = type_model.create({
  258. 'name': 'school has student',
  259. 'name_inverse': 'studies at school',
  260. 'handle_invalid_onchange': 'delete'})
  261. # Second create relation based on those conditions.
  262. partner_school = partner_model.create({
  263. 'name': 'Test School',
  264. 'is_company': True,
  265. 'ref': 'TS'})
  266. partner_bart = partner_model.create({
  267. 'name': 'Bart Simpson',
  268. 'is_company': False,
  269. 'ref': 'BS'})
  270. relation_school2bart = relation_model.create({
  271. 'left_partner_id': partner_school.id,
  272. 'type_id': type_school2student.id,
  273. 'right_partner_id': partner_bart.id})
  274. # Delete type. Relations with type should also cease to exist:
  275. type_school2student.unlink()
  276. self.assertFalse(relation_school2bart.exists())