Skip to main content

Quantities

Struct Quantities 

Source
pub struct Quantities {
Show 18 fields pub electricity: Option<MeterInput>, pub sect14a_modul3: Option<Sect14aModul3Verbrauch>, pub gas: Option<GasMeterInput>, pub heat: Option<WaermeMeterInput>, pub wasser: Option<WasserMeterInput>, pub solar: Option<SolarMeterInput>, pub ggv_solar: Option<GgvSolarInput>, pub eeg: Option<EegMeterInput>, pub einspeisung: Option<EegMeterInput>, pub hems: Option<HemsMeterInput>, pub emobility: Option<EmobilityMeterInput>, pub service: Option<ServiceMeterInput>, pub dynamic_intervals: Vec<DynamicInterval>, pub dynamic_epex_prices: HashMap<OffsetDateTime, Decimal>, pub eeg_gutschrift_eur: Option<Decimal>, pub prosumer: Option<ProsumerMeterInput>, pub sect41a_annual_comparison: Option<Sect41aAnnualComparison>, pub energy_share: Option<EnergyShareMeterInput>,
}
Expand description

All metered quantities for one billing period.

Replaces the scattered positional parameters of the old calculate_* functions. Set only the fields relevant for the current billing run — defaults are None/ empty for unused products.

§Multi-product billing

To bill a customer with electricity + solar + HEMS on one invoice:

let quantities = Quantities {
    electricity: Some(MeterInput { arbeitsmenge_kwh: dec!(500), ..Default::default() }),
    solar: Some(SolarMeterInput { eigenverbrauch_kwh: dec!(120) }),
    hems: Some(HemsMeterInput { months: Some(dec!(1)), ..Default::default() }),
    ..Default::default()
};

Fields§

§electricity: Option<MeterInput>

Electricity consumption (STROM, WAERMEPUMPE, WALLBOX).

§sect14a_modul3: Option<Sect14aModul3Verbrauch>

§14a Modul 3 — the controllable device’s energy per Tarifstufe.

The Netzbetreiber’s time windows, not the supplier’s HT/NT: the two gratings are set by different parties and rarely coincide, which is why this is not derived from MeterInput’s Zweitarif split.

§gas: Option<GasMeterInput>

Natural gas consumption (GAS).

§heat: Option<WaermeMeterInput>

District heat / Fernwärme (WAERME).

§wasser: Option<WasserMeterInput>

Drinking water / wastewater (WASSER).

§solar: Option<SolarMeterInput>

Solar self-consumption / Mieterstrom / GGV (SOLAR) — simple single-rate path.

§ggv_solar: Option<GgvSolarInput>

§42b EnWG (Solarpaket I) — GGV community solar hybrid billing.

Use instead of (or in addition to) solar when the plant’s generation must be proportionally allocated among tenants. The SolarProvider will then generate two positions per tenant:

  • PV portion: min(consumption, allocated_pv) at the community solar rate
  • Grid portion: max(0, consumption − allocated_pv) at the regular electricity rate

Computed via GgvNutzungsplan::allocate(plant_generation_kwh) in billingd.

§eeg: Option<EegMeterInput>

EEG feed-in meter data (simplified path — rates from TariffInput).

§einspeisung: Option<EegMeterInput>

Non-EEG Direktvermarktung feed-in (EINSPEISUNG).

§hems: Option<HemsMeterInput>

HEMS subscription and event data.

§emobility: Option<EmobilityMeterInput>

E-mobility CPO/EMSP data.

§service: Option<ServiceMeterInput>

Energiedienstleistung service data.

§dynamic_intervals: Vec<DynamicInterval>

§41a dynamic tariff intervals (15-min Lastgang from edmd).

§dynamic_epex_prices: HashMap<OffsetDateTime, Decimal>

EPEX Spot price map for §41a billing: quarter-hour MTU start (UTC) → ct/kWh.

Keyed on the 15-minute market time unit start instant (crate::provider::mtu_start) — DST-safe and aligned with the EPEX SPOT 15-min day-ahead products (live since 2025-10-01).

Set by the service layer (billingd) after fetching from productd. DynamicElectricityProvider reads this map as a fallback when its internal SpotPriceSource has no data for an interval. This is the standard production path: build_engine() creates the provider with an empty source, and prices flow in here at bill() time.

§eeg_gutschrift_eur: Option<Decimal>

EEG Gutschrift credit passed through to electricity billing (e.g. from einsd).

§prosumer: Option<ProsumerMeterInput>

Prosumer meter data (PV self-consumption + grid draw).

When set, ElectricityProvider uses the prosumer billing path:

  • Grid consumption is billed at full tariff (commodity + NNE + Stromsteuer)
  • Self-consumption is Stromsteuer-exempt (§ 9 Abs. 1 Nr. 3 StromStG)
  • NNE does NOT apply to self-consumed energy
§sect41a_annual_comparison: Option<Sect41aAnnualComparison>

§41a Abs. 6 EnWG — annual savings comparison for dynamic tariff customers.

When set, DynamicElectricityProvider renders a mandatory informational position on the annual invoice comparing actual dynamic costs against a reference fixed tariff (§41a Abs. 6 EnWG).

§energy_share: Option<EnergyShareMeterInput>

§42c EnWG Energy Sharing — allocated community energy for this customer.

When set, EnergyShareProvider generates a credit position for the customer’s share of locally produced community electricity.

§Data source

Populated by billingd after querying the sharing community’s allocation data from edmd (virtual meter with GgvConstantAllocation or GgvProportionalAllocation rule — same infrastructure as §42b EnWG GGV).

Implementations§

Source§

impl Quantities

Source

pub fn empty_energy_sources(&self) -> Vec<&'static str>

The metered sources that were supplied and carry no quantity at all.

A supply invoice for a period longer than a day whose every energy source reads zero charges the standing charges and nothing for the commodity, and reads exactly like an ordinary invoice — the quantity twin of the KEIN_ARBEITSPREIS family, which refuses a product that prices nothing.

Only sources with an energy or volume dimension are considered. HEMS and Energiedienstleistung are billed per month and per event, so “zero kWh” says nothing about them.

Names the sources rather than answering yes/no, so the finding can say which reading is missing. Empty when at least one source carries a quantity, or when none of these sources was supplied at all.

Trait Implementations§

Source§

impl Clone for Quantities

Source§

fn clone(&self) -> Quantities

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Quantities

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Quantities

Source§

fn default() -> Quantities

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more