Commit 8ff0d430 by Awais Jibran

Fix & cleanup course run seats in publisher

parent 1eaf7a1c
...@@ -17,3 +17,4 @@ PARTNER_COORDINATOR_GROUP_NAME = 'Partner Coordinators' ...@@ -17,3 +17,4 @@ PARTNER_COORDINATOR_GROUP_NAME = 'Partner Coordinators'
# Waffle flags # Waffle flags
PUBLISHER_ENTITLEMENTS_WAFFLE_SWITCH = 'publisher_entitlements' PUBLISHER_ENTITLEMENTS_WAFFLE_SWITCH = 'publisher_entitlements'
PUBLISHER_CREATE_AUDIT_SEATS_FOR_VERIFIED_COURSE_RUNS = 'publisher_create_audit_seats_for_verified_course_runs'
...@@ -15,6 +15,7 @@ from course_discovery.apps.course_metadata.choices import CourseRunPacing ...@@ -15,6 +15,7 @@ from course_discovery.apps.course_metadata.choices import CourseRunPacing
from course_discovery.apps.course_metadata.models import LevelType, Organization, Person, Subject from course_discovery.apps.course_metadata.models import LevelType, Organization, Person, Subject
from course_discovery.apps.ietf_language_tags.models import LanguageTag from course_discovery.apps.ietf_language_tags.models import LanguageTag
from course_discovery.apps.publisher.choices import CourseRunStateChoices, PublisherUserRole from course_discovery.apps.publisher.choices import CourseRunStateChoices, PublisherUserRole
from course_discovery.apps.publisher.constants import PUBLISHER_CREATE_AUDIT_SEATS_FOR_VERIFIED_COURSE_RUNS
from course_discovery.apps.publisher.mixins import LanguageModelSelect2Multiple, get_user_organizations from course_discovery.apps.publisher.mixins import LanguageModelSelect2Multiple, get_user_organizations
from course_discovery.apps.publisher.models import ( from course_discovery.apps.publisher.models import (
Course, CourseEntitlement, CourseRun, CourseRunState, CourseState, CourseUserRole, OrganizationExtension, Course, CourseEntitlement, CourseRun, CourseRunState, CourseState, CourseUserRole, OrganizationExtension,
...@@ -392,6 +393,10 @@ class SeatForm(BaseForm): ...@@ -392,6 +393,10 @@ class SeatForm(BaseForm):
model = Seat model = Seat
def save(self, commit=True, course_run=None, changed_by=None): # pylint: disable=arguments-differ def save(self, commit=True, course_run=None, changed_by=None): # pylint: disable=arguments-differ
"""Saves the seat for a particular course run."""
# Background -- EDUCATOR-2337 (Should be removed once the data is consistent)
self.validate_and_remove_seats(course_run)
# When seat is save make sure its prices and others fields updated accordingly. # When seat is save make sure its prices and others fields updated accordingly.
seat = super(SeatForm, self).save(commit=False) seat = super(SeatForm, self).save(commit=False)
if seat.type in [Seat.HONOR, Seat.AUDIT]: if seat.type in [Seat.HONOR, Seat.AUDIT]:
...@@ -413,12 +418,12 @@ class SeatForm(BaseForm): ...@@ -413,12 +418,12 @@ class SeatForm(BaseForm):
if commit: if commit:
seat.save() seat.save()
if waffle.switch_is_active('publisher_create_audit_seats_for_verified_course_runs'): if waffle.switch_is_active(PUBLISHER_CREATE_AUDIT_SEATS_FOR_VERIFIED_COURSE_RUNS):
course_run = seat.course_run course_run = seat.course_run
audit_seats = course_run.seats.filter(type=Seat.AUDIT) audit_seats = course_run.seats.filter(type=Seat.AUDIT)
# Ensure that course runs with a verified seat always have an audit seat # Ensure that course runs with a verified seat always have an audit seat
if seat.type in (Seat.CREDIT, Seat.VERIFIED,): if seat.type in Seat.PAID_AND_AUDIT_APPLICABLE_SEATS:
if not audit_seats.exists(): if not audit_seats.exists():
course_run.seats.create(type=Seat.AUDIT, price=0, upgrade_deadline=None) course_run.seats.create(type=Seat.AUDIT, price=0, upgrade_deadline=None)
logger.info('Created audit seat for course run [%d]', course_run.id) logger.info('Created audit seat for course run [%d]', course_run.id)
...@@ -448,6 +453,22 @@ class SeatForm(BaseForm): ...@@ -448,6 +453,22 @@ class SeatForm(BaseForm):
seat.credit_hours = None seat.credit_hours = None
seat.credit_price = 0.00 seat.credit_price = 0.00
def validate_and_remove_seats(self, course_run):
"""
Remove course run seats if the data is bogus
Temporary call to remove the duplicate course run seats -- EDUCATOR-2337
Background: There was a bug in the system, where course run seats being duplicated,
in order to cleanup, remove all the existing seats.
"""
if not course_run:
return
all_course_run_seats = course_run.seats.all()
seats_data_is_bogus = all_course_run_seats.count() > 2
if seats_data_is_bogus:
logger.info('Removing bogus course run [%d] seats [%d]', course_run.id, all_course_run_seats.count())
all_course_run_seats.delete()
class CourseEntitlementForm(BaseForm): class CourseEntitlementForm(BaseForm):
MODE_CHOICES = [ MODE_CHOICES = [
......
...@@ -25,15 +25,15 @@ from course_discovery.apps.course_metadata.models import LevelType, Organization ...@@ -25,15 +25,15 @@ from course_discovery.apps.course_metadata.models import LevelType, Organization
from course_discovery.apps.course_metadata.utils import UploadToFieldNamePath from course_discovery.apps.course_metadata.utils import UploadToFieldNamePath
from course_discovery.apps.ietf_language_tags.models import LanguageTag from course_discovery.apps.ietf_language_tags.models import LanguageTag
from course_discovery.apps.publisher import emails from course_discovery.apps.publisher import emails
from course_discovery.apps.publisher.choices import (CourseRunStateChoices, CourseStateChoices, InternalUserRole, from course_discovery.apps.publisher.choices import (
PublisherUserRole) CourseRunStateChoices, CourseStateChoices, InternalUserRole, PublisherUserRole
)
from course_discovery.apps.publisher.utils import is_email_notification_enabled, is_internal_user, is_publisher_admin from course_discovery.apps.publisher.utils import is_email_notification_enabled, is_internal_user, is_publisher_admin
from course_discovery.apps.publisher.validators import ImageMultiSizeValidator from course_discovery.apps.publisher.validators import ImageMultiSizeValidator
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
PAID_SEATS = ['verified', 'professional']
class ChangedByMixin(models.Model): class ChangedByMixin(models.Model):
changed_by = models.ForeignKey(User, null=True, blank=True) changed_by = models.ForeignKey(User, null=True, blank=True)
...@@ -430,6 +430,11 @@ class CourseRun(TimeStampedModel, ChangedByMixin): ...@@ -430,6 +430,11 @@ class CourseRun(TimeStampedModel, ChangedByMixin):
seats = self.seats.filter(type__in=[Seat.AUDIT, Seat.VERIFIED, Seat.PROFESSIONAL, Seat.CREDIT]) seats = self.seats.filter(type__in=[Seat.AUDIT, Seat.VERIFIED, Seat.PROFESSIONAL, Seat.CREDIT])
return all([seat.is_valid_seat for seat in seats]) if seats else False return all([seat.is_valid_seat for seat in seats]) if seats else False
@property
def paid_seats(self):
""" Return course run paid seats """
return self.seats.filter(type__in=Seat.PAID_SEATS)
def get_absolute_url(self): def get_absolute_url(self):
return reverse('publisher:publisher_course_run_detail', kwargs={'pk': self.id}) return reverse('publisher:publisher_course_run_detail', kwargs={'pk': self.id})
...@@ -441,6 +446,8 @@ class Seat(TimeStampedModel, ChangedByMixin): ...@@ -441,6 +446,8 @@ class Seat(TimeStampedModel, ChangedByMixin):
PROFESSIONAL = 'professional' PROFESSIONAL = 'professional'
NO_ID_PROFESSIONAL = 'no-id-professional' NO_ID_PROFESSIONAL = 'no-id-professional'
CREDIT = 'credit' CREDIT = 'credit'
PAID_SEATS = [VERIFIED, PROFESSIONAL, CREDIT]
PAID_AND_AUDIT_APPLICABLE_SEATS = [CREDIT, VERIFIED]
SEAT_TYPE_CHOICES = ( SEAT_TYPE_CHOICES = (
(HONOR, _('Honor')), (HONOR, _('Honor')),
......
...@@ -34,8 +34,8 @@ from course_discovery.apps.publisher.choices import ( ...@@ -34,8 +34,8 @@ from course_discovery.apps.publisher.choices import (
CourseRunStateChoices, CourseStateChoices, InternalUserRole, PublisherUserRole CourseRunStateChoices, CourseStateChoices, InternalUserRole, PublisherUserRole
) )
from course_discovery.apps.publisher.constants import ( from course_discovery.apps.publisher.constants import (
ADMIN_GROUP_NAME, INTERNAL_USER_GROUP_NAME, PROJECT_COORDINATOR_GROUP_NAME, PUBLISHER_ENTITLEMENTS_WAFFLE_SWITCH, ADMIN_GROUP_NAME, INTERNAL_USER_GROUP_NAME, PROJECT_COORDINATOR_GROUP_NAME,
REVIEWER_GROUP_NAME PUBLISHER_CREATE_AUDIT_SEATS_FOR_VERIFIED_COURSE_RUNS, PUBLISHER_ENTITLEMENTS_WAFFLE_SWITCH, REVIEWER_GROUP_NAME
) )
from course_discovery.apps.publisher.models import ( from course_discovery.apps.publisher.models import (
Course, CourseEntitlement, CourseRun, CourseRunState, CourseState, OrganizationExtension, Seat Course, CourseEntitlement, CourseRun, CourseRunState, CourseState, OrganizationExtension, Seat
...@@ -554,25 +554,36 @@ class CreateCourseRunViewTests(SiteMixin, TestCase): ...@@ -554,25 +554,36 @@ class CreateCourseRunViewTests(SiteMixin, TestCase):
def test_existing_run_and_seat_data_auto_populated(self): def test_existing_run_and_seat_data_auto_populated(self):
""" """
Verify that existing course run and seat data auto populated on new course run form. Verify that existing course run and seat data auto populated on new course run form.
Create a course run with a verified seat (for a verified and credit seat, audit seat
is automatically created), then try to create a new run of the same course and verify
the previous course run's seats and pacing is automatically populated.
""" """
verified_seat_price = 550.0
latest_run = self.course.course_runs.latest('created') latest_run = self.course.course_runs.latest('created')
factories.SeatFactory(course_run=latest_run, type=Seat.VERIFIED, price=550.0) factories.SeatFactory(course_run=latest_run, type=Seat.VERIFIED, price=verified_seat_price)
latest_seat = latest_run.seats.latest('created') factories.SeatFactory(course_run=latest_run, type=Seat.AUDIT)
# Verified seat should be preselected
verified_seat = latest_run.seats.get(type=Seat.VERIFIED)
response = self.client.get(self.create_course_run_url_new) response = self.client.get(self.create_course_run_url_new)
response_content = BeautifulSoup(response.content) response_content = BeautifulSoup(response.content)
pacing_type_attribute = response_content.find( pacing_type_attribute = response_content.find(
"input", {"value": latest_run.pacing_type, "type": "radio", "name": "pacing_type"} "input", {"value": latest_run.pacing_type, "type": "radio", "name": "pacing_type"}
) )
seat_type_attribute = response_content.find("option", {"value": latest_seat.type}) seat_type_attribute = response_content.find("option", {"value": verified_seat.type})
price_attribute = response_content.find( price_attribute = response_content.find(
"input", {"value": latest_seat.price, "id": "id_price", "step": "0.01", "type": "number"} "input", {"value": verified_seat.price, "id": "id_price", "step": "0.01", "type": "number"}
) )
# Verify that existing course run and seat values auto populated on form. # Verify that existing course run and seat values auto populated on form.
assert pacing_type_attribute is not None self.assertIsNotNone(pacing_type_attribute)
assert seat_type_attribute is not None self.assertIn('checked=""', str(pacing_type_attribute))
assert price_attribute is not None self.assertIsNotNone(seat_type_attribute)
self.assertIn('selected=""', str(seat_type_attribute))
self.assertIsNotNone(price_attribute)
self.assertIn(str(verified_seat_price), str(price_attribute))
def test_credit_type_without_price(self): def test_credit_type_without_price(self):
""" Verify that without credit price course-run cannot be created with credit seat type. """ """ Verify that without credit price course-run cannot be created with credit seat type. """
...@@ -664,7 +675,7 @@ class CreateCourseRunViewTests(SiteMixin, TestCase): ...@@ -664,7 +675,7 @@ class CreateCourseRunViewTests(SiteMixin, TestCase):
assign_perm( assign_perm(
OrganizationExtension.VIEW_COURSE_RUN, self.organization_extension.group, self.organization_extension OrganizationExtension.VIEW_COURSE_RUN, self.organization_extension.group, self.organization_extension
) )
toggle_switch('publisher_create_audit_seats_for_verified_course_runs', True) toggle_switch(PUBLISHER_CREATE_AUDIT_SEATS_FOR_VERIFIED_COURSE_RUNS, True)
self.course.entitlements.create(mode=entitlement_mode, price=entitlement_price) self.course.entitlements.create(mode=entitlement_mode, price=entitlement_price)
post_data = {'start': '2018-02-01 00:00:00', 'end': '2018-02-28 00:00:00', 'pacing_type': 'instructor_paced'} post_data = {'start': '2018-02-01 00:00:00', 'end': '2018-02-28 00:00:00', 'pacing_type': 'instructor_paced'}
...@@ -3072,7 +3083,7 @@ class CourseRunEditViewTests(SiteMixin, TestCase): ...@@ -3072,7 +3083,7 @@ class CourseRunEditViewTests(SiteMixin, TestCase):
assign_perm(OrganizationExtension.EDIT_COURSE_RUN, self.group, self.organization_extension) assign_perm(OrganizationExtension.EDIT_COURSE_RUN, self.group, self.organization_extension)
assign_perm(OrganizationExtension.VIEW_COURSE_RUN, self.group, self.organization_extension) assign_perm(OrganizationExtension.VIEW_COURSE_RUN, self.group, self.organization_extension)
# assert edit page is loading sucesfully. # assert edit page is loading successfully.
self.edit_page_url = reverse('publisher:publisher_course_runs_edit', kwargs={'pk': self.new_course_run.id}) self.edit_page_url = reverse('publisher:publisher_course_runs_edit', kwargs={'pk': self.new_course_run.id})
response = self.client.get(self.edit_page_url) response = self.client.get(self.edit_page_url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
...@@ -3105,6 +3116,19 @@ class CourseRunEditViewTests(SiteMixin, TestCase): ...@@ -3105,6 +3116,19 @@ class CourseRunEditViewTests(SiteMixin, TestCase):
response = self.client.get(url) response = self.client.get(url)
self.assertContains(response, 'CERTIFICATE TYPE AND PRICE', status_code=200) self.assertContains(response, 'CERTIFICATE TYPE AND PRICE', status_code=200)
def login_with_course_user_role(self, course_run, role=PublisherUserRole.CourseTeam):
self.client.logout()
user = course_run.course.course_user_roles.get(role=role).user
self.client.login(username=user.username, password=USER_PASSWORD)
return user
def assert_seats(self, course_run, expected_seat_count, expected_seats):
"""Helper method to assert expected course run seats"""
course_run_seats = Seat.objects.filter(course_run=course_run).order_by('type')
self.assertEqual(course_run_seats.count(), expected_seat_count)
seat_types = [seat.type for seat in course_run_seats]
self.assertEqual(seat_types, expected_seats)
def test_edit_page_with_two_seats(self): def test_edit_page_with_two_seats(self):
""" """
Verify that if a course run has both audit and verified seats, Verified seat is displayed Verify that if a course run has both audit and verified seats, Verified seat is displayed
...@@ -3220,16 +3244,12 @@ class CourseRunEditViewTests(SiteMixin, TestCase): ...@@ -3220,16 +3244,12 @@ class CourseRunEditViewTests(SiteMixin, TestCase):
def test_update_course_run_with_seat(self): def test_update_course_run_with_seat(self):
""" Verify that course run edit page create seat object also if not exists previously.""" """ Verify that course run edit page create seat object also if not exists previously."""
user = self.login_with_course_user_role(self.new_course_run)
self.client.logout()
user = self.new_course_run.course.course_user_roles.get(role=PublisherUserRole.CourseTeam).user
self.client.login(username=user.username, password=USER_PASSWORD)
self.assertNotEqual(self.course_run.changed_by, user) self.assertNotEqual(self.course_run.changed_by, user)
# post data without seat # post data without seat
data = {'image': ''} data = {'image': ''}
updated_dict = self._post_data(data, self.new_course, self.new_course_run) updated_dict = self._post_data(data, self.new_course, self.new_course_run)
updated_dict['type'] = Seat.PROFESSIONAL updated_dict['type'] = Seat.PROFESSIONAL
updated_dict['price'] = 10.00 updated_dict['price'] = 10.00
...@@ -3242,12 +3262,52 @@ class CourseRunEditViewTests(SiteMixin, TestCase): ...@@ -3242,12 +3262,52 @@ class CourseRunEditViewTests(SiteMixin, TestCase):
target_status_code=200 target_status_code=200
) )
course_run = CourseRun.objects.get(id=self.new_course_run.id) self.assert_seats(self.new_course_run, 1, [Seat.PROFESSIONAL])
self.assertEqual(self.new_course_run.seats.first().price, 10)
self.assertEqual(self.new_course_run.seats.first().history.all().count(), 1)
def test_update_course_run_create_duplicate_seats(self):
"""
Tests that course run seats are not duplicated when editing.
Course run seats should remain consistent when updating seats.
"""
self.login_with_course_user_role(self.new_course_run)
data = {'image': '', 'type': Seat.VERIFIED, 'price': 10.00}
toggle_switch(PUBLISHER_CREATE_AUDIT_SEATS_FOR_VERIFIED_COURSE_RUNS, True)
post_data = self._post_data(data, self.new_course, self.new_course_run)
self.client.post(self.edit_page_url, post_data)
self.assert_seats(self.new_course_run, 2, [Seat.AUDIT, Seat.VERIFIED])
post_data['price'] = 20.00
self.client.post(self.edit_page_url, post_data)
self.assert_seats(self.new_course_run, 2, [Seat.AUDIT, Seat.VERIFIED])
self.assertEqual(self.new_course_run.paid_seats.first().price, 20.00)
@ddt.data(Seat.VERIFIED, Seat.CREDIT)
def test_cleanup_course_run_seats_bogus_data(self, seat_type):
"""
Test that bogus course run seat data is corrected upon saving the
course run.
Some data in publisher has duplicate course seats, this tests that we are able
to correct the data upon course run save.
"""
# Login and verify the course run has no seats.
self.login_with_course_user_role(self.new_course_run)
self.assert_seats(self.new_course_run, 0, [])
self.assertEqual(course_run.seats.first().type, Seat.PROFESSIONAL) # create some bogus seats for the course run & verify the seats exists
self.assertEqual(course_run.seats.first().price, 10) __ = [self.new_course_run.seats.create(type=seat_type) for _ in range(10)]
self.assert_seats(self.new_course_run, 10, [seat_type] * 10)
self.assertEqual(course_run.seats.first().history.all().count(), 1) # Make course run save post request and verify the correct course seats.
toggle_switch(PUBLISHER_CREATE_AUDIT_SEATS_FOR_VERIFIED_COURSE_RUNS, True)
data = {'image': '', 'type': Seat.VERIFIED, 'price': 100.00}
post_data = self._post_data(data, self.new_course, self.new_course_run)
self.client.post(self.edit_page_url, post_data)
self.assert_seats(self.new_course_run, 2, [Seat.AUDIT, Seat.VERIFIED])
self.assertEqual(self.new_course_run.paid_seats.first().price, 100.00)
def test_update_course_run_for_course_that_uses_entitlements(self): def test_update_course_run_for_course_that_uses_entitlements(self):
""" Verify that a user cannot change Seat data when editing courseruns for courses that use entitlements. """ """ Verify that a user cannot change Seat data when editing courseruns for courses that use entitlements. """
...@@ -3840,7 +3900,7 @@ class CreateRunFromDashboardViewTests(SiteMixin, TestCase): ...@@ -3840,7 +3900,7 @@ class CreateRunFromDashboardViewTests(SiteMixin, TestCase):
assign_perm( assign_perm(
OrganizationExtension.VIEW_COURSE_RUN, self.organization_extension.group, self.organization_extension OrganizationExtension.VIEW_COURSE_RUN, self.organization_extension.group, self.organization_extension
) )
toggle_switch('publisher_create_audit_seats_for_verified_course_runs', True) toggle_switch(PUBLISHER_CREATE_AUDIT_SEATS_FOR_VERIFIED_COURSE_RUNS, True)
self.course.entitlements.create(mode=entitlement_mode, price=entitlement_price) self.course.entitlements.create(mode=entitlement_mode, price=entitlement_price)
post_data = { post_data = {
......
...@@ -30,13 +30,17 @@ from course_discovery.apps.publisher.choices import CourseRunStateChoices, Cours ...@@ -30,13 +30,17 @@ from course_discovery.apps.publisher.choices import CourseRunStateChoices, Cours
from course_discovery.apps.publisher.constants import PUBLISHER_ENTITLEMENTS_WAFFLE_SWITCH from course_discovery.apps.publisher.constants import PUBLISHER_ENTITLEMENTS_WAFFLE_SWITCH
from course_discovery.apps.publisher.dataloader.create_courses import process_course from course_discovery.apps.publisher.dataloader.create_courses import process_course
from course_discovery.apps.publisher.emails import send_email_for_published_course_run_editing from course_discovery.apps.publisher.emails import send_email_for_published_course_run_editing
from course_discovery.apps.publisher.forms import (AdminImportCourseForm, CourseEntitlementForm, CourseForm, from course_discovery.apps.publisher.forms import (
CourseRunForm, CourseSearchForm, SeatForm) AdminImportCourseForm, CourseEntitlementForm, CourseForm, CourseRunForm, CourseSearchForm, SeatForm
from course_discovery.apps.publisher.models import (PAID_SEATS, Course, CourseEntitlement, CourseRun, CourseRunState, )
CourseState, CourseUserRole, OrganizationExtension, PublisherUser, from course_discovery.apps.publisher.models import (
Seat, UserAttributes) Course, CourseEntitlement, CourseRun, CourseRunState, CourseState, CourseUserRole, OrganizationExtension,
from course_discovery.apps.publisher.utils import (get_internal_users, has_role_for_course, is_internal_user, PublisherUser, Seat, UserAttributes
is_project_coordinator_user, is_publisher_admin, make_bread_crumbs) )
from course_discovery.apps.publisher.utils import (
get_internal_users, has_role_for_course, is_internal_user, is_project_coordinator_user, is_publisher_admin,
make_bread_crumbs
)
from course_discovery.apps.publisher.wrappers import CourseRunWrapper from course_discovery.apps.publisher.wrappers import CourseRunWrapper
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -582,15 +586,23 @@ class CreateCourseRunView(mixins.LoginRequiredMixin, mixins.PublisherUserRequire ...@@ -582,15 +586,23 @@ class CreateCourseRunView(mixins.LoginRequiredMixin, mixins.PublisherUserRequire
new_run.save() new_run.save()
def _initialize_seat_form(self, last_run=None): def _initialize_seat_form(self, last_run):
initial_seat_data = {} initial_seat_data = {}
if last_run: if not last_run:
try: return self.seat_form(initial=initial_seat_data)
latest_seat = last_run.seats.latest('created')
initial_seat_data = model_to_dict(latest_seat) def _get_latest_seat():
del initial_seat_data['id'], initial_seat_data['course_run'], initial_seat_data['changed_by'] """Returns latest course run seat. Paid seats are Preferred"""
except Seat.DoesNotExist: if last_run.paid_seats:
pass return last_run.paid_seats.latest()
return last_run.seats.latest()
try:
latest_seat = _get_latest_seat()
initial_seat_data = model_to_dict(latest_seat)
del initial_seat_data['id'], initial_seat_data['course_run'], initial_seat_data['changed_by']
except Seat.DoesNotExist:
pass
return self.seat_form(initial=initial_seat_data) return self.seat_form(initial=initial_seat_data)
...@@ -787,6 +799,11 @@ class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMix ...@@ -787,6 +799,11 @@ class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMix
'organizations': mixins.get_user_organizations(user) 'organizations': mixins.get_user_organizations(user)
} }
def get_latest_course_run_seat(self, course_run):
if course_run.paid_seats:
return course_run.paid_seats.first()
return course_run.seats.first()
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
context = self.get_context_data() context = self.get_context_data()
course_run = context.get('course_run') course_run = context.get('course_run')
...@@ -804,11 +821,8 @@ class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMix ...@@ -804,11 +821,8 @@ class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMix
) )
if not course.uses_entitlements: if not course.uses_entitlements:
course_run_paid_seat = course_run.seats.filter(type__in=PAID_SEATS).first() course_run_seat = self.get_latest_course_run_seat(course_run)
if course_run_paid_seat: context['seat_form'] = self.seat_form(instance=course_run_seat)
context['seat_form'] = self.seat_form(instance=course_run_paid_seat)
else:
context['seat_form'] = self.seat_form(instance=course_run.seats.first())
start_date = course_run.start.strftime("%B %d, %Y") if course_run.start else None start_date = course_run.start.strftime("%B %d, %Y") if course_run.start else None
context['breadcrumbs'] = make_bread_crumbs( context['breadcrumbs'] = make_bread_crumbs(
...@@ -841,16 +855,14 @@ class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMix ...@@ -841,16 +855,14 @@ class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMix
form_data_is_valid = form_data_is_valid and not seat_data_in_form form_data_is_valid = form_data_is_valid and not seat_data_in_form
seat_form = None seat_form = None
else: else:
seat_form = self.seat_form(request.POST, instance=course_run.seats.first()) seat_form = self.seat_form(request.POST, instance=self.get_latest_course_run_seat(course_run))
form_data_is_valid = form_data_is_valid and seat_form.is_valid() form_data_is_valid = form_data_is_valid and seat_form.is_valid()
context['seat_form'] = seat_form context['seat_form'] = seat_form
if form_data_is_valid: if form_data_is_valid:
try: try:
with transaction.atomic(): with transaction.atomic():
course_run = run_form.save(changed_by=user) course_run = run_form.save(changed_by=user)
run_form.save_m2m() run_form.save_m2m()
# If price-type comes with request then save the seat object. # If price-type comes with request then save the seat object.
......
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