1use rust_decimal::Decimal;
18use rust_decimal::dec;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
22pub enum MessstellenKategorie {
23 Pflichteinbau(PflichtBand),
25 OptionalerEinbau,
29}
30
31#[derive(
38 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
39)]
40pub enum PflichtBand {
41 Bis10000,
43 Bis20000,
45 Bis50000,
47 Bis100000,
49 Ueber100000,
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
55pub enum Entgeltschuldner {
56 Netzbetreiber,
58 Letztverbraucher,
60}
61
62#[must_use]
68pub fn preisobergrenze_eur_per_jahr(
69 kategorie: MessstellenKategorie,
70 schuldner: Entgeltschuldner,
71) -> Option<Decimal> {
72 use Entgeltschuldner as E;
73 use MessstellenKategorie as K;
74 use PflichtBand as B;
75
76 match (kategorie, schuldner) {
77 (K::Pflichteinbau(_), E::Netzbetreiber) => Some(dec!(80)),
79 (K::Pflichteinbau(B::Bis10000), E::Letztverbraucher) => Some(dec!(40)),
80 (K::Pflichteinbau(B::Bis20000), E::Letztverbraucher) => Some(dec!(50)),
81 (K::Pflichteinbau(B::Bis50000), E::Letztverbraucher) => Some(dec!(110)),
82 (K::Pflichteinbau(B::Bis100000), E::Letztverbraucher) => Some(dec!(140)),
83 (K::Pflichteinbau(B::Ueber100000), E::Letztverbraucher) => None,
85 (K::OptionalerEinbau, _) => Some(dec!(30)),
87 }
88}
89
90#[must_use]
92pub fn gesamtobergrenze_eur_per_jahr(kategorie: MessstellenKategorie) -> Option<Decimal> {
93 let nb = preisobergrenze_eur_per_jahr(kategorie, Entgeltschuldner::Netzbetreiber)?;
94 let lv = preisobergrenze_eur_per_jahr(kategorie, Entgeltschuldner::Letztverbraucher)?;
95 Some(nb + lv)
96}
97
98pub const STEUEREINRICHTUNG_OBERGRENZE_EUR_PER_JAHR: Decimal = dec!(50);
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105 use Entgeltschuldner as E;
106 use MessstellenKategorie as K;
107 use PflichtBand as B;
108
109 #[test]
111 fn the_pflichteinbau_schedule() {
112 for (band, lv, total) in [
113 (B::Bis10000, dec!(40), dec!(120)),
114 (B::Bis20000, dec!(50), dec!(130)),
115 (B::Bis50000, dec!(110), dec!(190)),
116 (B::Bis100000, dec!(140), dec!(220)),
117 ] {
118 let k = K::Pflichteinbau(band);
119 assert_eq!(
120 preisobergrenze_eur_per_jahr(k, E::Netzbetreiber),
121 Some(dec!(80))
122 );
123 assert_eq!(
124 preisobergrenze_eur_per_jahr(k, E::Letztverbraucher),
125 Some(lv)
126 );
127 assert_eq!(gesamtobergrenze_eur_per_jahr(k), Some(total));
128 }
129 }
130
131 #[test]
134 fn the_top_band_caps_only_the_grid_operators_share() {
135 let k = K::Pflichteinbau(B::Ueber100000);
136 assert_eq!(
137 preisobergrenze_eur_per_jahr(k, E::Netzbetreiber),
138 Some(dec!(80))
139 );
140 assert_eq!(preisobergrenze_eur_per_jahr(k, E::Letztverbraucher), None);
141 assert_eq!(
142 gesamtobergrenze_eur_per_jahr(k),
143 None,
144 "no total where one share is open"
145 );
146 }
147
148 #[test]
150 fn an_optional_installation_is_capped_at_thirty_each() {
151 for schuldner in [E::Netzbetreiber, E::Letztverbraucher] {
152 assert_eq!(
153 preisobergrenze_eur_per_jahr(K::OptionalerEinbau, schuldner),
154 Some(dec!(30))
155 );
156 }
157 assert_eq!(
158 gesamtobergrenze_eur_per_jahr(K::OptionalerEinbau),
159 Some(dec!(60))
160 );
161 }
162
163 #[test]
165 fn the_bands_rise_monotonically() {
166 let bands = [B::Bis10000, B::Bis20000, B::Bis50000, B::Bis100000];
167 let mut previous = Decimal::ZERO;
168 for band in bands {
169 let ceiling = preisobergrenze_eur_per_jahr(K::Pflichteinbau(band), E::Letztverbraucher)
170 .expect("a fixed ceiling");
171 assert!(ceiling > previous, "{band:?} must exceed the band below it");
172 previous = ceiling;
173 }
174 }
175}