From 76b662471cc00e7b96a7c21ea55cae5546b313b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jean-S=C3=A9bastien=20Caux?= <git@jscaux.org>
Date: Sat, 16 Mar 2024 10:43:51 +0100
Subject: [PATCH] Simplify construction: only use PubFrac model

---
 scipost_django/finances/admin.py              |  51 +--------
 ...xpenditurecoverage_publication_and_more.py |  39 +++++++
 scipost_django/finances/models/__init__.py    |   4 -
 .../finances/models/pex_coverage.py           |  44 --------
 scipost_django/finances/models/pubfrac.py     |  19 ++--
 .../finances/models/pubfrac_compensation.py   |  34 ------
 scipost_django/finances/models/subsidy.py     |  19 +---
 .../templates/finances/_subsidy_details.html  |  59 ++--------
 scipost_django/finances/utils.py              |  29 +++--
 scipost_django/journals/models/publication.py |  20 +---
 .../journals/publication_detail.html          | 101 ++++--------------
 11 files changed, 99 insertions(+), 320 deletions(-)
 create mode 100644 scipost_django/finances/migrations/0041_remove_publicationexpenditurecoverage_publication_and_more.py
 delete mode 100644 scipost_django/finances/models/pex_coverage.py
 delete mode 100644 scipost_django/finances/models/pubfrac_compensation.py

diff --git a/scipost_django/finances/admin.py b/scipost_django/finances/admin.py
index a56da3b02..4311d246c 100644
--- a/scipost_django/finances/admin.py
+++ b/scipost_django/finances/admin.py
@@ -9,8 +9,6 @@ from .models import (
     SubsidyPayment,
     SubsidyAttachment,
     PubFrac,
-    PubFracCompensation,
-    PublicationExpenditureCoverage,
     WorkLog,
     PeriodicReportType,
     PeriodicReport,
@@ -79,6 +77,7 @@ class PubFracAdmin(admin.ModelAdmin):
     autocomplete_fields = [
         "organization",
         "publication",
+        "compensated_by",
     ]
     search_fields = [
         "publication__doi_label",
@@ -92,54 +91,6 @@ class PubFracAdmin(admin.ModelAdmin):
         return (obj.publication.doi_label)
 
 
-@admin.register(PubFracCompensation)
-class PubFracCompensationAdmin(admin.ModelAdmin):
-    list_display = [
-        "subsidy",
-        "doi_label_display",
-        "amount",
-    ]
-    autocomplete_fields = [
-        "subsidy",
-        "pubfrac",
-    ]
-    search_fields = [
-        "subsidy",
-        "pubfrac__organization__name",
-        "pubfrac__organization__name_original",
-        "pubfrac__organization__acronym",
-        "pubfrac__publication__doi_label",
-    ]
-
-    @admin.display(description='doi label')
-    def doi_label_display(self, obj):
-        return (obj.pubfrac.publication.doi_label)
-
-
-@admin.register(PublicationExpenditureCoverage)
-class PublicationExpenditureCoverageAdmin(admin.ModelAdmin):
-    list_display = [
-        "subsidy",
-        "doi_label_display",
-        "amount",
-    ]
-    autocomplete_fields = [
-        "subsidy",
-        "publication",
-    ]
-    search_fields = [
-        "subsidy",
-        "subsidy__organization__name",
-        "subsidy__organization__name_original",
-        "subsidy__organization__acronym",
-        "publication__doi_label",
-    ]
-
-    @admin.display(description='doi label')
-    def doi_label_display(self, obj):
-        return (obj.publication.doi_label)
-
-
 @admin.register(WorkLog)
 class WorkLogAdmin(admin.ModelAdmin):
     autocomplete_fields = ["user"]
diff --git a/scipost_django/finances/migrations/0041_remove_publicationexpenditurecoverage_publication_and_more.py b/scipost_django/finances/migrations/0041_remove_publicationexpenditurecoverage_publication_and_more.py
new file mode 100644
index 000000000..dfad70c26
--- /dev/null
+++ b/scipost_django/finances/migrations/0041_remove_publicationexpenditurecoverage_publication_and_more.py
@@ -0,0 +1,39 @@
+# Generated by Django 4.2.10 on 2024-03-16 09:09
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("finances", "0040_alter_pubfraccompensation_options_and_more"),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name="publicationexpenditurecoverage",
+            name="publication",
+        ),
+        migrations.RemoveField(
+            model_name="publicationexpenditurecoverage",
+            name="subsidy",
+        ),
+        migrations.AddField(
+            model_name="pubfrac",
+            name="compensated_by",
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="compensated_pubfracs",
+                to="finances.subsidy",
+            ),
+        ),
+        migrations.DeleteModel(
+            name="PubFracCompensation",
+        ),
+        migrations.DeleteModel(
+            name="PublicationExpenditureCoverage",
+        ),
+    ]
diff --git a/scipost_django/finances/models/__init__.py b/scipost_django/finances/models/__init__.py
index c1669c99e..a3406bafc 100644
--- a/scipost_django/finances/models/__init__.py
+++ b/scipost_django/finances/models/__init__.py
@@ -8,12 +8,8 @@ from .periodic_report import (
     PeriodicReport,
 )
 
-from .pex_coverage import PublicationExpenditureCoverage
-
 from .pubfrac import PubFrac
 
-from .pubfrac_compensation import PubFracCompensation
-
 from .subsidy import Subsidy
 
 from .subsidy_payment import SubsidyPayment
diff --git a/scipost_django/finances/models/pex_coverage.py b/scipost_django/finances/models/pex_coverage.py
deleted file mode 100644
index cdc846b7b..000000000
--- a/scipost_django/finances/models/pex_coverage.py
+++ /dev/null
@@ -1,44 +0,0 @@
-__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
-__license__ = "AGPL v3"
-
-
-from django.db import models
-
-
-class PublicationExpenditureCoverage(models.Model):
-    """
-    An amount from a Subsidy which is ascribed to a Publication as expenditure coverage.
-
-    A Coverage is applied to a Publication as a whole, not to individual PubFracs.
-    This class thus complements PubFracCompensation, which compensates costs
-    at the PubFrac level.
-    """
-
-    subsidy = models.ForeignKey(
-        "finances.Subsidy",
-        related_name="pex_coverages",
-        on_delete=models.CASCADE,
-    )
-
-    publication = models.ForeignKey(
-        "journals.Publication",
-        related_name="pex_coverages",
-        on_delete=models.CASCADE,
-    )
-
-    amount = models.PositiveIntegerField()
-
-    class Meta:
-        constraints = [
-            models.UniqueConstraint(
-                fields=["subsidy", "publication"], name="unique_subsidy_publication"
-            ),
-        ]
-        verbose_name = "PEX coverage"
-        verbose_name_plural = "PEX coverages"
-
-    def __str__(self):
-        return (
-            f"€{self.amount} for {self.publication.doi_label} "
-            f"from {self.subsidy.organization}"
-        )
diff --git a/scipost_django/finances/models/pubfrac.py b/scipost_django/finances/models/pubfrac.py
index b4c9015c0..3cd0f66db 100644
--- a/scipost_django/finances/models/pubfrac.py
+++ b/scipost_django/finances/models/pubfrac.py
@@ -32,6 +32,13 @@ class PubFrac(models.Model):
     fraction = models.DecimalField(
         max_digits=4, decimal_places=3, default=Decimal("0.000")
     )
+    compensated_by = models.ForeignKey(
+        "finances.Subsidy",
+        related_name="compensated_pubfracs",
+        blank=True,
+        null=True,
+        on_delete=models.CASCADE,
+    )
 
     # Calculated field
     cf_value = models.PositiveIntegerField(blank=True, null=True)
@@ -49,17 +56,7 @@ class PubFrac(models.Model):
 
     @property
     def compensated(self):
-        """Compensated part of this PubFrac."""
-        return (
-            self.pubfrac_compensations.aggregate(models.Sum("amount"))["amount__sum"]
-            if self.pubfrac_compensations.exists()
-            else 0
-        )
-
-    @property
-    def arrears(self):
-        """Uncovered and uncompensated part of this PubFrac."""
-        return self.cf_value - self.compensated
+        return self.compensated_by is not None
 
 
 @receiver(pre_save, sender=PubFrac)
diff --git a/scipost_django/finances/models/pubfrac_compensation.py b/scipost_django/finances/models/pubfrac_compensation.py
deleted file mode 100644
index 0aa5c48ab..000000000
--- a/scipost_django/finances/models/pubfrac_compensation.py
+++ /dev/null
@@ -1,34 +0,0 @@
-__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
-__license__ = "AGPL v3"
-
-
-from django.db import models
-
-
-class PubFracCompensation(models.Model):
-    """
-    An amount from a Subsidy which ascribed to a PubFrac as compensation.
-    """
-
-    subsidy = models.ForeignKey(
-        "finances.Subsidy",
-        related_name="pubfrac_compensations",
-        on_delete=models.CASCADE,
-    )
-
-    pubfrac = models.ForeignKey(
-        "finances.PubFrac",
-        related_name="pubfrac_compensations",
-        on_delete=models.CASCADE,
-    )
-
-    amount = models.PositiveIntegerField()
-
-    class Meta:
-        constraints = [
-            models.UniqueConstraint(
-                fields=["subsidy", "pubfrac"], name="unique_subsidy_pubfrac"
-            ),
-        ]
-        verbose_name = "PubFrac compensation"
-        verbose_name_plural = "PubFrac compensations"
diff --git a/scipost_django/finances/models/subsidy.py b/scipost_django/finances/models/subsidy.py
index 969128667..e62a00cca 100644
--- a/scipost_django/finances/models/subsidy.py
+++ b/scipost_django/finances/models/subsidy.py
@@ -124,22 +124,11 @@ class Subsidy(models.Model):
     @property
     def total_compensations(self):
         """
-        Sum of the amounts of all PubFracCompensations related to this Subsidy.
+        Sum of the amounts of all compensations related to this Subsidy.
         """
         return (
-            self.pubfrac_compensations.aggregate(Sum("amount"))["amount__sum"]
-            if self.pubfrac_compensations.exists()
-            else 0
-        )
-
-    @property
-    def total_coverages(self):
-        """
-        Sum of the PublicationExpenditureCoverages related to this Subsidy.
-        """
-        return (
-            self.pex_coverages.aggregate(Sum("amount"))["amount__sum"]
-            if self.pex_coverages.exists()
+            self.compensated_pubfracs.aggregate(Sum("cf_value"))["cf_value__sum"]
+            if self.compensated_pubfracs.exists()
             else 0
         )
 
@@ -148,4 +137,4 @@ class Subsidy(models.Model):
         """
         Part of the Subsidy amount which hasn't been allocated.
         """
-        return self.amount - self.total_compensations - self.total_coverages
+        return self.amount - self.total_compensations
diff --git a/scipost_django/finances/templates/finances/_subsidy_details.html b/scipost_django/finances/templates/finances/_subsidy_details.html
index 57de260f9..92d363fc9 100644
--- a/scipost_django/finances/templates/finances/_subsidy_details.html
+++ b/scipost_django/finances/templates/finances/_subsidy_details.html
@@ -110,27 +110,24 @@
 {% if 'edadmin' in user_roles %}
   {% if subsidy.amount_publicly_shown %}
 
+    <h3 class="highlight">Expenditures compensated by this Subsidy</h3>
     <div class="row">
-      <div class="col-12">
-	<h3 class="highlight">Expenditures compensated or covered by this Subsidy</h3>
-
+      <div class="col-lg-6">
 	<table class="table mt-2 caption-top">
 	  <caption>PubFrac Compensations</caption>
 	  <thead class="table-light">
 	    <tr>
 	      <th>Publication</th>
 	      <th>PubFrac value</th>
-	      <th>PubFrac compensation</th>
 	    </tr>
 	  </thead>
 	  <tbody>
-	    {% for compensation in subsidy.pubfrac_compensations.all %}
+	    {% for compensated_pubfrac in subsidy.compensated_pubfracs.all %}
 	      <tr>
 		<td>
-		  <a href="{% url 'scipost:publication_detail' doi_label=compensation.pubfrac.publication.doi_label %}">{{ compensation.pubfrac.publication.doi_label }}</a>
+		  <a href="{% url 'scipost:publication_detail' doi_label=compensated_pubfrac.publication.doi_label %}">{{ compensated_pubfrac.publication.doi_label }}</a>
 		</td>
-		<td>&euro;{{ compensation.pubfrac.cf_value }}</td>
-		<td>&euro;{{ compensation.amount }}</td>
+		<td>&euro;{{ compensated_pubfrac.cf_value }}</td>
 	      </tr>
 	    {% empty %}
 	      <tr>
@@ -139,65 +136,29 @@
 	    {% endfor %}
 	    <tr class="bg-secondary bg-opacity-10">
 	      <th>Total compensations from this Subsidy</th>
-	      <td></td>
 	      <td>&euro;{{ subsidy.total_compensations }}</td>
 	    </tr>
 	  </tbody>
 	</table>
-
-	<table class="table caption-top">
-	  <caption>Expenditure Coverages</caption>
-	  <thead class="table-light">
-	    <tr>
-	      <th>Publication</th>
-	      <th>Expenditure</th>
-	      <th>Coverage</th>
-	    </tr>
-	  </thead>
-	  <tbody>
-	    {% for coverage in subsidy.pex_coverages.all %}
-	      <tr>
-		<td>
-		  <a href="{% url 'scipost:publication_detail' doi_label=coverage.publication.doi_label %}">{{ coverage.publication.doi_label }}</a>
-		</td>
-		<td>&euro;{{ coverage.publication.expenditures }}</td>
-		<td>&euro;{{ coverage.amount }}</td>
-	      </tr>
-	    {% empty %}
-	      <tr>
-		<td>No Coverage defined</td>
-	      </tr>
-	    {% endfor %}
-	    <tr class="bg-secondary bg-opacity-10">
-	      <th>Total coverages from this Subsidy</th>
-	      <td></td>
-	      <td>&euro;{{ subsidy.total_coverages }}</td>
-	    </tr>
-	  </tbody>
-	</table>
-
+      </div>
+      <div class="col-lg-6">
 	<table class="table mt-2 caption-top">
 	  <caption>Balance</caption>
 	  <tbody>
 	    <tr>
 	      <th>Subsidy amount</th>
-	      <td>{{ subsidy.amount }}</td>
+	      <td>&euro;{{ subsidy.amount }}</td>
 	    </tr>
 	    <tr>
 	      <th>Compensations</th>
-	      <td>{{ subsidy.total_compensations }}</td>
-	    </tr>
-	    <tr>
-	      <th>Coverages</th>
-	      <td>{{ subsidy.total_coverages }}</td>
+	      <td>&euro;{{ subsidy.total_compensations }}</td>
 	    </tr>
 	    <tr class="bg-secondary bg-opacity-10">
 	      <th>Remainder (allocated to reserve fund)</th>
-	      <td>{{ subsidy.remainder }}</td>
+	      <td>&euro;{{ subsidy.remainder }}</td>
 	    </tr>
 	  </tbody>
 	</table>
-
       </div>
     </div>
   {% endif %}
diff --git a/scipost_django/finances/utils.py b/scipost_django/finances/utils.py
index 676246545..ca818cf3c 100644
--- a/scipost_django/finances/utils.py
+++ b/scipost_django/finances/utils.py
@@ -2,7 +2,7 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
 __license__ = "AGPL v3"
 
 
-from .models import Subsidy, PubFrac, PubFracCompensation
+from .models import Subsidy, PubFrac
 
 
 def id_to_slug(id):
@@ -13,9 +13,9 @@ def slug_to_id(slug):
     return max(0, int(slug) - 821)
 
 
-def distribute_subsidy(subsidy: Subsidy, algorithm: str):
+def allocate_subsidy(subsidy: Subsidy, algorithm: str):
     """
-    Allocate subsidy amount to compensations of PubFrac
+    Allocate subsidy amount to compensations of PubFrac or coverage of expenditures.
 
     Algorithm choices:
     * any PubFrac ascribed to org from affiliations
@@ -27,12 +27,13 @@ def distribute_subsidy(subsidy: Subsidy, algorithm: str):
     """
 
     algorithms = [
-        "PubFrac_ascribed_to_Org",
-        "full_PEX_if_author_affiliated_to_Org",
-        "PubFrac_author_affiliation_same_country_as_Org",
-        "full_PEX_author_affiliation_same_country_as_Org",
-        "full_PEX_if_pub_funding_ack_includes_Org",
-        "full_PEX_if_pub_matches_specialties",
+        "compensate_PubFrac_related_to_Org",
+        "cover_full_PEX_if_PubFrac_related_to_Org",
+        "compensate_PubFrac_if_author_affiliation_same_country_as_Org",
+        "cover_full_PEX_if_author_affiliation_same_country_as_Org",
+        "cover_full_PEX_if_pub_funding_ack_includes_Org",
+        "cover_full_PEX_if_pub_matches_specialties",
+        "allocate_to_reserve_fund",
     ]
 
     if algorithm is "PubFrac_ascribed_to_Org":
@@ -48,12 +49,8 @@ def distribute_subsidy(subsidy: Subsidy, algorithm: str):
         for pubfrac in pubfracs.all():
             print(f"{distributed = };\tadding {pubfrac = }")
             if pubfrac.cf_value <= subsidy.remainder:
-                pfc, created = PubFracCompensation.objects.get_or_create(
-                    subsidy=subsidy,
-                    pubfrac=pubfrac,
-                    amount=pubfrac.cf_value,
-                )
-                if created:
-                    distributed += pubfrac.cf_value
+                pubfrac.compensated_by = subsidy
+                pubfrac.save()
+                distributed += pubfrac.cf_value
             else:
                 break
diff --git a/scipost_django/journals/models/publication.py b/scipost_django/journals/models/publication.py
index 2f92b0959..3e3e73dc4 100644
--- a/scipost_django/journals/models/publication.py
+++ b/scipost_django/journals/models/publication.py
@@ -25,7 +25,6 @@ from ..managers import PublicationQuerySet
 from ..validators import doi_publication_validator
 
 from common.utils import get_current_domain
-from finances.models import PubFracCompensation
 from scipost.constants import SCIPOST_APPROACHES
 from scipost.fields import ChoiceArrayField
 
@@ -430,32 +429,17 @@ class Publication(models.Model):
         """Checks that the support fractions sum up to one."""
         return self.pubfracs.aggregate(Sum("fraction"))["fraction__sum"] == 1
 
-    @property
-    def covered_expenditures(self):
-        """Covered part of expenditures for this Publication."""
-        return (
-            self.pex_coverages.aggregate(Sum("amount"))["amount__sum"]
-            if self.pex_coverages.exists()
-            else 0
-        )
-
     @property
     def compensated_expenditures(self):
         """Compensated part of expenditures for this Publication."""
-        qs = PubFracCompensation.objects.filter(pubfrac__publication=self)
-        return qs.aggregate(Sum("amount"))["amount__sum"] if qs.exists() else 0
+        qs = self.pubfracs.filter(compensated_by__isnull=False)
+        return qs.aggregate(Sum("cf_value"))["cf_value__sum"] if qs.exists() else 0
 
     @property
     def uncompensated_expenditures(self):
         """Unompensated part of expenditures for this Publication."""
         return self.expenditures - self.compensated_expenditures
 
-    @property
-    def outstanding_expenditures(self):
-        """Expenditures which hasn't been compensated or covered."""
-        return (self.expenditures - self.covered_expenditures -
-                self.compensated_expenditures)
-
     @property
     def citation(self):
         if self.cf_citation:
diff --git a/scipost_django/journals/templates/journals/publication_detail.html b/scipost_django/journals/templates/journals/publication_detail.html
index 200b5c0e4..0576c8a5c 100644
--- a/scipost_django/journals/templates/journals/publication_detail.html
+++ b/scipost_django/journals/templates/journals/publication_detail.html
@@ -172,17 +172,16 @@
 
   {% if 'edadmin' in user_roles %}
     <h3 class="mt-4">
-      Expenditures and Balance
+      Expenditures and Compensations
     </h3>
-    <table class="table mt-2 caption-top">
-      <caption>PubFracs, Compensations and Arrears</caption>
+    <table class="table mt-2">
       <thead class="table-light">
 	<tr>
 	  <th>Organization</th>
 	  <th>PubFrac</th>
 	  <th>Value</th>
 	  <th>Compensation</th>
-	  <th>Arrears</th>
+	  <th>Uncompensated</th>
 	</tr>
       </thead>
       <tbody>
@@ -191,88 +190,32 @@
 	    <td><a href="{% url 'organizations:organization_detail' pk=pubfrac.organization.id %}">{{ pubfrac.organization }}</a></td>
 	    <td>{{ pubfrac.fraction }}</td>
 	    <td>&euro;{{ pubfrac.cf_value }}</td>
-	    <td>
-	      <ul>
-		{% for pc in pubfrac.pubfrac_compensations.all %}
-		  <li>
-		    &euro;{{ pc.amount }}&emsp;
-		    {% if pc.subsidy.organization != pubfrac.organization %}
-		      from&nbsp;ally&nbsp;
-		      <a href="{% url 'organizations:organization_detail' pk=pc.subsidy.organization.id %}">{{ pc.subsidy.organization }}</a>
-		    {% endif %}
-		    (<a href="{% url 'finances:subsidy_details' pk=pc.subsidy.id %}" target="_blank">
-		      see Subsidy details
-		    </a>)
-		  </li>
-		{% empty %}
-		  <li>No compensation</li>
-		{% endfor %}
-	      </ul>
-	    </td>
-	    {% with pubfrac.arrears as arrears %}
-	      <td class="{% if arrears == 0 %}bg-success{{% else %}bg-danger{% endif %} bg-opacity-25">
-		&euro;{{ pubfrac.arrears }}
+	    {% if pubfrac.compensated %}
+	      <td class="bg-success bg-opacity-25">
+		by <a href="{% url 'organizations:organization_detail' pk=pubfrac.compensated_by.organization.id %}">{{ pubfrac.compensated_by.organization }}</a>
+		(<a href="{% url 'finances:subsidy_details' pk=pubfrac.compensated_by.id %}">
+		see Subsidy details
+		</a>)
 	      </td>
-	    {% endwith %}
+	      <td class="bg-success bg-opacity-25">&euro;0</td>
+	    {% else %}
+	      <td><span class="text-danger">{% include 'bi/x-circle-fill.html' %}</span></td>
+	      <td class="bg-danger bg-opacity-25">&euro;{{ pubfrac.cf_value }}</td>
+	    {% endif %}
 	  </tr>
 	{% endfor %}
-	<tr>
-	  <th>Totals</th>
-	  <td>1</td>
-	  <td>{{ publication.expenditures }}</td>
-	  {% if publication.uncompensated_expenditures == 0 %}
-	    <td class="bg-success bg-opacity-25">{{ publication.compensated_expenditures }}</td>
-	    <td class="bg-success bg-opacity-25">{{ publication.uncompensated_expenditures }}</td>
-	  {% else %}
-	    <td class="bg-danger bg-opacity-25">{{ publication.compensated_expenditures }}</td>
-	    <td class="bg-danger bg-opacity-25">{{ publication.uncompensated_expenditures }}</td>
-	  {% endif %}
-	</tr>
-      </tbody>
-    </table>
-
-    <table class="table mt-2 caption-top">
-      <caption>Balance</caption>
-      <tbody>
-	<tr>
-	  <th>Expenditures</th>
-	  <td></td>
-	  <td>{{ publication.expenditures }}</td>
-	</tr>
-	<tr>
-	  <th>PubFrac Compensations</th>
-	  <td>
-	  </td>
-	  <td>{{ publication.compensated_expenditures }}</td>
-	</tr>
-	<tr>
-	  <th>Coverages</th>
-	  <td>
-	    <ul>
-	      {% for coverage in publication.pex_coverages.all %}
-		<li>
-		  &euro;{{ coverage.amount }}
-		  from <a href="{% url 'organizations:organization_detail' pk=coverage.subsidy.organization.id %}">{{ coverage.subsidy.organization }}</a>
-		  (<a href="{% url 'finances:subsidy_details' pk=coverage.subsidy.id %}" target="_blank">
-		  see Subsidy details
-		  </a>
-		</li>
-	      {% empty %}
-		<li>No coverage received</li>
-	      {% endfor %}
-	    </ul>
-	  </td>
-	  <td>{{ publication.covered_expenditures }}</td>
-	</tr>
-	{% with publication.outstanding_expenditures as outstanding %}
-	  <tr class="{% if outstanding > 0 %}bg-danger{% else %}bg-success{% endif %} bg-opacity-25">
-	    <th>Outstanding Expenditures</th>
-	    <td></td>
-	    <td>{{ outstanding }}</td>
+	{% with publication.uncompensated_expenditures as uncompensated %}
+	  <tr>
+	    <th>Totals</th>
+	    <td>1</td>
+	    <td>{{ publication.expenditures }}</td>
+	    <td class="{% if uncompensated == 0 %}bg-success{% else %}bg-danger{% endif %} bg-opacity-25">{{ publication.compensated_expenditures }}</td>
+	    <td class="{% if uncompensated == 0 %}bg-success{% else %}bg-danger{% endif %} bg-opacity-25">{{ publication.uncompensated_expenditures }}</td>
 	  </tr>
 	{% endwith %}
       </tbody>
     </table>
+
   {% endif %}
 
   {% if publication.status == 'draft' and perms.scipost.can_draft_publication %}
-- 
GitLab