dalsi
Some checks failed
CI and deploy / migration-check (push) Failing after 21s
CI and deploy / deploy (push) Has been skipped

This commit is contained in:
Dusan Vojacek
2026-05-23 00:34:52 +02:00
parent a52be1b792
commit 1ec92bdf79
5 changed files with 313 additions and 63 deletions

View File

@@ -81,7 +81,10 @@ declare
v_first_neg_prague_date date;
v_pre_neg_peak_sell_ord int;
v_preneg_export_min_soc_wh numeric;
v_max_sell_czk_kwh numeric;
v_morning_zone_peak_sell numeric;
v_morning_preneg_start_hour int := 5;
v_morning_preneg_end_hour int := 11;
v_evening_peak_start_hour int := 17;
v_charge_acquisition numeric;
v_est_grid_wh numeric;
v_est_pv_wh numeric;
@@ -556,6 +559,14 @@ begin
wk.sell_price > v_ref_buy_czk_kwh + v_degrad_czk_kwh
end
)
-- Na dni prvního sell<0 nepočítat noční „šrot“ (0004) do globálního rozpočtu —
-- jinak vyčerpá Wh před ranní špičkou (home-01: půlnoc 3,7 vs. 07:00 3,06).
and not (
v_first_neg_prague_date is not null
and (wk.interval_start at time zone 'Europe/Prague')::date = v_first_neg_prague_date
and extract(hour from wk.interval_start at time zone 'Europe/Prague')
< v_morning_preneg_start_hour
)
order by wk.sell_price desc, wk.slot_ord desc
loop
exit when v_cum >= v_discharge_target_wh;
@@ -565,46 +576,96 @@ begin
end loop;
end if;
-- Globální sell špičky (≈ max sell v horizontu): vždy export baterie, i po vyčerpání Wh rozpočtu.
select coalesce(max(wk.sell_price), 0)
into v_max_sell_czk_kwh
from _ems_plan_slot_wk wk;
-- Večerní špičky per kalendářní den (≥17:00 Prague): ne globální max horizontu (jinak půlnoc).
for r_slot in
select
(wk.interval_start at time zone 'Europe/Prague')::date as plan_date,
coalesce(max(wk.sell_price), 0) as evening_peak_sell
from _ems_plan_slot_wk wk
where extract(hour from wk.interval_start at time zone 'Europe/Prague')
>= v_evening_peak_start_hour
group by (wk.interval_start at time zone 'Europe/Prague')::date
loop
if r_slot.evening_peak_sell > 0 then
update _ems_plan_slot_wk wk
set allow_discharge_export = true
where (wk.interval_start at time zone 'Europe/Prague')::date = r_slot.plan_date
and extract(hour from wk.interval_start at time zone 'Europe/Prague')
>= v_evening_peak_start_hour
and wk.sell_price >= r_slot.evening_peak_sell - v_degrad_czk_kwh
and (
case
when v_purchase_pricing_mode = 'fixed' then
wk.sell_price > v_degrad_czk_kwh
else
wk.sell_price > v_ref_buy_czk_kwh + v_degrad_czk_kwh
end
);
end if;
end loop;
if v_max_sell_czk_kwh > 0 then
update _ems_plan_slot_wk wk
set allow_discharge_export = true
where wk.sell_price >= v_max_sell_czk_kwh - v_degrad_czk_kwh
and (
case
when v_purchase_pricing_mode = 'fixed' then
wk.sell_price > v_degrad_czk_kwh
else
wk.sell_price > v_ref_buy_czk_kwh + v_degrad_czk_kwh
end
);
end if;
-- Před prvním sell<0 téhož dne: export v lokálním max kladného sell (např. 07:00, ne včerejší 20:45).
-- Ranní pásmo před prvním sell<0 (511 Prague): lokální peak, ne půlnoc celého dne.
if v_first_neg_sell_ord is not null
and v_first_neg_prague_date is not null
and p_current_soc_wh >= v_preneg_export_min_soc_wh
then
select wk.slot_ord
into v_pre_neg_peak_sell_ord
select coalesce(max(wk.sell_price), 0)
into v_morning_zone_peak_sell
from _ems_plan_slot_wk wk
where wk.slot_ord < v_first_neg_sell_ord
and wk.sell_price >= 0
and (wk.interval_start at time zone 'Europe/Prague')::date = v_first_neg_prague_date
order by wk.sell_price desc, wk.slot_ord
limit 1;
and extract(hour from wk.interval_start at time zone 'Europe/Prague')
between v_morning_preneg_start_hour and v_morning_preneg_end_hour;
if v_pre_neg_peak_sell_ord is not null then
if v_morning_zone_peak_sell > 0 then
update _ems_plan_slot_wk wk
set allow_discharge_export = true
where wk.slot_ord = v_pre_neg_peak_sell_ord;
where wk.slot_ord < v_first_neg_sell_ord
and wk.sell_price >= 0
and (wk.interval_start at time zone 'Europe/Prague')::date = v_first_neg_prague_date
and extract(hour from wk.interval_start at time zone 'Europe/Prague')
between v_morning_preneg_start_hour and v_morning_preneg_end_hour
and wk.sell_price >= v_morning_zone_peak_sell - v_degrad_czk_kwh;
select wk.slot_ord
into v_pre_neg_peak_sell_ord
from _ems_plan_slot_wk wk
where wk.slot_ord < v_first_neg_sell_ord
and wk.sell_price >= 0
and (wk.interval_start at time zone 'Europe/Prague')::date = v_first_neg_prague_date
and extract(hour from wk.interval_start at time zone 'Europe/Prague')
between v_morning_preneg_start_hour and v_morning_preneg_end_hour
order by wk.sell_price desc, wk.slot_ord
limit 1;
end if;
end if;
-- Mezi ranní peak a prvním sell<0: zákaz „pozdního dumpu“ při nízkém sell (07:30 za 2 Kč).
if v_first_neg_sell_ord is not null
and v_first_neg_prague_date is not null
and v_morning_zone_peak_sell is not null
and v_morning_zone_peak_sell > 0
then
update _ems_plan_slot_wk wk
set allow_discharge_export = false
where wk.slot_ord < v_first_neg_sell_ord
and (wk.interval_start at time zone 'Europe/Prague')::date = v_first_neg_prague_date
and extract(hour from wk.interval_start at time zone 'Europe/Prague')
between v_morning_preneg_start_hour and v_morning_preneg_end_hour
and wk.sell_price < v_morning_zone_peak_sell - v_degrad_czk_kwh;
update _ems_plan_slot_wk wk
set allow_discharge_export = false
where wk.slot_ord < v_first_neg_sell_ord
and (wk.interval_start at time zone 'Europe/Prague')::date = v_first_neg_prague_date
and extract(hour from wk.interval_start at time zone 'Europe/Prague')
>= v_morning_preneg_start_hour
and extract(hour from wk.interval_start at time zone 'Europe/Prague')
< v_evening_peak_start_hour
and wk.sell_price < v_morning_zone_peak_sell - v_degrad_czk_kwh;
end if;
-- Acquisition: grid nabíjení před prvním exportem ve STEJNÝ den jako záporné výkupní okno
-- (ne dřívější večerní export v horizontu rolling replanu).
select min(wk.interval_start)