grid_tariffs/
operator.rs

1use chrono::Utc;
2use indexmap::IndexMap;
3use serde::Serialize;
4
5use crate::{
6    Country, Currency, Language, Links, MainFuseSizes, PriceList, price_list::PriceListSimplified,
7    registry::sweden,
8};
9
10#[derive(Debug, Clone, Serialize)]
11#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
12pub struct GridOperator {
13    name: &'static str,
14    vat_number: &'static str,
15    /// Costs are specified in this currency
16    country: Country,
17    /// The main fuse size range that this info covers
18    main_fuses: MainFuseSizes,
19    price_lists: &'static [PriceList],
20    links: Links,
21}
22
23impl GridOperator {
24    pub const fn name(&self) -> &str {
25        self.name
26    }
27
28    pub const fn vat_number(&self) -> &str {
29        self.vat_number
30    }
31
32    pub const fn country(&self) -> Country {
33        self.country
34    }
35
36    pub const fn links(&self) -> &Links {
37        &self.links
38    }
39
40    pub fn active_price_lists(&self) -> Vec<&'static PriceList> {
41        let now = Utc::now().date_naive();
42        let mut map: IndexMap<Option<&str>, &PriceList> = IndexMap::new();
43        for pl in self.price_lists {
44            if now >= pl.from_date() {
45                if let Some(current_max_date) = map.get(&pl.variant()).map(|pl| pl.from_date()) {
46                    if pl.from_date() > current_max_date {
47                        map.insert(pl.variant(), pl);
48                    }
49                } else {
50                    map.insert(pl.variant(), pl);
51                }
52            }
53        }
54        map.into_values().collect()
55    }
56
57    pub fn active_price_list(&self, variant: Option<&str>) -> Option<&'static PriceList> {
58        self.active_price_lists()
59            .iter()
60            .filter(|pl| pl.variant() == variant)
61            .next_back()
62            .copied()
63    }
64
65    pub fn price_lists(&self) -> &'static [PriceList] {
66        self.price_lists
67    }
68
69    pub const fn currency(&self) -> Currency {
70        match self.country {
71            Country::SE => Currency::SEK,
72        }
73    }
74
75    pub fn get(country: Country, name: &str) -> Option<&'static Self> {
76        match country {
77            Country::SE => sweden::GRID_OPERATORS
78                .iter()
79                .find(|o| o.name == name)
80                .copied(),
81        }
82    }
83
84    pub fn get_by_vat_id(country: Country, vat_id: &str) -> Option<&'static Self> {
85        match country {
86            Country::SE => sweden::GRID_OPERATORS
87                .iter()
88                .find(|o| o.vat_number == vat_id)
89                .copied(),
90        }
91    }
92
93    pub fn all() -> Vec<&'static Self> {
94        sweden::GRID_OPERATORS.to_vec()
95    }
96
97    pub fn all_for_country(country: Country) -> &'static [&'static Self] {
98        match country {
99            Country::SE => sweden::GRID_OPERATORS,
100        }
101    }
102
103    pub(crate) const fn builder() -> GridOperatorBuilder {
104        GridOperatorBuilder::new()
105    }
106
107    pub fn simplified(
108        &self,
109        fuse_size: u16,
110        yearly_consumption: u32,
111        language: Language,
112    ) -> GridOperatorSimplified {
113        GridOperatorSimplified::new(self, fuse_size, yearly_consumption, language)
114    }
115}
116
117/// Grid operator with only current prices
118#[derive(Debug, Clone, Serialize)]
119#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
120pub struct GridOperatorSimplified {
121    name: &'static str,
122    vat_number: &'static str,
123    /// Costs are specified in this currency
124    country: Country,
125    price_lists: Vec<PriceListSimplified>,
126}
127
128impl GridOperatorSimplified {
129    pub fn name(&self) -> &'static str {
130        self.name
131    }
132
133    pub fn vat_number(&self) -> &'static str {
134        self.vat_number
135    }
136
137    pub fn country(&self) -> Country {
138        self.country
139    }
140
141    pub fn price_lists(&self) -> &[PriceListSimplified] {
142        &self.price_lists
143    }
144}
145
146impl GridOperatorSimplified {
147    fn new(op: &GridOperator, fuse_size: u16, yearly_consumption: u32, language: Language) -> Self {
148        Self {
149            name: op.name,
150            vat_number: op.vat_number,
151            country: op.country(),
152            price_lists: op
153                .active_price_lists()
154                .into_iter()
155                .map(|pl| pl.simplified(fuse_size, yearly_consumption, language))
156                .collect(),
157        }
158    }
159}
160
161#[derive(Debug, Clone)]
162pub(crate) struct GridOperatorBuilder {
163    name: Option<&'static str>,
164    vat_number: Option<&'static str>,
165    /// Costs are specified in this currency
166    country: Option<Country>,
167    /// The main fuse size range that this info covers
168    main_fuses: Option<MainFuseSizes>,
169    price_lists: Option<&'static [PriceList]>,
170    links: Option<Links>,
171}
172
173impl GridOperatorBuilder {
174    pub(crate) const fn new() -> Self {
175        Self {
176            name: None,
177            vat_number: None,
178            country: None,
179            main_fuses: None,
180            price_lists: None,
181            links: None,
182        }
183    }
184
185    pub(crate) const fn name(mut self, name: &'static str) -> Self {
186        self.name = Some(name);
187        self
188    }
189
190    pub(crate) const fn vat_number(mut self, vat_number: &'static str) -> Self {
191        self.vat_number = Some(vat_number);
192        self
193    }
194
195    pub(crate) const fn country(mut self, country: Country) -> Self {
196        self.country = Some(country);
197        self
198    }
199
200    pub(crate) const fn main_fuses(mut self, main_fuses: MainFuseSizes) -> Self {
201        self.main_fuses = Some(main_fuses);
202        self
203    }
204
205    pub(crate) const fn links(mut self, links: Links) -> Self {
206        self.links = Some(links);
207        self
208    }
209
210    pub(crate) const fn price_lists(mut self, price_lists: &'static [PriceList]) -> Self {
211        self.price_lists = Some(price_lists);
212        self
213    }
214
215    pub(crate) const fn build(self) -> GridOperator {
216        GridOperator {
217            name: self.name.expect("`name` required"),
218            vat_number: self.vat_number.expect("`vat_number` required"),
219            country: self.country.expect("`country` required"),
220            main_fuses: self.main_fuses.expect("`main_fuses` required"),
221            price_lists: self.price_lists.expect("`price_lists` expected"),
222            links: self.links.expect("`links` required"),
223        }
224    }
225}