Files
ems/db/routines/R__066_fn_site_notifications_context.sql
Dusan Vojacek 69c979b967
Some checks failed
CI and deploy / migration-check (push) Failing after 11s
CI and deploy / deploy (push) Has been skipped
fix notfications
2026-04-27 19:13:16 +02:00

140 lines
5.3 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
create or replace function ems.fn_site_notifications_context(p_site_id int)
returns jsonb
language sql
stable
as $fn$
select
case
when not exists (select 1 from ems.site s0 where s0.id = p_site_id) then
jsonb_build_object('error', 'not_found')
else jsonb_build_object(
'timezone',
coalesce(
nullif(trim((select s.timezone from ems.site s where s.id = p_site_id)), ''),
'Europe/Prague'
),
'mode_code',
(select m.mode_code from ems.site_operating_mode m where m.site_id = p_site_id),
'has_plan',
exists (
select 1
from ems.planning_run pr
where pr.site_id = p_site_id
and pr.status = 'active'
),
'tomorrow_slots',
(
select count(*)::int
from ems.vw_site_effective_price v
where v.site_id = p_site_id
and (v.interval_start at time zone coalesce(
nullif(trim((select s2.timezone from ems.site s2 where s2.id = p_site_id)), ''),
'Europe/Prague'
))::date = (
(
current_timestamp at time zone coalesce(
nullif(trim((select s3.timezone from ems.site s3 where s3.id = p_site_id)), ''),
'Europe/Prague'
)
)::date + 1
)
),
'reserve_soc',
(select min(ab.reserve_soc_percent)::float from ems.asset_battery ab where ab.site_id = p_site_id),
'min_soc',
(select min(ab.min_soc_percent)::float from ems.asset_battery ab where ab.site_id = p_site_id),
'soc_pct',
(select li.battery_soc_percent::float from ems.vw_latest_inverter li where li.site_id = p_site_id order by li.measured_at desc nulls last limit 1),
'inv_measured_at',
(select li.measured_at from ems.vw_latest_inverter li where li.site_id = p_site_id order by li.measured_at desc nulls last limit 1),
'hb_last_seen',
(select hb.last_seen from ems.site_heartbeat hb where hb.site_id = p_site_id limit 1),
'price_slots',
coalesce(
(
select jsonb_agg(
jsonb_build_object(
'interval_start', v.interval_start,
'effective_buy_price_czk_kwh', v.effective_buy_price_czk_kwh,
'effective_sell_price_czk_kwh', v.effective_sell_price_czk_kwh
)
order by v.interval_start
)
from ems.vw_site_effective_price v
where v.site_id = p_site_id
and v.interval_start >= now()
-- Python notifikace používají jen ceny v horizontu 6 h (24×15 min slotů).
and v.interval_start < now() + interval '6 hours'
),
'[]'::jsonb
),
'avg_buy',
(
select avg(v.effective_buy_price_czk_kwh)::float
from ems.vw_site_effective_price v
where v.site_id = p_site_id
and v.interval_start::date in (current_date, current_date + 1)
),
'usable_wh',
(
select coalesce(sum(ab.usable_capacity_wh), 0)::float
from ems.asset_battery ab
join ems.asset_inverter ai on ai.id = ab.inverter_id
where ai.site_id = p_site_id
),
'ev_sessions',
coalesce(
(
select jsonb_agg(
jsonb_build_object(
'id', es.id,
'charger_id', es.charger_id,
'energy_delivered_wh', es.energy_delivered_wh,
'target_soc_pct', es.target_soc_pct,
'session_start', es.session_start,
'soc_at_connect_pct', es.soc_at_connect_pct,
'battery_capacity_kwh', coalesce(av_id.battery_capacity_kwh, av_def.battery_capacity_kwh),
'make', coalesce(av_id.make, av_def.make),
'model', coalesce(av_id.model, av_def.model),
'default_target_soc_pct', coalesce(av_id.default_target_soc_pct, av_def.default_target_soc_pct),
'charger_code', ac.code
)
order by es.id
)
from ems.ev_session es
join ems.asset_ev_charger ac on ac.id = es.charger_id
left join ems.asset_vehicle av_id on av_id.id = es.vehicle_id
left join ems.asset_vehicle av_def
on av_def.default_charger_id = ac.id
and es.vehicle_id is null
where es.site_id = p_site_id
and es.session_end is null
),
'[]'::jsonb
),
'neg_windows',
coalesce(
(
select jsonb_agg(
jsonb_build_object(
'predicted_date', p.predicted_date,
'window_start_hour', p.window_start_hour,
'window_end_hour', p.window_end_hour,
'probability_pct', p.probability_pct
)
order by p.predicted_date, p.window_start_hour
)
from ems.predicted_negative_price_window p
where p.site_id = p_site_id
and p.predicted_date between current_date and current_date + 2
and p.probability_pct >= 50
),
'[]'::jsonb
)
)
end;
$fn$;
comment on function ems.fn_site_notifications_context(int) is
'Vstupy pro build_smart_notifications + infra pravidla (GET /notifications).';