63 lines
1.5 KiB
Python
63 lines
1.5 KiB
Python
"""Schemas for the commodity-scoped thermal cost ledger."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Literal
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class MeterCostPeriodSchema(BaseModel):
|
|
"""One auditable thermal ledger row; all Decimal values are JSON strings."""
|
|
|
|
commodity: Literal["heating", "hot_water"]
|
|
period_start: datetime
|
|
period_end: datetime
|
|
meter_id: int | None
|
|
source_binding_id: int | None
|
|
contract_version_id: int | None
|
|
quantity: str
|
|
cost: str
|
|
currency: str
|
|
cost_breakdown: dict[str, str]
|
|
pricing_snapshot: dict[str, dict[str, str]]
|
|
quality: str
|
|
degraded: bool
|
|
degraded_reason: str | None
|
|
|
|
|
|
class MeterCostsResponse(BaseModel):
|
|
items: list[MeterCostPeriodSchema]
|
|
total: int = Field(description="Total matching rows before pagination.")
|
|
|
|
|
|
class ThermalFixedBreakdown(BaseModel):
|
|
"""D11 annual-standing charges accrued per settled local day, as Decimal strings."""
|
|
|
|
heating_network: str
|
|
metering: str
|
|
delivery_set: str
|
|
hot_water_network: str
|
|
other: str
|
|
|
|
|
|
class ThermalCostSummaryResponse(BaseModel):
|
|
currency: str
|
|
heating: str
|
|
hot_water_heating: str
|
|
hot_water: str
|
|
hot_water_tax: str
|
|
variable_subtotal: str
|
|
fixed_breakdown: ThermalFixedBreakdown
|
|
fixed_subtotal: str
|
|
all_in: str
|
|
period_count: int
|
|
degraded_count: int
|
|
|
|
|
|
class MeterCostRecomputeResponse(BaseModel):
|
|
processed: int
|
|
normal: int
|
|
degraded: int
|