This commit is contained in:
@@ -45,7 +45,8 @@ public class HandlerConfig {
|
|||||||
StatisticProtectedFilesHandler statisticProtectedFilesHandler,
|
StatisticProtectedFilesHandler statisticProtectedFilesHandler,
|
||||||
StatisticViolationHandler statisticViolationHandler,
|
StatisticViolationHandler statisticViolationHandler,
|
||||||
StatisticSubscriberHandler statisticSubscriberHandler,
|
StatisticSubscriberHandler statisticSubscriberHandler,
|
||||||
StatisticTokenHandler statisticTokenHandler
|
StatisticTokenHandler statisticTokenHandler,
|
||||||
|
StatisticIncomeHandler statisticIncomeHandler
|
||||||
|
|
||||||
) {
|
) {
|
||||||
Map<Integer, RequestHandler> map = new HashMap<>();
|
Map<Integer, RequestHandler> map = new HashMap<>();
|
||||||
@@ -83,6 +84,7 @@ public class HandlerConfig {
|
|||||||
map.put(30023, statisticViolationHandler);
|
map.put(30023, statisticViolationHandler);
|
||||||
map.put(30024, statisticSubscriberHandler);
|
map.put(30024, statisticSubscriberHandler);
|
||||||
map.put(30025, statisticTokenHandler);
|
map.put(30025, statisticTokenHandler);
|
||||||
|
map.put(30026, statisticIncomeHandler);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package ru.soune.nocopy.dto.statistic;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class IncomeStatisticRequest {
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package ru.soune.nocopy.dto.statistic;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class IncomeStatisticResponse {
|
||||||
|
|
||||||
|
@JsonProperty("total_income")
|
||||||
|
private Long totalIncome;
|
||||||
|
|
||||||
|
@JsonProperty("total_available")
|
||||||
|
private Long totalAvailable;
|
||||||
|
|
||||||
|
@JsonProperty("total_hold")
|
||||||
|
private Long totalHold;
|
||||||
|
|
||||||
|
@JsonProperty("income_per_user")
|
||||||
|
private Percentiles incomePerUser;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class Percentiles {
|
||||||
|
@JsonProperty("p5")
|
||||||
|
private Long p5;
|
||||||
|
|
||||||
|
@JsonProperty("p50")
|
||||||
|
private Long p50;
|
||||||
|
|
||||||
|
@JsonProperty("p95")
|
||||||
|
private Long p95;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package ru.soune.nocopy.handler;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import ru.soune.nocopy.dto.BaseRequest;
|
||||||
|
import ru.soune.nocopy.dto.BaseResponse;
|
||||||
|
import ru.soune.nocopy.dto.MessageCode;
|
||||||
|
import ru.soune.nocopy.dto.statistic.IncomeStatisticResponse;
|
||||||
|
import ru.soune.nocopy.service.statistic.IncomeStatisticService;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class StatisticIncomeHandler implements RequestHandler {
|
||||||
|
|
||||||
|
private final IncomeStatisticService statisticService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseResponse handle(BaseRequest request) throws Exception {
|
||||||
|
IncomeStatisticResponse statistics = statisticService.getIncomeStatistics();
|
||||||
|
|
||||||
|
return new BaseResponse(
|
||||||
|
request.getMsgId(),
|
||||||
|
MessageCode.SUCCESS.getCode(),
|
||||||
|
MessageCode.SUCCESS.getDescription(),
|
||||||
|
statistics
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,4 +43,22 @@ public interface ReferralJpaRepository extends JpaRepository<Referral, Long> {
|
|||||||
|
|
||||||
@Query("SELECT COUNT(r) FROM Referral r WHERE r.inviterId = :userId")
|
@Query("SELECT COUNT(r) FROM Referral r WHERE r.inviterId = :userId")
|
||||||
int countTotalInvitees(@Param("userId") Long userId);
|
int countTotalInvitees(@Param("userId") Long userId);
|
||||||
|
|
||||||
|
@Query("SELECT COALESCE(SUM(r.totalIncome), 0) FROM Referral r")
|
||||||
|
Long getTotalIncome();
|
||||||
|
|
||||||
|
@Query("SELECT COALESCE(SUM(r.availableIncome), 0) FROM Referral r")
|
||||||
|
Long getTotalAvailableIncome();
|
||||||
|
|
||||||
|
@Query("SELECT COALESCE(SUM(r.holdBalance), 0) FROM Referral r")
|
||||||
|
Long getTotalHoldBalance();
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT
|
||||||
|
r.userId,
|
||||||
|
r.totalIncome
|
||||||
|
FROM Referral r
|
||||||
|
WHERE r.totalIncome > 0
|
||||||
|
""")
|
||||||
|
List<Object[]> getIncomePerUser();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package ru.soune.nocopy.service.statistic;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.soune.nocopy.dto.statistic.IncomeStatisticResponse;
|
||||||
|
import ru.soune.nocopy.repository.ReferralJpaRepository;
|
||||||
|
import ru.soune.nocopy.util.PercentileCalculator;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class IncomeStatisticService {
|
||||||
|
private final ReferralJpaRepository referralRepository;
|
||||||
|
|
||||||
|
private static final int PERCENTILE_5 = 5;
|
||||||
|
|
||||||
|
private static final int PERCENTILE_50 = 50;
|
||||||
|
|
||||||
|
private static final int PERCENTILE_95 = 95;
|
||||||
|
|
||||||
|
public IncomeStatisticResponse getIncomeStatistics() {
|
||||||
|
Long totalIncome = referralRepository.getTotalIncome();
|
||||||
|
Long totalAvailable = referralRepository.getTotalAvailableIncome();
|
||||||
|
Long totalHold = referralRepository.getTotalHoldBalance();
|
||||||
|
|
||||||
|
List<Object[]> incomeData = referralRepository.getIncomePerUser();
|
||||||
|
List<Long> incomeValues = extractIncomeValues(incomeData);
|
||||||
|
|
||||||
|
PercentileCalculator.PercentilesResult incomePercentiles =
|
||||||
|
PercentileCalculator.calculatePercentiles(incomeValues, PERCENTILE_5, PERCENTILE_50,
|
||||||
|
PERCENTILE_95);
|
||||||
|
|
||||||
|
return IncomeStatisticResponse.builder()
|
||||||
|
.totalIncome(totalIncome != null ? totalIncome : 0L)
|
||||||
|
.totalAvailable(totalAvailable != null ? totalAvailable : 0L)
|
||||||
|
.totalHold(totalHold != null ? totalHold : 0L)
|
||||||
|
.incomePerUser(new IncomeStatisticResponse.Percentiles(
|
||||||
|
incomePercentiles.getP5() != null ? incomePercentiles.getP5() : 0L,
|
||||||
|
incomePercentiles.getP50() != null ? incomePercentiles.getP50() : 0L,
|
||||||
|
incomePercentiles.getP95() != null ? incomePercentiles.getP95() : 0L
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Long> extractIncomeValues(List<Object[]> data) {
|
||||||
|
return data.stream()
|
||||||
|
.map(row -> row[1] != null ? ((Number) row[1]).longValue() : 0L)
|
||||||
|
.filter(value -> value > 0)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user