def test_sync_affiliation_circular(self): """ Test circular sync of affiliations. """ facility_id = self.db.ensure_facility('test_tel') self.assertIsInstance(facility_id, int) queue_id = self.db.add_queue(facility_id, 'Queue1', 'Q1') self.assertIsInstance(queue_id, int) records = AffiliationCollection() records[0] = Affiliation( None, queue_id, 'Aff A', False, AffiliationType.STANDARD, None) records[1] = Affiliation( None, queue_id, 'Aff B', False, AffiliationType.STANDARD, None) records[2] = Affiliation( None, queue_id, 'Aff C', False, AffiliationType.STANDARD, None) records[3] = Affiliation( None, queue_id, 'Aff D', False, AffiliationType.STANDARD, None) records[4] = Affiliation( None, queue_id, 'Aff E', False, AffiliationType.STANDARD, None) n = self.db.sync_queue_affiliation(queue_id, records) self.assertEqual(n, (5, 0, 0)) records = self.db.search_affiliation(queue_id=queue_id, order_by_id=True) id_ = list(records.keys()) records[id_[1]] = records[id_[1]]._replace(name='Aff C') records[id_[2]] = records[id_[2]]._replace(name='Aff D') records[id_[3]] = records[id_[3]]._replace(name='Aff B') with self.assertRaisesRegexp(UserError, 'Circular update'): self.db.sync_queue_affiliation(queue_id, records)
def test_sync_affiliation(self): """ Test troublesome sync situations for affiliations. """ facility_id = self.db.ensure_facility('test_tel') self.assertIsInstance(facility_id, int) queue_id = self.db.add_queue(facility_id, 'Queue1', 'Q1') self.assertIsInstance(queue_id, int) records = AffiliationCollection() records[0] = Affiliation( None, queue_id, 'Aff A', False, AffiliationType.STANDARD, None) records[1] = Affiliation( None, queue_id, 'Aff B', False, AffiliationType.STANDARD, None) records[2] = Affiliation( None, queue_id, 'Aff C', False, AffiliationType.STANDARD, None) records[3] = Affiliation( None, queue_id, 'Aff D', False, AffiliationType.STANDARD, None) records[4] = Affiliation( None, queue_id, 'Aff E', False, AffiliationType.STANDARD, None) records[5] = Affiliation( None, queue_id, 'Aff F', False, AffiliationType.STANDARD, None) n = self.db.sync_queue_affiliation(queue_id, records) self.assertEqual(n, (6, 0, 0)) records = self.db.search_affiliation(queue_id=queue_id, order_by_id=True) id_ = list(records.keys()) # Delete an affiliation and rename another affiliation to its old name. records[id_[0]] = records[id_[0]]._replace(name='Aff F') with self.assertRaisesRegexp(UserError, 'duplicate values'): self.db.sync_queue_affiliation(queue_id, records) del records[id_[5]] n = self.db.sync_queue_affiliation(queue_id, records) self.assertEqual(n, (0, 1, 1)) self.assertEqual( [x.name for x in self.db.search_affiliation( queue_id=queue_id, order_by_id=True).values()], ['Aff F', 'Aff B', 'Aff C', 'Aff D', 'Aff E']) # Rename an affiliation and rename another to its previous name. records[id_[1]] = records[id_[1]]._replace(name='Aff E') records[id_[4]] = records[id_[4]]._replace(name='Aff EE') n = self.db.sync_queue_affiliation(queue_id, records) self.assertEqual(n, (0, 2, 0)) self.assertEqual( [x.name for x in self.db.search_affiliation( queue_id=queue_id, order_by_id=True).values()], ['Aff F', 'Aff E', 'Aff C', 'Aff D', 'Aff EE'])
def test_affiliation_assignment(self): # Set up "constants" for test affiliation IDs. UNKNOWN = 0 # Returned by Hedwig. AFF_1 = 1 AFF_2 = 2 AFF_3 = 3 STAFF = 5 OTHER = 6 MISSING = 7 # Used to test behavior with invalid input values. # Prepare affiliations. affiliations = AffiliationCollection() affiliations[AFF_1] = Affiliation(AFF_1, None, 'Aff 1', hidden=False, type=AffiliationType.STANDARD, weight=50) affiliations[AFF_2] = Affiliation(AFF_2, None, 'Aff 2', hidden=False, type=AffiliationType.STANDARD, weight=20) affiliations[AFF_3] = Affiliation(AFF_3, None, 'Aff 3', hidden=False, type=AffiliationType.STANDARD, weight=20) affiliations[STAFF] = Affiliation(STAFF, None, 'Staff', hidden=False, type=AffiliationType.SHARED, weight=None) affiliations[OTHER] = Affiliation(OTHER, None, 'Other', hidden=False, type=AffiliationType.EXCLUDED, weight=None) # Perform test: no members at all. self._test_affiliation_assignment('No members', affiliations, None, [], {UNKNOWN: 1.0}) # Perform tests: PI only. self._test_affiliation_assignment('Simple PI only', affiliations, AFF_1, [], {AFF_1: 1.0}) self._test_affiliation_assignment('Excluded PI only', affiliations, OTHER, [], {UNKNOWN: 1.0}) self._test_affiliation_assignment('Invalid PI only', affiliations, MISSING, [], {UNKNOWN: 1.0}) # Perform tests: CoIs only. self._test_affiliation_assignment('1 simple CoI only', affiliations, None, [AFF_2], {AFF_2: 1.0}) self._test_affiliation_assignment('1 invalid CoI only', affiliations, None, [MISSING], {UNKNOWN: 1.0}) self._test_affiliation_assignment('2 simple CoIs only', affiliations, None, [AFF_2, AFF_3], { AFF_2: 0.5, AFF_3: 0.5 }) self._test_affiliation_assignment('2 simple CoIs only (incl. invalid)', affiliations, None, [AFF_1, MISSING], { AFF_1: 0.5, UNKNOWN: 0.5 }) self._test_affiliation_assignment( '2 simple CoIs only (incl. invalid higher weight)', affiliations, None, [AFF_2, MISSING], { AFF_2: 20 / 70, UNKNOWN: 50 / 70 }) self._test_affiliation_assignment('3 simple CoIs only', affiliations, None, [AFF_2, AFF_3, AFF_3], { AFF_2: 1 / 3, AFF_3: 2 / 3 }) self._test_affiliation_assignment('2 simple CoIs with weighting', affiliations, None, [AFF_1, AFF_2], { AFF_1: 50 / 70, AFF_2: 20 / 70 }) self._test_affiliation_assignment('4 simple CoIs with weighting', affiliations, None, [AFF_1, AFF_2, AFF_2, AFF_3], { AFF_1: 50 / 110, AFF_2: 40 / 110, AFF_3: 20 / 110 }) self._test_affiliation_assignment('1 excluded CoI only', affiliations, None, [OTHER], {UNKNOWN: 1.0}) self._test_affiliation_assignment( '2 CoIs only with excluded (equal weight)', affiliations, None, [AFF_1, OTHER], { AFF_1: 0.5, 0: 0.5 }) self._test_affiliation_assignment( '2 CoIs only with excluded (higher weight)', affiliations, None, [AFF_2, OTHER], { AFF_2: 20 / 70, UNKNOWN: 50 / 70 }) # Perform tests: PI and CoIs (simple). self._test_affiliation_assignment('Complete simple (equal weight)', affiliations, AFF_1, [AFF_2, AFF_3], { AFF_1: 0.5, AFF_2: 0.25, AFF_3: 0.25 }) self._test_affiliation_assignment('Complete simple (different weight)', affiliations, AFF_2, [AFF_1, AFF_3], { AFF_2: 0.5, AFF_1: 0.5 * 50 / 70, AFF_3: 0.5 * 20 / 70 }) self._test_affiliation_assignment( 'Complete simple (multiple equal weight)', affiliations, AFF_1, [AFF_2, AFF_2, AFF_3, AFF_3, AFF_3], { AFF_1: 0.5, AFF_2: 0.5 * 2 / 5, AFF_3: 0.5 * 3 / 5 }) self._test_affiliation_assignment( 'Complete simple (multiple different weight)', affiliations, AFF_2, [AFF_1, AFF_1, AFF_3, AFF_3, AFF_3], { AFF_2: 0.5, AFF_1: 0.5 * ((2 * 50) / (2 * 50 + 3 * 20)), AFF_3: 0.5 * ((3 * 20) / (2 * 50 + 3 * 20)) }) # Perform tests: PI and CoIs (with excluded). self._test_affiliation_assignment('Complete with excluded PI', affiliations, OTHER, [AFF_2, AFF_2], { UNKNOWN: 0.5, AFF_2: 0.5 }) self._test_affiliation_assignment('Complete with excluded CoI', affiliations, AFF_1, [AFF_2, OTHER], { AFF_1: 0.5 + 0.5 * (50 / 70), AFF_2: 0.5 * (20 / 70) }) self._test_affiliation_assignment( 'Complete with excluded CoI (lower weight PI)', affiliations, AFF_2, [AFF_1, OTHER], { AFF_2: 0.5 + 0.5 * (20 / 70), AFF_1: 0.5 * (50 / 70) }) self._test_affiliation_assignment( 'Complete with excluded PI and CoI (equal weight)', affiliations, OTHER, [AFF_1, OTHER], { UNKNOWN: 0.5 + 0.25, AFF_1: 0.25 }) self._test_affiliation_assignment( 'Complete with excluded PI and CoI (higher weight)', affiliations, OTHER, [AFF_2, OTHER], { UNKNOWN: 0.5 + 0.5 * (50 / 70), AFF_2: 0.5 * (20 / 70) }) # Perform tests: shared affiliations. self._test_affiliation_assignment('Shared PI only', affiliations, STAFF, [], { AFF_1: 50 / 90, AFF_2: 20 / 90, AFF_3: 20 / 90 }) self._test_affiliation_assignment( 'Shared PI and 1 CoI', affiliations, STAFF, [AFF_1], { AFF_1: 0.5 * (50 / 90) + 0.5, AFF_2: 0.5 * (20 / 90), AFF_3: 0.5 * (20 / 90) }) self._test_affiliation_assignment( 'Shared PI and 2 CoIs', affiliations, STAFF, [AFF_1, AFF_2], { AFF_1: 0.5 * (50 / 90) + 0.5 * (50 / 70), AFF_2: 0.5 * (20 / 90) + 0.5 * (20 / 70), AFF_3: 0.5 * (20 / 90) }) self._test_affiliation_assignment( 'Shared PI and 3 CoIs', affiliations, STAFF, [AFF_1, AFF_2, AFF_2], { AFF_1: 0.5 * (50 / 90) + 0.5 * (50 / 90), AFF_2: 0.5 * (20 / 90) + 0.5 * (40 / 90), AFF_3: 0.5 * (20 / 90) }) self._test_affiliation_assignment('Simple PI and shared CoI', affiliations, AFF_1, [STAFF], {AFF_1: 1.0}) self._test_affiliation_assignment('Simple PI and 2 shared CoIs', affiliations, AFF_1, [STAFF, STAFF], {AFF_1: 1.0}) self._test_affiliation_assignment( 'Simple PI and shared and normal (low weight) CoIs', affiliations, AFF_1, [AFF_2, STAFF], { AFF_1: 0.5 + 0.5 * (50 / (50 + 20)), AFF_2: 0.5 * (20 / (50 + 20)) }) self._test_affiliation_assignment( 'Simple PI and shared and normal (high weight) CoIs', affiliations, AFF_1, [AFF_1, STAFF], {AFF_1: 1.0}) self._test_affiliation_assignment( 'Simple PI and shared and missing CoIs', affiliations, AFF_1, [UNKNOWN, STAFF], { AFF_1: 0.5 + 0.5 * (50 / (50 + 50)), UNKNOWN: 0.5 * (50 / (50 + 50)) }) self._test_affiliation_assignment('Shared PI and excluded CoI', affiliations, STAFF, [OTHER], { AFF_1: (50 / 90), AFF_2: (20 / 90), AFF_3: (20 / 90) }) self._test_affiliation_assignment('Shared PI and shared CoI', affiliations, STAFF, [STAFF], { AFF_1: (50 / 90), AFF_2: (20 / 90), AFF_3: (20 / 90) }) self._test_affiliation_assignment( 'Shared PI and shared and normal CoI', affiliations, STAFF, [STAFF, AFF_2], { AFF_1: 0.5 * (50 / 90) + 0.5 * (((50 / 90) * 50) / (50 + 20)), AFF_2: 0.5 * (20 / 90) + 0.5 * (((20 / 90) * 50 + 20) / (50 + 20)), AFF_3: 0.5 * (20 / 90) + 0.5 * (((20 / 90) * 50) / (50 + 20)) }) self._test_affiliation_assignment( 'Shared PI and multiple CoIs', affiliations, STAFF, [AFF_1, AFF_2, AFF_2, STAFF, OTHER], { AFF_1: 0.5 * (50 / 90) + 0.5 * ((2 * (50 / 90) * 50 + 50) / 190), AFF_2: 0.5 * (20 / 90) + 0.5 * ((2 * (20 / 90) * 50 + 2 * 20) / 190), AFF_3: 0.5 * (20 / 90) + 0.5 * ((2 * (20 / 90) * 50) / 190) })