diff --git a/ecommerce/migrations/0044_alter_product_unique_purchasable_object.py b/ecommerce/migrations/0044_alter_product_unique_purchasable_object.py new file mode 100644 index 0000000000..11be2c0f52 --- /dev/null +++ b/ecommerce/migrations/0044_alter_product_unique_purchasable_object.py @@ -0,0 +1,21 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("ecommerce", "0043_refund_request_status"), + ] + + operations = [ + migrations.RemoveConstraint( + model_name="product", + name="unique_purchasable_object", + ), + migrations.AddConstraint( + model_name="product", + constraint=models.UniqueConstraint( + fields=("object_id", "content_type"), + name="unique_purchasable_object", + ), + ), + ] diff --git a/ecommerce/models.py b/ecommerce/models.py index 300139c2c1..265b91384a 100644 --- a/ecommerce/models.py +++ b/ecommerce/models.py @@ -102,8 +102,7 @@ class Product(TimestampedModel): class Meta: constraints = [ models.UniqueConstraint( - fields=["object_id", "is_active", "content_type"], - condition=models.Q(is_active=True), + fields=["object_id", "content_type"], name="unique_purchasable_object", ) ] diff --git a/ecommerce/models_test.py b/ecommerce/models_test.py index fe3b331f97..7cb42d886a 100644 --- a/ecommerce/models_test.py +++ b/ecommerce/models_test.py @@ -329,9 +329,9 @@ def test_product_managers(): ) -def test_product_multiple_active_for_single_purchasable_object(): - """Test that creating multiple Products with the same course/program - and are active is not allowed +def test_product_multiple_for_single_purchasable_object(): + """Test that creating multiple Products with the same course/program is not allowed, + regardless of active state. """ first_product = ProductFactory.create() try: @@ -341,6 +341,16 @@ def test_product_multiple_active_for_single_purchasable_object(): except IntegrityError: pass + first_product.delete() + try: + with transaction.atomic(): + ProductFactory.create(purchasable_object=first_product.purchasable_object) + pytest.fail( + "A Product was created for a purchasable_object that already has an inactive Product." + ) + except IntegrityError: + pass + def test_order_update_reference_number(user): """Test when order is created/updated, reference_number is updated in db"""