diff --git a/src/identifiers/logic.py b/src/identifiers/logic.py index 03316da4f4..ac601dcda8 100755 --- a/src/identifiers/logic.py +++ b/src/identifiers/logic.py @@ -95,22 +95,25 @@ def register_batch_of_crossref_dois(articles): add_doi_logs(test_mode, articles) if use_crossref: - - identifiers = [] - for article in articles: - try: - identifier = article.get_identifier('doi', object=True) - if not identifier: - identifier = identifier_logic.generate_crossref_doi_with_pattern(article) - identifiers.append(identifier) - except AttributeError as e: - logger.debug(f'Error with article {article.pk}: {e}') - + identifiers = get_doi_identifiers_for_articles(articles) return send_crossref_deposit(test_mode, identifiers, journal) else: return 'Crossref Disabled', 'Disabled' +def get_doi_identifiers_for_articles(articles): + identifiers = [] + for article in articles: + try: + identifier = article.get_identifier('doi', object=True) + if not identifier: + identifier = generate_crossref_doi_with_pattern(article) + identifiers.append(identifier) + except AttributeError as e: + logger.debug(f'Error with article {article.pk}: {e}') + return identifiers + + def register_crossref_component(article, xml, supp_file): use_crossref = setting_handler.get_setting('Identifiers', 'use_crossref', article.journal).processed_value diff --git a/src/identifiers/migrations/0007_batch_doi_registration_20220315.py b/src/identifiers/migrations/0007_batch_doi_registration_20220315.py new file mode 100644 index 0000000000..077a8019ea --- /dev/null +++ b/src/identifiers/migrations/0007_batch_doi_registration_20220315.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2022-03-15 20:06 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + +def migrate_current_crossref_deposit_identifiers(apps, schema_editor): + CrossrefDeposit = apps.get_model("identifiers", "CrossrefDeposit") + for crossref_deposit in CrossrefDeposit.objects.all(): + if crossref_deposit.identifier: + crossref_deposit.identifiers.add(crossref_deposit.identifier) + +class Migration(migrations.Migration): + + dependencies = [ + ('identifiers', '0006_crossrefdeposit'), + ] + + operations = [ + migrations.AddField( + model_name='crossrefdeposit', + name='deposit', + field=models.TextField(blank=True, help_text='The deposit document with rendered XML for the DOI batch.', null=True), + ), + migrations.AddField( + model_name='crossrefdeposit', + name='identifiers', + field=models.ManyToManyField(to='identifiers.Identifier'), + ), + migrations.AlterField( + model_name='crossrefdeposit', + name='identifier', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='deposit_identifier', to='identifiers.Identifier'), + ), + migrations.RunPython(migrate_current_crossref_deposit_identifiers, reverse_code=migrations.RunPython.noop), + ] diff --git a/src/identifiers/models.py b/src/identifiers/models.py index c9dfda9cfb..0d001eb7d4 100755 --- a/src/identifiers/models.py +++ b/src/identifiers/models.py @@ -49,9 +49,16 @@ class CrossrefDeposit(models.Model): 2. If success is False, then all other flags except queued should be disregarded as non-useful. 3. If success is True but citation_success is False, then the deposit succeeded, but Crossref had trouble parsing some references for unknown reasons. + + The identifiers must all be for the same journal. """ - identifier = models.ForeignKey("identifiers.Identifier", on_delete=models.CASCADE) + identifiers = models.ManyToManyField("identifiers.Identifier") + deposit = models.TextField( + null=True, + blank=True, + help_text='The deposit document with rendered XML for the DOI batch.' + ) has_result = models.BooleanField(default=False) success = models.BooleanField(default=False) queued = models.BooleanField(default=False) @@ -61,16 +68,34 @@ class CrossrefDeposit(models.Model): date_time = models.DateTimeField(default=timezone.now) polling_attempts = models.PositiveIntegerField(default=0) + # Note: CrossrefDeposit.identifier is deprecated from version 1.4.2 + identifier = models.ForeignKey( + "identifiers.Identifier", + on_delete=models.CASCADE, + blank=True, + null=True, + related_name='deposit_identifier', # Required to avoid reverse accessor clashes + ) + + @property + def journal(self): + journals = set([identifier.article.journal for identifier in identifiers]) + if journals.count() > 1: + error = f'Identifiers from multiple journals passed to CrossrefDeposit: {journals}' + logger.debug(error) + else: + return journals.pop() + def poll(self): self.polling_attempts += 1 self.save() test_mode = setting_handler.get_setting('Identifiers', 'crossref_test', - self.identifier.article.journal).processed_value or settings.DEBUG + self.journal).processed_value or settings.DEBUG username = setting_handler.get_setting('Identifiers', 'crossref_username', - self.identifier.article.journal).processed_value + self.journal).processed_value password = setting_handler.get_setting('Identifiers', 'crossref_password', - self.identifier.article.journal).processed_value + self.journal).processed_value if test_mode: test_var = 'test' diff --git a/src/identifiers/tests/test_models.py b/src/identifiers/tests/test_models.py new file mode 100644 index 0000000000..63907ead75 --- /dev/null +++ b/src/identifiers/tests/test_models.py @@ -0,0 +1,30 @@ +from django.test import TestCase + +from identifiers import logic, models +from utils.testing import helpers +from utils.shared import clear_cache + + +class TestLogic(TestCase): + + @classmethod + def setUpTestData(cls): + + cls.press = helpers.create_press() + cls.journal_one, cls.journal_two = helpers.create_journals() + cls.ten_articles = [helpers.create_article(cls.journal_one) for i in range(10)] + cls.ten_identifiers = logic.get_doi_identifiers_for_articles(cls.ten_articles) + + + def test_crossref_deposit(self): + template = 'common/identifiers/crossref_doi_batch.xml' + template_context = logic.create_crossref_doi_batch_context( + self.journal_one, + set(self.ten_identifiers) + ) + deposit = logic.render_to_string(template, template_context) + crd = models.CrossrefDeposit( + [identifier.pk for identifier in self.ten_identifiers], + deposit=deposit, + ) + pass