-- jeden řádek planning_interval jako jsonb pro aktivní plán a slot offset (Prague 15min) create or replace function ems.fn_planning_interval_at_offset( p_site_id int, p_offset_slots int default 0 ) returns jsonb language sql stable as $fn$ select to_jsonb(pi) from ems.planning_interval pi join ems.planning_run pr on pr.id = pi.run_id where pr.site_id = p_site_id and pr.status = 'active' and pi.interval_start = ems.fn_planning_slot_boundary_prague(p_offset_slots) limit 1; $fn$; create or replace function ems.fn_planning_max_effective_charge_w(p_site_id int) returns int language sql stable as $fn$ select coalesce( least( coalesce(ai.max_battery_charge_w, ai.max_charge_power_w), coalesce( ab.bms_max_charge_w, case when ab.max_charge_c_rate is not null then (ab.max_charge_c_rate * ab.usable_capacity_wh)::bigint end, coalesce(ai.max_battery_charge_w, ai.max_charge_power_w) ) )::int, 0 ) from ems.asset_battery ab join ems.asset_inverter ai on ai.id = ab.inverter_id and ai.site_id = ab.site_id where ab.site_id = p_site_id and ai.controllable is true and ai.active is true order by ab.id limit 1; $fn$;