-- Cache delta profilu PV (těžká agregace forecast_accuracy) — refresh po fn_fill_forecast_accuracy. -- Prefix R__018: musí běžet před R__022 (volá fn_refresh_site_pv_delta_profile_cache). drop function if exists ems.fn_refresh_site_pv_delta_profile_cache(int); create or replace function ems.fn_refresh_site_pv_delta_profile_cache( p_site_id int, p_force boolean default false ) returns void language plpgsql as $fn$ declare v_profile jsonb; begin -- VÝKON: agregace 120 dní nad forecast_accuracy trvá ~44 s/site na prod — -- po 15 min ji přepočítávat dusilo celou DB (timeouty API). Profil má 14d -- poločas, denní granularitu — čerstvost 6 h bohatě stačí. if not p_force and exists ( select 1 from ems.site_pv_forecast_calibration c where c.site_id = p_site_id and c.delta_profile_cached_at > now() - interval '6 hours' ) then return; end if; v_profile := ems.fn_pv_forecast_delta_profile( p_site_id, now() - interval '120 days', now() ); update ems.site_pv_forecast_calibration c set delta_profile_cache = v_profile, delta_profile_cached_at = now(), updated_at = now() where c.site_id = p_site_id; if not found then insert into ems.site_pv_forecast_calibration ( site_id, delta_learn_min_ts, delta_profile_cache, delta_profile_cached_at ) values ( p_site_id, timestamptz '2026-04-11T22:00:00Z', v_profile, now() ); end if; end; $fn$; comment on function ems.fn_refresh_site_pv_delta_profile_cache(int) is 'Přepočte a uloží delta_profile_cache pro site (volá fn_pv_forecast_delta_profile).'; create or replace function ems.fn_pv_forecast_delta_profile_cached( p_site_id int, p_data_from timestamptz default (now() - interval '120 days'), p_data_to timestamptz default now(), p_half_life_days numeric default 14, p_threshold_w int default 150, p_top_n_days int default 3, p_non_top_day_factor numeric default 0.02, p_day_weight_gamma numeric default 1.0, p_max_age interval default interval '30 minutes' ) returns jsonb language plpgsql stable as $fn$ declare v_cached jsonb; v_cached_at timestamptz; begin select c.delta_profile_cache, c.delta_profile_cached_at into v_cached, v_cached_at from ems.site_pv_forecast_calibration c where c.site_id = p_site_id; if v_cached is not null and v_cached_at is not null and v_cached_at >= now() - p_max_age and p_data_from >= (now() - interval '120 days') and p_data_to <= now() + interval '5 minutes' then return v_cached; end if; return ems.fn_pv_forecast_delta_profile( p_site_id, p_data_from, p_data_to, p_half_life_days, p_threshold_w, p_top_n_days, p_non_top_day_factor, p_day_weight_gamma ); end; $fn$; comment on function ems.fn_pv_forecast_delta_profile_cached is 'Delta profil z cache (max 30 min) nebo přepočet; pro canonical PV a /plan/current.';