grid_tariffs/
transfer_fee.rs

1use serde::Serialize;
2
3use crate::{
4    Cost, Money,
5    costs::{CostPeriods, CostPeriodsSimple},
6};
7
8#[derive(Debug, Clone, Copy, Serialize)]
9#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
10#[serde(tag = "type", content = "value")]
11pub enum TransferFee {
12    /// Price was not listed on their website
13    Unlisted,
14    /// Transfer fee has not been verified by us
15    Unverified,
16    /// Fee does not change except possibly by fuse size
17    Simple(Cost),
18    /// Transfer fee that varies by the current spot price
19    /// We have currently only observed that Växjö Energi uses this variant
20    SpotPriceVariable {
21        base_cost: Money,
22        spot_price_multiplier: f64,
23        approximated: bool,
24    },
25    Periods(CostPeriods),
26}
27
28impl TransferFee {
29    pub const fn is_unverified(&self) -> bool {
30        matches!(self, Self::Unverified)
31    }
32
33    pub const fn simple_cost(&self) -> Option<Cost> {
34        match self {
35            Self::Simple(cost) => Some(*cost),
36            _ => None,
37        }
38    }
39
40    pub fn simplified(&self, fuse_size: u16, yearly_consumption: u32) -> TransferFeeSimplified {
41        TransferFeeSimplified::new(self, fuse_size, yearly_consumption)
42    }
43
44    pub(super) const fn new_periods(periods: CostPeriods) -> Self {
45        Self::Periods(periods)
46    }
47
48    pub(super) const fn fixed(int: i64, fract: u8) -> Self {
49        Self::Simple(Cost::fixed(int, fract))
50    }
51
52    pub(super) const fn fixed_subunit(subunit: f64) -> Self {
53        Self::Simple(Cost::fixed_subunit(subunit))
54    }
55
56    pub(super) fn is_yearly_consumption_based(&self, fuse_size: u16) -> bool {
57        match self {
58            TransferFee::Unlisted
59            | TransferFee::Unverified
60            | TransferFee::SpotPriceVariable { .. } => false,
61            TransferFee::Simple(cost) => cost.is_yearly_consumption_based(fuse_size),
62            TransferFee::Periods(periods) => periods.is_yearly_consumption_based(fuse_size),
63        }
64    }
65}
66
67/// Like TransferFee, but with costs being simple Money objects
68#[derive(Debug, Clone, Serialize)]
69#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
70#[serde(tag = "type", content = "value")]
71pub enum TransferFeeSimplified {
72    /// Price was not listed on their website
73    Unlisted,
74    /// Transfer fee has not been verified by us
75    Unverified,
76    /// Fee does not change except possibly by fuse size
77    Simple(Option<Money>),
78    /// Transfer fee that varies by the current spot price
79    /// We have currently only observed that Växjö Energi uses this variant
80    SpotPriceVariable {
81        base_cost: Money,
82        spot_price_multiplier: f64,
83        approximated: bool,
84    },
85    Periods(CostPeriodsSimple),
86}
87
88impl TransferFeeSimplified {
89    fn new(fee: &TransferFee, fuse_size: u16, yearly_consumption: u32) -> Self {
90        match *fee {
91            TransferFee::Unlisted => TransferFeeSimplified::Unlisted,
92            TransferFee::Unverified => TransferFeeSimplified::Unverified,
93            TransferFee::Simple(cost) => {
94                TransferFeeSimplified::Simple(cost.cost_for(fuse_size, yearly_consumption))
95            }
96            TransferFee::SpotPriceVariable {
97                base_cost,
98                spot_price_multiplier,
99                approximated,
100            } => TransferFeeSimplified::SpotPriceVariable {
101                base_cost,
102                spot_price_multiplier,
103                approximated,
104            },
105            TransferFee::Periods(periods) => TransferFeeSimplified::Periods(
106                CostPeriodsSimple::new(periods, fuse_size, yearly_consumption),
107            ),
108        }
109    }
110}