fix repeatable migrations
This commit is contained in:
148
db/routines/R__037_fn_planning_run_commit.sql
Normal file
148
db/routines/R__037_fn_planning_run_commit.sql
Normal file
@@ -0,0 +1,148 @@
|
||||
-- uložení planning_run + planning_interval v jedné transakci
|
||||
|
||||
create or replace function ems.fn_planning_run_commit(
|
||||
p_site_id int,
|
||||
p_horizon_start timestamptz,
|
||||
p_horizon_end timestamptz,
|
||||
p_run_meta jsonb,
|
||||
p_intervals jsonb
|
||||
)
|
||||
returns int
|
||||
language plpgsql
|
||||
as $fn$
|
||||
declare
|
||||
v_run_id int;
|
||||
r record;
|
||||
v_has_slot_inputs boolean;
|
||||
begin
|
||||
v_has_slot_inputs := coalesce(
|
||||
(jsonb_typeof(p_intervals) = 'array' and jsonb_array_length(p_intervals) > 0
|
||||
and (p_intervals->0) ? 'load_baseline_w'),
|
||||
false
|
||||
);
|
||||
insert into ems.planning_run (
|
||||
site_id, horizon_start, horizon_end, status,
|
||||
run_type, triggered_by, replan_from,
|
||||
soc_at_replan_wh, solver_duration_ms, forecast_correction_factor
|
||||
) values (
|
||||
p_site_id,
|
||||
p_horizon_start,
|
||||
p_horizon_end,
|
||||
'draft',
|
||||
nullif(trim(p_run_meta->>'run_type'), ''),
|
||||
nullif(trim(p_run_meta->>'triggered_by'), ''),
|
||||
case
|
||||
when p_run_meta ? 'replan_from' and (p_run_meta->>'replan_from') is not null
|
||||
and (p_run_meta->>'replan_from') <> 'null'
|
||||
then (p_run_meta->>'replan_from')::timestamptz
|
||||
else null::timestamptz
|
||||
end,
|
||||
(p_run_meta->>'soc_at_replan_wh')::numeric,
|
||||
(p_run_meta->>'solver_duration_ms')::int,
|
||||
(p_run_meta->>'forecast_correction_factor')::numeric
|
||||
)
|
||||
returning id into v_run_id;
|
||||
|
||||
for r in select * from jsonb_array_elements(p_intervals) as elem(value)
|
||||
loop
|
||||
if v_has_slot_inputs then
|
||||
insert into ems.planning_interval (
|
||||
run_id, interval_start,
|
||||
battery_setpoint_w, battery_soc_target_pct,
|
||||
grid_setpoint_w,
|
||||
ev1_setpoint_w, ev2_setpoint_w, ev1_via_bat_w, ev2_via_bat_w,
|
||||
heat_pump_enabled, heat_pump_setpoint_w,
|
||||
pv_a_curtailed_w, expected_cost_czk,
|
||||
effective_buy_price, effective_sell_price,
|
||||
is_predicted_price,
|
||||
load_baseline_w,
|
||||
pv_a_forecast_raw_w, pv_b_forecast_raw_w,
|
||||
pv_a_forecast_solver_w, pv_b_forecast_solver_w
|
||||
) values (
|
||||
v_run_id,
|
||||
(r.value->>'interval_start')::timestamptz,
|
||||
(r.value->>'battery_setpoint_w')::int,
|
||||
(r.value->>'battery_soc_target_pct')::numeric,
|
||||
(r.value->>'grid_setpoint_w')::int,
|
||||
nullif(r.value->>'ev1_setpoint_w', '')::int,
|
||||
nullif(r.value->>'ev2_setpoint_w', '')::int,
|
||||
coalesce((r.value->>'ev1_via_bat_w')::int, 0),
|
||||
coalesce((r.value->>'ev2_via_bat_w')::int, 0),
|
||||
coalesce((r.value->>'heat_pump_enabled')::boolean, false),
|
||||
(r.value->>'heat_pump_setpoint_w')::int,
|
||||
(r.value->>'pv_a_curtailed_w')::int,
|
||||
(r.value->>'expected_cost_czk')::numeric,
|
||||
(r.value->>'effective_buy_price')::numeric,
|
||||
(r.value->>'effective_sell_price')::numeric,
|
||||
coalesce((r.value->>'is_predicted_price')::boolean, false),
|
||||
(r.value->>'load_baseline_w')::int,
|
||||
(r.value->>'pv_a_forecast_raw_w')::int,
|
||||
(r.value->>'pv_b_forecast_raw_w')::int,
|
||||
(r.value->>'pv_a_forecast_solver_w')::int,
|
||||
(r.value->>'pv_b_forecast_solver_w')::int
|
||||
);
|
||||
else
|
||||
insert into ems.planning_interval (
|
||||
run_id, interval_start,
|
||||
battery_setpoint_w, battery_soc_target_pct,
|
||||
grid_setpoint_w,
|
||||
ev1_setpoint_w, ev2_setpoint_w, ev1_via_bat_w, ev2_via_bat_w,
|
||||
heat_pump_enabled, heat_pump_setpoint_w,
|
||||
pv_a_curtailed_w, expected_cost_czk,
|
||||
effective_buy_price, effective_sell_price,
|
||||
is_predicted_price
|
||||
) values (
|
||||
v_run_id,
|
||||
(r.value->>'interval_start')::timestamptz,
|
||||
(r.value->>'battery_setpoint_w')::int,
|
||||
(r.value->>'battery_soc_target_pct')::numeric,
|
||||
(r.value->>'grid_setpoint_w')::int,
|
||||
nullif(r.value->>'ev1_setpoint_w', '')::int,
|
||||
nullif(r.value->>'ev2_setpoint_w', '')::int,
|
||||
coalesce((r.value->>'ev1_via_bat_w')::int, 0),
|
||||
coalesce((r.value->>'ev2_via_bat_w')::int, 0),
|
||||
coalesce((r.value->>'heat_pump_enabled')::boolean, false),
|
||||
(r.value->>'heat_pump_setpoint_w')::int,
|
||||
(r.value->>'pv_a_curtailed_w')::int,
|
||||
(r.value->>'expected_cost_czk')::numeric,
|
||||
(r.value->>'effective_buy_price')::numeric,
|
||||
(r.value->>'effective_sell_price')::numeric,
|
||||
coalesce((r.value->>'is_predicted_price')::boolean, false)
|
||||
);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
update ems.planning_run
|
||||
set status = 'superseded'
|
||||
where site_id = p_site_id
|
||||
and status = 'active'
|
||||
and id <> v_run_id;
|
||||
|
||||
update ems.planning_run
|
||||
set status = 'active'
|
||||
where id = v_run_id;
|
||||
|
||||
return v_run_id;
|
||||
end;
|
||||
$fn$;
|
||||
|
||||
create or replace function ems.fn_forecast_correction_log_insert(
|
||||
p_site_id int,
|
||||
p_window_start timestamptz,
|
||||
p_window_end timestamptz,
|
||||
p_actual_pv_wh numeric,
|
||||
p_forecast_pv_wh numeric,
|
||||
p_correction_factor numeric,
|
||||
p_applied_to_run_id int
|
||||
)
|
||||
returns void
|
||||
language sql
|
||||
as $fn$
|
||||
insert into ems.forecast_correction_log (
|
||||
site_id, window_start, window_end,
|
||||
actual_pv_wh, forecast_pv_wh, correction_factor, applied_to_run_id
|
||||
) values (
|
||||
p_site_id, p_window_start, p_window_end,
|
||||
p_actual_pv_wh, p_forecast_pv_wh, p_correction_factor, p_applied_to_run_id
|
||||
);
|
||||
$fn$;
|
||||
Reference in New Issue
Block a user