Skip to content

Commit

Permalink
Merge branch 'master' into bilalqamar95/dockerfile-setup-removal
Browse files Browse the repository at this point in the history
  • Loading branch information
BilalQamar95 authored Jan 21, 2025
2 parents 585f8e4 + c1e3b88 commit 7763aff
Show file tree
Hide file tree
Showing 16 changed files with 316 additions and 201 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ License Manager |Codecov|_
.. |Codecov| image:: http://codecov.io/github/edx/license-manager/coverage.svg?branch=master
.. _Codecov: http://codecov.io/github/edx/license-manager?branch=master

Django backend for managing licenses and subscriptions.
Django backend for managing licenses and subscriptions for enterprise customer.

Setting up license-manager
--------------------------
Expand Down
43 changes: 43 additions & 0 deletions catalog-info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# This file records information about this repo. Its use is described in OEP-55:
# https://open-edx-proposals.readthedocs.io/en/latest/processes/oep-0055-proc-project-maintainers.html

apiVersion: backstage.io/v1alpha1
# (Required) Acceptable Values: Component, Resource, System
# Use `Component` unless you know how backstage works and what the other kinds mean.
kind: Component
metadata:
# (Required) Must be the name of the repo, without the owning organization.
name: 'license-manager'
description: "Django backend for managing licenses and subscriptions for enterprise customer."
annotations:
# (Optional) Annotation keys and values can be whatever you want.
# We use it in Open edX repos to have a comma-separated list of GitHub user
# names that might be interested in changes to the architecture of this
# component.
openedx.org/arch-interest-groups: ""
# (Optional) We use the below annotation to indicate whether or not this
# repository should be tagged for openedx releases and which branch is tagged.
openedx.org/release: ""
spec:

# (Required) This can be a group (`group:<github_group_name>`) or a user (`user:<github_username>`).
# Don't forget the "user:" or "group:" prefix. Groups must be GitHub team
# names in the openedx GitHub organization: https://github.com/orgs/openedx/teams
#
# If you need a new team created, create an issue with Axim engineering:
# https://github.com/openedx/axim-engineering/issues/new/choose
owner: group:2u-enterprise

# (Required) Acceptable Type Values: service, website, library
type: 'service'

# (Required) Acceptable Lifecycle Values: experimental, production, deprecated
lifecycle: 'production'

# (Optional) The value can be the name of any known component.
subcomponentOf: '<name_of_a_component>'

# (Optional) An array of different components or resources.
dependsOn:
- '<component_or_resource>'
- '<another_component_or_resource>'
15 changes: 6 additions & 9 deletions license_manager/apps/subscriptions/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,20 +233,17 @@ def sync_agreement_with_enterprise_customer(customer_agreement):

def toggle_auto_apply_licenses(customer_agreement_uuid, subscription_uuid):
"""
Turn auto apply licenses on for the subscription with the given uuid and off for the current
plan used for auto applied licenses. If subscription_uuid is empty or None, turn auto apply licenses
Turn auto apply licenses on for the subscription with the given uuid and off for all other
auto-applied plans in the given customer agreement. If subscription_uuid is empty or None, turn auto apply licenses
off for the current plan.
"""
# There should only be one plan for auto-applied licenses at any given time
current_plan_for_auto_applied_licenses = SubscriptionPlan.objects.filter(
for plan in SubscriptionPlan.objects.filter(
customer_agreement_id=customer_agreement_uuid,
should_auto_apply_licenses=True
).first()

if current_plan_for_auto_applied_licenses:
current_plan_for_auto_applied_licenses.should_auto_apply_licenses = False
current_plan_for_auto_applied_licenses.save()
):
plan.should_auto_apply_licenses = False
plan.save()

if not subscription_uuid:
return
Expand Down
21 changes: 18 additions & 3 deletions license_manager/apps/subscriptions/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ class SubscriptionPlanForm(forms.ModelForm):
choices=SubscriptionPlanShouldAutoApplyLicensesChoices.CHOICES,
required=False,
label="Should auto apply licenses",
help_text="Whether licenses from this Subscription Plan should be auto applied."
help_text=(
"""
Whether licenses from this Subscription Plan should be auto applied.
It it possible and acceptable for more than one plan in a single
customer agreement to have this field enabled.
"""
)
)

# Extra form field to specify the number of licenses to be associated with the subscription plan
Expand Down Expand Up @@ -292,8 +298,17 @@ def populate_subscription_for_auto_applied_licenses_choices(self, instance):
choices=choices,
required=False,
initial=empty_choice if not current_plan else (current_plan.uuid, current_plan.title),
help_text="The subscription plan to be associated with auto apply licenses. Selecting a license"
" will automatically enable the \"Should auto apply licenses\" field on the subscription plan"
help_text=(
"""
The subscription plan from which licenses will be auto-applied, if any.
If you do not manually modify this field, it will be automatically set, chosen as the
most recently started plan that is active, current, and has 'should_auto_apply_licenses'
set to true. Manually selecting/modifying the plan for this field will have two effects:
It will automatically enable the \"Should auto apply licenses\" field on the selected plan,
and it will automatically *disable* that field on all other plans
associated with this customer agreement.
"""
),
)
self.fields['subscription_for_auto_applied_licenses'] = choice_field

Expand Down
2 changes: 1 addition & 1 deletion license_manager/apps/subscriptions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def auto_applicable_subscription(self):
is_active=True,
start_date__lte=now,
expiration_date__gte=now
).first()
).order_by('-start_date').first()

return plan

Expand Down
49 changes: 49 additions & 0 deletions license_manager/apps/subscriptions/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,55 @@ def test_is_locked_for_renewal_processing(self, is_locked_for_renewal_processing
renewed_subscription_plan.is_locked_for_renewal_processing, is_locked_for_renewal_processing,
)

def test_auto_applicable_subscription(self):
"""
Tests that we pick the most recent auto-applicable plan for a CustomerAgreement.
"""
agreement = CustomerAgreementFactory.create()
SubscriptionPlanFactory.create(
customer_agreement=agreement,
start_date=localized_datetime(2020, 1, 1),
should_auto_apply_licenses=True,
)
SubscriptionPlanFactory.create(
customer_agreement=agreement,
start_date=localized_datetime(2020, 4, 1),
should_auto_apply_licenses=True,
)
plan_3 = SubscriptionPlanFactory.create(
customer_agreement=agreement,
start_date=localized_datetime(2020, 12, 1),
should_auto_apply_licenses=True,
)
# make one plan that hasn't started yet
SubscriptionPlanFactory.create(
customer_agreement=agreement,
start_date=localized_utcnow() + timedelta(days=1),
should_auto_apply_licenses=True,
)
self.assertEqual(agreement.auto_applicable_subscription, plan_3)

def test_auto_applicable_subscription_none_available(self):
"""
Tests that when no current, auto-applicable plan is available,
CustomerAgreement.auto_applicable_subscription evaluates to null.
"""
agreement = CustomerAgreementFactory.create()
# make a plan that's expired
SubscriptionPlanFactory.create(
customer_agreement=agreement,
start_date=localized_datetime(2020, 1, 1),
expiration_date=localized_utcnow() + timedelta(days=-1),
should_auto_apply_licenses=True,
)
# make one plan that hasn't started yet
SubscriptionPlanFactory.create(
customer_agreement=agreement,
start_date=localized_utcnow() + timedelta(days=1),
should_auto_apply_licenses=True,
)
self.assertIsNone(agreement.auto_applicable_subscription)

def test_auto_apply_licenses_turned_on_at(self):
"""
Tests that auto_apply_licenses_turned_on_at returns the correct time.
Expand Down
45 changes: 23 additions & 22 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ asgiref==3.8.1
# via
# django
# django-cors-headers
attrs==24.2.0
attrs==24.3.0
# via
# jsonschema
# referencing
Expand All @@ -24,9 +24,9 @@ billiard==4.2.1
# via celery
bleach[css]==6.2.0
# via -r requirements/base.in
boto3==1.35.63
boto3==1.35.97
# via django-ses
botocore==1.35.63
botocore==1.35.97
# via
# boto3
# s3transfer
Expand All @@ -35,15 +35,15 @@ celery==5.4.0
# -r requirements/base.in
# django-celery-results
# edx-celeryutils
certifi==2024.8.30
certifi==2024.12.14
# via requests
cffi==1.17.1
# via
# cryptography
# pynacl
charset-normalizer==3.4.0
charset-normalizer==3.4.1
# via requests
click==8.1.7
click==8.1.8
# via
# celery
# click-didyoumean
Expand All @@ -57,17 +57,17 @@ click-plugins==1.1.1
# via celery
click-repl==0.3.0
# via celery
code-annotations==1.8.1
code-annotations==2.1.0
# via edx-toggles
cryptography==43.0.3
cryptography==44.0.0
# via
# pyjwt
# social-auth-core
defusedxml==0.8.0rc2
# via
# python3-openid
# social-auth-core
django==4.2.16
django==4.2.17
# via
# -c requirements/common_constraints.txt
# -r requirements/base.in
Expand Down Expand Up @@ -119,7 +119,7 @@ django-model-utils==5.0.0
# -r requirements/base.in
# edx-celeryutils
# edx-rbac
django-ses==4.2.0
django-ses==4.3.1
# via -r requirements/base.in
django-simple-history==3.7.0
# via -r requirements/base.in
Expand Down Expand Up @@ -147,7 +147,7 @@ drf-jwt==1.19.2
# via edx-drf-extensions
drf-nested-routers==0.94.1
# via -r requirements/base.in
drf-spectacular==0.27.2
drf-spectacular==0.28.0
# via -r requirements/base.in
edx-auth-backends==4.4.0
# via -r requirements/base.in
Expand Down Expand Up @@ -178,7 +178,7 @@ idna==3.10
# via requests
inflection==0.5.1
# via drf-spectacular
jinja2==3.1.4
jinja2==3.1.5
# via code-annotations
jmespath==1.0.1
# via
Expand All @@ -196,9 +196,9 @@ markupsafe==3.0.2
# via jinja2
monotonic==1.6
# via analytics-python
mysqlclient==2.2.6
mysqlclient==2.2.7
# via -r requirements/base.in
newrelic==10.2.0
newrelic==10.4.0
# via edx-django-utils
oauthlib==3.2.2
# via
Expand All @@ -210,11 +210,11 @@ ply==3.11
# via djangoql
prompt-toolkit==3.0.48
# via click-repl
psutil==6.1.0
psutil==6.1.1
# via edx-django-utils
pycparser==2.22
# via cffi
pyjwt[crypto]==2.10.0
pyjwt[crypto]==2.10.1
# via
# drf-jwt
# edx-auth-backends
Expand All @@ -240,7 +240,7 @@ pyyaml==6.0.2
# via
# code-annotations
# drf-spectacular
redis==5.2.0
redis==5.2.1
# via -r requirements/base.in
referencing==0.35.1
# via
Expand All @@ -255,19 +255,19 @@ requests==2.32.3
# social-auth-core
requests-oauthlib==2.0.0
# via social-auth-core
rpds-py==0.21.0
rpds-py==0.22.3
# via
# jsonschema
# referencing
rules==3.5
# via -r requirements/base.in
s3transfer==0.10.3
s3transfer==0.10.4
# via boto3
semantic-version==2.10.0
# via edx-drf-extensions
simplejson==3.19.3
# via -r requirements/base.in
six==1.16.0
six==1.17.0
# via
# analytics-python
# edx-auth-backends
Expand All @@ -279,9 +279,9 @@ social-auth-core==4.5.4
# via
# edx-auth-backends
# social-auth-app-django
sqlparse==0.5.2
sqlparse==0.5.3
# via django
stevedore==5.3.0
stevedore==5.4.0
# via
# code-annotations
# edx-django-utils
Expand All @@ -300,6 +300,7 @@ uritemplate==4.1.1
# via drf-spectacular
urllib3==2.2.3
# via
# -c requirements/common_constraints.txt
# botocore
# requests
vine==5.1.0
Expand Down
4 changes: 4 additions & 0 deletions requirements/common_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ elasticsearch<7.14.0
# Cause: https://github.com/openedx/edx-lint/issues/458
# This can be unpinned once https://github.com/openedx/edx-lint/issues/459 has been resolved.
pip<24.3

# Cause: https://github.com/openedx/edx-lint/issues/475
# This can be unpinned once https://github.com/openedx/edx-lint/issues/476 has been resolved.
urllib3<2.3.0
Loading

0 comments on commit 7763aff

Please sign in to comment.