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(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) => TransferFeeSimplified::Simple(
107 cost.cost_for(fuse_size, yearly_consumption)
108 .unwrap_or(Money::ZERO),
109 ),
110 TransferFee::SpotPriceVariable {
111 base_cost,
112 spot_price_multiplier,
113 approximated,
114 } => TransferFeeSimplified::SpotPriceVariable {
115 base_cost,
116 spot_price_multiplier,
117 approximated,
118 info: Default::default(),
119 },
120 TransferFee::Periods(periods) => TransferFeeSimplified::Periods(
121 CostPeriodsSimple::new(periods, fuse_size, yearly_consumption, language),
122 ),
123 }
124 .add_info(language)
125 }
126
127 fn add_info(mut self, language: Language) -> Self {
128 match self {
129 TransferFeeSimplified::Unlisted => self,
130 TransferFeeSimplified::Unverified => self,
131 TransferFeeSimplified::Simple(_) => self,
132 TransferFeeSimplified::SpotPriceVariable {
133 base_cost,
134 spot_price_multiplier,
135 approximated,
136 info,
137 } => {
138 let percentage = spot_price_multiplier * 100.;
139 let mut info = match language {
140 Language::En => format!(
141 "The grid operator bases its transfer fee on a fixed part of {} and {}% of the current spot price.",
142 base_cost.display(Currency::SEK),
143 percentage
144 ),
145 Language::Sv => format!(
146 "Nätbolaget baserar sin överföringsavgift på en fast del om {} samt {}% av spotpriset.",
147 base_cost.display(Currency::SEK),
148 percentage
149 ),
150 };
151 if approximated {
152 info.push_str(&match language {
153 Language::En => format!(
154 " The percentage is estimated as the grid operator doesn't list it on their website."
155 ),
156 Language::Sv => format!(
157 " Procentsatsen är uppskattad eftersom nätbolaget inte skriver ut exakt vad den är på sin webbplats."
158 ),
159 })
160 }
161 TransferFeeSimplified::SpotPriceVariable {
162 base_cost,
163 spot_price_multiplier,
164 approximated,
165 info,
166 }
167 }
168 TransferFeeSimplified::Periods(_) => self,
169 }
170 }
171}