Пример #1
0
    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"]})
Пример #2
0
    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())
Пример #3
0
    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())
Пример #6
0
    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])
Пример #7
0
    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)
Пример #8
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)
Пример #9
0
    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)
Пример #10
0
    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)
Пример #12
0
    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,
     )
Пример #14
0
    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),
                ]
            },
        )
Пример #15
0
    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)
Пример #16
0
    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)
Пример #18
0
    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())
Пример #19
0
    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)
Пример #20
0
    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
                    ),
                ]
            },
        )
Пример #21
0
    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)
Пример #23
0
    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])
Пример #27
0
    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
        )
Пример #28
0
    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")