M7-T06: add meter management UI (timeline, declare swap, edit) to Energy view
This commit is contained in:
Vendored
+278
@@ -559,6 +559,84 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/energy/meters": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/**
|
||||
* List Energy Meters
|
||||
* @description List all meter epochs in ascending ``started_at`` order.
|
||||
*
|
||||
* Returns the full historical sequence of meter installations across all
|
||||
* commodities. The active meter (``ended_at=null``) appears last because it
|
||||
* has the latest ``started_at``.
|
||||
*/
|
||||
get: operations["list_energy_meters_api_energy_meters_get"];
|
||||
put?: never;
|
||||
/**
|
||||
* Declare Energy Meter
|
||||
* @description Declare a new meter epoch (swap, home move, or initial declaration).
|
||||
*
|
||||
* Closes the current active meter for the given commodity at ``started_at``
|
||||
* and opens a new active meter. If no active meter exists, the new meter is
|
||||
* simply created without closing anything.
|
||||
*
|
||||
* **Validation**: ``started_at`` must be **≥** the current active meter's
|
||||
* own ``started_at`` (no chronological backdate below the active epoch's
|
||||
* start). Equal timestamps are allowed (replaces the current meter at the
|
||||
* same logical moment). Violation → 422.
|
||||
*
|
||||
* **Retroactive recompute**: if ``started_at`` is in the past, billing
|
||||
* records from that point forward are re-judged via ``recompute_range`` to
|
||||
* reflect the new meter attribution. The response includes the count of
|
||||
* recomputed periods in ``recomputed_periods`` (not part of ``MeterResponse``
|
||||
* — the recompute is transparent; callers should re-fetch costs if needed).
|
||||
*/
|
||||
post: operations["declare_energy_meter_api_energy_meters_post"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/energy/meters/{meter_id}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
/**
|
||||
* Patch Energy Meter
|
||||
* @description Partially update a meter epoch: rename, edit note, or correct started_at.
|
||||
*
|
||||
* - ``label``: updates the human-readable label.
|
||||
* - ``note``: updates the free-form note.
|
||||
* - ``started_at``: **retroactive correction** — shifts this meter's start
|
||||
* boundary. The service layer maintains timeline continuity by also
|
||||
* updating the preceding meter's ``ended_at``. Validation:
|
||||
* * Must be strictly after the previous meter's own ``started_at``.
|
||||
* * Must be strictly before this meter's ``ended_at`` (if closed).
|
||||
* Violation → 422.
|
||||
*
|
||||
* **Retroactive recompute when ``started_at`` changes**: billing records in
|
||||
* the window ``[min(old, new), now)`` are re-judged to reflect the corrected
|
||||
* meter attribution.
|
||||
*
|
||||
* Not found → 404.
|
||||
*/
|
||||
patch: operations["patch_energy_meter_api_energy_meters__meter_id__patch"];
|
||||
trace?: never;
|
||||
};
|
||||
"/api/expose": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1569,6 +1647,114 @@ export interface components {
|
||||
*/
|
||||
sell_normal: number;
|
||||
};
|
||||
/**
|
||||
* MeterDeclareRequest
|
||||
* @description Request body for POST /api/energy/meters.
|
||||
*
|
||||
* Declares a new meter epoch (swap, home move, or initial declaration). The
|
||||
* service layer closes the current active meter for the given commodity at
|
||||
* ``started_at`` and opens a new one.
|
||||
*
|
||||
* ``started_at`` follows the Principle-A localisation convention: a
|
||||
* timezone-naive value is interpreted as the **server's local wall-clock time**
|
||||
* (e.g. CEST midnight → stored as UTC the night before); a timezone-aware
|
||||
* value is converted to UTC as-is. Omitting ``started_at`` is not allowed —
|
||||
* every meter declaration must carry an explicit start timestamp.
|
||||
*
|
||||
* ``commodity`` defaults to ``"electricity"``; the field is available for
|
||||
* future use with ``gas`` or ``heating``.
|
||||
*/
|
||||
MeterDeclareRequest: {
|
||||
/** Label */
|
||||
label: string;
|
||||
/**
|
||||
* Started At
|
||||
* Format: date-time
|
||||
* @description UTC (or server-local naive) datetime from which this meter epoch starts. May be in the past (retroactive declaration).
|
||||
*/
|
||||
started_at: string;
|
||||
/** @description Why this epoch was created. One of: initial, meter_swap, home_move, other. */
|
||||
reason: components["schemas"]["MeterReason"];
|
||||
/** Note */
|
||||
note?: string | null;
|
||||
/**
|
||||
* Commodity
|
||||
* @description Energy commodity this meter measures. Defaults to 'electricity'.
|
||||
* @default electricity
|
||||
*/
|
||||
commodity: string;
|
||||
};
|
||||
/**
|
||||
* MeterListResponse
|
||||
* @description Response schema for GET /api/energy/meters.
|
||||
*
|
||||
* Meters are returned in ascending ``started_at`` order so the caller sees
|
||||
* the historical installation sequence.
|
||||
*/
|
||||
MeterListResponse: {
|
||||
/** Items */
|
||||
items: components["schemas"]["MeterResponse"][];
|
||||
/** Total */
|
||||
total: number;
|
||||
};
|
||||
/**
|
||||
* MeterPatchRequest
|
||||
* @description Request body for PATCH /api/energy/meters/{id}.
|
||||
*
|
||||
* All fields are optional. Only non-``None`` values are applied.
|
||||
*
|
||||
* Updating ``started_at`` is a **retroactive correction**: the service layer
|
||||
* maintains timeline continuity (adjusting the preceding meter's ``ended_at``)
|
||||
* and the API layer triggers ``recompute_range`` over the affected window so
|
||||
* that billing attribution is re-judged.
|
||||
*/
|
||||
MeterPatchRequest: {
|
||||
/** Label */
|
||||
label?: string | null;
|
||||
/** Note */
|
||||
note?: string | null;
|
||||
/**
|
||||
* Started At
|
||||
* @description Retroactive correction of the meter epoch start timestamp. Triggers billing recompute over the affected window.
|
||||
*/
|
||||
started_at?: string | null;
|
||||
};
|
||||
/**
|
||||
* MeterReason
|
||||
* @description Allowed values for the meter epoch creation reason.
|
||||
* @enum {string}
|
||||
*/
|
||||
MeterReason: "initial" | "meter_swap" | "home_move" | "other";
|
||||
/**
|
||||
* MeterResponse
|
||||
* @description Response schema for a single Meter epoch row.
|
||||
*
|
||||
* ``ended_at`` is ``null`` for the currently active meter.
|
||||
*/
|
||||
MeterResponse: {
|
||||
/** Id */
|
||||
id: number;
|
||||
/** Label */
|
||||
label: string;
|
||||
/** Commodity */
|
||||
commodity: string;
|
||||
/**
|
||||
* Started At
|
||||
* Format: date-time
|
||||
*/
|
||||
started_at: string;
|
||||
/** Ended At */
|
||||
ended_at: string | null;
|
||||
/** Reason */
|
||||
reason: string;
|
||||
/** Note */
|
||||
note: string | null;
|
||||
/**
|
||||
* Created At
|
||||
* Format: date-time
|
||||
*/
|
||||
created_at: string;
|
||||
};
|
||||
/**
|
||||
* MetricInfo
|
||||
* @description Metadata for a single measurable quantity in a device's profile.
|
||||
@@ -3007,6 +3193,98 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
list_energy_meters_api_energy_meters_get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["MeterListResponse"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
declare_energy_meter_api_energy_meters_post: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: {
|
||||
"X-CSRF-Token"?: string | null;
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["MeterDeclareRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
201: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["MeterResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
patch_energy_meter_api_energy_meters__meter_id__patch: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: {
|
||||
"X-CSRF-Token"?: string | null;
|
||||
};
|
||||
path: {
|
||||
meter_id: number;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["MeterPatchRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["MeterResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
get_expose_api_expose_get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
Reference in New Issue
Block a user