/
berkas
/
Spend-tracker
Обзор
Документация
Войти
/
berkas
/
Spend-tracker
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
api/src/main/java/com/spendtracker/service/ReportService.java
198 строк
6 KB
akasianov
Created endpoint report/period-compare
15 янв 2026, 09:58
15 янв 2026, 09:58
432481a
Код
Авторство
О чём код?
package com.spendtracker.application.service; import com.spendtracker.application.dto.PeriodReportDto; import com.spendtracker.domain.InflationRate; import com.spendtracker.application.dto.ReportResultDto; import com.spendtracker.application.dto.PeriodCompareReportDto; import com.spendtracker.domain.Transaction; import com.spendtracker.repository.TransactionRepository; import com.spendtracker.repository.InflationRateRepository; import com.spendtracker.repository.filter.TransactionFilter; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.time.YearMonth; import java.util.*; @Service public class ReportService { private final TransactionRepository transactionRepository; private final InflationRateRepository inflationRateRepository; public ReportService( TransactionRepository transactionRepository, InflationRateRepository inflationRateRepository ) { this.transactionRepository = transactionRepository; this.inflationRateRepository = inflationRateRepository; } public ReportResultDto getReport( String userId, LocalDateTime start, LocalDateTime end, String categoryId, Integer limit, String sortBy ) { TransactionFilter filter = new TransactionFilter(); filter.setUserIds(Set.of(userId)); filter.setStart(start); filter.setEnd(end); if (categoryId != null) { filter.setCategoryIds(Set.of(categoryId)); } List<Transaction> transactions = transactionRepository.findAll(filter); if ("amount".equalsIgnoreCase(sortBy)) { transactions.sort(Comparator.comparing(Transaction::getAmount)); } else { transactions.sort(Comparator.comparing(Transaction::getDate)); } if (limit != null && limit > 0 && limit < transactions.size()) { transactions = transactions.subList(0, limit); } BigDecimal totalIncome = BigDecimal.ZERO; BigDecimal totalExpense = BigDecimal.ZERO; for (Transaction t : transactions) { if ("INCOME".equalsIgnoreCase(t.getType())) { totalIncome = totalIncome.add(t.getAmount()); } else if ("EXPENSE".equalsIgnoreCase(t.getType())) { totalExpense = totalExpense.add(t.getAmount()); } } return new ReportResultDto( totalIncome, totalExpense, transactions.size() ); } public PeriodReportDto getPeriodReport( String userId, YearMonth start, YearMonth end ) { TransactionFilter filter = new TransactionFilter(); filter.setUserIds(Set.of(userId)); filter.setStart(start.atDay(1).atStartOfDay()); filter.setEnd(end.atEndOfMonth().atTime(23, 59, 59)); List<Transaction> transactions = transactionRepository.findAll(filter); BigDecimal nominalIncome = BigDecimal.ZERO; BigDecimal nominalExpense = BigDecimal.ZERO; for (Transaction t : transactions) { if ("INCOME".equalsIgnoreCase(t.getType())) { nominalIncome = nominalIncome.add(t.getAmount()); } else { nominalExpense = nominalExpense.add(t.getAmount()); } } BigDecimal inflationIndex = calculateInflationIndex(start, end); return new PeriodReportDto( nominalIncome, nominalExpense, nominalIncome.multiply(inflationIndex), nominalExpense.multiply(inflationIndex) ); } public PeriodCompareReportDto getPeriodCompareReport( String userId, YearMonth startA, YearMonth endA, YearMonth startB, YearMonth endB ) { BigDecimal sumA = getNominalTotal(userId, startA, endA); BigDecimal sumB = getNominalTotal(userId, startB, endB); BigDecimal inflationIndexAToB = calculateInflationIndex(endA, endB); BigDecimal sumAReal = sumA.multiply(inflationIndexAToB); BigDecimal sumBReal = sumB; BigDecimal difference = sumBReal.subtract(sumAReal); BigDecimal growthPercent = BigDecimal.ZERO; if (sumAReal.compareTo(BigDecimal.ZERO) > 0) { growthPercent = difference .divide(sumAReal, 6, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)); } return new PeriodCompareReportDto( sumA, sumB, sumAReal, sumBReal, difference, growthPercent ); } BigDecimal calculateInflationIndex( YearMonth start, YearMonth end ) { List<InflationRate> rates = inflationRateRepository.findAllByStartAndEndDates( start.getYear(), end.getYear() ); Map<YearMonth, BigDecimal> rateMap = new HashMap<>(); for (InflationRate r : rates) { rateMap.put( YearMonth.of(r.getYear(), r.getMonth()), r.getRate() ); } BigDecimal index = BigDecimal.ONE; YearMonth current = start.plusMonths(1); while (!current.isAfter(end)) { BigDecimal rate = rateMap.get(current); if (rate != null) { index = index.multiply( BigDecimal.ONE.add(rate) ); } current = current.plusMonths(1); } return index; } BigDecimal getNominalTotal( String userId, YearMonth start, YearMonth end ) { TransactionFilter filter = new TransactionFilter(); filter.setUserIds(Set.of(userId)); filter.setStart(start.atDay(1).atStartOfDay()); filter.setEnd(end.atEndOfMonth().atTime(23, 59, 59)); return transactionRepository.findAll(filter) .stream() .map(Transaction::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::add); } }