Skip to main content

bo4e_core/enums/
calculation_method.rs

1//! Calculation method (Kalkulationsmethode) enumeration.
2
3use serde::{Deserialize, Serialize};
4
5/// Calculation method for price sheets.
6///
7/// List of different calculation methods for a price sheet.
8///
9/// German: Kalkulationsmethode
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
12#[cfg_attr(feature = "json-schema", schemars(rename = "Kalkulationsmethode"))]
13#[non_exhaustive]
14pub enum CalculationMethod {
15    /// Step model - total quantity is assigned to one step and the price applies to entire quantity
16    #[serde(rename = "STUFEN")]
17    Steps,
18
19    /// Zone model - total quantity is distributed across zones with respective prices
20    #[serde(rename = "ZONEN")]
21    Zones,
22
23    /// Pre-zone base price (Vorzonengrundpreis)
24    #[serde(rename = "VORZONEN_GP")]
25    PreZoneBasePrice,
26
27    /// Sigmoid function (Sigmoidfunktion)
28    #[serde(rename = "SIGMOID")]
29    Sigmoid,
30
31    /// Reactive power above 50% of active power
32    #[serde(rename = "BLINDARBEIT_GT_50_PROZENT")]
33    ReactivePowerAbove50Percent,
34
35    /// Reactive power above 40% of active power
36    #[serde(rename = "BLINDARBEIT_GT_40_PROZENT")]
37    ReactivePowerAbove40Percent,
38
39    /// Reactive power with free allowance (defined by cos phi or percentage)
40    #[serde(rename = "BLINDARBEIT_MIT_FREIMENGE")]
41    ReactivePowerWithFreeAllowance,
42
43    /// Working and base price zoned
44    #[serde(rename = "AP_GP_ZONEN")]
45    WorkingAndBasePriceZoned,
46
47    /// Capacity charge based on installed capacity
48    #[serde(rename = "LP_INSTALL_LEISTUNG")]
49    CapacityChargeInstalledCapacity,
50
51    /// Working price based on transport or distribution network
52    #[serde(rename = "AP_TRANSPORT_ODER_VERTEILNETZ")]
53    WorkingPriceTransportOrDistribution,
54
55    /// Working price based on transport/distribution network, local network via sigmoid
56    #[serde(rename = "AP_TRANSPORT_ODER_VERTEILNETZ_ORTSVERTEILNETZ_SIGMOID")]
57    WorkingPriceTransportOrDistributionLocalSigmoid,
58
59    /// Capacity charge based on annual consumption
60    #[serde(rename = "LP_JAHRESVERBRAUCH")]
61    CapacityChargeAnnualConsumption,
62
63    /// Capacity price based on transport or distribution network
64    #[serde(rename = "LP_TRANSPORT_ODER_VERTEILNETZ")]
65    CapacityPriceTransportOrDistribution,
66
67    /// Capacity price based on transport/distribution network, local network via sigmoid
68    #[serde(rename = "LP_TRANSPORT_ODER_VERTEILNETZ_ORTSVERTEILNETZ_SIGMOID")]
69    CapacityPriceTransportOrDistributionLocalSigmoid,
70
71    /// Function-based capacity determination for consumption above SLP threshold
72    #[serde(rename = "FUNKTIONEN")]
73    Functions,
74
75    /// Above SLP threshold, function-based calculation as LGK
76    #[serde(rename = "VERBRAUCH_UEBER_SLP_GRENZE_FUNKTIONSBEZOGEN_WEITERE_BERECHNUNG_ALS_LGK")]
77    ConsumptionAboveSLPThresholdFunctionBasedLGK,
78}
79
80impl CalculationMethod {
81    /// Returns the German name.
82    pub fn german_name(&self) -> &'static str {
83        match self {
84            Self::Steps => "Stufen",
85            Self::Zones => "Zonen",
86            Self::PreZoneBasePrice => "Vorzonengrundpreis",
87            Self::Sigmoid => "Sigmoid",
88            Self::ReactivePowerAbove50Percent => "Blindarbeit oberhalb 50% der Wirkarbeit",
89            Self::ReactivePowerAbove40Percent => "Blindarbeit oberhalb 40% der Wirkarbeit",
90            Self::ReactivePowerWithFreeAllowance => "Blindarbeit mit Freimenge",
91            Self::WorkingAndBasePriceZoned => "Arbeits- und Grundpreis gezont",
92            Self::CapacityChargeInstalledCapacity => {
93                "Leistungsentgelt auf Grundlage der installierten Leistung"
94            }
95            Self::WorkingPriceTransportOrDistribution => {
96                "AP auf Grundlage Transport- oder Verteilnetz"
97            }
98            Self::WorkingPriceTransportOrDistributionLocalSigmoid => {
99                "AP auf Grundlage Transport- oder Verteilnetz, Ortsverteilnetz über Sigmoid"
100            }
101            Self::CapacityChargeAnnualConsumption => {
102                "Leistungsentgelt auf Grundlage des Jahresverbrauchs"
103            }
104            Self::CapacityPriceTransportOrDistribution => {
105                "LP auf Grundlage Transport- oder Verteilnetz"
106            }
107            Self::CapacityPriceTransportOrDistributionLocalSigmoid => {
108                "LP auf Grundlage Transport- oder Verteilnetz, Ortsverteilnetz über Sigmoid"
109            }
110            Self::Functions => "Funktionen",
111            Self::ConsumptionAboveSLPThresholdFunctionBasedLGK => {
112                "Verbrauch über SLP-Grenze funktionsbezogen als LGK"
113            }
114        }
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn test_serialize() {
124        assert_eq!(
125            serde_json::to_string(&CalculationMethod::Steps).unwrap(),
126            r#""STUFEN""#
127        );
128        assert_eq!(
129            serde_json::to_string(&CalculationMethod::Zones).unwrap(),
130            r#""ZONEN""#
131        );
132    }
133
134    #[test]
135    fn test_deserialize() {
136        assert_eq!(
137            serde_json::from_str::<CalculationMethod>(r#""SIGMOID""#).unwrap(),
138            CalculationMethod::Sigmoid
139        );
140    }
141
142    #[test]
143    fn test_roundtrip() {
144        for method in [
145            CalculationMethod::Steps,
146            CalculationMethod::Zones,
147            CalculationMethod::PreZoneBasePrice,
148            CalculationMethod::Sigmoid,
149            CalculationMethod::ReactivePowerAbove50Percent,
150            CalculationMethod::ReactivePowerAbove40Percent,
151            CalculationMethod::ReactivePowerWithFreeAllowance,
152            CalculationMethod::WorkingAndBasePriceZoned,
153            CalculationMethod::CapacityChargeInstalledCapacity,
154            CalculationMethod::WorkingPriceTransportOrDistribution,
155            CalculationMethod::WorkingPriceTransportOrDistributionLocalSigmoid,
156            CalculationMethod::CapacityChargeAnnualConsumption,
157            CalculationMethod::CapacityPriceTransportOrDistribution,
158            CalculationMethod::CapacityPriceTransportOrDistributionLocalSigmoid,
159            CalculationMethod::Functions,
160            CalculationMethod::ConsumptionAboveSLPThresholdFunctionBasedLGK,
161        ] {
162            let json = serde_json::to_string(&method).unwrap();
163            let parsed: CalculationMethod = serde_json::from_str(&json).unwrap();
164            assert_eq!(method, parsed);
165        }
166    }
167}