From 0afd2ef8baa214b01aed5020220a94e5d5c0afa2 Mon Sep 17 00:00:00 2001
From: George Katsikas <giorgakis.katsikas@gmail.com>
Date: Thu, 12 Sep 2024 14:20:20 +0200
Subject: [PATCH] add proceedings metadata deposition tools

fixes #165
---
 scipost_django/journals/forms.py              | 119 +++++++++++++-----
 .../journals/_publication_actions.html        |   4 +-
 .../journals/_publication_preparation.html    |   2 +-
 .../create_proceedings_metadata_xml.html      |  70 +++++++++++
 ...l => create_publication_metadata_xml.html} |   2 +-
 .../journals/metadata_xml_deposit.html        |  38 +++---
 .../templates/xml/proceedings_crossref.html   | 113 +++++++++++++++++
 scipost_django/journals/urls/general.py       |   4 +-
 scipost_django/journals/views.py              |  40 +++++-
 9 files changed, 331 insertions(+), 61 deletions(-)
 create mode 100644 scipost_django/journals/templates/journals/create_proceedings_metadata_xml.html
 rename scipost_django/journals/templates/journals/{create_metadata_xml.html => create_publication_metadata_xml.html} (95%)
 create mode 100644 scipost_django/journals/templates/xml/proceedings_crossref.html

diff --git a/scipost_django/journals/forms.py b/scipost_django/journals/forms.py
index d5573a552..5d5f3fa1e 100644
--- a/scipost_django/journals/forms.py
+++ b/scipost_django/journals/forms.py
@@ -12,7 +12,7 @@ from datetime import datetime
 
 from django import forms
 from django.conf import settings
-from django.db.models import Q, Max
+from django.db.models import Q, Max, prefetch_related_objects
 from django.forms import BaseModelFormSet, modelformset_factory
 from django.template import loader
 from django.utils import timezone
@@ -305,12 +305,8 @@ class CreateMetadataXMLForm(forms.ModelForm):
         if cls.parser is None:
             cls.parser = ET.XMLParser(schema=cls.schema)
 
-    class Meta:
-        model = Publication
-        fields = ["metadata_xml"]
-
     def __init__(self, *args, **kwargs):
-        xml = self.new_xml(kwargs.get("instance"))
+        xml = self.generate_xml(kwargs.get("instance"))
         self.xml_str = self.format_xml(self.decode_html_entities(xml))
         kwargs["initial"] = {"metadata_xml": self.xml_str}
 
@@ -341,34 +337,11 @@ class CreateMetadataXMLForm(forms.ModelForm):
         self.instance.latest_metadata_update = timezone.now()
         return super().save(*args, **kwargs)
 
-    def new_xml(self, publication):
+    def generate_xml(self, object):
         """
         Create new XML structure, return as a string.
         """
-        # Create a doi_batch_id
-        salt = ""
-        for i in range(5):
-            salt = salt + random.choice(string.ascii_letters)
-        salt = salt.encode("utf8")
-        idsalt = publication.title[:10]
-        idsalt = idsalt.encode("utf8")
-        doi_batch_id = hashlib.sha1(salt + idsalt).hexdigest()
-
-        funders = (
-            Funder.objects.filter(grants__in=publication.grants.all())
-            | publication.funders_generic.all()
-        ).distinct()
-
-        # Render from template
-        template = loader.get_template("xml/publication_crossref.html")
-        context = {
-            "domain": get_current_domain(),
-            "publication": publication,
-            "doi_batch_id": doi_batch_id,
-            "deposit_email": settings.CROSSREF_DEPOSIT_EMAIL,
-            "funders": funders,
-        }
-        return template.render(context)
+        return ""
 
     def format_xml(self, xml_str: str) -> str:
         """
@@ -400,7 +373,81 @@ class CreateMetadataXMLForm(forms.ModelForm):
             return False, [str(error)], xml_str
 
 
-class CreateMetadataDOAJForm(forms.ModelForm):
+class CreatePublicationMetadataXMLForm(CreateMetadataXMLForm):
+
+    class Meta:
+        model = Publication
+        fields = ["metadata_xml"]
+
+    def generate_xml(self, publication):
+        # Create a doi_batch_id
+        salt = ""
+        for i in range(5):
+            salt = salt + random.choice(string.ascii_letters)
+        salt = salt.encode("utf8")
+        idsalt = publication.title[:10]
+        idsalt = idsalt.encode("utf8")
+        doi_batch_id = hashlib.sha1(salt + idsalt).hexdigest()
+
+        prefetch_related_objects(
+            [publication],
+            "authors__profile",
+            "authors__affiliations",
+            "grants",
+        )
+
+        funders = (
+            Funder.objects.filter(grants__in=publication.grants.all())
+            | publication.funders_generic.all()
+        ).distinct()
+
+        # Render from template
+        template = loader.get_template("xml/publication_crossref.html")
+        context = {
+            "domain": get_current_domain(),
+            "publication": publication,
+            "doi_batch_id": doi_batch_id,
+            "deposit_email": settings.CROSSREF_DEPOSIT_EMAIL,
+            "funders": funders,
+        }
+        return template.render(context)
+
+
+class CreateProceedingsMetadataXMLForm(CreateMetadataXMLForm):
+
+    class Meta:
+        model = Proceedings
+        fields = ["metadata_xml"]
+
+    def generate_xml(self, proceedings: "Proceedings"):
+        # Create a doi_batch_id
+        salt = ""
+        for i in range(5):
+            salt = salt + random.choice(string.ascii_letters)
+        salt = salt.encode("utf8")
+        idsalt = proceedings.event_name[:10]
+        idsalt = idsalt.encode("utf8")
+        doi_batch_id = hashlib.sha1(salt + idsalt).hexdigest()
+
+        prefetch_related_objects(
+            [proceedings],
+            "fellowships__contributor__profile",
+            "issue__publications__authors__profile",
+            "issue__publications__authors__affiliations",
+        )
+
+        # Render from template
+        template = loader.get_template("xml/proceedings_crossref.html")
+        context = {
+            "domain": get_current_domain(),
+            "proceedings": proceedings,
+            "doi_batch_id": doi_batch_id,
+            "deposit_email": settings.CROSSREF_DEPOSIT_EMAIL,
+        }
+        return template.render(context)
+
+
+class CreatePublicationMetadataDOAJForm(forms.ModelForm):
     class Meta:
         model = Publication
         fields = ["metadata_DOAJ"]
@@ -694,7 +741,9 @@ class DraftPublicationForm(forms.ModelForm):
 
             # Create supplementary information for any provided external links
             #! Refactor: may be possible to check if url is present in related publications
-            is_codebase = self.issue is None and "codebase" in self.to_journal.name.lower()
+            is_codebase = (
+                self.issue is None and "codebase" in self.to_journal.name.lower()
+            )
             if self.submission.code_repository_url and not is_codebase:
                 PublicationResource.objects.get_or_create(
                     publication=self.instance,
@@ -702,7 +751,9 @@ class DraftPublicationForm(forms.ModelForm):
                     url=self.submission.code_repository_url,
                     comments="Code repository",
                 )
-            is_datasets = self.issue is None and "datasets" in self.to_journal.name.lower()
+            is_datasets = (
+                self.issue is None and "datasets" in self.to_journal.name.lower()
+            )
             if self.submission.data_repository_url and not is_datasets:
                 PublicationResource.objects.get_or_create(
                     publication=self.instance,
diff --git a/scipost_django/journals/templates/journals/_publication_actions.html b/scipost_django/journals/templates/journals/_publication_actions.html
index b72b5a569..93aec8fa1 100644
--- a/scipost_django/journals/templates/journals/_publication_actions.html
+++ b/scipost_django/journals/templates/journals/_publication_actions.html
@@ -31,7 +31,7 @@
     <div>Crossref</div>
     <ul>
       <li>
-        <a href="{% url 'journals:create_metadata_xml' publication.doi_label %}">Create/update the XML metadata</a>
+        <a href="{% url 'journals:create_publication_metadata_xml' publication.doi_label %}">Create/update the XML metadata</a>
       </li>
       <li>
         <a href="{% url 'journals:metadata_xml_deposit' publication.doi_label 'deposit' %}">Deposit the metadata to Crossref</a>
@@ -75,7 +75,7 @@
         <a href="{% url 'journals:manage_publication_resources' publication.doi_label %}">Manage publication resources</a>
       </li>
       <li>
-	<a href="{% url 'journals:define_pubfracs' publication.doi_label %}">Define PubFracs (balanced affiliations algorithm)</a>
+        <a href="{% url 'journals:define_pubfracs' publication.doi_label %}">Define PubFracs (balanced affiliations algorithm)</a>
       </li>
       <li>
         <a href="{% url 'journals:adjust_pubfracs' publication.doi_label %}">Adjust PubFracs</a>
diff --git a/scipost_django/journals/templates/journals/_publication_preparation.html b/scipost_django/journals/templates/journals/_publication_preparation.html
index 2da316ae8..4cd448b93 100644
--- a/scipost_django/journals/templates/journals/_publication_preparation.html
+++ b/scipost_django/journals/templates/journals/_publication_preparation.html
@@ -10,7 +10,7 @@
   <li>{% if publication.has_citation_list %}<span class="text-success">{% include 'bi/check-square-fill.html' %}</span>{% else %}{% include 'bi/square.html' %}{% endif %}<a href="{% url 'journals:create_citation_list_metadata' publication.doi_label %}">Create/update citation metadata</a></li>
   <li>{% if publication.has_funding_statement %}<span class="text-success">{% include 'bi/check-square-fill.html' %}</span>{% else %}{% include 'bi/square.html' %}{% endif %}<a href="{% url 'journals:create_funding_info_metadata' publication.doi_label %}">Create/update funding info metadata</a></li>
   <li>{% if publication.grants.exists %}<span class="text-success">{% include 'bi/check-square-fill.html' %}</span>{% else %}{% include 'bi/square.html' %}{% endif %}<a href="{% url 'journals:update_grants' publication.doi_label %}">Create/update grants</a></li>
-  <li>{% if publication.has_xml_metadata %}<span class="text-success">{% include 'bi/check-square-fill.html' %}</span>{% else %}{% include 'bi/square.html' %}{% endif %}<a href="{% url 'journals:create_metadata_xml' publication.doi_label %}">Create/update Crossref metadata</a> <em>(please do after citation and funding info are added)</em></li>
+  <li>{% if publication.has_xml_metadata %}<span class="text-success">{% include 'bi/check-square-fill.html' %}</span>{% else %}{% include 'bi/square.html' %}{% endif %}<a href="{% url 'journals:create_publication_metadata_xml' publication.doi_label %}">Create/update Crossref metadata</a> <em>(please do after citation and funding info are added)</em></li>
   {% comment %} <li>{% if publication.references.exists %}<span class="text-success">{% include 'bi/check-square-fill.html' %}</span>{% else %}{% include 'bi/square.html' %}{% endif %}<a href="{% url 'journals:update_references' doi_label=publication.doi_label %}">Create/update references</a></li> {% endcomment %}
 </ul>
 
diff --git a/scipost_django/journals/templates/journals/create_proceedings_metadata_xml.html b/scipost_django/journals/templates/journals/create_proceedings_metadata_xml.html
new file mode 100644
index 000000000..784e969d2
--- /dev/null
+++ b/scipost_django/journals/templates/journals/create_proceedings_metadata_xml.html
@@ -0,0 +1,70 @@
+{% extends 'scipost/base.html' %}
+
+{% block pagetitle %}
+  : Create metadata xml
+{% endblock pagetitle %}
+
+{% block breadcrumb %}
+  <div class="breadcrumb-container">
+    <div class="container">
+      <nav class="breadcrumb hidden-sm-down">
+        <a href="{% url 'journals:journals' %}" class="breadcrumb-item">Journals</a>
+        <a href="{% url 'journals:manage_metadata' %}" class="breadcrumb-item">Administration</a>
+        <span class="breadcrumb-item active">Create metadata XML</span>
+      </nav>
+    </div>
+  </div>
+{% endblock %}
+
+{% load bootstrap %}
+
+{% block content %}
+
+  <div class="row">
+    <div class="col-12">
+      <h1 class="highlight">Create metadata XML (for Crossref deposit)</h1>
+      <p>
+        The following field is prefilled with data from the Proceedings object, formatted for readability. Once you accept them, they will be flattened to a single line and overwrite the current metadata shown below.
+      </p>
+      <br />
+      <form action="{% url 'journals:create_proceedings_metadata_xml' proceedings.pk %}"
+            method="post">
+        {% csrf_token %}
+        {{ form|bootstrap }}
+
+        {% if errors %}
+          <div class="bg-danger bg-opacity-10 p-3 mb-2">
+            <span class="fw-bold me-2">XML validation result:</span>
+            <ul class="mb-0">
+
+              {% for error in errors %}<li>{{ error }}</li>{% endfor %}
+
+            </ul>
+          </div>
+          <div class="bg-warning bg-opacity-10 p-3 mb-2">
+            <span class="fw-bold me-2">Add publication date</span>
+            <p class="mb-0">
+              Some errors were found during XML validation. This may be due to missing publication date,
+              which you can add by <a href="{% url 'proceedings:proceedings_edit' proceedings.pk %}">editing the proceedings</a>.
+            </p>
+          </div>
+        {% else %}
+          <div class="bg-success bg-opacity-10 p-3 mb-2">
+            <span class="fw-bold me-2">XML validation result:</span>
+            Valid
+          </div>
+        {% endif %}
+
+        <input type="submit" class="btn btn-primary" value="Accept the metadata" />
+        <a href="{% url 'journals:manage_metadata' %}" class="ms-3 btn btn-link">Back to Admin</a>
+      </form>
+
+      <hr class="divider" />
+
+      <h3>Current metadata xml</h3>
+      <br />
+      <pre><code>{{ proceedings.metadata_xml|linebreaksbr }}</code></pre>
+    </div>
+  </div>
+
+{% endblock content %}
diff --git a/scipost_django/journals/templates/journals/create_metadata_xml.html b/scipost_django/journals/templates/journals/create_publication_metadata_xml.html
similarity index 95%
rename from scipost_django/journals/templates/journals/create_metadata_xml.html
rename to scipost_django/journals/templates/journals/create_publication_metadata_xml.html
index dc21fce32..af010cd25 100644
--- a/scipost_django/journals/templates/journals/create_metadata_xml.html
+++ b/scipost_django/journals/templates/journals/create_publication_metadata_xml.html
@@ -27,7 +27,7 @@
         The following field is prefilled with data from the Publication object, formatted for readability. Once you accept them, they will be flattened to a single line and overwrite the current metadata shown below.
       </p>
       <br />
-      <form action="{% url 'journals:create_metadata_xml' publication.doi_label %}"
+      <form action="{% url 'journals:create_publication_metadata_xml' publication.doi_label %}"
             method="post">
         {% csrf_token %}
         {{ form|bootstrap }}
diff --git a/scipost_django/journals/templates/journals/metadata_xml_deposit.html b/scipost_django/journals/templates/journals/metadata_xml_deposit.html
index ad147d91c..f194f8d81 100644
--- a/scipost_django/journals/templates/journals/metadata_xml_deposit.html
+++ b/scipost_django/journals/templates/journals/metadata_xml_deposit.html
@@ -1,6 +1,8 @@
 {% extends 'scipost/base.html' %}
 
-{% block pagetitle %}: metadata XML deposit{% endblock pagetitle %}
+{% block pagetitle %}
+  : metadata XML deposit
+{% endblock pagetitle %}
 
 {% block breadcrumb %}
   <div class="breadcrumb-container">
@@ -19,7 +21,9 @@
 
   <div class="row">
     <div class="col-12">
-      <h1 class="highlight">Metadata deposit <small>(using the {{ option }} server)</small></h1>
+      <h1 class="highlight">
+        Metadata deposit <small>(using the {{ option }} server)</small>
+      </h1>
     </div>
   </div>
 
@@ -34,8 +38,10 @@
         <pre><code>{{ response_text|linebreaks }}</code></pre>
 
         {% if perms.scipost.can_publish_accepted_submission %}
-          <br>
-          <p><a href="{{publication.get_absolute_url}}">return to the publication's page</a>, to the <a href="{% url 'journals:manage_metadata' %}">general metadata management page</a></p>
+          <br />
+          <p>
+            <a href="{{ publication.get_absolute_url }}">return to the publication's page</a>, to the <a href="{% url 'journals:manage_metadata' %}">general metadata management page</a>
+          </p>
         {% endif %}
 
 
@@ -45,18 +51,20 @@
     <div class="row">
       <div class="col-12">
         <p>
-          <span class="text-danger">The metadata file for this metadata timestamp already exists.</span><br>
-          You might want to <a href="{% url 'journals:create_metadata_xml' doi_label=publication.doi_label %}">produce new metadata</a> to do a new deposit instead.
+          <span class="text-danger">The metadata file for this metadata timestamp already exists.</span>
+          <br />
+          You might want to <a href="{% url 'journals:create_publication_metadata_xml' doi_label=publication.doi_label %}">produce new metadata</a> to do a new deposit instead.
           <p>
 
-          {% if perms.scipost.can_publish_accepted_submission %}
-          <p>
-            <a href="{% url 'journals:manage_metadata' %}">Back to Admin</a>
-          </p>
-          {% endif %}
-      </div>
-    </div>
-  {% endif %}
+            {% if perms.scipost.can_publish_accepted_submission %}
+              <p>
+                <a href="{% url 'journals:manage_metadata' %}">Back to Admin</a>
+              </p>
+            {% endif %}
 
+          </div>
+        </div>
+      {% endif %}
 
-{% endblock %}
+
+    {% endblock %}
diff --git a/scipost_django/journals/templates/xml/proceedings_crossref.html b/scipost_django/journals/templates/xml/proceedings_crossref.html
new file mode 100644
index 000000000..388859ab9
--- /dev/null
+++ b/scipost_django/journals/templates/xml/proceedings_crossref.html
@@ -0,0 +1,113 @@
+{% spaceless %}
+<?xml version="1.0" encoding="UTF-8"?>
+<doi_batch version="5.3.1" xmlns="http://www.crossref.org/schema/5.3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:fr="http://www.crossref.org/fundref.xsd" xsi:schemaLocation="http://www.crossref.org/schema/5.3.1 http://www.crossref.org/shema/deposit/crossref5.3.1.xsd" xmlns:ai="http://www.crossref.org/AccessIndicators.xsd" xmlns:jats="http://www.ncbi.nlm.nih.gov/JATS1" xmlns:mml="http://www.w3.org/1998/Math/MathML">
+    <head>
+        <doi_batch_id>{{ doi_batch_id }}</doi_batch_id>
+        <timestamp>{% now "YmdHis" %}</timestamp>
+        <depositor>
+            <depositor_name>scipost</depositor_name>
+            <email_address>{{ deposit_email }}</email_address>
+        </depositor>
+        <registrant>scipost</registrant>
+    </head>
+    <body>
+      <conference>
+        <contributors>
+          {% if proceedings.lead_fellow %} <!-- If there is a lead fellow, we put them first -->
+            <person_name sequence="first" contributor_role="editor">
+              <given_name>{{ proceedings.lead_fellow.contributor.profile.first_name }}</given_name>
+              <surname>{{ proceedings.lead_fellow.contributor.profile.last_name }}</surname>
+            </person_name>
+            {% for fellow in proceedings.fellowships.all %}
+              {% if not fellow == proceedings.lead_fellow %}
+                <person_name sequence="additional" contributor_role="editor">
+                  <given_name>{{ fellow.contributor.profile.first_name }}</given_name>
+                  <surname>{{ fellow.contributor.profile.last_name }}</surname>
+                </person_name>
+              {% endif %}
+            {% endfor %}
+          {% else %} <!-- If there is no lead fellow, we list them in default order -->
+            {% for fellow in proceedings.fellowships.all %}
+              <person_name sequence="{% if forloop.first %}first{% else %}additional{% endif %}" contributor_role="editor">
+                <given_name>{{ fellow.contributor.profile.first_name }}</given_name>
+                <surname>{{ fellow.contributor.profile.last_name }}</surname>
+              </person_name>
+            {% endfor %}
+          {% endif %}
+          <person_name sequence="first" contributor_role="editor">
+            <given_name>Elvira</given_name>
+            <surname>Drolbman</surname>
+          </person_name>
+        </contributors>
+        <event_metadata>
+          <conference_name>{{ proceedings.event_name }}</conference_name>
+          <conference_acronym>{{ proceedings.event_suffix }}</conference_acronym>
+          <conference_date start_month="{{ proceedings.event_start_date|date:'m' }}" start_year="{{ proceedings.event_start_date|date:'Y' }}" start_day="{{ proceedings.event_start_date|date:'d' }}" end_month="{{ proceedings.event_end_date|date:'m' }}" end_year="{{ proceedings.event_end_date|date:'Y' }}" end_day="{{ proceedings.event_end_date|date:'d' }}">
+            {{ proceedings.event_start_date|date:'Y-m-d' }} to {{ proceedings.event_end_date|date:'Y-m-d' }}
+          </conference_date>
+        </event_metadata>
+        <proceedings_metadata language="en">
+          <proceedings_title>Proceedings of the {{ proceedings.event_name }}</proceedings_title>
+          <publisher>
+            <publisher_name>SciPost</publisher_name>
+            <publisher_place>Amsterdam, The Netherlands</publisher_place>
+          </publisher>
+          {% if proceedings.publication_date %}
+            <publication_date media_type="online">
+              <month>{{ proceedings.publication_date|date:'m' }}</month>
+              <day>{{ proceedings.publication_date|date:'d' }}</day>
+              <year>{{ proceedings.publication_date|date:'Y' }}</year>
+            </publication_date>
+          {% endif %}
+          <noisbn reason="simple_series"/>
+          <doi_data>
+            <doi>{{ proceedings.issue.doi_string }}</doi>
+            <resource>https://{{ domain }}/{{ proceedings.issue.doi_string }}</resource>
+          </doi_data>
+        </proceedings_metadata>
+        {% for publication in proceedings.issue.publications.all %}
+          <conference_paper publication_type="full_text">
+            <contributors>
+              {% for publication_author in publication.authors.all %}
+                {% include "xml/_person_name_crossref.html" with  publication_author=publication_author%}
+              {% endfor %}
+            </contributors>
+            <titles>
+              <title>{{ publication.title }}</title>
+            </titles>
+            <publication_date media_type="online">
+              <month>{{ publication.publication_date|date:'m' }}</month>
+              <day>{{ publication.publication_date|date:'d' }}</day>
+              <year>{{ publication.publication_date|date:'Y' }}</year>
+            </publication_date>
+            <doi_data>
+              <doi>{{ publication.doi_string }}</doi>
+              <resource>https://{{ domain }}/{{ publication.doi_string }}</resource>
+              {% if publication.pdf_file %}
+                <collection property='crawler-based'>
+                  <item crawler='iParadigms'>
+                    <resource>https://{{ domain }}/{{ publication.doi_string }}/pdf</resource>
+                  </item>
+                </collection>
+                <collection property='text-mining'>
+                  <item>
+                    <resource mime_type='application/pdf'>https://{{ domain }}/{{ publication.doi_string }}/pdf</resource>
+                  </item>
+                </collection>
+              {% endif %}
+            </doi_data>
+            {% if publication.metadata.citation_list %}
+                <citation_list>
+                    {% for ref in publication.metadata.citation_list %}
+                        <citation key="{{ ref.key }}">
+                            <doi>{{ ref.doi }}</doi>
+                        </citation>
+                    {% endfor %}
+                </citation_list>
+            {% endif %}
+          </conference_paper>
+        {% endfor %}
+      </conference>
+    </body>
+</doi_batch>
+{% endspaceless %}
diff --git a/scipost_django/journals/urls/general.py b/scipost_django/journals/urls/general.py
index f59b77266..603659cf1 100644
--- a/scipost_django/journals/urls/general.py
+++ b/scipost_django/journals/urls/general.py
@@ -267,8 +267,8 @@ urlpatterns = [
     ),
     path(
         "admin/<publication_doi_label:doi_label>/metadata/crossref/create",
-        journals_views.CreateMetadataXMLView.as_view(),
-        name="create_metadata_xml",
+        journals_views.CreatePublicationMetadataXMLView.as_view(),
+        name="create_publication_metadata_xml",
     ),
     path(
         "admin/<publication_doi_label:doi_label>/metadata/crossref/deposit/<str:option>",
diff --git a/scipost_django/journals/views.py b/scipost_django/journals/views.py
index af2337e4b..f99a177e3 100644
--- a/scipost_django/journals/views.py
+++ b/scipost_django/journals/views.py
@@ -14,6 +14,7 @@ import requests
 
 import matplotlib
 
+from proceedings.models import Proceedings
 from scipost.permissions import HTMXPermissionsDenied, HTMXResponse
 from submissions.models.decision import EditorialDecision
 
@@ -72,6 +73,8 @@ from .models import (
 from .forms import (
     AbstractJATSForm,
     CitationListItemForm,
+    CreateProceedingsMetadataXMLForm,
+    CreatePublicationMetadataXMLForm,
     DraftPublicationUpdateForm,
     FundingInfoForm,
     HTMXInlinePublicationResourceForm,
@@ -81,7 +84,7 @@ from .forms import (
     CreateMetadataXMLForm,
     CitationListBibitemsForm,
     ReferenceFormSet,
-    CreateMetadataDOAJForm,
+    CreatePublicationMetadataDOAJForm,
     DraftPublicationForm,
     PublicationGrantsForm,
     DraftAccompanyingPublicationForm,
@@ -1321,7 +1324,7 @@ def _hx_publication_metadata_delete_generic_funding(request, doi_label, funder_i
     return HttpResponse("")
 
 
-class CreateMetadataXMLView(
+class CreatePublicationMetadataXMLView(
     PublicationMixin, ProdSupervisorPublicationPermissionMixin, UpdateView
 ):
     """
@@ -1331,8 +1334,8 @@ class CreateMetadataXMLView(
     The contents can then be sent to Crossref for registration.
     """
 
-    form_class = CreateMetadataXMLForm
-    template_name = "journals/create_metadata_xml.html"
+    form_class = CreatePublicationMetadataXMLForm
+    template_name = "journals/create_publication_metadata_xml.html"
 
     def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
         context = super().get_context_data(**kwargs)
@@ -1342,6 +1345,28 @@ class CreateMetadataXMLView(
         return {**context, "valid": valid, "errors": errors, "xml_str": xml_str}
 
 
+class CreateProceedingsMetadataXMLView(UpdateView):
+    """
+    To be called by an EdAdmin (or Production Supervisor) after all proceedings
+    publications have been published. Populates the metadata_xml field of a Proceedings instance.
+    The contents can then be sent to Crossref for registration.
+    """
+
+    model = Proceedings
+    form_class = CreateProceedingsMetadataXMLForm
+    template_name = "journals/create_proceedings_metadata_xml.html"
+
+    def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
+        context = super().get_context_data(**kwargs)
+        form = context["form"]
+        valid, errors, xml_str = form.validate_xml(form.xml_str)
+
+        return {**context, "valid": valid, "errors": errors, "xml_str": xml_str}
+
+    def get_success_url(self) -> str:
+        return reverse("journals:manage_proceedings_metadata")
+
+
 @permission_required("scipost.can_draft_publication", return_403=True)
 @transaction.atomic
 def metadata_xml_deposit(request, doi_label, option="test"):
@@ -1370,7 +1395,7 @@ def metadata_xml_deposit(request, doi_label, option="test"):
         )
         return redirect(
             reverse(
-                "journals:create_metadata_xml",
+                "journals:create_publication_metadata_xml",
                 kwargs={"doi_label": publication.doi_label},
             )
         )
@@ -1484,7 +1509,7 @@ def mark_deposit_success(request, deposit_id, success):
 @permission_required("scipost.can_publish_accepted_submission", return_403=True)
 def produce_metadata_DOAJ(request, doi_label):
     publication = get_object_or_404(Publication, doi_label=doi_label)
-    form = CreateMetadataDOAJForm(
+    form = CreatePublicationMetadataDOAJForm(
         request.POST or None, instance=publication, request=request
     )
     if form.is_valid():
@@ -1898,6 +1923,7 @@ def generic_metadata_xml_deposit(request, **kwargs):
     * Reports
     * Comments
     * PublicationUpdates
+    * Proceedings
 
     The metadata is created and immediately deposited at Crossref.
 
@@ -1907,6 +1933,8 @@ def generic_metadata_xml_deposit(request, **kwargs):
 
     For PublicationUpdates, the deposit type is `journal_article` and
     the journal is used as container.
+
+    For Proceedings, the deposit type is `conference`.
     """
     domain = get_current_domain()
 
-- 
GitLab