diff --git a/cms/djangoapps/contentstore/management/commands/backfill_orgs_and_org_courses.py b/cms/djangoapps/contentstore/management/commands/backfill_orgs_and_org_courses.py index 7816380b47..2bfd535279 100644 --- a/cms/djangoapps/contentstore/management/commands/backfill_orgs_and_org_courses.py +++ b/cms/djangoapps/contentstore/management/commands/backfill_orgs_and_org_courses.py @@ -39,6 +39,56 @@ class Command(BaseCommand): > logo=None, > active=True, > ) + + Example run of command: + + root@studio:/edx/app/edxapp/edx-platform# ./manage.py cms backfill_orgs_and_org_courses + << ... lots of logging output ... >> + ------------------------------------------------------ + Dry-run of bulk-adding organizations... + Will create 5 organizations: + KyleX + KyleX2 + KyleX3 + KyleX4 + KyleX5 + Will reactivate 2 organizations: + BD04 + BD05 + ------------------------------------------------------ + Dry-run of bulk-adding organization-course linkages... + Will create 5 organization-course linkages: + kylex,course-v1:KyleX+OrgTest+1 + kylex2,course-v1:KyleX2+OrgTest+1 + kylex3,course-v1:KyleX3+OrgTest+1 + kylex4,course-v1:KyleX4+OrgTest+1 + kylex5,course-v1:KyleX5+OrgTest+1 + Will reactivate 0 organization-course linkages: + ------------------------------------------------------ + Commit changes shown above to the database [y/n]? x + Commit changes shown above to the database [y/n]? yes + ------------------------------------------------------ + Bulk-adding organizations... + Created 5 organizations: + KyleX + KyleX2 + KyleX3 + KyleX4 + KyleX5 + Reactivated 2 organizations: + BD04 + BD05 + ------------------------------------------------------ + Bulk-adding organization-course linkages... + Created 5 organization-course linkages: + kylex,course-v1:KyleX+OrgTest+1 + kylex2,course-v1:KyleX2+OrgTest+1 + kylex3,course-v1:KyleX3+OrgTest+1 + kylex4,course-v1:KyleX4+OrgTest+1 + kylex5,course-v1:KyleX5+OrgTest+1 + Reactivated 0 organization-course linkages: + ------------------------------------------------------ + root@studio:/edx/app/edxapp/edx-platform# """ # Make help message the first line of docstring. @@ -85,10 +135,7 @@ class Command(BaseCommand): if not confirm_changes(options, orgs, org_courseid_pairs): print("No changes applied.") return - print("Applying changes...") - organizations_api.bulk_add_organizations(orgs, dry_run=False) - organizations_api.bulk_add_organization_courses(org_courseid_pairs, dry_run=False) - print("Changes applied successfully.") + bulk_add_data(orgs, org_courseid_pairs, dry_run=False) def confirm_changes(options, orgs, org_courseid_pairs): @@ -111,8 +158,7 @@ def confirm_changes(options, orgs, org_courseid_pairs): raise CommandError("Only one of 'apply' and 'dry' may be specified") if options.get('apply'): return True - organizations_api.bulk_add_organizations(orgs, dry_run=True) - organizations_api.bulk_add_organization_courses(org_courseid_pairs, dry_run=True) + bulk_add_data(orgs, org_courseid_pairs, dry_run=True) if options.get('dry'): return False answer = "" @@ -121,6 +167,52 @@ def confirm_changes(options, orgs, org_courseid_pairs): return answer.lower().startswith('y') +def bulk_add_data(orgs, org_courseid_pairs, dry_run): + """ + Bulk-add the organizations and organization-course linkages. + + Print out list of organizations and organization-course linkages, + one per line. We distinguish between records that are added by + being created vs. those that are being added by just reactivating an + existing record. + + Arguments: + options (dict[str]): command-line arguments. + orgs (list[dict]): list of org data dictionaries to bulk-add. + org_courseid_pairs (list[tuple[dict, str]]): + list of (org data dictionary, course key string) links to bulk-add. + dry_run: Whether or not this run should be "dry" (ie, don't apply changes). + """ + adding_phrase = "Dry-run of bulk-adding" if dry_run else "Bulk-adding" + created_phrase = "Will create" if dry_run else "Created" + reactivated_phrase = "Will reactivate" if dry_run else "Reactivated" + + print("------------------------------------------------------") + print(f"{adding_phrase} organizations...") + orgs_created, orgs_reactivated = organizations_api.bulk_add_organizations( + orgs, dry_run=dry_run + ) + print(f"{created_phrase} {len(orgs_created)} organizations:") + for org_short_name in sorted(orgs_created): + print(f" {org_short_name}") + print(f"{reactivated_phrase} {len(orgs_reactivated)} organizations:") + for org_short_name in sorted(orgs_reactivated): + print(f" {org_short_name}") + + print("------------------------------------------------------") + print(f"{adding_phrase} organization-course linkages...") + linkages_created, linkages_reactivated = organizations_api.bulk_add_organization_courses( + org_courseid_pairs, dry_run=dry_run + ) + print(f"{created_phrase} {len(linkages_created)} organization-course linkages:") + for org_short_name, course_id in sorted(linkages_created): + print(f" {org_short_name},{course_id}") + print(f"{reactivated_phrase} {len(linkages_reactivated)} organization-course linkages:") + for org_short_name, course_id in sorted(linkages_reactivated): + print(f" {org_short_name},{course_id}") + print("------------------------------------------------------") + + def find_orgslug_courseid_pairs(): """ Returns the unique pairs of (organization short name, course run key string) diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_backfill_orgs_and_org_courses.py b/cms/djangoapps/contentstore/management/commands/tests/test_backfill_orgs_and_org_courses.py index 555a5c9702..976e0dbbfe 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_backfill_orgs_and_org_courses.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_backfill_orgs_and_org_courses.py @@ -140,8 +140,20 @@ class BackfillOrgsAndOrgCoursesTest(SharedModuleStoreTestCase): }, ) @ddt.unpack - @patch.object(organizations_api, 'bulk_add_organizations') - @patch.object(organizations_api, 'bulk_add_organization_courses') + @patch.object( + # Mock out `bulk_add_organizations` to do nothing and return empty + # lists, indicating no organizations created or reactivated. + organizations_api, + 'bulk_add_organizations', + return_value=([], []), + ) + @patch.object( + # Mock out `bulk_add_organization_courses` to do nothing and return empty + # lists, indicating no linkages created or reactivated. + organizations_api, + 'bulk_add_organization_courses', + return_value=([], []), + ) def test_arguments_and_input( self, mock_add_orgs,