second version

This commit is contained in:
Dusan Vojacek
2026-04-03 14:23:16 +02:00
parent 897b95f728
commit 9f4126946d
105 changed files with 9738 additions and 1470 deletions

View File

@@ -5,31 +5,122 @@
-- =============================================================
CREATE OR REPLACE FUNCTION ems.fn_effective_buy_price(
p_site_id INT,
p_site_id INT,
p_interval_start TIMESTAMPTZ
)
RETURNS NUMERIC(10,6)
LANGUAGE sql
LANGUAGE plpgsql
STABLE
AS $$
DECLARE
v_spot_price NUMERIC;
v_dist_rate NUMERIC;
v_system_services NUMERIC;
v_ote_fee NUMERIC;
v_vat_rate NUMERIC;
v_buy_margin_fixed NUMERIC;
v_buy_margin_pct NUMERIC;
v_buy_margin NUMERIC;
v_is_vt BOOLEAN;
v_local_time TIME;
v_dow INT;
v_hdo_code_id INT;
v_tariff_id INT;
v_rate_type TEXT;
BEGIN
SELECT
mip.buy_raw_price_czk_kwh
+ smc.buy_margin_fixed_czk
+ (mip.buy_raw_price_czk_kwh * smc.buy_margin_percent / 100.0)
FROM ems.market_interval_price mip
CROSS JOIN ems.site_market_config smc
WHERE mip.market_source = 'OTE_CZ'
AND mip.interval_start = p_interval_start
AND smc.site_id = p_site_id
smc.buy_margin_fixed_czk,
smc.buy_margin_percent,
smc.system_services_czk_kwh,
smc.ote_fee_czk_kwh,
smc.hdo_code_id,
smc.tariff_id,
dt.vat_rate
INTO
v_buy_margin_fixed,
v_buy_margin_pct,
v_system_services,
v_ote_fee,
v_hdo_code_id,
v_tariff_id,
v_vat_rate
FROM ems.site_market_config smc
LEFT JOIN ems.distribution_tariff dt ON dt.id = smc.tariff_id
WHERE smc.site_id = p_site_id
AND smc.valid_from <= p_interval_start
AND (smc.valid_to IS NULL OR smc.valid_to > p_interval_start)
ORDER BY smc.valid_from DESC
LIMIT 1;
IF NOT FOUND THEN
RETURN NULL;
END IF;
SELECT buy_raw_price_czk_kwh INTO v_spot_price
FROM ems.market_interval_price
WHERE market_source IN ('OTE_CZ', 'OTE_CZ_DAM')
AND interval_start = p_interval_start
LIMIT 1;
IF v_spot_price IS NULL THEN
RETURN NULL;
END IF;
v_local_time := (p_interval_start AT TIME ZONE 'Europe/Prague')::TIME;
v_dow := EXTRACT(DOW FROM p_interval_start AT TIME ZONE 'Europe/Prague');
-- 0=neděle, 6=sobota
IF v_hdo_code_id IS NOT NULL THEN
SELECT EXISTS (
SELECT 1
FROM ems.hdo_code_window w
WHERE w.hdo_code_id = v_hdo_code_id
AND (
w.day_type = 'all'
OR (w.day_type = 'workday' AND v_dow BETWEEN 1 AND 5)
OR (w.day_type = 'weekend' AND v_dow IN (0, 6))
)
AND w.rate_type = 'VT'
AND v_local_time >= w.window_from
AND v_local_time < w.window_to
) INTO v_is_vt;
ELSE
v_is_vt := false;
END IF;
v_rate_type := CASE WHEN v_is_vt THEN 'VT' ELSE 'NT' END;
IF v_tariff_id IS NOT NULL THEN
SELECT price_czk_kwh INTO v_dist_rate
FROM ems.distribution_tariff_rate
WHERE tariff_id = v_tariff_id
AND rate_type = v_rate_type
AND valid_from <= p_interval_start::DATE
AND (valid_to IS NULL OR valid_to > p_interval_start::DATE)
ORDER BY valid_from DESC
LIMIT 1;
END IF;
v_dist_rate := COALESCE(v_dist_rate, 0);
v_system_services := COALESCE(v_system_services, 0);
v_ote_fee := COALESCE(v_ote_fee, 0);
v_buy_margin_fixed := COALESCE(v_buy_margin_fixed, 0);
v_buy_margin_pct := COALESCE(v_buy_margin_pct, 0);
v_buy_margin := v_buy_margin_fixed + (v_spot_price * v_buy_margin_pct / 100.0);
v_vat_rate := COALESCE(v_vat_rate, 0.21);
RETURN ROUND(
(v_spot_price + v_dist_rate + v_system_services + v_ote_fee + v_buy_margin)
* (1 + v_vat_rate),
6
);
END;
$$;
COMMENT ON FUNCTION ems.fn_effective_buy_price(INT, TIMESTAMPTZ) IS
'Vrátí efektivní nákupní cenu elektřiny v Kč/kWh pro danou lokalitu a 15min interval.
Přičítá fixní a procentní nákupní marži dle aktuálně platné site_market_config.';
'Efektivní nákupní cena elektřiny Kč/kWh včetně DPH.
Složky: spot OTE + distribuce NT/VT (dle HDO) + systémové služby + OTE poplatek + marže (fix + % ze spotu).
DPH aplikováno na celou částku. Distribuce závisí na HDO kódu site.';
-- ------------------------------------------------------------
@@ -38,24 +129,86 @@ CREATE OR REPLACE FUNCTION ems.fn_effective_sell_price(
p_interval_start TIMESTAMPTZ
)
RETURNS NUMERIC(10,6)
LANGUAGE sql
LANGUAGE plpgsql
STABLE
AS $$
SELECT
mip.sell_raw_price_czk_kwh
+ smc.sell_margin_fixed_czk
+ (mip.sell_raw_price_czk_kwh * smc.sell_margin_percent / 100.0)
FROM ems.market_interval_price mip
CROSS JOIN ems.site_market_config smc
WHERE mip.market_source = 'OTE_CZ'
AND mip.interval_start = p_interval_start
AND smc.site_id = p_site_id
AND smc.valid_from <= p_interval_start
AND (smc.valid_to IS NULL OR smc.valid_to > p_interval_start)
ORDER BY smc.valid_from DESC
DECLARE
v_spot_price NUMERIC;
v_sell_margin_fixed NUMERIC;
v_sell_margin_pct NUMERIC;
BEGIN
SELECT sell_margin_fixed_czk, sell_margin_percent
INTO v_sell_margin_fixed, v_sell_margin_pct
FROM ems.site_market_config
WHERE site_id = p_site_id
AND valid_from <= p_interval_start
AND (valid_to IS NULL OR valid_to > p_interval_start)
ORDER BY valid_from DESC
LIMIT 1;
IF NOT FOUND THEN
RETURN NULL;
END IF;
SELECT sell_raw_price_czk_kwh INTO v_spot_price
FROM ems.market_interval_price
WHERE market_source IN ('OTE_CZ', 'OTE_CZ_DAM')
AND interval_start = p_interval_start
LIMIT 1;
IF v_spot_price IS NULL THEN
RETURN NULL;
END IF;
RETURN ROUND(
v_spot_price
+ COALESCE(v_sell_margin_fixed, 0)
+ (v_spot_price * COALESCE(v_sell_margin_pct, 0) / 100.0),
6
);
END;
$$;
COMMENT ON FUNCTION ems.fn_effective_sell_price(INT, TIMESTAMPTZ) IS
'Vrátí efektivní prodejní cenu elektřiny v Kč/kWh pro danou lokalitu a 15min interval.
Aplikuje fixní a procentní prodejní marži (záporná marže = srážka z prodejní ceny).';
'Efektivní prodejní cena elektřiny Kč/kWh bez DPH (neplátce DPH).
Složky: spot OTE + fixní/procentní prodejní marže (záporná = srážka).
Zelený bonus není součástí ceny počítá se z výroby přes fn_green_bonus_revenue().
Záporná hodnota = platíme za export (záporné spotové ceny).';
-- ------------------------------------------------------------
CREATE OR REPLACE FUNCTION ems.fn_green_bonus_revenue(
p_pv_array_id INT,
p_interval_start TIMESTAMPTZ,
p_production_wh NUMERIC
)
RETURNS NUMERIC
LANGUAGE plpgsql
STABLE
AS $$
DECLARE
v_bonus_rate NUMERIC;
BEGIN
SELECT green_bonus_czk_kwh INTO v_bonus_rate
FROM ems.asset_pv_array
WHERE id = p_pv_array_id
AND green_bonus_czk_kwh IS NOT NULL
AND green_bonus_valid_from <= p_interval_start::DATE
AND (green_bonus_valid_to IS NULL
OR green_bonus_valid_to > p_interval_start::DATE);
IF v_bonus_rate IS NULL OR p_production_wh IS NULL OR p_production_wh <= 0 THEN
RETURN 0;
END IF;
RETURN ROUND((p_production_wh / 1000.0) * v_bonus_rate, 6);
END;
$$;
COMMENT ON FUNCTION ems.fn_green_bonus_revenue(INT, TIMESTAMPTZ, NUMERIC) IS
'Příjem ze zeleného bonusu za výrobu FVE pole v daném intervalu.
Bonus plyne z celkové výroby bez ohledu na to kam energie šla
(interní spotřeba, baterie, EV, TČ i export do sítě).
Sazba se načítá dle platnosti (valid_from/valid_to) ročně aktualizovatelné.
Vrátí 0 pokud pole nemá zelený bonus nebo výroba je nulová.
Použití: SELECT ems.fn_green_bonus_revenue(pv_array_id, interval_start, production_wh);';