second version
This commit is contained in:
@@ -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);';
|
||||
|
||||
Reference in New Issue
Block a user