2023-12-30 21:44:07 +02:00
|
|
|
package dev.mvvasilev.finances.services;
|
|
|
|
|
|
|
|
import dev.mvvasilev.common.data.AbstractEntity;
|
|
|
|
import dev.mvvasilev.finances.dtos.CategoryDTO;
|
2024-01-02 18:20:00 +02:00
|
|
|
import dev.mvvasilev.finances.dtos.SpendingByCategoriesDTO;
|
2023-12-30 21:44:07 +02:00
|
|
|
import dev.mvvasilev.finances.dtos.SpendingByCategoryDTO;
|
2024-01-02 18:20:00 +02:00
|
|
|
import dev.mvvasilev.finances.dtos.SpendingOverTimeByCategoryDTO;
|
|
|
|
import dev.mvvasilev.finances.enums.TimePeriod;
|
2023-12-30 21:44:07 +02:00
|
|
|
import dev.mvvasilev.finances.persistence.StatisticsRepository;
|
|
|
|
import dev.mvvasilev.finances.persistence.TransactionCategoryRepository;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
import java.time.LocalDateTime;
|
2024-01-02 18:20:00 +02:00
|
|
|
import java.time.temporal.ChronoUnit;
|
|
|
|
import java.util.*;
|
2023-12-30 21:44:07 +02:00
|
|
|
|
|
|
|
@Service
|
|
|
|
public class StatisticsService {
|
|
|
|
|
|
|
|
private final TransactionCategoryRepository transactionCategoryRepository;
|
|
|
|
|
|
|
|
private final StatisticsRepository statisticsRepository;
|
|
|
|
|
|
|
|
public StatisticsService(TransactionCategoryRepository transactionCategoryRepository, StatisticsRepository statisticsRepository) {
|
|
|
|
this.transactionCategoryRepository = transactionCategoryRepository;
|
|
|
|
this.statisticsRepository = statisticsRepository;
|
|
|
|
}
|
|
|
|
|
2024-01-02 18:20:00 +02:00
|
|
|
public SpendingByCategoriesDTO spendingByCategory(Long[] categoryId, LocalDateTime from, LocalDateTime to) {
|
|
|
|
final var categories = transactionCategoryRepository.findAllById(Arrays.stream(categoryId).toList()).stream().map(c -> new CategoryDTO(c.getId(), c.getName(), null)).toList();
|
|
|
|
|
2023-12-30 21:44:07 +02:00
|
|
|
final var spendingByCategory = statisticsRepository.fetchSpendingByCategory(
|
2024-01-02 18:20:00 +02:00
|
|
|
categoryId,
|
2023-12-30 21:44:07 +02:00
|
|
|
from,
|
2024-01-02 18:20:00 +02:00
|
|
|
to
|
2023-12-30 21:44:07 +02:00
|
|
|
);
|
|
|
|
|
2024-01-02 18:20:00 +02:00
|
|
|
return new SpendingByCategoriesDTO(
|
|
|
|
categories,
|
2023-12-30 21:44:07 +02:00
|
|
|
spendingByCategory
|
|
|
|
);
|
|
|
|
}
|
2024-01-02 18:20:00 +02:00
|
|
|
|
|
|
|
public SpendingOverTimeByCategoryDTO spendingByCategoryOverTime(
|
|
|
|
Long[] categoryId,
|
|
|
|
TimePeriod period,
|
|
|
|
LocalDateTime from,
|
|
|
|
LocalDateTime to
|
|
|
|
) {
|
|
|
|
return new SpendingOverTimeByCategoryDTO(
|
|
|
|
transactionCategoryRepository.findAllById(Arrays.stream(categoryId).toList()).stream().map(c -> new CategoryDTO(c.getId(), c.getName(), null)).toList(),
|
|
|
|
period.getDuration(),
|
|
|
|
statisticsRepository.fetchSpendingByCategoryOverTime(from, to, period, categoryId).stream().map(dto -> new SpendingByCategoryDTO(
|
|
|
|
dto.categoryId(),
|
|
|
|
dto.periodBeginningTimestamp(),
|
|
|
|
dto.amountForPeriod()
|
|
|
|
)).toList()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Impose limits if necessary
|
|
|
|
private boolean validatePeriodWithinLimits(LocalDateTime from, LocalDateTime to, TimePeriod period) {
|
|
|
|
return switch (period) {
|
|
|
|
// Can't request daily spending breakdown for a period longer than a month
|
|
|
|
case DAILY -> ChronoUnit.MONTHS.between(from, to) <= 1;
|
|
|
|
// Can't request weekly spending breakdown for a period longer than a year
|
|
|
|
case WEEKLY -> ChronoUnit.YEARS.between(from, to) <= 1;
|
|
|
|
// Can't request bi-weekly spending breakdown for a period longer than a year
|
|
|
|
case BIWEEKLY -> ChronoUnit.YEARS.between(from, to) <= 1;
|
|
|
|
// Can't request monthly spending breakdown for a period longer than 3 years
|
|
|
|
case MONTHLY -> ChronoUnit.YEARS.between(from, to) <= 3;
|
|
|
|
// Can't request quarterly spending breakdown for a period longer than 5 years
|
|
|
|
case QUARTERLY -> ChronoUnit.YEARS.between(from, to) <= 5;
|
|
|
|
// Can't request yearly spending breakdown for a period longer than 30 years
|
|
|
|
case YEARLY -> ChronoUnit.YEARS.between(from, to) <= 30;
|
|
|
|
};
|
|
|
|
}
|
2024-01-03 22:46:16 +02:00
|
|
|
|
|
|
|
public Double sumByCategory(Long[] categoryId, LocalDateTime from, LocalDateTime to, Boolean includeUncategorized) {
|
|
|
|
return statisticsRepository.sumByCategory(categoryId, from, to, includeUncategorized);
|
|
|
|
}
|
2023-12-30 21:44:07 +02:00
|
|
|
}
|