fix recurrents

This commit is contained in:
xds
2025-02-18 16:43:43 +03:00
parent 5a689bcd95
commit bf2dfca1cc

View File

@@ -1,21 +1,31 @@
package space.luminic.budgerapp.services package space.luminic.budgerapp.services
import org.bson.Document
import org.bson.types.ObjectId import org.bson.types.ObjectId
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.cache.annotation.CacheEvict import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.Cacheable import org.springframework.cache.annotation.Cacheable
import org.springframework.data.domain.Sort
import org.springframework.data.domain.Sort.Direction
import org.springframework.data.mongodb.core.ReactiveMongoTemplate
import org.springframework.data.mongodb.core.aggregation.Aggregation.*
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.security.core.context.ReactiveSecurityContextHolder import org.springframework.security.core.context.ReactiveSecurityContextHolder
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.* import space.luminic.budgerapp.models.*
import space.luminic.budgerapp.repos.RecurrentRepo import space.luminic.budgerapp.repos.RecurrentRepo
import space.luminic.budgerapp.repos.TransactionRepo import space.luminic.budgerapp.repos.TransactionRepo
import java.time.YearMonth import java.time.YearMonth
import java.time.ZoneId
@Service @Service
class RecurrentService( class RecurrentService(
private val reactiveMongoTemplate: ReactiveMongoTemplate,
private val recurrentRepo: RecurrentRepo, private val recurrentRepo: RecurrentRepo,
private val transactionRepo: TransactionRepo, private val transactionRepo: TransactionRepo,
private val userService: UserService, private val userService: UserService,
@@ -24,12 +34,42 @@ class RecurrentService(
private val logger = LoggerFactory.getLogger(javaClass) private val logger = LoggerFactory.getLogger(javaClass)
@Cacheable("recurrentsList")
fun getRecurrents(space: Space): Mono<List<Recurrent>> {
fun getRecurrents(space: Space): Mono<List<Recurrent>> {
val lookupCategories = lookup("categories", "category.\$id", "_id", "categoryDetails")
val unwindCategory = unwind("categoryDetails")
val lookupSpace = lookup("spaces", "space.\$id", "_id", "spaceDetails")
val unwindSpace = unwind("spaceDetails")
val matchStage = match(Criteria.where("spaceDetails._id").`is`(ObjectId(space.id)))
val sort =sort(Sort.by(Direction.ASC, "atDay"))
val aggregation =
newAggregation(lookupCategories, unwindCategory,lookupSpace, unwindSpace, matchStage, sort)
// Запрос рекуррентных платежей // Запрос рекуррентных платежей
return recurrentRepo.findRecurrentsBySpaceId(ObjectId(space.id)) return reactiveMongoTemplate.aggregate(aggregation, "recurrents", Document::class.java).collectList().map { docs ->
.collectList() // Преобразуем Flux<Recurrent> в Mono<List<Recurrent>> docs.map { doc ->
val categoryDoc = doc.get("categoryDetails", Document::class.java)
val categoryTypeDoc = categoryDoc.get("type", Document::class.java)
Recurrent(
id = doc.getObjectId("_id").toString(),
space = space,
atDay = doc.getInteger("atDay"),
category = Category(
id = categoryDoc.getObjectId("_id").toString(),
space = space,
type = CategoryType(categoryTypeDoc.getString("code"), categoryTypeDoc.getString("name")),
name = categoryDoc.getString("name"),
description = categoryDoc.getString("description"),
icon = categoryDoc.getString("icon"),
),
name = doc.getString("name"),
description = doc.getString("description"),
amount = doc.getInteger("amount"),
createdAt = doc.getDate("createdAt"),
)
}.toList()
}
} }
@@ -51,36 +91,33 @@ class RecurrentService(
) )
} }
@CacheEvict(cacheNames = ["recurrentsList", "recurrents"])
fun createRecurrentsForBudget(space: Space, budget: Budget): Mono<Void> { fun createRecurrentsForBudget(space: Space, budget: Budget): Mono<Void> {
val currentYearMonth = YearMonth.of(budget.dateFrom.year, budget.dateFrom.monthValue) val currentYearMonth = YearMonth.of(budget.dateFrom.year, budget.dateFrom.monthValue)
val daysInCurrentMonth = currentYearMonth.lengthOfMonth() val daysInCurrentMonth = currentYearMonth.lengthOfMonth()
val context = ReactiveSecurityContextHolder.getContext() val context = ReactiveSecurityContextHolder.getContext()
.doOnNext { println("Security context: $it") } .doOnNext { println("Security context: $it") }
.switchIfEmpty(Mono.error(IllegalStateException("SecurityContext is empty!"))) .switchIfEmpty(Mono.error(IllegalStateException("SecurityContext is empty!")))
return context return context
.map { .map { it.authentication }
logger.debug(it.authentication.name)
it.authentication
}
.flatMap { authentication -> .flatMap { authentication ->
val username = authentication.name val username = authentication.name
userService.getByUsername(username) userService.getByUsername(username)
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username"))) .switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
} }
.flatMapMany { user -> .flatMapMany { user ->
recurrentRepo.findRecurrentsBySpaceId(ObjectId(space.id)) getRecurrents(space) // Теперь это Mono<List<Recurrent>>
.flatMapMany { Flux.fromIterable(it) } // Преобразуем List<Recurrent> в Flux<Recurrent>
.map { recurrent -> .map { recurrent ->
// Определяем дату транзакции // Определяем дату транзакции
val transactionDate = when { val transactionDate = when {
recurrent.atDay <= daysInCurrentMonth && recurrent.atDay >= budget.dateFrom.dayOfMonth -> { recurrent.atDay in budget.dateFrom.dayOfMonth..daysInCurrentMonth -> {
currentYearMonth.atDay(recurrent.atDay) currentYearMonth.atDay(recurrent.atDay)
} }
recurrent.atDay < budget.dateFrom.dayOfMonth -> { recurrent.atDay < budget.dateFrom.dayOfMonth -> {
currentYearMonth.atDay(recurrent.atDay).plusMonths(1) currentYearMonth.atDay(recurrent.atDay).plusMonths(1)
} }
else -> { else -> {
val extraDays = recurrent.atDay - daysInCurrentMonth val extraDays = recurrent.atDay - daysInCurrentMonth
currentYearMonth.plusMonths(1).atDay(extraDays) currentYearMonth.plusMonths(1).atDay(extraDays)
@@ -89,6 +126,7 @@ class RecurrentService(
// Создаем транзакцию // Создаем транзакцию
Transaction( Transaction(
space = space,
date = transactionDate, date = transactionDate,
amount = recurrent.amount.toDouble(), amount = recurrent.amount.toDouble(),
category = recurrent.category, category = recurrent.category,
@@ -101,8 +139,7 @@ class RecurrentService(
} }
.collectList() // Собираем все транзакции в список .collectList() // Собираем все транзакции в список
.flatMap { transactions -> .flatMap { transactions ->
transactionRepo.saveAll(transactions) // Сохраняем все транзакции разом transactionRepo.saveAll(transactions).then() // Сохраняем все транзакции разом и возвращаем Mono<Void>
.then() // Возвращаем Mono<Void>
} }
} }