grid_tariffs/
price_list.rs

1use chrono::{DateTime, NaiveDate};
2use chrono_tz::Tz;
3use serde::Serialize;
4
5use crate::{
6    FeedInRevenueSimplified, Language, Money, PowerTariff, PowerTariffSimplified,
7    TransferFeeSimplified, costs::Cost, feed_in_revenue::FeedInRevenue, helpers,
8    transfer_fee::TransferFee,
9};
10
11#[derive(Debug, Clone, Serialize)]
12#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
13pub struct PriceList {
14    variant: Option<&'static str>,
15    from_date: NaiveDate,
16    /// Fixed monthly fee
17    monthly_fee: Cost,
18    /// Fixed monthly fee for allowing energy production
19    monthly_production_fee: Cost,
20    transfer_fee: TransferFee,
21    feed_in_revenue: FeedInRevenue,
22    power_tariff: PowerTariff,
23}
24
25impl PriceList {
26    pub(crate) const fn builder() -> PriceListBuilder {
27        PriceListBuilder::new()
28    }
29
30    pub const fn variant(&self) -> Option<&'static str> {
31        self.variant
32    }
33
34    pub const fn from_date(&self) -> NaiveDate {
35        self.from_date
36    }
37
38    pub const fn monthly_fee(&self) -> &Cost {
39        &self.monthly_fee
40    }
41
42    pub const fn monthly_production_fee(&self) -> &Cost {
43        &self.monthly_production_fee
44    }
45
46    pub const fn transfer_fee(&self) -> &TransferFee {
47        &self.transfer_fee
48    }
49
50    pub const fn feed_in_revenue(&self) -> &FeedInRevenue {
51        &self.feed_in_revenue
52    }
53
54    pub const fn power_tariff(&self) -> &PowerTariff {
55        &self.power_tariff
56    }
57
58    /// Total fee per kWh
59    ///
60    /// Please note that taxes are not included.
61    ///
62    pub fn kwh_fee(
63        &self,
64        timestamp: DateTime<Tz>,
65        spotprice: Money,
66        fuse_size: u16,
67        yearly_consumption: u32,
68    ) -> Money {
69        self.transfer_fee()
70            .kwh_cost(timestamp, spotprice, fuse_size, yearly_consumption)
71    }
72
73    /// Total revenue per kWh
74    ///
75    /// Please note that tax reductions are not included.
76    ///
77    pub fn kwh_revenue(
78        &self,
79        timestamp: DateTime<Tz>,
80        spotprice: Money,
81        fuse_size: u16,
82        yearly_consumption: u32,
83    ) -> Money {
84        self.feed_in_revenue()
85            .kwh_revenue(timestamp, spotprice, fuse_size, yearly_consumption)
86    }
87
88    pub fn simplified(
89        &self,
90        fuse_size: u16,
91        yearly_consumption: u32,
92        language: Language,
93    ) -> PriceListSimplified {
94        PriceListSimplified::new(self, fuse_size, yearly_consumption, language)
95    }
96}
97
98#[derive(Debug, Clone)]
99pub(crate) struct PriceListBuilder {
100    variant: Option<&'static str>,
101    from_date: Option<NaiveDate>,
102    /// Fixed monthly fee
103    monthly_fee: Option<Cost>,
104    /// Fixed monthly fee for allowing energy production
105    monthly_production_fee: Option<Cost>,
106    transfer_fee: Option<TransferFee>,
107    feed_in_revenue: Option<FeedInRevenue>,
108    power_tariff: Option<PowerTariff>,
109}
110
111impl PriceListBuilder {
112    pub(crate) const fn new() -> Self {
113        Self {
114            variant: None,
115            from_date: None,
116            monthly_fee: None,
117            monthly_production_fee: None,
118            transfer_fee: None,
119            feed_in_revenue: None,
120            power_tariff: None,
121        }
122    }
123
124    pub(crate) const fn build(self) -> PriceList {
125        PriceList {
126            variant: self.variant,
127            from_date: self.from_date.expect("`from_date` required"),
128            monthly_fee: self.monthly_fee.expect("`monthly_fee` required"),
129            monthly_production_fee: self
130                .monthly_production_fee
131                .expect("`monthly_production_fee` required"),
132            transfer_fee: self.transfer_fee.expect("`transfer_fee` required"),
133            feed_in_revenue: self.feed_in_revenue.expect("`feed_in_revenue` required"),
134            power_tariff: self.power_tariff.expect("`grid_tariff` required"),
135        }
136    }
137
138    pub(crate) const fn variant(mut self, name: &'static str) -> Self {
139        self.variant = Some(name);
140        self
141    }
142
143    #[allow(clippy::wrong_self_convention)]
144    pub(crate) const fn from_date(mut self, year: i32, month: u32, day: u32) -> Self {
145        self.from_date = Some(helpers::date(year, month, day));
146        self
147    }
148
149    pub(crate) const fn monthly_fee(mut self, monthly_fee: Cost) -> Self {
150        self.monthly_fee = Some(monthly_fee);
151        self
152    }
153
154    pub(crate) const fn monthly_production_fee(mut self, monthly_production_fee: Cost) -> Self {
155        self.monthly_production_fee = Some(monthly_production_fee);
156        self
157    }
158
159    pub(crate) const fn transfer_fee(mut self, transfer_fee: TransferFee) -> Self {
160        self.transfer_fee = Some(transfer_fee);
161        self
162    }
163
164    pub(crate) const fn feed_in_revenue(mut self, feed_in_revenue: FeedInRevenue) -> Self {
165        self.feed_in_revenue = Some(feed_in_revenue);
166        self
167    }
168
169    pub(crate) const fn power_tariff(mut self, power_tariff: PowerTariff) -> Self {
170        self.power_tariff = Some(power_tariff);
171        self
172    }
173}
174
175#[derive(Debug, Clone, Serialize)]
176#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
177pub struct PriceListSimplified {
178    variant: Option<&'static str>,
179    fuse_size: u16,
180    /// If the energy consumption of the household affects the costs and/or fees for this fuse size
181    yearly_consumption_based: bool,
182    from_date: NaiveDate,
183    /// Fixed monthly fee
184    monthly_fee: Option<Money>,
185    /// Fixed monthly fee for allowing energy production
186    monthly_production_fee: Option<Money>,
187    transfer_fee: TransferFeeSimplified,
188    feed_in_revenue: FeedInRevenueSimplified,
189    power_tariff: PowerTariffSimplified,
190}
191
192impl PriceListSimplified {
193    fn new(pl: &PriceList, fuse_size: u16, yearly_consumption: u32, language: Language) -> Self {
194        Self {
195            variant: pl.variant,
196            fuse_size,
197            yearly_consumption_based: pl.monthly_fee.is_yearly_consumption_based(fuse_size)
198                || pl
199                    .monthly_production_fee
200                    .is_yearly_consumption_based(fuse_size)
201                || pl.transfer_fee.is_yearly_consumption_based(fuse_size),
202            from_date: pl.from_date,
203            monthly_fee: pl.monthly_fee.cost_for(fuse_size, yearly_consumption),
204            monthly_production_fee: pl
205                .monthly_production_fee
206                .cost_for(fuse_size, yearly_consumption),
207            transfer_fee: pl
208                .transfer_fee
209                .simplified(fuse_size, yearly_consumption, language),
210            feed_in_revenue: pl
211                .feed_in_revenue
212                .simplified(fuse_size, yearly_consumption, language),
213            power_tariff: pl
214                .power_tariff
215                .simplified(fuse_size, yearly_consumption, language),
216        }
217    }
218}