1use serde::Serialize;
2
3use crate::{Cost, CostPeriods, CostPeriodsSimple, Language, Money, currency::Currency};
4
5#[derive(Debug, Clone, Copy, Serialize)]
6#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
7pub enum TransferFee {
8 Unlisted,
10 Unverified,
12 Simple(Cost),
14 SpotPriceVariable {
17 base_cost: Money,
18 spot_price_multiplier: f64,
19 approximated: bool,
20 },
21 Periods(CostPeriods),
22}
23
24impl TransferFee {
25 pub const fn is_unverified(&self) -> bool {
26 matches!(self, Self::Unverified)
27 }
28
29 pub const fn simple_cost(&self) -> Option<Cost> {
30 match self {
31 Self::Simple(cost) => Some(*cost),
32 _ => None,
33 }
34 }
35
36 pub const fn spot_price_variable(
37 base_cost_subunit: f64,
38 spot_price_multiplier: f64,
39 approximated: bool,
40 ) -> Self {
41 Self::SpotPriceVariable {
42 base_cost: Money::new_subunit(base_cost_subunit),
43 spot_price_multiplier,
44 approximated,
45 }
46 }
47
48 pub fn simplified(
49 &self,
50 fuse_size: u16,
51 yearly_consumption: u32,
52 language: Language,
53 ) -> TransferFeeSimplified {
54 TransferFeeSimplified::new(self, fuse_size, yearly_consumption, language)
55 }
56
57 pub(super) const fn new_periods(periods: CostPeriods) -> Self {
58 Self::Periods(periods)
59 }
60
61 pub(super) const fn fixed(int: i64, fract: u8) -> Self {
62 Self::Simple(Cost::fixed(int, fract))
63 }
64
65 pub(super) const fn fixed_subunit(subunit: f64) -> Self {
66 Self::Simple(Cost::fixed_subunit(subunit))
67 }
68
69 pub(super) fn is_yearly_consumption_based(&self, fuse_size: u16) -> bool {
70 match self {
71 TransferFee::Unlisted
72 | TransferFee::Unverified
73 | TransferFee::SpotPriceVariable { .. } => false,
74 TransferFee::Simple(cost) => cost.is_yearly_consumption_based(fuse_size),
75 TransferFee::Periods(periods) => periods.is_yearly_consumption_based(fuse_size),
76 }
77 }
78}
79
80#[derive(Debug, Clone, Serialize)]
82#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
83pub enum TransferFeeSimplified {
84 Unlisted,
86 Unverified,
88 Simple(Option<Money>),
90 SpotPriceVariable {
93 base_cost: Money,
94 spot_price_multiplier: f64,
95 approximated: bool,
96 info: String,
97 },
98 Periods(CostPeriodsSimple),
99}
100
101impl TransferFeeSimplified {
102 fn new(fee: &TransferFee, fuse_size: u16, yearly_consumption: u32, language: Language) -> Self {
103 match *fee {
104 TransferFee::Unlisted => TransferFeeSimplified::Unlisted,
105 TransferFee::Unverified => TransferFeeSimplified::Unverified,
106 TransferFee::Simple(cost) => {
107 TransferFeeSimplified::Simple(cost.cost_for(fuse_size, yearly_consumption))
108 }
109 TransferFee::SpotPriceVariable {
110 base_cost,
111 spot_price_multiplier,
112 approximated,
113 } => TransferFeeSimplified::SpotPriceVariable {
114 base_cost,
115 spot_price_multiplier,
116 approximated,
117 info: Default::default(),
118 },
119 TransferFee::Periods(periods) => TransferFeeSimplified::Periods(
120 CostPeriodsSimple::new(periods, fuse_size, yearly_consumption, language),
121 ),
122 }
123 .add_info(language)
124 }
125
126 fn add_info(mut self, language: Language) -> Self {
127 match self {
128 TransferFeeSimplified::Unlisted => self,
129 TransferFeeSimplified::Unverified => self,
130 TransferFeeSimplified::Simple(_) => self,
131 TransferFeeSimplified::SpotPriceVariable {
132 base_cost,
133 spot_price_multiplier,
134 approximated,
135 info,
136 } => {
137 let percentage = spot_price_multiplier * 100.;
138 let mut info = match language {
139 Language::En => format!(
140 "The grid operator bases its transfer fee on a fixed part of {} and {}% of the current spot price.",
141 base_cost.display(Currency::SEK),
142 percentage
143 ),
144 Language::Sv => format!(
145 "Nätbolaget baserar sin överföringsavgift på en fast del om {} samt {}% av spotpriset.",
146 base_cost.display(Currency::SEK),
147 percentage
148 ),
149 };
150 if approximated {
151 info.push_str(&match language {
152 Language::En => format!(
153 " The percentage is estimated as the grid operator doesn't list it on their website."
154 ),
155 Language::Sv => format!(
156 " Procentsatsen är uppskattad eftersom nätbolaget inte skriver ut exakt vad den är på sin webbplats."
157 ),
158 })
159 }
160 TransferFeeSimplified::SpotPriceVariable {
161 base_cost,
162 spot_price_multiplier,
163 approximated,
164 info,
165 }
166 }
167 TransferFeeSimplified::Periods(_) => self,
168 }
169 }
170}