Skip to content

Commit

Permalink
feat: add lms_user_email and content_tile to Transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnagro committed Oct 24, 2023
1 parent 2f4b8f0 commit 6d24559
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ Unreleased
**********
* Nothing unreleased

[1.3.0]
*******
* Add optional ``lms_user_email`` and ``content_title`` to the ``Transaction`` model

[1.2.0]
*******
* Add an ``Adjustment`` model
Expand Down
98 changes: 98 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Docker in this repo is only supported for running tests locally
# as an alternative to virtualenv natively - johnnagro 2022-02-11
FROM ubuntu:focal as app
MAINTAINER sre@edx.org


# Packages installed:
# git; Used to pull in particular requirements from github rather than pypi,
# and to check the sha of the code checkout.

# build-essentials; so we can use make with the docker container

# language-pack-en locales; ubuntu locale support so that system utilities have a consistent
# language and time zone.

# python; ubuntu doesnt ship with python, so this is the python we will use to run the application

# python3-pip; install pip to install application requirements.txt files

# pkg-config
# mysqlclient>=2.2.0 requires this (https://github.com/PyMySQL/mysqlclient/issues/620)

# libmysqlclient-dev; to install header files needed to use native C implementation for
# MySQL-python for performance gains.

# libssl-dev; # mysqlclient wont install without this.

# python3-dev; to install header files for python extensions; much wheel-building depends on this

# gcc; for compiling python extensions distributed with python packages like mysql-client

# If you add a package here please include a comment above describing what it is used for
RUN apt-get update && apt-get -qy install --no-install-recommends \
language-pack-en \
locales \
python3.8 \
python3-pip \
python3.8-venv \
pkg-config \
libmysqlclient-dev \
libssl-dev \
python3-dev \
gcc \
build-essential \
git \
curl


RUN pip install --upgrade pip setuptools
# delete apt package lists because we do not need them inflating our image
RUN rm -rf /var/lib/apt/lists/*

RUN ln -s /usr/bin/python3 /usr/bin/python

RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
ENV DJANGO_SETTINGS_MODULE enterprise.settings.test

# Env vars: path
ENV VIRTUAL_ENV='/edx/app/venvs/openedx-ledger'
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
ENV PATH="/edx/app/openedx-ledger/node_modules/.bin:${PATH}"
ENV PATH="/edx/app/openedx-ledger/bin:${PATH}"
ENV PATH="/edx/app/nodeenv/bin:${PATH}"

RUN useradd -m --shell /bin/false app

WORKDIR /edx/app/openedx-ledger

RUN python3.8 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"

# Copy the requirements explicitly even though we copy everything below
# this prevents the image cache from busting unless the dependencies have changed.
COPY requirements/ /edx/app/openedx-ledger/requirements/

# Dependencies are installed as root so they cannot be modified by the application user.
RUN pip install -r requirements/dev.txt
RUN pip install nodeenv

# Set up a Node environment and install Node requirements.
# Must be done after Python requirements, since nodeenv is installed
# via pip.
# The node environment is already 'activated' because its .../bin was put on $PATH.
RUN nodeenv /edx/app/nodeenv --node=18.15.0 --prebuilt

RUN mkdir -p /edx/var/log

# Code is owned by root so it cannot be modified by the application user.
# So we copy it before changing users.
USER app

# This line is after the requirements so that changes to the code will not
# bust the image cache
COPY . /edx/app/openedx-ledger

5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ style:
lint:
pylint openedx_ledger tests manage.py setup.py

## Docker in this repo is only supported for running tests locally
## as an alternative to virtualenv natively
test-shell: ## Run a shell, as root, on the specified service container
docker-compose run -u 0 test-shell env TERM=$(TERM) /bin/bash

## Localization targets

extract_translations: ## extract strings to be translated, outputting .mo files
Expand Down
25 changes: 25 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Docker in this repo is only supported for running tests locally
# as an alternative to virtualenv natively - johnnagro 2022-02-11
version: "2.1"
services:
test-shell:
build:
context: .
dockerfile: Dockerfile
container_name: openedx-ledger.test.app
hostname: app.test.openedx-ledger
volumes:
- .:/edx/app/openedx-ledger

networks:
- devstack_default
# Allows attachment to this container using 'docker attach <containerID>'.
stdin_open: true
tty: true
environment:
DJANGO_SETTINGS_MODULE: test_settings

networks:
devstack_default:
external: true

2 changes: 1 addition & 1 deletion openedx_ledger/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""
A library that records transactions against a ledger, denominated in units of value.
"""
__version__ = "1.2.0"
__version__ = "1.3.0"
10 changes: 10 additions & 0 deletions openedx_ledger/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ def create_transaction(
quantity,
idempotency_key,
lms_user_id=None,
lms_user_email=None,
content_key=None,
content_tile=None,
subsidy_access_policy_uuid=None,
state=models.TransactionStateChoices.CREATED,
**metadata
Expand All @@ -57,9 +59,15 @@ def create_transaction(
lms_user_id (int, Optional):
The lms_user_id representing the learner who is enrolling. Skip if this does not represent a policy
enrolling a learner into content.
lms_user_email (str, Optional):
The lms_user_email representing the learner who is enrolling. Skip if this does not represent a policy
enrolling a learner into content or if the email is not readily available.
content_key (str, Optional):
The identifier of the content into which the learner is enrolling. Skip if this does not represent a policy
enrolling a learner into content.
content_title (str, Optional):
The title of the content into which the learner is enrolling. Skip if this does not represent a policy
enrolling a learner into content or if the title is not readily available.
subsidy_access_policy_uuid (str, Optional):
The policy which permitted the creation of the new Transaction. Skip if this does not represent a policy
enrolling a learner into content.
Expand Down Expand Up @@ -88,7 +96,9 @@ def create_transaction(
defaults={
"quantity": quantity,
"content_key": content_key,
"content_title": content_tile,
"lms_user_id": lms_user_id,
"lms_user_email": lms_user_email,
"subsidy_access_policy_uuid": subsidy_access_policy_uuid,
"state": state,
"metadata": metadata,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 3.2.18 on 2023-10-24 19:59

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('openedx_ledger', '0008_adjustment_model'),
]

operations = [
migrations.AddField(
model_name='historicaltransaction',
name='content_title',
field=models.CharField(blank=True, db_index=True, help_text='The title of the content associated with this Transaction.The title is captured at the time the Transaction is created and may not be up to date.', max_length=255, null=True),
),
migrations.AddField(
model_name='historicaltransaction',
name='lms_user_email',
field=models.CharField(blank=True, db_index=True, help_text='The email of the Open edX LMS user record with which this Transaction is associated.The email is captured at the time the Transaction is created and may not be up to date.', max_length=255, null=True),
),
migrations.AddField(
model_name='transaction',
name='content_title',
field=models.CharField(blank=True, db_index=True, help_text='The title of the content associated with this Transaction.The title is captured at the time the Transaction is created and may not be up to date.', max_length=255, null=True),
),
migrations.AddField(
model_name='transaction',
name='lms_user_email',
field=models.CharField(blank=True, db_index=True, help_text='The email of the Open edX LMS user record with which this Transaction is associated.The email is captured at the time the Transaction is created and may not be up to date.', max_length=255, null=True),
),
]
20 changes: 20 additions & 0 deletions openedx_ledger/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,16 @@ class Meta:
"The id of the Open edX LMS user record with which this Transaction is associated."
),
)
lms_user_email = models.CharField(
max_length=255,
blank=True,
null=True,
db_index=True,
help_text=(
"The email of the Open edX LMS user record with which this Transaction is associated."
"The email is captured at the time the Transaction is created and may not be up to date."
)
)
content_key = models.CharField(
max_length=255,
blank=True,
Expand All @@ -353,6 +363,16 @@ class Meta:
"The globally unique content identifier. Joinable with ContentMetadata.content_key in enterprise-catalog."
)
)
content_title = models.CharField(
max_length=255,
blank=True,
null=True,
db_index=True,
help_text=(
"The title of the content associated with this Transaction."
"The title is captured at the time the Transaction is created and may not be up to date."
)
)
fulfillment_identifier = models.CharField(
max_length=255,
blank=True,
Expand Down
3 changes: 3 additions & 0 deletions openedx_ledger/test_utils/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class Meta:
quantity = factory.Faker("random_int", min=-100000, max=-100)
ledger = factory.Iterator(Ledger.objects.all())
lms_user_id = factory.Faker("random_int", min=1, max=1000)
lms_user_email = factory.Faker("email")
content_key = factory.Faker("lexify", text="???+?????101")
content_title = factory.Faker("lexify", text="???: ?????? ???")


class ExternalFulfillmentProviderFactory(factory.django.DjangoModelFactory):
Expand Down
2 changes: 2 additions & 0 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ def setUp(self):
self.transaction_5 = TransactionFactory(
ledger=self.ledger,
lms_user_id=3,
lms_user_email='user@example.com',
content_key="course-v1:edX+test+course.3",
content_title="Edx: test course 3",
quantity=-10,
state=models.TransactionStateChoices.PENDING,
)
Expand Down

0 comments on commit 6d24559

Please sign in to comment.