From b39ceb4e56c7a42f3469d765088fa47fafa8edfd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jean-S=C3=A9bastien=20Caux?= <git@jscaux.org>
Date: Sun, 17 Mar 2024 21:30:38 +0100
Subject: [PATCH] Display PubFracs table only for Organizations that have them

---
 scipost_django/organizations/models.py        |   4 +
 .../organizations/_organization_card.html     | 211 +++++++++---------
 2 files changed, 110 insertions(+), 105 deletions(-)

diff --git a/scipost_django/organizations/models.py b/scipost_django/organizations/models.py
index 1836bc257..ec53cb080 100644
--- a/scipost_django/organizations/models.py
+++ b/scipost_django/organizations/models.py
@@ -394,6 +394,10 @@ class Organization(models.Model):
             "total": fractions.aggregate(Sum("fraction"))["fraction__sum"],
         }
 
+    def has_pubfracs(self):
+        """Whether this Organization is mentioned in any author affiliation."""
+        return self.pubfracs.exists()
+
     @property
     def has_current_subsidy(self):
         """
diff --git a/scipost_django/organizations/templates/organizations/_organization_card.html b/scipost_django/organizations/templates/organizations/_organization_card.html
index 1c6993869..7269ce906 100644
--- a/scipost_django/organizations/templates/organizations/_organization_card.html
+++ b/scipost_django/organizations/templates/organizations/_organization_card.html
@@ -260,117 +260,118 @@
 
 
 
+	  {% if not organization.has_pubfracs %}
+	    <p>PubFracs are not defined for this Organization, since it does not appear as author affiliation in any Publication.</p>
+	  {% else %}
+	    <table class="table caption-top">
+	      <caption>Based on PubFracs for {{ organization }}</caption>
+	      <thead class="table-light">
+		<tr>
+		  <th>Year (click to toggle details)</th>
+		  <th class="text-end">NAP</th>
+		  <th class="text-end">PubFrac<br>expenditures</th>
+		  <th class="text-end">Subsidy<br>support</th>
+		  <th class="text-end">Compensations (self)</th>
+		  <th class="text-end">Reserved</th>
+		  <th class="text-end">Compensations (Allies)</th>
+		  <th class="text-end">Balance</th>
+		</tr>
+	      </thead>
+	      <tbody>
+		<tr class="table-light">
+		  <td>Cumulative</td>
+		  <td class="text-end">{{ balance.cumulative.nap }}</td>
+		  <td class="text-end">&euro;{{ balance.cumulative.expenditures }}</td>
+		  <td class="text-end">&euro;{{ balance.cumulative.subsidy_income }}</td>
+		  <td class="text-end">&euro;{{ balance.cumulative.self_compensated }}</td>
+		  <td class="text-end">&euro;{{ balance.cumulative.reserved }}</td>
+		  <td class="text-end">&euro;{{ balance.cumulative.ally_compensated }}</td>
+		  <td class="text-end bg-{% if balance.cumulative.balance < 0 %}danger{% else %}success{% endif %} bg-opacity-25">
+		    &euro;{{ balance.cumulative.balance }}
+		  </td>
+		</tr>
+		{% now "Y" as current_year %}
+		{% for year in pubyears %}
+		  {% for key, val in balance.items %}
+		    {% if year == key|add:"0" %}
+		      <tr>
+			<td>
+			  <a class="mx-1 my-0 p-0" data-bs-toggle="collapse" href="#details-{{ year }}" role="button" aria-expanded="false" aria-controls="details-{{ year }}">{{ key }}{% if key == current_year %}&emsp;(ongoing){% endif %}</a>
+			</td>
+			<td class="text-end">{{ val.expenditures.total.nap }}</td>
+			<td class="text-end">
+			  &euro;{{ val.expenditures.total.expenditures }}
+			</td>
+			<td class="text-end">&euro;{{ val.subsidy_income }}</td>
+			<td class="text-end">
+			  &euro;{{ val.expenditures.total.self_compensated }}
+			</td>
+			<td class="text-end">&euro;{{ val.reserved }}</td>
+			<td class="text-end">
+			  &euro;{{ val.expenditures.total.ally_compensated }}
+			</td>
+			<td class="text-end bg-{% if val.balance < 0 %}danger{% else %}success{% endif %} bg-opacity-25">
+			  &euro;{{ val.balance }}
+			</td>
+		      </tr>
+		      <tr class="collapse" id="details-{{ year }}">
+			<td class="pe-0" colspan="8">
+			  <div class="ms-4 me-0 p-2 border border-secondary">
 
+			    <p>The following table give an overview of expenditures and their compensation, compiled for all Publications which are associated to {{ organization }} for {{ year }}.</p>
 
-	  <table class="table caption-top">
-	    <caption>Based on PubFracs for {{ organization }}</caption>
-	    <thead class="table-light">
-	      <tr>
-		<th>Year (click to toggle details)</th>
-		<th class="text-end">NAP</th>
-		<th class="text-end">PubFrac<br>expenditures</th>
-		<th class="text-end">Subsidy<br>support</th>
-		<th class="text-end">Compensations (self)</th>
-		<th class="text-end">Reserved</th>
-		<th class="text-end">Compensations (Allies)</th>
-		<th class="text-end">Balance</th>
-	      </tr>
-	    </thead>
-	    <tbody>
-	      <tr class="table-light">
-		<td>Cumulative</td>
-		<td class="text-end">{{ balance.cumulative.nap }}</td>
-		<td class="text-end">&euro;{{ balance.cumulative.expenditures }}</td>
-		<td class="text-end">&euro;{{ balance.cumulative.subsidy_income }}</td>
-		<td class="text-end">&euro;{{ balance.cumulative.self_compensated }}</td>
-		<td class="text-end">&euro;{{ balance.cumulative.reserved }}</td>
-		<td class="text-end">&euro;{{ balance.cumulative.ally_compensated }}</td>
-		<td class="text-end bg-{% if balance.cumulative.balance < 0 %}danger{% else %}success{% endif %} bg-opacity-25">
-		  &euro;{{ balance.cumulative.balance }}
-		</td>
-	      </tr>
-	      {% now "Y" as current_year %}
-	      {% for year in pubyears %}
-		{% for key, val in balance.items %}
-		  {% if year == key|add:"0" %}
-		    <tr>
-		      <td>
-			<a class="mx-1 my-0 p-0" data-bs-toggle="collapse" href="#details-{{ year }}" role="button" aria-expanded="false" aria-controls="details-{{ year }}">{{ key }}{% if key == current_year %}&emsp;(ongoing){% endif %}</a>
-		      </td>
-		      <td class="text-end">{{ val.expenditures.total.nap }}</td>
-		      <td class="text-end">
-			&euro;{{ val.expenditures.total.expenditures }}
-		      </td>
-		      <td class="text-end">&euro;{{ val.subsidy_income }}</td>
-		      <td class="text-end">
-			&euro;{{ val.expenditures.total.self_compensated }}
-		      </td>
-		      <td class="text-end">&euro;{{ val.reserved }}</td>
-		      <td class="text-end">
-			&euro;{{ val.expenditures.total.ally_compensated }}
-		      </td>
-		      <td class="text-end bg-{% if val.balance < 0 %}danger{% else %}success{% endif %} bg-opacity-25">
-			&euro;{{ val.balance }}
-		      </td>
-		    </tr>
-		    <tr class="collapse" id="details-{{ year }}">
-		      <td class="pe-0" colspan="8">
-			<div class="ms-4 me-0 p-2 border border-secondary">
-
-			  <p>The following table give an overview of expenditures and their compensation, compiled for all Publications which are associated to {{ organization }} for {{ year }}.</p>
-
-			  <p>You can see the list of associated publications and their PubFracs under the <em>Publications & PubFracs</em> tab.</p>
-			  <p>The data presented here uses PubFracs directly associated to {{ organization }}.</p>
+			    <p>You can see the list of associated publications and their PubFracs under the <em>Publications & PubFracs</em> tab.</p>
+			    <p>The data presented here uses PubFracs directly associated to {{ organization }}.</p>
 
-			  <table class="table table-bordered caption-top mb-0">
-			    <caption>Expenditures ({{ organization }})</caption>
-			    <thead class="table-secondary">
-			      <tr>
-				<th>Journal</th>
-				<th class="text-end">APEX</th>
-				<th class="text-end">NAP</th>
-				<th class="text-end">PubFracs</th>
-				<th class="text-end">Expenditures share</th>
-				<th class="text-end">Compensations<br>(Organization)</th>
-				<th class="text-end">Compensations<br>(Allies)</th>
-				<th class="text-end">Balance<br>(uncompensated)</th>
-			      </tr>
-			    </thead>
-			    <tbody>
-			      {% for journal, journaldata in val.expenditures.per_journal.items %}
+			    <table class="table table-bordered caption-top mb-0">
+			      <caption>Expenditures ({{ organization }})</caption>
+			      <thead class="table-secondary">
 				<tr>
-				  <td>{{ journal }}</td>
-				  <td class="text-end">&euro;{{ journaldata.costperpaper }}</td>
-				  <td class="text-end">{{ journaldata.nap }}</td>
-				  <td class="text-end">{{ journaldata.pubfracs }}</td>
-				  <td class="text-end">&euro;{{ journaldata.expenditures }}</td>
-				  <td class="text-end">&euro;{{ journaldata.self_compensated }}</td>
-				  <td class="text-end">&euro;{{ journaldata.ally_compensated }}</td>
-				  {% if journaldata.uncompensated > 0 %}
-				    <td class="bg-danger bg-opacity-25 text-end">-&euro;{{ journaldata.uncompensated }}</td>
-				  {% else %}
-				    <td class="bg-success bg-opacity-25 text-end">&euro;{{ journaldata.uncompensated }}</td>
-				  {% endif %}
+				  <th>Journal</th>
+				  <th class="text-end">APEX</th>
+				  <th class="text-end">NAP</th>
+				  <th class="text-end">PubFracs</th>
+				  <th class="text-end">Expenditures share</th>
+				  <th class="text-end">Compensations<br>(Organization)</th>
+				  <th class="text-end">Compensations<br>(Allies)</th>
+				  <th class="text-end">Balance<br>(uncompensated)</th>
 				</tr>
-			      {% endfor %}
-			    </tbody>
-			  </table>
-			  <details class="ms-2 mb-2">
-			    <summary>
-			      Info on this table
-			    </summary>
-			    <p class="mt-1">This <strong>Expenditures (Organization-level)</strong> table compiles the expenditures by SciPost to publish all papers which are associated to this Organization for {{ year }}, weighed by this Organization's PubFracs for these individual papers. The next columns detail the compensations (through Subsidies) obtained from this Organization, or from other (ally) Organizations on its behalf. Any negative balance hits SciPost's reserve budget.</p>
-			  </details>
-
-			</div>
-		      </td>
-		    </tr>
-		  {% endif %}
+			      </thead>
+			      <tbody>
+				{% for journal, journaldata in val.expenditures.per_journal.items %}
+				  <tr>
+				    <td>{{ journal }}</td>
+				    <td class="text-end">&euro;{{ journaldata.costperpaper }}</td>
+				    <td class="text-end">{{ journaldata.nap }}</td>
+				    <td class="text-end">{{ journaldata.pubfracs }}</td>
+				    <td class="text-end">&euro;{{ journaldata.expenditures }}</td>
+				    <td class="text-end">&euro;{{ journaldata.self_compensated }}</td>
+				    <td class="text-end">&euro;{{ journaldata.ally_compensated }}</td>
+				    {% if journaldata.uncompensated > 0 %}
+				      <td class="bg-danger bg-opacity-25 text-end">-&euro;{{ journaldata.uncompensated }}</td>
+				    {% else %}
+				      <td class="bg-success bg-opacity-25 text-end">&euro;{{ journaldata.uncompensated }}</td>
+				    {% endif %}
+				  </tr>
+				{% endfor %}
+			      </tbody>
+			    </table>
+			    <details class="ms-2 mb-2">
+			      <summary>
+				Info on this table
+			      </summary>
+			      <p class="mt-1">This <strong>Expenditures (Organization-level)</strong> table compiles the expenditures by SciPost to publish all papers which are associated to this Organization for {{ year }}, weighed by this Organization's PubFracs for these individual papers. The next columns detail the compensations (through Subsidies) obtained from this Organization, or from other (ally) Organizations on its behalf. Any negative balance hits SciPost's reserve budget.</p>
+			    </details>
+
+			  </div>
+			</td>
+		      </tr>
+		    {% endif %}
+		  {% endfor %}
 		{% endfor %}
-	      {% endfor %}
-	    </tbody>
-	  </table>
-
+	      </tbody>
+	    </table>
+	  {% endif %}
 
 
 
-- 
GitLab