Commit 47c725d3 by Ivan Ivic

[SOL-2173] Add Backend Validation for End Datetime and Start Datetime

parent 8cd1c75f
...@@ -186,13 +186,13 @@ class CouponMixin(object): ...@@ -186,13 +186,13 @@ class CouponMixin(object):
code=code, code=code,
course_seat_types=course_seat_types, course_seat_types=course_seat_types,
email_domains=email_domains, email_domains=email_domains,
end_datetime=datetime.date(2020, 1, 1), end_datetime=datetime.datetime(2020, 1, 1),
max_uses=max_uses, max_uses=max_uses,
note=note, note=note,
partner=partner, partner=partner,
price=price, price=price,
quantity=quantity, quantity=quantity,
start_datetime=datetime.date(2015, 1, 1), start_datetime=datetime.datetime(2015, 1, 1),
title=title, title=title,
voucher_type=voucher_type voucher_type=voucher_type
) )
......
...@@ -2,7 +2,6 @@ from __future__ import unicode_literals ...@@ -2,7 +2,6 @@ from __future__ import unicode_literals
import logging import logging
import dateutil.parser
from django.conf import settings from django.conf import settings
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import IntegrityError, transaction from django.db import IntegrityError, transaction
...@@ -154,13 +153,13 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet): ...@@ -154,13 +153,13 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
code=code, code=code,
course_seat_types=course_seat_types, course_seat_types=course_seat_types,
email_domains=request.data.get('email_domains'), email_domains=request.data.get('email_domains'),
end_datetime=dateutil.parser.parse(request.data.get('end_datetime')), end_datetime=request.data.get('end_datetime'),
max_uses=max_uses, max_uses=max_uses,
note=request.data.get('note'), note=request.data.get('note'),
partner=partner, partner=partner,
price=request.data.get('price'), price=request.data.get('price'),
quantity=request.data.get('quantity'), quantity=request.data.get('quantity'),
start_datetime=dateutil.parser.parse(request.data.get('start_datetime')), start_datetime=request.data.get('start_datetime'),
title=request.data.get('title'), title=request.data.get('title'),
voucher_type=voucher_type voucher_type=voucher_type
) )
......
...@@ -545,7 +545,8 @@ class VoucherAddMessagesViewTests(TestCase): ...@@ -545,7 +545,8 @@ class VoucherAddMessagesViewTests(TestCase):
def test_voucher_expired_error_msg(self): def test_voucher_expired_error_msg(self):
""" Verify correct error message is returned when voucher has expired. """ """ Verify correct error message is returned when voucher has expired. """
end_datetime = datetime.datetime.now() - datetime.timedelta(days=1) end_datetime = datetime.datetime.now() - datetime.timedelta(days=1)
factories.VoucherFactory(code=COUPON_CODE, end_datetime=end_datetime) start_datetime = datetime.datetime.now() - datetime.timedelta(days=2)
factories.VoucherFactory(code=COUPON_CODE, end_datetime=end_datetime, start_datetime=start_datetime)
self.assertMessage(_("Coupon code '{code}' has expired.").format(code=COUPON_CODE)) self.assertMessage(_("Coupon code '{code}' has expired.").format(code=COUPON_CODE))
def test_voucher_added_to_basket_msg(self): def test_voucher_added_to_basket_msg(self):
......
...@@ -388,10 +388,10 @@ class EnrollmentFulfillmentModuleTests(CourseCatalogTestMixin, FulfillmentTestMi ...@@ -388,10 +388,10 @@ class EnrollmentFulfillmentModuleTests(CourseCatalogTestMixin, FulfillmentTestMi
benefit_value=100.00, benefit_value=100.00,
catalog=catalog, catalog=catalog,
coupon=coupon, coupon=coupon,
end_datetime=datetime.datetime.now(), end_datetime=datetime.datetime.now() + datetime.timedelta(days=30),
name="Test Voucher", name="Test Voucher",
quantity=10, quantity=10,
start_datetime=datetime.datetime.now() + datetime.timedelta(days=30), start_datetime=datetime.datetime.now(),
voucher_type=Voucher.SINGLE_USE voucher_type=Voucher.SINGLE_USE
) )
voucher = vouchers[0] voucher = vouchers[0]
......
import datetime
import logging import logging
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
...@@ -29,6 +30,11 @@ class Voucher(AbstractVoucher): ...@@ -29,6 +30,11 @@ class Voucher(AbstractVoucher):
super(Voucher, self).save(*args, **kwargs) # pylint: disable=bad-super-call super(Voucher, self).save(*args, **kwargs) # pylint: disable=bad-super-call
def clean(self): def clean(self):
self.clean_code()
self.clean_datetimes()
super(Voucher, self).clean() # pylint: disable=bad-super-call
def clean_code(self):
if not self.code: if not self.code:
logger.exception('Failed to create Voucher. Voucher code must be set.') logger.exception('Failed to create Voucher. Voucher code must be set.')
raise ValidationError(_('Voucher code must be set.')) raise ValidationError(_('Voucher code must be set.'))
...@@ -36,5 +42,15 @@ class Voucher(AbstractVoucher): ...@@ -36,5 +42,15 @@ class Voucher(AbstractVoucher):
logger.exception('Failed to create Voucher. Voucher code must contain only alphanumeric characters.') logger.exception('Failed to create Voucher. Voucher code must contain only alphanumeric characters.')
raise ValidationError(_('Voucher code must contain only alphanumeric characters.')) raise ValidationError(_('Voucher code must contain only alphanumeric characters.'))
def clean_datetimes(self):
if not (self.end_datetime and self.start_datetime):
logger.exception('Failed to create Voucher. Voucher start and end datetime fields must be set.')
raise ValidationError(_('Voucher start and end datetime fields must be set.'))
if not (isinstance(self.end_datetime, datetime.datetime) and
isinstance(self.start_datetime, datetime.datetime)):
logger.exception('Failed to create Voucher. Voucher start and end datetime fields must be type datetime.')
raise ValidationError(_('Voucher start and end datetime fields must be type datetime.'))
from oscar.apps.voucher.models import * # noqa pylint: disable=wildcard-import,unused-wildcard-import,wrong-import-position from oscar.apps.voucher.models import * # noqa pylint: disable=wildcard-import,unused-wildcard-import,wrong-import-position
import datetime import datetime
import ddt
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.utils.timezone import now from django.utils.timezone import now
...@@ -9,25 +10,51 @@ from ecommerce.tests.testcases import TestCase ...@@ -9,25 +10,51 @@ from ecommerce.tests.testcases import TestCase
Voucher = get_model('voucher', 'Voucher') Voucher = get_model('voucher', 'Voucher')
@ddt.ddt
class VoucherTests(TestCase): class VoucherTests(TestCase):
def test_create_voucher(self): def setUp(self):
""" Verify voucher is created. """ super(VoucherTests, self).setUp()
data = { self.data = {
'code': 'TESTCODE', 'code': 'TESTCODE',
'start_datetime': str(now() - datetime.timedelta(days=1)), 'end_datetime': now() + datetime.timedelta(days=1),
'end_datetime': str(now() + datetime.timedelta(days=1)) 'start_datetime': now() - datetime.timedelta(days=1)
} }
voucher = Voucher.objects.create(**data)
self.assertEqual(voucher.code, data['code']) def test_create_voucher(self):
self.assertEqual(voucher.start_datetime, data['start_datetime']) """ Verify voucher is created. """
self.assertEqual(voucher.end_datetime, data['end_datetime']) voucher = Voucher.objects.create(**self.data)
self.assertEqual(voucher.code, self.data['code'])
self.assertEqual(voucher.start_datetime, self.data['start_datetime'])
self.assertEqual(voucher.end_datetime, self.data['end_datetime'])
def test_no_code_raises_exception(self): def test_no_code_raises_exception(self):
""" Verify creating voucher without code set raises exception. """ """ Verify creating voucher without code set raises exception. """
del self.data['code']
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
Voucher.objects.create() Voucher.objects.create(**self.data)
def test_wrong_code_data_raises_exception(self): def test_wrong_code_data_raises_exception(self):
""" Verify creating voucher with code value that contains spaces (non alphanumeric value) raises exception. """ """ Verify creating voucher with code value that contains spaces (non alphanumeric value) raises exception. """
self.data['code'] = 'Only alphanumeric without spaces'
with self.assertRaises(ValidationError):
Voucher.objects.create(**self.data)
@ddt.data('end_datetime', 'start_datetime')
def test_no_datetime_set_raises_exception(self, key):
""" Verify creating voucher without start/end datetime set raises exception. """
del self.data[key]
with self.assertRaises(ValidationError):
Voucher.objects.create(**self.data)
@ddt.data('end_datetime', 'start_datetime')
def test_incorrect_datetime_value_raises_exception(self, key):
""" Verify creating voucher with incorrect start/end datetime value raises exception. """
self.data[key] = 'incorrect value'
with self.assertRaises(ValidationError):
Voucher.objects.create(**self.data)
def test_start_datetime_after_end_datetime(self):
""" Verify creating voucher with start datetime set after end datetime raises exception. """
self.data['start_datetime'] = self.data['end_datetime'] + datetime.timedelta(days=1)
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
Voucher.objects.create(code='Only alphanumeric without spaces') Voucher.objects.create(**self.data)
...@@ -6,6 +6,7 @@ import hashlib ...@@ -6,6 +6,7 @@ import hashlib
import logging import logging
import uuid import uuid
import dateutil.parser
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
...@@ -367,6 +368,26 @@ def _create_new_voucher(code, coupon, end_datetime, name, offer, start_datetime, ...@@ -367,6 +368,26 @@ def _create_new_voucher(code, coupon, end_datetime, name, offer, start_datetime,
raise ValidationError(_('Voucher can not be created when code is set in enrollment coupon.')) raise ValidationError(_('Voucher can not be created when code is set in enrollment coupon.'))
voucher_code = code or _generate_code_string(settings.VOUCHER_CODE_LENGTH) voucher_code = code or _generate_code_string(settings.VOUCHER_CODE_LENGTH)
if not end_datetime:
logger.exception('Failed to create Voucher. Voucher end datetime field must be set.')
raise ValidationError(_('Voucher end datetime field must be set.'))
elif not isinstance(end_datetime, datetime.datetime):
try:
end_datetime = dateutil.parser.parse(end_datetime)
except (AttributeError, ValueError):
logger.exception('Failed to create Voucher. Voucher end datetime value [%s] is invalid.', end_datetime)
raise ValidationError(_('Voucher end datetime value [{date}] is invalid.'.format(date=end_datetime)))
if not start_datetime:
logger.exception('Failed to create Voucher. Voucher start datetime field must be set.')
raise ValidationError(_('Voucher start datetime field must be set.'))
elif not isinstance(start_datetime, datetime.datetime):
try:
start_datetime = dateutil.parser.parse(start_datetime)
except (AttributeError, ValueError):
logger.exception('Failed to create Voucher. Voucher start datetime value [%s] is invalid.', start_datetime)
raise ValidationError(_('Voucher start datetime value [{date}] is invalid.'.format(date=start_datetime)))
voucher = Voucher.objects.create( voucher = Voucher.objects.create(
name=name, name=name,
code=voucher_code, code=voucher_code,
......
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