-- Defaulty nové ev_session pro vozidlo: kaskáda -- 1) ems.ev_weekly_requirement — nejbližší budoucí výskyt enabled řádku -- do 48 h od příjezdu (deadline_hour v den dow, Europe/Prague), -- 2) forecast z týdenního rytmu (V089: fn_ev_next_departure + -- fn_ev_required_soc), jen při asset_vehicle.target_soc_forecast_enabled, -- 3) defaulty vozidla (default_target_soc_pct; deadline = příští výskyt -- default_deadline_hour v Europe/Prague). -- Volá fn_ev_session_transition při založení session; ruční přepis přes -- fn_ev_session_apply_patch (Discord / UI) vždy vyhrává. create or replace function ems.fn_ev_session_defaults( p_vehicle_id int, p_arrival timestamptz ) returns jsonb language plpgsql stable as $fn$ declare v_vehicle record; v_weekly record; v_forecast_departure timestamptz; v_deadline timestamptz; begin select av.default_target_soc_pct, av.default_deadline_hour, av.target_soc_forecast_enabled into v_vehicle from ems.asset_vehicle av where av.id = p_vehicle_id; if not found then return jsonb_build_object( 'target_soc_pct', null, 'deadline', null, 'source', 'none' ); end if; -- 1) týdenní požadavek: nejbližší budoucí výskyt do 48 h (Europe/Prague) select wr.target_soc_pct, occ.deadline into v_weekly from generate_series(0, 2) as offs cross join lateral ( select ((p_arrival at time zone 'Europe/Prague')::date + offs) as d ) day join ems.ev_weekly_requirement wr on wr.vehicle_id = p_vehicle_id and wr.enabled and wr.dow = extract(isodow from day.d)::int - 1 cross join lateral ( select (day.d::timestamp + make_interval(hours => wr.deadline_hour)) at time zone 'Europe/Prague' as deadline ) occ where occ.deadline > p_arrival and occ.deadline <= p_arrival + interval '48 hours' order by occ.deadline limit 1; if v_weekly.deadline is not null then return jsonb_build_object( 'target_soc_pct', v_weekly.target_soc_pct, 'deadline', v_weekly.deadline, 'source', 'weekly' ); end if; -- 2) forecast z týdenního rytmu (chování shodné s dřívějším -- fn_ev_session_transition: deadline = typický odjezd; target P80, -- při málo datech default target) if v_vehicle.target_soc_forecast_enabled then v_forecast_departure := ems.fn_ev_next_departure(p_vehicle_id, p_arrival); if v_forecast_departure is not null then return jsonb_build_object( 'target_soc_pct', coalesce( ems.fn_ev_required_soc(p_vehicle_id, v_forecast_departure), v_vehicle.default_target_soc_pct ), 'deadline', v_forecast_departure, 'source', 'forecast' ); end if; end if; -- 3) defaulty vozidla: deadline = příští výskyt default_deadline_hour v_deadline := ( (p_arrival at time zone 'Europe/Prague')::date::timestamp + make_interval(hours => v_vehicle.default_deadline_hour) ) at time zone 'Europe/Prague'; if v_deadline <= p_arrival then v_deadline := ( ((p_arrival at time zone 'Europe/Prague')::date + 1)::timestamp + make_interval(hours => v_vehicle.default_deadline_hour) ) at time zone 'Europe/Prague'; end if; return jsonb_build_object( 'target_soc_pct', v_vehicle.default_target_soc_pct, 'deadline', v_deadline, 'source', 'default' ); end; $fn$; comment on function ems.fn_ev_session_defaults is 'Target SoC + deadline pro novou ev_session: jsonb {target_soc_pct, deadline, source}. Kaskáda ev_weekly_requirement (výskyt do 48 h, Europe/Prague) → forecast (target_soc_forecast_enabled) → defaulty vozidla (deadline = příští výskyt default_deadline_hour). p_vehicle_id null/neznámé → null hodnoty.';