def test_save_without_matter_type_only_mt1(self, timezone_mock, models_timezone_mock): _mock_datetime_now_with(datetime.datetime(2014, 1, 2, 12, 59, 0), timezone_mock, models_timezone_mock) case = make_recipe('legalaid.case') category = case.eligibility_check.category provider = make_recipe('cla_provider.provider', active=True) make_recipe('cla_provider.provider_allocation', weighted_distribution=0.5, provider=provider, category=category) case.matter_type1 = make_recipe('legalaid.matter_type1', category=category) case.save() helper = ProviderAllocationHelper() form = ProviderAllocationForm(case=case, data={ 'provider': helper.get_suggested_provider(category).pk}, providers=helper.get_qualifying_providers( category)) self.assertFalse(form.is_valid()) self.assertDictEqual(form.errors, {'__all__': [ u"Can't assign to specialist provider without setting matter_type1 and matter_type2"]})
def test_save_out_office_hours_no_valid_provider(self, timezone_mock, models_timezone_mock): _mock_datetime_now_with(datetime.datetime(2014, 1, 1, 8, 59, 0), timezone_mock, models_timezone_mock) case = make_recipe('legalaid.case') category = case.eligibility_check.category case.matter_type1 = make_recipe('legalaid.matter_type1', category=category) case.matter_type2 = make_recipe('legalaid.matter_type2', category=category) case.save() provider = make_recipe('cla_provider.provider', active=True) make_recipe('cla_provider.provider_allocation', weighted_distribution=0.5, provider=provider, category=category) # TODO - create a ProviderAllocation for this provider with the # same category as the case and a positive weighted_distribution helper = ProviderAllocationHelper() suggested = helper.get_suggested_provider(category) self.assertIsNone(suggested) form = ProviderAllocationForm(case=case, data={ 'provider': suggested.pk if suggested else None}, providers=helper.get_qualifying_providers( category)) self.assertFalse(form.is_valid())
def test_save_in_office_hours(self, timezone_mock): _mock_datetime_now_with(datetime.datetime(2014, 1, 2, 9, 1, 0), timezone_mock) case = make_recipe('legalaid.case') category = case.eligibility_check.category case.matter_type1 = make_recipe('legalaid.matter_type1', category=category) case.matter_type2 = make_recipe('legalaid.matter_type2', category=category) case.save() user = make_user() provider = make_recipe('cla_provider.provider', active=True) make_recipe('cla_provider.provider_allocation', weighted_distribution=0.5, provider=provider, category=category) helper = ProviderAllocationHelper() form = ProviderAllocationForm(case=case, data={ 'provider': helper.get_suggested_provider(category).pk}, providers=helper.get_qualifying_providers( category)) self.assertTrue(form.is_valid()) self.assertEqual(Log.objects.count(), 0) form.save(user) self.assertEqual(case.provider, provider) self.assertEqual(Log.objects.count(), 1)
def test_allocation_resets_when_weighting_changes( self, mock_openinghours_available): base_datetime = timezone.make_aware( datetime.datetime(day=7, month=7, year=2015, hour=12, minute=0), timezone.get_current_timezone()) category = make_recipe("legalaid.category") provider1 = make_recipe("cla_provider.provider", active=True) provider2 = make_recipe("cla_provider.provider", active=True) make_recipe("cla_provider.provider_allocation", weighted_distribution=1, provider=provider1, category=category) make_recipe("cla_provider.provider_allocation", weighted_distribution=1, provider=provider2, category=category) ProviderAllocation.objects.update(modified=base_datetime - datetime.timedelta(days=30)) existing_eligibility_checks = make_recipe( "legalaid.eligibility_check_yes", category=category, _quantity=50) new_eligibility_checks = make_recipe("legalaid.eligibility_check_yes", category=category, _quantity=50) with mock.patch("cla_common.call_centre_availability.current_datetime", base_datetime), mock.patch( "legalaid.models.timezone.now", return_value=base_datetime): for e in existing_eligibility_checks: as_of = base_datetime helper = ProviderAllocationHelper(as_of) d = make_recipe("diagnosis.diagnosis_yes", category=category) c = make_recipe("legalaid.eligible_case", eligibility_check=e, diagnosis=d) c.assign_to_provider(provider1) self.assertEqual(provider1.case_set.count(), 50) self.assertEqual(provider2.case_set.count(), 0) new_datetime = base_datetime + datetime.timedelta(days=1) ProviderAllocation.objects.update(modified=new_datetime) with mock.patch("cla_common.call_centre_availability.current_datetime", new_datetime), mock.patch( "legalaid.models.timezone.now", return_value=new_datetime): for e in new_eligibility_checks: as_of = new_datetime helper = ProviderAllocationHelper(as_of) d = make_recipe("diagnosis.diagnosis_yes", category=category) c = make_recipe("legalaid.eligible_case", eligibility_check=e, diagnosis=d) p = helper.get_suggested_provider(category) c.assign_to_provider(p) self.assertEqual(provider1.case_set.count(), 75) self.assertEqual(provider2.case_set.count(), 25)
def test_even_distribution(self, mock_openinghours_available): # Test the distribution of cases to {accuracy} accuracy over {total} cases total = 80 accuracy = Decimal("0.001") with mock.patch("cla_common.call_centre_availability.current_datetime", datetime.datetime(2015, 7, 7, 11, 59, 0)): helper = ProviderAllocationHelper() as_of = timezone.make_aware( datetime.datetime(day=7, month=7, year=2015, hour=12, minute=0), timezone.get_current_timezone()) category = make_recipe("legalaid.category") provider1 = make_recipe("cla_provider.provider", active=True) provider2 = make_recipe("cla_provider.provider", active=True) provider3 = make_recipe("cla_provider.provider", active=True) provider4 = make_recipe("cla_provider.provider", active=True) make_recipe("cla_provider.provider_allocation", weighted_distribution=5, provider=provider1, category=category) make_recipe("cla_provider.provider_allocation", weighted_distribution=1, provider=provider2, category=category) make_recipe("cla_provider.provider_allocation", weighted_distribution=1, provider=provider3, category=category) make_recipe("cla_provider.provider_allocation", weighted_distribution=1, provider=provider4, category=category) ProviderAllocation.objects.update(modified=as_of - datetime.timedelta(days=1)) ec = make_recipe("legalaid.eligibility_check_yes", category=category, _quantity=total) for n, e in enumerate(ec): d = make_recipe("diagnosis.diagnosis_yes", category=category) c = make_recipe("legalaid.eligible_case", id=n + 1, eligibility_check=e, diagnosis=d) p = helper.get_suggested_provider(category) c.assign_to_provider(p) self.assertEqual(Case.objects.all().count(), total) self.assertWithinAllowedAccuracy(50, accuracy, provider1.case_set.count()) self.assertWithinAllowedAccuracy(10, accuracy, provider2.case_set.count()) self.assertWithinAllowedAccuracy(10, accuracy, provider3.case_set.count()) self.assertWithinAllowedAccuracy(10, accuracy, provider4.case_set.count())
def test_get_qualifying_providers(self): category1 = make_recipe("legalaid.category") category2 = make_recipe("legalaid.category") cat1_provider1 = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.provider_allocation", weighted_distribution=0.5, provider=cat1_provider1, category=category1 ) cat1_provider2 = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.provider_allocation", weighted_distribution=0.5, provider=cat1_provider2, category=category1 ) cat2_provider1 = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.provider_allocation", weighted_distribution=0.5, provider=cat2_provider1, category=category2 ) helper = ProviderAllocationHelper() cat1_providers = helper.get_qualifying_providers(category1) self.assertItemsEqual(cat1_providers, [cat1_provider1, cat1_provider2]) # Set cat1_provider2.active == False => only one prov returned cat1_provider2.active = False cat1_provider2.save() helper = ProviderAllocationHelper() cat1_providers = helper.get_qualifying_providers(category1) self.assertItemsEqual(cat1_providers, [cat1_provider1])
def assign_suggest(self, request, reference=None, **kwargs): """ @return: dict - 'suggested_provider' (single item) ; 'suitable_providers' all possible providers for this category. """ as_of = None if 'as_of' in request.GET and (settings.DEBUG or settings.TEST_MODE): as_of = parser.parse(request.GET.get('as_of')) as_of = as_of.replace(tzinfo=timezone.get_current_timezone()) obj = self.get_object() helper = ProviderAllocationHelper(as_of=as_of) if hasattr(obj, 'eligibility_check') and obj.eligibility_check != None and obj.eligibility_check.category: category = obj.eligibility_check.category suggested = helper.get_suggested_provider(category) if suggested: suggested_provider = ProviderSerializer(suggested).data else: suggested_provider = None else: category = None suggested_provider = None suitable_providers = [ ProviderSerializer(p).data for p in helper.get_qualifying_providers(category)] suggestions = {'suggested_provider': suggested_provider, 'suitable_providers': suitable_providers, 'as_of': helper.as_of } return DRFResponse(suggestions)
def test__get_random_provider_with_empty_list(self, MockedProviderAllocation): MockedProviderAllocation.objects.filter.return_value = [] helper = ProviderAllocationHelper() winner = helper._get_random_provider(mock.MagicMock()) self.assertEqual(winner, None)
def test_get_suggested_provider_rota(self): as_of = timezone.make_aware( datetime.datetime(day=7, month=12, year=2014, hour=10, minute=0), timezone.get_current_timezone() ) category = make_recipe("legalaid.category") provider = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.outofhoursrota", provider=provider, start_date=as_of, end_date=as_of + datetime.timedelta(days=1), category=category, ) helper = ProviderAllocationHelper(as_of=as_of) choosen_provider = helper.get_suggested_provider(category) self.assertEqual(choosen_provider, provider) # Set cat1_provider2.active == False => only one prov returned provider.active = False provider.save() helper = ProviderAllocationHelper(as_of=as_of) choosen_provider = helper.get_suggested_provider(category) self.assertEqual(choosen_provider, None)
def test_save_out_office_hours_bank_holiday(self, timezone_mock, models_timezone_mock): _mock_datetime_now_with(datetime.datetime(2014, 1, 1, 9, 1, 0), timezone_mock, models_timezone_mock) case = make_recipe('legalaid.case') category = case.eligibility_check.category case.matter_type1 = make_recipe('legalaid.matter_type1', category=category) case.matter_type2 = make_recipe('legalaid.matter_type2', category=category) case.save() provider = make_recipe('cla_provider.provider', active=True) make_recipe('cla_provider.provider_allocation', weighted_distribution=0.5, provider=provider, category=category) helper = ProviderAllocationHelper() suggested = helper.get_suggested_provider(category) self.assertIsNone(suggested) form = ProviderAllocationForm(case=case, data={ 'provider': suggested.pk if suggested else None}, providers=helper.get_qualifying_providers( category)) self.assertFalse(form.is_valid()) self.assertEqual(Log.objects.count(), 0)
def test__get_random_provider_with_empty_list(self, MockedProviderAllocation): MockedProviderAllocation.objects.filter.return_value = [] helper = ProviderAllocationHelper() winner = helper._get_random_provider(mock.MagicMock()) self.assertEqual(winner, None)
def test_save_out_office_hours_saturday(self, timezone_mock, models_timezone_mock): _mock_datetime_now_with(datetime.datetime(2014, 11, 1, 10, 30, 0), timezone_mock, models_timezone_mock) case = make_recipe("legalaid.case") category = case.eligibility_check.category case.matter_type1 = make_recipe("legalaid.matter_type1", category=category) case.matter_type2 = make_recipe("legalaid.matter_type2", category=category) case.save() user = make_user() provider = make_recipe("cla_provider.provider", active=True) in_hours_provider = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.outofhoursrota", provider=provider, start_date=datetime.datetime( 2013, 12, 30).replace(tzinfo=timezone.get_current_timezone()), end_date=datetime.datetime( 2014, 12, 2).replace(tzinfo=timezone.get_current_timezone()), category=category, ) make_recipe("cla_provider.provider_allocation", weighted_distribution=1, provider=in_hours_provider, category=category) make_recipe("cla_provider.provider_allocation", weighted_distribution=0, provider=provider, category=category) with mock.patch.object( ProviderAllocationHelper, "_get_random_provider", return_value=in_hours_provider) as mocked_get_random_provider: helper = ProviderAllocationHelper() form = ProviderAllocationForm( case=case, data={"provider": helper.get_suggested_provider(category).pk}, providers=helper.get_qualifying_providers(category), ) self.assertEqual(mocked_get_random_provider.call_count, 0) self.assertTrue(form.is_valid()) self.assertEqual(Log.objects.count(), 0) form.save(user) self.assertEqual(case.provider, provider) self.assertEqual(Log.objects.count(), 1)
def setUp(self): self.category = make_recipe("legalaid.category") self.helper = ProviderAllocationHelper() self.date = timezone.now().replace(hour=0, minute=0, second=0) self.provider_allocations = make_recipe( "cla_provider.provider_allocation", category=self.category, weighted_distribution=1.0, provider__active=True, _quantity=10, )
def test_save_without_matter_type_category_mismatch( self, timezone_mock, models_timezone_mock): _mock_datetime_now_with(datetime.datetime(2014, 1, 2, 12, 59, 0), timezone_mock, models_timezone_mock) case = make_recipe("legalaid.case") category = case.eligibility_check.category provider = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.outofhoursrota", provider=provider, start_date=datetime.datetime( 2013, 12, 30).replace(tzinfo=timezone.get_current_timezone()), end_date=datetime.datetime( 2014, 1, 2).replace(tzinfo=timezone.get_current_timezone()), category=category, ) make_recipe("cla_provider.provider_allocation", weighted_distribution=0.5, provider=provider, category=category) case.matter_type1 = make_recipe("legalaid.matter_type1", category=category) other_category = make_recipe("legalaid.category") case.matter_type2 = make_recipe("legalaid.matter_type2", category=other_category) case.save() helper = ProviderAllocationHelper() form = ProviderAllocationForm( case=case, data={"provider": helper.get_suggested_provider(category).pk}, providers=helper.get_qualifying_providers(category), ) self.assertFalse(form.is_valid()) self.assertDictEqual( form.errors, { "__all__": [ u"Category of matter type 1: {category1} must match category of matter type 2: {category2}" .format(category1=category.name, category2=other_category.name), u"Category of Matter Types: {category1}, {category2} must match category of case: {case_category}" .format(category1=category.name, category2=other_category.name, case_category=category.name), ] }, )
def test_save_out_office_hours_saturday(self, timezone_mock, models_timezone_mock): _mock_datetime_now_with(datetime.datetime(2014, 11, 1, 10, 30, 0), timezone_mock, models_timezone_mock) case = make_recipe('legalaid.case') category = case.eligibility_check.category case.matter_type1 = make_recipe('legalaid.matter_type1', category=category) case.matter_type2 = make_recipe('legalaid.matter_type2', category=category) case.save() user = make_user() provider = make_recipe('cla_provider.provider', active=True) in_hours_provider = make_recipe('cla_provider.provider', active=True) make_recipe('cla_provider.outofhoursrota', provider=provider, start_date=datetime.datetime(2013, 12, 30).replace( tzinfo=timezone.get_current_timezone()), end_date=datetime.datetime(2014, 12, 2).replace( tzinfo=timezone.get_current_timezone()), category=category ) make_recipe('cla_provider.provider_allocation', weighted_distribution=1, provider=in_hours_provider, category=category) make_recipe('cla_provider.provider_allocation', weighted_distribution=0, provider=provider, category=category) with mock.patch.object(ProviderAllocationHelper, '_get_random_provider', return_value=in_hours_provider) as mocked_get_random_provider: helper = ProviderAllocationHelper() form = ProviderAllocationForm(case=case, data={ 'provider': helper.get_suggested_provider(category).pk}, providers=helper.get_qualifying_providers( category)) self.assertEqual(mocked_get_random_provider.call_count, 0) self.assertTrue(form.is_valid()) self.assertEqual(Log.objects.count(), 0) form.save(user) self.assertEqual(case.provider, provider) self.assertEqual(Log.objects.count(), 1)
def test_save_out_office_hours(self, timezone_mock, models_timezone_mock): _mock_datetime_now_with(datetime.datetime(2014, 1, 2, 8, 59, 0), timezone_mock, models_timezone_mock) case = make_recipe("legalaid.case") category = case.eligibility_check.category case.matter_type1 = make_recipe("legalaid.matter_type1", category=category) case.matter_type2 = make_recipe("legalaid.matter_type2", category=category) case.save() user = make_user() provider = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.outofhoursrota", provider=provider, start_date=datetime.datetime( 2013, 12, 30).replace(tzinfo=timezone.get_current_timezone()), end_date=datetime.datetime( 2014, 1, 2, 9, 0).replace(tzinfo=timezone.get_current_timezone()), category=category, ) make_recipe("cla_provider.provider_allocation", weighted_distribution=0.5, provider=provider, category=category) # TODO - create a ProviderAllocation for this provider with the # same category as the case and a positive weighted_distribution helper = ProviderAllocationHelper() form = ProviderAllocationForm( case=case, data={"provider": helper.get_suggested_provider(category).pk}, providers=helper.get_qualifying_providers(category), ) self.assertTrue(form.is_valid()) self.assertEqual(Log.objects.count(), 0) form.save(user) self.assertEqual(case.provider, provider) self.assertEqual(Log.objects.count(), 1)
def test_get_suggested_provider_best_fit(self, mock_openingHours_available): # slightly brute force test as_of = timezone.make_aware( datetime.datetime(day=8, month=12, year=2014, hour=10, minute=0), timezone.get_current_timezone()) category = make_recipe("legalaid.category") provider1 = make_recipe("cla_provider.provider", active=True) provider2 = make_recipe("cla_provider.provider", active=True) make_recipe("cla_provider.provider_allocation", weighted_distribution=0.5, provider=provider1, category=category) make_recipe("cla_provider.provider_allocation", weighted_distribution=1, provider=provider2, category=category) ProviderAllocation.objects.update(modified=as_of - datetime.timedelta(days=1)) helper = ProviderAllocationHelper(as_of=as_of) counts = {provider1: 0, provider2: 0} # quick sanity check that random allocation is working for i in range(100): sugg = helper.get_suggested_provider(category) counts[sugg] += 1 self.assertTrue(counts[provider2] > counts[provider1]) case1 = make_recipe("legalaid.eligible_case", diagnosis__category=category) case1.assign_to_provider(provider1) # cases assigned at != today are ignored, so expect same as before counts = {provider1: 0, provider2: 0} for i in range(100): sugg = helper.get_suggested_provider(category) counts[sugg] += 1 self.assertTrue(counts[provider2] > counts[provider1]) case1.provider_assigned_at = as_of case1.save() for i in range(100): self.assertEqual(helper.get_suggested_provider(category), provider2)
def test_even_allocation(self): # Test the distribution of cases to {accuracy} accuracy over {total} cases total = 8000 accuracy = Decimal("0.001") with mock.patch( "cla_common.call_centre_availability.current_datetime", datetime.datetime(2015, 7, 7, 11, 59, 0) ): helper = ProviderAllocationHelper() as_of = timezone.make_aware( datetime.datetime(day=7, month=7, year=2015, hour=12, minute=0), timezone.get_current_timezone() ) category = make_recipe("legalaid.category") provider1 = make_recipe("cla_provider.provider", active=True) provider2 = make_recipe("cla_provider.provider", active=True) provider3 = make_recipe("cla_provider.provider", active=True) provider4 = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.provider_allocation", weighted_distribution=5, provider=provider1, category=category ) make_recipe( "cla_provider.provider_allocation", weighted_distribution=1, provider=provider2, category=category ) make_recipe( "cla_provider.provider_allocation", weighted_distribution=1, provider=provider3, category=category ) make_recipe( "cla_provider.provider_allocation", weighted_distribution=1, provider=provider4, category=category ) ProviderAllocation.objects.update(modified=as_of - datetime.timedelta(days=1)) ec = make_recipe("legalaid.eligibility_check_yes", category=category, _quantity=total) for n, e in enumerate(ec): d = make_recipe("diagnosis.diagnosis_yes", category=category) c = make_recipe("legalaid.eligible_case", id=n + 1, eligibility_check=e, diagnosis=d) p = helper.get_suggested_provider(category) c.assign_to_provider(p) self.assertEqual(Case.objects.all().count(), total) self.assertWithinAllowedAccuracy(5000, accuracy, provider1.case_set.count()) self.assertWithinAllowedAccuracy(1000, accuracy, provider2.case_set.count()) self.assertWithinAllowedAccuracy(1000, accuracy, provider3.case_set.count()) self.assertWithinAllowedAccuracy(1000, accuracy, provider4.case_set.count())
def test_save_out_office_hours(self, timezone_mock, models_timezone_mock): _mock_datetime_now_with(datetime.datetime(2014, 1, 2, 8, 59, 0), timezone_mock, models_timezone_mock) case = make_recipe('legalaid.case') category = case.eligibility_check.category case.matter_type1 = make_recipe('legalaid.matter_type1', category=category) case.matter_type2 = make_recipe('legalaid.matter_type2', category=category) case.save() user = make_user() provider = make_recipe('cla_provider.provider', active=True) make_recipe('cla_provider.outofhoursrota', provider=provider, start_date=datetime.datetime(2013, 12, 30).replace( tzinfo=timezone.get_current_timezone()), end_date=datetime.datetime(2014, 1, 2).replace( tzinfo=timezone.get_current_timezone()), category=category ) make_recipe('cla_provider.provider_allocation', weighted_distribution=0.5, provider=provider, category=category) # TODO - create a ProviderAllocation for this provider with the # same category as the case and a positive weighted_distribution helper = ProviderAllocationHelper() form = ProviderAllocationForm(case=case, data={ 'provider': helper.get_suggested_provider(category).pk}, providers=helper.get_qualifying_providers( category)) self.assertTrue(form.is_valid()) self.assertEqual(Log.objects.count(), 0) form.save(user) self.assertEqual(case.provider, provider) self.assertEqual(Log.objects.count(), 1)
def test_save_without_matter_type_category_mismatch(self, timezone_mock, models_timezone_mock): _mock_datetime_now_with(datetime.datetime(2014, 1, 2, 12, 59, 0), timezone_mock, models_timezone_mock) case = make_recipe("legalaid.case") category = case.eligibility_check.category provider = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.outofhoursrota", provider=provider, start_date=datetime.datetime(2013, 12, 30).replace(tzinfo=timezone.get_current_timezone()), end_date=datetime.datetime(2014, 1, 2).replace(tzinfo=timezone.get_current_timezone()), category=category, ) make_recipe( "cla_provider.provider_allocation", weighted_distribution=0.5, provider=provider, category=category ) case.matter_type1 = make_recipe("legalaid.matter_type1", category=category) other_category = make_recipe("legalaid.category") case.matter_type2 = make_recipe("legalaid.matter_type2", category=other_category) case.save() helper = ProviderAllocationHelper() form = ProviderAllocationForm( case=case, data={"provider": helper.get_suggested_provider(category).pk}, providers=helper.get_qualifying_providers(category), ) self.assertFalse(form.is_valid()) self.assertDictEqual( form.errors, { "__all__": [ u"Category of matter type 1: {category1} must match category of matter type 2: {category2}".format( category1=category.name, category2=other_category.name ), u"Category of Matter Types: {category1}, {category2} must match category of case: {case_category}".format( category1=category.name, category2=other_category.name, case_category=category.name ), ] }, )
def _test__get_random_provider(self, alloc_data, num_iterations=100000): # print "\n\nNew test" helper = ProviderAllocationHelper() helper._providers_in_category = self.build_providers(alloc_data) results = defaultdict(int) category = mock.MagicMock() for i in range(0, num_iterations): winner = helper._get_random_provider(category) results[winner.id] += 1 for id, count in results.items(): prob = (count * 100.) / num_iterations # print 'expected %s - found %s. Difference %s' % ( # alloc_data[id]['expected_prob'], prob, # ((alloc_data[id]['expected_prob'] * 0.01) * num_iterations) - \ # ((prob * 0.01) * num_iterations) # ) self.assertAlmostEqual(prob, alloc_data[id]['expected_prob'], delta=1.5)
def _test__get_random_provider(self, alloc_data, num_iterations=100000): # print "\n\nNew test" helper = ProviderAllocationHelper() helper._providers_in_category = self.build_providers(alloc_data) results = defaultdict(int) category = mock.MagicMock() for i in range(0, num_iterations): winner = helper._get_random_provider(category) results[winner.id] += 1 for id, count in results.items(): prob = (count * 100.0) / num_iterations # print 'expected %s - found %s. Difference %s' % ( # alloc_data[id]['expected_prob'], prob, # ((alloc_data[id]['expected_prob'] * 0.01) * num_iterations) - \ # ((prob * 0.01) * num_iterations) # ) self.assertAlmostEqual(prob, alloc_data[id]["expected_prob"], delta=1.5)
def test_get_suggested_provider_best_fit(self): # slightly brute force test as_of = timezone.make_aware( datetime.datetime(day=8, month=12, year=2014, hour=10, minute=0), timezone.get_current_timezone() ) category = make_recipe("legalaid.category") provider1 = make_recipe("cla_provider.provider", active=True) provider2 = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.provider_allocation", weighted_distribution=0.5, provider=provider1, category=category ) make_recipe("cla_provider.provider_allocation", weighted_distribution=1, provider=provider2, category=category) ProviderAllocation.objects.update(modified=as_of - datetime.timedelta(days=1)) helper = ProviderAllocationHelper(as_of=as_of) counts = {provider1: 0, provider2: 0} # quick sanity check that random allocation is working for i in range(100): sugg = helper.get_suggested_provider(category) counts[sugg] += 1 self.assertTrue(counts[provider2] > counts[provider1]) case1 = make_recipe("legalaid.eligible_case", diagnosis__category=category) case1.assign_to_provider(provider1) # cases assigned at != today are ignored, so expect same as before counts = {provider1: 0, provider2: 0} for i in range(100): sugg = helper.get_suggested_provider(category) counts[sugg] += 1 self.assertTrue(counts[provider2] > counts[provider1]) case1.provider_assigned_at = as_of case1.save() for i in range(100): self.assertEqual(helper.get_suggested_provider(category), provider2)
def test_get_suggested_provider_rota(self): as_of = timezone.make_aware( datetime.datetime(day=7, month=12, year=2014, hour=10, minute=0), timezone.get_current_timezone()) category = make_recipe("legalaid.category") provider = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.outofhoursrota", provider=provider, start_date=as_of, end_date=as_of + datetime.timedelta(days=1), category=category, ) helper = ProviderAllocationHelper(as_of=as_of) choosen_provider = helper.get_suggested_provider(category) self.assertEqual(choosen_provider, provider) # Set cat1_provider2.active == False => only one prov returned provider.active = False provider.save() helper = ProviderAllocationHelper(as_of=as_of) choosen_provider = helper.get_suggested_provider(category) self.assertEqual(choosen_provider, None)
def test_get_suggested_provider_random(self): as_of = timezone.make_aware( datetime.datetime(day=8, month=12, year=2014, hour=10, minute=0), timezone.get_current_timezone()) category = make_recipe("legalaid.category") provider = make_recipe("cla_provider.provider", active=True) make_recipe("cla_provider.provider_allocation", weighted_distribution=0.5, provider=provider, category=category) helper = ProviderAllocationHelper(as_of=as_of) choosen_provider = helper._get_random_provider(category) self.assertEqual(choosen_provider, provider) # Set cat1_provider2.active == False => only one prov returned provider.active = False provider.save() helper = ProviderAllocationHelper(as_of=as_of) choosen_provider = helper.get_suggested_provider(category) self.assertEqual(choosen_provider, None)
def test_get_qualifying_providers(self): category1 = make_recipe("legalaid.category") category2 = make_recipe("legalaid.category") cat1_provider1 = make_recipe("cla_provider.provider", active=True) make_recipe("cla_provider.provider_allocation", weighted_distribution=0.5, provider=cat1_provider1, category=category1) cat1_provider2 = make_recipe("cla_provider.provider", active=True) make_recipe("cla_provider.provider_allocation", weighted_distribution=0.5, provider=cat1_provider2, category=category1) cat2_provider1 = make_recipe("cla_provider.provider", active=True) make_recipe("cla_provider.provider_allocation", weighted_distribution=0.5, provider=cat2_provider1, category=category2) helper = ProviderAllocationHelper() cat1_providers = helper.get_qualifying_providers(category1) self.assertItemsEqual(cat1_providers, [cat1_provider1, cat1_provider2]) # Set cat1_provider2.active == False => only one prov returned cat1_provider2.active = False cat1_provider2.save() helper = ProviderAllocationHelper() cat1_providers = helper.get_qualifying_providers(category1) self.assertItemsEqual(cat1_providers, [cat1_provider1])
def assign(self, request, reference=None, **kwargs): """ Assigns the case to a provider """ obj = self.get_object() helper = ProviderAllocationHelper() category = obj.eligibility_check.category if obj.eligibility_check else None suitable_providers = helper.get_qualifying_providers(category) # find given provider in suitable - avoid extra lookup and ensures # valid provider for sp in suitable_providers: if sp.id == int(request.DATA['provider_id']): p = sp break else: raise ValueError("Provider not found") # if we're inside office hours then: # Randomly assign to provider who offers this category of service # else it should be the on duty provider data = request.DATA.copy() data['provider'] = p.pk form = ProviderAllocationForm(case=obj, data=data, providers=suitable_providers) if form.is_valid(): provider = form.save(request.user) notify_case_assigned(provider, form.case) provider_serialised = ProviderSerializer(provider) return DRFResponse(data=provider_serialised.data) return DRFResponse( dict(form.errors), status=status.HTTP_400_BAD_REQUEST )
def test_get_suggested_provider_random(self): as_of = timezone.make_aware( datetime.datetime(day=8, month=12, year=2014, hour=10, minute=0), timezone.get_current_timezone() ) category = make_recipe("legalaid.category") provider = make_recipe("cla_provider.provider", active=True) make_recipe( "cla_provider.provider_allocation", weighted_distribution=0.5, provider=provider, category=category ) helper = ProviderAllocationHelper(as_of=as_of) choosen_provider = helper._get_random_provider(category) self.assertEqual(choosen_provider, provider) # Set cat1_provider2.active == False => only one prov returned provider.active = False provider.save() helper = ProviderAllocationHelper(as_of=as_of) choosen_provider = helper.get_suggested_provider(category) self.assertEqual(choosen_provider, None)
class ProviderAllocationHelperTestCase(TestCase): def setUp(self): self.category = make_recipe("legalaid.category") self.helper = ProviderAllocationHelper() self.date = timezone.now().replace(hour=0, minute=0, second=0) self.provider_allocations = make_recipe( "cla_provider.provider_allocation", category=self.category, weighted_distribution=1.0, provider__active=True, _quantity=10, ) @mock.patch( "cla_provider.helpers.ProviderAllocationHelper._get_random_provider") @mock.patch( "cla_provider.helpers.ProviderDistributionHelper.get_distribution") def test_best_fit_provider_shortcut_no_cases_for_today( self, mocked_helper, mocked_random_provider_helper): mocked_helper.return_value = {} mocked_random_provider_helper.return_value = "TEST" ret = self.helper._get_best_fit_provider(self.category) self.assertTrue(mocked_helper.called) self.assertTrue(mocked_random_provider_helper.called) self.assertEqual(ret, "TEST") @mock.patch( "cla_provider.helpers.ProviderAllocationHelper._get_random_provider") @mock.patch( "cla_provider.helpers.ProviderDistributionHelper.get_distribution") def test_best_fit_provider_shortcut_current_is_ideal( self, mocked_helper, mocked_random_provider_helper): pd_helper = ProviderDistributionHelper(self.date) mocked_helper.return_value = pd_helper.make_ideal( 10, self.provider_allocations) mocked_random_provider_helper.return_value = "TEST" ret = self.helper._get_best_fit_provider(self.category) self.assertTrue(mocked_helper.called) self.assertTrue(mocked_random_provider_helper.called) self.assertEqual(ret, "TEST") @mock.patch( "cla_provider.helpers.ProviderAllocationHelper._get_random_provider") @mock.patch( "cla_provider.helpers.ProviderDistributionHelper.get_distribution") def test_best_fit_provider_current_is_notideal_only1( self, mocked_helper, mocked_random_provider_helper): pd_helper = ProviderDistributionHelper(self.date) ideal = pd_helper.make_ideal(10, self.provider_allocations) ideal[ideal.keys()[0]] = 0.0 mocked_helper.return_value = ideal mocked_random_provider_helper.return_value = "TEST" ret = self.helper._get_best_fit_provider(self.category) self.assertTrue(mocked_helper.called) self.assertFalse(mocked_random_provider_helper.called) self.assertNotEqual(ret, "TEST") self.assertEqual(ret.id, ideal.keys()[0]) @skip("because test is flaky... waiting for Python dev to fix") @mock.patch( "cla_provider.helpers.ProviderAllocationHelper._get_random_provider") @mock.patch( "cla_provider.helpers.ProviderDistributionHelper.get_distribution") def test_best_fit_provider_current_is_notideal_2( self, mocked_helper, mocked_random_provider_helper): pd_helper = ProviderDistributionHelper(self.date) ideal = pd_helper.make_ideal(10, self.provider_allocations) ideal[ideal.keys()[0]] = 0.0 ideal[ideal.keys()[1]] = 0.0 mocked_helper.return_value = ideal mocked_random_provider_helper.return_value = "TEST" ret = self.helper._get_best_fit_provider(self.category) self.assertTrue(mocked_helper.called) mocked_random_provider_helper.assert_called_once_with( self.category, limit_choices_to=ideal.keys()[:2]) self.assertEqual(ret, "TEST")