Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions osf/management/commands/migrate_funder_ids_to_ror.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def handle(self, *args, **options):
self.stdout.write(f" Records updated: {stats['updated']}")
self.stdout.write(f" Records re-indexed: {stats['reindexed']}")
self.stdout.write(f" Funders migrated: {stats['funders_migrated']}")
self.stdout.write(f" Funders not in mapping: {stats['not_in_mapping']}")
self.stdout.write(f" Unmapped funders removed: {stats['not_in_mapping']}")
if stats['errors']:
self.stdout.write(self.style.ERROR(f" Errors: {stats['errors']}"))

Expand Down Expand Up @@ -307,14 +307,15 @@ def migrate_record(self, record, mapping, dry_run, update_funder_name):
f'{funder_identifier} -> {ror_info["ror_id"]}'
)
else:
# No mapping found, keep original
updated_funding_info.append(funder)
# No mapping found, remove unmapped Crossref funder
record_modified = True
funder_stats['not_found'] += 1
funder_stats['unmapped_ids'].add(funder_identifier)

logger.warning(
f'No ROR mapping found for Crossref Funder ID: {funder_identifier} '
f'in record {record.guid._id}'
f'{"[DRY RUN] " if dry_run else ""}'
f'Removing unmapped Crossref Funder ID: {funder_identifier} '
f'from record {record.guid._id}'
)

# Warn about duplicate ROR IDs that would result from migration
Expand Down
20 changes: 8 additions & 12 deletions osf_tests/management_commands/test_migrate_funder_ids_to_ror.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ def test_migrate_multiple_funders(self, record_with_multiple_funders, csv_mappin
assert funders[2]['funder_identifier'] == 'https://ror.org/021nxhr62'
assert funders[2]['funder_identifier_type'] == 'ROR'

def test_unmapped_funder_preserved(self, record_with_unmapped_funder, csv_mapping_file):
"""Test that funders not in mapping are preserved unchanged."""
def test_unmapped_funder_removed(self, record_with_unmapped_funder, csv_mapping_file):
"""Test that funders not in mapping are removed."""
command = Command()
command.stdout = type('MockStdout', (), {'write': lambda self, x: None})()

Expand All @@ -214,17 +214,13 @@ def test_unmapped_funder_preserved(self, record_with_unmapped_funder, csv_mappin
update_funder_name=False
)

assert updated is False
assert updated is True
assert stats['migrated'] == 0
assert stats['not_found'] == 1
assert 'http://dx.doi.org/10.13039/999999999' in stats['unmapped_ids']

record_with_unmapped_funder.refresh_from_db()
funder = record_with_unmapped_funder.funding_info[0]

# Should be unchanged
assert funder['funder_identifier'] == 'http://dx.doi.org/10.13039/999999999'
assert funder['funder_identifier_type'] == 'Crossref Funder ID'
assert record_with_unmapped_funder.funding_info == []

def test_load_mapping_various_id_formats(self, csv_mapping_file):
"""Test that mapping handles various ID formats."""
Expand Down Expand Up @@ -347,17 +343,17 @@ def test_reindex_not_triggered_with_skip_flag(self, record_with_crossref_funder,
assert funder['funder_identifier'] == 'https://ror.org/01cwqze88'
assert funder['funder_identifier_type'] == 'ROR'

def test_reindex_not_triggered_for_unmapped_records(self, record_with_unmapped_funder, csv_mapping_file, mock_reindex):
"""Test that re-indexing is NOT triggered for records that weren't updated."""
def test_reindex_triggered_for_unmapped_records(self, record_with_unmapped_funder, csv_mapping_file, mock_reindex):
"""Test that re-indexing IS triggered when unmapped funders are removed."""
mock_update_search, mock_request_identifier_update = mock_reindex

call_command(
'migrate_funder_ids_to_ror',
'--csv-file', csv_mapping_file,
)

mock_update_search.assert_not_called()
mock_request_identifier_update.assert_not_called()
mock_update_search.assert_called()
mock_request_identifier_update.assert_called_with('doi')

def test_end_to_end_call_command(self, record_with_crossref_funder, record_with_multiple_funders, csv_mapping_file, mock_reindex):
"""Test the full management command end-to-end via call_command."""
Expand Down
Loading