diff --git a/common/djangoapps/course_modes/models.py b/common/djangoapps/course_modes/models.py index 53c8078e0b..0b015a133c 100644 --- a/common/djangoapps/course_modes/models.py +++ b/common/djangoapps/course_modes/models.py @@ -138,6 +138,8 @@ class CourseMode(models.Model): EXECUTIVE_EDUCATION = 'executive-education' PAID_EXECUTIVE_EDUCATION = 'paid-executive-education' UNPAID_EXECUTIVE_EDUCATION = 'unpaid-executive-education' + PAID_BOOTCAMP = 'paid-bootcamp' + UNPAID_BOOTCAMP = 'unpaid-bootcamp' DEFAULT_MODE = Mode( settings.COURSE_MODE_DEFAULTS['slug'], @@ -162,15 +164,17 @@ class CourseMode(models.Model): MASTERS, EXECUTIVE_EDUCATION, PAID_EXECUTIVE_EDUCATION, - UNPAID_EXECUTIVE_EDUCATION + UNPAID_EXECUTIVE_EDUCATION, + PAID_BOOTCAMP, + UNPAID_BOOTCAMP ] # Modes utilized for audit/free enrollments - AUDIT_MODES = [AUDIT, HONOR, UNPAID_EXECUTIVE_EDUCATION] + AUDIT_MODES = [AUDIT, HONOR, UNPAID_EXECUTIVE_EDUCATION, UNPAID_BOOTCAMP] # Modes that allow a student to pursue a verified certificate VERIFIED_MODES = [ - VERIFIED, PROFESSIONAL, MASTERS, EXECUTIVE_EDUCATION, PAID_EXECUTIVE_EDUCATION + VERIFIED, PROFESSIONAL, MASTERS, EXECUTIVE_EDUCATION, PAID_EXECUTIVE_EDUCATION, PAID_BOOTCAMP ] # Modes that allow a student to pursue a non-verified certificate @@ -181,7 +185,8 @@ class CourseMode(models.Model): # Modes that are eligible to purchase credit CREDIT_ELIGIBLE_MODES = [ - VERIFIED, PROFESSIONAL, NO_ID_PROFESSIONAL_MODE, EXECUTIVE_EDUCATION, PAID_EXECUTIVE_EDUCATION + VERIFIED, PROFESSIONAL, NO_ID_PROFESSIONAL_MODE, EXECUTIVE_EDUCATION, PAID_EXECUTIVE_EDUCATION, + PAID_BOOTCAMP ] # Modes for which certificates/programs may need to be updated diff --git a/lms/djangoapps/certificates/migrations/0034_auto_20220401_1213.py b/lms/djangoapps/certificates/migrations/0034_auto_20220401_1213.py new file mode 100644 index 0000000000..c2a1bb73a5 --- /dev/null +++ b/lms/djangoapps/certificates/migrations/0034_auto_20220401_1213.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.12 on 2022-04-01 12:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('certificates', '0033_auto_20220307_1100'), + ] + + operations = [ + migrations.AlterField( + model_name='certificatetemplate', + name='mode', + field=models.CharField(blank=True, choices=[('verified', 'verified'), ('honor', 'honor'), ('audit', 'audit'), ('professional', 'professional'), ('no-id-professional', 'no-id-professional'), ('masters', 'masters'), ('executive-education', 'executive-education'), ('paid-executive-education', 'paid-executive-education'), ('paid-bootcamp', 'paid-bootcamp')], default='honor', help_text='The course mode for this template.', max_length=125, null=True), + ), + migrations.AlterField( + model_name='generatedcertificate', + name='mode', + field=models.CharField(choices=[('verified', 'verified'), ('honor', 'honor'), ('audit', 'audit'), ('professional', 'professional'), ('no-id-professional', 'no-id-professional'), ('masters', 'masters'), ('executive-education', 'executive-education'), ('paid-executive-education', 'paid-executive-education'), ('paid-bootcamp', 'paid-bootcamp')], default='honor', max_length=32), + ), + migrations.AlterField( + model_name='historicalgeneratedcertificate', + name='mode', + field=models.CharField(choices=[('verified', 'verified'), ('honor', 'honor'), ('audit', 'audit'), ('professional', 'professional'), ('no-id-professional', 'no-id-professional'), ('masters', 'masters'), ('executive-education', 'executive-education'), ('paid-executive-education', 'paid-executive-education'), ('paid-bootcamp', 'paid-bootcamp')], default='honor', max_length=32), + ), + ] diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index 35b14d17fd..dd6be3ccbd 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -213,11 +213,12 @@ class GeneratedCertificate(models.Model): 'masters', 'executive-education', 'paid-executive-education', + 'paid-bootcamp', ) VERIFIED_CERTS_MODES = [ CourseMode.VERIFIED, CourseMode.CREDIT_MODE, CourseMode.MASTERS, CourseMode.EXECUTIVE_EDUCATION, - CourseMode.PAID_EXECUTIVE_EDUCATION + CourseMode.PAID_EXECUTIVE_EDUCATION, CourseMode.PAID_BOOTCAMP ] user = models.ForeignKey(User, on_delete=models.CASCADE) diff --git a/lms/djangoapps/program_enrollments/rest_api/v1/utils.py b/lms/djangoapps/program_enrollments/rest_api/v1/utils.py index 1b62654827..8db3afd248 100644 --- a/lms/djangoapps/program_enrollments/rest_api/v1/utils.py +++ b/lms/djangoapps/program_enrollments/rest_api/v1/utils.py @@ -217,7 +217,8 @@ def get_enrollments_for_courses_in_program(user, program): user=user, course_id__in=course_keys, mode__in=[ - CourseMode.VERIFIED, CourseMode.MASTERS, CourseMode.EXECUTIVE_EDUCATION, CourseMode.PAID_EXECUTIVE_EDUCATION + CourseMode.VERIFIED, CourseMode.MASTERS, CourseMode.EXECUTIVE_EDUCATION, CourseMode.PAID_EXECUTIVE_EDUCATION, + CourseMode.PAID_BOOTCAMP ], is_active=True, ) diff --git a/lms/envs/common.py b/lms/envs/common.py index bf81a9769e..7ce08d678c 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -4604,6 +4604,18 @@ COURSE_ENROLLMENT_MODES = { "display_name": _("Paid Executive Education"), "min_price": 1 }, + "unpaid-bootcamp": { + "id": 11, + "slug": "unpaid-bootcamp", + "display_name": _("Unpaid Bootcamp"), + "min_price": 0 + }, + "paid-bootcamp": { + "id": 12, + "slug": "paid-bootcamp", + "display_name": _("Paid Bootcamp"), + "min_price": 1 + }, } CONTENT_TYPE_GATE_GROUP_IDS = { diff --git a/lms/templates/instructor/instructor_dashboard_2/course_info.html b/lms/templates/instructor/instructor_dashboard_2/course_info.html index 60cf57b2e4..0daa68f6b8 100644 --- a/lms/templates/instructor/instructor_dashboard_2/course_info.html +++ b/lms/templates/instructor/instructor_dashboard_2/course_info.html @@ -44,6 +44,16 @@ from openedx.core.djangolib.markup import HTML, Text