feat(dashboard): add metering data overview endpoint for user dashboard
This commit is contained in:
parent
5ff22e53bd
commit
765cbb0ec7
@ -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.api.dto.DashboardStatsDto;
|
||||||
import at.mueller.eeg.backend.dashboard.service.DashboardService;
|
import at.mueller.eeg.backend.dashboard.service.DashboardService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ -30,4 +33,14 @@ public class DashboardController {
|
|||||||
public ResponseEntity<DashboardStatsDto.UserStats> getUserDashboard(@CurrentUserId String userId) {
|
public ResponseEntity<DashboardStatsDto.UserStats> getUserDashboard(@CurrentUserId String userId) {
|
||||||
return ResponseEntity.ok(dashboardService.getUserStats(UUID.fromString(userId)));
|
return ResponseEntity.ok(dashboardService.getUserStats(UUID.fromString(userId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/user/metering-data/overview")
|
||||||
|
@PreAuthorize("hasRole('MEMBER')")
|
||||||
|
public ResponseEntity<DashboardStatsDto.MeteringDataOverview> 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,12 @@
|
|||||||
package at.mueller.eeg.backend.dashboard.api.dto;
|
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 {
|
public interface DashboardStatsDto {
|
||||||
record AdminStats(
|
record AdminStats(
|
||||||
long totalCommunities,
|
long totalCommunities,
|
||||||
@ -13,4 +20,21 @@ public interface DashboardStatsDto {
|
|||||||
long activeMemberships,
|
long activeMemberships,
|
||||||
long pendingMemberships
|
long pendingMemberships
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
record MeteringDataOverview(
|
||||||
|
List<MeteringPointSummary> meteringPoints,
|
||||||
|
List<TimeSeriesEntry> timeSeries
|
||||||
|
) {}
|
||||||
|
|
||||||
|
record MeteringPointSummary(
|
||||||
|
UUID id,
|
||||||
|
String atNumber,
|
||||||
|
PointType type,
|
||||||
|
double totalKwh
|
||||||
|
) {}
|
||||||
|
|
||||||
|
record TimeSeriesEntry(
|
||||||
|
LocalDateTime timestamp,
|
||||||
|
Map<String, Double> values
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,10 @@
|
|||||||
package at.mueller.eeg.backend.dashboard.service;
|
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.domain.MembershipStatus;
|
||||||
import at.mueller.eeg.backend.community.repository.EnergyCommunityRepository;
|
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.MembershipRepository;
|
||||||
import at.mueller.eeg.backend.community.repository.MeteringPointRepository;
|
import at.mueller.eeg.backend.community.repository.MeteringPointRepository;
|
||||||
import at.mueller.eeg.backend.dashboard.api.dto.DashboardStatsDto;
|
import at.mueller.eeg.backend.dashboard.api.dto.DashboardStatsDto;
|
||||||
@ -11,7 +14,12 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
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
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ -22,6 +30,7 @@ public class DashboardService {
|
|||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
private final MembershipRepository membershipRepository;
|
private final MembershipRepository membershipRepository;
|
||||||
private final MeteringPointRepository meteringPointRepository;
|
private final MeteringPointRepository meteringPointRepository;
|
||||||
|
private final MeteringDataRepository meteringDataRepository;
|
||||||
|
|
||||||
public DashboardStatsDto.AdminStats getAdminStats() {
|
public DashboardStatsDto.AdminStats getAdminStats() {
|
||||||
long communities = energyCommunityRepository.count();
|
long communities = energyCommunityRepository.count();
|
||||||
@ -39,4 +48,47 @@ public class DashboardService {
|
|||||||
|
|
||||||
return new DashboardStatsDto.UserStats(meteringPoints, activeMemberships, pendingMemberships);
|
return new DashboardStatsDto.UserStats(meteringPoints, activeMemberships, pendingMemberships);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DashboardStatsDto.MeteringDataOverview getMeteringDataOverview(UUID userId, LocalDateTime from, LocalDateTime to) {
|
||||||
|
List<MeteringPoint> meteringPoints = meteringPointRepository.findAllByUserId(userId);
|
||||||
|
|
||||||
|
List<DashboardStatsDto.MeteringPointSummary> summaries = new ArrayList<>();
|
||||||
|
Map<String, Map<LocalDate, Double>> dailyData = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
for (MeteringPoint mp : meteringPoints) {
|
||||||
|
List<MeteringData> 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<LocalDate> allDays = dailyData.values().stream()
|
||||||
|
.flatMap(m -> m.keySet().stream())
|
||||||
|
.collect(Collectors.toCollection(TreeSet::new));
|
||||||
|
|
||||||
|
List<DashboardStatsDto.TimeSeriesEntry> timeSeries = allDays.stream()
|
||||||
|
.map(day -> {
|
||||||
|
Map<String, Double> 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user