grid_tariffs/
revenues.rs

1use serde::Serialize;
2
3use crate::{Cost, CostPeriods, CostPeriodsSimple, Language, Money};
4
5/// Feed-in revenue, per kWh (usually from solar production)
6/// A Swedish concept for "thanking" micro producers (<=43,5 kW) for reducing losses in the grid
7#[derive(Debug, Clone, Copy, Serialize)]
8#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
9pub enum FeedInRevenue {
10    Simple(Cost),
11    /// Not yet checked
12    Unverified,
13    /// Could not be located on their website or elsewhere
14    Unlisted,
15    /// Varies by the current spot price
16    SpotPriceVariable {
17        base_cost: Money,
18        spot_price_multiplier: f64,
19        /// If this is approximated from actual data, or if it's based on documented pricing
20        approximated: bool,
21    },
22    Periods(CostPeriods),
23}
24
25impl FeedInRevenue {
26    pub const fn is_unverified(&self) -> bool {
27        matches!(self, Self::Unverified)
28    }
29
30    pub(super) const fn new_periods(periods: CostPeriods) -> Self {
31        Self::Periods(periods)
32    }
33
34    pub(super) const fn fixed_subunit(subunit: f64) -> Self {
35        Self::Simple(Cost::fixed_subunit(subunit))
36    }
37
38    pub fn simplified(
39        &self,
40        fuse_size: u16,
41        yearly_consumption: u32,
42        language: Language,
43    ) -> FeedInRevenueSimplified {
44        FeedInRevenueSimplified::new(self, fuse_size, yearly_consumption, language)
45    }
46}
47
48/// Feed-in revenue, per kWh (usually from solar production)
49/// Like FeedInRevenue, but with costs being simple Money objects
50#[derive(Debug, Clone, Serialize)]
51#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
52pub enum FeedInRevenueSimplified {
53    Simple(Option<Money>),
54    /// Not yet checked
55    Unverified,
56    /// Could not be located on their website or elsewhere
57    Unlisted,
58    /// Varies by the current spot price
59    SpotPriceVariable {
60        base_cost: Money,
61        spot_price_multiplier: f64,
62        /// If this is approximated from actual data, or if it's based on documented pricing
63        approximated: bool,
64    },
65    Periods {
66        #[serde(flatten)]
67        periods: CostPeriodsSimple,
68    },
69}
70
71impl FeedInRevenueSimplified {
72    fn new(
73        fee: &FeedInRevenue,
74        fuse_size: u16,
75        yearly_consumption: u32,
76        language: Language,
77    ) -> Self {
78        match *fee {
79            FeedInRevenue::Unlisted => Self::Unlisted,
80            FeedInRevenue::Unverified => Self::Unverified,
81            FeedInRevenue::Simple(cost) => {
82                Self::Simple(cost.cost_for(fuse_size, yearly_consumption))
83            }
84            FeedInRevenue::SpotPriceVariable {
85                base_cost,
86                spot_price_multiplier,
87                approximated,
88            } => Self::SpotPriceVariable {
89                base_cost,
90                spot_price_multiplier,
91                approximated,
92            },
93            FeedInRevenue::Periods(periods) => Self::Periods {
94                periods: CostPeriodsSimple::new(periods, fuse_size, yearly_consumption, language),
95            },
96        }
97    }
98}