#![allow(clippy::missing_panics_doc, reason = "tests are allowed to panic")]
#![allow(clippy::panic, reason = "tests are allowed to panic")]
use rust_decimal_macros::dec;
use crate::{
cdr, json, price,
price::test::UnwrapReport as _,
tariff,
test::{self},
Version,
};
fn cdr_with_current(
energy_kwh: f64,
min_current_amp: f64,
max_current_amp: f64,
total_cost_excl: f64,
total_cost_incl: f64,
total_energy_cost_excl: f64,
total_energy_cost_incl: f64,
) -> String {
serde_json::json!({
"country_code": "NL",
"party_id": "TDR",
"start_date_time": "2022-01-13T10:00:00Z",
"end_date_time": "2022-01-13T11:00:00Z",
"currency": "EUR",
"tariffs": [],
"cdr_location": { "country": "NLD" },
"charging_periods": [{
"start_date_time": "2022-01-13T10:00:00Z",
"dimensions": [
{ "type": "ENERGY", "volume": energy_kwh },
{ "type": "MIN_CURRENT", "volume": min_current_amp },
{ "type": "MAX_CURRENT", "volume": max_current_amp }
]
}],
"total_cost": { "excl_vat": total_cost_excl, "incl_vat": total_cost_incl },
"total_energy_cost": { "excl_vat": total_energy_cost_excl, "incl_vat": total_energy_cost_incl },
"total_time": 1.0,
"total_energy": energy_kwh,
"last_updated": "2022-01-13T00:00:00Z"
})
.to_string()
}
fn cdr_with_power(
energy_kwh: f64,
min_power_kw: f64,
max_power_kw: f64,
total_cost_excl: f64,
total_cost_incl: f64,
total_energy_cost_excl: f64,
total_energy_cost_incl: f64,
) -> String {
serde_json::json!({
"country_code": "NL",
"party_id": "TDR",
"start_date_time": "2022-01-13T10:00:00Z",
"end_date_time": "2022-01-13T11:00:00Z",
"currency": "EUR",
"tariffs": [],
"cdr_location": { "country": "NLD" },
"charging_periods": [{
"start_date_time": "2022-01-13T10:00:00Z",
"dimensions": [
{ "type": "ENERGY", "volume": energy_kwh },
{ "type": "MIN_POWER", "volume": min_power_kw },
{ "type": "MAX_POWER", "volume": max_power_kw }
]
}],
"total_cost": { "excl_vat": total_cost_excl, "incl_vat": total_cost_incl },
"total_energy_cost": { "excl_vat": total_energy_cost_excl, "incl_vat": total_energy_cost_incl },
"total_time": 1.0,
"total_energy": energy_kwh,
"last_updated": "2022-01-13T00:00:00Z"
})
.to_string()
}
fn tariff_min_current(threshold_amp: f64) -> String {
serde_json::json!({
"id": "T_MIN_CURRENT",
"country_code": "NL",
"party_id": "TDR",
"currency": "EUR",
"elements": [
{
"restrictions": { "min_current": threshold_amp },
"price_components": [{ "type": "ENERGY", "price": 0.80, "vat": 10.0, "step_size": 1 }]
},
{
"price_components": [{ "type": "ENERGY", "price": 0.20, "vat": 10.0, "step_size": 1 }]
}
],
"last_updated": "2022-01-01T00:00:00Z"
})
.to_string()
}
fn tariff_max_current(threshold_amp: f64) -> String {
serde_json::json!({
"id": "T_MAX_CURRENT",
"country_code": "NL",
"party_id": "TDR",
"currency": "EUR",
"elements": [
{
"restrictions": { "max_current": threshold_amp },
"price_components": [{ "type": "ENERGY", "price": 0.20, "vat": 10.0, "step_size": 1 }]
},
{
"price_components": [{ "type": "ENERGY", "price": 0.80, "vat": 10.0, "step_size": 1 }]
}
],
"last_updated": "2022-01-01T00:00:00Z"
})
.to_string()
}
fn tariff_min_power(threshold_kw: f64) -> String {
serde_json::json!({
"id": "T_MIN_POWER",
"country_code": "NL",
"party_id": "TDR",
"currency": "EUR",
"elements": [
{
"restrictions": { "min_power": threshold_kw },
"price_components": [{ "type": "ENERGY", "price": 0.80, "vat": 10.0, "step_size": 1 }]
},
{
"price_components": [{ "type": "ENERGY", "price": 0.20, "vat": 10.0, "step_size": 1 }]
}
],
"last_updated": "2022-01-01T00:00:00Z"
})
.to_string()
}
fn tariff_max_power(threshold_kw: f64) -> String {
serde_json::json!({
"id": "T_MAX_POWER",
"country_code": "NL",
"party_id": "TDR",
"currency": "EUR",
"elements": [
{
"restrictions": { "max_power": threshold_kw },
"price_components": [{ "type": "ENERGY", "price": 0.20, "vat": 10.0, "step_size": 1 }]
},
{
"price_components": [{ "type": "ENERGY", "price": 0.80, "vat": 10.0, "step_size": 1 }]
}
],
"last_updated": "2022-01-01T00:00:00Z"
})
.to_string()
}
fn price_cdr(cdr_json: &str, tariff_json: &str) -> price::Report {
let (cdr, _) = cdr::build(json::parse_object(cdr_json).unwrap(), Version::V221).into_parts();
let (tariff, _) =
tariff::build(json::parse_object(tariff_json).unwrap(), Version::V221).into_parts();
let report = cdr::price(
&cdr,
price::TariffSource::Override(vec![tariff]),
chrono_tz::Tz::UTC,
)
.unwrap_report(cdr.as_json_str());
let (report, warnings) = report.into_parts();
assert!(warnings.is_empty(), "{:#?}", warnings.path_id_map());
report
}
#[test]
fn min_current_applies_when_peak_meets_threshold() {
test::setup();
let cdr_json = cdr_with_current(10.0, 10.0, 20.0, 8.00, 8.80, 8.00, 8.80);
let report = price_cdr(&cdr_json, &tariff_min_current(15.0));
let cost = report.total_cost.calculated.unwrap();
assert_eq!(cost.excl_vat, dec!(8.00).into());
assert_eq!(cost.incl_vat, Some(dec!(8.80).into()));
}
#[test]
fn min_current_does_not_apply_when_peak_below_threshold() {
test::setup();
let cdr_json = cdr_with_current(10.0, 10.0, 14.0, 2.00, 2.20, 2.00, 2.20);
let report = price_cdr(&cdr_json, &tariff_min_current(15.0));
let cost = report.total_cost.calculated.unwrap();
assert_eq!(cost.excl_vat, dec!(2.00).into());
assert_eq!(cost.incl_vat, Some(dec!(2.20).into()));
}
#[test]
fn max_current_applies_when_trough_below_threshold() {
test::setup();
let cdr_json = cdr_with_current(10.0, 10.0, 20.0, 2.00, 2.20, 2.00, 2.20);
let report = price_cdr(&cdr_json, &tariff_max_current(15.0));
let cost = report.total_cost.calculated.unwrap();
assert_eq!(cost.excl_vat, dec!(2.00).into());
assert_eq!(cost.incl_vat, Some(dec!(2.20).into()));
}
#[test]
fn max_current_does_not_apply_when_trough_meets_or_exceeds_threshold() {
test::setup();
let cdr_json = cdr_with_current(10.0, 16.0, 20.0, 8.00, 8.80, 8.00, 8.80);
let report = price_cdr(&cdr_json, &tariff_max_current(15.0));
let cost = report.total_cost.calculated.unwrap();
assert_eq!(cost.excl_vat, dec!(8.00).into());
assert_eq!(cost.incl_vat, Some(dec!(8.80).into()));
}
#[test]
fn min_power_applies_when_peak_meets_threshold() {
test::setup();
let cdr_json = cdr_with_power(10.0, 5.0, 15.0, 8.00, 8.80, 8.00, 8.80);
let report = price_cdr(&cdr_json, &tariff_min_power(10.0));
let cost = report.total_cost.calculated.unwrap();
assert_eq!(cost.excl_vat, dec!(8.00).into());
assert_eq!(cost.incl_vat, Some(dec!(8.80).into()));
}
#[test]
fn min_power_does_not_apply_when_peak_below_threshold() {
test::setup();
let cdr_json = cdr_with_power(10.0, 5.0, 9.0, 2.00, 2.20, 2.00, 2.20);
let report = price_cdr(&cdr_json, &tariff_min_power(10.0));
let cost = report.total_cost.calculated.unwrap();
assert_eq!(cost.excl_vat, dec!(2.00).into());
assert_eq!(cost.incl_vat, Some(dec!(2.20).into()));
}
#[test]
fn max_power_applies_when_trough_below_threshold() {
test::setup();
let cdr_json = cdr_with_power(10.0, 5.0, 15.0, 2.00, 2.20, 2.00, 2.20);
let report = price_cdr(&cdr_json, &tariff_max_power(10.0));
let cost = report.total_cost.calculated.unwrap();
assert_eq!(cost.excl_vat, dec!(2.00).into());
assert_eq!(cost.incl_vat, Some(dec!(2.20).into()));
}
#[test]
fn max_power_does_not_apply_when_trough_meets_or_exceeds_threshold() {
test::setup();
let cdr_json = cdr_with_power(10.0, 11.0, 15.0, 8.00, 8.80, 8.00, 8.80);
let report = price_cdr(&cdr_json, &tariff_max_power(10.0));
let cost = report.total_cost.calculated.unwrap();
assert_eq!(cost.excl_vat, dec!(8.00).into());
assert_eq!(cost.incl_vat, Some(dec!(8.80).into()));
}