Skip to content

Commit

Permalink
Merge pull request #2 from openedx/hu/ent-6730
Browse files Browse the repository at this point in the history
feat: django simple history
  • Loading branch information
brobro10000 authored Feb 16, 2023
2 parents a0491fa + 49d3c48 commit 76efa56
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 4 deletions.
6 changes: 6 additions & 0 deletions .annotation_safe_list.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ auth.User:
".. pii_retirement": "consumer_api"
contenttypes.ContentType:
".. no_pii:": "This model has no PII"
openedx_ledger.HistoricalLedger:
".. no_pii:": "This model has no PII"
openedx_ledger.HistoricalReversal:
".. no_pii:": "This model has no PII"
openedx_ledger.HistoricalTransaction:
".. no_pii:": "This model has no PII"
sessions.Session:
".. no_pii:": "This model has no PII"
social_django.Association:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
*.py[cod]
__pycache__
.pytest_cache
default.db

# C extensions
*.so
Expand Down
Empty file removed default.db
Empty file.
2 changes: 1 addition & 1 deletion openedx_ledger/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
A library that records transactions against a ledger, denominated in units of value.
"""
__version__ = "0.1.1"
__version__ = "0.1.2"

default_app_config = "openedx_ledger.apps.EdxLedgerConfig"
7 changes: 4 additions & 3 deletions openedx_ledger/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
Admin configuration for openedx_ledger models.
"""
from django.contrib import admin
from simple_history.admin import SimpleHistoryAdmin

from openedx_ledger import models


@admin.register(models.Ledger)
class LedgerAdmin(admin.ModelAdmin):
class LedgerAdmin(SimpleHistoryAdmin):
"""
Admin configuration for the Ledger model.
"""
Expand Down Expand Up @@ -39,7 +40,7 @@ def balance(self, obj):


@admin.register(models.Transaction)
class TransactionAdmin(admin.ModelAdmin):
class TransactionAdmin(SimpleHistoryAdmin):
"""
Admin configuration for the Transaction model.
"""
Expand All @@ -54,7 +55,7 @@ class Meta:


@admin.register(models.Reversal)
class ReversalAdmin(admin.ModelAdmin):
class ReversalAdmin(SimpleHistoryAdmin):
"""
Admin configuration for the Reversal model.
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Generated by Django 3.2.16 on 2023-02-14 12:49

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import jsonfield.fields
import model_utils.fields
import simple_history.models
import uuid


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('openedx_ledger', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='HistoricalTransaction',
fields=[
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False)),
('idempotency_key', models.CharField(db_index=True, max_length=255)),
('quantity', models.BigIntegerField()),
('metadata', jsonfield.fields.JSONField(blank=True, null=True)),
('lms_user_id', models.IntegerField(blank=True, db_index=True, null=True)),
('content_uuid', models.UUIDField(blank=True, db_index=True, null=True)),
('reference_id', models.CharField(blank=True, db_index=True, help_text='The identifier of the item acquired via the transaction.e.g. a course enrollment ID, an entitlement ID, a subscription license ID.', max_length=255, null=True)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField()),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('ledger', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='openedx_ledger.ledger')),
],
options={
'verbose_name': 'historical transaction',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalReversal',
fields=[
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False)),
('idempotency_key', models.CharField(db_index=True, max_length=255)),
('quantity', models.BigIntegerField()),
('metadata', jsonfield.fields.JSONField(blank=True, null=True)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField()),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('transaction', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='openedx_ledger.transaction')),
],
options={
'verbose_name': 'historical reversal',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalLedger',
fields=[
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False)),
('idempotency_key', models.CharField(db_index=True, max_length=255)),
('unit', models.CharField(choices=[('usd_cents', 'U.S. Dollar (Cents)'), ('seats', 'Seats in a course'), ('jpy', 'Japanese Yen')], db_index=True, default='usd_cents', max_length=255)),
('metadata', jsonfield.fields.JSONField(blank=True, null=True)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField()),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical ledger',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
]
4 changes: 4 additions & 0 deletions openedx_ledger/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.db.transaction import atomic
from jsonfield.fields import JSONField
from model_utils.models import TimeStampedModel
from simple_history.models import HistoricalRecords

# Units on the ledger model - probably yes. TODO: say why
# Unit conversion - price/seat is captured somewhere, is it in here?
Expand Down Expand Up @@ -80,6 +81,7 @@ class Ledger(TimeStampedModelWithUuid):
blank=True,
null=True,
)
history = HistoricalRecords()

def balance(self):
"""
Expand Down Expand Up @@ -170,6 +172,7 @@ class Meta:
"e.g. a course enrollment ID, an entitlement ID, a subscription license ID."
),
)
history = HistoricalRecords()


class Reversal(BaseTransaction):
Expand All @@ -192,5 +195,6 @@ class Meta:
null=True,
on_delete=models.SET_NULL,
)
history = HistoricalRecords()
# Reversal quantities should always have the opposite sign of the transaction (i.e. negative)
# We have to enforce this somehow...
2 changes: 2 additions & 0 deletions test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def root(*args):
'django.contrib.messages',
'django.contrib.sessions',
'openedx_ledger',
'simple_history',
)

LOCALE_PATHS = [
Expand All @@ -47,6 +48,7 @@ def root(*args):
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'simple_history.middleware.HistoryRequestMiddleware',
)

TEMPLATES = [{
Expand Down

0 comments on commit 76efa56

Please sign in to comment.