fix forecast graf
All checks were successful
deploy / deploy (push) Successful in 1m30s
test / smoke-test (push) Successful in 7s

This commit is contained in:
Dusan Vojacek
2026-04-12 20:55:10 +02:00
parent 3066a82265
commit f7d3162eb7
2 changed files with 32 additions and 17 deletions

View File

@@ -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

View File

@@ -244,22 +244,20 @@ export function useDashboardData(siteId: number | null) {
const forecastBySlot = new Map<string, { a: number; b: number }>()
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<ReturnType<typeof getSiteForecastPv>> | null }))
}),
.catch(() => ({ ymd, fc: null as Awaited<ReturnType<typeof getSiteForecastPv>> | 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<string, { a: number; b: number }>()
const forecastByYmd = new Map(forecastResults.map((r) => [r.ymd, r.fc]))
const addForecastToByStart = (
fc: NonNullable<Awaited<ReturnType<typeof getSiteForecastPv>>>,
byStart: Map<string, { a: number; b: number }>,
) => {
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<string, { a: number; b: number }>()
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',