From 07a71ad50408ecab42dabd3449bd6d37d65713b2 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 21 Jul 2026 10:07:55 +0000 Subject: [PATCH] =?UTF-8?q?Band=20a=20continuous=20SAP=20score=20on=20its?= =?UTF-8?q?=20published=20rating=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- datatypes/epc/domain/epc.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/datatypes/epc/domain/epc.py b/datatypes/epc/domain/epc.py index 18d72b310..e1b6d95aa 100644 --- a/datatypes/epc/domain/epc.py +++ b/datatypes/epc/domain/epc.py @@ -1,3 +1,4 @@ +from decimal import ROUND_HALF_UP, Decimal from enum import Enum @@ -34,7 +35,14 @@ class Epc(Enum): @classmethod def from_sap_continuous(cls, score: float) -> "Epc": - raise NotImplementedError + """The band an un-rounded SAP rating is *published* in. + + A dwelling is banded on the integer published on its EPC, which rounds + half up (SAP 10.2 §13) — so this is `from_sap_score` over that rounding + rather than over Python's half-to-even `round`, which would drop an + exact x.5 at a band floor into the band below.""" + published: int = int(Decimal(score).quantize(Decimal("1"), rounding=ROUND_HALF_UP)) + return cls.from_sap_score(published) def sap_lower_bound(self) -> int: """The minimum SAP rating in this band — the inverse of