Commit da2db893 by Vedran Karacic Committed by Vedran Karačić

Change product class name strings with constants

parent 0d860ceb
......@@ -10,6 +10,9 @@ COURSE_ID_PATTERN = r'(?P<course_id>{})'.format(COURSE_ID_REGEX)
# Seat constants
SEAT_PRODUCT_CLASS_NAME = 'Seat'
# Coupon constant
COUPON_PRODUCT_CLASS_NAME = 'Coupon'
# Enrollment Code constants
ENROLLMENT_CODE_PRODUCT_CLASS_NAME = 'Enrollment Code'
ENROLLMENT_CODE_SWITCH = 'create_enrollment_codes'
......
......@@ -5,8 +5,10 @@ import httpretty
from django.conf import settings
from django.core.cache import cache
from django.test import RequestFactory
from oscar.core.utils import slugify
from oscar.test import factories
from ecommerce.core.constants import COUPON_PRODUCT_CLASS_NAME
from ecommerce.core.models import BusinessClient
from ecommerce.extensions.catalogue.utils import create_coupon_product
from ecommerce.extensions.api.v2.views.coupons import CouponViewSet
......@@ -187,8 +189,10 @@ class CouponMixin(object):
@property
def coupon_product_class(self):
defaults = {'requires_shipping': False, 'track_stock': False, 'name': 'Coupon'}
pc, created = ProductClass.objects.get_or_create(name='Coupon', slug='coupon', defaults=defaults)
defaults = {'requires_shipping': False, 'track_stock': False, 'name': COUPON_PRODUCT_CLASS_NAME}
pc, created = ProductClass.objects.get_or_create(
name=COUPON_PRODUCT_CLASS_NAME, slug=slugify(COUPON_PRODUCT_CLASS_NAME), defaults=defaults
)
if created:
factories.ProductAttributeFactory(
......
......@@ -12,7 +12,8 @@ import waffle
from ecommerce.core.constants import (
ENROLLMENT_CODE_PRODUCT_CLASS_NAME,
ENROLLMENT_CODE_SEAT_TYPES,
ENROLLMENT_CODE_SWITCH
ENROLLMENT_CODE_SWITCH,
SEAT_PRODUCT_CLASS_NAME
)
from ecommerce.courses.publishers import LMSPublisher
from ecommerce.extensions.catalogue.utils import generate_sku
......@@ -45,7 +46,7 @@ class Course(models.Model):
parent, created = self.products.get_or_create(
course=self,
structure=Product.PARENT,
product_class=ProductClass.objects.get(slug='seat'),
product_class=ProductClass.objects.get(name=SEAT_PRODUCT_CLASS_NAME),
)
ProductCategory.objects.get_or_create(category=Category.objects.get(name='Seats'), product=parent)
parent.title = 'Seat in {}'.format(self.name)
......@@ -100,7 +101,7 @@ class Course(models.Model):
@property
def parent_seat_product(self):
""" Returns the course seat parent Product. """
return self.products.get(product_class__slug='seat', structure=Product.PARENT)
return self.products.get(product_class__name=SEAT_PRODUCT_CLASS_NAME, structure=Product.PARENT)
@property
def seat_products(self):
......
......@@ -16,6 +16,7 @@ from oscar.core.loading import get_model
from requests.exceptions import ConnectionError, Timeout
from slumber.exceptions import SlumberBaseException
from ecommerce.core.constants import COUPON_PRODUCT_CLASS_NAME
from ecommerce.coupons.views import voucher_is_valid
from ecommerce.courses.utils import get_course_catalogs
from ecommerce.enterprise.utils import is_enterprise_feature_enabled
......@@ -72,7 +73,9 @@ def get_course_vouchers_for_learner(site, user, course_id):
vouchers = []
for entitlement in entitlements:
try:
coupon_product = Product.objects.filter(product_class__name='Coupon').get(id=entitlement)
coupon_product = Product.objects.filter(
product_class__name=COUPON_PRODUCT_CLASS_NAME
).get(id=entitlement)
except Product.DoesNotExist:
logger.exception('There was an error getting coupon product with the entitlement id %s', entitlement)
return None
......
......@@ -14,7 +14,7 @@ from rest_framework import serializers
from rest_framework.reverse import reverse
import waffle
from ecommerce.core.constants import ISO_8601_FORMAT, COURSE_ID_REGEX
from ecommerce.core.constants import COURSE_ID_REGEX, ISO_8601_FORMAT, SEAT_PRODUCT_CLASS_NAME
from ecommerce.core.models import Site, SiteConfiguration
from ecommerce.core.url_utils import get_ecommerce_url
from ecommerce.courses.models import Course
......@@ -329,7 +329,7 @@ class AtomicPublicationSerializer(serializers.Serializer): # pylint: disable=ab
for product in products:
# Verify that each product is intended to be a Seat.
product_class = product.get('product_class')
if product_class != 'Seat':
if product_class != SEAT_PRODUCT_CLASS_NAME:
raise serializers.ValidationError(
_(u"Invalid product class [{product_class}] requested.".format(product_class=product_class))
)
......
......@@ -9,7 +9,7 @@ from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse
from oscar.core.loading import get_model, get_class
from ecommerce.core.constants import ISO_8601_FORMAT
from ecommerce.core.constants import ISO_8601_FORMAT, SEAT_PRODUCT_CLASS_NAME
from ecommerce.core.tests import toggle_switch
from ecommerce.courses.models import Course
from ecommerce.courses.publishers import LMSPublisher
......@@ -125,7 +125,7 @@ class CourseViewSetTests(ProductSerializerMixin, CourseCatalogTestMixin, TestCas
self.assertEqual(course.products.count(), 1)
# Validate the parent seat
seat_product_class = ProductClass.objects.get(slug='seat')
seat_product_class = ProductClass.objects.get(name=SEAT_PRODUCT_CLASS_NAME)
parent = course.parent_seat_product
self.assertEqual(parent.structure, Product.PARENT)
self.assertEqual(parent.title, 'Seat in Test Course')
......
......@@ -8,6 +8,7 @@ from django.core.urlresolvers import reverse
from django.test import RequestFactory
from oscar.core.loading import get_model
from ecommerce.core.constants import COUPON_PRODUCT_CLASS_NAME
from ecommerce.coupons.tests.mixins import CouponMixin
from ecommerce.courses.models import Course
from ecommerce.extensions.api.serializers import ProductSerializer
......@@ -171,4 +172,4 @@ class ProductViewSetCouponTests(CouponMixin, ProductViewSetBase):
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.content)
self.assertEqual(response_data['count'], 1)
self.assertEqual(response_data['results'][0]['product_class'], 'Coupon')
self.assertEqual(response_data['results'][0]['product_class'], COUPON_PRODUCT_CLASS_NAME)
......@@ -7,7 +7,7 @@ from django.core.urlresolvers import reverse
import mock
import pytz
from ecommerce.core.constants import ISO_8601_FORMAT
from ecommerce.core.constants import ISO_8601_FORMAT, SEAT_PRODUCT_CLASS_NAME
from ecommerce.core.tests import toggle_switch
from ecommerce.courses.models import Course
from ecommerce.courses.publishers import LMSPublisher
......@@ -33,7 +33,7 @@ class AtomicPublicationTests(CourseCatalogTestMixin, TestCase):
'verification_deadline': EXPIRES_STRING,
'products': [
{
'product_class': 'Seat',
'product_class': SEAT_PRODUCT_CLASS_NAME,
'expires': None,
'price': 0.00,
'attribute_values': [
......@@ -52,7 +52,7 @@ class AtomicPublicationTests(CourseCatalogTestMixin, TestCase):
}
},
{
'product_class': 'Seat',
'product_class': SEAT_PRODUCT_CLASS_NAME,
'expires': None,
'price': 0.00,
'attribute_values': [
......@@ -75,7 +75,7 @@ class AtomicPublicationTests(CourseCatalogTestMixin, TestCase):
}
},
{
'product_class': 'Seat',
'product_class': SEAT_PRODUCT_CLASS_NAME,
'expires': EXPIRES_STRING,
'price': 10.00,
'attribute_values': [
......@@ -98,7 +98,7 @@ class AtomicPublicationTests(CourseCatalogTestMixin, TestCase):
}
},
{
'product_class': 'Seat',
'product_class': SEAT_PRODUCT_CLASS_NAME,
'expires': EXPIRES_STRING,
'price': 100.00,
'attribute_values': [
......
......@@ -12,6 +12,7 @@ from rest_framework import filters, generics, serializers, status, viewsets
from rest_framework.permissions import IsAdminUser, IsAuthenticated
from rest_framework.response import Response
from ecommerce.core.constants import COUPON_PRODUCT_CLASS_NAME
from ecommerce.core.models import BusinessClient
from ecommerce.core.utils import log_message_and_raise_validation_error
from ecommerce.coupons.utils import prepare_course_seat_types
......@@ -42,7 +43,7 @@ Voucher = get_model('voucher', 'Voucher')
class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
""" Coupon resource. """
queryset = Product.objects.filter(product_class__name='Coupon')
queryset = Product.objects.filter(product_class__name=COUPON_PRODUCT_CLASS_NAME)
permission_classes = (IsAuthenticated, IsAdminUser)
filter_backends = (filters.DjangoFilterBackend,)
filter_class = ProductFilter
......
......@@ -8,7 +8,6 @@ from django.utils.translation import ugettext_lazy as _
from oscar.core.loading import get_class, get_model
import pytz
from ecommerce.core.constants import ENROLLMENT_CODE_PRODUCT_CLASS_NAME, SEAT_PRODUCT_CLASS_NAME
from ecommerce.referrals.models import Referral
Applicator = get_class('offer.utils', 'Applicator')
......@@ -38,7 +37,7 @@ def prepare_basket(request, product, voucher=None):
basket = Basket.get_basket(request.user, request.site)
basket.flush()
basket.add_product(product, 1)
if product.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME:
if product.is_enrollment_code_product:
basket.clear_vouchers()
elif voucher:
basket.clear_vouchers()
......@@ -56,14 +55,13 @@ def prepare_basket(request, product, voucher=None):
def get_basket_switch_data(product):
product_class_name = product.get_product_class().name
structure = product.structure
switch_link_text = None
if product_class_name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME:
if product.is_enrollment_code_product:
switch_link_text = _('Click here to just purchase an enrollment for yourself')
structure = 'child'
elif product_class_name == SEAT_PRODUCT_CLASS_NAME:
elif product.is_seat_product:
switch_link_text = _('Click here to purchase multiple seats in this course')
structure = 'standalone'
......
......@@ -13,7 +13,6 @@ from oscar.apps.basket.views import VoucherAddView as BaseVoucherAddView, Vouche
from requests.exceptions import ConnectionError, Timeout
from slumber.exceptions import SlumberBaseException
from ecommerce.core.constants import ENROLLMENT_CODE_PRODUCT_CLASS_NAME, SEAT_PRODUCT_CLASS_NAME
from ecommerce.core.exceptions import SiteConfigurationError
from ecommerce.core.url_utils import get_lms_url
from ecommerce.courses.utils import get_certificate_type_display_value, get_course_info_from_catalog, mode_for_seat
......@@ -65,7 +64,7 @@ class BasketSingleItemView(View):
# If the product is not an Enrollment Code, we check to see if the user is already
# enrolled to prevent double-enrollment and/or accidental coupon usage
if product.get_product_class().name != ENROLLMENT_CODE_PRODUCT_CLASS_NAME:
if not product.is_enrollment_code_product:
try:
if request.user.is_user_already_enrolled(request, product):
logger.warning(
......@@ -96,9 +95,9 @@ class BasketSummaryView(BasketView):
Return the seat type based on the product class
"""
seat_type = None
if product.get_product_class().name == SEAT_PRODUCT_CLASS_NAME:
if product.is_seat_product:
seat_type = get_certificate_type_display_value(product.attr.certificate_type)
elif product.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME:
elif product.is_enrollment_code_product:
seat_type = get_certificate_type_display_value(product.attr.seat_type)
return seat_type
......@@ -174,8 +173,7 @@ class BasketSummaryView(BasketView):
switch_link_text = partner_sku = order_details_msg = None
for line in lines:
product_class_name = line.product.get_product_class().name
if product_class_name == 'Seat':
if line.product.is_seat_product:
line_data = self._get_course_data(line.product)
certificate_type = line.product.attr.certificate_type
......@@ -193,7 +191,7 @@ class BasketSummaryView(BasketView):
order_details_msg = _(
'You will be automatically enrolled in the course upon completing your order.'
)
elif product_class_name == 'Enrollment Code':
elif line.product.is_enrollment_code_product:
line_data = self._get_course_data(line.product)
show_voucher_form = False
order_details_msg = _(
......@@ -219,7 +217,7 @@ class BasketSummaryView(BasketView):
line_data.update({
'benefit_value': benefit_value,
'enrollment_code': line.product.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME,
'enrollment_code': line.product.is_enrollment_code_product,
'line': line,
'seat_type': self._determine_seat_type(line.product),
})
......
......@@ -2,6 +2,9 @@
from __future__ import unicode_literals
from django.db import models, migrations
from oscar.core.utils import slugify
from ecommerce.core.constants import SEAT_PRODUCT_CLASS_NAME
def create_catalog(apps, schema_editor):
......@@ -20,8 +23,8 @@ def create_catalog(apps, schema_editor):
seat = ProductClass.objects.create(
track_stock=False,
requires_shipping=False,
name='Seat',
slug='seat'
name=SEAT_PRODUCT_CLASS_NAME,
slug=slugify(SEAT_PRODUCT_CLASS_NAME)
)
# Create product attributes for course seat products
......@@ -66,7 +69,7 @@ def remove_catalog(apps, schema_editor):
ProductClass = apps.get_model("catalogue", "ProductClass")
Category.objects.filter(slug='seats').delete()
ProductClass.objects.filter(slug='seat').delete()
ProductClass.objects.filter(name=SEAT_PRODUCT_CLASS_NAME).delete()
class Migration(migrations.Migration):
......
......@@ -3,12 +3,14 @@ from __future__ import unicode_literals
from django.db import models, migrations
from ecommerce.core.constants import SEAT_PRODUCT_CLASS_NAME
def create_credit_provider_attribute(apps, schema_editor):
# Get seat Object
ProductClass = apps.get_model('catalogue', 'ProductClass')
seat = ProductClass.objects.get(name='Seat')
seat = ProductClass.objects.get(name=SEAT_PRODUCT_CLASS_NAME)
# Create our Product Attributes
ProductAttribute = apps.get_model('catalogue', 'ProductAttribute')
......@@ -23,11 +25,6 @@ def create_credit_provider_attribute(apps, schema_editor):
def delete_credit_provider_attribute(apps, schema_editor):
"""For backward compatibility"""
# Get seat Object
ProductClass = apps.get_model('catalogue', 'ProductClass')
seat = ProductClass.objects.get(name='Seat')
# Delete our Product Attributes
ProductAttribute = apps.get_model('catalogue', 'ProductAttribute')
ProductAttribute.objects.filter(code='credit_provider').delete()
......
......@@ -3,12 +3,14 @@ from __future__ import unicode_literals
from django.db import models, migrations
from ecommerce.core.constants import SEAT_PRODUCT_CLASS_NAME
def create_credit_hours_attribute(apps, schema_editor):
# Get seat Object
ProductClass = apps.get_model('catalogue', 'ProductClass')
seat = ProductClass.objects.get(name='Seat')
seat = ProductClass.objects.get(name=SEAT_PRODUCT_CLASS_NAME)
# Create our Product Attributes
ProductAttribute = apps.get_model('catalogue', 'ProductAttribute')
......
......@@ -3,6 +3,9 @@ from __future__ import unicode_literals
from django.db import migrations
from oscar.core.loading import get_model
from oscar.core.utils import slugify
from ecommerce.core.constants import COUPON_PRODUCT_CLASS_NAME
Category = get_model("catalogue", "Category")
ProductAttribute = get_model("catalogue", "ProductAttribute")
......@@ -15,8 +18,8 @@ def create_product_class(apps, schema_editor):
coupon = ProductClass.objects.create(
track_stock=False,
requires_shipping=False,
name='Coupon',
slug='coupon',
name=COUPON_PRODUCT_CLASS_NAME,
slug=slugify(COUPON_PRODUCT_CLASS_NAME),
)
ProductAttribute.objects.create(
......@@ -40,7 +43,7 @@ def create_product_class(apps, schema_editor):
def remove_product_class(apps, schema_editor):
""" Reverse function. """
Category.objects.filter(slug='coupon').delete()
ProductClass.objects.filter(slug='coupon').delete()
ProductClass.objects.filter(name=COUPON_PRODUCT_CLASS_NAME).delete()
def remove_enrollment_code(apps, schema_editor):
......
......@@ -4,13 +4,16 @@ from __future__ import unicode_literals
from django.db import migrations
from oscar.core.loading import get_model
from ecommerce.core.constants import COUPON_PRODUCT_CLASS_NAME
ProductAttribute = get_model("catalogue", "ProductAttribute")
ProductClass = get_model("catalogue", "ProductClass")
def create_note_attribute(apps, schema_editor):
"""Create coupon note attribute."""
coupon = ProductClass.objects.get(name='Coupon')
coupon = ProductClass.objects.get(name=COUPON_PRODUCT_CLASS_NAME)
ProductAttribute.objects.create(
product_class=coupon,
name='Note',
......@@ -22,7 +25,7 @@ def create_note_attribute(apps, schema_editor):
def remove_note_attribute(apps, schema_editor):
"""Remove coupon note attribute."""
coupon = ProductClass.objects.get(name='Coupon')
coupon = ProductClass.objects.get(name=COUPON_PRODUCT_CLASS_NAME)
ProductAttribute.objects.get(product_class=coupon, name='Note').delete()
......
......@@ -3,6 +3,7 @@ from __future__ import unicode_literals
from django.db import migrations
from oscar.core.loading import get_model
from oscar.core.utils import slugify
from ecommerce.core.constants import ENROLLMENT_CODE_PRODUCT_CLASS_NAME
......@@ -18,7 +19,7 @@ def create_enrollment_code_product_class(apps, schema_editor):
track_stock=False,
requires_shipping=False,
name=ENROLLMENT_CODE_PRODUCT_CLASS_NAME,
slug='enrollment_code',
slug=slugify(ENROLLMENT_CODE_PRODUCT_CLASS_NAME),
)
ProductAttribute.objects.create(
......
......@@ -4,6 +4,10 @@ from django.utils.translation import ugettext_lazy as _
from oscar.apps.catalogue.abstract_models import AbstractProduct, AbstractProductAttributeValue
from simple_history.models import HistoricalRecords
from ecommerce.core.constants import (
COUPON_PRODUCT_CLASS_NAME, ENROLLMENT_CODE_PRODUCT_CLASS_NAME, SEAT_PRODUCT_CLASS_NAME
)
class Product(AbstractProduct):
course = models.ForeignKey(
......@@ -13,6 +17,18 @@ class Product(AbstractProduct):
help_text=_('Last date/time on which this product can be purchased.'))
history = HistoricalRecords()
@property
def is_seat_product(self):
return self.get_product_class().name == SEAT_PRODUCT_CLASS_NAME
@property
def is_enrollment_code_product(self):
return self.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME
@property
def is_coupon_product(self):
return self.get_product_class().name == COUPON_PRODUCT_CLASS_NAME
class ProductAttributeValue(AbstractProductAttributeValue):
history = HistoricalRecords()
......@@ -32,4 +48,4 @@ class Catalog(models.Model):
# noinspection PyUnresolvedReferences
from oscar.apps.catalogue.models import * # noqa pylint: disable=wildcard-import,unused-wildcard-import,wrong-import-position,ungrouped-imports
from oscar.apps.catalogue.models import * # noqa pylint: disable=wildcard-import,unused-wildcard-import,wrong-import-position,ungrouped-imports,wrong-import-order
......@@ -3,9 +3,10 @@ from __future__ import unicode_literals
import logging
from oscar.core.loading import get_model
from oscar.core.utils import slugify
from oscar.test import factories
from ecommerce.core.constants import ENROLLMENT_CODE_PRODUCT_CLASS_NAME
from ecommerce.core.constants import ENROLLMENT_CODE_PRODUCT_CLASS_NAME, SEAT_PRODUCT_CLASS_NAME
from ecommerce.courses.tests.factories import CourseFactory
from ecommerce.tests.factories import PartnerFactory
......@@ -94,7 +95,9 @@ class CourseCatalogTestMixin(object):
('id_verification_required', 'boolean'),
('credit_hours', 'integer'),
)
product_class = self._create_product_class('Seat', 'seat', attributes)
product_class = self._create_product_class(
SEAT_PRODUCT_CLASS_NAME, slugify(SEAT_PRODUCT_CLASS_NAME), attributes
)
return product_class
@property
......@@ -104,5 +107,7 @@ class CourseCatalogTestMixin(object):
('course_key', 'text'),
('id_verification_required', 'boolean')
)
product_class = self._create_product_class(ENROLLMENT_CODE_PRODUCT_CLASS_NAME, 'enrollment_code', attributes)
product_class = self._create_product_class(
ENROLLMENT_CODE_PRODUCT_CLASS_NAME, slugify(ENROLLMENT_CODE_PRODUCT_CLASS_NAME), attributes
)
return product_class
from oscar.core.loading import get_model
from oscar.test.factories import ProductFactory, VoucherFactory
from ecommerce.core.constants import COUPON_PRODUCT_CLASS_NAME
from ecommerce.extensions.voucher.models import CouponVouchers
from ecommerce.tests.testcases import TestCase
......@@ -13,7 +14,7 @@ class CouponProductTest(TestCase):
def test_coupon_product(self):
"""Test if a coupon product is properly created."""
coupon_product_class, _ = ProductClass.objects.get_or_create(name='coupon')
coupon_product_class, _ = ProductClass.objects.get_or_create(name=COUPON_PRODUCT_CLASS_NAME)
coupon_product = ProductFactory(
product_class=coupon_product_class,
title='Test product'
......
......@@ -7,7 +7,7 @@ from django.conf import settings
from django.db.utils import IntegrityError
from oscar.core.loading import get_model
from ecommerce.core.constants import ENROLLMENT_CODE_PRODUCT_CLASS_NAME, SEAT_PRODUCT_CLASS_NAME
from ecommerce.core.constants import COUPON_PRODUCT_CLASS_NAME
from ecommerce.extensions.voucher.models import CouponVouchers
from ecommerce.extensions.voucher.utils import create_vouchers
......@@ -71,7 +71,7 @@ def create_coupon_product(
IntegrityError: An error occured when create_vouchers method returns
an IntegrityError exception
"""
product_class = ProductClass.objects.get(slug='coupon')
product_class = ProductClass.objects.get(name=COUPON_PRODUCT_CLASS_NAME)
coupon_product = Product.objects.create(title=title, product_class=product_class)
ProductCategory.objects.get_or_create(product=coupon_product, category=category)
......@@ -126,23 +126,21 @@ def generate_sku(product, partner):
Example: 76E4E71
"""
product_class = product.get_product_class()
if not product_class:
if not product.get_product_class():
raise AttributeError('Product has no product class')
if product_class.name == 'Coupon':
if product.is_coupon_product:
_hash = ' '.join((
unicode(product.id),
str(partner.id)
))
elif product_class.name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME:
elif product.is_enrollment_code_product:
_hash = ' '.join((
getattr(product.attr, 'course_key', ''),
getattr(product.attr, 'seat_type', ''),
unicode(partner.id)
))
elif product_class.name == SEAT_PRODUCT_CLASS_NAME:
elif product.is_seat_product:
_hash = ' '.join((
getattr(product.attr, 'certificate_type', ''),
product.attr.course_key,
......
......@@ -71,7 +71,7 @@ def send_course_purchase_email(sender, order=None, **kwargs): # pylint: disable
'Failed to send credit receipt notification. Credit seat product [%s] has no provider.', product.id
)
return
elif product.get_product_class().name == 'Seat':
elif product.is_seat_product:
provider_data = get_credit_provider_details(
access_token=order.site.siteconfiguration.access_token,
credit_provider_id=credit_provider_id,
......
......@@ -15,7 +15,7 @@ from rest_framework import status
import requests
from requests.exceptions import ConnectionError, Timeout
from ecommerce.core.constants import ENROLLMENT_CODE_PRODUCT_CLASS_NAME, SEAT_PRODUCT_CLASS_NAME
from ecommerce.core.constants import ENROLLMENT_CODE_PRODUCT_CLASS_NAME
from ecommerce.core.url_utils import get_lms_enrollment_api_url
from ecommerce.courses.models import Course
from ecommerce.courses.utils import mode_for_seat
......@@ -126,7 +126,7 @@ class EnrollmentFulfillmentModule(BaseFulfillmentModule):
return requests.post(enrollment_api_url, data=json.dumps(data), headers=headers, timeout=timeout)
def supports_line(self, line):
return line.product.get_product_class().name == SEAT_PRODUCT_CLASS_NAME
return line.product.is_seat_product
def get_supported_lines(self, lines):
""" Return a list of lines that can be fulfilled through enrollment.
......@@ -329,7 +329,7 @@ class CouponFulfillmentModule(BaseFulfillmentModule):
True if the line contains product of product class Coupon.
False otherwise.
"""
return line.product.get_product_class().name == 'Coupon'
return line.product.is_coupon_product
def get_supported_lines(self, lines):
""" Return a list of lines containing products with Coupon product class
......@@ -385,7 +385,7 @@ class EnrollmentCodeFulfillmentModule(BaseFulfillmentModule):
True if the line contains an Enrollment code.
False otherwise.
"""
return line.product.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME
return line.product.is_enrollment_code_product
def get_supported_lines(self, lines):
""" Return a list of lines containing Enrollment code products that can be fulfilled.
......
......@@ -12,7 +12,9 @@ from oscar.test.newfactories import UserFactory, BasketFactory
from requests.exceptions import ConnectionError, Timeout
from testfixtures import LogCapture
from ecommerce.core.constants import ENROLLMENT_CODE_PRODUCT_CLASS_NAME, ENROLLMENT_CODE_SWITCH
from ecommerce.core.constants import (
COUPON_PRODUCT_CLASS_NAME, ENROLLMENT_CODE_PRODUCT_CLASS_NAME, ENROLLMENT_CODE_SWITCH, SEAT_PRODUCT_CLASS_NAME
)
from ecommerce.core.tests import toggle_switch
from ecommerce.core.url_utils import get_lms_enrollment_api_url
from ecommerce.coupons.tests.mixins import CouponMixin
......@@ -152,7 +154,7 @@ class EnrollmentFulfillmentModuleTests(CourseCatalogTestMixin, FulfillmentTestMi
def test_enrollment_module_fulfill_bad_attributes(self):
"""Test that use of the Fulfillment Module fails when the product does not have attributes."""
ProductAttribute.objects.get(product_class__name='Seat', code='course_key').delete()
ProductAttribute.objects.get(product_class__name=SEAT_PRODUCT_CLASS_NAME, code='course_key').delete()
EnrollmentFulfillmentModule().fulfill_product(self.order, list(self.order.lines.all()))
self.assertEqual(LINE.FULFILLMENT_CONFIGURATION_ERROR, self.order.lines.all()[0].status)
......@@ -374,7 +376,7 @@ class EnrollmentFulfillmentModuleTests(CourseCatalogTestMixin, FulfillmentTestMi
"""
catalog = Catalog.objects.create(partner=self.partner)
coupon_product_class, _ = ProductClass.objects.get_or_create(name='coupon')
coupon_product_class, _ = ProductClass.objects.get_or_create(name=COUPON_PRODUCT_CLASS_NAME)
coupon = factories.create_product(
product_class=coupon_product_class,
title='Test product'
......
......@@ -18,8 +18,7 @@ class Order(AbstractOrder):
@property
def contains_coupon(self):
""" Return a boolean if the order contains a Coupon. """
return any(line.product.get_product_class().name == 'Coupon' for line in
self.basket.all_lines())
return any(line.product.is_coupon_product for line in self.basket.all_lines())
class PaymentEvent(AbstractPaymentEvent):
......
import ddt
from oscar.test import factories
from ecommerce.core.constants import COUPON_PRODUCT_CLASS_NAME
from ecommerce.extensions.fulfillment.status import ORDER
from ecommerce.tests.testcases import TestCase
......@@ -31,8 +32,7 @@ class OrderTests(TestCase):
def test_contains_coupon(self):
self.assertFalse(self.order.contains_coupon)
product_class = u'Coupon'
product = factories.create_product(product_class=product_class)
product = factories.create_product(product_class=COUPON_PRODUCT_CLASS_NAME)
basket = factories.create_basket(empty=True)
factories.create_stockrecord(product, num_in_stock=1)
basket.add_product(product)
......
......@@ -3,6 +3,8 @@ from django.utils import timezone
from oscar.apps.partner import availability, strategy
from oscar.core.loading import get_model
from ecommerce.core.constants import SEAT_PRODUCT_CLASS_NAME
class CourseSeatAvailabilityPolicyMixin(strategy.StockRequired):
"""
......@@ -15,7 +17,7 @@ class CourseSeatAvailabilityPolicyMixin(strategy.StockRequired):
@property
def seat_class(self):
ProductClass = get_model('catalogue', 'ProductClass')
return ProductClass.objects.get(slug='seat')
return ProductClass.objects.get(name=SEAT_PRODUCT_CLASS_NAME)
def availability_policy(self, product, stockrecord):
""" A product is unavailable for non-admin users if the current date is
......
......@@ -5,7 +5,6 @@ from django.dispatch import receiver
from ecommerce_worker.sailthru.v1.tasks import update_course_enrollment
from oscar.core.loading import get_class, get_model
from ecommerce.core.constants import SEAT_PRODUCT_CLASS_NAME
from ecommerce.core.url_utils import get_lms_url
from ecommerce.courses.utils import mode_for_seat
from ecommerce.extensions.analytics.utils import silence_exceptions
......@@ -58,9 +57,7 @@ def process_checkout_complete(sender, order=None, user=None, request=None, # py
product = line.product
# ignore everything except course seats. no support for coupons as of yet
product_class_name = product.get_product_class().name
if product_class_name == SEAT_PRODUCT_CLASS_NAME:
if product.is_seat_product:
price = line.line_price_excl_tax
course_id = product.course_id
......@@ -90,11 +87,8 @@ def process_basket_addition(sender, product=None, user=None, request=None, baske
return
# ignore everything except course seats. no support for coupons as of yet
product_class_name = product.get_product_class().name
if product_class_name == SEAT_PRODUCT_CLASS_NAME:
if product.is_seat_product:
course_id = product.course_id
stock_record = product.stockrecords.first()
if stock_record:
price = stock_record.price_excl_tax
......
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