diff --git a/lms/djangoapps/commerce/api/v1/tests/test_views.py b/lms/djangoapps/commerce/api/v1/tests/test_views.py index b45ca537cd6b..2bf2a8ed4462 100644 --- a/lms/djangoapps/commerce/api/v1/tests/test_views.py +++ b/lms/djangoapps/commerce/api/v1/tests/test_views.py @@ -13,11 +13,13 @@ from django.test import TestCase from django.test.utils import override_settings from django.urls import reverse, reverse_lazy +from opaque_keys.edx.keys import CourseKey from rest_framework.utils.encoders import JSONEncoder from common.djangoapps.course_modes.models import CourseMode +from common.djangoapps.course_modes.tests.factories import CourseModeFactory from lms.djangoapps.verify_student.models import VerificationDeadline -from common.djangoapps.student.tests.factories import UserFactory +from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory @@ -190,6 +192,29 @@ def test_update(self): # Verify the verification deadline is updated self.assertEqual(VerificationDeadline.deadline_for_course(self.course.id), verification_deadline) + def test_update_min_price(self): + """ + Verify CourseMode objects can have min_price updated to a min_price type float via PUT on the API. + """ + new_min_price = 50.00 + course_mode_updated = CourseMode( + course_id=self.course_mode.course_id, + mode_slug=u'verified', + min_price=new_min_price, + ) + updated_data = self._serialize_course(self.course, [course_mode_updated]) + + response = self.client.put( + self.path, + data=json.dumps(updated_data), + content_type=JSON_CONTENT_TYPE + ) + self.assertEqual(response.status_code, 200) + + response_updated = json.loads(response.content.decode('utf-8'))['modes'] + self.assertEqual(response_updated[0]['price'], int(new_min_price)) + self.assertIsInstance(response_updated[0]['price'], int) + def test_update_invalid_dates(self): """ Verify the API does not allow the verification deadline to be set before the course mode upgrade deadlines. diff --git a/lms/djangoapps/commerce/api/v1/views.py b/lms/djangoapps/commerce/api/v1/views.py index 80d3bd7fed5d..48af5a28c0ce 100644 --- a/lms/djangoapps/commerce/api/v1/views.py +++ b/lms/djangoapps/commerce/api/v1/views.py @@ -12,6 +12,7 @@ from rest_framework.authentication import SessionAuthentication from rest_framework.generics import ListAPIView, RetrieveUpdateAPIView from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response from rest_framework.views import APIView from openedx.core.lib.api.authentication import BearerAuthentication @@ -23,7 +24,7 @@ from ...utils import is_account_activation_requirement_disabled from .models import Course from .permissions import ApiKeyOrModelPermission, IsAuthenticatedOrActivationOverridden -from .serializers import CourseSerializer +from .serializers import CourseSerializer, CourseModeSerializer log = logging.getLogger(__name__) @@ -67,6 +68,19 @@ def pre_save(self, obj): # a CourseKey to a string, which is not desired. pass + def put(self, request, *args, **kwargs): + """ + Performs a partial update of a Course/CourseMode instance. + """ + course_mode = CourseMode.objects.filter(course_id=kwargs['course_id']).first() + + if not isinstance(course_mode.min_price, int): + course_mode.min_price = int(course_mode.min_price) + serializer = CourseModeSerializer(course_mode, data=request.data, partial=True) + if serializer.is_valid(raise_exception=True): + serializer.save() + return Response(serializer.data) + return Response(request.data) class OrderView(APIView): """ Retrieve order details. """