diff --git a/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/api/DashboardController.java b/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/api/DashboardController.java index 25d1a61..51e2a6b 100644 --- a/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/api/DashboardController.java +++ b/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/api/DashboardController.java @@ -4,12 +4,15 @@ import at.mueller.eeg.backend.common.security.CurrentUserId; import at.mueller.eeg.backend.dashboard.api.dto.DashboardStatsDto; import at.mueller.eeg.backend.dashboard.service.DashboardService; import lombok.RequiredArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.time.LocalDateTime; import java.util.UUID; @RestController @@ -30,4 +33,14 @@ public class DashboardController { public ResponseEntity getUserDashboard(@CurrentUserId String userId) { return ResponseEntity.ok(dashboardService.getUserStats(UUID.fromString(userId))); } + + @GetMapping("/user/metering-data/overview") + @PreAuthorize("hasRole('MEMBER')") + public ResponseEntity getMeteringDataOverview( + @CurrentUserId String userId, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime from, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime to) { + return ResponseEntity.ok(dashboardService.getMeteringDataOverview( + UUID.fromString(userId), from, to)); + } } \ No newline at end of file diff --git a/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/api/dto/DashboardStatsDto.java b/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/api/dto/DashboardStatsDto.java index ed00399..395932f 100644 --- a/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/api/dto/DashboardStatsDto.java +++ b/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/api/dto/DashboardStatsDto.java @@ -1,5 +1,12 @@ package at.mueller.eeg.backend.dashboard.api.dto; +import at.mueller.eeg.backend.community.domain.PointType; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.UUID; + public interface DashboardStatsDto { record AdminStats( long totalCommunities, @@ -13,4 +20,21 @@ public interface DashboardStatsDto { long activeMemberships, long pendingMemberships ) {} + + record MeteringDataOverview( + List meteringPoints, + List timeSeries + ) {} + + record MeteringPointSummary( + UUID id, + String atNumber, + PointType type, + double totalKwh + ) {} + + record TimeSeriesEntry( + LocalDateTime timestamp, + Map values + ) {} } \ No newline at end of file diff --git a/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/service/DashboardService.java b/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/service/DashboardService.java index eb814bc..e469261 100644 --- a/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/service/DashboardService.java +++ b/eeg_backend/src/main/java/at/mueller/eeg/backend/dashboard/service/DashboardService.java @@ -1,7 +1,10 @@ package at.mueller.eeg.backend.dashboard.service; +import at.mueller.eeg.backend.community.domain.MeteringData; +import at.mueller.eeg.backend.community.domain.MeteringPoint; import at.mueller.eeg.backend.community.domain.MembershipStatus; import at.mueller.eeg.backend.community.repository.EnergyCommunityRepository; +import at.mueller.eeg.backend.community.repository.MeteringDataRepository; import at.mueller.eeg.backend.community.repository.MembershipRepository; import at.mueller.eeg.backend.community.repository.MeteringPointRepository; import at.mueller.eeg.backend.dashboard.api.dto.DashboardStatsDto; @@ -11,7 +14,12 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.UUID; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -22,6 +30,7 @@ public class DashboardService { private final UserRepository userRepository; private final MembershipRepository membershipRepository; private final MeteringPointRepository meteringPointRepository; + private final MeteringDataRepository meteringDataRepository; public DashboardStatsDto.AdminStats getAdminStats() { long communities = energyCommunityRepository.count(); @@ -39,4 +48,47 @@ public class DashboardService { return new DashboardStatsDto.UserStats(meteringPoints, activeMemberships, pendingMemberships); } + + public DashboardStatsDto.MeteringDataOverview getMeteringDataOverview(UUID userId, LocalDateTime from, LocalDateTime to) { + List meteringPoints = meteringPointRepository.findAllByUserId(userId); + + List summaries = new ArrayList<>(); + Map> dailyData = new LinkedHashMap<>(); + + for (MeteringPoint mp : meteringPoints) { + List data = meteringDataRepository.findByMeteringPointIdAndIntervalStartBetween(mp.getId(), from, to); + + double totalKwh = data.stream().mapToDouble(MeteringData::getKwh).sum(); + summaries.add(new DashboardStatsDto.MeteringPointSummary( + mp.getId(), + mp.getAtNumber(), + mp.getType(), + totalKwh + )); + + for (MeteringData d : data) { + LocalDate day = d.getIntervalStart().toLocalDate(); + dailyData.computeIfAbsent(mp.getAtNumber(), k -> new LinkedHashMap<>()) + .merge(day, d.getKwh(), Double::sum); + } + } + + Set allDays = dailyData.values().stream() + .flatMap(m -> m.keySet().stream()) + .collect(Collectors.toCollection(TreeSet::new)); + + List timeSeries = allDays.stream() + .map(day -> { + Map values = new LinkedHashMap<>(); + for (MeteringPoint mp : meteringPoints) { + values.put(mp.getAtNumber(), + dailyData.getOrDefault(mp.getAtNumber(), Collections.emptyMap()) + .getOrDefault(day, 0.0)); + } + return new DashboardStatsDto.TimeSeriesEntry(day.atStartOfDay(), values); + }) + .toList(); + + return new DashboardStatsDto.MeteringDataOverview(summaries, timeSeries); + } } \ No newline at end of file