Skip to content

Commit

Permalink
Install django-extensions.
Browse files Browse the repository at this point in the history
  • Loading branch information
iloveagent57 committed Dec 14, 2020
1 parent 5a7abd7 commit 84cbd1e
Show file tree
Hide file tree
Showing 14 changed files with 212 additions and 188 deletions.
7 changes: 5 additions & 2 deletions docs/decisions/0002-customer-agreements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,14 @@ Consequences
============

The most notable change is that a single customer, via a ``CustomerAgreement``, may now have multiple (active)
``SubscriptionPlans`` at any time. This supports the example use case of rolling "batches" of subscriptions.
``SubscriptionPlans`` at any time. This supports the example use case of rolling "batches" of subscriptions. Notably,
for determining the expiration experience for customer admins (as well as learners), we can determine
the plan that is closest/furthest from expiration to guide in-application messaging about when a set of learners
may lose access to a catalog.

The Django Admin page for ``SubscriptionPlans`` will change:

* A ``CustomerAgreement`` instance must now be created during the creation of a ``SubscriptionPlan``. The ``uuid``
and ``slug`` fields should be copied from the ``EnterpriseCustomer`` model (see edx-enterprise).
* The ``enterprise_customer_uuid`` field is no longer directly accessible from this model.
An administrator of license-manager must now access it from plan's related ``CustomerAgreement``.
An administrator of license-manager must now access it from a plan's related ``CustomerAgreement``.
26 changes: 17 additions & 9 deletions docs/decisions/0003-subscription-renewals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ their active subscription's expiration date. For example, for a subscription wi
a start date of 2021-01-01, and an end date of 2021-12-31, we'd like to allow the customer to renew that subscription
for 150 on, say, 2021-06-17. The renewed subscription would become active on 2022-01-01 and expire on 2022-12-31.
Our data schema should support this business arrangement, and the data models should align closely with the
different logical entities involved in this business arrangement.
different logical entities involved in this business arrangement. Lastly, the experience for learners and adminsistrators
should remain consistent after a plan is renewed. They shouldn't notice a change in the functioning of the application
or their access to content, regardless of how data changes behind the curtain.

Decision
========
Expand Down Expand Up @@ -62,7 +64,7 @@ of which will be placed in the associated renewals ``renewed_subscription_plan_i
How is the renewal processed?
-----------------------------

The actual renewal process would should primarily be a scheduled daily job that looks at all renewals
The actual renewal process will primarily be achieved by a scheduled daily job that looks at all renewals
and determines if any renewed plans should be created at the time the job is run:

* If there is 1 or fewer days between the current time and the ``effective_date`` of a renewal, the renewal should
Expand All @@ -86,7 +88,9 @@ What happens to the licenses?
* We have merged code into license-manager that will ensure, going forward, bulk actions are recorded in the license
history tables.
* Additionally, we will backfill missing creation historical license records, based on the creation date of the license.
This needs to be done before we transfer any licenses to new subscription plans.
This needs to be done before we transfer any licenses to new subscription plans, so that, for any license,
we have a historical record of each subscription plan it was ever associated with, along with an understanding of `when`
it was associated with a given subscription plan.
* Since we already have licenses in the wild without associated historical creation tracking, we'll
introduce some defensive checking/snapshotting that should occur prior to the license transfer process.
This can be as simple as assuring that a historical record reflecting the license's association with the original
Expand Down Expand Up @@ -138,7 +142,9 @@ What happens to the licensed enrollments?
-----------------------------------------

* We will introduce a new field, ``plan_at_time_of_enrollment``, on the ``LicensedEnterpriseEnrollment`` records.
This gives us an even faster way to tie enrollments to plans, plus, it give us a good way to reconcile history, if needed.
This gives us an even faster way to tie enrollments to plans, and it give us a good way to reconcile history, if needed.
This means that when a licensed enrollment record is created, we must record with it the UUID of the subscription
plan to which the license belongs.
* We will backpopulate this field with each license record's current subscription plan UUID. This is only permissible
because we have not yet transferred any licenses between subscription plans.
* After these two steps are completed, licensed enrollment records do not need to be changed during the license transfer,
Expand Down Expand Up @@ -173,7 +179,7 @@ How does this impact the subscription learner experience?

* It shouldn't.
* A user's existing license is transferred over to a new, active plan that should have the same catalog.
* Ther license UUID doesn't change.
* Their license UUID doesn't change.
* Nothing about their enrollment state should change.
* If we start tracking the subscription UUID at time of enrollment in the ``LicensedEnterpriseCourseEnrollment`` model,
that won't change, and we'll have a good (and easy to access) source of truth about the learner's subscription state
Expand Down Expand Up @@ -202,7 +208,9 @@ while still representing the true state of the world.

Misc. Open Questions
--------------------
* Can you renew with a different catalog product? What happens to enrollment/revenue allocation if that action
occurs in the middle of a month? Can we stipulate that all plans have to end at the end of a month, and that
renewals cannot begin in the middle of a month?
* Can we make the product ID/catalog non-editable after licensed enrollments begin to occur?
Can you renew with a different catalog product? What happens to enrollment/revenue allocation if that action
occurs in the middle of a month? Can we stipulate that all plans have to end at the end of a month, and that
renewals cannot begin in the middle of a month?

* Our simplifying assumption for now is that a subscription plan renewal should be for the same catalog
as the original plan. At the time of this writing, we don't plan to enforce this in the schema.
8 changes: 8 additions & 0 deletions docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ Open the shell to the license manager container for manual commands
$ make app-shell
Once inside an application container, there's a particularly useful tool called `django-extensions_` that allows
you to run ``./manage.py shell_plus``, which is superior to the built-in Django ``shell`` because it automatically
imports all of the models from the app, along with some helpful Django imports.
``django-extensions`` is only installed via dev requirements and will only work when run with the ``devstack.py``
settings, because that's where it is installed into ``INSTALLED_APPS``. The ``./manage.py show_urls`` is also helpful.

.. _django-extensions: https://github.com/django-extensions/django-extensions#using-it


Local/Private Settings
----------------------
Expand Down
4 changes: 4 additions & 0 deletions license_manager/settings/devstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@
# Feature Toggles
FEATURES[EXPOSE_LICENSE_ACTIVATION_KEY_OVER_API] = True

# Install django-extensions for improved dev experiences
# https://github.com/django-extensions/django-extensions#using-it
INSTALLED_APPS += ('django_extensions',)

# Make some loggers less noisy (useful during test failure)
import logging

Expand Down
36 changes: 18 additions & 18 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,32 @@
amqp==2.6.1 # via kombu
backoff==1.10.0 # via -r requirements/base.in
billiard==3.6.3.0 # via celery
boto3==1.16.10 # via django-ses
botocore==1.19.10 # via boto3, s3transfer
boto3==1.16.35 # via django-ses
botocore==1.19.35 # via boto3, s3transfer
celery==4.4.7 # via -c requirements/constraints.txt, -r requirements/base.in, edx-celeryutils
certifi==2020.6.20 # via requests
cffi==1.14.3 # via cryptography
certifi==2020.12.5 # via requests
cffi==1.14.4 # via cryptography
chardet==3.0.4 # via requests
coreapi==2.3.3 # via django-rest-swagger, openapi-codec
coreschema==0.0.4 # via coreapi
cryptography==3.2.1 # via pyjwt
cryptography==3.3.1 # via pyjwt
defusedxml==0.6.0 # via python3-openid, social-auth-core
django-cors-headers==3.5.0 # via -r requirements/base.in
django-crum==0.7.7 # via edx-django-utils, edx-rbac
django-extensions==3.0.9 # via -r requirements/base.in
django-cors-headers==3.6.0 # via -r requirements/base.in
django-crum==0.7.9 # via edx-django-utils, edx-rbac
django-extensions==3.1.0 # via -r requirements/base.in
django-filter==2.4.0 # via -r requirements/base.in
django-model-utils==4.0.0 # via -r requirements/base.in, edx-celeryutils, edx-rbac
django-model-utils==4.1.1 # via -r requirements/base.in, edx-celeryutils, edx-rbac
django-rest-swagger==2.2.0 # via -r requirements/base.in
django-ses==1.0.3 # via -r requirements/base.in
django-simple-history==2.12.0 # via -r requirements/base.in
django-waffle==2.0.0 # via -r requirements/base.in, edx-django-utils, edx-drf-extensions
django==2.2.17 # via -c requirements/constraints.txt, -r requirements/base.in, django-cors-headers, django-crum, django-filter, django-model-utils, django-ses, djangorestframework, drf-jwt, drf-nested-routers, edx-auth-backends, edx-celeryutils, edx-django-utils, edx-drf-extensions, edx-rbac, jsonfield2, rest-condition
djangorestframework==3.12.1 # via -r requirements/base.in, django-rest-swagger, drf-jwt, drf-nested-routers, edx-drf-extensions, rest-condition
drf-jwt==1.17.2 # via edx-drf-extensions
drf-nested-routers==0.92.1 # via -r requirements/base.in
djangorestframework==3.12.2 # via -r requirements/base.in, django-rest-swagger, drf-jwt, drf-nested-routers, edx-drf-extensions, rest-condition
drf-jwt==1.17.3 # via edx-drf-extensions
drf-nested-routers==0.92.5 # via -r requirements/base.in
edx-auth-backends==3.1.0 # via -r requirements/base.in
edx-celeryutils==0.5.2 # via -r requirements/base.in
edx-django-utils==3.11.0 # via -r requirements/base.in, edx-drf-extensions
edx-django-utils==3.13.0 # via -r requirements/base.in, edx-drf-extensions
edx-drf-extensions==6.2.0 # via -r requirements/base.in, edx-rbac
edx-opaque-keys==2.1.1 # via edx-drf-extensions
edx-rbac==1.3.3 # via -r requirements/base.in
Expand All @@ -45,7 +45,7 @@ jmespath==0.10.0 # via boto3, botocore
jsonfield2==4.0.0.post0 # via edx-celeryutils
kombu==4.6.11 # via celery
markupsafe==1.1.1 # via jinja2
mysqlclient==2.0.1 # via -r requirements/base.in
mysqlclient==2.0.2 # via -r requirements/base.in
newrelic==5.22.1.152 # via edx-django-utils
oauthlib==3.1.0 # via requests-oauthlib, social-auth-core
openapi-codec==1.3.2 # via django-rest-swagger
Expand All @@ -55,13 +55,13 @@ pycparser==2.20 # via cffi
pycryptodomex==3.9.9 # via pyjwkest
pyjwkest==1.4.2 # via edx-drf-extensions
pyjwt[crypto]==1.7.1 # via drf-jwt, edx-auth-backends, edx-rest-api-client, social-auth-core
pymongo==3.11.0 # via edx-opaque-keys
pymongo==3.11.2 # via edx-opaque-keys
python-dateutil==2.8.1 # via botocore, edx-drf-extensions
python3-openid==3.2.0 # via social-auth-core
pytz==2020.4 # via -r requirements/base.in, celery, django, django-ses
redis==3.5.3 # via -r requirements/base.in
requests-oauthlib==1.3.0 # via social-auth-core
requests==2.24.0 # via coreapi, edx-drf-extensions, edx-rest-api-client, pyjwkest, requests-oauthlib, slumber, social-auth-core
requests==2.25.0 # via coreapi, edx-drf-extensions, edx-rest-api-client, pyjwkest, requests-oauthlib, slumber, social-auth-core
rest-condition==1.0.3 # via edx-drf-extensions
rules==2.2 # via -r requirements/base.in
s3transfer==0.3.3 # via boto3
Expand All @@ -72,8 +72,8 @@ slumber==0.7.1 # via edx-rest-api-client
social-auth-app-django==3.1.0 # via -c requirements/constraints.txt, edx-auth-backends
social-auth-core==3.2.0 # via -c requirements/constraints.txt, edx-auth-backends, social-auth-app-django
sqlparse==0.4.1 # via django
stevedore==3.2.2 # via edx-django-utils, edx-opaque-keys
stevedore==3.3.0 # via edx-django-utils, edx-opaque-keys
uritemplate==3.0.1 # via coreapi
urllib3==1.25.11 # via botocore, requests
urllib3==1.26.2 # via botocore, requests
vine==1.3.0 # via amqp, celery
zipp==1.2.0 # via -c requirements/constraints.txt, -r requirements/base.in
1 change: 1 addition & 0 deletions requirements/dev.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
ddt # Data-driven tests
diff-cover # Changeset diff test coverage
django-debug-toolbar # For debugging Django
django-extensions # Custom dev extensions
gunicorn
inflect
pywatchman # More effecient checking for runserver reload trigger events
Loading

0 comments on commit 84cbd1e

Please sign in to comment.