Skip to content

Commit

Permalink
Clears discounts when reusing an existing PendingOrder (#1721)
Browse files Browse the repository at this point in the history
* Clears discounts when reusing an existing PendingOrder
  • Loading branch information
jkachel committed Jul 5, 2023
1 parent 753e426 commit f01fc97
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 7 deletions.
20 changes: 14 additions & 6 deletions ecommerce/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,17 +640,25 @@ def _get_or_create(
product_content_types.append(product.content_type_id)

# Get or create a PendingOrder
orders = Order.objects.select_for_update().filter(
lines__purchased_object_id__in=product_object_ids,
lines__purchased_content_type_id__in=product_content_types,
lines__product_version__in=product_versions,
state=Order.STATE.PENDING,
purchaser=user,
orders = (
Order.objects.select_for_update()
.prefetch_related("discounts")
.filter(
lines__purchased_object_id__in=product_object_ids,
lines__purchased_content_type_id__in=product_content_types,
lines__product_version__in=product_versions,
state=Order.STATE.PENDING,
purchaser=user,
)
)
# Previously, multiple PendingOrders could be created for a single user
# for the same product, if multiple exist, grab the first.
if orders:
order = orders.first()

for old_discount in order.discounts.all():
old_discount.delete()

else:
order = Order.objects.create(
state=Order.STATE.PENDING,
Expand Down
39 changes: 38 additions & 1 deletion ecommerce/models_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.core.exceptions import ValidationError
from django.db import IntegrityError, transaction
from mitol.common.utils import now_in_utc
from reversion.models import Version

from ecommerce.constants import (
DISCOUNT_TYPE_DOLLARS_OFF,
Expand Down Expand Up @@ -36,7 +37,6 @@
Transaction,
)
from users.factories import UserFactory
from reversion.models import Version

pytestmark = [pytest.mark.django_db]

Expand Down Expand Up @@ -423,6 +423,43 @@ def test_pending_order_is_reused(basket):
assert Order.objects.filter(state=Order.STATE.PENDING).count() == 1


def test_pending_order_is_reused_but_discounts_cleared(basket, unlimited_discount):
"""
If a pending order is reused and had discounts, then we want those discounts
to clear.
"""

with reversion.create_revision():
product = ProductFactory.create()

basket_item = BasketItem(product=product, basket=basket, quantity=1)
basket_item.save()
order = PendingOrder.create_from_basket(basket)
order.save()
assert Order.objects.filter(state=Order.STATE.PENDING).count() == 1

redemption = DiscountRedemption(
redeemed_discount=unlimited_discount,
redemption_date=now_in_utc(),
redeemed_order=order,
redeemed_by=order.purchaser,
)
redemption.save()

order.refresh_from_db()
assert order.discounts.count() == 1

order = PendingOrder.create_from_basket(basket)
order.save()
order.refresh_from_db()

# Verify that the existing PendingOrder is reused and a duplicate is not created.
# This is to ensure that we also reuse the HubSpot Deal associated with Orders.
# Also ensure the discounts aren't reattached to the order
assert Order.objects.filter(state=Order.STATE.PENDING).count() == 1
assert order.discounts.count() == 0


def test_new_pending_order_is_created_if_product_is_different():
"""
Test that creating a second PendingOrder with a different associated Product
Expand Down

0 comments on commit f01fc97

Please sign in to comment.