From 5b94f8baecfc484568b6695db47d4d3626b5090e Mon Sep 17 00:00:00 2001 From: Dusan Vojacek Date: Mon, 27 Apr 2026 18:42:06 +0200 Subject: [PATCH] fix prices reloading --- .../V066__site_market_config_validity_index.sql | 8 ++++++++ ..._064_fn_site_effective_prices_day_prague.sql | 9 ++++++++- frontend/src/hooks/useDashboardData.ts | 17 ++++++++++++----- 3 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 db/migration/V066__site_market_config_validity_index.sql diff --git a/db/migration/V066__site_market_config_validity_index.sql b/db/migration/V066__site_market_config_validity_index.sql new file mode 100644 index 0000000..20369ca --- /dev/null +++ b/db/migration/V066__site_market_config_validity_index.sql @@ -0,0 +1,8 @@ +-- ============================================================ +-- Site market config: urychlení lookupu platné konfigurace +-- (vw_site_effective_price, fn_effective_*_price) +-- ============================================================ + +create index if not exists idx_site_market_config_site_valid_from + on ems.site_market_config (site_id, valid_from desc); + diff --git a/db/routines/R__064_fn_site_effective_prices_day_prague.sql b/db/routines/R__064_fn_site_effective_prices_day_prague.sql index bbb52e0..93e8112 100644 --- a/db/routines/R__064_fn_site_effective_prices_day_prague.sql +++ b/db/routines/R__064_fn_site_effective_prices_day_prague.sql @@ -6,6 +6,11 @@ returns jsonb language sql stable as $fn$ + with bounds as ( + select + ((p_day::timestamp) at time zone 'Europe/Prague') as day_start_utc, + (((p_day + 1)::timestamp) at time zone 'Europe/Prague') as day_end_utc + ) select coalesce( jsonb_agg(u.j order by u.interval_start), '[]'::jsonb @@ -17,8 +22,10 @@ as $fn$ from ( select v.* from ems.vw_site_effective_price v + cross join bounds b where v.site_id = p_site_id - and (v.interval_start at time zone 'Europe/Prague')::date = p_day + and v.interval_start >= b.day_start_utc + and v.interval_start < b.day_end_utc order by v.interval_start ) t ) u; diff --git a/frontend/src/hooks/useDashboardData.ts b/frontend/src/hooks/useDashboardData.ts index a5dcb68..b7b0226 100644 --- a/frontend/src/hooks/useDashboardData.ts +++ b/frontend/src/hooks/useDashboardData.ts @@ -3,9 +3,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { getCurrentPlan, - getSitePrices, getForecastPvSlotsRangeCorrected, - type SiteEffectivePriceRowDto, } from '../api/backend' import { getJson } from '../api/postgrest' import { @@ -22,6 +20,7 @@ import type { HeatPumpLatestRow, ModeLogRecentRow, SiteStatusRow, + SiteEffectivePriceRow, Telemetry15m7dRow, } from '../types/ems' import type { PlanningIntervalDto } from '../types/plan' @@ -197,7 +196,7 @@ export function useDashboardData(siteId: number | null) { auditHourly, modeLog, hpArr, - ...priceLists + priceRows, ] = await Promise.all([ getCurrentPlan(siteId).catch((e: unknown) => { if (axios.isAxiosError(e) && e.response?.status === 404) { @@ -221,7 +220,15 @@ export function useDashboardData(siteId: number | null) { limit: '200', }), getJson('/vw_latest_heat_pump', { site_id: `eq.${siteId}` }), - ...[...dates].map((d) => getSitePrices(siteId, d)), + // Ceny bereme v jednom range dotazu přes PostgREST view (místo N× /api/v1/sites/{id}/prices?date=...). + // Okno: [windowStart, windowStart + TOTAL_SLOTS) pro mapování na sloty. + getJson('/vw_site_effective_price', { + site_id: `eq.${siteId}`, + interval_start: `gte.${new Date(windowStart).toISOString()}`, + interval_end: `lt.${new Date(windowStart + TOTAL_SLOTS * SLOT_MS).toISOString()}`, + order: 'interval_start.asc', + limit: String(TOTAL_SLOTS + 32), + }), ]) const status = Array.isArray(statusArr) && statusArr[0] ? statusArr[0]! : null @@ -235,7 +242,7 @@ export function useDashboardData(siteId: number | null) { } const priceBySlot = new Map() - const flatPrices: SiteEffectivePriceRowDto[] = priceLists.flat() as SiteEffectivePriceRowDto[] + const flatPrices: SiteEffectivePriceRow[] = Array.isArray(priceRows) ? priceRows : [] for (const r of flatPrices) { const k = slotTimeKey(new Date(r.interval_start).getTime()) priceBySlot.set(k, {