AnalyticsController.java
package com.ecommerce.analytics.interfaces.rest;
import com.ecommerce.analytics.application.model.AnalyticsModels.DashboardView;
import com.ecommerce.analytics.application.model.AnalyticsModels.RebuildView;
import com.ecommerce.analytics.application.model.AnalyticsModels.ReconciliationView;
import com.ecommerce.analytics.application.service.AnalyticsApplicationService;
import com.ecommerce.platform.common.api.ApiResponse;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
@Validated
@RestController
@RequestMapping("/api/v1/analytics")
public class AnalyticsController {
private final AnalyticsApplicationService service;
public AnalyticsController(AnalyticsApplicationService service) {
this.service = service;
}
@GetMapping("/overview")
public ApiResponse<DashboardView> overview(
@RequestParam(required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
LocalDate from,
@RequestParam(required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
LocalDate to,
@RequestParam(required = false)
Integer productLimit) {
return ApiResponse.success(service.dashboard(from, to, productLimit));
}
@GetMapping("/admin/reconciliation")
public ApiResponse<ReconciliationView> reconciliation(
@RequestParam(required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
LocalDate from,
@RequestParam(required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
LocalDate to) {
return ApiResponse.success(service.reconcile(from, to));
}
@PostMapping("/admin/rebuild")
public ApiResponse<RebuildView> rebuild(
@AuthenticationPrincipal Jwt jwt,
@Valid @RequestBody RebuildRequest request) {
return ApiResponse.success(service.rebuild(
operatorId(jwt),
request.commandId(),
request.reason(),
request.from(),
request.to()));
}
private long operatorId(Jwt jwt) {
try {
long value = Long.parseLong(jwt.getSubject());
if (value <= 0) {
throw new IllegalArgumentException("JWT subject must be positive");
}
return value;
} catch (RuntimeException exception) {
throw new IllegalArgumentException("JWT subject is invalid", exception);
}
}
public record RebuildRequest(
@NotBlank @Size(max = 64) String commandId,
@NotBlank @Size(min = 8, max = 500) String reason,
@NotNull LocalDate from,
@NotNull LocalDate to) {
}
}