grid_tariffs/
revenues.rs

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