Commit 019b61f5 by Tasawer

Removing expired FulfillmentMixin + fixing broken tests

XCOM-307
parent 916a5f23
...@@ -11,7 +11,7 @@ from oscar.test import factories ...@@ -11,7 +11,7 @@ from oscar.test import factories
from ecommerce.extensions.api.tests.test_authentication import AccessTokenMixin, OAUTH2_PROVIDER_URL from ecommerce.extensions.api.tests.test_authentication import AccessTokenMixin, OAUTH2_PROVIDER_URL
from ecommerce.extensions.api.v2.tests.views import OrderDetailViewTestMixin from ecommerce.extensions.api.v2.tests.views import OrderDetailViewTestMixin
from ecommerce.extensions.fulfillment.mixins import FulfillmentMixin from ecommerce.extensions.fulfillment.signals import SHIPPING_EVENT_NAME
from ecommerce.extensions.fulfillment.status import LINE, ORDER from ecommerce.extensions.fulfillment.status import LINE, ORDER
from ecommerce.tests.mixins import UserMixin, ThrottlingMixin from ecommerce.tests.mixins import UserMixin, ThrottlingMixin
...@@ -95,9 +95,10 @@ class OrderListViewTests(AccessTokenMixin, ThrottlingMixin, UserMixin, TestCase) ...@@ -95,9 +95,10 @@ class OrderListViewTests(AccessTokenMixin, ThrottlingMixin, UserMixin, TestCase)
@ddt.ddt @ddt.ddt
class OrderFulfillViewTests(UserMixin, TestCase): class OrderFulfillViewTests(UserMixin, TestCase):
def setUp(self): def setUp(self):
super(OrderFulfillViewTests, self).setUp() super(OrderFulfillViewTests, self).setUp()
ShippingEventType.objects.get_or_create(name=FulfillmentMixin.SHIPPING_EVENT_NAME) ShippingEventType.objects.get_or_create(name=SHIPPING_EVENT_NAME)
self.user = self.create_user(is_superuser=True) self.user = self.create_user(is_superuser=True)
self.client.login(username=self.user.username, password=self.password) self.client.login(username=self.user.username, password=self.password)
......
...@@ -3,7 +3,7 @@ import logging ...@@ -3,7 +3,7 @@ import logging
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from oscar.core.loading import get_model from oscar.core.loading import get_model, get_class
from rest_framework import status, generics, viewsets, mixins from rest_framework import status, generics, viewsets, mixins
from rest_framework.decorators import detail_route from rest_framework.decorators import detail_route
from rest_framework.exceptions import ParseError from rest_framework.exceptions import ParseError
...@@ -20,7 +20,6 @@ from ecommerce.extensions.api.constants import APIConstants as AC ...@@ -20,7 +20,6 @@ from ecommerce.extensions.api.constants import APIConstants as AC
from ecommerce.extensions.api.exceptions import BadRequestException from ecommerce.extensions.api.exceptions import BadRequestException
from ecommerce.extensions.api.permissions import CanActForUser from ecommerce.extensions.api.permissions import CanActForUser
from ecommerce.extensions.checkout.mixins import EdxOrderPlacementMixin from ecommerce.extensions.checkout.mixins import EdxOrderPlacementMixin
from ecommerce.extensions.fulfillment.mixins import FulfillmentMixin
from ecommerce.extensions.payment import exceptions as payment_exceptions from ecommerce.extensions.payment import exceptions as payment_exceptions
from ecommerce.extensions.payment.helpers import (get_processor_class, get_default_processor_class, from ecommerce.extensions.payment.helpers import (get_processor_class, get_default_processor_class,
get_processor_class_by_name) get_processor_class_by_name)
...@@ -365,7 +364,7 @@ class OrderByBasketRetrieveView(OrderRetrieveView): ...@@ -365,7 +364,7 @@ class OrderByBasketRetrieveView(OrderRetrieveView):
lookup_field = 'basket_id' lookup_field = 'basket_id'
class OrderFulfillView(FulfillmentMixin, generics.UpdateAPIView): class OrderFulfillView(generics.UpdateAPIView):
permission_classes = (IsAuthenticated, DjangoModelPermissions,) permission_classes = (IsAuthenticated, DjangoModelPermissions,)
lookup_field = 'number' lookup_field = 'number'
queryset = Order.objects.all() queryset = Order.objects.all()
...@@ -378,7 +377,8 @@ class OrderFulfillView(FulfillmentMixin, generics.UpdateAPIView): ...@@ -378,7 +377,8 @@ class OrderFulfillView(FulfillmentMixin, generics.UpdateAPIView):
return Response(status=status.HTTP_406_NOT_ACCEPTABLE) return Response(status=status.HTTP_406_NOT_ACCEPTABLE)
logger.info('Retrying fulfillment of order [%s]...', order.number) logger.info('Retrying fulfillment of order [%s]...', order.number)
order = self.fulfill_order(order) post_checkout = get_class('checkout.signals', 'post_checkout')
post_checkout.send(sender=post_checkout, order=order)
if order.can_retry_fulfillment: if order.can_retry_fulfillment:
logger.warning('Fulfillment of order [%s] failed!', order.number) logger.warning('Fulfillment of order [%s] failed!', order.number)
......
...@@ -11,7 +11,7 @@ from selenium.webdriver.firefox.webdriver import WebDriver ...@@ -11,7 +11,7 @@ from selenium.webdriver.firefox.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support.wait import WebDriverWait
from ecommerce.extensions.dashboard.tests import DashboardViewTestMixin from ecommerce.extensions.dashboard.tests import DashboardViewTestMixin
from ecommerce.extensions.fulfillment.mixins import FulfillmentMixin from ecommerce.extensions.fulfillment.signals import SHIPPING_EVENT_NAME
from ecommerce.extensions.fulfillment.status import ORDER, LINE from ecommerce.extensions.fulfillment.status import ORDER, LINE
from ecommerce.extensions.refund.tests.mixins import RefundTestMixin from ecommerce.extensions.refund.tests.mixins import RefundTestMixin
from ecommerce.tests.mixins import UserMixin from ecommerce.tests.mixins import UserMixin
...@@ -63,7 +63,7 @@ class OrderListViewTests(OrderViewTestsMixin, RefundTestMixin, LiveServerTestCas ...@@ -63,7 +63,7 @@ class OrderListViewTests(OrderViewTestsMixin, RefundTestMixin, LiveServerTestCas
self.order.save() self.order.save()
self.order.lines.all().update(status=LINE.FULFILLMENT_CONFIGURATION_ERROR) self.order.lines.all().update(status=LINE.FULFILLMENT_CONFIGURATION_ERROR)
ShippingEventType.objects.get_or_create(name=FulfillmentMixin.SHIPPING_EVENT_NAME) ShippingEventType.objects.get_or_create(name=SHIPPING_EVENT_NAME)
def _login(self): def _login(self):
""" Log into the service and navigate to the order list view. """ """ Log into the service and navigate to the order list view. """
......
"""Mixins to support views that fulfill orders."""
from oscar.core.loading import get_model, get_class
ShippingEventType = get_model('order', 'ShippingEventType')
EventHandler = get_class('order.processing', 'EventHandler')
# TODO (RFL): Retire this mixin in favor of the `post_checkout_callback`.
class FulfillmentMixin(object):
"""A mixin that provides the ability to fulfill orders."""
SHIPPING_EVENT_NAME = 'Shipped'
def fulfill_order(self, order):
"""Attempt fulfillment of an order."""
order_lines = order.lines.all()
line_quantities = [line.quantity for line in order_lines]
shipping_event, __ = ShippingEventType.objects.get_or_create(name=self.SHIPPING_EVENT_NAME)
fulfilled_order = EventHandler().handle_shipping_event(order, shipping_event, order_lines, line_quantities)
return fulfilled_order
from django.dispatch import receiver from django.dispatch import receiver
from oscar.core.loading import get_class from oscar.core.loading import get_class, get_model
ShippingEventType = get_model('order', 'ShippingEventType')
EventHandler = get_class('order.processing', 'EventHandler')
post_checkout = get_class('checkout.signals', 'post_checkout') post_checkout = get_class('checkout.signals', 'post_checkout')
SHIPPING_EVENT_NAME = 'Shipped'
@receiver(post_checkout, dispatch_uid='fulfillment.post_checkout_callback') @receiver(post_checkout, dispatch_uid='fulfillment.post_checkout_callback')
...@@ -11,7 +13,9 @@ def post_checkout_callback(sender, order=None, **kwargs): # pylint: disable=unu ...@@ -11,7 +13,9 @@ def post_checkout_callback(sender, order=None, **kwargs): # pylint: disable=unu
# module will also be loaded before coverage. Module loaded after coverage are falsely listed as not covered. # module will also be loaded before coverage. Module loaded after coverage are falsely listed as not covered.
# We do not want the false report, and we do not want to omit the api module from coverage reports. This is the # We do not want the false report, and we do not want to omit the api module from coverage reports. This is the
# "happy" medium. # "happy" medium.
from ecommerce.extensions.fulfillment import api
# TODO Determine if we need to create ShippingEvents first. order_lines = order.lines.all()
api.fulfill_order(order, order.lines.all()) line_quantities = [line.quantity for line in order_lines]
shipping_event, __ = ShippingEventType.objects.get_or_create(name=SHIPPING_EVENT_NAME)
EventHandler().handle_shipping_event(order, shipping_event, order_lines, line_quantities)
...@@ -2,6 +2,7 @@ from django.test import TestCase ...@@ -2,6 +2,7 @@ from django.test import TestCase
from oscar.core.loading import get_model from oscar.core.loading import get_model
from oscar.test import factories from oscar.test import factories
from ecommerce.extensions.fulfillment.signals import SHIPPING_EVENT_NAME
from ecommerce.extensions.fulfillment.status import LINE from ecommerce.extensions.fulfillment.status import LINE
from ecommerce.extensions.order.processing import EventHandler from ecommerce.extensions.order.processing import EventHandler
...@@ -11,9 +12,10 @@ ShippingEvent = get_model('order', 'ShippingEvent') ...@@ -11,9 +12,10 @@ ShippingEvent = get_model('order', 'ShippingEvent')
class EventHandlerTests(TestCase): class EventHandlerTests(TestCase):
def setUp(self): def setUp(self):
super(EventHandlerTests, self).setUp() super(EventHandlerTests, self).setUp()
self.shipping_event_type = ShippingEventType.objects.create(name='Shipped') self.shipping_event_type = ShippingEventType.objects.create(name=SHIPPING_EVENT_NAME)
self.order = factories.create_order() self.order = factories.create_order()
def test_create_shipping_event_all_lines_complete(self): def test_create_shipping_event_all_lines_complete(self):
......
...@@ -14,7 +14,7 @@ from oscar.core.loading import get_model, get_class ...@@ -14,7 +14,7 @@ from oscar.core.loading import get_model, get_class
from ecommerce.courses.utils import mode_for_seat from ecommerce.courses.utils import mode_for_seat
from ecommerce.extensions.api.constants import APIConstants as AC from ecommerce.extensions.api.constants import APIConstants as AC
from ecommerce.extensions.fulfillment.mixins import FulfillmentMixin from ecommerce.extensions.fulfillment.signals import SHIPPING_EVENT_NAME
Basket = get_model('basket', 'Basket') Basket = get_model('basket', 'Basket')
...@@ -65,7 +65,6 @@ class JwtMixin(object): ...@@ -65,7 +65,6 @@ class JwtMixin(object):
class BasketCreationMixin(JwtMixin): class BasketCreationMixin(JwtMixin):
"""Provides utility methods for creating baskets in test cases.""" """Provides utility methods for creating baskets in test cases."""
PATH = reverse('api:v2:baskets:create') PATH = reverse('api:v2:baskets:create')
SHIPPING_EVENT_NAME = FulfillmentMixin.SHIPPING_EVENT_NAME
FREE_SKU = u'𝑭𝑹𝑬𝑬-𝑷𝑹𝑶𝑫𝑼𝑪𝑻' FREE_SKU = u'𝑭𝑹𝑬𝑬-𝑷𝑹𝑶𝑫𝑼𝑪𝑻'
USERNAME = 'sgoodman' USERNAME = 'sgoodman'
USER_DATA = { USER_DATA = {
...@@ -131,7 +130,7 @@ class BasketCreationMixin(JwtMixin): ...@@ -131,7 +130,7 @@ class BasketCreationMixin(JwtMixin):
): ):
"""Verify that basket creation succeeded.""" """Verify that basket creation succeeded."""
# Ideally, we'd use Oscar's ShippingEventTypeFactory here, but it's not exposed/public. # Ideally, we'd use Oscar's ShippingEventTypeFactory here, but it's not exposed/public.
ShippingEventType.objects.get_or_create(name=self.SHIPPING_EVENT_NAME) ShippingEventType.objects.get_or_create(name=SHIPPING_EVENT_NAME)
with patch('ecommerce.extensions.analytics.utils.audit_log') as mock_audit_log: with patch('ecommerce.extensions.analytics.utils.audit_log') as mock_audit_log:
response = self.create_basket(skus=skus, checkout=checkout, payment_processor_name=payment_processor_name) response = self.create_basket(skus=skus, checkout=checkout, payment_processor_name=payment_processor_name)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment