grid_tariffs/
lib.rs

1#![allow(unused)]
2//! Grid operator information
3//!
4//! This information is written for consumers specifically
5//! Costs for apartments are excluded as we do not aim to support those
6//! All costs are specified with VAT included
7//!
8//! TODO: Change it so that a grid operator can have multiple price lists (e.g. Tekniska Verken becomes one)
9//! TODO: Verify that we use the correct pricing and calculation method for each grid operator
10//! TODO: Generate GridOperator entries from Tariff API
11//!
12use std::collections::HashMap;
13
14use chrono::{NaiveDate, Utc};
15use indexmap::IndexMap;
16use serde::Serialize;
17
18use crate::{
19    builder::GridOperatorBuilder, currency::Currency, defs::MainFuseSizes,
20    price_list::PriceListSimplified, registry::sweden,
21};
22pub use crate::{
23    costs::Cost,
24    country::{Country, CountryInfo},
25    fees::{TransferFee, TransferFeeSimplified},
26    links::*,
27    money::Money,
28    power_tariffs::PowerTariff,
29    price_list::PriceList,
30    revenues::{FeedInRevenue, FeedInRevenueSimplified},
31    tax_reductions::*,
32    taxes::*,
33};
34
35mod builder;
36mod costs;
37mod country;
38mod currency;
39mod defs;
40mod fees;
41mod helpers;
42mod links;
43mod money;
44mod power_tariffs;
45mod price_list;
46pub mod registry;
47mod revenues;
48mod tax_reductions;
49mod taxes;
50
51#[derive(Debug, Clone, Serialize)]
52#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
53pub struct GridOperator {
54    name: &'static str,
55    vat_number: &'static str,
56    /// Costs are specified in this currency
57    country: Country,
58    /// The main fuse size range that this info covers
59    main_fuses: MainFuseSizes,
60    price_lists: &'static [PriceList],
61    links: Links,
62}
63
64impl GridOperator {
65    pub const fn name(&self) -> &str {
66        &self.name
67    }
68
69    pub const fn vat_number(&self) -> &str {
70        &self.vat_number
71    }
72
73    pub const fn country(&self) -> Country {
74        self.country
75    }
76
77    pub const fn links(&self) -> &Links {
78        &self.links
79    }
80
81    pub fn active_price_lists(&self) -> Vec<&'static PriceList> {
82        let now = Utc::now().date_naive();
83        let mut map: IndexMap<Option<&str>, &PriceList> = IndexMap::new();
84        for pl in self.price_lists {
85            if now >= pl.from_date() {
86                if let Some(current_max_date) = map.get(&pl.variant()).map(|pl| pl.from_date()) {
87                    if pl.from_date() > current_max_date {
88                        map.insert(pl.variant(), pl);
89                    }
90                } else {
91                    map.insert(pl.variant(), pl);
92                }
93            }
94        }
95        map.into_values().collect()
96    }
97
98    pub fn active_price_list(&self, variant: Option<&str>) -> Option<&'static PriceList> {
99        self.active_price_lists()
100            .iter()
101            .filter(|pl| pl.variant() == variant)
102            .last()
103            .copied()
104    }
105
106    pub fn price_lists(&self) -> &'static [PriceList] {
107        self.price_lists
108    }
109
110    pub const fn currency(&self) -> Currency {
111        match self.country {
112            Country::SE => Currency::SEK,
113        }
114    }
115
116    pub fn get(country: Country, name: &str) -> Option<&'static Self> {
117        match country {
118            Country::SE => sweden::GRID_OPERATORS
119                .iter()
120                .find(|o| o.name == name)
121                .copied(),
122        }
123    }
124
125    pub fn all() -> Vec<&'static Self> {
126        sweden::GRID_OPERATORS.iter().copied().collect()
127    }
128
129    pub fn all_for_country(country: Country) -> &'static [&'static Self] {
130        match country {
131            Country::SE => sweden::GRID_OPERATORS,
132        }
133    }
134
135    pub(crate) const fn builder() -> GridOperatorBuilder {
136        GridOperatorBuilder::new()
137    }
138
139    pub fn simplified(&self, fuse_size: u16, yearly_consumption: u32) -> GridOperatorSimplified {
140        GridOperatorSimplified::new(self, fuse_size, yearly_consumption)
141    }
142}
143
144/// Grid operator with only current prices
145#[derive(Debug, Clone, Serialize)]
146#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
147pub struct GridOperatorSimplified {
148    name: &'static str,
149    vat_number: &'static str,
150    /// Costs are specified in this currency
151    country: Country,
152    price_lists: Vec<PriceListSimplified>,
153}
154
155impl GridOperatorSimplified {
156    pub fn name(&self) -> &'static str {
157        self.name
158    }
159
160    pub fn vat_number(&self) -> &'static str {
161        self.vat_number
162    }
163
164    pub fn country(&self) -> Country {
165        self.country
166    }
167
168    pub fn price_lists(&self) -> &[PriceListSimplified] {
169        &self.price_lists
170    }
171}
172
173impl GridOperatorSimplified {
174    fn new(op: &GridOperator, fuse_size: u16, yearly_consumption: u32) -> Self {
175        Self {
176            name: op.name,
177            vat_number: op.vat_number,
178            country: op.country(),
179            price_lists: op
180                .active_price_lists()
181                .into_iter()
182                .map(|pl| pl.simplified(fuse_size, yearly_consumption))
183                .collect(),
184        }
185    }
186}