generate_cdr_from_tariff/
generate_cdr_from_tariff.rs1#![expect(clippy::unwrap_used, reason = "examples can panic")]
2#![expect(clippy::print_stdout, reason = "examples can log to stdout")]
3#![expect(clippy::print_stderr, reason = "examples can log to stderr")]
4
5use std::str::FromStr as _;
6
7use chrono::{DateTime, Utc};
8use ocpi_tariffs::{cdr, generate, guess, tariff, warning, Version};
9use rust_decimal::Decimal;
10
11fn main() {
12 const TARIFF_JSON: &str = include_str!(
13 "../test_data/v211/real_world/time_and_parking_time_separate_tariff/tariff.json"
14 );
15
16 let report = tariff::parse_and_report(TARIFF_JSON).unwrap();
17 let guess::Report {
18 unexpected_fields,
19 version,
20 } = report;
21
22 if !unexpected_fields.is_empty() {
23 eprintln!("Strange... there are fields in the tariff that are not defined in the spec.");
24
25 for path in &unexpected_fields {
26 eprintln!(" * {path}");
27 }
28
29 eprintln!();
30 }
31
32 let tariff = version.certain_or(Version::V221);
33
34 let config = generate::Config {
35 timezone: chrono_tz::Europe::Amsterdam,
36 start_date_time: DateTime::<Utc>::from_str("2025-06-12 18:22:33+00:00").unwrap(),
37 end_date_time: DateTime::<Utc>::from_str("2025-06-12 22:33:44+00:00").unwrap(),
38 max_current_supply_amp: Decimal::from(4),
39 max_energy_battery_kwh: Decimal::from(24),
40 max_power_supply_kw: Decimal::from(80),
41 };
42 let report = match cdr::generate_from_tariff(&tariff, config) {
43 Ok(r) => r,
44 Err(set) => {
45 let (error, warnings) = set.into_parts();
46 print_error(&error);
47 print_warnings(&warnings);
48 return;
49 }
50 };
51 let (report, warnings) = report.into_parts();
52
53 print_warnings(&warnings);
54
55 let generate::Report {
56 tariff_id,
57 tariff_currency_code,
58 partial_cdr,
59 } = report;
60
61 println!("CDR genereated for tariff with id: `{tariff_id}` and currency code: `{tariff_currency_code}`");
62 println!("{partial_cdr:#?}");
63}
64
65fn print_error(error: &warning::Error<generate::Warning>) {
66 eprintln!(
67 "ERR: Unable to generate CDR due to error at path `{}`: {}",
68 error.element().path,
69 error.warning()
70 );
71}
72
73fn print_warnings(warnings: &warning::Set<generate::Warning>) {
74 if warnings.is_empty() {
75 return;
76 }
77
78 eprintln!(
79 "WARN: {} warnings from the linting:\n {}",
80 warnings.len_warnings(),
81 warning::SetWriter::new(warnings)
82 );
83}