Skip to main content

redispatch_xml/documents/
planned_resource_schedule.rs

1//! `PlannedResourceScheduleDocument` -- planned generation and consumption schedule for dispatchable resources.
2use serde::{Deserialize, Serialize};
3
4use crate::documents::activation::{ControlZoneRef, EicCodingScheme};
5use crate::types::{
6    AttrV, AttrVWithScheme, Direction, DocumentId, DocumentVersion, MarketParticipantId,
7    MarketRoleType, MeasureUnit, Period, TimeInterval, UtcDateTime,
8};
9
10// ── DocumentType ──────────────────────────────────────────────────────────────
11
12/// `DocumentType` codes for `PlannedResourceScheduleDocument`.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
14pub enum PrsDocType {
15    /// Day-ahead plan.
16    #[serde(rename = "A14")]
17    DayAheadPlan,
18    /// Intraday plan (Planungsdaten).
19    #[serde(rename = "Z08")]
20    IntradayPlan,
21    /// Stammdaten-based plan.
22    #[serde(rename = "Z09")]
23    StammdatenPlan,
24    /// Aggregate plan.
25    #[serde(rename = "Z11")]
26    AggregatePlan,
27    /// Corrected plan.
28    #[serde(rename = "Z12")]
29    CorrectedPlan,
30}
31
32/// `ProcessType` for `PlannedResourceScheduleDocument` (always forecast).
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
34pub enum PrsProcessType {
35    /// Forecast (day-ahead / intraday).
36    #[serde(rename = "A14")]
37    Forecast,
38}
39
40/// `BusinessType` codes for `PlannedResourceTimeSeries`.
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
42pub enum PrsBusinessType {
43    /// Production schedule (A01).
44    #[serde(rename = "A01")]
45    Production,
46    /// Consumption schedule (A04).
47    #[serde(rename = "A04")]
48    Consumption,
49    /// Generation forecast (A10).
50    #[serde(rename = "A10")]
51    GenerationForecast,
52    /// Consumption forecast (A11).
53    #[serde(rename = "A11")]
54    ConsumptionForecast,
55    /// Generation schedule (A12).
56    #[serde(rename = "A12")]
57    GenerationSchedule,
58    /// System operator redispatching schedule (A46).
59    #[serde(rename = "A46")]
60    SystemOperatorRedispatching,
61    /// Transmission capacity (A60).
62    #[serde(rename = "A60")]
63    TransmissionCapacity,
64    /// Exchange schedule (A61).
65    #[serde(rename = "A61")]
66    ExchangeSchedule,
67    /// Dispatchable production unit (A77).
68    #[serde(rename = "A77")]
69    ProductionDispatchable,
70    /// Dispatchable consumption unit (A79).
71    #[serde(rename = "A79")]
72    ConsumptionDispatchable,
73    /// Internal redispatch (A85).
74    #[serde(rename = "A85")]
75    InternalRedispatch,
76    /// Controllable generation unit (A93).
77    #[serde(rename = "A93")]
78    ControllableGeneration,
79    /// Controllable consumption unit (A94).
80    #[serde(rename = "A94")]
81    ControllableConsumption,
82    /// Network element (B59).
83    #[serde(rename = "B59")]
84    NetworkElement,
85    /// Flexibility resource (Z05).
86    #[serde(rename = "Z05")]
87    Flexibility,
88}
89
90/// `Status` codes for `PlannedResourceTimeSeries`.
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
92pub enum PrsTimeSeriesStatus {
93    /// Activated.
94    #[serde(rename = "A07")]
95    Activated,
96    /// Planned.
97    #[serde(rename = "A36")]
98    Planned,
99    /// Bedarf (demand / requested).
100    #[serde(rename = "Z06")]
101    Demand,
102}
103
104/// Product code (always `"8716867000016"` — active power).
105#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
106pub enum Product {
107    /// Active power.
108    #[serde(rename = "8716867000016")]
109    ActivePower,
110}
111
112/// Coding scheme for grid element identifiers.
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
114pub enum GridElementCodingScheme {
115    /// EIC.
116    #[serde(rename = "A01")]
117    Eic,
118    /// National resource code.
119    #[serde(rename = "A02")]
120    NationalResource,
121    /// Other national scheme.
122    #[serde(rename = "Z01")]
123    Other,
124}
125
126// ── PlannedResourceTimeSeries ─────────────────────────────────────────────────
127
128/// A single planned resource time series within a
129/// `PlannedResourceScheduleDocument`.
130#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
131pub struct PlannedResourceTimeSeries {
132    /// Reference to the original time series when this one corrects it.
133    ///
134    /// Without it a correction cannot be matched to what it corrects, so the
135    /// receiver either applies it twice or not at all.
136    #[serde(
137        rename = "OriginalTimeSeriesIdentification",
138        default,
139        skip_serializing_if = "Option::is_none"
140    )]
141    pub original_time_series_identification: Option<AttrV<DocumentId>>,
142    /// The **anfordernder Netzbetreiber** — the operator that identified the
143    /// Netzengpass and requested the Maßnahme (`BilAReM` Kap. 1).
144    ///
145    /// It is not necessarily the anweisende Netzbetreiber: a request travels up
146    /// the cascade, and Kap. 17.3.4 of the `MaBiS` Anlage puts a whole
147    /// Ausfallarbeit exchange between the two. Dropping it leaves the
148    /// Ausfallarbeit with no addressee.
149    #[serde(
150        rename = "RequestingGridOperator",
151        default,
152        skip_serializing_if = "Option::is_none"
153    )]
154    pub requesting_grid_operator: Option<AttrVWithScheme<MarketParticipantId>>,
155    /// Unique time-series identifier within this document (max 35 chars).
156    #[serde(rename = "TimeSeriesIdentification")]
157    pub time_series_identification: AttrV<DocumentId>,
158    /// Business type.
159    #[serde(rename = "BusinessType")]
160    pub business_type: AttrV<PrsBusinessType>,
161    /// Redispatch direction (optional — absent for non-directional series).
162    #[serde(rename = "Direction", default, skip_serializing_if = "Option::is_none")]
163    pub direction: Option<AttrV<Direction>>,
164    /// Control zone where the resource is connected (optional).
165    #[serde(
166        rename = "ConnectingArea",
167        default,
168        skip_serializing_if = "Option::is_none"
169    )]
170    pub connecting_area: Option<ControlZoneRef>,
171    /// Resource object identifier (optional).
172    #[serde(
173        rename = "ResourceObject",
174        default,
175        skip_serializing_if = "Option::is_none"
176    )]
177    pub resource_object: Option<AttrVWithScheme<String, GridElementCodingScheme>>,
178    /// Product code (always active power `8716867000016`).
179    #[serde(rename = "Product")]
180    pub product: AttrV<Product>,
181    /// German TSO control block reference (optional).
182    #[serde(
183        rename = "AcquiringArea",
184        default,
185        skip_serializing_if = "Option::is_none"
186    )]
187    pub acquiring_area: Option<AttrVWithScheme<String, EicCodingScheme>>,
188    /// Grid element EIC or resource code (optional).
189    #[serde(
190        rename = "GridElement",
191        default,
192        skip_serializing_if = "Option::is_none"
193    )]
194    pub grid_element: Option<AttrVWithScheme<String, GridElementCodingScheme>>,
195    /// Physical unit of quantity values.
196    /// Power unit.
197    ///
198    /// The XSD element is `MeasurementUnit`, not `MeasureUnit` — only the
199    /// `ActivationDocument` uses the shorter spelling, and only in its
200    /// `ActivationTimeSeries`.
201    #[serde(rename = "MeasurementUnit")]
202    pub measurement_unit: AttrV<MeasureUnit>,
203    /// Time series status (optional).
204    #[serde(rename = "Status", default, skip_serializing_if = "Option::is_none")]
205    pub status: Option<AttrV<PrsTimeSeriesStatus>>,
206    /// Resource provider (optional).
207    #[serde(
208        rename = "ResourceProvider",
209        default,
210        skip_serializing_if = "Option::is_none"
211    )]
212    pub resource_provider: Option<AttrVWithScheme<MarketParticipantId>>,
213    /// Quarter-hour power plan for the delivery day.
214    #[serde(rename = "Period")]
215    pub period: Period,
216}
217
218// ── PlannedResourceScheduleDocument ──────────────────────────────────────────
219
220/// `PlannedResourceScheduleDocument` — day-ahead and intraday resource
221/// planning data submitted by resource providers and DSOs.
222///
223/// XSD version: 1.0f (Fehlerkorrektur 2026-02-19)  
224/// No XML namespace (no `targetNamespace` in XSD).
225#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
226#[serde(rename = "PlannedResourceScheduleDocument")]
227pub struct PlannedResourceScheduleDocument {
228    /// Original sender when this document corrects an earlier one.
229    #[serde(
230        rename = "OriginalSenderIdentification",
231        default,
232        skip_serializing_if = "Option::is_none"
233    )]
234    pub original_sender_identification: Option<AttrVWithScheme<MarketParticipantId>>,
235    /// Identifier of the document being corrected.
236    #[serde(
237        rename = "OriginalDocumentIdentification",
238        default,
239        skip_serializing_if = "Option::is_none"
240    )]
241    pub original_document_identification: Option<AttrV<DocumentId>>,
242    /// Version of the document being corrected.
243    #[serde(
244        rename = "OriginalDocumentVersion",
245        default,
246        skip_serializing_if = "Option::is_none"
247    )]
248    pub original_document_version: Option<AttrV<DocumentVersion>>,
249    /// Creation timestamp of the document being corrected.
250    #[serde(
251        rename = "OriginalDocumentDateTime",
252        default,
253        skip_serializing_if = "Option::is_none"
254    )]
255    pub original_document_date_time: Option<AttrV<UtcDateTime>>,
256    /// Unique document identifier (max 35 chars).
257    #[serde(rename = "DocumentIdentification")]
258    pub document_identification: AttrV<DocumentId>,
259    /// Document version number (1–999).
260    #[serde(rename = "DocumentVersion")]
261    pub document_version: AttrV<DocumentVersion>,
262    /// Document type.
263    #[serde(rename = "DocumentType")]
264    pub document_type: AttrV<PrsDocType>,
265    /// Process type (always forecast).
266    #[serde(rename = "ProcessType")]
267    pub process_type: AttrV<PrsProcessType>,
268    /// Sender's market participant identifier.
269    #[serde(rename = "SenderIdentification")]
270    pub sender_identification: AttrVWithScheme<MarketParticipantId>,
271    /// Sender's market role.
272    #[serde(rename = "SenderRole")]
273    pub sender_role: AttrV<MarketRoleType>,
274    /// Receiver's market participant identifier.
275    #[serde(rename = "ReceiverIdentification")]
276    pub receiver_identification: AttrVWithScheme<MarketParticipantId>,
277    /// Receiver's market role.
278    #[serde(rename = "ReceiverRole")]
279    pub receiver_role: AttrV<MarketRoleType>,
280    /// Document creation timestamp (UTC, second precision).
281    #[serde(rename = "DocumentDateTime")]
282    pub document_date_time: AttrV<UtcDateTime>,
283    /// Delivery period covered by this document (UTC interval).
284    #[serde(rename = "TimePeriodCovered")]
285    pub time_period_covered: AttrV<TimeInterval>,
286    /// Planned resource time series (one or more).
287    #[serde(rename = "PlannedResourceTimeSeries", default)]
288    pub time_series: Vec<PlannedResourceTimeSeries>,
289}