import logging from datetime import datetime from django.contrib.contenttypes.models import ContentType from django.contrib.sites.models import Site from django.core.management import BaseCommand from django.db import transaction from faker import Faker from credentials.apps.catalog.models import Course, CourseRun, Organization, Pathway, Program from credentials.apps.core.models import User from credentials.apps.credentials.constants import CertificateType from credentials.apps.credentials.models import CourseCertificate, ProgramCertificate, Signatory, UserCredential from credentials.apps.records.constants import UserCreditPathwayStatus from credentials.apps.records.models import ProgramCertRecord, UserCreditPathway, UserGrade from credentials.shared.constants import PathwayType logger = logging.getLogger(__name__) class Command(BaseCommand): """ Seed all the data needed to display fake student records """ help = 'Seed catalog with fake data' def add_arguments(self, parser): """ Add arguments to the command parser """ parser.add_argument( '--site-name', action='store', default='Open edx', required=False, help="The site to attach all records to" ) parser.add_argument( '--user-name', action='store', type=str, default='edx', required=False, help="The user to attach all certs to" ) def handle(self, *args, **options): site_name = options.get('site_name') username = options.get('user_name') Command.seed_all(site_name, username) @staticmethod def log_action(object_type, object_id, created): """ Log a get_or_create action using a simple template """ action = "Created" if created else "Already exists" logger.info("%s %s %s", object_type, object_id, action) @staticmethod @transaction.atomic def seed_all(site_name, username): """ Seed all catalog data """ # Make predictable UUIDs using faker faker = Faker() faker.seed(1234) site = Command.get_site(site_name) organizations = Command.seed_organizations(site, faker) courses = Command.seed_courses(site, organizations, faker) course_runs = Command.seed_course_runs(courses, faker) programs = Command.seed_programs(site, organizations, course_runs, faker) user = Command.get_user(username) Command.seed_user_grades(user, course_runs) signatories = Command.seed_signatories(organizations) course_certificates = Command.seed_course_certificates(site, course_runs, signatories) program_certificates = Command.seed_program_certificates(site, programs, signatories) Command.seed_user_credentials(user, program_certificates, course_certificates, faker) Command.seed_program_cert_records(user, programs, faker) pathways = Command.seed_pathways(site, programs, faker) Command.seed_user_credit_pathways(user, pathways) industry_pathway = Command.seed_industry_pathway(site, programs, faker) @staticmethod def get_site(site_name): """ Get a specific site by its name """ site = Site.objects.get(name=site_name) if site: logger.info("Retrieved site: %s", site_name) else: logger.info("Error retrieving site: %s", site_name) return site @staticmethod def seed_organizations(site, faker): """ Seed two organizations """ organization1, created = Organization.objects.get_or_create( site=site, uuid=faker.uuid4(), name='Test-Org-1') Command.log_action('Organization', 'Test-Org-1', created) organization2, created = Organization.objects.get_or_create( site=site, uuid=faker.uuid4(), name='Test-Org-2') Command.log_action('Organization', 'Test-Org-2', created) return [organization1, organization2] @staticmethod def seed_courses(site, organizations, faker): """ Seed two courses per organization """ courses = [] course_id = 1 for organization in organizations: course1, created = Course.objects.get_or_create( site=site, uuid=faker.uuid4(), title="Course {}".format(course_id), key="Course-{}".format(course_id)) course1.owners = [organization] courses.append(course1) Command.log_action("Course", course_id, created) course2, created = Course.objects.get_or_create( site=site, uuid=faker.uuid4(), title="Course {}".format(course_id + 1), key="Course-{}".format(course_id + 1)) course2.owners = [organization] courses.append(course2) Command.log_action("Course", course_id + 1, created) course_id += 2 return courses @staticmethod def seed_course_runs(courses, faker): """ Seed one course run per course """ course_runs = [] course_run_id = 1 for course in courses: organization = course.owners.all()[0] key = "course-v1:{}+{}+{}".format(organization.name, course.key, course_run_id) course_run, created = CourseRun.objects.get_or_create( course=course, uuid=faker.uuid4(), start_date=datetime(2018, 1, 1), end_date=datetime(2018, 6, 1), key=key, ) Command.log_action("CourseRun for", course.title, created) course_runs.append(course_run) course_run_id += 1 return course_runs @staticmethod def seed_programs(site, organizations, course_runs, faker): """ Seed one program per org of all course runs for that org """ programs = [] program_id = 1 for organization in organizations: courses = Course.objects.filter(owners=organization) course_runs = [CourseRun.objects.get(course=course) for course in courses] program, created = Program.objects.update_or_create( site=site, uuid=faker.uuid4(), defaults={ 'title': 'Program {}'.format(program_id), 'status': 'active', }, ) program.course_runs = course_runs program.authoring_organizations = [organization] Command.log_action("Program", program_id, created) programs.append(program) program_id += 1 return programs @staticmethod def get_user(username): """ Get the test user """ return User.objects.get(username=username) @staticmethod def seed_user_grades(user, course_runs): """ Seed user grades for the test users """ user_grades = [] for course_run in course_runs: user_grade, created = UserGrade.objects.get_or_create( username=user.username, course_run=course_run, letter_grade='B', percent_grade=0.82, verified=True) Command.log_action("User Grade for", course_run.course.title, created) user_grades.append(user_grade) return user_grades @staticmethod def seed_signatories(organizations): """ Seed one signatory per org """ signatories = [] for organization in organizations: signatory, created = Signatory.objects.get_or_create( name=organization.name, title=organization.name) # TODO: add image Command.log_action("Signatory for", organization.name, created) signatories.append(signatory) return signatories @staticmethod def seed_program_certificates(site, programs, signatories): """ Seed program certs for two programs """ program_certificates = [] for program in programs: program_certificate, created = ProgramCertificate.objects.update_or_create( site=site, program_uuid=program.uuid, defaults={ 'is_active': True, 'language': 'en', }, ) program_certificate.signatories = signatories program_certificate.save() Command.log_action("Program certificate for", program.title, created) program_certificates.append(program_certificate) return program_certificates @staticmethod def seed_course_certificates(site, course_runs, signatories): """ Seed course certificates for all courses for user edx""" course_certificates = [] for course_run in course_runs: course_certificate, created = CourseCertificate.objects.update_or_create( site=site, course_id=course_run.key, defaults={ 'is_active': True, 'certificate_type': CertificateType.VERIFIED, } ) course_certificate.signatories = signatories course_certificate.save() Command.log_action("Course certificate for course run", course_run, created) course_certificates.append(course_certificate) return course_certificates @staticmethod def seed_user_credentials(user, program_certificates, course_certificates, faker): """ Seed user credentials for user """ user_program_credentials = [] user_course_credentials = [] for program_certificate in program_certificates: user_credential, created = UserCredential.objects.get_or_create( credential_content_type=ContentType.objects.get_for_model(program_certificate), credential_id=program_certificate.id, username=user.username, status=UserCredential.AWARDED, download_url="http://localhost:18150/download") Command.log_action("User Credential for", program_certificate, created) user_program_credentials.append(user_credential) for course_certificate in course_certificates: user_credential, created = UserCredential.objects.get_or_create( credential_content_type=ContentType.objects.get_for_model(course_certificate), credential_id=course_certificate.id, username=user.username, status=UserCredential.AWARDED, download_url="http://localhost:18150/download") Command.log_action("User Credential for Course", course_certificate.course_id, created) user_course_credentials.append(user_credential) return user_program_credentials, user_course_credentials @staticmethod def seed_program_cert_records(user, programs, faker): """ Seed program cert records for user""" program_cert_records = [] for program in programs: program_cert_record, created = ProgramCertRecord.objects.get_or_create( program=program, user=user, uuid=faker.uuid4()) Command.log_action("Program Cert Record with ID", program_cert_record.id, created) program_cert_records.append(program_cert_record) return program_cert_records @staticmethod def seed_pathways(site, programs, faker): """ Seed two pathways """ all_program_pathway, created = Pathway.objects.get_or_create( site=site, name='All program pathway', org_name="MIT", uuid=faker.uuid4()) all_program_pathway.programs = programs Command.log_action("Pathway with name", all_program_pathway.name, created) one_program_pathway, created = Pathway.objects.get_or_create( site=site, name='One program pathway', org_name="MIT", uuid=faker.uuid4()) one_program_pathway.programs = [programs[0]] Command.log_action("Pathway with name", one_program_pathway.name, created) return [all_program_pathway, one_program_pathway] @staticmethod def seed_user_credit_pathways(user, pathways): """ Seed one UserCreditPathway, this denotes that a user has sent an email to that pathway """ user_credit_pathway, created = UserCreditPathway.objects.get_or_create( user=user, pathway=pathways[1], status=UserCreditPathwayStatus.SENT) Command.log_action("UserCreditPathway for user", user.username, created) return user_credit_pathway @staticmethod def seed_industry_pathway(site, programs, faker): """ Seed one industry pathway """ industry_pathway, created = Pathway.objects.get_or_create( site=site, uuid=faker.uuid4(), defaults={ 'name': 'Test industry pathway', 'org_name': 'Dunder Mifflin', 'pathway_type': PathwayType.INDUSTRY.value, }, ) industry_pathway.programs = programs Command.log_action("Industry pathway with name", industry_pathway.name, created) return industry_pathway