Files
ems/db/routines/R__013_fn_ev_arrival_stats.sql
2026-04-19 20:15:46 +02:00

66 lines
2.0 KiB
PL/PgSQL

CREATE OR REPLACE FUNCTION ems.fn_update_ev_arrival_stats(
p_site_id INT,
p_charger_id INT,
p_vehicle_id INT,
p_arrived_at TIMESTAMPTZ
)
RETURNS VOID
LANGUAGE sql
AS $$
INSERT INTO ems.ev_arrival_stats
(site_id, charger_id, vehicle_id, day_of_week, arrival_hour, sample_count, last_updated)
VALUES (
p_site_id,
p_charger_id,
p_vehicle_id,
EXTRACT(DOW FROM p_arrived_at AT TIME ZONE 'Europe/Prague')::INT,
EXTRACT(HOUR FROM p_arrived_at AT TIME ZONE 'Europe/Prague')::INT,
1,
now()
)
ON CONFLICT (site_id, charger_id, day_of_week, arrival_hour) DO UPDATE SET
sample_count = ems.ev_arrival_stats.sample_count + 1,
last_updated = now();
$$;
COMMENT ON FUNCTION ems.fn_update_ev_arrival_stats(INT, INT, INT, TIMESTAMPTZ) IS
'Přidá jeden příjezd do statistiky. Volat při otevření nové EV session
(telemetry_collector: přechod status available → preparing/charging).';
CREATE OR REPLACE FUNCTION ems.fn_ev_expected_arrival(
p_site_id INT,
p_charger_id INT,
p_for_date DATE DEFAULT (
(CURRENT_TIMESTAMP AT TIME ZONE 'Europe/Prague')::date + 1
)
)
RETURNS TABLE (
expected_hour INT,
confidence_pct INT,
sample_count INT
)
LANGUAGE sql
STABLE
AS $$
SELECT
s.arrival_hour,
ROUND(
s.sample_count::NUMERIC
/ NULLIF(SUM(s.sample_count) OVER (PARTITION BY s.day_of_week), 0)
* 100
)::INT,
s.sample_count
FROM ems.ev_arrival_stats s
WHERE s.site_id = p_site_id
AND s.charger_id = p_charger_id
AND s.day_of_week = EXTRACT(DOW FROM p_for_date)::INT
AND s.sample_count >= 2
ORDER BY s.sample_count DESC
LIMIT 3;
$$;
COMMENT ON FUNCTION ems.fn_ev_expected_arrival(INT, INT, DATE) IS
'Top 3 nejčastější hodiny příjezdu EV pro den v týdnu odpovídající kalendářnímu datu p_for_date.
Backend předává „zítřek“ v časové zóně lokality. Použití: notifikace, později solver.';