# -*- coding: utf-8 -*- # Copyright 2016-2017 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from datetime import date from dateutil.relativedelta import relativedelta from psycopg2 import IntegrityError from openerp import fields from openerp.exceptions import ValidationError from .test_partner_relation_common import TestPartnerRelationCommon class TestPartnerRelation(TestPartnerRelationCommon): post_install = True def test_selection_name_search(self): """Test wether we can find type selection on reverse name.""" selection_types = self.selection_model.name_search( name=self.selection_person2company.name) self.assertTrue(selection_types) self.assertTrue( (self.selection_person2company.id, self.selection_person2company.name) in selection_types) def test_self_allowed(self): """Test creation of relation to same partner when type allows.""" type_allow = self.type_model.create({ 'name': 'allow', 'name_inverse': 'allow_inverse', 'contact_type_left': 'p', 'contact_type_right': 'p', 'allow_self': True}) self.assertTrue(type_allow) reflexive_relation = self.relation_model.create({ 'type_id': type_allow.id, 'left_partner_id': self.partner_01_person.id, 'right_partner_id': self.partner_01_person.id}) self.assertTrue(reflexive_relation) def test_self_disallowed(self): """Test creating relation to same partner when disallowed. Attempt to create a relation of a partner to the same partner should raise an error when the type of relation explicitly disallows this. """ type_disallow = self.type_model.create({ 'name': 'disallow', 'name_inverse': 'disallow_inverse', 'contact_type_left': 'p', 'contact_type_right': 'p', 'allow_self': False}) self.assertTrue(type_disallow) with self.assertRaises(ValidationError): self.relation_model.create({ 'type_id': type_disallow.id, 'left_partner_id': self.partner_01_person.id, 'right_partner_id': self.partner_01_person.id}) def test_self_default(self): """Test default not to allow relation with same partner. Attempt to create a relation of a partner to the same partner raise an error when the type of relation does not explicitly allow this. """ type_default = self.type_model.create({ 'name': 'default', 'name_inverse': 'default_inverse', 'contact_type_left': 'p', 'contact_type_right': 'p'}) self.assertTrue(type_default) with self.assertRaises(ValidationError): self.relation_model.create({ 'type_id': type_default.id, 'left_partner_id': self.partner_01_person.id, 'right_partner_id': self.partner_01_person.id}) def test_self_mixed(self): """Test creation of relation with wrong types. Trying to create a relation between partners with an inappropiate type should raise an error. """ with self.assertRaises(ValidationError): self.relation_model.create({ 'type_id': self.type_company2person.id, 'left_partner_id': self.partner_01_person.id, 'right_partner_id': self.partner_02_company.id}) def test_symmetric(self): """Test creating symmetric relation.""" # Start out with non symmetric relation: type_symmetric = self.type_model.create({ 'name': 'not yet symmetric', 'name_inverse': 'the other side of not symmetric', 'is_symmetric': False, 'contact_type_left': False, 'contact_type_right': 'p'}) # not yet symmetric relation should result in two records in # selection: selection_symmetric = self.selection_model.search([ ('type_id', '=', type_symmetric.id)]) self.assertEqual(len(selection_symmetric), 2) # Now change to symmetric and test name and inverse name: with self.env.do_in_draft(): type_symmetric.write({ 'name': 'sym', 'is_symmetric': True}) self.assertEqual(type_symmetric.is_symmetric, True) self.assertEqual( type_symmetric.name_inverse, type_symmetric.name) self.assertEqual( type_symmetric.contact_type_right, type_symmetric.contact_type_left) # now update the database: type_symmetric.write({ 'name': type_symmetric.name, 'is_symmetric': type_symmetric.is_symmetric, 'name_inverse': type_symmetric.name_inverse, 'contact_type_right': type_symmetric.contact_type_right}) # symmetric relation should result in only one record in # selection: selection_symmetric = self.selection_model.search([ ('type_id', '=', type_symmetric.id)]) self.assertEqual(len(selection_symmetric), 1) relation = self.relation_all_model.create({ 'type_selection_id': selection_symmetric.id, 'this_partner_id': self.partner_02_company.id, 'other_partner_id': self.partner_01_person.id}) partners = self.partner_model.search([ ('search_relation_type_id', '=', relation.type_selection_id.id)]) self.assertTrue(self.partner_01_person in partners) self.assertTrue(self.partner_02_company in partners) def test_category_domain(self): """Test check on category in relations.""" # Check on left side: with self.assertRaises(ValidationError): self.relation_model.create({ 'type_id': self.type_ngo2volunteer.id, 'left_partner_id': self.partner_02_company.id, 'right_partner_id': self.partner_04_volunteer.id}) # Check on right side: with self.assertRaises(ValidationError): self.relation_model.create({ 'type_id': self.type_ngo2volunteer.id, 'left_partner_id': self.partner_03_ngo.id, 'right_partner_id': self.partner_01_person.id}) def test_relation_type_change(self): """Test change in relation type conditions.""" # First create a relation type having no particular conditions. (type_school2student, school2student, school2student_inverse) = \ self._create_relation_type_selection({ 'name': 'school has student', 'name_inverse': 'studies at school'}) # Second create relations based on those conditions. partner_school = self.partner_model.create({ 'name': 'Test School', 'is_company': True, 'ref': 'TS'}) partner_bart = self.partner_model.create({ 'name': 'Bart Simpson', 'is_company': False, 'ref': 'BS'}) partner_lisa = self.partner_model.create({ 'name': 'Lisa Simpson', 'is_company': False, 'ref': 'LS'}) relation_school2bart = self.relation_all_model.create({ 'this_partner_id': partner_school.id, 'type_selection_id': school2student.id, 'other_partner_id': partner_bart.id}) self.assertTrue(relation_school2bart) relation_school2lisa = self.relation_all_model.create({ 'this_partner_id': partner_school.id, 'type_selection_id': school2student.id, 'other_partner_id': partner_lisa.id}) self.assertTrue(relation_school2lisa) relation_bart2lisa = self.relation_all_model.create({ 'this_partner_id': partner_bart.id, 'type_selection_id': school2student.id, 'other_partner_id': partner_lisa.id}) self.assertTrue(relation_bart2lisa) # Third creata a category and make it a condition for the # relation type. # - Test restriction # - Test ignore category_student = self.category_model.create({'name': 'Student'}) with self.assertRaises(ValidationError): type_school2student.write({ 'partner_category_right': category_student.id}) self.assertFalse(type_school2student.partner_category_right.id) type_school2student.write({ 'handle_invalid_onchange': 'ignore', 'partner_category_right': category_student.id}) self.assertEqual( type_school2student.partner_category_right.id, category_student.id) # Fourth make company type a condition for left partner # - Test ending # - Test deletion partner_bart.write({ 'category_id': [(4, category_student.id)]}) partner_lisa.write({ 'category_id': [(4, category_student.id)]}) # Future student to be deleted by end action: partner_homer = self.partner_model.create({ 'name': 'Homer Simpson', 'is_company': False, 'ref': 'HS', 'category_id': [(4, category_student.id)]}) relation_lisa2homer = self.relation_all_model.create({ 'this_partner_id': partner_lisa.id, 'type_selection_id': school2student.id, 'other_partner_id': partner_homer.id, 'date_start': fields.Date.to_string( date.today() + relativedelta(months=+6))}) self.assertTrue(relation_lisa2homer) type_school2student.write({ 'handle_invalid_onchange': 'end', 'contact_type_left': 'c'}) self.assertEqual( relation_bart2lisa.date_end, fields.Date.today()) self.assertFalse(relation_lisa2homer.exists()) type_school2student.write({ 'handle_invalid_onchange': 'delete', 'contact_type_left': 'c', 'contact_type_right': 'p'}) self.assertFalse(relation_bart2lisa.exists()) def test_relation_type_unlink_dberror(self): """Test deleting relation type when not possible. This test will catch a DB Integrity error. Because of that the cursor will be invalidated, and further tests using the objects will not be possible. """ # First create a relation type having restrict particular conditions. type_model = self.env['res.partner.relation.type'] relation_model = self.env['res.partner.relation'] partner_model = self.env['res.partner'] type_school2student = type_model.create({ 'name': 'school has student', 'name_inverse': 'studies at school', 'handle_invalid_onchange': 'restrict'}) # Second create relation based on those conditions. partner_school = partner_model.create({ 'name': 'Test School', 'is_company': True, 'ref': 'TS'}) partner_bart = partner_model.create({ 'name': 'Bart Simpson', 'is_company': False, 'ref': 'BS'}) relation_model.create({ 'left_partner_id': partner_school.id, 'type_id': type_school2student.id, 'right_partner_id': partner_bart.id}) # Unlink should for the moment lead to error because of restrict: with self.assertRaises(IntegrityError): type_school2student.unlink() def test_relation_type_unlink(self): """Test delete of relation type, including deleting relations.""" # First create a relation type having restrict particular conditions. type_model = self.env['res.partner.relation.type'] relation_model = self.env['res.partner.relation'] partner_model = self.env['res.partner'] type_school2student = type_model.create({ 'name': 'school has student', 'name_inverse': 'studies at school', 'handle_invalid_onchange': 'delete'}) # Second create relation based on those conditions. partner_school = partner_model.create({ 'name': 'Test School', 'is_company': True, 'ref': 'TS'}) partner_bart = partner_model.create({ 'name': 'Bart Simpson', 'is_company': False, 'ref': 'BS'}) relation_school2bart = relation_model.create({ 'left_partner_id': partner_school.id, 'type_id': type_school2student.id, 'right_partner_id': partner_bart.id}) # Delete type. Relations with type should also cease to exist: type_school2student.unlink() self.assertFalse(relation_school2bart.exists())