Skip to content

Commit

Permalink
Merge pull request #271 from openedx/pwnage101/ENT-9075-5
Browse files Browse the repository at this point in the history
fix: make initial deposit backfill defensive against subsidy-less ledgers
  • Loading branch information
pwnage101 authored Jul 10, 2024
2 parents c2fa02a + 744f00f commit 147a34f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,23 @@
Note this has no reverse migration logic. Attempts to rollback the deployment which includes this PR will not delete
(un-backfill) the deposits created during the forward migration.
"""
import logging

import django.utils.timezone
from django.db import migrations

from enterprise_subsidy.apps.subsidy.migration_utils import find_legacy_initial_transactions
from enterprise_subsidy.apps.subsidy.models import SubsidyReferenceChoices

logger = logging.getLogger(__name__)


def forwards_func(apps, schema_editor):
"""
The core logic of this migration.
"""
# We get the models from the versioned app registry; if we directly import it, it'll be the wrong version.
Ledger = apps.get_model("openedx_ledger", "Ledger")
Transaction = apps.get_model("openedx_ledger", "Transaction")
Deposit = apps.get_model("openedx_ledger", "Deposit")
HistoricalDeposit = apps.get_model("openedx_ledger", "HistoricalDeposit")
Expand All @@ -44,12 +49,22 @@ def forwards_func(apps, schema_editor):
deposits_to_backfill = []
historical_deposits_to_backfill = []
for tx in legacy_initial_transactions:
sales_contract_reference_id = None
sales_contract_reference_provider = None
try:
sales_contract_reference_id = tx.ledger.subsidy.reference_id
sales_contract_reference_provider = sales_contract_reference_providers[tx.ledger.subsidy.reference_type]
except Ledger.subsidy.RelatedObjectDoesNotExist:
logger.warning(
"Found a ledger (%s) without a related subsidy, so the initial deposit will not have a sales contract.",
tx.ledger.uuid,
)
deposit_fields = {
"ledger": tx.ledger,
"transaction": tx,
"desired_deposit_quantity": tx.quantity,
"sales_contract_reference_id": tx.ledger.subsidy.reference_id,
"sales_contract_reference_provider": sales_contract_reference_providers[tx.ledger.subsidy.reference_type],
"sales_contract_reference_id": sales_contract_reference_id,
"sales_contract_reference_provider": sales_contract_reference_provider,
}
deposit = Deposit(**deposit_fields)
historical_deposit = HistoricalDeposit(
Expand Down
66 changes: 43 additions & 23 deletions enterprise_subsidy/apps/subsidy/tests/test_migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,22 @@

@pytest.mark.django_db
@pytest.mark.parametrize(
"initial_deposit_exists,subsidy_reference_id",
"initial_deposit_exists,subsidy_exists,subsidy_reference_id",
[
(False, None),
(False, "abc123"),
(True, None),
(True, "abc123"),
(False, False, None),
(False, True, None),
(False, True, "abc123"),
(True, False, None),
(True, True, None),
(True, True, "abc123"),
],
)
def test_migration_0022_backfill_initial_deposits(migrator, initial_deposit_exists, subsidy_reference_id):
def test_migration_0022_backfill_initial_deposits(
migrator,
initial_deposit_exists,
subsidy_exists,
subsidy_reference_id,
):
"""
Test Backfilling initial deposits via data migration.
"""
Expand All @@ -36,23 +43,27 @@ def test_migration_0022_backfill_initial_deposits(migrator, initial_deposit_exis
SalesContractReferenceProvider = old_state.apps.get_model("openedx_ledger", "SalesContractReferenceProvider")

ledger = Ledger.objects.create()
subsidy = Subsidy.objects.create(
ledger=ledger,
starting_balance=100,
reference_id=subsidy_reference_id,
enterprise_customer_uuid=uuid.uuid4(),
)
subsidy = None
if subsidy_exists:
subsidy = Subsidy.objects.create(
ledger=ledger,
starting_balance=100,
reference_id=subsidy_reference_id,
enterprise_customer_uuid=uuid.uuid4(),
)
transaction = Transaction.objects.create(
ledger=ledger,
idempotency_key=INITIAL_DEPOSIT_TRANSACTION_SLUG,
quantity=subsidy.starting_balance,
quantity=subsidy.starting_balance if subsidy_exists else 100,
state=TransactionStateChoices.COMMITTED
)
if initial_deposit_exists:
sales_contract_reference_provider = SalesContractReferenceProvider.objects.create(
slug=subsidy.reference_type,
name="Foo Bar",
)
sales_contract_reference_provider = None
if subsidy_exists:
sales_contract_reference_provider = SalesContractReferenceProvider.objects.create(
slug=subsidy.reference_type,
name="Foo Bar",
)
Deposit.objects.create(
ledger=ledger,
desired_deposit_quantity=transaction.quantity,
Expand Down Expand Up @@ -83,14 +94,23 @@ def test_migration_0022_backfill_initial_deposits(migrator, initial_deposit_exis

# Finally check that all the deposit values are correct.
assert Deposit.objects.first().ledger.uuid == ledger.uuid
assert Deposit.objects.first().desired_deposit_quantity == subsidy.starting_balance
assert Deposit.objects.first().desired_deposit_quantity == 100
assert Deposit.objects.first().transaction.uuid == transaction.uuid
assert Deposit.objects.first().sales_contract_reference_id == subsidy_reference_id
assert Deposit.objects.first().sales_contract_reference_provider.slug == subsidy.reference_type
if subsidy_exists:
assert Deposit.objects.first().sales_contract_reference_id == subsidy_reference_id
assert Deposit.objects.first().sales_contract_reference_provider.slug == subsidy.reference_type
else:
assert Deposit.objects.first().sales_contract_reference_id is None
assert Deposit.objects.first().sales_contract_reference_provider is None

assert HistoricalDeposit.objects.first().ledger.uuid == ledger.uuid
assert HistoricalDeposit.objects.first().desired_deposit_quantity == subsidy.starting_balance
assert HistoricalDeposit.objects.first().desired_deposit_quantity == 100
assert HistoricalDeposit.objects.first().transaction.uuid == transaction.uuid
assert HistoricalDeposit.objects.first().sales_contract_reference_id == subsidy_reference_id
assert HistoricalDeposit.objects.first().sales_contract_reference_provider.slug == subsidy.reference_type
if subsidy_exists:
assert HistoricalDeposit.objects.first().sales_contract_reference_id == subsidy_reference_id
assert HistoricalDeposit.objects.first().sales_contract_reference_provider.slug == subsidy.reference_type
else:
assert HistoricalDeposit.objects.first().sales_contract_reference_id is None
assert HistoricalDeposit.objects.first().sales_contract_reference_provider is None
assert HistoricalDeposit.objects.first().history_type == "+"
assert HistoricalDeposit.objects.first().history_change_reason == "Data migration to backfill initial deposits"

0 comments on commit 147a34f

Please sign in to comment.