Ejemplo n.º 1
0
    def setUp(self):
        super().setUp()
        self.activated_user = UserFactory()
        self.assigned_user = UserFactory()
        self.unlicensed_user = UserFactory()
        self.enterprise_customer_uuid = uuid4()
        self.enterprise_catalog_uuid = uuid4()
        self.course_key = 'testX'

        self.customer_agreement = CustomerAgreementFactory(
            enterprise_customer_uuid=self.enterprise_customer_uuid, )
        self.active_subscription_for_customer = SubscriptionPlanFactory.create(
            customer_agreement=self.customer_agreement,
            enterprise_catalog_uuid=self.enterprise_catalog_uuid,
            is_active=True,
        )
        self.activated_license = LicenseFactory.create(
            status=constants.ACTIVATED,
            user_email=self.activated_user.email,
            subscription_plan=self.active_subscription_for_customer,
        )
        self.assigned_license = LicenseFactory.create(
            status=constants.ASSIGNED,
            user_email=self.assigned_user.email,
            subscription_plan=self.active_subscription_for_customer,
        )
    def test_1_subscription_expiring_outside_date_range(
            self, mock_license_expiration_task):
        """
        Verifies that only expired subscriptions within the expired range
        have their license uuids sent to edx-enterprise
        """
        # A recently expired subscription that should be processed
        expired_subscription = SubscriptionPlanFactory.create(
            start_date=self.today - timedelta(days=7),
            expiration_date=self.today,
        )

        # An expired subscription that expired about a month ago
        older_expired_subscription = SubscriptionPlanFactory.create(
            start_date=self.today - timedelta(days=60),
            expiration_date=self.today - timedelta(days=30),
        )

        # Create an activated license on each subscription
        license_to_expire_enrollments = LicenseFactory.create(
            status=ACTIVATED, subscription_plan=expired_subscription)
        LicenseFactory.create(status=ACTIVATED,
                              subscription_plan=older_expired_subscription)

        call_command(self.command_name)
        mock_license_expiration_task.assert_called_with(
            [str(license_to_expire_enrollments.uuid)])
Ejemplo n.º 3
0
    def test_renewal_processed_with_no_existing_future_plan(self):
        prior_plan = SubscriptionPlanFactory()
        original_activated_licenses = [
            LicenseFactory.create(
                subscription_plan=prior_plan,
                status=constants.ACTIVATED,
                user_email='activated_user_{}@example.com'.format(i))
            for i in range(5)
        ]
        original_assigned_licenses = [
            LicenseFactory.create(
                subscription_plan=prior_plan,
                status=constants.ASSIGNED,
                user_email='assigned_user_{}@example.com'.format(i))
            for i in range(5)
        ]
        original_licenses = original_activated_licenses + original_assigned_licenses

        renewal = SubscriptionPlanRenewalFactory(
            prior_subscription_plan=prior_plan,
            number_of_licenses=10,
            license_types_to_copy=constants.LicenseTypesToRenew.
            ASSIGNED_AND_ACTIVATED)

        with freezegun.freeze_time(NOW):
            api.renew_subscription(renewal)

        renewal.refresh_from_db()
        original_plan = renewal.prior_subscription_plan
        future_plan = renewal.renewed_subscription_plan
        self.assertTrue(renewal.processed)
        self.assertEqual(renewal.processed_datetime, NOW)
        self.assertEqual(original_plan.product_id, future_plan.product_id)
        self.assertEqual(future_plan.num_licenses, renewal.number_of_licenses)
        self._assert_all_licenses_renewed(future_plan)
    def test_2_subscriptions_expiring_within_range(
            self, mock_license_expiration_task):
        """
        Verifies that all expired subscriptions within the expired range have their license uuids sent to edx-enterprise
        """
        expired_subscription_1 = SubscriptionPlanFactory.create(
            start_date=datetime.strptime('2013-1-01', '%Y-%m-%d'),
            expiration_date=datetime.strptime('2014-1-01', '%Y-%m-%d'),
        )

        expired_subscription_2 = SubscriptionPlanFactory.create(
            start_date=datetime.strptime('2015-1-01', '%Y-%m-%d'),
            expiration_date=datetime.strptime('2016-1-01', '%Y-%m-%d'),
        )

        # Create an activated license on each subscription
        expired_license_1 = LicenseFactory.create(
            status=ACTIVATED, subscription_plan=expired_subscription_1)
        expired_license_2 = LicenseFactory.create(
            status=ACTIVATED, subscription_plan=expired_subscription_2)

        call_command(self.command_name, "--expired-after=2013-1-01",
                     "--expired-before=2016-1-01")
        actual_args = mock_license_expiration_task.call_args_list[0][0][0]
        assert sorted(actual_args) == sorted(
            [str(expired_license_1.uuid),
             str(expired_license_2.uuid)])
Ejemplo n.º 5
0
    def setUpTestData(cls):
        super().setUpTestData()

        # technically this will be off on leap years, but we just need something later than now, so it's not a problem
        ONE_YEAR_FROM_NOW = localized_datetime_from_datetime(datetime.now() + timedelta(days=365))
        TWO_YEARS_FROM_NOW = localized_datetime_from_datetime(datetime.now() + timedelta(days=730))

        cls.user_email = '*****@*****.**'
        cls.enterprise_customer_uuid = uuid.uuid4()
        cls.customer_agreement = CustomerAgreementFactory.create(
            enterprise_customer_uuid=cls.enterprise_customer_uuid,
        )

        cls.subscription_plan = SubscriptionPlanFactory()

        cls.active_current_plan = SubscriptionPlanFactory.create(
            customer_agreement=cls.customer_agreement,
            is_active=True,
            start_date=localized_datetime(2021, 1, 1),
            expiration_date=ONE_YEAR_FROM_NOW,
        )
        cls.active_current_license = LicenseFactory.create(
            user_email=cls.user_email,
            subscription_plan=cls.active_current_plan,
        )

        cls.inactive_current_plan = SubscriptionPlanFactory.create(
            customer_agreement=cls.customer_agreement,
            is_active=False,
            start_date=localized_datetime(2021, 1, 1),
            expiration_date=ONE_YEAR_FROM_NOW,
        )
        cls.inactive_current_license = LicenseFactory.create(
            user_email=cls.user_email,
            subscription_plan=cls.inactive_current_plan,
        )

        cls.non_current_active_plan = SubscriptionPlanFactory.create(
            customer_agreement=cls.customer_agreement,
            is_active=True,
            start_date=ONE_YEAR_FROM_NOW,
            expiration_date=TWO_YEARS_FROM_NOW,
        )
        cls.non_current_active_license = LicenseFactory.create(
            user_email=cls.user_email,
            subscription_plan=cls.non_current_active_plan,
        )

        cls.non_current_inactive_plan = SubscriptionPlanFactory.create(
            customer_agreement=cls.customer_agreement,
            is_active=False,
            start_date=ONE_YEAR_FROM_NOW,
            expiration_date=TWO_YEARS_FROM_NOW,
        )
        cls.non_current_inactive_license = LicenseFactory.create(
            user_email=cls.user_email,
            subscription_plan=cls.non_current_inactive_plan,
        )
    def _create_expired_plan_with_licenses(self,
                                           unassigned_licenses_count=1,
                                           assigned_licenses_count=2,
                                           activated_licenses_count=3,
                                           revoked_licenses_count=4,
                                           start_date=today -
                                           timedelta(days=7),
                                           expiration_date=today,
                                           expiration_processed=False):
        """
        Creates a plan with licenses. The plan is expired by default.
        """
        expired_plan = SubscriptionPlanFactory.create(
            start_date=start_date,
            expiration_date=expiration_date,
            expiration_processed=expiration_processed)

        LicenseFactory.create_batch(unassigned_licenses_count,
                                    status=UNASSIGNED,
                                    subscription_plan=expired_plan)
        LicenseFactory.create_batch(assigned_licenses_count,
                                    status=ASSIGNED,
                                    subscription_plan=expired_plan)
        LicenseFactory.create_batch(activated_licenses_count,
                                    status=ACTIVATED,
                                    subscription_plan=expired_plan)
        LicenseFactory.create_batch(revoked_licenses_count,
                                    status=REVOKED,
                                    subscription_plan=expired_plan)

        return expired_plan
    def test_1_subscription_expiring_today(self, mock_license_expiration_task):
        """
        When there is a subscription expiring verify only the assigned and activated licenses are sent to edx-enterprise
        """
        expired_subscription = SubscriptionPlanFactory.create(
            start_date=self.today - timedelta(days=7),
            expiration_date=self.today,
        )

        # Create licenses with a variety of statuses
        LicenseFactory.create_batch(3, subscription_plan=expired_subscription)
        LicenseFactory.create_batch(2,
                                    status=ASSIGNED,
                                    subscription_plan=expired_subscription)
        LicenseFactory.create(status=ACTIVATED,
                              subscription_plan=expired_subscription)
        LicenseFactory.create(status=REVOKED,
                              subscription_plan=expired_subscription)

        call_command(self.command_name)
        expired_license_uuids = [
            str(license.uuid)
            for license in expired_subscription.licenses.filter(
                status__in=[ASSIGNED, ACTIVATED])
        ]
        mock_license_expiration_task.assert_called_with(expired_license_uuids)
Ejemplo n.º 8
0
    def test_activated_license_is_revoked(
        self,
        is_revocation_cap_enabled,
    ):
        agreement = CustomerAgreementFactory.create(
            enterprise_customer_uuid=uuid.UUID(
                '00000000-1111-2222-3333-444444444444'), )
        subscription_plan = SubscriptionPlanFactory.create(
            customer_agreement=agreement,
            is_revocation_cap_enabled=is_revocation_cap_enabled,
            num_revocations_applied=0,
            revoke_max_percentage=100,
        )
        original_license = LicenseFactory.create(
            status=constants.ACTIVATED,
            subscription_plan=subscription_plan,
            lms_user_id=123,
        )

        with freezegun.freeze_time(NOW):
            api.revoke_license(original_license)

        original_license.refresh_from_db()
        self.assertEqual(original_license.status, constants.REVOKED)
        self.assertEqual(original_license.revoked_date, NOW)

        # There should now be 1 unassigned license
        self.assertEqual(subscription_plan.unassigned_licenses.count(), 1)
Ejemplo n.º 9
0
def test_track_license_changes_with_properties(mock_track_event, _):
    licenses = LicenseFactory.create_batch(5)
    track_license_changes(licenses, SegmentEvents.LICENSE_CREATED,
                          {'counter': 2})
    assert mock_track_event.call_count == 5
    mock_track_event.assert_called_with(None, SegmentEvents.LICENSE_CREATED,
                                        {'counter': 2})
Ejemplo n.º 10
0
    def test_license_renewed_to_and_from(self):
        """
        Tests that links between renewed licenses are sane.
        """
        original = LicenseFactory.create()
        future = LicenseFactory.create()

        original.renewed_to = future
        original.save()
        future.save()

        self.assertEqual(future.renewed_from, original)

        another_one = LicenseFactory.create()
        self.assertIsNone(another_one.renewed_to)
        self.assertIsNone(another_one.renewed_from)
Ejemplo n.º 11
0
def make_test_email_data():
    """
    Returns a dictionary of data needed to send emails
    """

    # Create a SubscriptionPlan and associate a batch of licenses using Factories
    subscription = SubscriptionPlanFactory()
    licenses = LicenseFactory.create_batch(6)
    subscription.licenses.set(licenses)

    custom_template_text = {
        'greeting': 'Hello',
        'closing': 'Goodbye',
    }

    email_recipient_list = [
        '*****@*****.**',
        '*****@*****.**',
        '*****@*****.**',
    ]

    # Use emails from list created above to create assigned licenses
    for lic, email in zip(licenses, email_recipient_list):
        lic.user_email = email
        lic.status = ASSIGNED
        lic.save()

    return {
        'subscription_plan': subscription,
        'licenses': licenses,
        'custom_template_text': custom_template_text,
        'email_recipient_list': email_recipient_list
    }
Ejemplo n.º 12
0
    def test_cannot_renew_with_existing_assigned_future_licenses(self):
        future_plan = SubscriptionPlanFactory()
        LicenseFactory.create_batch(
            5,
            subscription_plan=future_plan,
            status=constants.ACTIVATED,
        )
        renewal = SubscriptionPlanRenewalFactory(
            renewed_subscription_plan=future_plan,
            number_of_licenses=20,
        )

        expected_message = 'there are existing licenses in the renewed plan that are activated'
        with self.assertRaisesRegex(exceptions.RenewalProcessingError,
                                    expected_message):
            api.renew_subscription(renewal)
Ejemplo n.º 13
0
    def test_cannot_renew_too_many_existing_unassigned_licenses(self):
        future_plan = SubscriptionPlanFactory()
        LicenseFactory.create_batch(
            50,
            subscription_plan=future_plan,
            status=constants.UNASSIGNED,
        )
        renewal = SubscriptionPlanRenewalFactory(
            renewed_subscription_plan=future_plan,
            number_of_licenses=20,
        )

        expected_message = 'More licenses exist than were requested to be renewed'
        with self.assertRaisesRegex(exceptions.RenewalProcessingError,
                                    expected_message):
            api.renew_subscription(renewal)
Ejemplo n.º 14
0
    def test_cannot_renew_for_fewer_licenses(self):
        prior_plan = SubscriptionPlanFactory()
        LicenseFactory.create_batch(
            5,
            subscription_plan=prior_plan,
            status=constants.ACTIVATED,
        )
        renewal = SubscriptionPlanRenewalFactory(
            number_of_licenses=2,
            prior_subscription_plan=prior_plan,
        )

        expected_message = 'Cannot renew for fewer than the number of original activated licenses.'
        with self.assertRaisesRegex(exceptions.RenewalProcessingError,
                                    expected_message):
            api.renew_subscription(renewal)
Ejemplo n.º 15
0
    def test_bulk_revoked_event(self, *_):
        """
        Test that bulk revoking licenses  triggers the right set of events:
        revoke event and creation of a fresh license
        the customer can now use as a replacement.
        """
        self._setup_request_jwt(user=self.user)
        alice_license = LicenseFactory.create(user_email='*****@*****.**',
                                              status=constants.ACTIVATED)
        bob_license = LicenseFactory.create(user_email='*****@*****.**',
                                            status=constants.ACTIVATED)
        self.subscription_plan.licenses.set([alice_license, bob_license])

        request_payload = {
            'user_emails': [
                '*****@*****.**',
                '*****@*****.**',
            ],
        }

        # Patch differently because the modules import track_event differently:
        with mock.patch('license_manager.apps.subscriptions.models.track_event') as mock_revoke_track_event, \
                mock.patch('license_manager.apps.subscriptions.event_utils.track_event') as mock_create_track_event:
            response = self.api_client.post(self.bulk_revoke_license_url,
                                            request_payload)
            assert response.status_code == status.HTTP_204_NO_CONTENT

            assert mock_revoke_track_event.call_count == 2
            assert mock_create_track_event.call_count == 2

            assert (mock_revoke_track_event.call_args_list[0][0][1] ==
                    constants.SegmentEvents.LICENSE_REVOKED)
            assert (mock_revoke_track_event.call_args_list[0][0][2]
                    ['assigned_email'] == '*****@*****.**')
            assert (mock_create_track_event.call_args_list[0][0][1] ==
                    constants.SegmentEvents.LICENSE_CREATED)
            assert mock_create_track_event.call_args_list[0][0][2][
                'assigned_email'] == ''

            assert (mock_revoke_track_event.call_args_list[1][0][1] ==
                    constants.SegmentEvents.LICENSE_REVOKED)
            assert (mock_revoke_track_event.call_args_list[1][0][2]
                    ['assigned_email'] == '*****@*****.**')
            assert (mock_create_track_event.call_args_list[1][0][1] ==
                    constants.SegmentEvents.LICENSE_CREATED)
            assert mock_create_track_event.call_args_list[1][0][2][
                'assigned_email'] == ''
Ejemplo n.º 16
0
 def test_basic_bulk_create_event(self):
     """
     Basic test to make sure batch creates trigger create event.
     """
     # Mock the calls to track_event specifically imported in the models file.
     with mock.patch('license_manager.apps.subscriptions.models.track_event'
                     ) as mock_track_event:
         num_licenses = 5
         LicenseFactory.create_batch(
             num_licenses,
             subscription_plan=self.subscription_plan,
             status=constants.UNASSIGNED,
         )
         assert mock_track_event.call_count == num_licenses
         for call in mock_track_event.call_args_list:
             # We should have events all called with the created event:
             assert call[0][1] == constants.SegmentEvents.LICENSE_CREATED
Ejemplo n.º 17
0
    def test_save(self, new_status):
        """
        Test that validation for duplicate assigned/activated licenses occurs on save.
        """
        LicenseFactory.create(
            user_email=self.user_email,
            subscription_plan=self.active_current_plan,
            status=ASSIGNED
        )

        unassigned_license = LicenseFactory.create(
            user_email=self.user_email,
            subscription_plan=self.active_current_plan,
            status=UNASSIGNED
        )

        with self.assertRaises(ValidationError):
            unassigned_license.status = new_status
            unassigned_license.save()
Ejemplo n.º 18
0
 def test_subscription_factory_licenses(self):
     """
     Verify a subscription plan factory can have licenses associated with it.
     """
     subscription = SubscriptionPlanFactory()
     licenses = LicenseFactory.create_batch(5)
     subscription.licenses.set(licenses)
     # Verify the subscription plan uuid is correctly set on the licenses
     license = subscription.licenses.first()
     self.assertEqual(subscription.uuid, license.subscription_plan.uuid)
Ejemplo n.º 19
0
    def test_license_renewed_events(self):
        """ Test that our standard renewal routine triggers the right set of events
        for all licenses involved:
            - a creation event for each new license
            - NO assignment or activation event since the license comes from a renewal.
            - a renewal event for each old/new license pair
        """
        prior_plan = SubscriptionPlanFactory()
        original_activated_licenses = [
            LicenseFactory.create(
                subscription_plan=prior_plan,
                status=constants.ACTIVATED,
                user_email='activated_user_{}@example.com'.format(i))
            for i in range(2)
        ]
        original_assigned_licenses = [
            LicenseFactory.create(
                subscription_plan=prior_plan,
                status=constants.ASSIGNED,
                user_email='assigned_user_{}@example.com'.format(i))
            for i in range(2)
        ]
        original_licenses = original_activated_licenses + original_assigned_licenses

        renewal = SubscriptionPlanRenewalFactory(
            prior_subscription_plan=prior_plan,
            number_of_licenses=len(original_licenses),
            license_types_to_copy=constants.LicenseTypesToRenew.
            ASSIGNED_AND_ACTIVATED)

        with mock.patch(
                'license_manager.apps.subscriptions.event_utils.track_event'
        ) as mock_track_event:
            with freeze_time(NOW):
                api.renew_subscription(renewal)
            renewal.refresh_from_db()

            for call in mock_track_event.call_args_list[0:4]:
                assert call[0][1] == constants.SegmentEvents.LICENSE_CREATED

            for call in mock_track_event.call_args_list[4:]:
                assert call[0][1] == constants.SegmentEvents.LICENSE_RENEWED
            assert mock_track_event.call_count == 8
Ejemplo n.º 20
0
 def test_license_factory(self):
     """
     Verify an unassigned license is created and associated with a subscription.
     """
     license = LicenseFactory()
     self.assertEqual(license.status, UNASSIGNED)
     subscription_licenses = [
         license.uuid
         for license in license.subscription_plan.licenses.all()
     ]
     self.assertIn(license.uuid, subscription_licenses)
Ejemplo n.º 21
0
    def test_delete_unassigned_licenses_post_freeze(self):
        subscription_plan = SubscriptionPlanFactory(
            can_freeze_unused_licenses=True)
        LicenseFactory.create_batch(
            5,
            subscription_plan=subscription_plan,
            status=constants.UNASSIGNED,
        )
        LicenseFactory.create_batch(
            2,
            subscription_plan=subscription_plan,
            status=constants.ASSIGNED,
        )
        LicenseFactory.create_batch(
            1,
            subscription_plan=subscription_plan,
            status=constants.ACTIVATED,
        )

        with freezegun.freeze_time(NOW):
            api.delete_unused_licenses_post_freeze(subscription_plan)

        assert subscription_plan.unassigned_licenses.count() == 0
        assert subscription_plan.assigned_licenses.count() == 2
        assert subscription_plan.activated_licenses.count() == 1

        assert subscription_plan.last_freeze_timestamp == NOW
Ejemplo n.º 22
0
    def test_renewal_processed_with_existing_future_plan(self):
        prior_plan = SubscriptionPlanFactory()
        original_licenses = [
            LicenseFactory.create(
                subscription_plan=prior_plan,
                status=constants.ACTIVATED,
                user_email='activated_user_{}@example.com'.format(i))
            for i in range(5)
        ]

        # create some revoked original licenses that should not be renewed
        LicenseFactory.create_batch(
            67,
            subscription_plan=prior_plan,
            status=constants.REVOKED,
        )

        future_plan = SubscriptionPlanFactory()
        LicenseFactory.create_batch(
            10,
            subscription_plan=future_plan,
            status=constants.UNASSIGNED,
        )
        renewal = SubscriptionPlanRenewalFactory(
            prior_subscription_plan=prior_plan,
            renewed_subscription_plan=future_plan,
            number_of_licenses=10,
        )

        with freezegun.freeze_time(NOW):
            api.renew_subscription(renewal)

        future_plan.refresh_from_db()
        self.assertTrue(renewal.processed)
        self.assertEqual(renewal.processed_datetime, NOW)
        self.assertEqual(future_plan.num_licenses, renewal.number_of_licenses)
        self._assert_all_licenses_renewed(future_plan)
    def test_expiring_10k_licenses_batched(self, mock_license_expiration_task):
        """
        Verifies that all expired subscriptions within the expired range have their license uuids sent to edx-enterprise
        """
        # A recently expired subscription that should be processed
        expired_subscription_1 = SubscriptionPlanFactory.create(
            start_date=self.today - timedelta(days=7),
            expiration_date=self.today,
        )
        expired_subscription_2 = SubscriptionPlanFactory.create(
            start_date=self.today - timedelta(days=7),
            expiration_date=self.today,
        )

        LicenseFactory.create_batch(500,
                                    status=ACTIVATED,
                                    subscription_plan=expired_subscription_1)
        LicenseFactory.create_batch(500,
                                    status=ACTIVATED,
                                    subscription_plan=expired_subscription_2)

        call_command(self.command_name)
        expected_call_count = math.ceil(1000 / LICENSE_EXPIRATION_BATCH_SIZE)
        assert expected_call_count == mock_license_expiration_task.call_count
Ejemplo n.º 24
0
def test_track_event_via_braze_alias(mock_braze_client):
    test_email = '*****@*****.**'
    assigned_license = LicenseFactory.create(
        subscription_plan=SubscriptionPlanFactory.create(),
        lms_user_id=5,
        user_email=test_email,
        status=ASSIGNED,
        auto_applied=True)
    test_event_name = 'test-event-name'
    test_event_properties = {
        'license_uuid':
        str(assigned_license.uuid),
        'enterprise_customer_slug':
        assigned_license.subscription_plan.customer_agreement.
        enterprise_customer_slug,
    }
    expected_user_alias = {
        "alias_name": test_email,
        "alias_label": ENTERPRISE_BRAZE_ALIAS_LABEL,
    }
    expected_attributes = {
        "user_alias":
        expected_user_alias,
        "email":
        test_email,
        "is_enterprise_learner":
        True,
        "_update_existing_only":
        False,
        "license_uuid":
        str(assigned_license.uuid),
        "enterprise_customer_slug":
        assigned_license.subscription_plan.customer_agreement.
        enterprise_customer_slug,
    }
    expected_event = {
        "user_alias": expected_user_alias,
        "name": test_event_name,
        "time": _iso_8601_format_string(localized_utcnow()),
        "properties": test_event_properties,
        "_update_existing_only": False,
    }
    _track_event_via_braze_alias(test_email, test_event_name,
                                 test_event_properties)
    mock_braze_client().create_braze_alias.assert_any_call(
        [test_email], ENTERPRISE_BRAZE_ALIAS_LABEL)
    mock_braze_client().track_user.assert_any_call(
        attributes=[expected_attributes], events=[expected_event])
Ejemplo n.º 25
0
    def test_cannot_revoke_license_if_not_assigned_or_activated(
            self, license_status):
        subscription_plan = SubscriptionPlanFactory.create(
            is_revocation_cap_enabled=False, )
        original_license = LicenseFactory.create(
            status=license_status,
            subscription_plan=subscription_plan,
        )

        expected_msg = 'status of {} cannot be revoked'.format(license_status)
        with self.assertRaisesRegex(exceptions.LicenseRevocationError,
                                    expected_msg):
            api.revoke_license(original_license)

        original_license.refresh_from_db()
        self.assertEqual(original_license.status, license_status)
Ejemplo n.º 26
0
    def test_auto_applied_licenses_count_since(self):
        """
        Tests that the correct auto-applied license count is returned.
        """
        subscription_plan = SubscriptionPlanFactory.create(should_auto_apply_licenses=True)
        timestamp_1 = localized_utcnow()
        LicenseFactory.create_batch(1, subscription_plan=subscription_plan, auto_applied=True, activation_date=timestamp_1)
        LicenseFactory.create_batch(3, subscription_plan=subscription_plan, auto_applied=False, activation_date=timestamp_1)

        self.assertEqual(subscription_plan.auto_applied_licenses_count_since(), 1)
        timestamp_2 = timestamp_1 + timedelta(seconds=1)
        self.assertEqual(subscription_plan.auto_applied_licenses_count_since(timestamp_2), 0)
        LicenseFactory.create_batch(5, subscription_plan=subscription_plan, auto_applied=True, activation_date=timestamp_2)
        self.assertEqual(subscription_plan.auto_applied_licenses_count_since(timestamp_2), 5)
Ejemplo n.º 27
0
    def test_renewal_processed_segment_events(self, mock_track_event):
        prior_plan = SubscriptionPlanFactory()
        [
            LicenseFactory.create(subscription_plan=prior_plan,
                                  status=constants.ACTIVATED,
                                  user_email='activated_user_{}@example.com')
        ]

        renewal = SubscriptionPlanRenewalFactory(
            prior_subscription_plan=prior_plan,
            number_of_licenses=1,
            license_types_to_copy=constants.LicenseTypesToRenew.
            ASSIGNED_AND_ACTIVATED)
        api.renew_subscription(renewal)
        assert mock_track_event.call_count == 2
        assert (mock_track_event.call_args_list[0].args[1] ==
                constants.SegmentEvents.LICENSE_CREATED)
        assert (mock_track_event.call_args_list[1].args[1] ==
                constants.SegmentEvents.LICENSE_RENEWED)
        self.assertFalse(
            mock_track_event.call_args_list[1].args[2]['is_auto_renewed'])
Ejemplo n.º 28
0
    def test_revocation_limit_reached_raises_error(
        self,
        revoke_max_percentage,
        number_licenses_to_create,
    ):
        subscription_plan = SubscriptionPlanFactory.create(
            is_revocation_cap_enabled=True,
            revoke_max_percentage=revoke_max_percentage,
            # SubscriptionPlan.num_revocations_remaining defines the absolute revocation cap
            # as:
            #
            # revocations_remaining =
            #    ceil(num_licenses * revoke_max_percentage) - num_revocations_applied
            #
            # So given the revoke max percentage and number of licenses to create,
            # we can derive the number of revocations previously applied in the plan
            # needed in order to raise an exception the "next time" we attempt a revocation
            # by setting revocations_remaining to 0 and solving for num_revocations_applied:
            #
            # 0 = ceil(num_licenses * revoke_max_percent) - num_revocations_applied
            # ==>
            # num_revocations_applied = ceil(num_licenses * revoke_max_percent)
            #
            # (the "next time we revoke" being the call to revoke_license() below).
            num_revocations_applied=ceil(revoke_max_percentage *
                                         number_licenses_to_create),
        )
        original_licenses = LicenseFactory.create_batch(
            number_licenses_to_create,
            status=constants.ACTIVATED,
            subscription_plan=subscription_plan,
        )

        for original_license in original_licenses:
            with self.assertRaisesRegex(exceptions.LicenseRevocationError,
                                        'limit has been reached'):
                api.revoke_license(original_license)

            original_license.refresh_from_db()
            self.assertEqual(original_license.status, constants.ACTIVATED)
Ejemplo n.º 29
0
def test_get_license_tracking_properties():
    test_email = '*****@*****.**'
    assigned_license = LicenseFactory.create(
        subscription_plan=SubscriptionPlanFactory.create(),
        lms_user_id=5,
        user_email=test_email,
        status=ASSIGNED,
        auto_applied=True)
    flat_data = get_license_tracking_properties(assigned_license)
    assert flat_data['license_uuid'] == str(assigned_license.uuid)
    assert flat_data['license_activation_key'] == str(
        assigned_license.activation_key)
    assert flat_data['previous_license_uuid'] == ''
    assert flat_data['assigned_date'] == _iso_8601_format_string(
        assigned_license.assigned_date)
    assert flat_data['activation_date'] == _iso_8601_format_string(
        assigned_license.activation_date)
    assert flat_data['assigned_lms_user_id'] == assigned_license.lms_user_id
    assert flat_data['assigned_email'] == test_email
    assert flat_data['auto_applied'] is True
    assert flat_data['enterprise_customer_uuid'] \
        == str(assigned_license.subscription_plan.customer_agreement.enterprise_customer_uuid)
    assert flat_data['enterprise_customer_slug'] \
        == assigned_license.subscription_plan.customer_agreement.enterprise_customer_slug
    assert flat_data['expiration_processed'] \
        == assigned_license.subscription_plan.expiration_processed
    assert flat_data['customer_agreement_uuid'] \
        == str(assigned_license.subscription_plan.customer_agreement.uuid)
    assert flat_data['enterprise_customer_name'] \
        == assigned_license.subscription_plan.customer_agreement.enterprise_customer_name

    # Check that all the data is a basic type that can be serialized so it will be clean in segment:
    for k, v in flat_data.items():
        assert isinstance(k, str)
        assert (isinstance(v, str) or isinstance(v, int)
                or isinstance(v, bool))
Ejemplo n.º 30
0
    def setUpTestData(cls):
        super().setUpTestData()

        subscription_plan = SubscriptionPlanFactory()
        day_before_retirement_deadline = localized_utcnow() - timedelta(
            DAYS_TO_RETIRE + 1)
        cls.expired_subscription_plan = SubscriptionPlanFactory(
            expiration_date=day_before_retirement_deadline)

        # Set up a bunch of licenses that should not be retired
        LicenseFactory.create_batch(
            3,
            status=ACTIVATED,
            subscription_plan=subscription_plan,
            revoked_date=None,
        )
        LicenseFactory.create_batch(
            4,
            status=REVOKED,
            subscription_plan=subscription_plan,
            revoked_date=localized_utcnow(),
        )
        LicenseFactory.create_batch(
            5,
            status=REVOKED,
            subscription_plan=subscription_plan,
            revoked_date=localized_utcnow(),
        )
        LicenseFactory.create_batch(
            5,
            status=REVOKED,
            subscription_plan=subscription_plan,
            revoked_date=day_before_retirement_deadline,
            user_email=
            None,  # The user_email is None to represent already retired licenses
        )
        LicenseFactory.create_batch(
            2,
            status=ASSIGNED,
            subscription_plan=subscription_plan,
            assigned_date=localized_utcnow(),
            revoked_date=None,
        )

        # Set up licenses that should be retired as either there subscription plan has been expired for long enough
        # for retirement, or they were assigned/revoked a day before the current date to retire.
        cls.num_revoked_licenses_to_retire = 6
        cls.revoked_licenses_ready_for_retirement = LicenseFactory.create_batch(
            cls.num_revoked_licenses_to_retire,
            status=REVOKED,
            subscription_plan=subscription_plan,
            revoked_date=day_before_retirement_deadline,
        )
        for revoked_license in cls.revoked_licenses_ready_for_retirement:
            revoked_license.lms_user_id = faker.random_int()
            revoked_license.user_email = faker.email()
            revoked_license.save()

        cls.num_assigned_licenses_to_retire = 7
        cls.assigned_licenses_ready_for_retirement = LicenseFactory.create_batch(
            cls.num_assigned_licenses_to_retire,
            status=ASSIGNED,
            subscription_plan=subscription_plan,
            assigned_date=day_before_retirement_deadline,
        )
        for assigned_license in cls.assigned_licenses_ready_for_retirement:
            assigned_license.lms_user_id = faker.random_int()
            assigned_license.user_email = faker.email()
            assigned_license.save()

        # Create licenses of different statuses that should be retired from association with an old expired subscription
        LicenseFactory.create(
            status=ACTIVATED,
            subscription_plan=cls.expired_subscription_plan,
            lms_user_id=faker.random_int(),
            user_email=faker.email(),
        )
        LicenseFactory.create(
            status=ASSIGNED,
            subscription_plan=cls.expired_subscription_plan,
            lms_user_id=faker.random_int(),
            user_email=faker.email(),
        )
        LicenseFactory.create(
            status=REVOKED,
            lms_user_id=faker.random_int(),
            user_email=faker.email(),
            subscription_plan=cls.expired_subscription_plan,
        )