M8-T16: add thermal meter cost APIs
This commit is contained in:
@@ -220,7 +220,14 @@ def compute_closed_periods(session: Session, *, now: datetime | None = None) ->
|
||||
return written
|
||||
|
||||
|
||||
def recompute_range(session: Session, start: datetime, end: datetime) -> int:
|
||||
def recompute_range(session: Session, start: datetime, end: datetime, *, commit: bool = True) -> int:
|
||||
"""Recompute a thermal range.
|
||||
|
||||
The historical service entry point remains self-committing for the scheduler
|
||||
and direct callers. HTTP callers pass ``commit=False`` so validation,
|
||||
recomputation, response statistics, and the single commit share one
|
||||
transaction owned by the route.
|
||||
"""
|
||||
cursor, end = floor_to_quarter(_utc(start)), _utc(end)
|
||||
now, written = datetime.now(UTC), 0
|
||||
while cursor < end:
|
||||
@@ -229,7 +236,8 @@ def recompute_range(session: Session, start: datetime, end: datetime) -> int:
|
||||
if compute_period(session, commodity, cursor, overwrite=True):
|
||||
written += 1
|
||||
cursor += _PERIOD
|
||||
session.commit()
|
||||
if commit:
|
||||
session.commit()
|
||||
return written
|
||||
|
||||
|
||||
@@ -257,7 +265,9 @@ def summarize(session: Session, start: datetime, end: datetime, *, now: datetime
|
||||
final_day = timezone_service.local_date(end - timedelta(microseconds=1))
|
||||
final_day = min(final_day, _settled_end_date(now or datetime.now(UTC)))
|
||||
day = timezone_service.local_date(start)
|
||||
fixed = Decimal("0")
|
||||
fixed_breakdown: dict[str, Decimal] = {key: Decimal("0") for key in (
|
||||
"heating_network", "metering", "delivery_set", "hot_water_network", "other"
|
||||
)}
|
||||
versions = active_contract_versions(session, scope="thermal")
|
||||
while start < end and day <= final_day:
|
||||
day_start = datetime.combine(day, time.min, tzinfo=timezone_service.local_tz()).astimezone(UTC)
|
||||
@@ -275,14 +285,14 @@ def summarize(session: Session, start: datetime, end: datetime, *, now: datetime
|
||||
if segment_start >= segment_end:
|
||||
continue
|
||||
values = version.values["standing"]
|
||||
annual = sum((_decimal(values.get(key, "0")) for key in (
|
||||
"heating_network", "metering", "delivery_set", "hot_water_network", "other"
|
||||
)), Decimal("0"))
|
||||
fraction = Decimal(str((segment_end - segment_start).total_seconds())) / local_day_seconds
|
||||
fixed += annual / Decimal("365") * fraction
|
||||
for key in fixed_breakdown:
|
||||
fixed_breakdown[key] += _decimal(values.get(key, "0")) / Decimal("365") * fraction
|
||||
day += timedelta(days=1)
|
||||
fixed = sum(fixed_breakdown.values(), Decimal("0"))
|
||||
return {
|
||||
"currency": good[0].currency if good else "EUR", "variable_cost": variable,
|
||||
"fixed_cost": fixed, "total_cost": variable + fixed, "breakdown": breakdown,
|
||||
"fixed_cost": fixed, "fixed_breakdown": fixed_breakdown,
|
||||
"total_cost": variable + fixed, "breakdown": breakdown,
|
||||
"period_count": len(good), "degraded_count": len(rows) - len(good),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user