@@ -636,13 +636,50 @@ def dashboard(
636636 and c.efficiency is not null
637637 then (((d.start_rated_range_km - d.end_rated_range_km) * c.efficiency) / d.distance * 100)::float8
638638 else null
639- end as estimated_kwh_per_100km
639+ end as estimated_kwh_per_100km,
640+ coalesce(route.route_points, '[]'::jsonb) as route_points
640641 from public.drives d
641642 join public.cars c on c.id = d.car_id
642643 left join public.addresses sa on sa.id = d.start_address_id
643644 left join public.addresses ea on ea.id = d.end_address_id
644645 left join public.geofences sg on sg.id = d.start_geofence_id
645646 left join public.geofences eg on eg.id = d.end_geofence_id
647+ left join lateral (
648+ select jsonb_agg(
649+ jsonb_build_object(
650+ 'sampled_at', sampled.date,
651+ 'latitude', sampled.latitude::float8,
652+ 'longitude', sampled.longitude::float8,
653+ 'speed', sampled.speed,
654+ 'power', sampled.power,
655+ 'battery_level', sampled.battery_level
656+ )
657+ order by sampled.date
658+ ) as route_points
659+ from (
660+ select date, latitude, longitude, speed, power, battery_level
661+ from (
662+ select
663+ p.date,
664+ p.latitude,
665+ p.longitude,
666+ p.speed,
667+ p.power,
668+ p.battery_level,
669+ (row_number() over (order by p.date))::int as rn,
670+ (count(*) over ())::int as total
671+ from public.positions p
672+ where p.drive_id = d.id
673+ and p.latitude is not null
674+ and p.longitude is not null
675+ ) ranked
676+ where total <= 160
677+ or rn = 1
678+ or rn = total
679+ or ((rn - 1) %% greatest(1, ceil(total / 160.0)::int)) = 0
680+ order by date
681+ ) sampled
682+ ) route on true
646683 where d.car_id = %s
647684 and (%s::timestamp is null or d.start_date >= %s::timestamp)
648685 and d.start_date <= %s::timestamp
@@ -724,7 +761,8 @@ def dashboard(
724761 ch.latest_charge_at,
725762 ch.max_power_kw,
726763 ch.fast_charger,
727- ({ active_charge_condition ()} )::bool as is_active
764+ ({ active_charge_condition ()} )::bool as is_active,
765+ coalesce(charge_samples.samples, '[]'::jsonb) as samples
728766 from public.charging_processes cp
729767 left join public.addresses a on a.id = cp.address_id
730768 left join public.geofences g on g.id = cp.geofence_id
@@ -745,6 +783,47 @@ def dashboard(
745783 order by date desc
746784 limit 1
747785 ) latest on true
786+ left join lateral (
787+ select jsonb_agg(
788+ jsonb_build_object(
789+ 'sampled_at', sampled.date,
790+ 'minute', extract(epoch from (sampled.date - cp.start_date)) / 60.0,
791+ 'charger_power_kw', sampled.charger_power,
792+ 'battery_level', sampled.battery_level,
793+ 'charge_energy_added_kwh', sampled.charge_energy_added::float8,
794+ 'charger_voltage', sampled.charger_voltage,
795+ 'charger_actual_current', sampled.charger_actual_current
796+ )
797+ order by sampled.date
798+ ) as samples
799+ from (
800+ select
801+ date,
802+ charger_power,
803+ battery_level,
804+ charge_energy_added,
805+ charger_voltage,
806+ charger_actual_current
807+ from (
808+ select
809+ c.date,
810+ c.charger_power,
811+ c.battery_level,
812+ c.charge_energy_added,
813+ c.charger_voltage,
814+ c.charger_actual_current,
815+ (row_number() over (order by c.date))::int as rn,
816+ (count(*) over ())::int as total
817+ from public.charges c
818+ where c.charging_process_id = cp.id
819+ ) ranked
820+ where total <= 160
821+ or rn = 1
822+ or rn = total
823+ or ((rn - 1) %% greatest(1, ceil(total / 160.0)::int)) = 0
824+ order by date
825+ ) sampled
826+ ) charge_samples on true
748827 left join lateral (
749828 select date as latest_seen_at
750829 from public.positions
0 commit comments