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 JOIN ems.asset_pv_array apa
ON apa.id = fpr.pv_array_id AND apa.site_id = fpr.site_id ON apa.id = fpr.pv_array_id AND apa.site_id = fpr.site_id
WHERE fpr.site_id = $1 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' AND fpr.status = 'ok'
ORDER BY fpi.interval_start, fpr.pv_array_id, fpr.created_at DESC ORDER BY fpi.interval_start, fpr.pv_array_id, fpr.created_at DESC
) latest ) latest

View File

@@ -244,22 +244,20 @@ export function useDashboardData(siteId: number | null) {
const forecastBySlot = new Map<string, { a: number; b: number }>() const forecastBySlot = new Map<string, { a: number; b: number }>()
const forecastDays: ForecastDayTotal[] = [] 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( const forecastResults = await Promise.all(
Array.from({ length: 7 }, (_, d) => { forecastFetchDates.map((ymd) =>
const ymd = pragueAddCalendarDays(today, d) getSiteForecastPv(siteId, ymd)
return getSiteForecastPv(siteId, ymd)
.then((fc) => ({ ymd, fc })) .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) { const forecastByYmd = new Map(forecastResults.map((r) => [r.ymd, r.fc]))
if (!fc) { const addForecastToByStart = (
forecastDays.push({ date: ymd, label: ymd, kwh: 0 }) fc: NonNullable<Awaited<ReturnType<typeof getSiteForecastPv>>>,
continue byStart: Map<string, { a: number; b: number }>,
} ) => {
let kwh = 0
const byStart = new Map<string, { a: number; b: number }>()
for (const x of fc.pv_a ?? []) { for (const x of fc.pv_a ?? []) {
const t = new Date(x.interval_start).getTime() const t = new Date(x.interval_start).getTime()
const p = Number(x.power_w ?? 0) const p = Number(x.power_w ?? 0)
@@ -274,12 +272,23 @@ export function useDashboardData(siteId: number | null) {
cur.b += p cur.b += p
byStart.set(slotTimeKey(t), cur) 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) { for (const [, v] of byStart) {
kwh += ((v.a + v.b) * 0.25) / 1000 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', { const label = new Date(ymd + 'T12:00:00Z').toLocaleDateString('cs-CZ', {
weekday: 'short', weekday: 'short',
day: 'numeric', day: 'numeric',