diff --git a/src/main/kotlin/space/luminic/budgerapp/services/RecurrentService.kt b/src/main/kotlin/space/luminic/budgerapp/services/RecurrentService.kt index e806293..b3c85aa 100644 --- a/src/main/kotlin/space/luminic/budgerapp/services/RecurrentService.kt +++ b/src/main/kotlin/space/luminic/budgerapp/services/RecurrentService.kt @@ -1,21 +1,31 @@ package space.luminic.budgerapp.services + +import org.bson.Document import org.bson.types.ObjectId import org.slf4j.LoggerFactory import org.springframework.cache.annotation.CacheEvict 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.stereotype.Service +import reactor.core.publisher.Flux import reactor.core.publisher.Mono import space.luminic.budgerapp.models.* import space.luminic.budgerapp.repos.RecurrentRepo import space.luminic.budgerapp.repos.TransactionRepo import java.time.YearMonth +import java.time.ZoneId @Service class RecurrentService( + private val reactiveMongoTemplate: ReactiveMongoTemplate, private val recurrentRepo: RecurrentRepo, private val transactionRepo: TransactionRepo, private val userService: UserService, @@ -24,12 +34,42 @@ class RecurrentService( private val logger = LoggerFactory.getLogger(javaClass) - @Cacheable("recurrentsList") - fun getRecurrents(space: Space): Mono> { + fun getRecurrents(space: Space): Mono> { + 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)) - .collectList() // Преобразуем Flux в Mono> + return reactiveMongoTemplate.aggregate(aggregation, "recurrents", Document::class.java).collectList().map { docs -> + 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 { val currentYearMonth = YearMonth.of(budget.dateFrom.year, budget.dateFrom.monthValue) val daysInCurrentMonth = currentYearMonth.lengthOfMonth() + val context = ReactiveSecurityContextHolder.getContext() .doOnNext { println("Security context: $it") } .switchIfEmpty(Mono.error(IllegalStateException("SecurityContext is empty!"))) + return context - .map { - logger.debug(it.authentication.name) - it.authentication - } + .map { it.authentication } .flatMap { authentication -> val username = authentication.name userService.getByUsername(username) .switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username"))) } .flatMapMany { user -> - recurrentRepo.findRecurrentsBySpaceId(ObjectId(space.id)) + getRecurrents(space) // Теперь это Mono> + .flatMapMany { Flux.fromIterable(it) } // Преобразуем List в Flux .map { recurrent -> // Определяем дату транзакции val transactionDate = when { - recurrent.atDay <= daysInCurrentMonth && recurrent.atDay >= budget.dateFrom.dayOfMonth -> { + recurrent.atDay in budget.dateFrom.dayOfMonth..daysInCurrentMonth -> { currentYearMonth.atDay(recurrent.atDay) } - recurrent.atDay < budget.dateFrom.dayOfMonth -> { currentYearMonth.atDay(recurrent.atDay).plusMonths(1) } - else -> { val extraDays = recurrent.atDay - daysInCurrentMonth currentYearMonth.plusMonths(1).atDay(extraDays) @@ -89,6 +126,7 @@ class RecurrentService( // Создаем транзакцию Transaction( + space = space, date = transactionDate, amount = recurrent.amount.toDouble(), category = recurrent.category, @@ -101,8 +139,7 @@ class RecurrentService( } .collectList() // Собираем все транзакции в список .flatMap { transactions -> - transactionRepo.saveAll(transactions) // Сохраняем все транзакции разом - .then() // Возвращаем Mono + transactionRepo.saveAll(transactions).then() // Сохраняем все транзакции разом и возвращаем Mono } }