Skip to main content

redispatch_xml/documents/
activation.rs

1//! `ActivationDocument` -- redispatch activation orders (ACO), confirmations (ACR), and activation adjustments (AAR).
2use serde::{Deserialize, Serialize};
3
4use crate::types::{
5    AttrV, AttrVWithScheme, ControlZone, Direction, DocumentId, DocumentVersion,
6    MarketParticipantId, MarketRoleType, MeasureUnit, Period, TimeInterval, UtcDateTime,
7};
8
9// ── Namespace ─────────────────────────────────────────────────────────────────
10
11/// Expected XML namespace for `ActivationDocument`.
12pub const NAMESPACE: &str = "urn:entsoe.eu:wgedi:errp:activationdocument:5:0";
13
14// ── DocumentType ─────────────────────────────────────────────────────────────
15
16/// `DocumentType` codes for `ActivationDocument`.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
18pub enum ActivationDocType {
19    /// Activation response (ACR).
20    #[serde(rename = "A41")]
21    ActivationResponse,
22    /// Tender reduction (AAR).
23    #[serde(rename = "A42")]
24    TenderReduction,
25    /// Redispatch activation document (ACO).
26    #[serde(rename = "A96")]
27    RedispatchActivation,
28}
29
30/// `ProcessType` codes for `ActivationDocument`.
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
32pub enum ActivationProcessType {
33    /// Redispatch activation process.
34    #[serde(rename = "A41")]
35    Redispatch,
36    /// Test / other.
37    #[serde(rename = "Z01")]
38    Other,
39}
40
41/// `Status` codes used in `ActivationTimeSeries`.
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
43pub enum TimeSeriesStatus {
44    /// Volumes available (used for partial-rejection ACR).
45    #[serde(rename = "A06")]
46    Available,
47    /// Quantities activated (Information).
48    #[serde(rename = "A07")]
49    Activated,
50    /// Quantities ordered (Anweisung / ACO).
51    #[serde(rename = "A10")]
52    Ordered,
53}
54
55/// `BusinessType` codes used in `ActivationTimeSeries`.
56#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
57pub enum TimeSeriesBusinessType {
58    /// System Operator redispatching (Deltaanweisung).
59    #[serde(rename = "A46")]
60    SystemOperatorRedispatching,
61    /// Internal redispatch (Sollwertvorgabe).
62    #[serde(rename = "A85")]
63    InternalRedispatch,
64}
65
66// ── Document-level Reason ─────────────────────────────────────────────────────
67
68/// Reason code at the `ActivationDocument` root level (document-level
69/// acceptance/rejection).
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
71pub enum DocumentReasonCode {
72    /// Deadline exceeded (Frist abgelaufen).
73    #[serde(rename = "A57")]
74    DeadlineExceeded,
75    /// Complementary information.
76    #[serde(rename = "A95")]
77    ComplementaryInfo,
78    /// Technical constraint.
79    #[serde(rename = "A96")]
80    TechnicalConstraint,
81}
82
83/// Root-level reason attached to an `ActivationDocument`.
84#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
85pub struct DocumentReason {
86    /// Document-level reason code.
87    #[serde(rename = "ReasonCode")]
88    pub code: AttrV<DocumentReasonCode>,
89    /// Optional free-text description.
90    #[serde(
91        rename = "ReasonText",
92        default,
93        skip_serializing_if = "Option::is_none"
94    )]
95    pub text: Option<String>,
96}
97
98// ── ActivationTimeSeries ──────────────────────────────────────────────────────
99
100/// Reference to a `ResourceObject` with its NDE coding scheme.
101pub type ResourceObjectRef = AttrVWithScheme<String, ResourceObjectCodingScheme>;
102
103/// Coding scheme for resource object identifiers.
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
105pub enum ResourceObjectCodingScheme {
106    /// Germany National coding scheme (BDEW resource code).
107    #[serde(rename = "NDE")]
108    Nde,
109}
110
111/// Reference to a control zone (EIC) with `codingScheme = "A01"`.
112pub type ControlZoneRef = AttrVWithScheme<ControlZone, EicCodingScheme>;
113
114/// Coding scheme for EIC-coded identifiers (always `A01`).
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
116pub enum EicCodingScheme {
117    /// EIC — Energy Identification Coding Scheme.
118    #[serde(rename = "A01")]
119    Eic,
120}
121
122/// A single activated time series within an `ActivationDocument`.
123///
124/// Each `ActivationTimeSeries` covers one direction (up/down) for one
125/// `ResourceObject`. An `ActivationDocument` may contain up to two time
126/// series (one per direction).
127#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
128pub struct ActivationTimeSeries {
129    /// Unique time-series identifier within this document.
130    #[serde(rename = "AllocationIdentification")]
131    pub allocation_identification: AttrV<DocumentId>,
132    /// Resource provider (EIV or NB) — optional when sender is the provider.
133    #[serde(
134        rename = "ResourceProvider",
135        default,
136        skip_serializing_if = "Option::is_none"
137    )]
138    pub resource_provider: Option<AttrVWithScheme<MarketParticipantId>>,
139    /// Business type: delta instruction (`A46`) or setpoint (`A85`).
140    #[serde(rename = "BusinessType")]
141    pub business_type: AttrV<TimeSeriesBusinessType>,
142    /// German TSO control block (always `10YCB-GERMANY--8`, EIC).
143    #[serde(rename = "AcquiringArea")]
144    pub acquiring_area: AttrVWithScheme<String, EicCodingScheme>,
145    /// Connecting control zone where the resource object is connected.
146    #[serde(rename = "ConnectingArea")]
147    pub connecting_area: ControlZoneRef,
148    /// Physical unit of the quantity values (`MAW` or `P1`).
149    #[serde(rename = "MeasureUnit")]
150    pub measure_unit: AttrV<MeasureUnit>,
151    /// Redispatch direction: up (`A01`) or down (`A02`).
152    #[serde(rename = "Direction")]
153    pub direction: AttrV<Direction>,
154    /// Activation / order / availability status.
155    #[serde(rename = "Status")]
156    pub status: AttrV<TimeSeriesStatus>,
157    /// Resource object identifier (BDEW resource code, NDE scheme).
158    #[serde(rename = "ResourceObject")]
159    pub resource_object: ResourceObjectRef,
160    /// `DocumentIdentification` of the originating planning data (optional).
161    #[serde(
162        rename = "SendersDocumentIdentification",
163        default,
164        skip_serializing_if = "Option::is_none"
165    )]
166    pub senders_document_identification: Option<AttrV<DocumentId>>,
167    /// `DocumentVersion` of the originating planning data (optional).
168    #[serde(
169        rename = "SendersDocumentVersion",
170        default,
171        skip_serializing_if = "Option::is_none"
172    )]
173    pub senders_document_version: Option<AttrV<DocumentVersion>>,
174    /// `CreationDateTime` of the originating planning data (optional).
175    #[serde(
176        rename = "SendersDocumentDateTime",
177        default,
178        skip_serializing_if = "Option::is_none"
179    )]
180    pub senders_document_date_time: Option<AttrV<UtcDateTime>>,
181    /// Original `TimeSeriesIdentification` (not used in practice).
182    #[serde(
183        rename = "SendersTimeSeriesIdentification",
184        default,
185        skip_serializing_if = "Option::is_none"
186    )]
187    pub senders_time_series_identification: Option<AttrV<DocumentId>>,
188    /// Original sender's market participant ID when forwarded via data provider.
189    #[serde(
190        rename = "OriginalSenderIdentification",
191        default,
192        skip_serializing_if = "Option::is_none"
193    )]
194    pub original_sender_identification: Option<AttrVWithScheme<MarketParticipantId>>,
195    /// Original `DocumentIdentification` when forwarded.
196    #[serde(
197        rename = "OriginalDocumentIdentification",
198        default,
199        skip_serializing_if = "Option::is_none"
200    )]
201    pub original_document_identification: Option<AttrV<DocumentId>>,
202    /// Original `DocumentVersion` when forwarded.
203    #[serde(
204        rename = "OriginalDocumentVersion",
205        default,
206        skip_serializing_if = "Option::is_none"
207    )]
208    pub original_document_version: Option<AttrV<DocumentVersion>>,
209    /// Original `CreationDateTime` when forwarded.
210    #[serde(
211        rename = "OriginalDocumentDateTime",
212        default,
213        skip_serializing_if = "Option::is_none"
214    )]
215    pub original_document_date_time: Option<AttrV<UtcDateTime>>,
216    /// Original `AllocationIdentification` when forwarded.
217    #[serde(
218        rename = "OriginalAllocationIdentification",
219        default,
220        skip_serializing_if = "Option::is_none"
221    )]
222    pub original_allocation_identification: Option<AttrV<DocumentId>>,
223    /// Quarter-hour activation data for the delivery day.
224    #[serde(rename = "Period")]
225    pub period: Period,
226}
227
228// ── ActivationDocument ────────────────────────────────────────────────────────
229
230/// `ActivationDocument` — Redispatch 2.0 activation instruction, response, or
231/// reduction document.
232///
233/// XSD version: 1.1f (Fehlerkorrektur 2026-02-19)  
234/// Namespace: `urn:entsoe.eu:wgedi:errp:activationdocument:5:0`
235///
236/// Three document types share this format:
237/// - **ACO** (`A96`): Activation order sent by the requesting NB to the
238///   resource provider's NB.
239/// - **ACR** (`A41`): Activation response from the resource provider's NB.
240/// - **AAR** (`A42`): Tender reduction sent by the requesting NB when it
241///   reduces or cancels a previously issued ACO.
242#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
243#[serde(rename = "ActivationDocument")]
244pub struct ActivationDocument {
245    /// Unique document identifier (max 35 chars, case-sensitive).
246    #[serde(rename = "DocumentIdentification")]
247    pub document_identification: AttrV<DocumentId>,
248    /// Document version number (1–999).
249    #[serde(rename = "DocumentVersion")]
250    pub document_version: AttrV<DocumentVersion>,
251    /// Document type: ACR (`A41`), AAR (`A42`), or ACO (`A96`).
252    #[serde(rename = "DocumentType")]
253    pub document_type: AttrV<ActivationDocType>,
254    /// Process type: always `A41` (redispatch process).
255    #[serde(rename = "ProcessType")]
256    pub process_type: AttrV<ActivationProcessType>,
257    /// Sender's market participant identifier.
258    #[serde(rename = "SenderIdentification")]
259    pub sender_identification: AttrVWithScheme<MarketParticipantId>,
260    /// Sender's market role.
261    #[serde(rename = "SenderRole")]
262    pub sender_role: AttrV<MarketRoleType>,
263    /// Receiver's market participant identifier.
264    #[serde(rename = "ReceiverIdentification")]
265    pub receiver_identification: AttrVWithScheme<MarketParticipantId>,
266    /// Receiver's market role.
267    #[serde(rename = "ReceiverRole")]
268    pub receiver_role: AttrV<MarketRoleType>,
269    /// Document creation timestamp (UTC, second precision).
270    #[serde(rename = "CreationDateTime")]
271    pub creation_date_time: AttrV<UtcDateTime>,
272    /// Delivery day covered by this document (UTC interval, minute precision).
273    #[serde(rename = "ActivationTimeInterval")]
274    pub activation_time_interval: AttrV<TimeInterval>,
275    /// `DocumentIdentification` of the ACO this ACR/AAR responds to (optional).
276    #[serde(
277        rename = "OrderIdentification",
278        default,
279        skip_serializing_if = "Option::is_none"
280    )]
281    pub order_identification: Option<AttrV<DocumentId>>,
282    /// `DocumentVersion` of the ACO this ACR/AAR responds to (optional).
283    #[serde(
284        rename = "OrderIdentificationVersion",
285        default,
286        skip_serializing_if = "Option::is_none"
287    )]
288    pub order_identification_version: Option<AttrV<DocumentVersion>>,
289    /// Activated time series (1–2 entries; one per direction).
290    #[serde(rename = "ActivationTimeSeries", default)]
291    pub time_series: Vec<ActivationTimeSeries>,
292    /// Document-level reason (optional; present on full rejections).
293    #[serde(rename = "Reason", default, skip_serializing_if = "Option::is_none")]
294    pub reason: Option<DocumentReason>,
295}