Implement mediated bulk purchase epic
Updating EX-60 logic
This commit is contained in:
committed by
Chris Dodge
parent
27c83d51df
commit
2cc0433833
@@ -15,6 +15,8 @@ from xmodule.error_module import ErrorDescriptor
|
||||
from django.test.client import Client
|
||||
from student.models import CourseEnrollment
|
||||
from student.views import get_course_enrollment_pairs
|
||||
import unittest
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class TestCourseListing(ModuleStoreTestCase):
|
||||
@@ -54,6 +56,7 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
self.client.logout()
|
||||
super(TestCourseListing, self).tearDown()
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
def test_get_course_list(self):
|
||||
"""
|
||||
Test getting courses
|
||||
|
||||
@@ -32,6 +32,7 @@ from student.tests.factories import UserFactory, CourseModeFactory
|
||||
from certificates.models import CertificateStatuses
|
||||
from certificates.tests.factories import GeneratedCertificateFactory
|
||||
import shoppingcart
|
||||
from bulk_email.models import Optout
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -265,6 +266,50 @@ class DashboardTest(TestCase):
|
||||
verified_mode.save()
|
||||
self.assertFalse(enrollment.refundable())
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
@patch('courseware.views.log.warning')
|
||||
def test_blocked_course_scenario(self, log_warning):
|
||||
|
||||
self.client.login(username="jack", password="test")
|
||||
|
||||
#create testing invoice 1
|
||||
sale_invoice_1 = shoppingcart.models.Invoice.objects.create(
|
||||
total_amount=1234.32, company_name='Test1', company_contact_name='Testw',
|
||||
company_contact_email='test1@test.com', customer_reference_number='2Fwe23S',
|
||||
recipient_name='Testw_1', recipient_email='test2@test.com', internal_reference="A",
|
||||
course_id=self.course.id, is_valid=False
|
||||
)
|
||||
course_reg_code = shoppingcart.models.CourseRegistrationCode(code="abcde", course_id=self.course.id,
|
||||
created_by=self.user, invoice=sale_invoice_1)
|
||||
course_reg_code.save()
|
||||
|
||||
cart = shoppingcart.models.Order.get_cart_for_user(self.user)
|
||||
shoppingcart.models.PaidCourseRegistration.add_to_order(cart, self.course.id)
|
||||
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': course_reg_code.code})
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
# freely enroll the user into course
|
||||
resp = self.client.get(reverse('shoppingcart.views.register_courses'))
|
||||
self.assertIn('success', resp.content)
|
||||
|
||||
response = self.client.get(reverse('dashboard'))
|
||||
self.assertIn('You can no longer access this course because payment has not yet been received', response.content)
|
||||
optout_object = Optout.objects.filter(user=self.user, course_id=self.course.id)
|
||||
self.assertEqual(len(optout_object), 1)
|
||||
|
||||
# Direct link to course redirect to user dashboard
|
||||
self.client.get(reverse('courseware', kwargs={"course_id": self.course.id.to_deprecated_string()}))
|
||||
log_warning.assert_called_with(
|
||||
u'User %s cannot access the course %s because payment has not yet been received', self.user, self.course.id.to_deprecated_string())
|
||||
|
||||
# Now re-validating the invoice
|
||||
invoice = shoppingcart.models.Invoice.objects.get(id=sale_invoice_1.id)
|
||||
invoice.is_valid = True
|
||||
invoice.save()
|
||||
|
||||
response = self.client.get(reverse('dashboard'))
|
||||
self.assertNotIn('You can no longer access this course because payment has not yet been received', response.content)
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
def test_refundable_of_purchased_course(self):
|
||||
|
||||
@@ -315,6 +360,7 @@ class EnrollInCourseTest(TestCase):
|
||||
self.mock_tracker = patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
def test_enrollment(self):
|
||||
user = User.objects.create_user("joe", "joe@joe.com", "password")
|
||||
course_id = SlashSeparatedCourseKey("edX", "Test101", "2013")
|
||||
@@ -419,6 +465,7 @@ class EnrollInCourseTest(TestCase):
|
||||
self.assertTrue(CourseEnrollment.is_enrolled(user, course_id))
|
||||
self.assert_enrollment_event_was_emitted(user, course_id)
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
def test_enrollment_by_email(self):
|
||||
user = User.objects.create(username="jack", email="jack@fake.edx.org")
|
||||
course_id = SlashSeparatedCourseKey("edX", "Test101", "2013")
|
||||
@@ -456,6 +503,7 @@ class EnrollInCourseTest(TestCase):
|
||||
CourseEnrollment.unenroll_by_email("not_jack@fake.edx.org", course_id)
|
||||
self.assert_no_events_were_emitted()
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
def test_enrollment_multiple_classes(self):
|
||||
user = User(username="rusty", email="rusty@fake.edx.org")
|
||||
course_id1 = SlashSeparatedCourseKey("edX", "Test101", "2013")
|
||||
@@ -478,6 +526,7 @@ class EnrollInCourseTest(TestCase):
|
||||
self.assertFalse(CourseEnrollment.is_enrolled(user, course_id1))
|
||||
self.assertFalse(CourseEnrollment.is_enrolled(user, course_id2))
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
def test_activation(self):
|
||||
user = User.objects.create(username="jack", email="jack@fake.edx.org")
|
||||
course_id = SlashSeparatedCourseKey("edX", "Test101", "2013")
|
||||
|
||||
@@ -92,6 +92,7 @@ from util.password_policy_validators import (
|
||||
|
||||
from third_party_auth import pipeline, provider
|
||||
from xmodule.error_module import ErrorDescriptor
|
||||
from shoppingcart.models import CourseRegistrationCode
|
||||
|
||||
import analytics
|
||||
from eventtracking import tracker
|
||||
@@ -431,6 +432,20 @@ def complete_course_mode_info(course_id, enrollment):
|
||||
return mode_info
|
||||
|
||||
|
||||
def is_course_blocked(request, redeemed_registration_codes, course_key):
|
||||
"""Checking either registration is blocked or not ."""
|
||||
blocked = False
|
||||
for redeemed_registration in redeemed_registration_codes:
|
||||
if not getattr(redeemed_registration.invoice, 'is_valid'):
|
||||
blocked = True
|
||||
# disabling email notifications for unpaid registration courses
|
||||
Optout.objects.get_or_create(user=request.user, course_id=course_key)
|
||||
log.info(u"User {0} ({1}) opted out of receiving emails from course {2}".format(request.user.username, request.user.email, course_key))
|
||||
track.views.server_track(request, "change-email1-settings", {"receive_emails": "no", "course": course_key.to_deprecated_string()}, page='dashboard')
|
||||
break
|
||||
|
||||
return blocked
|
||||
|
||||
@login_required
|
||||
@ensure_csrf_cookie
|
||||
def dashboard(request):
|
||||
@@ -493,6 +508,10 @@ def dashboard(request):
|
||||
show_refund_option_for = frozenset(course.id for course, _enrollment in course_enrollment_pairs
|
||||
if _enrollment.refundable())
|
||||
|
||||
block_courses = frozenset(course.id for course, enrollment in course_enrollment_pairs
|
||||
if is_course_blocked(request, CourseRegistrationCode.objects.filter(course_id=course.id, registrationcoderedemption__redeemed_by=request.user), course.id))
|
||||
|
||||
|
||||
enrolled_courses_either_paid = frozenset(course.id for course, _enrollment in course_enrollment_pairs
|
||||
if _enrollment.is_paid_course())
|
||||
# get info w.r.t ExternalAuthMap
|
||||
@@ -544,6 +563,7 @@ def dashboard(request):
|
||||
'verification_status': verification_status,
|
||||
'verification_msg': verification_msg,
|
||||
'show_refund_option_for': show_refund_option_for,
|
||||
'block_courses': block_courses,
|
||||
'denied_banner': denied_banner,
|
||||
'billing_email': settings.PAYMENT_SUPPORT_EMAIL,
|
||||
'language_options': language_options,
|
||||
|
||||
@@ -46,6 +46,7 @@ from xmodule.modulestore.search import path_to_location
|
||||
from xmodule.tabs import CourseTabList, StaffGradingTab, PeerGradingTab, OpenEndedGradingTab
|
||||
from xmodule.x_module import STUDENT_VIEW
|
||||
import shoppingcart
|
||||
from shoppingcart.models import CourseRegistrationCode
|
||||
from opaque_keys import InvalidKeyError
|
||||
|
||||
from microsite_configuration import microsite
|
||||
@@ -291,6 +292,14 @@ def index(request, course_id, chapter=None, section=None,
|
||||
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
||||
|
||||
user = User.objects.prefetch_related("groups").get(id=request.user.id)
|
||||
|
||||
# Redirecting to dashboard if the course is blocked due to un payment.
|
||||
redeemed_registration_codes = CourseRegistrationCode.objects.filter(course_id=course_key, registrationcoderedemption__redeemed_by=request.user)
|
||||
for redeemed_registration in redeemed_registration_codes:
|
||||
if not getattr(redeemed_registration.invoice, 'is_valid'):
|
||||
log.warning(u'User %s cannot access the course %s because payment has not yet been received', user, course_key.to_deprecated_string())
|
||||
return redirect(reverse('dashboard'))
|
||||
|
||||
request.user = user # keep just one instance of User
|
||||
course = get_course_with_access(user, 'load', course_key, depth=2)
|
||||
staff_access = has_access(user, 'staff', course)
|
||||
|
||||
@@ -44,12 +44,17 @@ import instructor.views.api
|
||||
from instructor.views.api import _split_input_list, common_exceptions_400
|
||||
from instructor_task.api_helper import AlreadyRunningError
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from shoppingcart.models import CourseRegistrationCode, RegistrationCodeRedemption, Order, PaidCourseRegistration, Coupon
|
||||
from shoppingcart.models import (
|
||||
RegistrationCodeRedemption, Order,
|
||||
PaidCourseRegistration, Coupon, Invoice, CourseRegistrationCode
|
||||
)
|
||||
from course_modes.models import CourseMode
|
||||
|
||||
from .test_tools import msk_from_problem_urlname
|
||||
from ..views.tools import get_extended_due
|
||||
|
||||
EXPECTED_CSV_HEADER = '"code","course_id","company_name","created_by","redeemed_by","invoice_id","purchaser","customer_reference_number","internal_reference"'
|
||||
EXPECTED_COUPON_CSV_HEADER = '"course_id","percentage_discount","code_redeemed_count","description"'
|
||||
|
||||
@common_exceptions_400
|
||||
def view_success(request): # pylint: disable=W0613
|
||||
@@ -73,6 +78,7 @@ class TestCommonExceptions400(unittest.TestCase):
|
||||
"""
|
||||
Testing the common_exceptions_400 decorator.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.request = Mock(spec=HttpRequest)
|
||||
self.request.META = {}
|
||||
@@ -114,6 +120,7 @@ class TestInstructorAPIDenyLevels(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
"""
|
||||
Ensure that users cannot access endpoints they shouldn't be able to.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.course = CourseFactory.create()
|
||||
self.user = UserFactory.create()
|
||||
@@ -138,8 +145,10 @@ class TestInstructorAPIDenyLevels(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
('get_students_features', {}),
|
||||
('get_distribution', {}),
|
||||
('get_student_progress_url', {'unique_student_identifier': self.user.username}),
|
||||
('reset_student_attempts', {'problem_to_reset': self.problem_urlname, 'unique_student_identifier': self.user.email}),
|
||||
('update_forum_role_membership', {'unique_student_identifier': self.user.email, 'rolename': 'Moderator', 'action': 'allow'}),
|
||||
('reset_student_attempts',
|
||||
{'problem_to_reset': self.problem_urlname, 'unique_student_identifier': self.user.email}),
|
||||
('update_forum_role_membership',
|
||||
{'unique_student_identifier': self.user.email, 'rolename': 'Moderator', 'action': 'allow'}),
|
||||
('list_forum_members', {'rolename': FORUM_ROLE_COMMUNITY_TA}),
|
||||
('proxy_legacy_analytics', {'aname': 'ProblemGradeDistribution'}),
|
||||
('send_email', {'send_to': 'staff', 'subject': 'test', 'message': 'asdf'}),
|
||||
@@ -153,7 +162,8 @@ class TestInstructorAPIDenyLevels(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
('bulk_beta_modify_access', {'identifiers': 'foo@example.org', 'action': 'add'}),
|
||||
('modify_access', {'unique_student_identifier': self.user.email, 'rolename': 'beta', 'action': 'allow'}),
|
||||
('list_course_role_members', {'rolename': 'beta'}),
|
||||
('rescore_problem', {'problem_to_reset': self.problem_urlname, 'unique_student_identifier': self.user.email}),
|
||||
('rescore_problem',
|
||||
{'problem_to_reset': self.problem_urlname, 'unique_student_identifier': self.user.email}),
|
||||
]
|
||||
|
||||
def _access_endpoint(self, endpoint, args, status_code, msg):
|
||||
@@ -267,6 +277,7 @@ class TestInstructorAPIEnrollment(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
This test does NOT exhaustively test state changes, that is the
|
||||
job of test_enrollment. This tests the response and action switch.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.request = RequestFactory().request()
|
||||
self.course = CourseFactory.create()
|
||||
@@ -278,7 +289,8 @@ class TestInstructorAPIEnrollment(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
self.enrolled_student,
|
||||
self.course.id
|
||||
)
|
||||
self.notenrolled_student = UserFactory(username='NotEnrolledStudent', first_name='NotEnrolled', last_name='Student')
|
||||
self.notenrolled_student = UserFactory(username='NotEnrolledStudent', first_name='NotEnrolled',
|
||||
last_name='Student')
|
||||
|
||||
# Create invited, but not registered, user
|
||||
cea = CourseEnrollmentAllowed(email='robot-allowed@robot.org', course_id=self.course.id)
|
||||
@@ -537,7 +549,8 @@ class TestInstructorAPIEnrollment(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
@ddt.data('http', 'https')
|
||||
def test_enroll_with_email_not_registered_autoenroll(self, protocol):
|
||||
url = reverse('students_update_enrollment', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
params = {'identifiers': self.notregistered_email, 'action': 'enroll', 'email_students': True, 'auto_enroll': True}
|
||||
params = {'identifiers': self.notregistered_email, 'action': 'enroll', 'email_students': True,
|
||||
'auto_enroll': True}
|
||||
environ = {'wsgi.url_scheme': protocol}
|
||||
response = self.client.post(url, params, **environ)
|
||||
print "type(self.notregistered_email): {}".format(type(self.notregistered_email))
|
||||
@@ -746,7 +759,8 @@ class TestInstructorAPIEnrollment(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
mock_uses_shib.return_value = True
|
||||
|
||||
url = reverse('students_update_enrollment', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
params = {'identifiers': self.notregistered_email, 'action': 'enroll', 'email_students': True, 'auto_enroll': True}
|
||||
params = {'identifiers': self.notregistered_email, 'action': 'enroll', 'email_students': True,
|
||||
'auto_enroll': True}
|
||||
environ = {'wsgi.url_scheme': protocol}
|
||||
response = self.client.post(url, params, **environ)
|
||||
print "type(self.notregistered_email): {}".format(type(self.notregistered_email))
|
||||
@@ -775,6 +789,7 @@ class TestInstructorAPIBulkBetaEnrollment(ModuleStoreTestCase, LoginEnrollmentTe
|
||||
"""
|
||||
Test bulk beta modify access endpoint.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.course = CourseFactory.create()
|
||||
self.instructor = InstructorFactory(course_key=self.course.id)
|
||||
@@ -923,7 +938,8 @@ class TestInstructorAPIBulkBetaEnrollment(ModuleStoreTestCase, LoginEnrollmentTe
|
||||
@ddt.data('http', 'https')
|
||||
def test_add_notenrolled_with_email_autoenroll(self, protocol):
|
||||
url = reverse('bulk_beta_modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
params = {'identifiers': self.notenrolled_student.email, 'action': 'add', 'email_students': True, 'auto_enroll': True}
|
||||
params = {'identifiers': self.notenrolled_student.email, 'action': 'add', 'email_students': True,
|
||||
'auto_enroll': True}
|
||||
environ = {'wsgi.url_scheme': protocol}
|
||||
response = self.client.post(url, params, **environ)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -1089,6 +1105,7 @@ class TestInstructorAPILevelsAccess(ModuleStoreTestCase, LoginEnrollmentTestCase
|
||||
Actually, modify_access does not have a very meaningful
|
||||
response yet, so only the status code is tested.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.course = CourseFactory.create()
|
||||
self.instructor = InstructorFactory(course_key=self.course.id)
|
||||
@@ -1331,6 +1348,7 @@ class TestInstructorAPILevelsDataDump(ModuleStoreTestCase, LoginEnrollmentTestCa
|
||||
"""
|
||||
Test endpoints that show data without side effects.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.course = CourseFactory.create()
|
||||
self.course_mode = CourseMode(course_id=self.course.id,
|
||||
@@ -1346,10 +1364,61 @@ class TestInstructorAPILevelsDataDump(ModuleStoreTestCase, LoginEnrollmentTestCa
|
||||
percentage_discount=10, created_by=self.instructor, is_active=True)
|
||||
self.coupon.save()
|
||||
|
||||
#create testing invoice 1
|
||||
self.sale_invoice_1 = Invoice.objects.create(
|
||||
total_amount=1234.32, company_name='Test1', company_contact_name='TestName', company_contact_email='Test@company.com',
|
||||
recipient_name='Testw', recipient_email='test1@test.com', customer_reference_number='2Fwe23S',
|
||||
internal_reference="A", course_id=self.course.id, is_valid=True
|
||||
)
|
||||
|
||||
self.students = [UserFactory() for _ in xrange(6)]
|
||||
for student in self.students:
|
||||
CourseEnrollment.enroll(student, self.course.id)
|
||||
|
||||
def test_invalidate_sale_record(self):
|
||||
"""
|
||||
Testing the sale invalidating scenario.
|
||||
"""
|
||||
for i in range(2):
|
||||
course_registration_code = CourseRegistrationCode(
|
||||
code='sale_invoice{}'.format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
created_by=self.instructor, invoice=self.sale_invoice_1
|
||||
)
|
||||
course_registration_code.save()
|
||||
|
||||
data = {'invoice_number': self.sale_invoice_1.id, 'event_type': "invalidate"}
|
||||
url = reverse('sale_validation', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
self.assert_request_status_code(200, url, method="POST", data=data)
|
||||
|
||||
#Now try to fetch data against not existing invoice number
|
||||
test_data_1 = {'invoice_number': 100, 'event_type': "invalidate"}
|
||||
self.assert_request_status_code(404, url, method="POST", data=test_data_1)
|
||||
|
||||
# Now invalidate the same invoice number and expect an Bad request
|
||||
response = self.assert_request_status_code(400, url, method="POST", data=data)
|
||||
self.assertIn("The sale associated with this invoice has already been invalidated.", response.content)
|
||||
|
||||
# now re_validate the invoice number
|
||||
data['event_type'] = "re_validate"
|
||||
self.assert_request_status_code(200, url, method="POST", data=data)
|
||||
|
||||
# Now re_validate the same actove invoice number and expect an Bad request
|
||||
response = self.assert_request_status_code(400, url, method="POST", data=data)
|
||||
self.assertIn("This invoice is already active.", response.content)
|
||||
|
||||
test_data_2 = {'invoice_number': self.sale_invoice_1.id}
|
||||
response = self.assert_request_status_code(400, url, method="POST", data=test_data_2)
|
||||
self.assertIn("Missing required event_type parameter", response.content)
|
||||
|
||||
test_data_3 = {'event_type': "re_validate"}
|
||||
response = self.assert_request_status_code(400, url, method="POST", data=test_data_3)
|
||||
self.assertIn("Missing required invoice_number parameter", response.content)
|
||||
|
||||
# submitting invalid invoice number
|
||||
data['invoice_number'] = 'testing'
|
||||
response = self.assert_request_status_code(400, url, method="POST", data=data)
|
||||
self.assertIn("invoice_number must be an integer, {value} provided".format(value=data['invoice_number']), response.content)
|
||||
|
||||
def test_get_ecommerce_purchase_features_csv(self):
|
||||
"""
|
||||
Test that the response from get_purchase_transaction is in csv format.
|
||||
@@ -1360,6 +1429,115 @@ class TestInstructorAPILevelsDataDump(ModuleStoreTestCase, LoginEnrollmentTestCa
|
||||
response = self.client.get(url + '/csv', {})
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
|
||||
def test_get_sale_records_features_csv(self):
|
||||
"""
|
||||
Test that the response from get_sale_records is in csv format.
|
||||
"""
|
||||
for i in range(2):
|
||||
course_registration_code = CourseRegistrationCode(
|
||||
code='sale_invoice{}'.format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
created_by=self.instructor, invoice=self.sale_invoice_1
|
||||
)
|
||||
course_registration_code.save()
|
||||
|
||||
url = reverse('get_sale_records', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
response = self.client.get(url + '/csv', {})
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
|
||||
def test_get_sale_records_features_json(self):
|
||||
"""
|
||||
Test that the response from get_sale_records is in json format.
|
||||
"""
|
||||
for i in range(5):
|
||||
course_registration_code = CourseRegistrationCode(
|
||||
code='sale_invoice{}'.format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
created_by=self.instructor, invoice=self.sale_invoice_1
|
||||
)
|
||||
course_registration_code.save()
|
||||
|
||||
url = reverse('get_sale_records', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
response = self.client.get(url, {})
|
||||
res_json = json.loads(response.content)
|
||||
self.assertIn('sale', res_json)
|
||||
|
||||
for res in res_json['sale']:
|
||||
self.validate_sale_records_response(res, course_registration_code, self.sale_invoice_1, 0)
|
||||
|
||||
def test_get_sale_records_features_with_used_code(self):
|
||||
"""
|
||||
Test that the response from get_sale_records is in json format and using one of the registration codes.
|
||||
"""
|
||||
for i in range(5):
|
||||
course_registration_code = CourseRegistrationCode(
|
||||
code='qwerty{}'.format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
created_by=self.instructor, invoice=self.sale_invoice_1
|
||||
)
|
||||
course_registration_code.save()
|
||||
|
||||
PaidCourseRegistration.add_to_order(self.cart, self.course.id)
|
||||
|
||||
# now using registration code
|
||||
self.client.post(reverse('shoppingcart.views.use_code'), {'code': 'qwerty0'})
|
||||
|
||||
url = reverse('get_sale_records', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
response = self.client.get(url, {})
|
||||
res_json = json.loads(response.content)
|
||||
self.assertIn('sale', res_json)
|
||||
|
||||
for res in res_json['sale']:
|
||||
self.validate_sale_records_response(res, course_registration_code, self.sale_invoice_1, 1)
|
||||
|
||||
def test_get_sale_records_features_with_multiple_invoices(self):
|
||||
"""
|
||||
Test that the response from get_sale_records is in json format for multiple invoices
|
||||
"""
|
||||
for i in range(5):
|
||||
course_registration_code = CourseRegistrationCode(
|
||||
code='qwerty{}'.format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
created_by=self.instructor, invoice=self.sale_invoice_1
|
||||
)
|
||||
course_registration_code.save()
|
||||
|
||||
#create test invoice 2
|
||||
sale_invoice_2 = Invoice.objects.create(
|
||||
total_amount=1234.32, company_name='Test1', company_contact_name='TestName', company_contact_email='Test@company.com',
|
||||
recipient_name='Testw_2', recipient_email='test2@test.com', customer_reference_number='2Fwe23S',
|
||||
internal_reference="B", course_id=self.course.id
|
||||
)
|
||||
|
||||
for i in range(5):
|
||||
course_registration_code = CourseRegistrationCode(
|
||||
code='xyzmn{}'.format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
created_by=self.instructor, invoice=sale_invoice_2
|
||||
)
|
||||
course_registration_code.save()
|
||||
|
||||
url = reverse('get_sale_records', kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
response = self.client.get(url, {})
|
||||
res_json = json.loads(response.content)
|
||||
self.assertIn('sale', res_json)
|
||||
|
||||
self.validate_sale_records_response(res_json['sale'][0], course_registration_code, self.sale_invoice_1, 0)
|
||||
self.validate_sale_records_response(res_json['sale'][1], course_registration_code, sale_invoice_2, 0)
|
||||
|
||||
def validate_sale_records_response(self, res, course_registration_code, invoice, used_codes):
|
||||
"""
|
||||
validate sale records attribute values with the response object
|
||||
"""
|
||||
self.assertEqual(res['total_amount'], invoice.total_amount)
|
||||
self.assertEqual(res['recipient_email'], invoice.recipient_email)
|
||||
self.assertEqual(res['recipient_name'], invoice.recipient_name)
|
||||
self.assertEqual(res['company_name'], invoice.company_name)
|
||||
self.assertEqual(res['company_contact_name'], invoice.company_contact_name)
|
||||
self.assertEqual(res['company_contact_email'], invoice.company_contact_email)
|
||||
self.assertEqual(res['internal_reference'], invoice.internal_reference)
|
||||
self.assertEqual(res['customer_reference_number'], invoice.customer_reference_number)
|
||||
self.assertEqual(res['invoice_number'], invoice.id)
|
||||
self.assertEqual(res['created_by'], course_registration_code.created_by.username)
|
||||
self.assertEqual(res['course_id'], invoice.course_id.to_deprecated_string())
|
||||
self.assertEqual(res['total_used_codes'], used_codes)
|
||||
self.assertEqual(res['total_codes'], 5)
|
||||
|
||||
def test_get_ecommerce_purchase_features_with_coupon_info(self):
|
||||
"""
|
||||
Test that some minimum of information is formatted
|
||||
@@ -1588,6 +1766,7 @@ class TestInstructorAPIRegradeTask(ModuleStoreTestCase, LoginEnrollmentTestCase)
|
||||
This test does NOT test whether the actions had an effect on the
|
||||
database, that is the job of task tests and test_enrollment.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.course = CourseFactory.create()
|
||||
self.instructor = InstructorFactory(course_key=self.course.id)
|
||||
@@ -1726,6 +1905,7 @@ class TestInstructorSendEmail(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
these endpoints are only accessible with courses that actually exist,
|
||||
only with valid email messages.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.course = CourseFactory.create()
|
||||
self.instructor = InstructorFactory(course_key=self.course.id)
|
||||
@@ -1967,6 +2147,7 @@ class TestInstructorEmailContentList(ModuleStoreTestCase, LoginEnrollmentTestCas
|
||||
"""
|
||||
Test the instructor email content history endpoint.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.course = CourseFactory.create()
|
||||
self.instructor = InstructorFactory(course_key=self.course.id)
|
||||
@@ -2105,12 +2286,14 @@ class TestInstructorAPIAnalyticsProxy(ModuleStoreTestCase, LoginEnrollmentTestCa
|
||||
|
||||
class FakeProxyResponse(object):
|
||||
""" Fake successful requests response object. """
|
||||
|
||||
def __init__(self):
|
||||
self.status_code = requests.status_codes.codes.OK
|
||||
self.content = '{"test_content": "robot test content"}'
|
||||
|
||||
class FakeBadProxyResponse(object):
|
||||
""" Fake strange-failed requests response object. """
|
||||
|
||||
def __init__(self):
|
||||
self.status_code = 'notok.'
|
||||
self.content = '{"test_content": "robot test content"}'
|
||||
@@ -2182,19 +2365,25 @@ class TestInstructorAPIAnalyticsProxy(ModuleStoreTestCase, LoginEnrollmentTestCa
|
||||
|
||||
class TestInstructorAPIHelpers(TestCase):
|
||||
""" Test helpers for instructor.api """
|
||||
|
||||
def test_split_input_list(self):
|
||||
strings = []
|
||||
lists = []
|
||||
strings.append("Lorem@ipsum.dolor, sit@amet.consectetur\nadipiscing@elit.Aenean\r convallis@at.lacus\r, ut@lacinia.Sed")
|
||||
lists.append(['Lorem@ipsum.dolor', 'sit@amet.consectetur', 'adipiscing@elit.Aenean', 'convallis@at.lacus', 'ut@lacinia.Sed'])
|
||||
strings.append(
|
||||
"Lorem@ipsum.dolor, sit@amet.consectetur\nadipiscing@elit.Aenean\r convallis@at.lacus\r, ut@lacinia.Sed")
|
||||
lists.append(['Lorem@ipsum.dolor', 'sit@amet.consectetur', 'adipiscing@elit.Aenean', 'convallis@at.lacus',
|
||||
'ut@lacinia.Sed'])
|
||||
|
||||
for (stng, lst) in zip(strings, lists):
|
||||
self.assertEqual(_split_input_list(stng), lst)
|
||||
|
||||
def test_split_input_list_unicode(self):
|
||||
self.assertEqual(_split_input_list('robot@robot.edu, robot2@robot.edu'), ['robot@robot.edu', 'robot2@robot.edu'])
|
||||
self.assertEqual(_split_input_list(u'robot@robot.edu, robot2@robot.edu'), ['robot@robot.edu', 'robot2@robot.edu'])
|
||||
self.assertEqual(_split_input_list(u'robot@robot.edu, robot2@robot.edu'), [u'robot@robot.edu', 'robot2@robot.edu'])
|
||||
self.assertEqual(_split_input_list('robot@robot.edu, robot2@robot.edu'),
|
||||
['robot@robot.edu', 'robot2@robot.edu'])
|
||||
self.assertEqual(_split_input_list(u'robot@robot.edu, robot2@robot.edu'),
|
||||
['robot@robot.edu', 'robot2@robot.edu'])
|
||||
self.assertEqual(_split_input_list(u'robot@robot.edu, robot2@robot.edu'),
|
||||
[u'robot@robot.edu', 'robot2@robot.edu'])
|
||||
scary_unistuff = unichr(40960) + u'abcd' + unichr(1972)
|
||||
self.assertEqual(_split_input_list(scary_unistuff), [scary_unistuff])
|
||||
|
||||
@@ -2383,7 +2572,7 @@ class TestDueDateExtensions(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
u'Username': self.user1.username}],
|
||||
u'header': [u'Username', u'Full Name', u'Extended Due Date'],
|
||||
u'title': u'Users with due date extensions for %s' %
|
||||
self.week1.display_name})
|
||||
self.week1.display_name})
|
||||
|
||||
def test_show_student_extensions(self):
|
||||
self.test_change_due_date()
|
||||
@@ -2396,7 +2585,7 @@ class TestDueDateExtensions(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
u'Unit': self.week1.display_name}],
|
||||
u'header': [u'Unit', u'Extended Due Date'],
|
||||
u'title': u'Due date extensions for %s (%s)' % (
|
||||
self.user1.profile.name, self.user1.username)})
|
||||
self.user1.profile.name, self.user1.username)})
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
|
||||
@@ -2405,6 +2594,7 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
|
||||
"""
|
||||
Test data dumps for E-commerce Course Registration Codes.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Fixtures.
|
||||
@@ -2413,14 +2603,19 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
|
||||
self.instructor = InstructorFactory(course_key=self.course.id)
|
||||
self.client.login(username=self.instructor.username, password='test')
|
||||
|
||||
# Active Registration Codes
|
||||
for i in range(12):
|
||||
course_registration_code = CourseRegistrationCode(
|
||||
code='MyCode0{}'.format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
transaction_group_name='Test Group', created_by=self.instructor
|
||||
)
|
||||
course_registration_code.save()
|
||||
url = reverse('generate_registration_codes',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
|
||||
data = {
|
||||
'total_registration_codes': 12, 'company_name': 'Test Group', 'company_contact_name': 'Test@company.com',
|
||||
'company_contact_email': 'Test@company.com', 'sale_price': 122.45, 'recipient_name': 'Test123',
|
||||
'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street',
|
||||
'address_line_2': '', 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '',
|
||||
'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': ''
|
||||
}
|
||||
|
||||
response = self.client.post(url, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
for i in range(5):
|
||||
order = Order(user=self.instructor, status='purchased')
|
||||
order.save()
|
||||
@@ -2433,6 +2628,48 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
|
||||
)
|
||||
registration_code_redemption.save()
|
||||
|
||||
def test_user_invoice_copy_preference(self):
|
||||
"""
|
||||
Test to remember user invoice copy preference
|
||||
"""
|
||||
url_reg_code = reverse('generate_registration_codes',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
|
||||
data = {
|
||||
'total_registration_codes': 5, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com',
|
||||
'company_contact_email': 'Test@company.com', 'sale_price': 121.45, 'recipient_name': 'Test123',
|
||||
'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '',
|
||||
'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '',
|
||||
'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': 'True'
|
||||
}
|
||||
|
||||
# user invoice copy preference will be saved in api user preference; model
|
||||
response = self.client.post(url_reg_code, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
|
||||
# get user invoice copy preference.
|
||||
url_user_invoice_preference = reverse('get_user_invoice_preference',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
|
||||
response = self.client.post(url_user_invoice_preference, data)
|
||||
result = json.loads(response.content)
|
||||
self.assertEqual(result['invoice_copy'], True)
|
||||
|
||||
# updating the user invoice copy preference during code generation flow
|
||||
data['invoice'] = ''
|
||||
response = self.client.post(url_reg_code, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
|
||||
# get user invoice copy preference.
|
||||
url_user_invoice_preference = reverse('get_user_invoice_preference',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
|
||||
response = self.client.post(url_user_invoice_preference, data)
|
||||
result = json.loads(response.content)
|
||||
self.assertEqual(result['invoice_copy'], False)
|
||||
|
||||
def test_generate_course_registration_codes_csv(self):
|
||||
"""
|
||||
Test to generate a response of all the generated course registration codes
|
||||
@@ -2440,16 +2677,23 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
|
||||
url = reverse('generate_registration_codes',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
|
||||
data = {'course_registration_code_number': 15.0, 'transaction_group_name': 'Test Group'}
|
||||
data = {
|
||||
'total_registration_codes': 15, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com',
|
||||
'company_contact_email': 'Test@company.com', 'sale_price': 122.45, 'recipient_name': 'Test123',
|
||||
'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '',
|
||||
'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '',
|
||||
'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': ''
|
||||
}
|
||||
|
||||
response = self.client.post(url, data)
|
||||
response = self.client.post(url, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith('"code","course_id","transaction_group_name","created_by","redeemed_by"'))
|
||||
self.assertTrue(body.startswith(EXPECTED_CSV_HEADER))
|
||||
self.assertEqual(len(body.split('\n')), 17)
|
||||
|
||||
@patch.object(instructor.views.api, 'random_code_generator', Mock(side_effect=['first', 'second', 'third', 'fourth']))
|
||||
@patch.object(instructor.views.api, 'random_code_generator',
|
||||
Mock(side_effect=['first', 'second', 'third', 'fourth']))
|
||||
def test_generate_course_registration_codes_matching_existing_coupon_code(self):
|
||||
"""
|
||||
Test the generated course registration code is already in the Coupon Table
|
||||
@@ -2459,16 +2703,23 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
|
||||
|
||||
coupon = Coupon(code='first', course_id=self.course.id.to_deprecated_string(), created_by=self.instructor)
|
||||
coupon.save()
|
||||
data = {'course_registration_code_number': 3, 'transaction_group_name': 'Test Group'}
|
||||
data = {
|
||||
'total_registration_codes': 3, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com',
|
||||
'company_contact_email': 'Test@company.com', 'sale_price': 122.45, 'recipient_name': 'Test123',
|
||||
'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '',
|
||||
'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '',
|
||||
'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': ''
|
||||
}
|
||||
|
||||
response = self.client.post(url, data)
|
||||
response = self.client.post(url, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith('"code","course_id","transaction_group_name","created_by","redeemed_by"'))
|
||||
self.assertTrue(body.startswith(EXPECTED_CSV_HEADER))
|
||||
self.assertEqual(len(body.split('\n')), 5) # 1 for headers, 1 for new line at the end and 3 for the actual data
|
||||
|
||||
@patch.object(instructor.views.api, 'random_code_generator', Mock(side_effect=['first', 'first', 'second', 'third']))
|
||||
@patch.object(instructor.views.api, 'random_code_generator',
|
||||
Mock(side_effect=['first', 'first', 'second', 'third']))
|
||||
def test_generate_course_registration_codes_integrity_error(self):
|
||||
"""
|
||||
Test for the Integrity error against the generated code
|
||||
@@ -2476,13 +2727,19 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
|
||||
url = reverse('generate_registration_codes',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
|
||||
data = {'course_registration_code_number': 2, 'transaction_group_name': 'Test Group'}
|
||||
data = {
|
||||
'total_registration_codes': 2, 'company_name': 'Test Group', 'company_contact_name': 'Test@company.com',
|
||||
'company_contact_email': 'Test@company.com', 'sale_price': 122.45, 'recipient_name': 'Test123',
|
||||
'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '',
|
||||
'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '',
|
||||
'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': ''
|
||||
}
|
||||
|
||||
response = self.client.post(url, data)
|
||||
response = self.client.post(url, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith('"code","course_id","transaction_group_name","created_by","redeemed_by"'))
|
||||
self.assertTrue(body.startswith(EXPECTED_CSV_HEADER))
|
||||
self.assertEqual(len(body.split('\n')), 4)
|
||||
|
||||
def test_spent_course_registration_codes_csv(self):
|
||||
@@ -2492,20 +2749,30 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
|
||||
url = reverse('spent_registration_codes',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
|
||||
data = {'spent_transaction_group_name': ''}
|
||||
data = {'spent_company_name': ''}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith('"code","course_id","transaction_group_name","created_by","redeemed_by"'))
|
||||
|
||||
self.assertTrue(body.startswith(EXPECTED_CSV_HEADER))
|
||||
|
||||
self.assertEqual(len(body.split('\n')), 7)
|
||||
|
||||
for i in range(9):
|
||||
course_registration_code = CourseRegistrationCode(
|
||||
code='TestCode{}'.format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
transaction_group_name='Group Alpha', created_by=self.instructor
|
||||
)
|
||||
course_registration_code.save()
|
||||
generate_code_url = reverse(
|
||||
'generate_registration_codes', kwargs={'course_id': self.course.id.to_deprecated_string()}
|
||||
)
|
||||
|
||||
data = {
|
||||
'total_registration_codes': 9, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com',
|
||||
'sale_price': 122.45, 'company_contact_email': 'Test@company.com', 'recipient_name': 'Test123',
|
||||
'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '',
|
||||
'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '',
|
||||
'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': ''
|
||||
}
|
||||
|
||||
response = self.client.post(generate_code_url, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
|
||||
for i in range(9):
|
||||
order = Order(user=self.instructor, status='purchased')
|
||||
@@ -2519,12 +2786,12 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
|
||||
)
|
||||
registration_code_redemption.save()
|
||||
|
||||
data = {'spent_transaction_group_name': 'Group Alpha'}
|
||||
data = {'spent_company_name': 'Group Alpha'}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith('"code","course_id","transaction_group_name","created_by","redeemed_by"'))
|
||||
self.assertTrue(body.startswith(EXPECTED_CSV_HEADER))
|
||||
self.assertEqual(len(body.split('\n')), 11)
|
||||
|
||||
def test_active_course_registration_codes_csv(self):
|
||||
@@ -2534,55 +2801,120 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
|
||||
url = reverse('active_registration_codes',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
|
||||
data = {'active_transaction_group_name': ''}
|
||||
data = {'active_company_name': ''}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith('"code","course_id","transaction_group_name","created_by","redeemed_by"'))
|
||||
self.assertTrue(body.startswith(EXPECTED_CSV_HEADER))
|
||||
self.assertEqual(len(body.split('\n')), 9)
|
||||
|
||||
for i in range(9):
|
||||
course_registration_code = CourseRegistrationCode(
|
||||
code='TestCode{}'.format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
transaction_group_name='Group Alpha', created_by=self.instructor
|
||||
)
|
||||
course_registration_code.save()
|
||||
generate_code_url = reverse(
|
||||
'generate_registration_codes', kwargs={'course_id': self.course.id.to_deprecated_string()}
|
||||
)
|
||||
|
||||
data = {'active_transaction_group_name': 'Group Alpha'}
|
||||
data = {
|
||||
'total_registration_codes': 9, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com',
|
||||
'company_contact_email': 'Test@company.com', 'sale_price': 122.45, 'recipient_name': 'Test123',
|
||||
'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '',
|
||||
'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '',
|
||||
'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': ''
|
||||
}
|
||||
|
||||
response = self.client.post(generate_code_url, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
|
||||
data = {'active_company_name': 'Group Alpha'}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith('"code","course_id","transaction_group_name","created_by","redeemed_by"'))
|
||||
self.assertTrue(body.startswith(EXPECTED_CSV_HEADER))
|
||||
self.assertEqual(len(body.split('\n')), 11)
|
||||
|
||||
def test_get_all_course_registration_codes_csv(self):
|
||||
"""
|
||||
Test to generate a response of all the course registration codes
|
||||
"""
|
||||
url = reverse('get_registration_codes',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
url = reverse(
|
||||
'get_registration_codes', kwargs={'course_id': self.course.id.to_deprecated_string()}
|
||||
)
|
||||
|
||||
data = {'download_transaction_group_name': ''}
|
||||
data = {'download_company_name': ''}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith('"code","course_id","transaction_group_name","created_by","redeemed_by"'))
|
||||
self.assertTrue(body.startswith(EXPECTED_CSV_HEADER))
|
||||
self.assertEqual(len(body.split('\n')), 14)
|
||||
|
||||
for i in range(9):
|
||||
course_registration_code = CourseRegistrationCode(
|
||||
code='TestCode{}'.format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
transaction_group_name='Group Alpha', created_by=self.instructor
|
||||
)
|
||||
course_registration_code.save()
|
||||
generate_code_url = reverse(
|
||||
'generate_registration_codes', kwargs={'course_id': self.course.id.to_deprecated_string()}
|
||||
)
|
||||
|
||||
data = {'download_transaction_group_name': 'Group Alpha'}
|
||||
data = {
|
||||
'total_registration_codes': 9, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com',
|
||||
'company_contact_email': 'Test@company.com', 'sale_price': 122.45, 'recipient_name': 'Test123',
|
||||
'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '',
|
||||
'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '',
|
||||
'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': ''
|
||||
}
|
||||
|
||||
response = self.client.post(generate_code_url, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
|
||||
data = {'download_company_name': 'Group Alpha'}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith('"code","course_id","transaction_group_name","created_by","redeemed_by"'))
|
||||
self.assertTrue(body.startswith(EXPECTED_CSV_HEADER))
|
||||
self.assertEqual(len(body.split('\n')), 11)
|
||||
|
||||
def test_get_codes_with_sale_invoice(self):
|
||||
"""
|
||||
Test to generate a response of all the course registration codes
|
||||
"""
|
||||
generate_code_url = reverse(
|
||||
'generate_registration_codes', kwargs={'course_id': self.course.id.to_deprecated_string()}
|
||||
)
|
||||
|
||||
data = {
|
||||
'total_registration_codes': 5.5, 'company_name': 'Group Invoice', 'company_contact_name': 'Test@company.com',
|
||||
'company_contact_email': 'Test@company.com', 'sale_price': 122.45, 'recipient_name': 'Test123',
|
||||
'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '',
|
||||
'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '',
|
||||
'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': True
|
||||
}
|
||||
|
||||
response = self.client.post(generate_code_url, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
|
||||
url = reverse('get_registration_codes',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
data = {'download_company_name': 'Group Invoice'}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith(EXPECTED_CSV_HEADER))
|
||||
|
||||
def test_get_historical_coupon_codes(self):
|
||||
"""
|
||||
Test to download a response of all the active coupon codes
|
||||
"""
|
||||
get_coupon_code_url = reverse(
|
||||
'get_coupon_codes', kwargs={'course_id': self.course.id.to_deprecated_string()}
|
||||
)
|
||||
for i in range(10):
|
||||
coupon = Coupon(
|
||||
code='test_code{0}'.format(i), description='test_description', course_id=self.course.id,
|
||||
percentage_discount='{0}'.format(i), created_by=self.instructor, is_active=True
|
||||
)
|
||||
coupon.save()
|
||||
|
||||
response = self.client.get(get_coupon_code_url)
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'text/csv')
|
||||
body = response.content.replace('\r', '')
|
||||
self.assertTrue(body.startswith(EXPECTED_COUPON_CSV_HEADER))
|
||||
|
||||
@@ -175,8 +175,7 @@ class TestECommerceDashboardViews(ModuleStoreTestCase):
|
||||
self.assertTrue('Please Enter the Integer Value for Coupon Discount' in response.content)
|
||||
|
||||
course_registration = CourseRegistrationCode(
|
||||
code='Vs23Ws4j', course_id=self.course.id.to_deprecated_string(),
|
||||
transaction_group_name='Test Group', created_by=self.instructor
|
||||
code='Vs23Ws4j', course_id=self.course.id.to_deprecated_string(), created_by=self.instructor
|
||||
)
|
||||
course_registration.save()
|
||||
|
||||
@@ -254,7 +253,7 @@ class TestECommerceDashboardViews(ModuleStoreTestCase):
|
||||
response = self.client.post(self.url)
|
||||
self.assertTrue('<td>AS452</td>' in response.content)
|
||||
data = {
|
||||
'coupon_id': coupon.id, 'code': 'update_code', 'discount': '12',
|
||||
'coupon_id': coupon.id, 'code': 'AS452', 'discount': '10', 'description': 'updated_description', # pylint: disable=E1101
|
||||
'course_id': coupon.course_id.to_deprecated_string()
|
||||
}
|
||||
# URL for update_coupon
|
||||
@@ -263,43 +262,12 @@ class TestECommerceDashboardViews(ModuleStoreTestCase):
|
||||
self.assertTrue('coupon with the coupon id ({coupon_id}) updated Successfully'.format(coupon_id=coupon.id)in response.content)
|
||||
|
||||
response = self.client.post(self.url)
|
||||
self.assertTrue('<td>update_code</td>' in response.content)
|
||||
self.assertTrue('<td>12</td>' in response.content)
|
||||
self.assertTrue('<td>updated_description</td>' in response.content)
|
||||
|
||||
data['coupon_id'] = 1000 # Coupon Not Exist with this ID
|
||||
response = self.client.post(update_coupon_url, data=data)
|
||||
self.assertTrue('coupon with the coupon id ({coupon_id}) DoesNotExist'.format(coupon_id=1000) in response.content)
|
||||
|
||||
data['coupon_id'] = coupon.id
|
||||
data['discount'] = 123
|
||||
response = self.client.post(update_coupon_url, data=data)
|
||||
self.assertTrue('Please Enter the Coupon Discount Value Less than or Equal to 100' in response.content)
|
||||
|
||||
data['discount'] = '25%'
|
||||
response = self.client.post(update_coupon_url, data=data)
|
||||
self.assertTrue('Please Enter the Integer Value for Coupon Discount' in response.content)
|
||||
|
||||
data['coupon_id'] = '' # Coupon id is not provided
|
||||
response = self.client.post(update_coupon_url, data=data)
|
||||
self.assertTrue('coupon id not found' in response.content)
|
||||
|
||||
coupon1 = Coupon(
|
||||
code='11111', description='coupon', course_id=self.course.id.to_deprecated_string(),
|
||||
percentage_discount=20, created_by=self.instructor
|
||||
)
|
||||
coupon1.save()
|
||||
data = {'coupon_id': coupon.id, 'code': '11111', 'discount': '12'} # pylint: disable=E1101
|
||||
response = self.client.post(update_coupon_url, data=data)
|
||||
self.assertTrue('coupon with the coupon id ({coupon_id}) already exist'.format(coupon_id=coupon.id) in response.content) # pylint: disable=E1101
|
||||
|
||||
course_registration = CourseRegistrationCode(
|
||||
code='Vs23Ws4j', course_id=self.course.id.to_deprecated_string(),
|
||||
transaction_group_name='Test Group', created_by=self.instructor
|
||||
)
|
||||
course_registration.save()
|
||||
|
||||
data = {'coupon_id': coupon.id, 'code': 'Vs23Ws4j', # pylint: disable=E1101
|
||||
'discount': '6', 'course_id': coupon.course_id.to_deprecated_string()} # pylint: disable=E1101
|
||||
response = self.client.post(update_coupon_url, data=data)
|
||||
self.assertTrue("The code ({code}) that you have tried to define is already in use as a registration code".
|
||||
format(code=data['code']) in response.content)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
"""
|
||||
This is the UserPreference key for the user's recipient invoice copy
|
||||
"""
|
||||
INVOICE_KEY = 'pref-invoice-copy'
|
||||
|
||||
@@ -5,27 +5,30 @@ JSON views which the instructor dashboard requests.
|
||||
|
||||
Many of these GETs may become PUTs in the future.
|
||||
"""
|
||||
from django.views.decorators.http import require_POST
|
||||
|
||||
import StringIO
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from django_future.csrf import ensure_csrf_cookie
|
||||
from django.views.decorators.http import require_POST
|
||||
from django.views.decorators.cache import cache_control
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.mail.message import EmailMessage
|
||||
from django.db import IntegrityError
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.validators import validate_email
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
|
||||
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound
|
||||
from django.utils.html import strip_tags
|
||||
import string # pylint: disable=W0402
|
||||
import random
|
||||
from util.json_request import JsonResponse
|
||||
from instructor.views.instructor_task_helpers import extract_email_features, extract_task_features
|
||||
|
||||
from microsite_configuration import microsite
|
||||
|
||||
from courseware.access import has_access
|
||||
from courseware.courses import get_course_with_access, get_course_by_id
|
||||
from django.contrib.auth.models import User
|
||||
@@ -36,9 +39,9 @@ from django_comment_common.models import (
|
||||
FORUM_ROLE_MODERATOR,
|
||||
FORUM_ROLE_COMMUNITY_TA,
|
||||
)
|
||||
from edxmako.shortcuts import render_to_response
|
||||
from edxmako.shortcuts import render_to_response, render_to_string
|
||||
from courseware.models import StudentModule
|
||||
from shoppingcart.models import Coupon, CourseRegistrationCode, RegistrationCodeRedemption
|
||||
from shoppingcart.models import Coupon, CourseRegistrationCode, RegistrationCodeRedemption, Invoice, CourseMode
|
||||
from student.models import CourseEnrollment, unique_id_for_user, anonymous_id_for_user
|
||||
import instructor_task.api
|
||||
from instructor_task.api_helper import AlreadyRunningError
|
||||
@@ -56,6 +59,8 @@ import instructor_analytics.basic
|
||||
import instructor_analytics.distributions
|
||||
import instructor_analytics.csvs
|
||||
import csv
|
||||
from user_api.models import UserPreference
|
||||
from instructor.views import INVOICE_KEY
|
||||
|
||||
from submissions import api as sub_api # installed from the edx-submissions repository
|
||||
|
||||
@@ -552,6 +557,97 @@ def get_grading_config(request, course_id):
|
||||
return JsonResponse(response_payload)
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
||||
@require_level('staff')
|
||||
def get_sale_records(request, course_id, csv=False): # pylint: disable=W0613, W0621
|
||||
"""
|
||||
return the summary of all sales records for a particular course
|
||||
"""
|
||||
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
||||
query_features = [
|
||||
'company_name', 'company_contact_name', 'company_contact_email', 'total_codes', 'total_used_codes',
|
||||
'total_amount', 'created_at', 'customer_reference_number', 'recipient_name', 'recipient_email', 'created_by',
|
||||
'internal_reference', 'invoice_number', 'codes', 'course_id'
|
||||
]
|
||||
|
||||
sale_data = instructor_analytics.basic.sale_record_features(course_id, query_features)
|
||||
|
||||
if not csv:
|
||||
for item in sale_data:
|
||||
item['created_by'] = item['created_by'].username
|
||||
|
||||
response_payload = {
|
||||
'course_id': course_id.to_deprecated_string(),
|
||||
'sale': sale_data,
|
||||
'queried_features': query_features
|
||||
}
|
||||
return JsonResponse(response_payload)
|
||||
else:
|
||||
header, datarows = instructor_analytics.csvs.format_dictlist(sale_data, query_features)
|
||||
return instructor_analytics.csvs.create_csv_response("e-commerce_sale_records.csv", header, datarows)
|
||||
|
||||
|
||||
@require_level('staff')
|
||||
@require_POST
|
||||
def sale_validation(request, course_id):
|
||||
"""
|
||||
This method either invalidate or re validate the sale against the invoice number depending upon the event type
|
||||
"""
|
||||
try:
|
||||
invoice_number = request.POST["invoice_number"]
|
||||
except KeyError:
|
||||
return HttpResponseBadRequest("Missing required invoice_number parameter")
|
||||
try:
|
||||
invoice_number = int(invoice_number)
|
||||
except ValueError:
|
||||
return HttpResponseBadRequest(
|
||||
"invoice_number must be an integer, {value} provided".format(
|
||||
value=invoice_number
|
||||
)
|
||||
)
|
||||
try:
|
||||
event_type = request.POST["event_type"]
|
||||
except KeyError:
|
||||
return HttpResponseBadRequest("Missing required event_type parameter")
|
||||
|
||||
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
||||
try:
|
||||
obj_invoice = Invoice.objects.select_related('is_valid').get(id=invoice_number, course_id=course_id)
|
||||
except Invoice.DoesNotExist:
|
||||
return HttpResponseNotFound(_("Invoice number '{0}' does not exist.".format(invoice_number)))
|
||||
|
||||
if event_type == "invalidate":
|
||||
return invalidate_invoice(obj_invoice)
|
||||
else:
|
||||
return re_validate_invoice(obj_invoice)
|
||||
|
||||
|
||||
def invalidate_invoice(obj_invoice):
|
||||
"""
|
||||
This method invalidate the sale against the invoice number
|
||||
"""
|
||||
if not obj_invoice.is_valid:
|
||||
return HttpResponseBadRequest(_("The sale associated with this invoice has already been invalidated."))
|
||||
obj_invoice.is_valid = False
|
||||
obj_invoice.save()
|
||||
message = _('Invoice number {0} has been invalidated.').format(obj_invoice.id)
|
||||
return JsonResponse({'message': message})
|
||||
|
||||
|
||||
def re_validate_invoice(obj_invoice):
|
||||
"""
|
||||
This method re-validate the sale against the invoice number
|
||||
"""
|
||||
if obj_invoice.is_valid:
|
||||
return HttpResponseBadRequest(_("This invoice is already active."))
|
||||
|
||||
obj_invoice.is_valid = True
|
||||
obj_invoice.save()
|
||||
message = _('The registration codes for invoice {0} have been re-activated.').format(obj_invoice.id)
|
||||
return JsonResponse({'message': message})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
||||
@require_level('staff')
|
||||
@@ -635,7 +731,24 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=W06
|
||||
return instructor_analytics.csvs.create_csv_response("enrolled_profiles.csv", header, datarows)
|
||||
|
||||
|
||||
def save_registration_codes(request, course_id, generated_codes_list, group_name):
|
||||
@ensure_csrf_cookie
|
||||
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
||||
@require_level('staff')
|
||||
def get_coupon_codes(request, course_id): # pylint: disable=W0613
|
||||
"""
|
||||
Respond with csv which contains a summary of all Active Coupons.
|
||||
"""
|
||||
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
||||
active_coupons = Coupon.objects.filter(course_id=course_id, is_active=True)
|
||||
query_features = [
|
||||
'course_id', 'percentage_discount', 'code_redeemed_count', 'description'
|
||||
]
|
||||
coupons_list = instructor_analytics.basic.coupon_codes_features(query_features, active_coupons)
|
||||
header, data_rows = instructor_analytics.csvs.format_dictlist(coupons_list, query_features)
|
||||
return instructor_analytics.csvs.create_csv_response('Coupons.csv', header, data_rows)
|
||||
|
||||
|
||||
def save_registration_codes(request, course_id, generated_codes_list, invoice):
|
||||
"""
|
||||
recursive function that generate a new code every time and saves in the Course Registration Table
|
||||
if validation check passes
|
||||
@@ -645,17 +758,16 @@ def save_registration_codes(request, course_id, generated_codes_list, group_name
|
||||
# check if the generated code is in the Coupon Table
|
||||
matching_coupons = Coupon.objects.filter(code=code, is_active=True)
|
||||
if matching_coupons:
|
||||
return save_registration_codes(request, course_id, generated_codes_list, group_name)
|
||||
return save_registration_codes(request, course_id, generated_codes_list, invoice)
|
||||
|
||||
course_registration = CourseRegistrationCode(
|
||||
code=code, course_id=course_id.to_deprecated_string(),
|
||||
transaction_group_name=group_name, created_by=request.user
|
||||
code=code, course_id=course_id.to_deprecated_string(), created_by=request.user, invoice=invoice
|
||||
)
|
||||
try:
|
||||
course_registration.save()
|
||||
generated_codes_list.append(course_registration)
|
||||
except IntegrityError:
|
||||
return save_registration_codes(request, course_id, generated_codes_list, group_name)
|
||||
return save_registration_codes(request, course_id, generated_codes_list, invoice)
|
||||
|
||||
|
||||
def registration_codes_csv(file_name, codes_list, csv_type=None):
|
||||
@@ -667,7 +779,10 @@ def registration_codes_csv(file_name, codes_list, csv_type=None):
|
||||
:param csv_type:
|
||||
"""
|
||||
# csv headers
|
||||
query_features = ['code', 'course_id', 'transaction_group_name', 'created_by', 'redeemed_by']
|
||||
query_features = [
|
||||
'code', 'course_id', 'company_name', 'created_by',
|
||||
'redeemed_by', 'invoice_id', 'purchaser', 'customer_reference_number', 'internal_reference'
|
||||
]
|
||||
|
||||
registration_codes = instructor_analytics.basic.course_registration_features(query_features, codes_list, csv_type)
|
||||
header, data_rows = instructor_analytics.csvs.format_dictlist(registration_codes, query_features)
|
||||
@@ -679,7 +794,11 @@ def random_code_generator():
|
||||
generate a random alphanumeric code of length defined in
|
||||
REGISTRATION_CODE_LENGTH settings
|
||||
"""
|
||||
chars = string.ascii_uppercase + string.digits + string.ascii_lowercase
|
||||
chars = ''
|
||||
for char in string.ascii_uppercase + string.digits + string.ascii_lowercase:
|
||||
# removing vowel words and specific characters
|
||||
chars += char.strip('aAeEiIoOuU1l')
|
||||
|
||||
code_length = getattr(settings, 'REGISTRATION_CODE_LENGTH', 8)
|
||||
return string.join((random.choice(chars) for _ in range(code_length)), '')
|
||||
|
||||
@@ -695,11 +814,11 @@ def get_registration_codes(request, course_id): # pylint: disable=W0613
|
||||
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
||||
|
||||
#filter all the course registration codes
|
||||
registration_codes = CourseRegistrationCode.objects.filter(course_id=course_id).order_by('transaction_group_name')
|
||||
registration_codes = CourseRegistrationCode.objects.filter(course_id=course_id).order_by('invoice__company_name')
|
||||
|
||||
group_name = request.POST['download_transaction_group_name']
|
||||
if group_name:
|
||||
registration_codes = registration_codes.filter(transaction_group_name=group_name)
|
||||
company_name = request.POST['download_company_name']
|
||||
if company_name:
|
||||
registration_codes = registration_codes.filter(invoice__company_name=company_name)
|
||||
|
||||
csv_type = 'download'
|
||||
return registration_codes_csv("Registration_Codes.csv", registration_codes, csv_type)
|
||||
@@ -715,17 +834,86 @@ def generate_registration_codes(request, course_id):
|
||||
"""
|
||||
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
||||
course_registration_codes = []
|
||||
invoice_copy = False
|
||||
|
||||
# covert the course registration code number into integer
|
||||
try:
|
||||
course_code_number = int(request.POST['course_registration_code_number'])
|
||||
course_code_number = int(request.POST['total_registration_codes'])
|
||||
except ValueError:
|
||||
course_code_number = int(float(request.POST['course_registration_code_number']))
|
||||
course_code_number = int(float(request.POST['total_registration_codes']))
|
||||
|
||||
group_name = request.POST['transaction_group_name']
|
||||
company_name = request.POST['company_name']
|
||||
company_contact_name = request.POST['company_contact_name']
|
||||
company_contact_email = request.POST['company_contact_email']
|
||||
sale_price = request.POST['sale_price']
|
||||
recipient_name = request.POST['recipient_name']
|
||||
recipient_email = request.POST['recipient_email']
|
||||
address_line_1 = request.POST['address_line_1']
|
||||
address_line_2 = request.POST['address_line_2']
|
||||
address_line_3 = request.POST['address_line_3']
|
||||
city = request.POST['city']
|
||||
state = request.POST['state']
|
||||
zip_code = request.POST['zip']
|
||||
country = request.POST['country']
|
||||
internal_reference = request.POST['internal_reference']
|
||||
customer_reference_number = request.POST['customer_reference_number']
|
||||
recipient_list = [recipient_email]
|
||||
if request.POST.get('invoice', False):
|
||||
recipient_list.append(request.user.email)
|
||||
invoice_copy = True
|
||||
|
||||
UserPreference.set_preference(request.user, INVOICE_KEY, invoice_copy)
|
||||
sale_invoice = Invoice.objects.create(
|
||||
total_amount=sale_price, company_name=company_name, company_contact_email=company_contact_email,
|
||||
company_contact_name=company_contact_name, course_id=course_id, recipient_name=recipient_name,
|
||||
recipient_email=recipient_email, address_line_1=address_line_1, address_line_2=address_line_2,
|
||||
address_line_3=address_line_3, city=city, state=state, zip=zip_code, country=country,
|
||||
internal_reference=internal_reference, customer_reference_number=customer_reference_number
|
||||
)
|
||||
for _ in range(course_code_number): # pylint: disable=W0621
|
||||
save_registration_codes(request, course_id, course_registration_codes, group_name)
|
||||
save_registration_codes(request, course_id, course_registration_codes, sale_invoice)
|
||||
|
||||
site_name = microsite.get_value('SITE_NAME', 'localhost')
|
||||
course = get_course_by_id(course_id, depth=None)
|
||||
course_honor_mode = CourseMode.mode_for_course(course_id, 'honor')
|
||||
course_price = course_honor_mode.min_price
|
||||
quantity = course_code_number
|
||||
discount_price = (float(quantity * course_price) - float(sale_price))
|
||||
course_url = '{base_url}{course_about}'.format(
|
||||
base_url=request.META['HTTP_HOST'],
|
||||
course_about=reverse('about_course', kwargs={'course_id': course_id.to_deprecated_string()})
|
||||
)
|
||||
context = {
|
||||
'invoice': sale_invoice,
|
||||
'site_name': site_name,
|
||||
'course': course,
|
||||
'course_price': course_price,
|
||||
'discount_price': discount_price,
|
||||
'sale_price': sale_price,
|
||||
'quantity': quantity,
|
||||
'registration_codes': course_registration_codes,
|
||||
'course_url': course_url,
|
||||
}
|
||||
# composes registration codes invoice email
|
||||
subject = u'Invoice for {course_name}'.format(course_name=course.display_name)
|
||||
message = render_to_string('emails/registration_codes_sale_invoice.txt', context)
|
||||
from_address = microsite.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
|
||||
|
||||
#send_mail(subject, message, from_address, recipient_list, fail_silently=False)
|
||||
csv_file = StringIO.StringIO()
|
||||
csv_writer = csv.writer(csv_file)
|
||||
for registration_code in course_registration_codes:
|
||||
csv_writer.writerow([registration_code.code])
|
||||
|
||||
# send a unique email for each recipient, don't put all email addresses in a single email
|
||||
for recipient in recipient_list:
|
||||
email = EmailMessage()
|
||||
email.subject = subject
|
||||
email.body = message
|
||||
email.from_email = from_address
|
||||
email.to = [recipient]
|
||||
email.attach(u'RegistrationCodes.csv', csv_file.getvalue(), 'text/csv')
|
||||
email.send()
|
||||
|
||||
return registration_codes_csv("Registration_Codes.csv", course_registration_codes)
|
||||
|
||||
@@ -741,11 +929,11 @@ def active_registration_codes(request, course_id): # pylint: disable=W0613
|
||||
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
||||
|
||||
# find all the registration codes in this course
|
||||
registration_codes_list = CourseRegistrationCode.objects.filter(course_id=course_id).order_by('transaction_group_name')
|
||||
registration_codes_list = CourseRegistrationCode.objects.filter(course_id=course_id).order_by('invoice__company_name')
|
||||
|
||||
group_name = request.POST['active_transaction_group_name']
|
||||
if group_name:
|
||||
registration_codes_list = registration_codes_list.filter(transaction_group_name=group_name)
|
||||
company_name = request.POST['active_company_name']
|
||||
if company_name:
|
||||
registration_codes_list = registration_codes_list.filter(invoice__company_name=company_name)
|
||||
# find the redeemed registration codes if any exist in the db
|
||||
code_redemption_set = RegistrationCodeRedemption.objects.select_related('registration_code').filter(registration_code__course_id=course_id)
|
||||
if code_redemption_set.exists():
|
||||
@@ -768,17 +956,21 @@ def spent_registration_codes(request, course_id): # pylint: disable=W0613
|
||||
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
||||
|
||||
# find the redeemed registration codes if any exist in the db
|
||||
code_redemption_set = RegistrationCodeRedemption.objects.select_related('registration_code').filter(registration_code__course_id=course_id)
|
||||
code_redemption_set = RegistrationCodeRedemption.objects.select_related('registration_code').filter(
|
||||
registration_code__course_id=course_id
|
||||
)
|
||||
spent_codes_list = []
|
||||
if code_redemption_set.exists():
|
||||
redeemed_registration_codes = [code.registration_code.code for code in code_redemption_set]
|
||||
# filter the Registration Codes by course id and the redeemed codes and
|
||||
# you will get a list of all the spent(Redeemed) Registration Codes
|
||||
spent_codes_list = CourseRegistrationCode.objects.filter(course_id=course_id, code__in=redeemed_registration_codes).order_by('transaction_group_name')
|
||||
spent_codes_list = CourseRegistrationCode.objects.filter(
|
||||
course_id=course_id, code__in=redeemed_registration_codes
|
||||
).order_by('invoice__company_name')
|
||||
|
||||
group_name = request.POST['spent_transaction_group_name']
|
||||
if group_name:
|
||||
spent_codes_list = spent_codes_list.filter(transaction_group_name=group_name) # pylint: disable=E1103
|
||||
company_name = request.POST['spent_company_name']
|
||||
if company_name:
|
||||
spent_codes_list = spent_codes_list.filter(invoice__company_name=company_name) # pylint: disable=E1103
|
||||
|
||||
csv_type = 'spent'
|
||||
return registration_codes_csv("Spent_Registration_Codes.csv", spent_codes_list, csv_type)
|
||||
@@ -1371,6 +1563,20 @@ def proxy_legacy_analytics(request, course_id):
|
||||
)
|
||||
|
||||
|
||||
@require_POST
|
||||
def get_user_invoice_preference(request, course_id): # pylint: disable=W0613
|
||||
"""
|
||||
Gets invoice copy user's preferences.
|
||||
"""
|
||||
invoice_copy_preference = True
|
||||
if UserPreference.get_preference(request.user, INVOICE_KEY) is not None:
|
||||
invoice_copy_preference = UserPreference.get_preference(request.user, INVOICE_KEY) == 'True'
|
||||
|
||||
return JsonResponse({
|
||||
'invoice_copy': invoice_copy_preference
|
||||
})
|
||||
|
||||
|
||||
def _display_unit(unit):
|
||||
"""
|
||||
Gets string for displaying unit to user.
|
||||
|
||||
@@ -19,6 +19,12 @@ urlpatterns = patterns('', # nopep8
|
||||
'instructor.views.api.get_students_features', name="get_students_features"),
|
||||
url(r'^get_purchase_transaction(?P<csv>/csv)?$',
|
||||
'instructor.views.api.get_purchase_transaction', name="get_purchase_transaction"),
|
||||
url(r'^get_user_invoice_preference$',
|
||||
'instructor.views.api.get_user_invoice_preference', name="get_user_invoice_preference"),
|
||||
url(r'^get_sale_records(?P<csv>/csv)?$',
|
||||
'instructor.views.api.get_sale_records', name="get_sale_records"),
|
||||
url(r'^sale_validation_url$',
|
||||
'instructor.views.api.sale_validation', name="sale_validation"),
|
||||
url(r'^get_anon_ids$',
|
||||
'instructor.views.api.get_anon_ids', name="get_anon_ids"),
|
||||
url(r'^get_distribution$',
|
||||
@@ -68,6 +74,10 @@ urlpatterns = patterns('', # nopep8
|
||||
url(r'spent_registration_codes$',
|
||||
'instructor.views.api.spent_registration_codes', name="spent_registration_codes"),
|
||||
|
||||
# Coupon Codes..
|
||||
url(r'get_coupon_codes',
|
||||
'instructor.views.api.get_coupon_codes', name="get_coupon_codes"),
|
||||
|
||||
# spoc gradebook
|
||||
url(r'^gradebook$',
|
||||
'instructor.views.api.spoc_gradebook', name='spoc_gradebook'),
|
||||
|
||||
@@ -97,31 +97,8 @@ def update_coupon(request, course_id): # pylint: disable=W0613
|
||||
except ObjectDoesNotExist:
|
||||
return HttpResponseNotFound(_("coupon with the coupon id ({coupon_id}) DoesNotExist").format(coupon_id=coupon_id))
|
||||
|
||||
code = request.POST.get('code')
|
||||
filtered_coupons = Coupon.objects.filter(~Q(id=coupon_id), code=code, is_active=True)
|
||||
|
||||
if filtered_coupons:
|
||||
return HttpResponseNotFound(_("coupon with the coupon id ({coupon_id}) already exists").format(coupon_id=coupon_id))
|
||||
|
||||
# check if the coupon code is in the CourseRegistrationCode Table
|
||||
course_registration_code = CourseRegistrationCode.objects.filter(code=code)
|
||||
if course_registration_code:
|
||||
return HttpResponseNotFound(_(
|
||||
"The code ({code}) that you have tried to define is already in use as a registration code").format(code=code)
|
||||
)
|
||||
|
||||
description = request.POST.get('description')
|
||||
course_id = request.POST.get('course_id')
|
||||
try:
|
||||
discount = int(request.POST.get('discount'))
|
||||
except ValueError:
|
||||
return HttpResponseNotFound(_("Please Enter the Integer Value for Coupon Discount"))
|
||||
if discount > 100:
|
||||
return HttpResponseNotFound(_("Please Enter the Coupon Discount Value Less than or Equal to 100"))
|
||||
coupon.code = code
|
||||
coupon.description = description
|
||||
coupon.course_id = course_id
|
||||
coupon.percentage_discount = discount
|
||||
coupon.save()
|
||||
return HttpResponse(_("coupon with the coupon id ({coupon_id}) updated Successfully").format(coupon_id=coupon_id))
|
||||
|
||||
|
||||
@@ -156,15 +156,19 @@ def _section_e_commerce(course_key, access):
|
||||
'course_id': course_key.to_deprecated_string(),
|
||||
'ajax_remove_coupon_url': reverse('remove_coupon', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'ajax_get_coupon_info': reverse('get_coupon_info', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'get_user_invoice_preference_url': reverse('get_user_invoice_preference', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'sale_validation_url': reverse('sale_validation', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'ajax_update_coupon': reverse('update_coupon', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'ajax_add_coupon': reverse('add_coupon', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'get_purchase_transaction_url': reverse('get_purchase_transaction', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'get_sale_records_url': reverse('get_sale_records', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'instructor_url': reverse('instructor_dashboard', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'get_registration_code_csv_url': reverse('get_registration_codes', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'generate_registration_code_csv_url': reverse('generate_registration_codes', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'active_registration_code_csv_url': reverse('active_registration_codes', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'spent_registration_code_csv_url': reverse('spent_registration_codes', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'set_course_mode_url': reverse('set_course_mode_price', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'download_coupon_codes_url': reverse('get_coupon_codes', kwargs={'course_id': course_key.to_deprecated_string()}),
|
||||
'coupons': coupons,
|
||||
'total_amount': total_amount,
|
||||
'course_price': course_price
|
||||
|
||||
@@ -3,7 +3,7 @@ Student and course analytics.
|
||||
|
||||
Serve miscellaneous course and student data
|
||||
"""
|
||||
from shoppingcart.models import PaidCourseRegistration, CouponRedemption
|
||||
from shoppingcart.models import PaidCourseRegistration, CouponRedemption, Invoice, RegistrationCodeRedemption
|
||||
from django.contrib.auth.models import User
|
||||
import xmodule.graders as xmgraders
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
@@ -15,8 +15,58 @@ PROFILE_FEATURES = ('name', 'language', 'location', 'year_of_birth', 'gender',
|
||||
ORDER_ITEM_FEATURES = ('list_price', 'unit_cost', 'order_id')
|
||||
ORDER_FEATURES = ('purchase_time',)
|
||||
|
||||
SALE_FEATURES = ('total_amount', 'company_name', 'company_contact_name', 'company_contact_email', 'recipient_name',
|
||||
'recipient_email', 'customer_reference_number', 'internal_reference')
|
||||
|
||||
AVAILABLE_FEATURES = STUDENT_FEATURES + PROFILE_FEATURES
|
||||
COURSE_REGISTRATION_FEATURES = ('code', 'course_id', 'transaction_group_name', 'created_by')
|
||||
COURSE_REGISTRATION_FEATURES = ('code', 'course_id', 'created_by', 'created_at')
|
||||
COUPON_FEATURES = ('course_id', 'percentage_discount', 'description')
|
||||
|
||||
|
||||
def sale_record_features(course_id, features):
|
||||
"""
|
||||
Return list of sales features as dictionaries.
|
||||
|
||||
sales_records(course_id, ['company_name, total_codes', total_amount])
|
||||
would return [
|
||||
{'company_name': 'group_A', 'total_codes': '1', total_amount:'total_amount1 in decimal'.}
|
||||
{'company_name': 'group_B', 'total_codes': '2', total_amount:'total_amount2 in decimal'.}
|
||||
{'company_name': 'group_C', 'total_codes': '3', total_amount:'total_amount3 in decimal'.}
|
||||
]
|
||||
"""
|
||||
sales = Invoice.objects.filter(course_id=course_id)
|
||||
|
||||
def sale_records_info(sale, features):
|
||||
""" convert sales records to dictionary """
|
||||
|
||||
sale_features = [x for x in SALE_FEATURES if x in features]
|
||||
course_reg_features = [x for x in COURSE_REGISTRATION_FEATURES if x in features]
|
||||
|
||||
# Extracting sale information
|
||||
sale_dict = dict((feature, getattr(sale, feature))
|
||||
for feature in sale_features)
|
||||
|
||||
total_used_codes = RegistrationCodeRedemption.objects.filter(registration_code__in=sale.courseregistrationcode_set.all()).count()
|
||||
sale_dict.update({"invoice_number": getattr(sale, 'id')})
|
||||
sale_dict.update({"total_codes": sale.courseregistrationcode_set.all().count()})
|
||||
sale_dict.update({'total_used_codes': total_used_codes})
|
||||
|
||||
codes = list()
|
||||
for reg_code in sale.courseregistrationcode_set.all():
|
||||
codes.append(reg_code.code)
|
||||
|
||||
# Extracting registration code information
|
||||
obj_course_reg_code = sale.courseregistrationcode_set.all()[:1].get()
|
||||
course_reg_dict = dict((feature, getattr(obj_course_reg_code, feature))
|
||||
for feature in course_reg_features)
|
||||
|
||||
course_reg_dict['course_id'] = course_id.to_deprecated_string()
|
||||
course_reg_dict.update({'codes': ", ".join(codes)})
|
||||
sale_dict.update(dict(course_reg_dict.items()))
|
||||
|
||||
return sale_dict
|
||||
|
||||
return [sale_records_info(sale, features) for sale in sales]
|
||||
|
||||
|
||||
def purchase_transactions(course_id, features):
|
||||
@@ -100,6 +150,36 @@ def enrolled_students_features(course_id, features):
|
||||
return [extract_student(student, features) for student in students]
|
||||
|
||||
|
||||
def coupon_codes_features(features, coupons_list):
|
||||
"""
|
||||
Return list of Coupon Codes as dictionaries.
|
||||
|
||||
coupon_codes_features
|
||||
would return [
|
||||
{'course_id': 'edX/Open_DemoX/edx_demo_course,, 'discount': '213' ..... }
|
||||
{'course_id': 'edX/Open_DemoX/edx_demo_course,, 'discount': '234' ..... }
|
||||
]
|
||||
"""
|
||||
|
||||
def extract_coupon(coupon, features):
|
||||
""" convert coupon_codes to dictionary
|
||||
:param coupon_codes:
|
||||
:param features:
|
||||
"""
|
||||
coupon_features = [x for x in COUPON_FEATURES if x in features]
|
||||
|
||||
coupon_dict = dict((feature, getattr(coupon, feature)) for feature in coupon_features)
|
||||
coupon_dict['code_redeemed_count'] = coupon.couponredemption_set.all().count()
|
||||
|
||||
# we have to capture the redeemed_by value in the case of the downloading and spent registration
|
||||
# codes csv. In the case of active and generated registration codes the redeemed_by value will be None.
|
||||
# They have not been redeemed yet
|
||||
|
||||
coupon_dict['course_id'] = coupon_dict['course_id'].to_deprecated_string()
|
||||
return coupon_dict
|
||||
return [extract_coupon(coupon, features) for coupon in coupons_list]
|
||||
|
||||
|
||||
def course_registration_features(features, registration_codes, csv_type):
|
||||
"""
|
||||
Return list of Course Registration Codes as dictionaries.
|
||||
@@ -120,14 +200,24 @@ def course_registration_features(features, registration_codes, csv_type):
|
||||
registration_features = [x for x in COURSE_REGISTRATION_FEATURES if x in features]
|
||||
|
||||
course_registration_dict = dict((feature, getattr(registration_code, feature)) for feature in registration_features)
|
||||
course_registration_dict['company_name'] = None
|
||||
if registration_code.invoice:
|
||||
course_registration_dict['company_name'] = getattr(registration_code.invoice, 'company_name')
|
||||
course_registration_dict['redeemed_by'] = None
|
||||
if registration_code.invoice:
|
||||
sale_invoice = Invoice.objects.get(id=registration_code.invoice_id)
|
||||
course_registration_dict['invoice_id'] = sale_invoice.id
|
||||
course_registration_dict['purchaser'] = sale_invoice.recipient_name
|
||||
course_registration_dict['customer_reference_number'] = sale_invoice.customer_reference_number
|
||||
course_registration_dict['internal_reference'] = sale_invoice.internal_reference
|
||||
|
||||
# we have to capture the redeemed_by value in the case of the downloading and spent registration
|
||||
# codes csv. In the case of active and generated registration codes the redeemed_by value will be None.
|
||||
# They have not been redeemed yet
|
||||
if csv_type is not None:
|
||||
try:
|
||||
course_registration_dict['redeemed_by'] = getattr(registration_code.registrationcoderedemption_set.get(registration_code=registration_code), 'redeemed_by')
|
||||
redeemed_by = getattr(registration_code.registrationcoderedemption_set.get(registration_code=registration_code), 'redeemed_by')
|
||||
course_registration_dict['redeemed_by'] = getattr(redeemed_by, 'email')
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
|
||||
|
||||
@@ -4,11 +4,17 @@ Tests for instructor.basic
|
||||
|
||||
from django.test import TestCase
|
||||
from student.models import CourseEnrollment
|
||||
from django.core.urlresolvers import reverse
|
||||
from student.tests.factories import UserFactory
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from shoppingcart.models import CourseRegistrationCode, RegistrationCodeRedemption, Order
|
||||
from shoppingcart.models import CourseRegistrationCode, RegistrationCodeRedemption, Order, Invoice, Coupon
|
||||
|
||||
from instructor_analytics.basic import enrolled_students_features, course_registration_features, AVAILABLE_FEATURES, STUDENT_FEATURES, PROFILE_FEATURES
|
||||
from instructor_analytics.basic import (
|
||||
sale_record_features, enrolled_students_features, course_registration_features, coupon_codes_features,
|
||||
AVAILABLE_FEATURES, STUDENT_FEATURES, PROFILE_FEATURES
|
||||
)
|
||||
from courseware.tests.factories import InstructorFactory
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
class TestAnalyticsBasic(TestCase):
|
||||
@@ -19,6 +25,7 @@ class TestAnalyticsBasic(TestCase):
|
||||
self.users = tuple(UserFactory() for _ in xrange(30))
|
||||
self.ces = tuple(CourseEnrollment.enroll(user, self.course_key)
|
||||
for user in self.users)
|
||||
self.instructor = InstructorFactory(course_key=self.course_key)
|
||||
|
||||
def test_enrolled_students_features_username(self):
|
||||
self.assertIn('username', AVAILABLE_FEATURES)
|
||||
@@ -44,20 +51,89 @@ class TestAnalyticsBasic(TestCase):
|
||||
self.assertEqual(len(AVAILABLE_FEATURES), len(STUDENT_FEATURES + PROFILE_FEATURES))
|
||||
self.assertEqual(set(AVAILABLE_FEATURES), set(STUDENT_FEATURES + PROFILE_FEATURES))
|
||||
|
||||
def test_course_registration_features(self):
|
||||
query_features = ['code', 'course_id', 'transaction_group_name', 'created_by', 'redeemed_by']
|
||||
|
||||
class TestCourseSaleRecordsAnalyticsBasic(TestCase):
|
||||
""" Test basic course sale records analytics functions. """
|
||||
def setUp(self):
|
||||
"""
|
||||
Fixtures.
|
||||
"""
|
||||
self.course = CourseFactory.create()
|
||||
self.instructor = InstructorFactory(course_key=self.course.id)
|
||||
self.client.login(username=self.instructor.username, password='test')
|
||||
|
||||
def test_course_sale_features(self):
|
||||
|
||||
query_features = [
|
||||
'company_name', 'company_contact_name', 'company_contact_email', 'total_codes', 'total_used_codes',
|
||||
'total_amount', 'created_at', 'customer_reference_number', 'recipient_name', 'recipient_email',
|
||||
'created_by', 'internal_reference', 'invoice_number', 'codes', 'course_id'
|
||||
]
|
||||
|
||||
#create invoice
|
||||
sale_invoice = Invoice.objects.create(
|
||||
total_amount=1234.32, company_name='Test1', company_contact_name='TestName',
|
||||
company_contact_email='test@company.com', recipient_name='Testw_1', recipient_email='test2@test.com',
|
||||
customer_reference_number='2Fwe23S', internal_reference="ABC", course_id=self.course.id
|
||||
)
|
||||
for i in range(5):
|
||||
course_code = CourseRegistrationCode(
|
||||
code="test_code{}".format(i), course_id=self.course_key.to_deprecated_string(),
|
||||
transaction_group_name='TestName', created_by=self.users[0]
|
||||
code="test_code{}".format(i), course_id=self.course.id.to_deprecated_string(),
|
||||
created_by=self.instructor, invoice=sale_invoice
|
||||
)
|
||||
course_code.save()
|
||||
|
||||
order = Order(user=self.users[0], status='purchased')
|
||||
course_sale_records_list = sale_record_features(self.course.id, query_features)
|
||||
|
||||
for sale_record in course_sale_records_list:
|
||||
self.assertEqual(sale_record['total_amount'], sale_invoice.total_amount)
|
||||
self.assertEqual(sale_record['recipient_email'], sale_invoice.recipient_email)
|
||||
self.assertEqual(sale_record['recipient_name'], sale_invoice.recipient_name)
|
||||
self.assertEqual(sale_record['company_name'], sale_invoice.company_name)
|
||||
self.assertEqual(sale_record['company_contact_name'], sale_invoice.company_contact_name)
|
||||
self.assertEqual(sale_record['company_contact_email'], sale_invoice.company_contact_email)
|
||||
self.assertEqual(sale_record['internal_reference'], sale_invoice.internal_reference)
|
||||
self.assertEqual(sale_record['customer_reference_number'], sale_invoice.customer_reference_number)
|
||||
self.assertEqual(sale_record['invoice_number'], sale_invoice.id)
|
||||
self.assertEqual(sale_record['created_by'], self.instructor)
|
||||
self.assertEqual(sale_record['total_used_codes'], 0)
|
||||
self.assertEqual(sale_record['total_codes'], 5)
|
||||
|
||||
|
||||
class TestCourseRegistrationCodeAnalyticsBasic(TestCase):
|
||||
""" Test basic course registration codes analytics functions. """
|
||||
def setUp(self):
|
||||
"""
|
||||
Fixtures.
|
||||
"""
|
||||
self.course = CourseFactory.create()
|
||||
self.instructor = InstructorFactory(course_key=self.course.id)
|
||||
self.client.login(username=self.instructor.username, password='test')
|
||||
|
||||
url = reverse('generate_registration_codes',
|
||||
kwargs={'course_id': self.course.id.to_deprecated_string()})
|
||||
|
||||
data = {
|
||||
'total_registration_codes': 12, 'company_name': 'Test Group', 'sale_price': 122.45,
|
||||
'company_contact_name': 'TestName', 'company_contact_email': 'test@company.com', 'recipient_name': 'Test123',
|
||||
'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '',
|
||||
'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '',
|
||||
'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': ''
|
||||
}
|
||||
|
||||
response = self.client.post(url, data, **{'HTTP_HOST': 'localhost'})
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
|
||||
def test_course_registration_features(self):
|
||||
query_features = [
|
||||
'code', 'course_id', 'company_name', 'created_by',
|
||||
'redeemed_by', 'invoice_id', 'purchaser', 'customer_reference_number', 'internal_reference'
|
||||
]
|
||||
order = Order(user=self.instructor, status='purchased')
|
||||
order.save()
|
||||
|
||||
registration_code_redemption = RegistrationCodeRedemption(
|
||||
order=order, registration_code_id=1, redeemed_by=self.users[0]
|
||||
order=order, registration_code_id=1, redeemed_by=self.instructor
|
||||
)
|
||||
registration_code_redemption.save()
|
||||
registration_codes = CourseRegistrationCode.objects.all()
|
||||
@@ -71,6 +147,32 @@ class TestAnalyticsBasic(TestCase):
|
||||
[registration_code.course_id.to_deprecated_string() for registration_code in registration_codes]
|
||||
)
|
||||
self.assertIn(
|
||||
course_registration['transaction_group_name'],
|
||||
[registration_code.transaction_group_name for registration_code in registration_codes]
|
||||
course_registration['company_name'],
|
||||
[getattr(registration_code.invoice, 'company_name') for registration_code in registration_codes]
|
||||
)
|
||||
self.assertIn(
|
||||
course_registration['invoice_id'],
|
||||
[registration_code.invoice_id for registration_code in registration_codes]
|
||||
)
|
||||
|
||||
def test_coupon_codes_features(self):
|
||||
query_features = [
|
||||
'course_id', 'percentage_discount', 'code_redeemed_count', 'description'
|
||||
]
|
||||
for i in range(10):
|
||||
coupon = Coupon(
|
||||
code='test_code{0}'.format(i), description='test_description', course_id=self.course.id,
|
||||
percentage_discount='{0}'.format(i), created_by=self.instructor, is_active=True
|
||||
)
|
||||
coupon.save()
|
||||
active_coupons = Coupon.objects.filter(course_id=self.course.id, is_active=True)
|
||||
active_coupons_list = coupon_codes_features(query_features, active_coupons)
|
||||
self.assertEqual(len(active_coupons_list), len(active_coupons))
|
||||
for active_coupon in active_coupons_list:
|
||||
self.assertEqual(set(active_coupon.keys()), set(query_features))
|
||||
self.assertIn(active_coupon['percentage_discount'], [coupon.percentage_discount for coupon in active_coupons])
|
||||
self.assertIn(active_coupon['description'], [coupon.description for coupon in active_coupons])
|
||||
self.assertIn(
|
||||
active_coupon['course_id'],
|
||||
[coupon.course_id.to_deprecated_string() for coupon in active_coupons]
|
||||
)
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'Invoice'
|
||||
db.create_table('shoppingcart_invoice', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('total_amount', self.gf('django.db.models.fields.FloatField')()),
|
||||
('purchaser_name', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)),
|
||||
('purchaser_contact', self.gf('django.db.models.fields.CharField')(max_length=255)),
|
||||
('purchaser_email', self.gf('django.db.models.fields.CharField')(max_length=255)),
|
||||
('tax_id', self.gf('django.db.models.fields.CharField')(max_length=64, null=True)),
|
||||
('reference', self.gf('django.db.models.fields.CharField')(max_length=255, null=True)),
|
||||
))
|
||||
db.send_create_signal('shoppingcart', ['Invoice'])
|
||||
|
||||
# Adding field 'CourseRegistrationCode.invoice'
|
||||
db.add_column('shoppingcart_courseregistrationcode', 'invoice',
|
||||
self.gf('django.db.models.fields.related.ForeignKey')(to=orm['shoppingcart.Invoice'], null=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'Invoice'
|
||||
db.delete_table('shoppingcart_invoice')
|
||||
|
||||
# Deleting field 'CourseRegistrationCode.invoice'
|
||||
db.delete_column('shoppingcart_courseregistrationcode', 'invoice_id')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'shoppingcart.certificateitem': {
|
||||
'Meta': {'object_name': 'CertificateItem', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_enrollment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['student.CourseEnrollment']"}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.coupon': {
|
||||
'Meta': {'object_name': 'Coupon'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 6, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'percentage_discount': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||
},
|
||||
'shoppingcart.couponredemption': {
|
||||
'Meta': {'object_name': 'CouponRedemption'},
|
||||
'coupon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Coupon']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.courseregistrationcode': {
|
||||
'Meta': {'object_name': 'CourseRegistrationCode'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 6, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_by_user'", 'to': "orm['auth.User']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'invoice': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Invoice']", 'null': 'True'}),
|
||||
'transaction_group_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'shoppingcart.invoice': {
|
||||
'Meta': {'object_name': 'Invoice'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'purchaser_contact': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'purchaser_email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'purchaser_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'reference': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'tax_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||
'total_amount': ('django.db.models.fields.FloatField', [], {})
|
||||
},
|
||||
'shoppingcart.order': {
|
||||
'Meta': {'object_name': 'Order'},
|
||||
'bill_to_cardtype': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
|
||||
'bill_to_ccnum': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_city': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_country': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_first': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_last': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_postalcode': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'bill_to_state': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_street1': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'bill_to_street2': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'processor_reply_dump': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'purchase_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'refunded_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.orderitem': {
|
||||
'Meta': {'object_name': 'OrderItem'},
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'fulfilled_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'line_desc': ('django.db.models.fields.CharField', [], {'default': "'Misc. Item'", 'max_length': '1024'}),
|
||||
'list_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'qty': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
|
||||
'refund_requested_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'report_comments': ('django.db.models.fields.TextField', [], {'default': "''"}),
|
||||
'service_fee': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32', 'db_index': 'True'}),
|
||||
'unit_cost': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.paidcourseregistration': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistration', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'default': "'honor'", 'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.paidcourseregistrationannotation': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistrationAnnotation'},
|
||||
'annotation': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.registrationcoderedemption': {
|
||||
'Meta': {'object_name': 'RegistrationCodeRedemption'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'redeemed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 6, 0, 0)', 'null': 'True'}),
|
||||
'redeemed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'registration_code': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.CourseRegistrationCode']"})
|
||||
},
|
||||
'student.courseenrollment': {
|
||||
'Meta': {'ordering': "('user', 'course_id')", 'unique_together': "(('user', 'course_id'),)", 'object_name': 'CourseEnrollment'},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'mode': ('django.db.models.fields.CharField', [], {'default': "'honor'", 'max_length': '100'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['shoppingcart']
|
||||
@@ -0,0 +1,252 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting field 'CourseRegistrationCode.transaction_group_name'
|
||||
db.delete_column('shoppingcart_courseregistrationcode', 'transaction_group_name')
|
||||
|
||||
# Deleting field 'Invoice.purchaser_contact'
|
||||
db.delete_column('shoppingcart_invoice', 'purchaser_contact')
|
||||
|
||||
# Deleting field 'Invoice.purchaser_email'
|
||||
db.delete_column('shoppingcart_invoice', 'purchaser_email')
|
||||
|
||||
# Deleting field 'Invoice.reference'
|
||||
db.delete_column('shoppingcart_invoice', 'reference')
|
||||
|
||||
# Deleting field 'Invoice.purchaser_name'
|
||||
db.delete_column('shoppingcart_invoice', 'purchaser_name')
|
||||
|
||||
# Adding field 'Invoice.company_name'
|
||||
db.add_column('shoppingcart_invoice', 'company_name',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.course_id'
|
||||
db.add_column('shoppingcart_invoice', 'course_id',
|
||||
self.gf('xmodule_django.models.CourseKeyField')(max_length=255, db_index=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.company_contact_name'
|
||||
db.add_column('shoppingcart_invoice', 'company_contact_name',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.company_contact_email'
|
||||
db.add_column('shoppingcart_invoice', 'company_contact_email',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.company_reference'
|
||||
db.add_column('shoppingcart_invoice', 'company_reference',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.internal_reference'
|
||||
db.add_column('shoppingcart_invoice', 'internal_reference',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding field 'CourseRegistrationCode.transaction_group_name'
|
||||
db.add_column('shoppingcart_courseregistrationcode', 'transaction_group_name',
|
||||
self.gf('django.db.models.fields.CharField')(blank=True, max_length=255, null=True, db_index=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.purchaser_contact'
|
||||
db.add_column('shoppingcart_invoice', 'purchaser_contact',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.purchaser_email'
|
||||
db.add_column('shoppingcart_invoice', 'purchaser_email',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.reference'
|
||||
db.add_column('shoppingcart_invoice', 'reference',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.purchaser_name'
|
||||
db.add_column('shoppingcart_invoice', 'purchaser_name',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255, db_index=True),
|
||||
keep_default=False)
|
||||
|
||||
# Deleting field 'Invoice.company_name'
|
||||
db.delete_column('shoppingcart_invoice', 'company_name')
|
||||
|
||||
# Deleting field 'Invoice.course_id'
|
||||
db.delete_column('shoppingcart_invoice', 'course_id')
|
||||
|
||||
# Deleting field 'Invoice.company_contact_name'
|
||||
db.delete_column('shoppingcart_invoice', 'company_contact_name')
|
||||
|
||||
# Deleting field 'Invoice.company_contact_email'
|
||||
db.delete_column('shoppingcart_invoice', 'company_contact_email')
|
||||
|
||||
# Deleting field 'Invoice.company_reference'
|
||||
db.delete_column('shoppingcart_invoice', 'company_reference')
|
||||
|
||||
# Deleting field 'Invoice.internal_reference'
|
||||
db.delete_column('shoppingcart_invoice', 'internal_reference')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'shoppingcart.certificateitem': {
|
||||
'Meta': {'object_name': 'CertificateItem', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_enrollment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['student.CourseEnrollment']"}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.coupon': {
|
||||
'Meta': {'object_name': 'Coupon'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 13, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'percentage_discount': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||
},
|
||||
'shoppingcart.couponredemption': {
|
||||
'Meta': {'object_name': 'CouponRedemption'},
|
||||
'coupon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Coupon']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.courseregistrationcode': {
|
||||
'Meta': {'object_name': 'CourseRegistrationCode'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 13, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_by_user'", 'to': "orm['auth.User']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'invoice': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Invoice']", 'null': 'True'})
|
||||
},
|
||||
'shoppingcart.invoice': {
|
||||
'Meta': {'object_name': 'Invoice'},
|
||||
'company_contact_email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'company_contact_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'company_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'company_reference': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'internal_reference': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'tax_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||
'total_amount': ('django.db.models.fields.FloatField', [], {})
|
||||
},
|
||||
'shoppingcart.order': {
|
||||
'Meta': {'object_name': 'Order'},
|
||||
'bill_to_cardtype': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
|
||||
'bill_to_ccnum': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_city': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_country': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_first': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_last': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_postalcode': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'bill_to_state': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_street1': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'bill_to_street2': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'processor_reply_dump': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'purchase_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'refunded_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.orderitem': {
|
||||
'Meta': {'object_name': 'OrderItem'},
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'fulfilled_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'line_desc': ('django.db.models.fields.CharField', [], {'default': "'Misc. Item'", 'max_length': '1024'}),
|
||||
'list_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'qty': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
|
||||
'refund_requested_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'report_comments': ('django.db.models.fields.TextField', [], {'default': "''"}),
|
||||
'service_fee': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32', 'db_index': 'True'}),
|
||||
'unit_cost': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.paidcourseregistration': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistration', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'default': "'honor'", 'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.paidcourseregistrationannotation': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistrationAnnotation'},
|
||||
'annotation': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.registrationcoderedemption': {
|
||||
'Meta': {'object_name': 'RegistrationCodeRedemption'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'redeemed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 13, 0, 0)', 'null': 'True'}),
|
||||
'redeemed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'registration_code': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.CourseRegistrationCode']"})
|
||||
},
|
||||
'student.courseenrollment': {
|
||||
'Meta': {'ordering': "('user', 'course_id')", 'unique_together': "(('user', 'course_id'),)", 'object_name': 'CourseEnrollment'},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'mode': ('django.db.models.fields.CharField', [], {'default': "'honor'", 'max_length': '100'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['shoppingcart']
|
||||
@@ -0,0 +1,173 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding field 'Invoice.is_valid'
|
||||
db.add_column('shoppingcart_invoice', 'is_valid',
|
||||
self.gf('django.db.models.fields.BooleanField')(default=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting field 'Invoice.is_valid'
|
||||
db.delete_column('shoppingcart_invoice', 'is_valid')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'shoppingcart.certificateitem': {
|
||||
'Meta': {'object_name': 'CertificateItem', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_enrollment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['student.CourseEnrollment']"}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.coupon': {
|
||||
'Meta': {'object_name': 'Coupon'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 20, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'percentage_discount': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||
},
|
||||
'shoppingcart.couponredemption': {
|
||||
'Meta': {'object_name': 'CouponRedemption'},
|
||||
'coupon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Coupon']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.courseregistrationcode': {
|
||||
'Meta': {'object_name': 'CourseRegistrationCode'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 20, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_by_user'", 'to': "orm['auth.User']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'invoice': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Invoice']", 'null': 'True'})
|
||||
},
|
||||
'shoppingcart.invoice': {
|
||||
'Meta': {'object_name': 'Invoice'},
|
||||
'company_contact_email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'company_contact_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'company_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'company_reference': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'internal_reference': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'is_valid': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'tax_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||
'total_amount': ('django.db.models.fields.FloatField', [], {})
|
||||
},
|
||||
'shoppingcart.order': {
|
||||
'Meta': {'object_name': 'Order'},
|
||||
'bill_to_cardtype': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
|
||||
'bill_to_ccnum': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_city': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_country': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_first': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_last': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_postalcode': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'bill_to_state': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_street1': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'bill_to_street2': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'processor_reply_dump': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'purchase_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'refunded_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.orderitem': {
|
||||
'Meta': {'object_name': 'OrderItem'},
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'fulfilled_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'line_desc': ('django.db.models.fields.CharField', [], {'default': "'Misc. Item'", 'max_length': '1024'}),
|
||||
'list_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'qty': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
|
||||
'refund_requested_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'report_comments': ('django.db.models.fields.TextField', [], {'default': "''"}),
|
||||
'service_fee': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32', 'db_index': 'True'}),
|
||||
'unit_cost': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.paidcourseregistration': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistration', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'default': "'honor'", 'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.paidcourseregistrationannotation': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistrationAnnotation'},
|
||||
'annotation': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.registrationcoderedemption': {
|
||||
'Meta': {'object_name': 'RegistrationCodeRedemption'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'redeemed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 20, 0, 0)', 'null': 'True'}),
|
||||
'redeemed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'registration_code': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.CourseRegistrationCode']"})
|
||||
},
|
||||
'student.courseenrollment': {
|
||||
'Meta': {'ordering': "('user', 'course_id')", 'unique_together': "(('user', 'course_id'),)", 'object_name': 'CourseEnrollment'},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'mode': ('django.db.models.fields.CharField', [], {'default': "'honor'", 'max_length': '100'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['shoppingcart']
|
||||
@@ -0,0 +1,244 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting field 'Invoice.tax_id'
|
||||
db.delete_column('shoppingcart_invoice', 'tax_id')
|
||||
|
||||
# Adding field 'Invoice.address_line_1'
|
||||
db.add_column('shoppingcart_invoice', 'address_line_1',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.address_line_2'
|
||||
db.add_column('shoppingcart_invoice', 'address_line_2',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.address_line_3'
|
||||
db.add_column('shoppingcart_invoice', 'address_line_3',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.city'
|
||||
db.add_column('shoppingcart_invoice', 'city',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.state'
|
||||
db.add_column('shoppingcart_invoice', 'state',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.zip'
|
||||
db.add_column('shoppingcart_invoice', 'zip',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=15, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.country'
|
||||
db.add_column('shoppingcart_invoice', 'country',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=64, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.purchase_order_number'
|
||||
db.add_column('shoppingcart_invoice', 'purchase_order_number',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=63, null=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding field 'Invoice.tax_id'
|
||||
db.add_column('shoppingcart_invoice', 'tax_id',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=64, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Deleting field 'Invoice.address_line_1'
|
||||
db.delete_column('shoppingcart_invoice', 'address_line_1')
|
||||
|
||||
# Deleting field 'Invoice.address_line_2'
|
||||
db.delete_column('shoppingcart_invoice', 'address_line_2')
|
||||
|
||||
# Deleting field 'Invoice.address_line_3'
|
||||
db.delete_column('shoppingcart_invoice', 'address_line_3')
|
||||
|
||||
# Deleting field 'Invoice.city'
|
||||
db.delete_column('shoppingcart_invoice', 'city')
|
||||
|
||||
# Deleting field 'Invoice.state'
|
||||
db.delete_column('shoppingcart_invoice', 'state')
|
||||
|
||||
# Deleting field 'Invoice.zip'
|
||||
db.delete_column('shoppingcart_invoice', 'zip')
|
||||
|
||||
# Deleting field 'Invoice.country'
|
||||
db.delete_column('shoppingcart_invoice', 'country')
|
||||
|
||||
# Deleting field 'Invoice.purchase_order_number'
|
||||
db.delete_column('shoppingcart_invoice', 'purchase_order_number')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'shoppingcart.certificateitem': {
|
||||
'Meta': {'object_name': 'CertificateItem', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_enrollment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['student.CourseEnrollment']"}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.coupon': {
|
||||
'Meta': {'object_name': 'Coupon'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 27, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'percentage_discount': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||
},
|
||||
'shoppingcart.couponredemption': {
|
||||
'Meta': {'object_name': 'CouponRedemption'},
|
||||
'coupon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Coupon']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.courseregistrationcode': {
|
||||
'Meta': {'object_name': 'CourseRegistrationCode'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 27, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_by_user'", 'to': "orm['auth.User']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'invoice': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Invoice']", 'null': 'True'})
|
||||
},
|
||||
'shoppingcart.invoice': {
|
||||
'Meta': {'object_name': 'Invoice'},
|
||||
'address_line_1': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'address_line_2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'address_line_3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'company_contact_email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'company_contact_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'company_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'company_reference': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'country': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'internal_reference': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'is_valid': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'purchase_order_number': ('django.db.models.fields.CharField', [], {'max_length': '63', 'null': 'True'}),
|
||||
'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'total_amount': ('django.db.models.fields.FloatField', [], {}),
|
||||
'zip': ('django.db.models.fields.CharField', [], {'max_length': '15', 'null': 'True'})
|
||||
},
|
||||
'shoppingcart.order': {
|
||||
'Meta': {'object_name': 'Order'},
|
||||
'bill_to_cardtype': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
|
||||
'bill_to_ccnum': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_city': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_country': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_first': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_last': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_postalcode': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'bill_to_state': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_street1': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'bill_to_street2': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'processor_reply_dump': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'purchase_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'refunded_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.orderitem': {
|
||||
'Meta': {'object_name': 'OrderItem'},
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'fulfilled_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'line_desc': ('django.db.models.fields.CharField', [], {'default': "'Misc. Item'", 'max_length': '1024'}),
|
||||
'list_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'qty': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
|
||||
'refund_requested_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'report_comments': ('django.db.models.fields.TextField', [], {'default': "''"}),
|
||||
'service_fee': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32', 'db_index': 'True'}),
|
||||
'unit_cost': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.paidcourseregistration': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistration', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'default': "'honor'", 'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.paidcourseregistrationannotation': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistrationAnnotation'},
|
||||
'annotation': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.registrationcoderedemption': {
|
||||
'Meta': {'object_name': 'RegistrationCodeRedemption'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'redeemed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 27, 0, 0)', 'null': 'True'}),
|
||||
'redeemed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'registration_code': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.CourseRegistrationCode']"})
|
||||
},
|
||||
'student.courseenrollment': {
|
||||
'Meta': {'ordering': "('user', 'course_id')", 'unique_together': "(('user', 'course_id'),)", 'object_name': 'CourseEnrollment'},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'mode': ('django.db.models.fields.CharField', [], {'default': "'honor'", 'max_length': '100'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['shoppingcart']
|
||||
@@ -0,0 +1,229 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting field 'Invoice.purchase_order_number'
|
||||
db.delete_column('shoppingcart_invoice', 'purchase_order_number')
|
||||
|
||||
# Deleting field 'Invoice.company_contact_name'
|
||||
db.delete_column('shoppingcart_invoice', 'company_contact_name')
|
||||
|
||||
# Deleting field 'Invoice.company_contact_email'
|
||||
db.delete_column('shoppingcart_invoice', 'company_contact_email')
|
||||
|
||||
# Adding field 'Invoice.company_email'
|
||||
db.add_column('shoppingcart_invoice', 'company_email',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.recipient_name'
|
||||
db.add_column('shoppingcart_invoice', 'recipient_name',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.recipient_email'
|
||||
db.add_column('shoppingcart_invoice', 'recipient_email',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.customer_reference_number'
|
||||
db.add_column('shoppingcart_invoice', 'customer_reference_number',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=63, null=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding field 'Invoice.purchase_order_number'
|
||||
db.add_column('shoppingcart_invoice', 'purchase_order_number',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=63, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.company_contact_name'
|
||||
db.add_column('shoppingcart_invoice', 'company_contact_name',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.company_contact_email'
|
||||
db.add_column('shoppingcart_invoice', 'company_contact_email',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Deleting field 'Invoice.company_email'
|
||||
db.delete_column('shoppingcart_invoice', 'company_email')
|
||||
|
||||
# Deleting field 'Invoice.recipient_name'
|
||||
db.delete_column('shoppingcart_invoice', 'recipient_name')
|
||||
|
||||
# Deleting field 'Invoice.recipient_email'
|
||||
db.delete_column('shoppingcart_invoice', 'recipient_email')
|
||||
|
||||
# Deleting field 'Invoice.customer_reference_number'
|
||||
db.delete_column('shoppingcart_invoice', 'customer_reference_number')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'shoppingcart.certificateitem': {
|
||||
'Meta': {'object_name': 'CertificateItem', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_enrollment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['student.CourseEnrollment']"}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.coupon': {
|
||||
'Meta': {'object_name': 'Coupon'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 28, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'percentage_discount': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||
},
|
||||
'shoppingcart.couponredemption': {
|
||||
'Meta': {'object_name': 'CouponRedemption'},
|
||||
'coupon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Coupon']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.courseregistrationcode': {
|
||||
'Meta': {'object_name': 'CourseRegistrationCode'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 28, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_by_user'", 'to': "orm['auth.User']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'invoice': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Invoice']", 'null': 'True'})
|
||||
},
|
||||
'shoppingcart.invoice': {
|
||||
'Meta': {'object_name': 'Invoice'},
|
||||
'address_line_1': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'address_line_2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'address_line_3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'company_email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'company_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'company_reference': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'country': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'customer_reference_number': ('django.db.models.fields.CharField', [], {'max_length': '63', 'null': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'internal_reference': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'is_valid': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'recipient_email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'recipient_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'total_amount': ('django.db.models.fields.FloatField', [], {}),
|
||||
'zip': ('django.db.models.fields.CharField', [], {'max_length': '15', 'null': 'True'})
|
||||
},
|
||||
'shoppingcart.order': {
|
||||
'Meta': {'object_name': 'Order'},
|
||||
'bill_to_cardtype': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
|
||||
'bill_to_ccnum': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_city': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_country': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_first': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_last': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_postalcode': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'bill_to_state': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_street1': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'bill_to_street2': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'processor_reply_dump': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'purchase_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'refunded_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.orderitem': {
|
||||
'Meta': {'object_name': 'OrderItem'},
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'fulfilled_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'line_desc': ('django.db.models.fields.CharField', [], {'default': "'Misc. Item'", 'max_length': '1024'}),
|
||||
'list_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'qty': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
|
||||
'refund_requested_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'report_comments': ('django.db.models.fields.TextField', [], {'default': "''"}),
|
||||
'service_fee': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32', 'db_index': 'True'}),
|
||||
'unit_cost': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.paidcourseregistration': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistration', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'default': "'honor'", 'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.paidcourseregistrationannotation': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistrationAnnotation'},
|
||||
'annotation': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.registrationcoderedemption': {
|
||||
'Meta': {'object_name': 'RegistrationCodeRedemption'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'redeemed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 28, 0, 0)', 'null': 'True'}),
|
||||
'redeemed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'registration_code': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.CourseRegistrationCode']"})
|
||||
},
|
||||
'student.courseenrollment': {
|
||||
'Meta': {'ordering': "('user', 'course_id')", 'unique_together': "(('user', 'course_id'),)", 'object_name': 'CourseEnrollment'},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'mode': ('django.db.models.fields.CharField', [], {'default': "'honor'", 'max_length': '100'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['shoppingcart']
|
||||
@@ -0,0 +1,205 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting field 'Invoice.company_email'
|
||||
db.delete_column('shoppingcart_invoice', 'company_email')
|
||||
|
||||
# Deleting field 'Invoice.company_reference'
|
||||
db.delete_column('shoppingcart_invoice', 'company_reference')
|
||||
|
||||
# Adding field 'Invoice.company_contact_name'
|
||||
db.add_column('shoppingcart_invoice', 'company_contact_name',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.company_contact_email'
|
||||
db.add_column('shoppingcart_invoice', 'company_contact_email',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding field 'Invoice.company_email'
|
||||
db.add_column('shoppingcart_invoice', 'company_email',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=255),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Invoice.company_reference'
|
||||
db.add_column('shoppingcart_invoice', 'company_reference',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Deleting field 'Invoice.company_contact_name'
|
||||
db.delete_column('shoppingcart_invoice', 'company_contact_name')
|
||||
|
||||
# Deleting field 'Invoice.company_contact_email'
|
||||
db.delete_column('shoppingcart_invoice', 'company_contact_email')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'shoppingcart.certificateitem': {
|
||||
'Meta': {'object_name': 'CertificateItem', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_enrollment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['student.CourseEnrollment']"}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.coupon': {
|
||||
'Meta': {'object_name': 'Coupon'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 29, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'percentage_discount': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||
},
|
||||
'shoppingcart.couponredemption': {
|
||||
'Meta': {'object_name': 'CouponRedemption'},
|
||||
'coupon': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Coupon']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.courseregistrationcode': {
|
||||
'Meta': {'object_name': 'CourseRegistrationCode'},
|
||||
'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 29, 0, 0)'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_by_user'", 'to': "orm['auth.User']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'invoice': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Invoice']", 'null': 'True'})
|
||||
},
|
||||
'shoppingcart.invoice': {
|
||||
'Meta': {'object_name': 'Invoice'},
|
||||
'address_line_1': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'address_line_2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'address_line_3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'company_contact_email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'company_contact_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'company_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'country': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'customer_reference_number': ('django.db.models.fields.CharField', [], {'max_length': '63', 'null': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'internal_reference': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'is_valid': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'recipient_email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'recipient_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'total_amount': ('django.db.models.fields.FloatField', [], {}),
|
||||
'zip': ('django.db.models.fields.CharField', [], {'max_length': '15', 'null': 'True'})
|
||||
},
|
||||
'shoppingcart.order': {
|
||||
'Meta': {'object_name': 'Order'},
|
||||
'bill_to_cardtype': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
|
||||
'bill_to_ccnum': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_city': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_country': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_first': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_last': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'bill_to_postalcode': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'bill_to_state': ('django.db.models.fields.CharField', [], {'max_length': '8', 'blank': 'True'}),
|
||||
'bill_to_street1': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'bill_to_street2': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'processor_reply_dump': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'purchase_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'refunded_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.orderitem': {
|
||||
'Meta': {'object_name': 'OrderItem'},
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'fulfilled_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'line_desc': ('django.db.models.fields.CharField', [], {'default': "'Misc. Item'", 'max_length': '1024'}),
|
||||
'list_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'qty': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
|
||||
'refund_requested_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
|
||||
'report_comments': ('django.db.models.fields.TextField', [], {'default': "''"}),
|
||||
'service_fee': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'cart'", 'max_length': '32', 'db_index': 'True'}),
|
||||
'unit_cost': ('django.db.models.fields.DecimalField', [], {'default': '0.0', 'max_digits': '30', 'decimal_places': '2'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'shoppingcart.paidcourseregistration': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistration', '_ormbases': ['shoppingcart.OrderItem']},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '128', 'db_index': 'True'}),
|
||||
'mode': ('django.db.models.fields.SlugField', [], {'default': "'honor'", 'max_length': '50'}),
|
||||
'orderitem_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['shoppingcart.OrderItem']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.paidcourseregistrationannotation': {
|
||||
'Meta': {'object_name': 'PaidCourseRegistrationAnnotation'},
|
||||
'annotation': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'shoppingcart.registrationcoderedemption': {
|
||||
'Meta': {'object_name': 'RegistrationCodeRedemption'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.Order']"}),
|
||||
'redeemed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 8, 29, 0, 0)', 'null': 'True'}),
|
||||
'redeemed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'registration_code': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['shoppingcart.CourseRegistrationCode']"})
|
||||
},
|
||||
'student.courseenrollment': {
|
||||
'Meta': {'ordering': "('user', 'course_id')", 'unique_together': "(('user', 'course_id'),)", 'object_name': 'CourseEnrollment'},
|
||||
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'mode': ('django.db.models.fields.CharField', [], {'default': "'honor'", 'max_length': '100'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['shoppingcart']
|
||||
@@ -317,6 +317,31 @@ class OrderItem(models.Model):
|
||||
return ''
|
||||
|
||||
|
||||
class Invoice(models.Model):
|
||||
"""
|
||||
This table capture all the information needed to support "invoicing"
|
||||
which is when a user wants to purchase Registration Codes,
|
||||
but will not do so via a Credit Card transaction.
|
||||
"""
|
||||
company_name = models.CharField(max_length=255, db_index=True)
|
||||
company_contact_name = models.CharField(max_length=255)
|
||||
company_contact_email = models.CharField(max_length=255)
|
||||
recipient_name = models.CharField(max_length=255)
|
||||
recipient_email = models.CharField(max_length=255)
|
||||
address_line_1 = models.CharField(max_length=255)
|
||||
address_line_2 = models.CharField(max_length=255, null=True)
|
||||
address_line_3 = models.CharField(max_length=255, null=True)
|
||||
city = models.CharField(max_length=255, null=True)
|
||||
state = models.CharField(max_length=255, null=True)
|
||||
zip = models.CharField(max_length=15, null=True)
|
||||
country = models.CharField(max_length=64, null=True)
|
||||
course_id = CourseKeyField(max_length=255, db_index=True)
|
||||
total_amount = models.FloatField()
|
||||
internal_reference = models.CharField(max_length=255, null=True)
|
||||
customer_reference_number = models.CharField(max_length=63, null=True)
|
||||
is_valid = models.BooleanField(default=True)
|
||||
|
||||
|
||||
class CourseRegistrationCode(models.Model):
|
||||
"""
|
||||
This table contains registration codes
|
||||
@@ -324,9 +349,9 @@ class CourseRegistrationCode(models.Model):
|
||||
"""
|
||||
code = models.CharField(max_length=32, db_index=True, unique=True)
|
||||
course_id = CourseKeyField(max_length=255, db_index=True)
|
||||
transaction_group_name = models.CharField(max_length=255, db_index=True, null=True, blank=True)
|
||||
created_by = models.ForeignKey(User, related_name='created_by_user')
|
||||
created_at = models.DateTimeField(default=datetime.now(pytz.utc))
|
||||
invoice = models.ForeignKey(Invoice, null=True)
|
||||
|
||||
@classmethod
|
||||
@transaction.commit_on_success
|
||||
@@ -574,7 +599,7 @@ class PaidCourseRegistration(OrderItem):
|
||||
Generates instructions when the user has purchased a PaidCourseRegistration.
|
||||
Basically tells the user to visit the dashboard to see their new classes
|
||||
"""
|
||||
notification = (_('Please visit your <a href="{dashboard_link}">dashboard</a> to see your new enrollments.')
|
||||
notification = (_('Please visit your <a href="{dashboard_link}">dashboard</a> to see your new course.')
|
||||
.format(dashboard_link=reverse('dashboard')))
|
||||
|
||||
return self.pk_with_subclass, set([notification])
|
||||
|
||||
@@ -96,8 +96,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
|
||||
"""
|
||||
add dummy registration code into models
|
||||
"""
|
||||
course_reg_code = CourseRegistrationCode(code=self.reg_code, course_id=course_key,
|
||||
transaction_group_name='A', created_by=self.user)
|
||||
course_reg_code = CourseRegistrationCode(code=self.reg_code, course_id=course_key, created_by=self.user)
|
||||
course_reg_code.save()
|
||||
|
||||
def add_course_to_user_cart(self):
|
||||
|
||||
@@ -10,19 +10,17 @@ class ECommerce
|
||||
@$section.data 'wrapper', @
|
||||
# gather elements
|
||||
@$list_purchase_csv_btn = @$section.find("input[name='list-purchase-transaction-csv']'")
|
||||
@$transaction_group_name = @$section.find("input[name='transaction_group_name']'")
|
||||
@$course_registration_number = @$section.find("input[name='course_registration_code_number']'")
|
||||
@$download_transaction_group_name = @$section.find("input[name='download_transaction_group_name']'")
|
||||
@$active_transaction_group_name = @$section.find("input[name='active_transaction_group_name']'")
|
||||
@$spent_transaction_group_name = @$section.find('input[name="spent_transaction_group_name"]')
|
||||
|
||||
@$generate_registration_code_form = @$section.find("form#course_codes_number")
|
||||
@$list_sale_csv_btn = @$section.find("input[name='list-sale-csv']'")
|
||||
@$download_company_name = @$section.find("input[name='download_company_name']'")
|
||||
@$active_company_name = @$section.find("input[name='active_company_name']'")
|
||||
@$spent_company_name = @$section.find('input[name="spent_company_name"]')
|
||||
@$download_coupon_codes = @$section.find('input[name="download-coupon-codes-csv"]')
|
||||
|
||||
@$download_registration_codes_form = @$section.find("form#download_registration_codes")
|
||||
@$active_registration_codes_form = @$section.find("form#active_registration_codes")
|
||||
@$spent_registration_codes_form = @$section.find("form#spent_registration_codes")
|
||||
|
||||
@$coupoon_error = @$section.find('#coupon-error')
|
||||
@$course_code_error = @$section.find('#code-error')
|
||||
@$error_msg = @$section.find('#error-msg')
|
||||
|
||||
# attach click handlers
|
||||
# this handler binds to both the download
|
||||
@@ -31,47 +29,28 @@ class ECommerce
|
||||
url = @$list_purchase_csv_btn.data 'endpoint'
|
||||
url += '/csv'
|
||||
location.href = url
|
||||
|
||||
@$list_sale_csv_btn.click (e) =>
|
||||
url = @$list_sale_csv_btn.data 'endpoint'
|
||||
url += '/csv'
|
||||
location.href = url
|
||||
|
||||
@$download_coupon_codes.click (e) =>
|
||||
url = @$download_coupon_codes.data 'endpoint'
|
||||
location.href = url
|
||||
|
||||
@$download_registration_codes_form.submit (e) =>
|
||||
@$course_code_error.attr('style', 'display: none')
|
||||
@$coupoon_error.attr('style', 'display: none')
|
||||
@$error_msg.attr('style', 'display: none')
|
||||
return true
|
||||
|
||||
@$active_registration_codes_form.submit (e) =>
|
||||
@$course_code_error.attr('style', 'display: none')
|
||||
@$coupoon_error.attr('style', 'display: none')
|
||||
@$error_msg.attr('style', 'display: none')
|
||||
return true
|
||||
|
||||
@$spent_registration_codes_form.submit (e) =>
|
||||
@$course_code_error.attr('style', 'display: none')
|
||||
@$coupoon_error.attr('style', 'display: none')
|
||||
@$error_msg.attr('style', 'display: none')
|
||||
return true
|
||||
|
||||
@$generate_registration_code_form.submit (e) =>
|
||||
@$course_code_error.attr('style', 'display: none')
|
||||
@$coupoon_error.attr('style', 'display: none')
|
||||
group_name = @$transaction_group_name.val()
|
||||
if group_name == ''
|
||||
@$course_code_error.html('Please Enter the Transaction Group Name').show()
|
||||
return false
|
||||
|
||||
if ($.isNumeric(group_name))
|
||||
@$course_code_error.html('Please Enter the non-numeric value for Transaction Group Name').show()
|
||||
return false;
|
||||
|
||||
registration_codes = @$course_registration_number.val();
|
||||
if (isInt(registration_codes) && $.isNumeric(registration_codes))
|
||||
if (parseInt(registration_codes) > 1000 )
|
||||
@$course_code_error.html('You can only generate 1000 Registration Codes at a time').show()
|
||||
return false;
|
||||
if (parseInt(registration_codes) == 0 )
|
||||
@$course_code_error.html('Please Enter the Value greater than 0 for Registration Codes').show()
|
||||
return false;
|
||||
return true;
|
||||
else
|
||||
@$course_code_error.html('Please Enter the Integer Value for Registration Codes').show()
|
||||
return false;
|
||||
|
||||
# handler for when the section title is clicked.
|
||||
onClickTitle: ->
|
||||
@clear_display()
|
||||
@@ -83,14 +62,10 @@ class ECommerce
|
||||
onExit: -> @clear_display()
|
||||
|
||||
clear_display: ->
|
||||
@$course_code_error.attr('style', 'display: none')
|
||||
@$coupoon_error.attr('style', 'display: none')
|
||||
@$course_registration_number.val('')
|
||||
@$transaction_group_name.val('')
|
||||
@$download_transaction_group_name.val('')
|
||||
@$active_transaction_group_name.val('')
|
||||
@$spent_transaction_group_name.val('')
|
||||
|
||||
@$error_msg.attr('style', 'display: none')
|
||||
@$download_company_name.val('')
|
||||
@$active_company_name.val('')
|
||||
@$spent_company_name.val('')
|
||||
|
||||
isInt = (n) -> return n % 1 == 0;
|
||||
# Clear any generated tables, warning messages, etc.
|
||||
|
||||
@@ -831,27 +831,32 @@ input[name="subject"] {
|
||||
|
||||
}
|
||||
#e-commerce{
|
||||
.coupon-errors {
|
||||
input {
|
||||
margin-bottom: 1em;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
.error-msgs {
|
||||
background: #FFEEF5;color:#B72667;text-align: center;padding: 10px 0px;
|
||||
font-family: "Open Sans",Verdana,Geneva,sans-serif,sans-serif;font-size: 15px;
|
||||
border-bottom: 1px solid #B72667;
|
||||
margin-bottom: 20px;
|
||||
display: none;
|
||||
}
|
||||
.success-msgs {
|
||||
background: #D0F5D5;color:#008801;text-align: center;padding: 10px 0px;
|
||||
font-family: "Open Sans",Verdana,Geneva,sans-serif,sans-serif;font-size: 15px;
|
||||
border-bottom: 1px solid #008801;
|
||||
margin-bottom: 20px;
|
||||
display: none;
|
||||
}
|
||||
.content{
|
||||
padding: 0 !important;
|
||||
}
|
||||
input[name="course_registration_code_number"] {
|
||||
margin-right: 10px;
|
||||
height: 34px;
|
||||
width: 258px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
input[name="transaction_group_name"], input[name="download_transaction_group_name"],
|
||||
input[name="active_transaction_group_name"], input[name="spent_transaction_group_name"] {
|
||||
input[name="download_company_name"],
|
||||
input[name="active_company_name"], input[name="spent_company_name"] {
|
||||
margin-right: 8px;
|
||||
height: 36px;
|
||||
width: 300px;
|
||||
width: 254px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.coupons-table {
|
||||
@@ -955,12 +960,21 @@ input[name="subject"] {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section#registration_code_generation_modal {
|
||||
margin-left: -442px;
|
||||
width: 930px;
|
||||
}
|
||||
// coupon edit and add modals
|
||||
#add-coupon-modal, #edit-coupon-modal, #set-course-mode-price-modal{
|
||||
#add-coupon-modal, #edit-coupon-modal, #set-course-mode-price-modal, #registration_code_generation_modal{
|
||||
.inner-wrapper {
|
||||
background: #fff;
|
||||
}
|
||||
span.tip-text {
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
color: #646464
|
||||
}
|
||||
top:-95px !important;
|
||||
width: 650px;
|
||||
margin-left: -325px;
|
||||
@@ -973,6 +987,10 @@ input[name="subject"] {
|
||||
@include button(simple, $blue);
|
||||
@extend .button-reset;
|
||||
}
|
||||
input[name="generate-registration-codes-csv"]{
|
||||
@include button(simple, $blue);
|
||||
@extend .button-reset;
|
||||
}
|
||||
input[type="submit"]#set_course_button{
|
||||
@include button(simple, $blue);
|
||||
@extend .button-reset;
|
||||
@@ -1014,6 +1032,61 @@ input[name="subject"] {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
}
|
||||
form#generate_codes ol.list-input{
|
||||
li{
|
||||
width: 278px;
|
||||
float: left;
|
||||
label.required:after {
|
||||
content: "*";
|
||||
margin-left: 5px;
|
||||
}
|
||||
min-height: 120px;
|
||||
}
|
||||
li.address_fields {
|
||||
min-height: 45px !important;
|
||||
}
|
||||
li#generate-registration-modal-field-city, li#generate-registration-modal-field-state,
|
||||
li#generate-registration-modal-field-zipcode{
|
||||
width: 205px;
|
||||
}
|
||||
li#generate-registration-modal-field-country {
|
||||
width: 204px;
|
||||
margin-left: 15px !important;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
li:nth-child(even){
|
||||
margin-left: 0px !important;
|
||||
}
|
||||
li:nth-child(3n) {
|
||||
margin-left: 15px !important;
|
||||
}
|
||||
li#generate-registration-modal-field-company-contact-name,
|
||||
li#generate-registration-modal-field-address-line-3,
|
||||
li#generate-registration-modal-field-zipcode {
|
||||
margin-left: 15px !important;
|
||||
}
|
||||
li:last-child{
|
||||
label {
|
||||
float: right;
|
||||
margin-top: -5px;
|
||||
right: 27px;
|
||||
}
|
||||
min-height: 5px;
|
||||
margin-left: 0px !important;
|
||||
input[type='checkbox'] {
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
li#generate-registration-modal-field-country ~ li#generate-registration-modal-field-total-price,
|
||||
li#generate-registration-modal-field-country ~ li#generate-registration-modal-field-internal-reference {
|
||||
margin-left: 0px !important;
|
||||
margin-right: 15px !important;
|
||||
}
|
||||
li#generate-registration-modal-field-custom-reference-number {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
li#set-course-mode-modal-field-price{
|
||||
width: 100%;
|
||||
label.required:after {
|
||||
@@ -1027,7 +1100,13 @@ input[name="subject"] {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
#coupon-content, #course-content {
|
||||
#registration-content form .field.text input {
|
||||
background: #fff;
|
||||
margin-bottom: 0;
|
||||
height: 40px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
#coupon-content, #course-content, #registration-content {
|
||||
padding: 20px;
|
||||
header {
|
||||
margin: 0;
|
||||
@@ -1086,6 +1165,19 @@ input[name="subject"] {
|
||||
}
|
||||
}
|
||||
}
|
||||
#registration-content form .group-form {
|
||||
|
||||
}
|
||||
#registration-content form {
|
||||
.field {
|
||||
margin: 0;
|
||||
}
|
||||
.group-form {
|
||||
margin: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1171,5 +1263,47 @@ input[name="subject"] {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
span.code_tip {
|
||||
background: none repeat scroll 0 0 #F8F4EC;
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
border-top: 1px solid #DDDDDD;
|
||||
color: #3C3C3C;
|
||||
display: block;
|
||||
line-height: 30px;
|
||||
margin-bottom: 6px;
|
||||
padding: 10px 15px 10px 20px;
|
||||
.add{
|
||||
@include button(simple, $blue);
|
||||
@extend .button-reset;
|
||||
font-size: em(13);
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
span.csv_tip {
|
||||
|
||||
display: block;
|
||||
line-height: 30px;
|
||||
margin-bottom: 6px;
|
||||
padding: 10px 15px 10px 1px;
|
||||
.add{
|
||||
font-size: em(13);
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
span.invalid_sale {
|
||||
background: none repeat scroll 0 0 #F8F4EC;
|
||||
color: #3C3C3C;
|
||||
display: block;
|
||||
line-height: 30px;
|
||||
height: 37px;
|
||||
margin-bottom: 6px;
|
||||
padding: 10px 15px 10px 1px;
|
||||
.add{
|
||||
@include button(simple, $blue);
|
||||
@extend .button-reset;
|
||||
font-size: em(13);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1108,4 +1108,61 @@
|
||||
@extend %t-copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
p.course-block{
|
||||
border-style: solid;
|
||||
border-color: #E3DC86;
|
||||
padding: 5px;
|
||||
border-width: 1px;
|
||||
background: #FDFBE4;
|
||||
|
||||
}
|
||||
.enter-course-blocked{
|
||||
|
||||
@include box-sizing(border-box);
|
||||
display: block;
|
||||
float: left;
|
||||
font: normal 15px/1.6rem $sans-serif;
|
||||
letter-spacing: 0;
|
||||
padding: 6px 32px 7px;
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
opacity:0.5;
|
||||
background:#808080;
|
||||
border:0;
|
||||
color:white;
|
||||
box-shadow:none;
|
||||
&.archived {
|
||||
@include button(simple, $button-archive-color);
|
||||
font: normal 15px/1.6rem $sans-serif;
|
||||
padding: 6px 32px 7px;
|
||||
|
||||
&:hover, &:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
a.disable-look{
|
||||
color: #808080;
|
||||
}
|
||||
a.disable-look-unregister{
|
||||
color: #808080;
|
||||
float: right;
|
||||
display: block;
|
||||
font-style: italic;
|
||||
color: $lighter-base-font-color;
|
||||
text-decoration: underline;
|
||||
font-size: .8em;
|
||||
margin-top: 32px;
|
||||
|
||||
}
|
||||
a.disable-look-settings{
|
||||
@extend a.disable-look-unregister;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
a.fade-cover{
|
||||
@extend .cover;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
|
||||
@@ -306,7 +306,8 @@
|
||||
<% course_mode_info = all_course_modes.get(course.id) %>
|
||||
<% show_refund_option = (course.id in show_refund_option_for) %>
|
||||
<% is_paid_course = (course.id in enrolled_courses_either_paid) %>
|
||||
<%include file='dashboard/_dashboard_course_listing.html' args="course=course, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, show_refund_option = show_refund_option, is_paid_course = is_paid_course" />
|
||||
<% is_course_blocked = (course.id in block_courses) %>
|
||||
<%include file='dashboard/_dashboard_course_listing.html' args="course=course, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, show_refund_option = show_refund_option, is_paid_course = is_paid_course, is_course_blocked = is_course_blocked" />
|
||||
% endfor
|
||||
|
||||
</ul>
|
||||
@@ -521,3 +522,13 @@
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
$("#unregister_block_course").click( function(event) {
|
||||
$("#unenroll_course_id").val( $(event.target).data("course-id") );
|
||||
$("#unenroll_course_number").text( $(event.target).data("course-number") );
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%page args="course, enrollment, show_courseware_link, cert_status, show_email_settings, course_mode_info, show_refund_option, is_paid_course" />
|
||||
<%page args="course, enrollment, show_courseware_link, cert_status, show_email_settings, course_mode_info, show_refund_option, is_paid_course, is_course_blocked" />
|
||||
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
<%!
|
||||
@@ -31,9 +31,15 @@
|
||||
%>
|
||||
|
||||
% if show_courseware_link:
|
||||
<a href="${course_target}" class="cover">
|
||||
% if not is_course_blocked:
|
||||
<a href="${course_target}" class="cover">
|
||||
<img src="${course_image_url(course)}" alt="${_('{course_number} {course_name} Cover Image').format(course_number=course.number, course_name=course.display_name_with_default) |h}" />
|
||||
</a>
|
||||
% else:
|
||||
<a class="fade-cover">
|
||||
<img src="${course_image_url(course)}" alt="${_('{course_number} {course_name} Cover Image').format(course_number=course.number, course_name=course.display_name_with_default) |h}" />
|
||||
</a>
|
||||
% endif
|
||||
% else:
|
||||
<div class="cover">
|
||||
<img src="${course_image_url(course)}" alt="${_('{course_number} {course_name} Cover Image').format(course_number=course.number, course_name=course.display_name_with_default) | h}" />
|
||||
@@ -80,7 +86,11 @@
|
||||
<h2 class="university">${get_course_about_section(course, 'university')}</h2>
|
||||
<h3>
|
||||
% if show_courseware_link:
|
||||
% if not is_course_blocked:
|
||||
<a href="${course_target}">${course.display_number_with_default | h} ${course.display_name_with_default}</a>
|
||||
% else:
|
||||
<a class="disable-look">${course.display_number_with_default | h} ${course.display_name_with_default}</a>
|
||||
% endif
|
||||
% else:
|
||||
<span>${course.display_number_with_default | h} ${course.display_name_with_default}</span>
|
||||
% endif
|
||||
@@ -91,7 +101,7 @@
|
||||
<%include file='_dashboard_certificate_information.html' args='cert_status=cert_status,course=course, enrollment=enrollment'/>
|
||||
% endif
|
||||
|
||||
% if course_mode_info['show_upsell']:
|
||||
% if course_mode_info['show_upsell'] and not is_course_blocked:
|
||||
<div class="message message-upsell has-actions is-expandable is-shown">
|
||||
|
||||
<div class="wrapper-tip">
|
||||
@@ -122,52 +132,116 @@
|
||||
</div>
|
||||
</div>
|
||||
%endif
|
||||
% if is_course_blocked:
|
||||
<p id="block-course-msg" class="course-block">
|
||||
${_('You can no longer access this course because payment has not yet been received. you can <a href="#">contact the account holder</a> to request payment, or you can')}
|
||||
<a id="unregister_block_course" rel="leanModal" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" href="#unenroll-modal" > ${_('unregister')} </a>
|
||||
${_('for this course.')}
|
||||
</p>
|
||||
%endif
|
||||
|
||||
% if show_courseware_link:
|
||||
% if course.has_ended():
|
||||
% if not is_course_blocked:
|
||||
<a href="${course_target}" class="enter-course archived">${_('View Archived Course')}</a>
|
||||
% else:
|
||||
<a class="enter-course-blocked archived">${_('View Archived Course')}</a>
|
||||
% endif
|
||||
% else:
|
||||
% if not is_course_blocked:
|
||||
<a href="${course_target}" class="enter-course">${_('View Course')}</a>
|
||||
% else:
|
||||
<a class="enter-course-blocked">${_('View Course')}</a>
|
||||
% endif
|
||||
% endif
|
||||
% endif
|
||||
|
||||
% if is_paid_course and show_refund_option:
|
||||
## Translators: The course's name will be added to the end of this sentence.
|
||||
% if not is_course_blocked:
|
||||
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unregister from the purchased course")}';
|
||||
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
|
||||
${_('Unregister')}
|
||||
</a>
|
||||
% else:
|
||||
<a class="disable-look-unregister" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unregister from the purchased course")}';
|
||||
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
|
||||
${_('Unregister')}
|
||||
</a>
|
||||
% endif
|
||||
% elif is_paid_course and not show_refund_option:
|
||||
## Translators: The course's name will be added to the end of this sentence.
|
||||
% if not is_course_blocked:
|
||||
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unregister from the purchased course")}';
|
||||
document.getElementById('refund-info').innerHTML=gettext('You will not be refunded the amount you paid.')">
|
||||
${_('Unregister')}
|
||||
</a>
|
||||
% else:
|
||||
<a class="disable-look-unregister" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unregister from the purchased course")}';
|
||||
document.getElementById('refund-info').innerHTML=gettext('You will not be refunded the amount you paid.')">
|
||||
${_('Unregister')}
|
||||
</a>
|
||||
% endif
|
||||
% elif enrollment.mode != "verified":
|
||||
## Translators: The course's name will be added to the end of this sentence.
|
||||
% if not is_course_blocked:
|
||||
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unregister from")}'; document.getElementById('refund-info').innerHTML=''">
|
||||
${_('Unregister')}
|
||||
</a>
|
||||
% else:
|
||||
<a class="disable-look-unregister" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unregister from")}'; document.getElementById('refund-info').innerHTML=''">
|
||||
${_('Unregister')}
|
||||
</a>
|
||||
% endif
|
||||
% elif show_refund_option:
|
||||
## Translators: The course's name will be added to the end of this sentence.
|
||||
% if not is_course_blocked:
|
||||
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unregister from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
|
||||
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
|
||||
${_('Unregister')}
|
||||
</a>
|
||||
% else:
|
||||
<a class="disable-look-unregister" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unregister from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
|
||||
document.getElementById('refund-info').innerHTML=gettext('You will be refunded the amount you paid.')">
|
||||
${_('Unregister')}
|
||||
</a>
|
||||
% endif
|
||||
% else:
|
||||
## Translators: The course's name will be added to the end of this sentence.
|
||||
% if not is_course_blocked:
|
||||
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unregister from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
|
||||
document.getElementById('refund-info').innerHTML=gettext('The refund deadline for this course has passed, so you will not receive a refund.')">
|
||||
${_('Unregister')}
|
||||
</a>
|
||||
% else:
|
||||
<a class="disable-look-unregister" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" onclick="document.getElementById('track-info').innerHTML='${_("Are you sure you want to unregister from the verified {cert_name_long} track of").format(cert_name_long=cert_name_long)}';
|
||||
document.getElementById('refund-info').innerHTML=gettext('The refund deadline for this course has passed, so you will not receive a refund.')">
|
||||
${_('Unregister')}
|
||||
</a>
|
||||
% endif
|
||||
% endif
|
||||
|
||||
% if show_email_settings:
|
||||
% if not is_course_blocked:
|
||||
<a href="#email-settings-modal" class="email-settings" rel="leanModal" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" data-optout="${course.id.to_deprecated_string() in course_optouts}">${_('Email Settings')}</a>
|
||||
% else:
|
||||
<a class="disable-look-settings" data-course-id="${course.id.to_deprecated_string()}" data-course-number="${course.number}" data-optout="${course.id.to_deprecated_string() in course_optouts}">${_('Email Settings')}</a>
|
||||
% endif
|
||||
% endif
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
</article>
|
||||
</article>
|
||||
</li>
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
|
||||
if("${is_course_blocked}" == "True"){
|
||||
$( "#unregister_block_course" ).click(function() {
|
||||
$('.disable-look-unregister').click();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
49
lms/templates/emails/registration_codes_sale_invoice.txt
Normal file
49
lms/templates/emails/registration_codes_sale_invoice.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
|
||||
${_("Professional Education Invoicing Center")}
|
||||
|
||||
${_("Portland Street, ")}
|
||||
${_("9th floor Cambridge, MA,")}
|
||||
${_("02139 finance@edx.org")}
|
||||
|
||||
${_("---------------------------------")}
|
||||
|
||||
${_("Bill To:")}
|
||||
|
||||
${_("{company_name}").format(company_name=invoice.company_name)}
|
||||
|
||||
${_("{purchaser_name}").format(purchaser_name=invoice.company_contact_name)}
|
||||
|
||||
% if invoice.customer_reference_number:
|
||||
${_("Customer Reference Number: {customer_reference_number}").format(customer_reference_number=invoice.customer_reference_number)}
|
||||
%endif
|
||||
|
||||
${_("---------------------------------")}
|
||||
|
||||
${_("Registration codes:")}
|
||||
|
||||
${_("Please distribute one of the following registration codes to each student who is going to enroll in the class.")}
|
||||
${_("A student can redeem one of these codes by registering an account on ({site_name}.edx.org), starting the purchase").format(site_name=site_name)}
|
||||
${_("process on this course by adding it to their shopping cart from this page ({course_url}), and").format(course_url=course_url)}
|
||||
${_("entering their registration code while in the shopping cart.")}
|
||||
|
||||
%for registration_code in registration_codes:
|
||||
${registration_code.code}
|
||||
%endfor
|
||||
|
||||
${_("---------------------------------")}
|
||||
|
||||
${_("Thank you for your purchase! Failure to pay this invoice will result the invalidation of student enrollments")}
|
||||
${_("that use these codes. All purchases are final. Please refer to the cancellation policy")}
|
||||
${_("on {site_name} for more information.").format(site_name=site_name)}
|
||||
|
||||
${_("---------------------------------")}
|
||||
|
||||
${_("Course: {course_name} {start_date} - {end_date}").format(course_name=course.display_name, start_date=course.start_date_text, end_date=course.end_date_text)}
|
||||
${_("Price: ${price}").format(price=course_price)}
|
||||
${_("Quantity: ${quantity}").format(quantity=quantity)}
|
||||
${_("Sub-Total: ${sub_total}").format(sub_total=quantity*course_price)}
|
||||
${_("Discount: ${discount}").format(discount=discount_price)}
|
||||
|
||||
${_("--------- ------")}
|
||||
${_("Total Due: ${total_price}").format(total_price=sale_price)}
|
||||
@@ -3,26 +3,21 @@
|
||||
<%include file="add_coupon_modal.html" args="section_data=section_data" />
|
||||
<%include file="edit_coupon_modal.html" args="section_data=section_data" />
|
||||
<%include file="set_course_mode_price_modal.html" args="section_data=section_data" />
|
||||
<%include file="generate_registarion_codes_modal.html" args="section_data=section_data" />
|
||||
<div class="ecommerce-wrapper">
|
||||
<h3 class="coupon-errors" id="code-error"></h3>
|
||||
<h3 class="error-msgs" id="error-msg"></h3>
|
||||
<div id = "accordion">
|
||||
<div class="wrap">
|
||||
<h2>Registration Codes</h2>
|
||||
<div>
|
||||
<p>Enter the transaction group name and number of registration codes that you want to generate. Click to generate a CSV :</p>
|
||||
<p>
|
||||
<form action="${ section_data['generate_registration_code_csv_url'] }" id="course_codes_number" method="post">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
|
||||
<input type="text" name="transaction_group_name" placeholder="Transaction Group Name"/>
|
||||
<input type="text" name="course_registration_code_number" placeholder="Number of Registration Codes" maxlength="4"/>
|
||||
<input type="submit" name="generate-registration-codes-csv" value="${_("Generate Registration Codes")}" data-csv="true">
|
||||
</form>
|
||||
</p>
|
||||
<span class="code_tip">Click to generate Registration Codes
|
||||
<a id="registration_code_generation_link" href="#reg_code_generation_modal" class="add blue-button">Generate Registration Codes</a>
|
||||
</span>
|
||||
<p>Click to generate a CSV file of all Course Registrations Codes:</p>
|
||||
<p>
|
||||
<form action="${ section_data['get_registration_code_csv_url'] }" id="download_registration_codes" method="post">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
|
||||
<input type="text" name="download_transaction_group_name" placeholder="Transaction Group Name (Optional)"/>
|
||||
<input type="text" name="download_company_name" placeholder="Company Name (Optional)"/>
|
||||
<input type="submit" name="list-registration-codes-csv" value="${_("Download Registration Codes")}" data-csv="true">
|
||||
</form>
|
||||
</p>
|
||||
@@ -30,7 +25,7 @@
|
||||
<p>
|
||||
<form action="${ section_data['active_registration_code_csv_url'] }" id="active_registration_codes" method="post">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
|
||||
<input type="text" name="active_transaction_group_name" placeholder="Transaction Group Name (Optional)"/>
|
||||
<input type="text" name="active_company_name" placeholder="Company Name (Optional)"/>
|
||||
<input type="submit" name="active-registration-codes-csv" value="${_("Active Registration Codes")}" data-csv="true">
|
||||
</form>
|
||||
</p>
|
||||
@@ -38,7 +33,7 @@
|
||||
<p>
|
||||
<form action="${ section_data['spent_registration_code_csv_url'] }" id="spent_registration_codes" method="post">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
|
||||
<input type="text" name="spent_transaction_group_name" placeholder="Transaction Group Name (Optional)"/>
|
||||
<input type="text" name="spent_company_name" placeholder="Company Name (Optional)"/>
|
||||
<input type="submit" name="spent-registration-codes-csv" value="${_("Spent Registration Codes")}" data-csv="true">
|
||||
</form>
|
||||
</p>
|
||||
@@ -63,16 +58,37 @@
|
||||
%if section_data['total_amount'] is not None:
|
||||
<span>${_("Total Amount: ")}<span>$${section_data['total_amount']}</span></span>
|
||||
%endif
|
||||
<p>${_("Click to generate a CSV file for all purchase transactions in this course")}</p>
|
||||
<p><input type="button" name="list-purchase-transaction-csv" value="${_("Download All e-Commerce Purchases")}" data-endpoint="${ section_data['get_purchase_transaction_url'] }" data-csv="true"></p>
|
||||
|
||||
<span class="csv_tip">${_("Click to generate a CSV file for all purchase transactions in this course")}
|
||||
<input class="add blue-button" type="button" name="list-purchase-transaction-csv" value="${_("Download All e-Commerce Purchases")}" data-endpoint="${ section_data['get_purchase_transaction_url'] }" data-csv="true">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end wrap -->
|
||||
</div><!-- end wrap -->
|
||||
<div class="wrap">
|
||||
<h2>${_("Sales")}</h2>
|
||||
<div>
|
||||
<span class="csv_tip">${_("Click to generate a CSV file for all sales records in this course")}
|
||||
<input type="button" class="add blue-button" name="list-sale-csv" value="${_("Download All e-Commerce Sales")}" data-endpoint="${ section_data['get_sale_records_url'] }" data-csv="true"></p></td>
|
||||
</span>
|
||||
<hr>
|
||||
<p>${_("Enter the invoice number to invalidate or re-validate sale")}</p>
|
||||
<span class="invalid_sale">
|
||||
<input type="number" id="invoice_number" placeholder= "${_("Enter Invoice Number")}"/>
|
||||
<input type="button" class="add blue-button" id="invalidate_invoice" value="${_("Invalidate Sale")}">
|
||||
<input type="button" class="add blue-button" id="re_validate_invoice" value="${_("Revalidate Sale")}">
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div><!-- end wrap -->
|
||||
%endif
|
||||
<div class="wrap">
|
||||
<h2>${_("Coupons List")}</h2>
|
||||
<div>
|
||||
<h3 class="coupon-errors" id="coupon-error"></h3>
|
||||
|
||||
<span class="csv_tip">${_("Click to generate a CSV file of all Coupon Codes:")}
|
||||
<input class="add blue-button" type="button" name="download-coupon-codes-csv" value="${_("Download coupon codes")}" data-endpoint="${ section_data['download_coupon_codes_url'] }" data-csv="true">
|
||||
</span>
|
||||
|
||||
<span class="tip">${_("Coupons Information")} <a id="add_coupon_link" href="#add-coupon-modal" rel="leanModal"
|
||||
class="add blue-button">${_("+ Add Coupon")}</a></span>
|
||||
<div class="wrapper-content wrapper">
|
||||
@@ -110,6 +126,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<a id="edit-modal-trigger" href="#edit-coupon-modal" rel="leanModal"></a>
|
||||
<a id="registration_code_generation_link-trigger" href="#registration_code_generation_modal" rel="leanModal"></a>
|
||||
%endif
|
||||
</section>
|
||||
</div>
|
||||
@@ -119,8 +136,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
|
||||
$(function () {
|
||||
var icons = {
|
||||
header: "ui-icon-circle-arrow-e",
|
||||
activeHeader: "ui-icon-circle-arrow-s"
|
||||
@@ -133,13 +150,17 @@
|
||||
var active = jQuery("#accordion").accordion('option', 'active');
|
||||
$.cookie('saved_index', null);
|
||||
$.cookie('saved_index', active);
|
||||
$('#error-msg').val('');
|
||||
$("#error-msg").fadeOut(2000 , function(){
|
||||
$('#error-msg').hide()
|
||||
});
|
||||
},
|
||||
animate: 400,
|
||||
header: "> div.wrap >h2",
|
||||
icons:icons,
|
||||
active:isNaN(parseInt($.cookie('saved_index'))) ? 0 : parseInt($.cookie('saved_index')),
|
||||
collapsible: true
|
||||
});
|
||||
});
|
||||
|
||||
$('a[rel*=leanModal]').leanModal();
|
||||
$.each($("a.edit-right"), function () {
|
||||
@@ -152,6 +173,46 @@
|
||||
$(this).removeAttr('href')
|
||||
}
|
||||
});
|
||||
$('#registration_code_generation_link').click(function(event){
|
||||
event.preventDefault();
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "${section_data['get_user_invoice_preference_url']}",
|
||||
success: function (data) {
|
||||
$('#invoice-copy').prop('checked', data.invoice_copy);
|
||||
$('#registration_code_generation_link-trigger').click();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
$('#invalidate_invoice, #re_validate_invoice').click(function (event) {
|
||||
event.preventDefault();
|
||||
var event_type = "re_validate"
|
||||
if($(event.target).attr('id')=='invalidate_invoice'){
|
||||
event_type = "invalidate"
|
||||
}
|
||||
if($('#invoice_number').val() == "") {
|
||||
$('#error-msg').attr('class','error-msgs')
|
||||
$('#error-msg').html("${_("Invoice number should not be empty.")}").show();
|
||||
return
|
||||
}
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
data: {invoice_number: $('#invoice_number').val(), event_type:event_type},
|
||||
url: "${section_data['sale_validation_url']}",
|
||||
success: function (data) {
|
||||
$('#error-msg').attr('class','success-msgs')
|
||||
$('#error-msg').html(data.message).show();
|
||||
$('#invoice_number').val('');
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
$('#error-msg').attr('class','error-msgs')
|
||||
$('#error-msg').html(jqXHR.responseText).show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('a.edit-right').click(function (event) {
|
||||
$('#edit_coupon_form #coupon_form_error').attr('style', 'display: none');
|
||||
$('#edit_coupon_form #coupon_form_error').text();
|
||||
@@ -167,8 +228,8 @@
|
||||
data: {id: coupon_id},
|
||||
url: "${section_data['ajax_get_coupon_info']}",
|
||||
success: function (data) {
|
||||
$('#coupon-error').val('');
|
||||
$('#coupon-error').attr('style', 'display: none');
|
||||
$('#error-msg').val('');
|
||||
$('#error-msg').hide()
|
||||
$('input#edit_coupon_code').val(data.coupon_code);
|
||||
$('input#edit_coupon_discount').val(data.coupon_discount);
|
||||
$('textarea#edit_coupon_description').val(data.coupon_description);
|
||||
@@ -177,7 +238,8 @@
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
var data = $.parseJSON(jqXHR.responseText);
|
||||
$('#coupon-error').html(data.message).show();
|
||||
$('#error-msg').attr('class','error-msgs')
|
||||
$('#error-msg').html(data.message).show();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -189,7 +251,7 @@
|
||||
anchor.data("disabled", "disabled");
|
||||
event.preventDefault();
|
||||
if ($(this).parent().parent('tr').hasClass('inactive_coupon')) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
@@ -201,48 +263,141 @@
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
var data = $.parseJSON(jqXHR.responseText);
|
||||
$('#coupon-error').html(data.message).show();
|
||||
$('#error-msg').attr('class','error-msgs')
|
||||
$('#error-msg').html(data.message).show();
|
||||
anchor.removeData("disabled");
|
||||
}
|
||||
});
|
||||
});
|
||||
var generate_registration_code_form = $("form#generate_codes");
|
||||
var generate_registration_button = $('input[name="generate-registration-codes-csv"]');
|
||||
var registration_code_error = $('#generate_codes #registration_code_form_error');
|
||||
|
||||
function validateEmail(sEmail) {
|
||||
filter = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/
|
||||
return filter.test(sEmail)
|
||||
}
|
||||
generate_registration_code_form.submit(function () {
|
||||
registration_code_error.attr('style', 'display: none');
|
||||
generate_registration_button.attr('disabled', true);
|
||||
var total_registration_codes = $('input[name="total_registration_codes"]').val();
|
||||
var recipient_name = $('input[name="recipient_name"]').val();
|
||||
var recipient_email = $('input[name="recipient_email"]').val();
|
||||
var sale_price = $('input[name="sale_price"]').val();
|
||||
var company_name = $('input[name="company_name"]').val();
|
||||
var company_contact_name = $('input[name="company_contact_name"]').val();
|
||||
var company_contact_email = $('input[name="company_contact_email"]').val();
|
||||
|
||||
var address_line = $('input[name="address_line_1"]').val();
|
||||
|
||||
if (company_name == '') {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the company name');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (($.isNumeric(company_name))) {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the non-numeric value for company name');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (company_contact_name == '') {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the company contact name');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (($.isNumeric(company_contact_name))) {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the non-numeric value for company contact name');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (company_contact_email == '') {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the company contact email');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (!(validateEmail(company_contact_email))) {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the valid email address');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (recipient_name == '') {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the recipient name');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (($.isNumeric(recipient_name))) {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the non-numeric value for recipient name');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (recipient_email == '') {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the recipient email');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (!(validateEmail(recipient_email))) {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the valid email address');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (address_line == '') {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the billing address');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (sale_price == '') {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the sale price');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false
|
||||
}
|
||||
if (!($.isNumeric(sale_price))) {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the numeric value for sale price');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false
|
||||
}
|
||||
if (total_registration_codes == '') {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the total registration codes');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false
|
||||
}
|
||||
if (!($.isNumeric(total_registration_codes))) {
|
||||
registration_code_error.attr('style', 'display: block !important');
|
||||
registration_code_error.text('Please enter the numeric value for total registration codes');
|
||||
generate_registration_button.removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
var modal_overLay = $('#lean_overlay')
|
||||
var registration_code_modal = $('#registration_code_generation_modal');
|
||||
registration_code_modal.hide();
|
||||
modal_overLay.hide();
|
||||
});
|
||||
|
||||
$('#edit_coupon_form').submit(function () {
|
||||
$("#update_coupon_button").attr('disabled', true);
|
||||
// Get the Code and Discount value and trim it
|
||||
var code = $.trim($('#edit_coupon_code').val());
|
||||
var coupon_discount = $.trim($('#edit_coupon_discount').val());
|
||||
|
||||
// Check if empty of not
|
||||
if (code === '') {
|
||||
$('#edit_coupon_form #coupon_form_error').attr('style', 'display: block !important');
|
||||
$('#edit_coupon_form #coupon_form_error').text("${_('Please Enter the Coupon Code')}");
|
||||
$("#update_coupon_button").removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (coupon_discount == '0') {
|
||||
$('#edit_coupon_form #coupon_form_error').attr('style', 'display: block !important');
|
||||
$('#edit_coupon_form #coupon_form_error').text("${_('Please Enter the Value Greater than 0')}");
|
||||
$("#update_coupon_button").removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (parseInt(coupon_discount) > 100) {
|
||||
$('#edit_coupon_form #coupon_form_error').attr('style', 'display: block !important');
|
||||
$('#edit_coupon_form #coupon_form_error').text("${_('Please Enter the Coupon Discount Value Less than or Equal to 100')}");
|
||||
$("#update_coupon_button").removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (!$.isNumeric(coupon_discount)) {
|
||||
$('#edit_coupon_form #coupon_form_error').attr('style', 'display: block !important');
|
||||
$('#edit_coupon_form #coupon_form_error').text("${_('Please Enter the Coupon Discount Value Greater than 0')}");
|
||||
$("#update_coupon_button").removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
$('#course_price_link').click(function () {
|
||||
reset_input_fields();
|
||||
});
|
||||
$('#add_coupon_link').click(function () {
|
||||
reset_input_fields();
|
||||
});
|
||||
$('#registration_code_generation_link').click(function () {
|
||||
reset_input_fields();
|
||||
$('input[name="generate-registration-codes-csv"]').removeAttr('disabled');
|
||||
});
|
||||
$('#set_price_form').submit(function () {
|
||||
$("#set_course_button").attr('disabled', true);
|
||||
@@ -253,19 +408,19 @@
|
||||
// Check if empty of not
|
||||
if (course_price === '') {
|
||||
$('#set_price_form #course_form_error').attr('style', 'display: block !important');
|
||||
$('#set_price_form #course_form_error').text("${_('Please Enter the Course Price')}");
|
||||
$('#set_price_form #course_form_error').text("${_('Please enter the course price')}");
|
||||
$("#set_course_button").removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (!$.isNumeric(course_price)) {
|
||||
$("#set_course_button").removeAttr('disabled');
|
||||
$('#set_price_form #course_form_error').attr('style', 'display: block !important');
|
||||
$('#set_price_form #course_form_error').text("${_('Please Enter the Numeric value for Discount')}");
|
||||
$('#set_price_form #course_form_error').text("${_('Please enter the numeric value for course price')}");
|
||||
return false;
|
||||
}
|
||||
if (currency == '') {
|
||||
$('#set_price_form #course_form_error').attr('style', 'display: block !important');
|
||||
$('#set_price_form #course_form_error').text("${_('Please Select the Currency')}");
|
||||
$('#set_price_form #course_form_error').text("${_('Please select the currency')}");
|
||||
$("#set_course_button").removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
@@ -280,25 +435,25 @@
|
||||
if (code === '') {
|
||||
$("#add_coupon_button").removeAttr('disabled');
|
||||
$('#add_coupon_form #coupon_form_error').attr('style', 'display: block !important');
|
||||
$('#add_coupon_form #coupon_form_error').text("${_('Please Enter the Coupon Code')}");
|
||||
$('#add_coupon_form #coupon_form_error').text("${_('Please enter the coupon code')}");
|
||||
return false;
|
||||
}
|
||||
if (coupon_discount == '0') {
|
||||
$('#add_coupon_form #coupon_form_error').attr('style', 'display: block !important');
|
||||
$('#add_coupon_form #coupon_form_error').text("${_('Please Enter the Coupon Discount Value Greater than 0')}");
|
||||
$('#add_coupon_form #coupon_form_error').text("${_('Please enter the coupon discount value greater than 0')}");
|
||||
$("#add_coupon_button").removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (parseInt(coupon_discount) > 100) {
|
||||
$('#add_coupon_form #coupon_form_error').attr('style', 'display: block !important');
|
||||
$('#add_coupon_form #coupon_form_error').text("${_('Please Enter the Coupon Discount Value Less than or Equal to 100')}");
|
||||
$('#add_coupon_form #coupon_form_error').text("${_('Please enter the coupon discount value less than or equal to 100')}");
|
||||
$("#add_coupon_button").removeAttr('disabled');
|
||||
return false;
|
||||
}
|
||||
if (!$.isNumeric(coupon_discount)) {
|
||||
$("#add_coupon_button").removeAttr('disabled');
|
||||
$('#add_coupon_form #coupon_form_error').attr('style', 'display: block !important');
|
||||
$('#add_coupon_form #coupon_form_error').text("${_('Please Enter the Numeric value for Discount')}");
|
||||
$('#add_coupon_form #coupon_form_error').text("${_('Please enter the numeric value for discount')}");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@@ -337,6 +492,7 @@
|
||||
$("#update_coupon_button").removeAttr('disabled');
|
||||
$("#add_coupon_button").removeAttr('disabled');
|
||||
$("#set_course_button").removeAttr('disabled');
|
||||
$('input[name="generate-registration-codes-csv"]').removeAttr('disabled');
|
||||
reset_input_fields();
|
||||
e.preventDefault();
|
||||
});
|
||||
@@ -347,9 +503,11 @@
|
||||
$("#edit-coupon-modal").attr("aria-hidden", "true");
|
||||
$(".edit-right").focus();
|
||||
$("#set-course-mode-price-modal").attr("aria-hidden", "true");
|
||||
$("#registration_code_generation_modal").attr("aria-hidden", "true");
|
||||
$("#add_coupon_button").removeAttr('disabled');
|
||||
$("#set_course_button").removeAttr('disabled');
|
||||
$("#update_coupon_button").removeAttr('disabled');
|
||||
$('input[name="generate-registration-codes-csv"]').removeAttr('disabled');
|
||||
reset_input_fields();
|
||||
};
|
||||
|
||||
@@ -366,11 +524,12 @@
|
||||
|
||||
$("#add-coupon-modal .close-modal").click(onModalClose);
|
||||
$("#edit-coupon-modal .close-modal").click(onModalClose);
|
||||
$('#registration_code_generation_modal .close-modal').click(onModalClose);
|
||||
$("#set-course-mode-price-modal .close-modal").click(reset_input_fields);
|
||||
|
||||
|
||||
// Hitting the ESC key will exit the modal
|
||||
$("#add-coupon-modal, #edit-coupon-modal, #set-course-mode-price-modal").on("keydown", function (e) {
|
||||
$("#add-coupon-modal, #edit-coupon-modal, #set-course-mode-price-modal, #registration_code_generation_modal").on("keydown", function (e) {
|
||||
var keyCode = e.keyCode || e.which;
|
||||
// 27 is the ESC key
|
||||
if (keyCode === 27) {
|
||||
@@ -378,19 +537,38 @@
|
||||
$("#add-coupon-modal .close-modal").click();
|
||||
$("#set-course-mode-price-modal .close-modal").click();
|
||||
$("#edit-coupon-modal .close-modal").click();
|
||||
$('#registration_code_generation_modal .close-modal').click();
|
||||
}
|
||||
});
|
||||
});
|
||||
var reset_input_fields = function () {
|
||||
$('#coupon-error').val('');
|
||||
$('#coupon-error').attr('style', 'display: none');
|
||||
$('#error-msg').val('');
|
||||
$('#error-msg').hide()
|
||||
$('#add_coupon_form #coupon_form_error').attr('style', 'display: none');
|
||||
$('#set_price_form #course_form_error').attr('style', 'display: none');
|
||||
$('#generate_codes #registration_code_form_error').attr('style', 'display: none');
|
||||
$('#add_coupon_form #coupon_form_error').text();
|
||||
$('input#mode_price').val('');
|
||||
$('input#coupon_code').val('');
|
||||
$('input#coupon_discount').val('');
|
||||
$('textarea#coupon_description').val('');
|
||||
|
||||
$('input[name="company_name"]').val('');
|
||||
$('input[name="total_registration_codes"]').val('');
|
||||
$('input[name="address_line_1"]').val('');
|
||||
$('input[name="address_line_2"]').val('');
|
||||
$('input[name="address_line_3"]').val('');
|
||||
$('input[name="city"]').val('');
|
||||
$('input[name="state"]').val('');
|
||||
$('input[name="zip"]').val('');
|
||||
$('input[name="country"]').val('');
|
||||
$('input[name="customer_reference_number"]').val('');
|
||||
$('input[name="recipient_name"]').val('');
|
||||
$('input[name="sale_price"]').val('');
|
||||
$('input[name="recipient_email"]').val('');
|
||||
$('input[name="company_contact_name"]').val('');
|
||||
$('input[name="company_contact_email"]').val('');
|
||||
$('input[name="invoice"]').attr('checked', 'checked');
|
||||
$('input[name="company_reference"]').val('');
|
||||
$('input[name="internal_reference"]').val('');
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -29,13 +29,13 @@
|
||||
<ol class="list-input">
|
||||
<li class="field required text" id="edit-coupon-modal-field-code">
|
||||
<label for="edit_coupon_code" class="required">${_("Code")}</label>
|
||||
<input class="field" id="edit_coupon_code" type="text" name="code" maxlength="16" value="" placeholder="example: A123DS"
|
||||
aria-required="true"/>
|
||||
<input class="field readonly" id="edit_coupon_code" type="text" name="code" maxlength="16" value="" placeholder="example: A123DS"
|
||||
readonly aria-required="true"/>
|
||||
</li>
|
||||
<li class="field required text" id="edit-coupon-modal-field-discount">
|
||||
<label for="edit_coupon_discount" class="required">${_("Percentage Discount")}</label>
|
||||
<input class="field" id="edit_coupon_discount" type="text" name="discount" value="" maxlength="3"
|
||||
aria-required="true"/>
|
||||
<input class="field readonly" id="edit_coupon_discount" type="text" name="discount" value="" maxlength="3"
|
||||
readonly aria-required="true"/>
|
||||
</li>
|
||||
|
||||
<li class="field" id="edit-coupon-modal-field-description">
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
<%! from django.core.urlresolvers import reverse %>
|
||||
<%page args="section_data"/>
|
||||
<section id="registration_code_generation_modal" class="modal" role="dialog" tabindex="-1" aria-label="${_('Generate Registration Code Modal')}">
|
||||
<div class="inner-wrapper">
|
||||
<button class="close-modal">
|
||||
<i class="icon-remove"></i>
|
||||
<span class="sr">
|
||||
## Translators: this is a control to allow users to exit out of this modal interface (a menu or piece of UI that takes the full focus of the screen)
|
||||
${_('Close')}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div id="registration-content">
|
||||
<header>
|
||||
<h2>${_("Generate Registration Codes")}</h2>
|
||||
</header>
|
||||
|
||||
<div class="instructions">
|
||||
<p>
|
||||
${_("Please enter the details below")}</p>
|
||||
</div>
|
||||
|
||||
<form id="generate_codes" action="${section_data['generate_registration_code_csv_url']}" method="post">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
|
||||
<div id="registration_code_form_error" class="modal-form-error"></div>
|
||||
<fieldset class="group group-form group-form-requiredinformation">
|
||||
<legend class="is-hidden">${_("Required Information")}</legend>
|
||||
|
||||
<ol class="list-input">
|
||||
<li class="field required text" id="generate-registration-modal-field-company-name">
|
||||
<label for="id_company_name" class="required text">${_("Organization Name")}</label>
|
||||
<input class="field required" id="id_company_name" type="text" name="company_name"
|
||||
placeholder="${_('Organization Name')}" aria-required="true" />
|
||||
<span class="tip-text">
|
||||
${_("What is the company the seats were sold to?")}
|
||||
</span>
|
||||
</li>
|
||||
<li class="field required text" id="generate-registration-modal-field-company-contact-name">
|
||||
<label for="id_company_contact_name" class="required text">${_("Organization Contact")}</label>
|
||||
<input class="field required" id="id_company_contact_name" type="text" name="company_contact_name"
|
||||
placeholder="${_('Name')}" aria-required="true" />
|
||||
<span class="tip-text">
|
||||
${_("Who is the key contact at the company the sale was made to? ")}
|
||||
</span>
|
||||
</li>
|
||||
<li class="field text" id="generate-registration-modal-field-company-email">
|
||||
<label for="id_company_contact_email" class="text"> </label>
|
||||
<input class="field" id="id_company_contact_email" type="email" value="" name="company_contact_email"
|
||||
placeholder="${_('Email')}" aria-required="true" />
|
||||
</li>
|
||||
<div class="clearfix"></div>
|
||||
<li class="field required text" id="generate-registration-modal-field-recipient-name">
|
||||
<label for="id_recipient_name" class="required text">${_("Invoice Recipient")}</label>
|
||||
<input class="field required" id="id_recipient_name" type="text" name="recipient_name"
|
||||
placeholder="${_('Name')}" aria-required="true"/>
|
||||
<span class="tip-text">
|
||||
${_("Who at the company should the invoice be sent to?")}
|
||||
</span>
|
||||
</li>
|
||||
<li class="field text" id="generate-registration-modal-field-recipient-email">
|
||||
<label for="id_recipient_email" class="text"> </label>
|
||||
<input class="field required" id="id_recipient_email" type="email" value="" placeholder="${_('Email')}"
|
||||
name="recipient_email" aria-required="true"/>
|
||||
</li>
|
||||
<div class="clearfix"></div>
|
||||
<li class="field required text address_fields" id="generate-registration-modal-field-address-line-1">
|
||||
<label for="id_address_line_1" class="required text">${_("Organization Billing Address")}</label>
|
||||
<input class="field required" id="id_address_line_1" type="text" name="address_line_1"
|
||||
placeholder="${_('Address Line 1')}" aria-required="true" />
|
||||
</li>
|
||||
<li class="field text address_fields" id="generate-registration-modal-field-address-line-2">
|
||||
<label for="id_address_line_2" class="text"> </label>
|
||||
<input class="field" id="id_address_line_2" type="text" name="address_line_2"
|
||||
placeholder="${_('Address Line 2')}" aria-required="true" />
|
||||
</li>
|
||||
<li class="field text address_fields" id="generate-registration-modal-field-address-line-3">
|
||||
<label for="id_address_line_3" class="text"> </label>
|
||||
<input class="field" id="id_address_line_3" type="text" name="address_line_3"
|
||||
placeholder="${_('Address Line 3')}" aria-required="true" />
|
||||
</li>
|
||||
<li class="field text address_fields" id="generate-registration-modal-field-city">
|
||||
<label for="id_city" class="text"> </label>
|
||||
<input class="field" id="id_city" type="text" name="city"
|
||||
placeholder="${_('City')}" aria-required="true" />
|
||||
</li>
|
||||
<li class="field text address_fields" id="generate-registration-modal-field-state">
|
||||
<label for="id_state" class="text"> </label>
|
||||
<input class="field" id="id_state" type="text" name="state"
|
||||
placeholder="${_('State/Province')}" aria-required="true" />
|
||||
</li>
|
||||
<li class="field text address_fields" id="generate-registration-modal-field-zipcode">
|
||||
<label for="id_zip" class="text"> </label>
|
||||
<input class="field" id="id_zip" type="text" name="zip"
|
||||
placeholder="${_('Zip')}" aria-required="true" />
|
||||
</li>
|
||||
<li class="field text address_fields" id="generate-registration-modal-field-country">
|
||||
<label for="id_country" class="text"> </label>
|
||||
<input class="field" id="id_country" type="text" name="country"
|
||||
placeholder="${_('Country')}" aria-required="true" />
|
||||
<span class="tip-text">
|
||||
</span>
|
||||
</li>
|
||||
<div class="clearfix"></div>
|
||||
<li class="field required text" id="generate-registration-modal-field-total-price">
|
||||
<label for="id_sale_price" class="required text">${_("Price of Sale")}</label>
|
||||
<input class="field required" id="id_sale_price" type="text" name="sale_price"
|
||||
aria-required="true" />
|
||||
<span class="tip-text">
|
||||
${_("What was the total sale price for all seats sold?")}
|
||||
</span>
|
||||
</li>
|
||||
<li class="field required text" id="generate-registration-modal-field-total-codes">
|
||||
<label for="id_total_registration_codes" class="required text">${_("Number of registrations")}</label>
|
||||
<input class="field required" id="id_total_registration_codes" type="text" name="total_registration_codes"
|
||||
aria-required="true"/>
|
||||
<span class="tip-text">
|
||||
${_("Number of codes to generate for the Invoice")}
|
||||
</span>
|
||||
</li>
|
||||
<div class="clearfix"></div>
|
||||
<li class="field text" id="generate-registration-modal-field-internal-reference">
|
||||
<label for="id_internal_reference" >${_("(Optional) Sale Label")}</label>
|
||||
<input class="field" id="id_internal_reference" type="text" name="internal_reference"
|
||||
aria-required="true" placeholder="BigCorp-IT-Department-1"/>
|
||||
<span class="tip-text">
|
||||
${_("Internal tag to associate with the sale")}
|
||||
</span>
|
||||
</li>
|
||||
<li class="field text" id="generate-registration-modal-field-custom-reference-number">
|
||||
<label for="id_customer_reference_number" >${_("(Optional) Customer Reference Number")}</label>
|
||||
<input class="field" id="id_customer_reference_number" type="text" name="customer_reference_number"
|
||||
aria-required="true" placeholder="PO #"/>
|
||||
<span class="tip-text">
|
||||
${_("Any reference specific to the purchasing company, e.g. PO #")}
|
||||
</span>
|
||||
</li>
|
||||
<div class="clearfix"></div>
|
||||
<li class="field text" id="generate-registration-modal-field-invoice-copy">
|
||||
<label for="id_invoice" >${_("Send me a copy of the invoice")}</label>
|
||||
<input class="field" id="id_invoice" type="checkbox" name="invoice"
|
||||
aria-required="true"/>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
<div class="submit">
|
||||
<input name="generate-registration-codes-csv" type="submit" value="${_('Generate Registration Codes')}" data-csv="true"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
Reference in New Issue
Block a user