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)])
    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 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,
        )
Ejemplo n.º 4
0
 def test_prior_renewals(self):
     renewed_subscription_plan_1 = SubscriptionPlanFactory.create()
     renewed_subscription_plan_2 = SubscriptionPlanFactory.create()
     renewal_1 = SubscriptionPlanRenewalFactory.create(
         prior_subscription_plan=self.subscription_plan,
         renewed_subscription_plan=renewed_subscription_plan_1
     )
     renewal_2 = SubscriptionPlanRenewalFactory.create(
         prior_subscription_plan=renewed_subscription_plan_1,
         renewed_subscription_plan=renewed_subscription_plan_2
     )
     self.assertEqual(renewed_subscription_plan_2.prior_renewals, [renewal_1, renewal_2])
    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
Ejemplo n.º 6
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_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_invalid_start_date_before_today(self):
     prior_subscription_plan = SubscriptionPlanFactory.create()
     form = make_bound_subscription_plan_renewal_form(
         prior_subscription_plan=prior_subscription_plan,
         effective_date=localized_utcnow() - timedelta(1),
         renewed_expiration_date=prior_subscription_plan.expiration_date +
         timedelta(366),
     )
     assert not form.is_valid()
Ejemplo n.º 10
0
 def test_is_locked_for_renewal_processing(self, is_locked_for_renewal_processing):
     today = localized_utcnow()
     with freezegun.freeze_time(today):
         renewed_subscription_plan = SubscriptionPlanFactory.create(expiration_date=today)
         renewal_kwargs = {'prior_subscription_plan': renewed_subscription_plan}
         if is_locked_for_renewal_processing:
             renewal_kwargs.update({'effective_date': renewed_subscription_plan.expiration_date})
         SubscriptionPlanRenewalFactory.create(**renewal_kwargs)
         self.assertEqual(renewed_subscription_plan.is_locked_for_renewal_processing, is_locked_for_renewal_processing)
Ejemplo n.º 11
0
 def test_valid_start_and_expiration_dates(self):
     prior_subscription_plan = SubscriptionPlanFactory.create()
     form = make_bound_subscription_plan_renewal_form(
         prior_subscription_plan=prior_subscription_plan,
         effective_date=prior_subscription_plan.expiration_date +
         timedelta(1),
         renewed_expiration_date=prior_subscription_plan.expiration_date +
         timedelta(366),
     )
     assert form.is_valid()
Ejemplo n.º 12
0
    def create_subscription_with_renewal(self,
                                         effective_date,
                                         processed=False):
        prior_subscription_plan = SubscriptionPlanFactory.create(
            start_date=self.now - timedelta(days=7),
            expiration_date=self.now,
        )

        renewed_subscription_plan = SubscriptionPlanFactory.create(
            start_date=self.now,
            expiration_date=self.now + timedelta(days=7),
        )

        SubscriptionPlanRenewalFactory.create(
            prior_subscription_plan=prior_subscription_plan,
            renewed_subscription_plan=renewed_subscription_plan,
            effective_date=effective_date,
            processed=processed)

        return (prior_subscription_plan)
Ejemplo n.º 13
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.º 14
0
    def test_auto_apply_licenses_turned_on_at(self):
        """
        Tests that auto_apply_licenses_turned_on_at returns the correct time.
        """
        subscription_plan = SubscriptionPlanFactory.create()
        subscription_plan.should_auto_apply_licenses = True
        subscription_plan.save()
        auto_apply_licenses_turned_on_at = subscription_plan.history.latest().history_date

        subscription_plan.is_active = True
        subscription_plan.save()
        latest_history_date = subscription_plan.history.latest().history_date

        self.assertEqual(subscription_plan.auto_apply_licenses_turned_on_at, auto_apply_licenses_turned_on_at)
        self.assertNotEqual(subscription_plan.auto_apply_licenses_turned_on_at, latest_history_date)
    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.º 16
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.º 17
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.º 18
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.º 19
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))