M8-T16: add thermal meter cost APIs
This commit is contained in:
@@ -704,6 +704,20 @@
|
||||
"description": "Return the price curve for the active contract.\n\n**Tibber contracts** (kind=\"tibber\"):\n Fetches ``tibber_price`` rows within ``[start, end]``, ordered ascending\n by ``starts_at``. At most ``limit`` rows are returned (most recent first\n within the window, then reversed to ascending order — identical to the\n modbus readings pattern).\n\n Response ``points`` carries per-slot:\n - ``buy = total`` (Tibber all-inclusive price)\n - ``sell = total − energy_tax − sell_fee − sell_adjust`` (from active version values)\n - ``level`` (Tibber price level, may be null)\n\n ``tariff`` is null.\n\n**Manual contracts** (kind=\"manual\"):\n ``points`` is empty. ``tariff`` carries the four effective prices\n derived using the billing engine formula:\n - ``buy_dal = energy.buy.dal + energy_tax + ode``\n - ``buy_normal = energy.buy.normal + energy_tax + ode``\n - ``sell_dal = energy.sell.dal``\n - ``sell_normal = energy.sell.normal``\n\n**No active contract**: returns kind=null, currency=\"EUR\", points=[], tariff=null (200).",
|
||||
"operationId": "get_prices_api_energy_prices_get",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "scope",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"enum": [
|
||||
"electricity",
|
||||
"thermal"
|
||||
],
|
||||
"type": "string",
|
||||
"default": "electricity",
|
||||
"title": "Scope"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "start",
|
||||
"in": "query",
|
||||
@@ -1401,6 +1415,288 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/energy/meter-costs": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"api-energy"
|
||||
],
|
||||
"summary": "Get Meter Costs",
|
||||
"description": "List thermal rows in a half-open time window with stable pagination.",
|
||||
"operationId": "get_meter_costs_api_energy_meter_costs_get",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "scope",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"const": "thermal",
|
||||
"type": "string",
|
||||
"default": "thermal",
|
||||
"title": "Scope"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "commodity",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"enum": [
|
||||
"heating",
|
||||
"hot_water"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Commodity"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "start",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Start"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "end",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "End"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"maximum": 5000,
|
||||
"minimum": 1,
|
||||
"default": 500,
|
||||
"title": "Limit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 0,
|
||||
"title": "Offset"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MeterCostsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/energy/meter-costs/summary": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"api-energy"
|
||||
],
|
||||
"summary": "Get Meter Cost Summary",
|
||||
"description": "Summarize thermal variable and once-per-contract daily fixed costs.",
|
||||
"operationId": "get_meter_cost_summary_api_energy_meter_costs_summary_get",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "scope",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"const": "thermal",
|
||||
"type": "string",
|
||||
"default": "thermal",
|
||||
"title": "Scope"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "start",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Start"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "end",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "End"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ThermalCostSummaryResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/energy/meter-costs/recompute": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"api-energy"
|
||||
],
|
||||
"summary": "Post Meter Cost Recompute",
|
||||
"description": "Atomically overwrite closed, UTC-quarter thermal rows in a bounded window.",
|
||||
"operationId": "post_meter_cost_recompute_api_energy_meter_costs_recompute_post",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "scope",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"const": "thermal",
|
||||
"type": "string",
|
||||
"default": "thermal",
|
||||
"title": "Scope"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "start",
|
||||
"in": "query",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"title": "Start"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "end",
|
||||
"in": "query",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"title": "End"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "X-CSRF-Token",
|
||||
"in": "header",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "X-Csrf-Token"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MeterCostRecomputeResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/energy/meters": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -4611,6 +4907,173 @@
|
||||
"title": "MeterBindingSummary",
|
||||
"description": "Stable, non-sensitive binding identity embedded in meter responses."
|
||||
},
|
||||
"MeterCostPeriodSchema": {
|
||||
"properties": {
|
||||
"commodity": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"heating",
|
||||
"hot_water"
|
||||
],
|
||||
"title": "Commodity"
|
||||
},
|
||||
"period_start": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"title": "Period Start"
|
||||
},
|
||||
"period_end": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"title": "Period End"
|
||||
},
|
||||
"meter_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Meter Id"
|
||||
},
|
||||
"source_binding_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Source Binding Id"
|
||||
},
|
||||
"contract_version_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Contract Version Id"
|
||||
},
|
||||
"quantity": {
|
||||
"type": "string",
|
||||
"title": "Quantity"
|
||||
},
|
||||
"cost": {
|
||||
"type": "string",
|
||||
"title": "Cost"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"title": "Currency"
|
||||
},
|
||||
"cost_breakdown": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "object",
|
||||
"title": "Cost Breakdown"
|
||||
},
|
||||
"pricing_snapshot": {
|
||||
"additionalProperties": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"type": "object",
|
||||
"title": "Pricing Snapshot"
|
||||
},
|
||||
"quality": {
|
||||
"type": "string",
|
||||
"title": "Quality"
|
||||
},
|
||||
"degraded": {
|
||||
"type": "boolean",
|
||||
"title": "Degraded"
|
||||
},
|
||||
"degraded_reason": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Degraded Reason"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"commodity",
|
||||
"period_start",
|
||||
"period_end",
|
||||
"meter_id",
|
||||
"source_binding_id",
|
||||
"contract_version_id",
|
||||
"quantity",
|
||||
"cost",
|
||||
"currency",
|
||||
"cost_breakdown",
|
||||
"pricing_snapshot",
|
||||
"quality",
|
||||
"degraded",
|
||||
"degraded_reason"
|
||||
],
|
||||
"title": "MeterCostPeriodSchema",
|
||||
"description": "One auditable thermal ledger row; all Decimal values are JSON strings."
|
||||
},
|
||||
"MeterCostRecomputeResponse": {
|
||||
"properties": {
|
||||
"processed": {
|
||||
"type": "integer",
|
||||
"title": "Processed"
|
||||
},
|
||||
"normal": {
|
||||
"type": "integer",
|
||||
"title": "Normal"
|
||||
},
|
||||
"degraded": {
|
||||
"type": "integer",
|
||||
"title": "Degraded"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"processed",
|
||||
"normal",
|
||||
"degraded"
|
||||
],
|
||||
"title": "MeterCostRecomputeResponse"
|
||||
},
|
||||
"MeterCostsResponse": {
|
||||
"properties": {
|
||||
"items": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/MeterCostPeriodSchema"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Items"
|
||||
},
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"title": "Total",
|
||||
"description": "Total matching rows before pagination."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"items",
|
||||
"total"
|
||||
],
|
||||
"title": "MeterCostsResponse"
|
||||
},
|
||||
"MeterDeclareRequest": {
|
||||
"properties": {
|
||||
"label": {
|
||||
@@ -5830,6 +6293,62 @@
|
||||
}
|
||||
],
|
||||
"description": "Fixed tariff table for manual contracts. Null for tibber contracts and when no active contract exists."
|
||||
},
|
||||
"contract_version_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Contract Version Id",
|
||||
"description": "Thermal active contract version identifier; omitted for electricity."
|
||||
},
|
||||
"effective_from": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Effective From",
|
||||
"description": "Thermal contract version start; omitted for electricity."
|
||||
},
|
||||
"effective_to": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Effective To",
|
||||
"description": "Thermal contract version end; omitted for electricity."
|
||||
},
|
||||
"values": {
|
||||
"anyOf": [
|
||||
{
|
||||
"additionalProperties": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Values",
|
||||
"description": "Thermal normalized Decimal-string contract values; omitted for electricity."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -6336,6 +6855,102 @@
|
||||
"title": "SummaryResponse",
|
||||
"description": "Response for GET /api/energy/costs/summary.\n\nMonetary values are in ``currency``; the ``*_kwh`` fields are energy totals\nin kWh. ``metered_import``/``metered_export`` are **money**, not energy —\nonly the ``_kwh``-suffixed fields carry kWh.\n\n``total_payable = metered_net + fixed_costs − credits``"
|
||||
},
|
||||
"ThermalCostSummaryResponse": {
|
||||
"properties": {
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"title": "Currency"
|
||||
},
|
||||
"heating": {
|
||||
"type": "string",
|
||||
"title": "Heating"
|
||||
},
|
||||
"hot_water_heating": {
|
||||
"type": "string",
|
||||
"title": "Hot Water Heating"
|
||||
},
|
||||
"hot_water": {
|
||||
"type": "string",
|
||||
"title": "Hot Water"
|
||||
},
|
||||
"hot_water_tax": {
|
||||
"type": "string",
|
||||
"title": "Hot Water Tax"
|
||||
},
|
||||
"variable_subtotal": {
|
||||
"type": "string",
|
||||
"title": "Variable Subtotal"
|
||||
},
|
||||
"fixed_breakdown": {
|
||||
"$ref": "#/components/schemas/ThermalFixedBreakdown"
|
||||
},
|
||||
"fixed_subtotal": {
|
||||
"type": "string",
|
||||
"title": "Fixed Subtotal"
|
||||
},
|
||||
"all_in": {
|
||||
"type": "string",
|
||||
"title": "All In"
|
||||
},
|
||||
"period_count": {
|
||||
"type": "integer",
|
||||
"title": "Period Count"
|
||||
},
|
||||
"degraded_count": {
|
||||
"type": "integer",
|
||||
"title": "Degraded Count"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"currency",
|
||||
"heating",
|
||||
"hot_water_heating",
|
||||
"hot_water",
|
||||
"hot_water_tax",
|
||||
"variable_subtotal",
|
||||
"fixed_breakdown",
|
||||
"fixed_subtotal",
|
||||
"all_in",
|
||||
"period_count",
|
||||
"degraded_count"
|
||||
],
|
||||
"title": "ThermalCostSummaryResponse"
|
||||
},
|
||||
"ThermalFixedBreakdown": {
|
||||
"properties": {
|
||||
"heating_network": {
|
||||
"type": "string",
|
||||
"title": "Heating Network"
|
||||
},
|
||||
"metering": {
|
||||
"type": "string",
|
||||
"title": "Metering"
|
||||
},
|
||||
"delivery_set": {
|
||||
"type": "string",
|
||||
"title": "Delivery Set"
|
||||
},
|
||||
"hot_water_network": {
|
||||
"type": "string",
|
||||
"title": "Hot Water Network"
|
||||
},
|
||||
"other": {
|
||||
"type": "string",
|
||||
"title": "Other"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"heating_network",
|
||||
"metering",
|
||||
"delivery_set",
|
||||
"hot_water_network",
|
||||
"other"
|
||||
],
|
||||
"title": "ThermalFixedBreakdown",
|
||||
"description": "D11 annual-standing charges accrued per settled local day, as Decimal strings."
|
||||
},
|
||||
"TibberTestPriceSchema": {
|
||||
"properties": {
|
||||
"starts_at": {
|
||||
|
||||
Reference in New Issue
Block a user