oprava import/export kwh
This commit is contained in:
@@ -3,6 +3,74 @@
|
||||
-- EMS Platform – funkce pro výpočet efektivní ceny per site
|
||||
-- Repeatable migration – nasazuje se při každé změně
|
||||
-- =============================================================
|
||||
-- Pomocné (audit/ekonomika): sjednocení import/export Wh — musí běžet před R__012/R__056.
|
||||
create or replace function ems.fn_audit_grid_import_wh_for_economics(
|
||||
p_import_wh numeric,
|
||||
p_export_wh numeric,
|
||||
p_grid_power_w int
|
||||
)
|
||||
returns numeric
|
||||
language sql
|
||||
stable
|
||||
as $$
|
||||
select case
|
||||
when coalesce(p_import_wh, 0) > 0 and coalesce(p_export_wh, 0) > 0 then
|
||||
coalesce(
|
||||
p_import_wh,
|
||||
greatest(coalesce(p_grid_power_w, 0), 0)::numeric / 4
|
||||
)
|
||||
when coalesce(p_export_wh, 0) = 0 then
|
||||
greatest(
|
||||
coalesce(
|
||||
p_import_wh,
|
||||
greatest(coalesce(p_grid_power_w, 0), 0)::numeric / 4
|
||||
),
|
||||
greatest(coalesce(p_grid_power_w, 0), 0)::numeric / 4
|
||||
)
|
||||
else
|
||||
coalesce(
|
||||
p_import_wh,
|
||||
greatest(coalesce(p_grid_power_w, 0), 0)::numeric / 4
|
||||
)
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function ems.fn_audit_grid_export_wh_for_economics(
|
||||
p_import_wh numeric,
|
||||
p_export_wh numeric,
|
||||
p_grid_power_w int
|
||||
)
|
||||
returns numeric
|
||||
language sql
|
||||
stable
|
||||
as $$
|
||||
select case
|
||||
when coalesce(p_import_wh, 0) > 0 and coalesce(p_export_wh, 0) > 0 then
|
||||
coalesce(
|
||||
p_export_wh,
|
||||
abs(least(coalesce(p_grid_power_w, 0), 0))::numeric / 4
|
||||
)
|
||||
when coalesce(p_import_wh, 0) = 0 then
|
||||
greatest(
|
||||
coalesce(
|
||||
p_export_wh,
|
||||
abs(least(coalesce(p_grid_power_w, 0), 0))::numeric / 4
|
||||
),
|
||||
abs(least(coalesce(p_grid_power_w, 0), 0))::numeric / 4
|
||||
)
|
||||
else
|
||||
coalesce(
|
||||
p_export_wh,
|
||||
abs(least(coalesce(p_grid_power_w, 0), 0))::numeric / 4
|
||||
)
|
||||
end;
|
||||
$$;
|
||||
|
||||
comment on function ems.fn_audit_grid_import_wh_for_economics(numeric, numeric, int) is
|
||||
'Import Wh pro audit/ekonomiku: u čistého importu max(uložený čítač, max(0,P_grid)×¼ h).';
|
||||
|
||||
comment on function ems.fn_audit_grid_export_wh_for_economics(numeric, numeric, int) is
|
||||
'Export Wh pro audit/ekonomiku: u čistého exportu max(uložený čítač, |min(0,P_grid)|×¼ h).';
|
||||
|
||||
CREATE OR REPLACE FUNCTION ems.fn_effective_buy_price(
|
||||
p_site_id INT,
|
||||
|
||||
@@ -14,13 +14,29 @@ as $fn$
|
||||
end,
|
||||
'grid_import_kwh',
|
||||
case
|
||||
when ai.actual_grid_import_wh is null then null
|
||||
else round(ai.actual_grid_import_wh::numeric / 1000, 4)
|
||||
when ai.actual_grid_import_wh is null
|
||||
and ai.actual_grid_export_wh is null
|
||||
and ai.actual_grid_power_w is null
|
||||
then null
|
||||
else round(
|
||||
ems.fn_audit_grid_import_wh_for_economics(
|
||||
ai.actual_grid_import_wh, ai.actual_grid_export_wh, ai.actual_grid_power_w
|
||||
)::numeric / 1000,
|
||||
4
|
||||
)
|
||||
end,
|
||||
'grid_export_kwh',
|
||||
case
|
||||
when ai.actual_grid_export_wh is null then null
|
||||
else round(ai.actual_grid_export_wh::numeric / 1000, 4)
|
||||
when ai.actual_grid_import_wh is null
|
||||
and ai.actual_grid_export_wh is null
|
||||
and ai.actual_grid_power_w is null
|
||||
then null
|
||||
else round(
|
||||
ems.fn_audit_grid_export_wh_for_economics(
|
||||
ai.actual_grid_import_wh, ai.actual_grid_export_wh, ai.actual_grid_power_w
|
||||
)::numeric / 1000,
|
||||
4
|
||||
)
|
||||
end,
|
||||
'batt_charge_kwh',
|
||||
case
|
||||
|
||||
@@ -45,6 +45,8 @@ DECLARE
|
||||
v_counter_export_last BIGINT;
|
||||
v_delta_import NUMERIC;
|
||||
v_delta_export NUMERIC;
|
||||
v_imp_before NUMERIC;
|
||||
v_exp_before NUMERIC;
|
||||
|
||||
-- 7 směrových toků (prioritní alokace per minuta; součet W/60 = Wh)
|
||||
r_flow RECORD;
|
||||
@@ -141,6 +143,13 @@ BEGIN
|
||||
v_grid_export_wh := v_delta_export;
|
||||
END IF;
|
||||
|
||||
v_imp_before := v_grid_import_wh;
|
||||
v_exp_before := v_grid_export_wh;
|
||||
v_grid_import_wh := ems.fn_audit_grid_import_wh_for_economics(
|
||||
v_imp_before, v_exp_before, v_avg_grid_power_w);
|
||||
v_grid_export_wh := ems.fn_audit_grid_export_wh_for_economics(
|
||||
v_imp_before, v_exp_before, v_avg_grid_power_w);
|
||||
|
||||
-- Agregovat EV nabíječky (součet průměrů po charger_id)
|
||||
SELECT COALESCE(SUM(avg_power), 0)::INT
|
||||
INTO v_sum_ev_power_w
|
||||
@@ -371,8 +380,9 @@ $$;
|
||||
COMMENT ON FUNCTION ems.fn_fill_audit_interval(INT, TIMESTAMPTZ) IS
|
||||
'Naplní nebo aktualizuje jeden řádek v audit_interval pro danou lokalitu a 15min interval.
|
||||
Agreguje průměry z telemetrie (střídač, EV, TČ), porovná se skutečným plánem a spočítá odchylky.
|
||||
Nově: per-minutový split pro 6 energetických veličin (import/export/batt/PV/load Wh);
|
||||
grid import/export primárně z delta Deye total counterů (reg 522-525), fallback per-minute.
|
||||
Per-minutový split pro 6 energetických veličin (import/export/batt/PV/load Wh);
|
||||
grid import/export nejprve z delta Deye total counterů (reg 522-525), fallback per-minute; poté sjednocení
|
||||
fn_audit_grid_*_wh_for_economics (u jednosměrného toku max s odhadem z průměrného grid_power_w).
|
||||
7 směrových toků (flow_*_wh): prioritní alokace per minuta z telemetrie (PV→load→batt→export; baterie→load/export; síť→zbytek).
|
||||
actual_cost_czk = per-direction (import_wh × buy - export_wh × sell).
|
||||
Zelený bonus: součet přes pole s green_bonus_czk_kwh.
|
||||
|
||||
@@ -21,8 +21,10 @@ as $fn$
|
||||
'day', (date_trunc('day', ai.interval_start at time zone 'Europe/Prague'))::date,
|
||||
'interval_count', count(*)::int,
|
||||
'pv_production_kwh', round(sum(coalesce(ai.actual_pv_production_wh, 0)) / 1000, 3),
|
||||
'grid_import_kwh', round(sum(coalesce(ai.actual_grid_import_wh, 0)) / 1000, 3),
|
||||
'grid_export_kwh', round(sum(coalesce(ai.actual_grid_export_wh, 0)) / 1000, 3),
|
||||
'grid_import_kwh', round(sum(ems.fn_audit_grid_import_wh_for_economics(
|
||||
ai.actual_grid_import_wh, ai.actual_grid_export_wh, ai.actual_grid_power_w)) / 1000, 3),
|
||||
'grid_export_kwh', round(sum(ems.fn_audit_grid_export_wh_for_economics(
|
||||
ai.actual_grid_import_wh, ai.actual_grid_export_wh, ai.actual_grid_power_w)) / 1000, 3),
|
||||
'batt_charge_kwh', round(sum(coalesce(ai.actual_batt_charge_wh, 0)) / 1000, 3),
|
||||
'batt_discharge_kwh', round(sum(coalesce(ai.actual_batt_discharge_wh, 0)) / 1000, 3),
|
||||
'load_kwh', round(sum(coalesce(ai.actual_load_consumption_wh, 0)) / 1000, 3),
|
||||
@@ -36,7 +38,9 @@ as $fn$
|
||||
'grid_import_cashflow_czk',
|
||||
round(
|
||||
sum(
|
||||
coalesce(ai.actual_grid_import_wh, 0) / 1000.0
|
||||
ems.fn_audit_grid_import_wh_for_economics(
|
||||
ai.actual_grid_import_wh, ai.actual_grid_export_wh, ai.actual_grid_power_w
|
||||
) / 1000.0
|
||||
* coalesce(ep.effective_buy_price_czk_kwh, 0)
|
||||
),
|
||||
2
|
||||
@@ -44,7 +48,9 @@ as $fn$
|
||||
'grid_export_revenue_czk',
|
||||
round(
|
||||
sum(
|
||||
coalesce(ai.actual_grid_export_wh, 0) / 1000.0
|
||||
ems.fn_audit_grid_export_wh_for_economics(
|
||||
ai.actual_grid_import_wh, ai.actual_grid_export_wh, ai.actual_grid_power_w
|
||||
) / 1000.0
|
||||
* coalesce(ep.effective_sell_price_czk_kwh, 0)
|
||||
),
|
||||
2
|
||||
|
||||
@@ -59,7 +59,13 @@ as $fn$
|
||||
coalesce(dt.vat_rate, 0.21) as vat_rate,
|
||||
mip.buy_raw_price_czk_kwh as buy_spot,
|
||||
mip.sell_raw_price_czk_kwh as sell_spot,
|
||||
pi.expected_cost_czk as planned_cost_czk
|
||||
pi.expected_cost_czk as planned_cost_czk,
|
||||
ems.fn_audit_grid_import_wh_for_economics(
|
||||
ai.actual_grid_import_wh, ai.actual_grid_export_wh, ai.actual_grid_power_w
|
||||
) as est_grid_import_wh,
|
||||
ems.fn_audit_grid_export_wh_for_economics(
|
||||
ai.actual_grid_import_wh, ai.actual_grid_export_wh, ai.actual_grid_power_w
|
||||
) as est_grid_export_wh
|
||||
from ems.audit_interval ai
|
||||
left join lateral (
|
||||
select smc_inner.*
|
||||
@@ -202,29 +208,19 @@ as $fn$
|
||||
select
|
||||
s5.site_id,
|
||||
s5.day_local,
|
||||
round(s5.est_grid_import_wh / 1000, 4) as import_kwh,
|
||||
round(s5.est_grid_export_wh / 1000, 4) as export_kwh,
|
||||
round(
|
||||
coalesce(s5.actual_grid_import_wh, greatest(s5.actual_grid_power_w, 0)::numeric / 4) / 1000,
|
||||
4
|
||||
) as import_kwh,
|
||||
round(
|
||||
coalesce(s5.actual_grid_export_wh, abs(least(s5.actual_grid_power_w, 0))::numeric / 4) / 1000,
|
||||
4
|
||||
) as export_kwh,
|
||||
round(
|
||||
coalesce(s5.actual_grid_import_wh, greatest(s5.actual_grid_power_w, 0)::numeric / 4) / 1000.0
|
||||
* coalesce(s5.buy_p, 0),
|
||||
s5.est_grid_import_wh / 1000.0 * coalesce(s5.buy_p, 0),
|
||||
4
|
||||
) as grid_import_cashflow_czk,
|
||||
round(
|
||||
coalesce(s5.actual_grid_export_wh, abs(least(s5.actual_grid_power_w, 0))::numeric / 4) / 1000.0
|
||||
* coalesce(s5.sell_p, 0),
|
||||
s5.est_grid_export_wh / 1000.0 * coalesce(s5.sell_p, 0),
|
||||
4
|
||||
) as grid_export_revenue_czk,
|
||||
round(
|
||||
coalesce(s5.actual_grid_import_wh, greatest(s5.actual_grid_power_w, 0)::numeric / 4) / 1000.0
|
||||
* coalesce(s5.buy_p, 0)
|
||||
- coalesce(s5.actual_grid_export_wh, abs(least(s5.actual_grid_power_w, 0))::numeric / 4) / 1000.0
|
||||
* coalesce(s5.sell_p, 0),
|
||||
s5.est_grid_import_wh / 1000.0 * coalesce(s5.buy_p, 0)
|
||||
- s5.est_grid_export_wh / 1000.0 * coalesce(s5.sell_p, 0),
|
||||
4
|
||||
) as dynamic_cost_czk,
|
||||
s5.green_bonus_czk,
|
||||
|
||||
Reference in New Issue
Block a user