1use chrono::Utc;
2use indexmap::IndexMap;
3use serde::Serialize;
4
5use crate::{
6 Country, Links, MainFuseSizes, PriceList, currency::Currency, 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 country: Country,
17 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 .last()
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 all() -> Vec<&'static Self> {
85 sweden::GRID_OPERATORS.iter().copied().collect()
86 }
87
88 pub fn all_for_country(country: Country) -> &'static [&'static Self] {
89 match country {
90 Country::SE => sweden::GRID_OPERATORS,
91 }
92 }
93
94 pub(crate) const fn builder() -> GridOperatorBuilder {
95 GridOperatorBuilder::new()
96 }
97
98 pub fn simplified(&self, fuse_size: u16, yearly_consumption: u32) -> GridOperatorSimplified {
99 GridOperatorSimplified::new(self, fuse_size, yearly_consumption)
100 }
101}
102
103#[derive(Debug, Clone, Serialize)]
105#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
106pub struct GridOperatorSimplified {
107 name: &'static str,
108 vat_number: &'static str,
109 country: Country,
111 price_lists: Vec<PriceListSimplified>,
112}
113
114impl GridOperatorSimplified {
115 pub fn name(&self) -> &'static str {
116 self.name
117 }
118
119 pub fn vat_number(&self) -> &'static str {
120 self.vat_number
121 }
122
123 pub fn country(&self) -> Country {
124 self.country
125 }
126
127 pub fn price_lists(&self) -> &[PriceListSimplified] {
128 &self.price_lists
129 }
130}
131
132impl GridOperatorSimplified {
133 fn new(op: &GridOperator, fuse_size: u16, yearly_consumption: u32) -> Self {
134 Self {
135 name: op.name,
136 vat_number: op.vat_number,
137 country: op.country(),
138 price_lists: op
139 .active_price_lists()
140 .into_iter()
141 .map(|pl| pl.simplified(fuse_size, yearly_consumption))
142 .collect(),
143 }
144 }
145}
146
147#[derive(Debug, Clone)]
148pub(crate) struct GridOperatorBuilder {
149 name: Option<&'static str>,
150 vat_number: Option<&'static str>,
151 country: Option<Country>,
153 main_fuses: Option<MainFuseSizes>,
155 price_lists: Option<&'static [PriceList]>,
156 links: Option<Links>,
157}
158
159impl GridOperatorBuilder {
160 pub(crate) const fn new() -> Self {
161 Self {
162 name: None,
163 vat_number: None,
164 country: None,
165 main_fuses: None,
166 price_lists: None,
167 links: None,
168 }
169 }
170
171 pub(crate) const fn name(mut self, name: &'static str) -> Self {
172 self.name = Some(name);
173 self
174 }
175
176 pub(crate) const fn vat_number(mut self, vat_number: &'static str) -> Self {
177 self.vat_number = Some(vat_number);
178 self
179 }
180
181 pub(crate) const fn country(mut self, country: Country) -> Self {
182 self.country = Some(country);
183 self
184 }
185
186 pub(crate) const fn main_fuses(mut self, main_fuses: MainFuseSizes) -> Self {
187 self.main_fuses = Some(main_fuses);
188 self
189 }
190
191 pub(crate) const fn links(mut self, links: Links) -> Self {
192 self.links = Some(links);
193 self
194 }
195
196 pub(crate) const fn price_lists(mut self, price_lists: &'static [PriceList]) -> Self {
197 self.price_lists = Some(price_lists);
198 self
199 }
200
201 pub(crate) const fn build(self) -> GridOperator {
202 GridOperator {
203 name: self.name.expect("`name` required"),
204 vat_number: self.vat_number.expect("`vat_number` required"),
205 country: self.country.expect("`country` required"),
206 main_fuses: self.main_fuses.expect("`main_fuses` required"),
207 price_lists: self.price_lists.expect("`price_lists` expected"),
208 links: self.links.expect("`links` required"),
209 }
210 }
211}