Skip to main content

Crate grid_billing

Crate grid_billing 

Source
Expand description

Role-neutral German grid settlement calculation engine.

Covers all DSO/TSO-side INVOIC documents:

  • NNE (Netznutzungsentgelt) — PIDs 31001, 31005, 31006, 31011
  • MMM (Mehr-/Mindermengensaldo) — PID 31002
  • MSB (Messstellenbetrieb) — PID 31009

§Calculation flow

Input → validation → Settlement Engine → GridSettlement → into_rechnung() (service layer)

GridSettlement is the canonical output. The service layer (netzbilanzd, invoicd) converts it to BO4E Rechnung. This keeps grid-billing publishable to crates.io without pulling in the internal rubo4e crate.

§Explainability

Every InvoicePosition carries a CalculationTrace with:

  • input values (quantity, unit price)
  • gross intermediate result before rounding
  • applicable LegalReferences (e.g. StromNEV §17, KAV §2)
  • the TariffSource justifying each rate

§No float money

All amounts use rust_decimal::Decimal and the billing::EuroAmount newtype.

§Example

use grid_billing::{NneInput, calculate_nne_invoice};
use rust_decimal::Decimal;
use time::macros::date;

fn d(s: &str) -> Decimal { Decimal::from_str_exact(s).unwrap() }

let result = calculate_nne_invoice(&NneInput {
    malo_id: "51238696780".into(),
    nb_mp_id: "9900357000004".into(),
    lf_mp_id: "9900012345678".into(),
    rechnungsnummer: "NNE-2025-001".into(),
    period_from: date!(2025-01-01),
    period_to:   date!(2025-01-31),
    invoice_date: date!(2025-02-15),
    due_date: date!(2025-03-15),
    arbeitsmenge_kwh: d("1500"),
    arbeitspreis_ct_per_kwh: d("3.5"),
    arbeitsmenge_ht_kwh: None,
    arbeitspreis_ht_ct_per_kwh: None,
    arbeitsmenge_nt_kwh: None,
    arbeitspreis_nt_ct_per_kwh: None,
    spitzenleistung_kw: None,
    leistungspreis_eur_per_kw: None,
    ka_satz_ct_per_kwh: Some(d("0.11")),
    tariff_sheet_id: Some("Preisblatt-NNE-2025-Q1".into()),
    sparte: grid_billing::Sparte::Strom,
    ka_klasse: Some(grid_billing::KaKlasse::TarifkundeLow),
}).expect("valid billing input");

// Every position explains itself:
for pos in &result.positions {
    println!("{}: {}", pos.text, pos.trace.explanation);
}

// Legal references used:
for r in result.all_legal_refs() {
    println!("  → {r}");
}

Re-exports§

pub use billing::calculate_mmm_invoice;
pub use billing::calculate_msb_invoice;
pub use billing::calculate_nne_invoice;
pub use billing::calculate_reversal;
pub use error::BillingError;
pub use types::CalculationTrace;
pub use types::GridInvoice;
pub use types::GridSettlement;
pub use types::InvoicePosition;
pub use types::KaKlasse;
pub use types::LegalReference;
pub use types::MmmInput;
pub use types::MsbInput;
pub use types::NneInput;
pub use types::QuantityUnit;
pub use types::SettlementStatus;
pub use types::SettlementType;
pub use types::SettlementWarning;
pub use types::Sparte;
pub use types::TariffSource;
pub use types::ValidationResult;
pub use types::WarningSeverity;
pub use types::validate_mmm_input;
pub use types::validate_msb_input;
pub use types::validate_nne_input;

Modules§

billing
NNE, MMM, and MSB settlement calculation logic.
error
Error types for grid-billing.
types
Input/output types for the settlement calculation engine.