def create_course(): params = request.get_json() accent_color = normalize_accent_color(get_param(params, 'accentColor')) degree_check_id = get_param(params, 'degreeCheckId') grade = get_param(params, 'grade') name = get_param(params, 'name') note = get_param(params, 'note') sid = get_param(params, 'sid') value = get_param(request.get_json(), 'unitRequirementIds') unit_requirement_ids = list(filter(None, value.split(','))) if isinstance( value, str) else value units = get_param(params, 'units') if 0 in map(lambda v: len(str(v).strip()) if v else 0, (name, sid)): raise BadRequestError('Missing one or more required parameters') course = DegreeProgressCourse.create( accent_color=accent_color, degree_check_id=degree_check_id, display_name=name, grade=grade, manually_created_at=datetime.now(), manually_created_by=current_user.get_id(), note=note, section_id=None, sid=sid, term_id=None, unit_requirement_ids=unit_requirement_ids or (), units=units, ) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(course.degree_check_id, current_user.get_id()) return tolerant_jsonify(course.to_api_json())
def update_course(course_id): course = DegreeProgressCourse.find_by_id(course_id) if course: params = request.get_json() accent_color = normalize_accent_color(get_param(params, 'accentColor')) grade = get_param(params, 'grade') grade = course.grade if grade is None else grade name = get_param(params, 'name') name = course.display_name if name is None else name if name is None: raise BadRequestError('name is required.') note = get_param(params, 'note') # Courses are mapped to degree_progress_unit_requirements value = get_param(request.get_json(), 'unitRequirementIds') unit_requirement_ids = list(filter( None, value.split(','))) if isinstance(value, str) else value units = get_param(params, 'units') or None course = DegreeProgressCourse.update( accent_color=accent_color, course_id=course_id, grade=grade, name=name, note=note, unit_requirement_ids=unit_requirement_ids, units=units, ) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(course.degree_check_id, current_user.get_id()) return tolerant_jsonify(course.to_api_json()) else: raise ResourceNotFoundError('Course not found.')
def update_category(category_id): params = request.get_json() units_lower = get_param(params, 'unitsLower') units_upper = get_param(params, 'unitsUpper') description = get_param(params, 'description') name = get_param(params, 'name') parent_category_id = get_param(params, 'parentCategoryId') # Courses can be mapped to degree_progress_unit_requirements value = get_param(request.get_json(), 'unitRequirementIds') unit_requirement_ids = list(filter(None, value.split(','))) if isinstance( value, str) else value category = DegreeProgressCategory.update( category_id=category_id, course_units_lower=units_lower, course_units_upper=units_upper, description=description, parent_category_id=parent_category_id, name=name, unit_requirement_ids=unit_requirement_ids, ) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(category.template_id, current_user.get_id()) return tolerant_jsonify(category.to_api_json())
def toggle_campus_requirement(category_id): params = request.get_json() is_satisfied = get_param(params, 'isSatisfied') if is_satisfied is None: raise BadRequestError('Parameter \'isSatisfied\' is required') category = _get_degree_category(category_id) if category.category_type not in [ 'Campus Requirement, Satisfied', 'Campus Requirement, Unsatisfied' ]: raise BadRequestError('Category must be a \'Campus Requirement\' type') if ((category.category_type == 'Campus Requirement, Satisfied' and is_satisfied is True) or (category.category_type == 'Campus Requirement, Unsatisfied' and is_satisfied is False)): app.logger.info( f'Request ignored: set is_satisfied={is_satisfied} on {category.category_type}' ) else: category = DegreeProgressCategory.set_campus_requirement_satisfied( category_id=category_id, is_satisfied=is_satisfied, ) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(category.template_id, current_user.get_id()) return tolerant_jsonify(category.to_api_json())
def recommend_category(category_id): params = request.get_json() is_recommended = get_param(params, 'isRecommended') if is_recommended is None: raise BadRequestError('Parameter \'isRecommended\' is required') accent_color = normalize_accent_color(get_param(params, 'accentColor')) grade = get_param(params, 'grade') note = get_param(params, 'note') units_lower = get_param(params, 'unitsLower') units_upper = get_param(params, 'unitsUpper') category = DegreeProgressCategory.recommend( accent_color=accent_color, category_id=category_id, course_units_lower=units_lower, course_units_upper=units_upper, grade=grade, is_recommended=is_recommended, note=(note or '').strip() or None, ) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(category.template_id, current_user.get_id()) return tolerant_jsonify(category.to_api_json())
def delete_degree_category(category_id): category = _get_degree_category(category_id) DegreeProgressCategory.delete(category.id) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(category.template_id, current_user.get_id()) return tolerant_jsonify({'message': f'Template {category_id} deleted'}), 200
def assign_course(course_id): params = request.get_json() course = DegreeProgressCourse.find_by_id(course_id) if course: # Get existing category assignment. If it's a placeholder then delete it at end of transaction. previous_category = DegreeProgressCategory.find_by_id( course.category_id) if course.category_id else None category_id = get_param(params, 'categoryId') category = DegreeProgressCategory.find_by_id( category_id) if category_id else None if category: if category.template_id != course.degree_check_id: raise BadRequestError( 'The category and course do not belong to the same degree_check instance.' ) children = DegreeProgressCategory.find_by_parent_category_id( parent_category_id=category_id) if next((c for c in children if c.category_type == 'Subcategory'), None): raise BadRequestError( 'A course cannot be assigned to a category with a subcategory.' ) course = DegreeProgressCourse.assign(category_id=category_id, course_id=course.id) else: # When user un-assigns a course we delete all copies of that course,. for copy_of_course in DegreeProgressCourse.get_courses( degree_check_id=course.degree_check_id, manually_created_at=course.manually_created_at, manually_created_by=course.manually_created_by, section_id=course.section_id, sid=course.sid, term_id=course.term_id, ): if copy_of_course.id != course.id: DegreeProgressCourseUnitRequirement.delete( copy_of_course.id) category = DegreeProgressCategory.find_by_id( copy_of_course.category_id) if category and 'Placeholder' in category.category_type: DegreeProgressCategory.delete(category.id) DegreeProgressCourse.delete(copy_of_course) ignore = to_bool_or_none(get_param(params, 'ignore')) course = DegreeProgressCourse.unassign(course_id=course.id, ignore=ignore) # If previous assignment was a "placeholder" category then delete it. if previous_category and 'Placeholder' in previous_category.category_type: DegreeProgressCategory.delete(previous_category.id) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(course.degree_check_id, current_user.get_id()) return tolerant_jsonify(course.to_api_json()) else: raise ResourceNotFoundError('Course not found.')
def create_category(): params = request.get_json() category_type = get_param(params, 'categoryType') course_units_lower = get_param(params, 'unitsLower') course_units_upper = get_param(params, 'unitsUpper') description = get_param(params, 'description') name = get_param(params, 'name') parent_category_id = get_param(params, 'parentCategoryId') position = get_param(params, 'position') template_id = get_param(params, 'templateId') # Categories are mapped to degree_progress_unit_requirements value = get_param(request.get_json(), 'unitRequirementIds') unit_requirement_ids = list(filter(None, value.split(','))) if isinstance( value, str) else value if not category_type or not name or not _is_valid_position( position) or not template_id: raise BadRequestError( "Insufficient data: categoryType, name, position and templateId are required.'" ) if category_type in ['Category', 'Campus Requirements' ] and parent_category_id: raise BadRequestError(f'{category_type} cannot have a parent.') if category_type in ('Course Requirement', 'Subcategory') and not parent_category_id: raise BadRequestError( f"The parentCategoryId param is required when categoryType equals '{category_type}'." ) if parent_category_id: parent = _get_degree_category(parent_category_id) parent_type = parent.category_type if parent_type == 'Course Requirement' or ( parent_type == 'Subcategory' and category_type == 'Category'): raise BadRequestError( f'Type {category_type} not allowed, based on parent type: {parent_type}.' ) if position != parent.position: raise BadRequestError( f'Category position ({position}) must match its parent ({parent.position}).' ) category = _create_category( category_type=category_type, course_units_lower=course_units_lower, course_units_upper=course_units_upper, description=description, name=name, parent_category_id=parent_category_id, position=position, template_id=template_id, unit_requirement_ids=unit_requirement_ids, ) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(template_id, current_user.get_id()) return tolerant_jsonify(category.to_api_json())
def delete_unit_requirement(unit_requirement_id): unit_requirement = DegreeProgressUnitRequirement.find_by_id(unit_requirement_id) if unit_requirement: DegreeProgressUnitRequirement.delete(unit_requirement_id) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(unit_requirement.template_id, current_user.get_id()) return tolerant_jsonify({'message': f'Unit requirement {unit_requirement_id} deleted'}), 200 else: raise ResourceNotFoundError(f'No unit_requirement found with id={unit_requirement_id}.')
def update_degree_note(degree_check_id): params = request.get_json() body = get_param(params, 'body') note = DegreeProgressNote.upsert( body=body, template_id=degree_check_id, updated_by=current_user.get_id(), ) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(degree_check_id, current_user.get_id()) return tolerant_jsonify(note.to_api_json())
def update_unit_requirement(unit_requirement_id): params = request.get_json() name = params.get('name') min_units = params.get('minUnits') if not name or not min_units: raise BadRequestError('Unit requirement \'name\' and \'minUnits\' must be provided.') unit_requirement = DegreeProgressUnitRequirement.update( id_=unit_requirement_id, min_units=min_units, name=name, updated_by=current_user.get_id(), ) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(unit_requirement.template_id, current_user.get_id()) return tolerant_jsonify(unit_requirement.to_api_json())
def delete_course(course_id): course = DegreeProgressCourse.find_by_id(course_id) if course: # Verify that course is a copy matches = DegreeProgressCourse.get_courses( degree_check_id=course.degree_check_id, manually_created_at=course.manually_created_at, manually_created_by=course.manually_created_by, section_id=course.section_id, sid=course.sid, term_id=course.term_id, ) def _delete_course(c): category = DegreeProgressCategory.find_by_id(c.category_id) DegreeProgressCourseUnitRequirement.delete(c.id) DegreeProgressCourse.delete(c) if category and 'Placeholder' in category.category_type: DegreeProgressCategory.delete(category_id=category.id) matches = sorted(matches, key=lambda c: c.created_at) if matches[0].id == course.id: if course.manually_created_by: for match in matches: _delete_course(match) else: raise BadRequestError('Only copied courses can be deleted.') else: _delete_course(course) # Update updated_at date of top-level record DegreeProgressTemplate.refresh_updated_at(course.degree_check_id, current_user.get_id()) return tolerant_jsonify({'message': f'Course {course_id} deleted'}), 200 else: raise ResourceNotFoundError('Course not found.')