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 {
27        #[serde(flatten)]
28        periods: CostPeriods,
29    },
30}
31
32impl FeedInRevenue {
33    pub const fn is_unverified(&self) -> bool {
34        matches!(self, Self::Unverified)
35    }
36
37    pub(super) const fn new_periods(periods: CostPeriods) -> Self {
38        Self::Periods { periods }
39    }
40
41    pub(super) const fn fixed_subunit(subunit: f64) -> Self {
42        Self::Simple(Cost::fixed_subunit(subunit))
43    }
44
45    pub fn simplified(&self, fuse_size: u16, yearly_consumption: u32) -> FeedInRevenueSimplified {
46        FeedInRevenueSimplified::new(self, fuse_size, yearly_consumption)
47    }
48}
49
50/// Feed-in revenue, per kWh (usually from solar production)
51/// Like FeedInRevenue, but with costs being simple Money objects
52#[derive(Debug, Clone, Serialize)]
53#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
54#[serde(tag = "type", content = "value")]
55pub enum FeedInRevenueSimplified {
56    Simple(Option<Money>),
57    /// Not yet checked
58    Unverified,
59    /// Could not be located on their website or elsewhere
60    Unlisted,
61    /// Varies by the current spot price
62    SpotPriceVariable {
63        base_cost: Money,
64        spot_price_multiplier: f64,
65        /// If this is approximated from actual data, or if it's based on documented pricing
66        approximated: bool,
67    },
68    Periods {
69        #[serde(flatten)]
70        periods: CostPeriodsSimple,
71    },
72}
73
74impl FeedInRevenueSimplified {
75    fn new(fee: &FeedInRevenue, fuse_size: u16, yearly_consumption: u32) -> Self {
76        match *fee {
77            FeedInRevenue::Unlisted => Self::Unlisted,
78            FeedInRevenue::Unverified => Self::Unverified,
79            FeedInRevenue::Simple(cost) => {
80                Self::Simple(cost.cost_for(fuse_size, yearly_consumption))
81            }
82            FeedInRevenue::SpotPriceVariable {
83                base_cost,
84                spot_price_multiplier,
85                approximated,
86            } => Self::SpotPriceVariable {
87                base_cost,
88                spot_price_multiplier,
89                approximated,
90            },
91            FeedInRevenue::Periods { periods } => Self::Periods {
92                periods: CostPeriodsSimple::new(periods, fuse_size, yearly_consumption),
93            },
94        }
95    }
96}