This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
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.SubscriberStatisticResponse;
|
||||
import ru.soune.nocopy.entity.tarif.TariffInfo;
|
||||
import ru.soune.nocopy.entity.user.User;
|
||||
import ru.soune.nocopy.repository.TariffInfoRepository;
|
||||
import ru.soune.nocopy.repository.UserRepository;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class SubscriberStatisticService {
|
||||
private final TariffInfoRepository tariffInfoRepository;
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
private static final String TERM_MONTHLY = "MONTHLY";
|
||||
|
||||
private static final String TERM_YEARLY = "YEAR";
|
||||
|
||||
public SubscriberStatisticResponse getSubscriberStatistics() {
|
||||
return SubscriberStatisticResponse.builder()
|
||||
.monthly(buildPeriodStatistics(TERM_MONTHLY))
|
||||
.yearly(buildPeriodStatistics(TERM_YEARLY))
|
||||
.build();
|
||||
}
|
||||
|
||||
private SubscriberStatisticResponse.PeriodStatistics buildPeriodStatistics(String term) {
|
||||
Long currentActive = tariffInfoRepository.getCurrentActiveSubscriptions(term);
|
||||
|
||||
List<TariffInfo> allTariffs = tariffInfoRepository.getAllTariffInfosForAnalysis(term);
|
||||
|
||||
Map<Long, List<TariffInfo>> tariffsByUser = groupTariffsByUser(allTariffs);
|
||||
|
||||
Long firstTime = countFirstTimeSubscriptions(tariffsByUser);
|
||||
Long renewals = countRenewals(tariffsByUser);
|
||||
UpDownGradeResult gradeResult = analyzeUpgradesAndDowngrades(tariffsByUser);
|
||||
|
||||
return SubscriberStatisticResponse.PeriodStatistics.builder()
|
||||
.currentActiveSubscriptions(currentActive != null ? currentActive : 0L)
|
||||
.firstTimeSubscriptions(firstTime)
|
||||
.renewals(renewals)
|
||||
.upgrades(gradeResult.upgrades)
|
||||
.downgrades(gradeResult.downgrades)
|
||||
.build();
|
||||
}
|
||||
|
||||
private Map<Long, List<TariffInfo>> groupTariffsByUser(List<TariffInfo> tariffs) {
|
||||
Map<Long, List<TariffInfo>> result = new HashMap<>();
|
||||
|
||||
for (TariffInfo ti : tariffs) {
|
||||
Optional<User> userOpt = userRepository.findByPersonalTariffInfoId(ti.getId());
|
||||
if (userOpt.isPresent()) {
|
||||
Long userId = userOpt.get().getId();
|
||||
result.computeIfAbsent(userId, k -> new ArrayList<>()).add(ti);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Long countFirstTimeSubscriptions(Map<Long, List<TariffInfo>> tariffsByUser) {
|
||||
return (long) tariffsByUser.size();
|
||||
}
|
||||
|
||||
private Long countRenewals(Map<Long, List<TariffInfo>> tariffsByUser) {
|
||||
return tariffsByUser.values().stream()
|
||||
.filter(list -> list.size() > 1)
|
||||
.mapToLong(list -> list.size() - 1)
|
||||
.sum();
|
||||
}
|
||||
|
||||
private UpDownGradeResult analyzeUpgradesAndDowngrades(Map<Long, List<TariffInfo>> tariffsByUser) {
|
||||
long upgrades = 0L;
|
||||
long downgrades = 0L;
|
||||
|
||||
for (List<TariffInfo> userTariffs : tariffsByUser.values()) {
|
||||
if (userTariffs.size() < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
userTariffs.sort(Comparator.comparing(TariffInfo::getStartTariff,
|
||||
Comparator.nullsLast(Comparator.naturalOrder())));
|
||||
|
||||
for (int i = 1; i < userTariffs.size(); i++) {
|
||||
TariffInfo previous = userTariffs.get(i - 1);
|
||||
TariffInfo current = userTariffs.get(i);
|
||||
|
||||
if (previous.getTariff() == null || current.getTariff() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double previousPrice = previous.getTariff().getPrice();
|
||||
double currentPrice = current.getTariff().getPrice();
|
||||
|
||||
if (currentPrice > previousPrice) {
|
||||
upgrades++;
|
||||
} else if (currentPrice < previousPrice) {
|
||||
downgrades++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new UpDownGradeResult(upgrades, downgrades);
|
||||
}
|
||||
|
||||
private static class UpDownGradeResult {
|
||||
final Long upgrades;
|
||||
final Long downgrades;
|
||||
|
||||
UpDownGradeResult(Long upgrades, Long downgrades) {
|
||||
this.upgrades = upgrades;
|
||||
this.downgrades = downgrades;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user