fix(tibber): deduct verkoopvergoeding (sell_fee) from feed-in sell price
frontend / frontend (push) Failing after 5m49s
pytest / test (push) Successful in 20m30s
docker-image / build-and-push (push) Successful in 13m26s

Tibber's API `total` already includes the buy-side inkoopvergoeding
(verified from production data: total = spot×1.21 + energy_tax 0.11085 +
inkoopvergoeding 0.0248). Under net metering Tibber pays back
`total − verkoopvergoeding` per returned kWh (NL: EUR 0.28 -> 0.2552), so the
two EUR 0.0248 fees do NOT cancel — the feed-in price sits 0.0248 below buy.

Model the verkoopvergoeding as a first-class, always-subtracted contract
field `energy.sell_fee` (default 0.0248) instead of folding it into
`sell_adjust`. New sell formula:

    sell = total − energy_tax − sell_fee − sell_adjust

`sell_adjust` now carries only the net-metering energy-tax refund
(= −energy_tax). Applied in both the billing strategy and the /prices
endpoint; recorded in the pricing snapshot. Frontend renders the field
automatically (dynamic profile form). Docs (references, m6) corrected to
drop the wrong "fees cancel" premise.
This commit is contained in:
2026-07-20 13:50:13 +02:00
parent b65f700d56
commit d07a083e03
11 changed files with 196 additions and 29 deletions
+5 -3
View File
@@ -169,7 +169,7 @@ def get_prices(
Response ``points`` carries per-slot:
- ``buy = total`` (Tibber all-inclusive price)
- ``sell = total energy_tax sell_adjust`` (from active version values)
- ``sell = total energy_tax sell_fee sell_adjust`` (from active version values)
- ``level`` (Tibber price level, may be null)
``tariff`` is null.
@@ -222,7 +222,8 @@ def get_prices(
)
rows = list(reversed(db.execute(stmt).scalars().all()))
# Derive sell price per-point using version values (energy_tax + sell_adjust).
# Derive sell price per-point using version values
# (energy_tax + sell_fee + sell_adjust).
from decimal import Decimal
def _d(v: Any) -> Decimal:
@@ -230,12 +231,13 @@ def get_prices(
energy = version.values.get("energy", {}) if version.values else {}
energy_tax = _d(energy.get("energy_tax", 0))
sell_fee = _d(energy.get("sell_fee", 0))
sell_adjust = _d(energy.get("sell_adjust", 0))
points = []
for row in rows:
total = _d(row.total)
sell = float(total - energy_tax - sell_adjust)
sell = float(total - energy_tax - sell_fee - sell_adjust)
points.append(
PricePointSchema(
starts_at=_as_utc(row.starts_at),