Skip to main content

redispatch_xml/documents/
acknowledgement.rs

1//! `AcknowledgementDocument` — application-level acknowledgement for all Redispatch 2.0 message types.
2use serde::{Deserialize, Serialize};
3
4use crate::types::{
5    AttrV, AttrVWithScheme, DocumentId, DocumentVersion, MarketParticipantId, MarketRoleType,
6    UtcDateTime,
7};
8
9// ── DocumentType / ReasonCode ─────────────────────────────────────────────────
10
11/// Document types that an `AcknowledgementDocument` may reference in
12/// `ReceivingDocumentType`.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
14pub enum AckReceivingDocType {
15    /// Day-ahead plan / forecast document (A14).
16    #[serde(rename = "A14")]
17    DayAheadPlan,
18    /// Activation response document (A41).
19    #[serde(rename = "A41")]
20    ActivationResponse,
21    /// Tender reduction / ACR document (A42).
22    #[serde(rename = "A42")]
23    TenderReduction,
24    /// Status request document (A60).
25    #[serde(rename = "A60")]
26    StatusRequest,
27    /// Planned unavailability document (A67).
28    #[serde(rename = "A67")]
29    PlannedUnavailability,
30    /// Forced (unplanned) unavailability document (A76).
31    #[serde(rename = "A76")]
32    ForcedUnavailability,
33    /// Production unavailability document (A80).
34    #[serde(rename = "A80")]
35    ProductionUnavailability,
36    /// Redispatch activation / ACO document (A96).
37    #[serde(rename = "A96")]
38    RedispatchActivation,
39    /// Network constraint document (B15).
40    #[serde(rename = "B15")]
41    NetworkConstraint,
42    /// Stammdaten creation document (Z01).
43    #[serde(rename = "Z01")]
44    StammdatenCreation,
45    /// Stammdaten update document (Z02).
46    #[serde(rename = "Z02")]
47    StammdatenUpdate,
48    /// Stammdaten deactivation document (Z03).
49    #[serde(rename = "Z03")]
50    StammdatenDeactivation,
51    /// Grid operator aggregate Stammdaten document (Z04).
52    #[serde(rename = "Z04")]
53    StammdatenNbAggregate,
54    /// Kostenblatt (cost sheet) document (Z05).
55    #[serde(rename = "Z05")]
56    Kostenblatt,
57    /// Intraday plan document (Z08).
58    #[serde(rename = "Z08")]
59    IntradayPlan,
60    /// Stammdaten plan document (Z09).
61    #[serde(rename = "Z09")]
62    StammdatenPlan,
63    /// Aggregate plan document (Z11).
64    #[serde(rename = "Z11")]
65    AggregatePlan,
66    /// Corrected plan document (Z12).
67    #[serde(rename = "Z12")]
68    CorrectedPlan,
69    /// Reserved document type (Z13).
70    #[serde(rename = "Z13")]
71    Reserved13,
72    /// Bilanzkreisstammdaten (balance zone master data) document (Z14).
73    #[serde(rename = "Z14")]
74    Bilanzkreisstammdaten,
75    /// Alternative status request document (Z15).
76    #[serde(rename = "Z15")]
77    StatusRequestAlt,
78    /// Kaskade (cascade) document (Z16).
79    #[serde(rename = "Z16")]
80    Kaskade,
81    /// Test message document (Z17).
82    #[serde(rename = "Z17")]
83    TestMessage,
84}
85
86/// Reason codes used at the `AcknowledgementDocument` root level.
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
88pub enum AckReasonCode {
89    /// Message fully accepted.
90    #[serde(rename = "A01")]
91    FullyAccepted,
92    /// Message fully rejected.
93    #[serde(rename = "A02")]
94    FullyRejected,
95    /// Syntax error detected.
96    #[serde(rename = "Z12")]
97    SyntaxError,
98    /// Assignment error.
99    #[serde(rename = "Z13")]
100    AssignmentError,
101    /// Document identification not unique.
102    #[serde(rename = "Z14")]
103    DocumentIdNotUnique,
104    /// Sender not authorised.
105    #[serde(rename = "Z15")]
106    SenderUnauthorised,
107    /// Not permitted per AWT (Anwendungstabelle).
108    #[serde(rename = "Z16")]
109    NotPermitted,
110    /// Format version invalid.
111    #[serde(rename = "Z17")]
112    FormatVersionInvalid,
113    /// Report period invalid.
114    #[serde(rename = "Z18")]
115    ReportPeriodInvalid,
116}
117
118/// Reason element at the `AcknowledgementDocument` root or `TimeSeriesRejection` level.
119#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
120pub struct AckReason {
121    /// Reason code.
122    #[serde(rename = "ReasonCode")]
123    pub code: AttrV<AckReasonCode>,
124    /// Optional free-text description.
125    #[serde(
126        rename = "ReasonText",
127        default,
128        skip_serializing_if = "Option::is_none"
129    )]
130    pub text: Option<String>,
131}
132
133// ── TimeSeriesRejection ───────────────────────────────────────────────────────
134
135/// Rejection detail for a single time series within the received document.
136#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
137pub struct TimeSeriesRejection {
138    /// The `TimeSeriesIdentification` or `AllocationIdentification` of the
139    /// rejected time series.
140    #[serde(
141        rename = "TimeSeriesIdentification",
142        default,
143        skip_serializing_if = "Option::is_none"
144    )]
145    pub time_series_identification: Option<AttrV<DocumentId>>,
146    /// Reasons for the rejection.
147    #[serde(rename = "Reason", default)]
148    pub reasons: Vec<AckReason>,
149}
150
151// ── AcknowledgementDocument ───────────────────────────────────────────────────
152
153/// `AcknowledgementDocument` — application-level acknowledgement for all
154/// Redispatch 2.0 document types.
155///
156/// XSD version: 1.0g (2025-10-01)  
157/// No XML namespace.
158///
159/// An `AcknowledgementDocument` is sent in response to any received Redispatch
160/// 2.0 document. The root-level `Reason` list indicates overall acceptance
161/// (`A01`) or rejection (`A02`). Per-time-series details appear in
162/// `time_series_rejections`.
163#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
164#[serde(rename = "AcknowledgementDocument")]
165pub struct AcknowledgementDocument {
166    /// Unique document identifier (max 35 chars).
167    #[serde(rename = "DocumentIdentification")]
168    pub document_identification: AttrV<DocumentId>,
169    /// Document creation timestamp (UTC, second precision).
170    #[serde(rename = "DocumentDateTime")]
171    pub document_date_time: AttrV<UtcDateTime>,
172    /// Sender's market participant identifier.
173    #[serde(rename = "SenderIdentification")]
174    pub sender_identification: AttrVWithScheme<MarketParticipantId>,
175    /// Sender's market role.
176    #[serde(rename = "SenderRole")]
177    pub sender_role: AttrV<MarketRoleType>,
178    /// Receiver's market participant identifier.
179    #[serde(rename = "ReceiverIdentification")]
180    pub receiver_identification: AttrVWithScheme<MarketParticipantId>,
181    /// Receiver's market role.
182    #[serde(rename = "ReceiverRole")]
183    pub receiver_role: AttrV<MarketRoleType>,
184    /// `DocumentIdentification` of the acknowledged document (optional).
185    #[serde(
186        rename = "ReceivingDocumentIdentification",
187        default,
188        skip_serializing_if = "Option::is_none"
189    )]
190    pub receiving_document_identification: Option<AttrV<DocumentId>>,
191    /// `DocumentVersion` of the acknowledged document (optional).
192    #[serde(
193        rename = "ReceivingDocumentVersion",
194        default,
195        skip_serializing_if = "Option::is_none"
196    )]
197    pub receiving_document_version: Option<AttrV<DocumentVersion>>,
198    /// `DocumentType` of the acknowledged document (optional).
199    #[serde(
200        rename = "ReceivingDocumentType",
201        default,
202        skip_serializing_if = "Option::is_none"
203    )]
204    pub receiving_document_type: Option<AttrV<AckReceivingDocType>>,
205    /// Original filename of the received AS4 payload (optional).
206    #[serde(
207        rename = "ReceivingPayloadName",
208        default,
209        skip_serializing_if = "Option::is_none"
210    )]
211    pub receiving_payload_name: Option<AttrV<String>>,
212    /// `DocumentDateTime` / `CreationDateTime` of the acknowledged document (optional).
213    #[serde(
214        rename = "DateTimeReceivingDocument",
215        default,
216        skip_serializing_if = "Option::is_none"
217    )]
218    pub date_time_receiving_document: Option<AttrV<UtcDateTime>>,
219    /// Per-time-series rejection details (optional).
220    #[serde(
221        rename = "TimeSeriesRejection",
222        default,
223        skip_serializing_if = "Vec::is_empty"
224    )]
225    pub time_series_rejections: Vec<TimeSeriesRejection>,
226    /// Document-level acceptance / rejection reasons (required, at least 1).
227    #[serde(rename = "Reason")]
228    pub reasons: Vec<AckReason>,
229}