From f7d3162eb7a43345e6a2d763c60208a2d8713900 Mon Sep 17 00:00:00 2001 From: Dusan Vojacek Date: Sun, 12 Apr 2026 20:55:10 +0200 Subject: [PATCH] fix forecast graf --- backend/app/main.py | 8 ++++- frontend/src/hooks/useDashboardData.ts | 41 ++++++++++++++++---------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/backend/app/main.py b/backend/app/main.py index abb72e3..45ed8e0 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1025,7 +1025,13 @@ async def get_site_forecast_pv( JOIN ems.asset_pv_array apa ON apa.id = fpr.pv_array_id AND apa.site_id = fpr.site_id WHERE fpr.site_id = $1 - AND fpi.interval_start::date = $2::date + AND ( + fpi.interval_start + AT TIME ZONE COALESCE( + (SELECT timezone FROM ems.site WHERE id = $1), + 'Europe/Prague' + ) + )::date = $2::date AND fpr.status = 'ok' ORDER BY fpi.interval_start, fpr.pv_array_id, fpr.created_at DESC ) latest diff --git a/frontend/src/hooks/useDashboardData.ts b/frontend/src/hooks/useDashboardData.ts index 25c0cf6..4c3b73e 100644 --- a/frontend/src/hooks/useDashboardData.ts +++ b/frontend/src/hooks/useDashboardData.ts @@ -244,22 +244,20 @@ export function useDashboardData(siteId: number | null) { const forecastBySlot = new Map() const forecastDays: ForecastDayTotal[] = [] - const today = todayPrague + const weekDates = Array.from({ length: 7 }, (_, d) => pragueAddCalendarDays(todayPrague, d)) + const forecastFetchDates = [...new Set([...dates, ...weekDates])].sort() const forecastResults = await Promise.all( - Array.from({ length: 7 }, (_, d) => { - const ymd = pragueAddCalendarDays(today, d) - return getSiteForecastPv(siteId, ymd) + forecastFetchDates.map((ymd) => + getSiteForecastPv(siteId, ymd) .then((fc) => ({ ymd, fc })) - .catch(() => ({ ymd, fc: null as Awaited> | null })) - }), + .catch(() => ({ ymd, fc: null as Awaited> | null })), + ), ) - for (const { ymd, fc } of forecastResults) { - if (!fc) { - forecastDays.push({ date: ymd, label: ymd, kwh: 0 }) - continue - } - let kwh = 0 - const byStart = new Map() + const forecastByYmd = new Map(forecastResults.map((r) => [r.ymd, r.fc])) + const addForecastToByStart = ( + fc: NonNullable>>, + byStart: Map, + ) => { for (const x of fc.pv_a ?? []) { const t = new Date(x.interval_start).getTime() const p = Number(x.power_w ?? 0) @@ -274,12 +272,23 @@ export function useDashboardData(siteId: number | null) { cur.b += p byStart.set(slotTimeKey(t), cur) } + } + for (const { fc } of forecastResults) { + if (!fc) continue + addForecastToByStart(fc, forecastBySlot) + } + for (const ymd of weekDates) { + const fc = forecastByYmd.get(ymd) ?? null + if (!fc) { + forecastDays.push({ date: ymd, label: ymd, kwh: 0 }) + continue + } + const byStart = new Map() + addForecastToByStart(fc, byStart) + let kwh = 0 for (const [, v] of byStart) { kwh += ((v.a + v.b) * 0.25) / 1000 } - for (const [k, v] of byStart) { - forecastBySlot.set(k, v) - } const label = new Date(ymd + 'T12:00:00Z').toLocaleDateString('cs-CZ', { weekday: 'short', day: 'numeric',