fix recurrents
This commit is contained in:
@@ -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>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user