FIX RYCHLOST EKONOMIKA
Some checks failed
CI and deploy / migration-check (push) Failing after 10s
CI and deploy / deploy (push) Has been skipped

This commit is contained in:
Dusan Vojacek
2026-04-27 19:47:18 +02:00
parent c52946a4ce
commit 8114ec5e63
5 changed files with 177 additions and 12 deletions

View File

@@ -1,3 +1,141 @@
-- Denní ekonomika za časové okno [p_ts_from, p_ts_to) bez joinu na vw_site_effective_price
-- (ten dělá cross join mip × site_market_config a je extrémně drahý při agregaci přes vw_economics_daily).
-- Ceny = fn_effective_buy_price / fn_effective_sell_price (stejně jako ve vw_site_effective_price).
create or replace function ems.fn_economics_daily_for_window(
p_site_id int,
p_ts_from timestamptz,
p_ts_to timestamptz
)
returns table (
site_id int,
day_local date,
interval_count int,
import_kwh numeric,
export_kwh numeric,
pv_kwh numeric,
load_kwh numeric,
pv_self_consumption_kwh numeric,
ev_kwh numeric,
hp_kwh numeric,
grid_import_cashflow_czk numeric,
grid_export_revenue_czk numeric,
import_cost_czk numeric,
export_revenue_czk numeric,
net_cost_czk numeric,
green_bonus_czk numeric,
total_balance_czk numeric,
planned_net_cost_czk numeric,
planned_balance_czk numeric,
deviation_cost_czk numeric
)
language sql
stable
as $fn$
with slots as (
select
ai.site_id,
(date_trunc('day', ai.interval_start at time zone 'Europe/Prague'))::date as day_local,
round(
coalesce(ai.actual_grid_import_wh, greatest(ai.actual_grid_power_w, 0)::numeric / 4) / 1000,
4
) as import_kwh,
round(
coalesce(ai.actual_grid_export_wh, abs(least(ai.actual_grid_power_w, 0))::numeric / 4) / 1000,
4
) as export_kwh,
round(
coalesce(ai.actual_grid_import_wh, greatest(ai.actual_grid_power_w, 0)::numeric / 4) / 1000.0
* coalesce(pr.buy_p, 0),
4
) as grid_import_cashflow_czk,
round(
coalesce(ai.actual_grid_export_wh, abs(least(ai.actual_grid_power_w, 0))::numeric / 4) / 1000.0
* coalesce(pr.sell_p, 0),
4
) as grid_export_revenue_czk,
round(
coalesce(ai.actual_grid_import_wh, greatest(ai.actual_grid_power_w, 0)::numeric / 4) / 1000.0
* coalesce(pr.buy_p, 0)
- coalesce(ai.actual_grid_export_wh, abs(least(ai.actual_grid_power_w, 0))::numeric / 4) / 1000.0
* coalesce(pr.sell_p, 0),
4
) as dynamic_cost_czk,
ai.green_bonus_czk,
pi.expected_cost_czk as planned_cost_czk,
ai.actual_pv_power_w,
ai.actual_load_power_w,
ai.actual_ev_power_w,
ai.actual_heat_pump_power_w
from ems.audit_interval ai
left join ems.planning_interval pi
on pi.run_id = ai.planning_run_id
and pi.interval_start = ai.interval_start
cross join lateral (
select
ems.fn_effective_buy_price(ai.site_id, ai.interval_start) as buy_p,
ems.fn_effective_sell_price(ai.site_id, ai.interval_start) as sell_p
) pr
where ai.site_id = p_site_id
and ai.interval_start >= p_ts_from
and ai.interval_start < p_ts_to
),
daily_agg as (
select
s.site_id,
s.day_local,
count(*)::int as interval_count,
round(sum(s.import_kwh), 3) as import_kwh,
round(sum(s.export_kwh), 3) as export_kwh,
round(sum(greatest(s.actual_pv_power_w, 0)::numeric / 4000), 3) as pv_kwh,
round(sum(greatest(s.actual_load_power_w, 0)::numeric / 4000), 3) as load_kwh,
round(sum(greatest(s.actual_ev_power_w, 0)::numeric / 4000), 3) as ev_kwh,
round(sum(greatest(s.actual_heat_pump_power_w, 0)::numeric / 4000), 3) as hp_kwh,
round(
sum(greatest(s.actual_pv_power_w, 0)::numeric / 4000) - sum(s.export_kwh),
3
) as pv_self_consumption_kwh,
round(sum(s.grid_import_cashflow_czk), 2) as grid_import_cashflow_czk,
round(sum(s.grid_export_revenue_czk), 2) as grid_export_revenue_czk,
round(sum(case when s.dynamic_cost_czk > 0 then s.dynamic_cost_czk else 0 end), 2) as import_cost_czk,
round(sum(case when s.dynamic_cost_czk < 0 then abs(s.dynamic_cost_czk) else 0 end), 2) as export_revenue_czk,
round(sum(s.dynamic_cost_czk), 2) as net_cost_czk,
round(coalesce(sum(s.green_bonus_czk), 0), 2) as green_bonus_czk,
round(-sum(s.dynamic_cost_czk) + coalesce(sum(s.green_bonus_czk), 0), 2) as total_balance_czk,
round(sum(s.planned_cost_czk), 2) as planned_net_cost_czk,
round(-coalesce(sum(s.planned_cost_czk), 0), 2) as planned_balance_czk,
round(sum(s.dynamic_cost_czk) - coalesce(sum(s.planned_cost_czk), 0), 2) as deviation_cost_czk
from slots s
group by s.site_id, s.day_local
)
select
d.site_id,
d.day_local,
d.interval_count,
d.import_kwh,
d.export_kwh,
d.pv_kwh,
d.load_kwh,
d.pv_self_consumption_kwh,
d.ev_kwh,
d.hp_kwh,
d.grid_import_cashflow_czk,
d.grid_export_revenue_czk,
d.import_cost_czk,
d.export_revenue_czk,
d.net_cost_czk,
d.green_bonus_czk,
d.total_balance_czk,
d.planned_net_cost_czk,
d.planned_balance_czk,
d.deviation_cost_czk
from daily_agg d
order by d.day_local;
$fn$;
comment on function ems.fn_economics_daily_for_window is
'Denní souhrn ekonomiky pro site v polovičně otevřeném UTC okně [from, to); bez vw_site_effective_price.';
create or replace function ems.fn_economics_daily_month(
p_site_id int,
p_month_start date,
@@ -50,13 +188,14 @@ as $fn$
'deviation_cost_czk', r.deviation_cost_czk,
'is_locked', (l.site_id is not null)
) as day_row
from ems.vw_economics_daily r
from ems.fn_economics_daily_for_window(
p_site_id,
(p_month_start::timestamp at time zone 'Europe/Prague'),
(p_month_end::timestamp at time zone 'Europe/Prague')
) r
left join ems.audit_day_lock l
on l.site_id = r.site_id
and l.day_local = r.day_local
where r.site_id = p_site_id
and r.day_local >= p_month_start
and r.day_local < p_month_end
order by r.day_local
) sub
),

View File

@@ -27,7 +27,11 @@ begin
v_total,
v_gic,
v_ger
from ems.vw_economics_daily r
from ems.fn_economics_daily_for_window(
p_site_id,
(p_day::timestamp at time zone 'Europe/Prague'),
((p_day + 1)::timestamp at time zone 'Europe/Prague')
) r
where r.site_id = p_site_id
and r.day_local = p_day;
@@ -71,4 +75,4 @@ end;
$fn$;
comment on function ems.fn_economics_lock_day(int, date) is
'Zamkne den ekonomiky podle aktuálního vw_economics_daily (POST lock).';
'Zamkne den ekonomiky podle fn_economics_daily_for_window (POST lock).';

View File

@@ -15,7 +15,11 @@ as $fn$
case when l.site_id is not null then l.green_bonus_czk else r.green_bonus_czk end as gb,
coalesce(l.grid_import_cashflow_czk, r.grid_import_cashflow_czk) as gic,
coalesce(l.grid_export_revenue_czk, r.grid_export_revenue_czk) as ger
from ems.vw_economics_daily r
from ems.fn_economics_daily_for_window(
p_site_id,
(p_month_start::timestamp at time zone 'Europe/Prague'),
(p_month_end::timestamp at time zone 'Europe/Prague')
) r
left join ems.audit_day_lock l
on l.site_id = r.site_id
and l.day_local = r.day_local