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: