diff --git a/schemes/schemes/domain.py b/schemes/schemes/domain.py
index 361b2818..a0fe1556 100644
--- a/schemes/schemes/domain.py
+++ b/schemes/schemes/domain.py
@@ -72,6 +72,16 @@ def change_control_adjustment(self) -> Decimal | None:
)
return sum(amounts, Decimal(0)) if self._financial_revisions else None
+ @property
+ def allocation_still_to_spend(self) -> Decimal:
+ funding_allocation = self.funding_allocation
+ spend_to_date = self.spend_to_date
+ return (
+ funding_allocation - spend_to_date
+ if funding_allocation is not None and spend_to_date is not None
+ else Decimal(0)
+ )
+
class SchemeType(Enum):
DEVELOPMENT = auto()
diff --git a/schemes/schemes/views.py b/schemes/schemes/views.py
index c1f4ac15..0e8b98cb 100644
--- a/schemes/schemes/views.py
+++ b/schemes/schemes/views.py
@@ -159,6 +159,7 @@ class SchemeFundingContext:
funding_allocation: Decimal | None
spend_to_date: Decimal | None
change_control_adjustment: Decimal | None
+ allocation_still_to_spend: Decimal
@staticmethod
def for_domain(scheme: Scheme) -> SchemeFundingContext:
@@ -166,6 +167,7 @@ def for_domain(scheme: Scheme) -> SchemeFundingContext:
funding_allocation=scheme.funding_allocation,
spend_to_date=scheme.spend_to_date,
change_control_adjustment=scheme.change_control_adjustment,
+ allocation_still_to_spend=scheme.allocation_still_to_spend,
)
diff --git a/schemes/templates/scheme_funding.html b/schemes/templates/scheme_funding.html
index 4300e062..8365a687 100644
--- a/schemes/templates/scheme_funding.html
+++ b/schemes/templates/scheme_funding.html
@@ -24,6 +24,14 @@
Funding
"value": {
"text": "£{:,}".format(funding.change_control_adjustment | round) if funding.change_control_adjustment else "N/A"
}
+ },
+ {
+ "key": {
+ "text": "Allocation still to spend"
+ },
+ "value": {
+ "text": "£{:,}".format(funding.allocation_still_to_spend | round)
+ }
}
]
}) }}
diff --git a/tests/e2e/pages.py b/tests/e2e/pages.py
index c018a32a..9284a17f 100644
--- a/tests/e2e/pages.py
+++ b/tests/e2e/pages.py
@@ -180,6 +180,7 @@ def __init__(self, component: Locator):
self._funding_allocation = component.get_by_role("definition").nth(0)
self._spend_to_date = component.get_by_role("definition").nth(1)
self._change_control_adjustment = component.get_by_role("definition").nth(2)
+ self._allocation_still_to_spend = component.get_by_role("definition").nth(3)
@property
def funding_allocation(self) -> str | None:
@@ -196,6 +197,11 @@ def change_control_adjustment(self) -> str | None:
text = self._change_control_adjustment.text_content()
return text.strip() if text else None
+ @property
+ def allocation_still_to_spend(self) -> str | None:
+ text = self._allocation_still_to_spend.text_content()
+ return text.strip() if text else None
+
def _get_base_url(app: Flask) -> str:
scheme = app.config["PREFERRED_URL_SCHEME"]
diff --git a/tests/e2e/test_scheme.py b/tests/e2e/test_scheme.py
index d47ed53b..2943c185 100644
--- a/tests/e2e/test_scheme.py
+++ b/tests/e2e/test_scheme.py
@@ -91,4 +91,5 @@ def test_scheme_funding(app_client: AppClient, oidc_client: OidcClient, app: Fla
funding_component.funding_allocation == "£110,000"
and funding_component.spend_to_date == "£50,000"
and funding_component.change_control_adjustment == "£10,000"
+ and funding_component.allocation_still_to_spend == "£60,000"
)
diff --git a/tests/integration/pages.py b/tests/integration/pages.py
index 7a42577c..485dcd5c 100644
--- a/tests/integration/pages.py
+++ b/tests/integration/pages.py
@@ -173,3 +173,7 @@ def __init__(self, tag: Tag):
self.change_control_adjustment = (
change_control_adjustment_tag.string.strip() if change_control_adjustment_tag.string else None
)
+ allocation_still_to_spend_tag = tag.select("main dd")[3]
+ self.allocation_still_to_spend = (
+ allocation_still_to_spend_tag.string.strip() if allocation_still_to_spend_tag.string else None
+ )
diff --git a/tests/integration/test_scheme.py b/tests/integration/test_scheme.py
index 65d900de..70aefdec 100644
--- a/tests/integration/test_scheme.py
+++ b/tests/integration/test_scheme.py
@@ -101,6 +101,7 @@ def test_scheme_shows_minimal_funding(schemes: SchemeRepository, client: FlaskCl
scheme_page.funding.funding_allocation == "N/A"
and scheme_page.funding.spend_to_date == "N/A"
and scheme_page.funding.change_control_adjustment == "N/A"
+ and scheme_page.funding.allocation_still_to_spend == "£0"
)
@@ -141,4 +142,5 @@ def test_scheme_shows_funding(schemes: SchemeRepository, client: FlaskClient) ->
scheme_page.funding.funding_allocation == "£110,000"
and scheme_page.funding.spend_to_date == "£50,000"
and scheme_page.funding.change_control_adjustment == "£10,000"
+ and scheme_page.funding.allocation_still_to_spend == "£60,000"
)
diff --git a/tests/unit/schemes/test_domain.py b/tests/unit/schemes/test_domain.py
index cf77afde..ca385edf 100644
--- a/tests/unit/schemes/test_domain.py
+++ b/tests/unit/schemes/test_domain.py
@@ -386,6 +386,62 @@ def test_get_change_control_adjustment_when_no_revisions(self) -> None:
assert scheme.change_control_adjustment is None
+ def test_get_allocation_still_to_spend(self) -> None:
+ scheme = Scheme(id_=1, name="Wirral Package", authority_id=2)
+ scheme.update_financial(
+ FinancialRevision(
+ effective_date_from=date(2020, 1, 1),
+ effective_date_to=None,
+ type=FinancialType.FUNDING_ALLOCATION,
+ amount=Decimal("110000"),
+ source=DataSource.ATF4_BID,
+ )
+ )
+ scheme.update_financial(
+ FinancialRevision(
+ effective_date_from=date(2020, 1, 1),
+ effective_date_to=None,
+ type=FinancialType.SPENT_TO_DATE,
+ amount=Decimal("50000"),
+ source=DataSource.ATF4_BID,
+ )
+ )
+
+ assert scheme.allocation_still_to_spend == Decimal("60000")
+
+ def test_get_allocation_still_to_spend_when_no_funding_allocation(self) -> None:
+ scheme = Scheme(id_=1, name="Wirral Package", authority_id=2)
+ scheme.update_financial(
+ FinancialRevision(
+ effective_date_from=date(2020, 1, 1),
+ effective_date_to=None,
+ type=FinancialType.SPENT_TO_DATE,
+ amount=Decimal("50000"),
+ source=DataSource.ATF4_BID,
+ )
+ )
+
+ assert scheme.allocation_still_to_spend == Decimal("-50000")
+
+ def test_get_allocation_still_to_spend_when_no_spend_to_date(self) -> None:
+ scheme = Scheme(id_=1, name="Wirral Package", authority_id=2)
+ scheme.update_financial(
+ FinancialRevision(
+ effective_date_from=date(2020, 1, 1),
+ effective_date_to=None,
+ type=FinancialType.FUNDING_ALLOCATION,
+ amount=Decimal("110000"),
+ source=DataSource.ATF4_BID,
+ )
+ )
+
+ assert scheme.allocation_still_to_spend == Decimal("110000")
+
+ def test_get_allocation_still_to_spend_when_no_revisions(self) -> None:
+ scheme = Scheme(id_=1, name="Wirral Package", authority_id=2)
+
+ assert scheme.allocation_still_to_spend == Decimal("0")
+
class TestMilestoneRevision:
@pytest.mark.parametrize(
diff --git a/tests/unit/schemes/test_views.py b/tests/unit/schemes/test_views.py
index 946f16cf..2dd71a76 100644
--- a/tests/unit/schemes/test_views.py
+++ b/tests/unit/schemes/test_views.py
@@ -164,6 +164,31 @@ def test_set_change_control_adjustment(self) -> None:
assert context.change_control_adjustment == Decimal("10000")
+ def test_set_allocation_still_to_spend(self) -> None:
+ scheme = Scheme(id_=0, name="", authority_id=0)
+ scheme.update_financial(
+ FinancialRevision(
+ effective_date_from=date(2020, 1, 1),
+ effective_date_to=None,
+ type=FinancialType.FUNDING_ALLOCATION,
+ amount=Decimal("110000"),
+ source=DataSource.ATF4_BID,
+ )
+ )
+ scheme.update_financial(
+ FinancialRevision(
+ effective_date_from=date(2020, 1, 1),
+ effective_date_to=None,
+ type=FinancialType.SPENT_TO_DATE,
+ amount=Decimal("50000"),
+ source=DataSource.ATF4_BID,
+ )
+ )
+
+ context = SchemeFundingContext.for_domain(scheme)
+
+ assert context.allocation_still_to_spend == Decimal("60000")
+
class TestSchemeRepr:
def test_create_domain(self) -> None: