Hloubková diagnóza EV potvrdila: oportunitní ekonomika via-baterie je v LP
správně, ale okraje lhaly nebo byly nevykonatelné:
- V099 + R__039: ems.ev_session.opportunistic_value_czk_kwh (NULL = zdědit
z asset_vehicle, 0 = vypnout pro session); headroom_wh z max(target_soc,
soc_at_connect) — „nenabíjet" (nízký target) už paradoxně NEzvětšuje
oportunistickou vrstvu; vehicles JSON nese min_power_w wallboxu.
- R__015: patch klíč opportunistic_value_czk_kwh (validace >= 0).
- solver_v2: (a) deadline suma range(t_dl) — slot začínající v deadline už
nepatří „do deadline"; (b) Σ ev_direct <= gi + PV (fyzikální split);
(c) binárka ev_on → setpoint ∈ {0} ∪ [min_power_w, max] (konec 400–900 W
nevykonatelných setpointů); (d) bez session EV == 0 (stop-session i golden
fixtures — žádné pumpování při buy<0); dekompozice total == needed − unmet
+ opp i pro needed = 0; (e) battery_arbitrage_czk = via_bat kWh × oportunitní
cena (min sell exportního slotu téhož pražského dne, jinak terminal value)
místo konstantní 0. Oportunismus PO deadline zůstává POVOLENÝ (rozhodnutí:
auto často doma, odjezd řeší rolling replan).
- R__033: fn_plan_current_bundle.intervals + ev1/ev2_via_bat_w (UI nemá cenit
EV kWh z baterie slotovým buy).
Golden gate beze změny snapshotů (v1 nedotčen, fixtures bez EV sessions);
solver_v2_eval před/po identický (CELKEM −1283.5 Kč, Δ −221.9 vs v1);
tests/test_solver_v2.py +7 testů; plná sada 310 passed / 4 xfailed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
81 lines
2.7 KiB
PL/PgSQL
81 lines
2.7 KiB
PL/PgSQL
create or replace function ems.fn_ev_session_apply_patch(
|
||
p_site_id int,
|
||
p_session_id int,
|
||
p_patch jsonb
|
||
)
|
||
returns jsonb
|
||
language plpgsql
|
||
as $fn$
|
||
declare
|
||
v_id int;
|
||
begin
|
||
if not (p_patch ? 'target_soc_pct')
|
||
and not (p_patch ? 'target_deadline')
|
||
and not (p_patch ? 'soc_at_connect_pct')
|
||
and not (p_patch ? 'opportunistic_value_czk_kwh') then
|
||
return jsonb_build_object('success', false, 'error', 'no_fields');
|
||
end if;
|
||
|
||
if (p_patch ? 'opportunistic_value_czk_kwh')
|
||
and jsonb_typeof(p_patch->'opportunistic_value_czk_kwh') <> 'null'
|
||
and (p_patch->>'opportunistic_value_czk_kwh')::numeric < 0 then
|
||
return jsonb_build_object(
|
||
'success', false, 'error', 'opportunistic_value_negative'
|
||
);
|
||
end if;
|
||
|
||
update ems.ev_session es
|
||
set
|
||
target_soc_pct = case
|
||
when p_patch ? 'target_soc_pct' then
|
||
case
|
||
when p_patch->'target_soc_pct' is null
|
||
or jsonb_typeof(p_patch->'target_soc_pct') = 'null' then null
|
||
else (p_patch->>'target_soc_pct')::double precision
|
||
end
|
||
else es.target_soc_pct
|
||
end,
|
||
-- skutečné SoC při připojení (Tesla Fleet API po příjezdu)
|
||
soc_at_connect_pct = case
|
||
when p_patch ? 'soc_at_connect_pct' then
|
||
case
|
||
when p_patch->'soc_at_connect_pct' is null
|
||
or jsonb_typeof(p_patch->'soc_at_connect_pct') = 'null' then null
|
||
else (p_patch->>'soc_at_connect_pct')::double precision
|
||
end
|
||
else es.soc_at_connect_pct
|
||
end,
|
||
target_deadline = case
|
||
when p_patch ? 'target_deadline' then
|
||
case
|
||
when p_patch->'target_deadline' is null
|
||
or jsonb_typeof(p_patch->'target_deadline') = 'null' then null
|
||
else (p_patch->>'target_deadline')::timestamptz
|
||
end
|
||
else es.target_deadline
|
||
end,
|
||
-- NULL = zdědit z asset_vehicle; 0 = oportunismus pro session vypnut
|
||
opportunistic_value_czk_kwh = case
|
||
when p_patch ? 'opportunistic_value_czk_kwh' then
|
||
case
|
||
when p_patch->'opportunistic_value_czk_kwh' is null
|
||
or jsonb_typeof(p_patch->'opportunistic_value_czk_kwh') = 'null' then null
|
||
else (p_patch->>'opportunistic_value_czk_kwh')::numeric
|
||
end
|
||
else es.opportunistic_value_czk_kwh
|
||
end
|
||
where es.id = p_session_id
|
||
and es.site_id = p_site_id
|
||
returning es.id into v_id;
|
||
|
||
if v_id is null then
|
||
return jsonb_build_object('success', false, 'session_id', null);
|
||
end if;
|
||
|
||
return jsonb_build_object('success', true, 'session_id', v_id);
|
||
end;
|
||
$fn$;
|
||
|
||
comment on function ems.fn_ev_session_apply_patch is
|
||
'PATCH EV session – jen klíče přítomné v JSON (ISO string pro deadline; soc_at_connect_pct z Tesla API; opportunistic_value_czk_kwh >= 0, NULL = zdědit z vozidla, 0 = vypnout).';
|