Skip to content

Commit 1b309f0

Browse files
committed
Implemented endpoint to get consumption by supply hourly
1 parent 94b5ab8 commit 1b309f0

File tree

9 files changed

+464
-0
lines changed

9 files changed

+464
-0
lines changed

src/main/java/org/lucoenergia/conluz/domain/consumption/datadis/get/GetDatadisConsumptionRepository.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,15 @@ public interface GetDatadisConsumptionRepository {
2222
*/
2323
List<DatadisConsumption> getDailyConsumptionsByRangeOfDates(@NotNull Supply supply,
2424
@NotNull OffsetDateTime startDate, @NotNull OffsetDateTime endDate);
25+
26+
/**
27+
* Retrieves a list of hourly consumption data within a specified date range for the given supply.
28+
*
29+
* @param supply the supply for which the consumption data is retrieved, must not be null
30+
* @param startDate the start date of the range, inclusive, must not be null
31+
* @param endDate the end date of the range, inclusive, must not be null
32+
* @return a list of {@code DatadisConsumption} objects representing hourly consumption data within the specified date range
33+
*/
34+
List<DatadisConsumption> getHourlyConsumptionsByRangeOfDates(@NotNull Supply supply,
35+
@NotNull OffsetDateTime startDate, @NotNull OffsetDateTime endDate);
2536
}

src/main/java/org/lucoenergia/conluz/domain/consumption/datadis/get/GetDatadisConsumptionService.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,17 @@ public interface GetDatadisConsumptionService {
2424
List<DatadisConsumption> getDailyConsumptionBySupply(@NotNull SupplyId supplyId,
2525
@NotNull OffsetDateTime startDate,
2626
@NotNull OffsetDateTime endDate);
27+
28+
/**
29+
* Retrieves hourly consumption data for a specific supply within a date range.
30+
* Access is restricted based on user role and ownership.
31+
*
32+
* @param supplyId the supply ID for which to retrieve consumption data
33+
* @param startDate the start date of the range, inclusive
34+
* @param endDate the end date of the range, inclusive
35+
* @return a list of hourly consumption data
36+
*/
37+
List<DatadisConsumption> getHourlyConsumptionBySupply(@NotNull SupplyId supplyId,
38+
@NotNull OffsetDateTime startDate,
39+
@NotNull OffsetDateTime endDate);
2740
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.lucoenergia.conluz.infrastructure.admin.supply.consumption;
2+
3+
import io.swagger.v3.oas.annotations.Operation;
4+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
5+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
6+
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
7+
import org.lucoenergia.conluz.domain.consumption.datadis.DatadisConsumption;
8+
import org.lucoenergia.conluz.domain.consumption.datadis.get.GetDatadisConsumptionService;
9+
import org.lucoenergia.conluz.domain.shared.SupplyId;
10+
import org.lucoenergia.conluz.infrastructure.shared.web.apidocs.ApiTag;
11+
import org.lucoenergia.conluz.infrastructure.shared.web.apidocs.response.BadRequestErrorResponse;
12+
import org.lucoenergia.conluz.infrastructure.shared.web.apidocs.response.ForbiddenErrorResponse;
13+
import org.lucoenergia.conluz.infrastructure.shared.web.apidocs.response.InternalServerErrorResponse;
14+
import org.lucoenergia.conluz.infrastructure.shared.web.apidocs.response.NotFoundErrorResponse;
15+
import org.lucoenergia.conluz.infrastructure.shared.web.apidocs.response.UnauthorizedErrorResponse;
16+
import org.springframework.format.annotation.DateTimeFormat;
17+
import org.springframework.security.access.prepost.PreAuthorize;
18+
import org.springframework.web.bind.annotation.GetMapping;
19+
import org.springframework.web.bind.annotation.PathVariable;
20+
import org.springframework.web.bind.annotation.RequestMapping;
21+
import org.springframework.web.bind.annotation.RequestParam;
22+
import org.springframework.web.bind.annotation.RestController;
23+
24+
import java.time.OffsetDateTime;
25+
import java.util.List;
26+
import java.util.UUID;
27+
28+
/**
29+
* Controller for retrieving hourly consumption data for a specific supply
30+
*/
31+
@RestController
32+
@RequestMapping("/api/v1/supplies/{id}/consumption/hourly")
33+
public class GetSupplyHourlyConsumptionController {
34+
35+
private final GetDatadisConsumptionService getDatadisConsumptionService;
36+
37+
public GetSupplyHourlyConsumptionController(GetDatadisConsumptionService getDatadisConsumptionService) {
38+
this.getDatadisConsumptionService = getDatadisConsumptionService;
39+
}
40+
41+
@GetMapping
42+
@Operation(
43+
summary = "Retrieves hourly consumption data for a specific supply",
44+
description = """
45+
This endpoint retrieves hourly consumption data from Datadis for a specific supply within a given date range.
46+
47+
**Authorization Rules:**
48+
- Users with role ADMIN can retrieve consumption data for any supply
49+
- Users with role PARTNER can only retrieve consumption data for their own supplies
50+
51+
The consumption data includes:
52+
- Total consumption in kWh
53+
- Surplus energy (energy sent to grid)
54+
- Self-consumption energy
55+
- Obtain method (Real/Estimated)
56+
57+
Data is aggregated by hour within the specified date range.
58+
""",
59+
tags = ApiTag.SUPPLIES,
60+
operationId = "getSupplyHourlyConsumption",
61+
security = @SecurityRequirement(name = "bearerToken")
62+
)
63+
@ApiResponses(value = {
64+
@ApiResponse(
65+
responseCode = "200",
66+
description = "Consumption data retrieved successfully",
67+
useReturnTypeSchema = true
68+
)
69+
})
70+
@BadRequestErrorResponse
71+
@InternalServerErrorResponse
72+
@UnauthorizedErrorResponse
73+
@ForbiddenErrorResponse
74+
@NotFoundErrorResponse
75+
@PreAuthorize("isAuthenticated()")
76+
public List<DatadisConsumption> getSupplyHourlyConsumption(
77+
@PathVariable("id") UUID id,
78+
@RequestParam("startDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime startDate,
79+
@RequestParam("endDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime endDate) {
80+
81+
return getDatadisConsumptionService.getHourlyConsumptionBySupply(SupplyId.of(id), startDate, endDate);
82+
}
83+
}

src/main/java/org/lucoenergia/conluz/infrastructure/consumption/datadis/get/GetDatadisConsumptionRepositoryInflux.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,37 @@ GROUP BY time(%s), cups
8686
}
8787
}
8888

89+
@Override
90+
public List<DatadisConsumption> getHourlyConsumptionsByRangeOfDates(Supply supply, OffsetDateTime startDate, OffsetDateTime endDate) {
91+
try (InfluxDB connection = influxDbConnectionManager.getConnection()) {
92+
93+
Query query = new Query(String.format(
94+
"""
95+
SELECT
96+
SUM("consumption_kwh") AS "consumption_kwh",
97+
SUM("surplus_energy_kwh") AS "surplus_energy_kwh",
98+
SUM("self_consumption_energy_kwh") AS "self_consumption_energy_kwh",
99+
LAST("obtain_method") AS "obtain_method"
100+
FROM "%s"
101+
WHERE cups = '%s'
102+
AND time >= '%s'
103+
AND time <= '%s'
104+
GROUP BY time(%s), cups
105+
""",
106+
DatadisConfigEntity.CONSUMPTION_KWH_MEASUREMENT,
107+
supply.getCode(),
108+
dateConverter.convertToString(startDate),
109+
dateConverter.convertToString(endDate),
110+
InfluxDuration.HOURLY));
111+
112+
QueryResult queryResult = connection.query(query);
113+
114+
InfluxDBResultMapper resultMapper = new InfluxDBResultMapper();
115+
List<DatadisConsumptionPoint> consumptionPoints = resultMapper.toPOJO(queryResult, DatadisConsumptionPoint.class);
116+
return mapToConsumption(consumptionPoints);
117+
}
118+
}
119+
89120
private List<DatadisConsumption> mapToConsumption(List<DatadisConsumptionPoint> consumptionPoints) {
90121
// Map fields from datadisConsumptionPoint to consumption here
91122
return consumptionPoints.stream()

src/main/java/org/lucoenergia/conluz/infrastructure/consumption/datadis/get/GetDatadisConsumptionRepositoryRest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ public List<DatadisConsumption> getDailyConsumptionsByRangeOfDates(Supply supply
119119
throw new NotImplementedException("Not yet implemented.");
120120
}
121121

122+
@Override
123+
public List<DatadisConsumption> getHourlyConsumptionsByRangeOfDates(Supply supply, OffsetDateTime startDate, OffsetDateTime endDate) {
124+
throw new NotImplementedException("Not yet implemented.");
125+
}
126+
122127
private void validateSupply(Supply supply) {
123128
if (supply.getDistributorCode() == null || supply.getDistributorCode().isEmpty()) {
124129
throw new DatadisSupplyConfigurationException("Distributor code is mandatory to get monthly consumption.");

src/main/java/org/lucoenergia/conluz/infrastructure/consumption/datadis/get/GetDatadisConsumptionServiceImpl.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,31 @@ public List<DatadisConsumption> getDailyConsumptionBySupply(SupplyId supplyId, O
6262
// Retrieve consumption data
6363
return getDatadisConsumptionRepository.getDailyConsumptionsByRangeOfDates(supply, startDate, endDate);
6464
}
65+
66+
@Override
67+
public List<DatadisConsumption> getHourlyConsumptionBySupply(SupplyId supplyId, OffsetDateTime startDate,
68+
OffsetDateTime endDate) {
69+
// Get current authenticated user
70+
User currentUser = authService.getCurrentUser()
71+
.orElseThrow(() -> new IllegalStateException("User must be authenticated"));
72+
73+
// Get the supply
74+
Optional<Supply> supplyOptional = getSupplyRepository.findById(supplyId);
75+
if (supplyOptional.isEmpty()) {
76+
throw new SupplyNotFoundException(supplyId);
77+
}
78+
79+
Supply supply = supplyOptional.get();
80+
81+
// Authorization: ADMIN can access any supply, non-ADMIN can only access their own supplies
82+
boolean isAdmin = currentUser.getRole() == Role.ADMIN;
83+
boolean isOwner = supply.getUser().getId().equals(currentUser.getId());
84+
85+
if (!isAdmin && !isOwner) {
86+
throw new AccessDeniedException("User does not have permission to access this supply's consumption data");
87+
}
88+
89+
// Retrieve consumption data
90+
return getDatadisConsumptionRepository.getHourlyConsumptionsByRangeOfDates(supply, startDate, endDate);
91+
}
6592
}

src/main/java/org/lucoenergia/conluz/infrastructure/shared/db/influxdb/InfluxDuration.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
public class InfluxDuration {
77

8+
public static final String HOURLY = "1h";
89
public static final String DAILY = "1d";
910
public static final String MONTHLY = "1mo";
1011
public static final String YEARLY = "1y";

0 commit comments

Comments
 (0)