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 pub(crate) const fn spot_price_variable_placeholder() -> TransferFee {
81 Self::spot_price_variable(2.0, 0.06, true)
82 }
83}
84
85#[derive(Debug, Clone, Serialize)]
87#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
88pub enum TransferFeeSimplified {
89 Unlisted,
91 Unverified,
93 Simple(Money),
95 SpotPriceVariable {
98 base_cost: Money,
99 spot_price_multiplier: f64,
100 approximated: bool,
101 info: String,
102 },
103 Periods(CostPeriodsSimple),
104}
105
106impl TransferFeeSimplified {
107 fn new(fee: &TransferFee, fuse_size: u16, yearly_consumption: u32, language: Language) -> Self {
108 match *fee {
109 TransferFee::Unlisted => TransferFeeSimplified::Unlisted,
110 TransferFee::Unverified => TransferFeeSimplified::Unverified,
111 TransferFee::Simple(cost) => TransferFeeSimplified::Simple(
112 cost.cost_for(fuse_size, yearly_consumption)
113 .unwrap_or(Money::ZERO),
114 ),
115 TransferFee::SpotPriceVariable {
116 base_cost,
117 spot_price_multiplier,
118 approximated,
119 } => TransferFeeSimplified::SpotPriceVariable {
120 base_cost,
121 spot_price_multiplier,
122 approximated,
123 info: Default::default(),
124 },
125 TransferFee::Periods(periods) => TransferFeeSimplified::Periods(
126 CostPeriodsSimple::new(periods, fuse_size, yearly_consumption, language),
127 ),
128 }
129 .add_info(language)
130 }
131
132 fn add_info(mut self, language: Language) -> Self {
133 match self {
134 TransferFeeSimplified::Unlisted => self,
135 TransferFeeSimplified::Unverified => self,
136 TransferFeeSimplified::Simple(_) => self,
137 TransferFeeSimplified::SpotPriceVariable {
138 base_cost,
139 spot_price_multiplier,
140 approximated,
141 info,
142 } => {
143 let percentage = spot_price_multiplier * 100.;
144 let mut info = match language {
145 Language::En => format!(
146 "The grid operator bases its transfer fee on a fixed part of {} and {}% of the current spot price.",
147 base_cost.display(Currency::SEK),
148 percentage
149 ),
150 Language::Sv => format!(
151 "Nätbolaget baserar sin överföringsavgift på en fast del om {} samt {}% av spotpriset.",
152 base_cost.display(Currency::SEK),
153 percentage
154 ),
155 };
156 if approximated {
157 info.push_str(match language {
158 Language::En => " The base fee and percentage are estimated, as the grid operator doesn't list them on their website.",
159 Language::Sv => " Basavgift och procentsats är uppskattade, eftersom nätbolaget inte skriver ut exakt vad de är på sin webbplats.",
160 })
161 }
162 TransferFeeSimplified::SpotPriceVariable {
163 base_cost,
164 spot_price_multiplier,
165 approximated,
166 info,
167 }
168 }
169 TransferFeeSimplified::Periods(_) => self,
170 }
171 }
172}