This commit is contained in:
Vladimir Voronin
2025-01-07 13:15:08 +03:00
parent 2506e6081f
commit 8b440ad9e8
45 changed files with 51 additions and 1048 deletions

View File

@@ -1,9 +1,7 @@
package space.luminic.budgerapp.services
import org.springframework.cache.annotation.Cacheable
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
import space.luminic.budgerapp.configs.AuthException
@@ -16,7 +14,6 @@ import space.luminic.budgerapp.utils.JWTUtil
import java.time.LocalDateTime
import java.time.ZoneId
import java.util.Date
import java.util.UUID
@Service

View File

@@ -1,42 +1,37 @@
package space.luminic.budgerapp.services
import org.slf4j.LoggerFactory
import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.Cacheable
import org.springframework.context.event.EventListener
import org.springframework.data.domain.Sort
import org.springframework.data.domain.Sort.Direction
import org.springframework.stereotype.Service
import space.luminic.budgerapp.models.Budget
import space.luminic.budgerapp.models.BudgetCategory
import space.luminic.budgerapp.models.Transaction
import org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.ReactiveMongoTemplate
import org.springframework.data.mongodb.core.aggregation.Aggregation.group
import org.springframework.data.mongodb.core.aggregation.Aggregation.lookup
import org.springframework.data.mongodb.core.aggregation.Aggregation.match
import org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation
import org.springframework.data.mongodb.core.aggregation.Aggregation.project
import org.springframework.data.mongodb.core.aggregation.Aggregation.sort
import org.springframework.data.mongodb.core.aggregation.Aggregation.unwind
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.stereotype.Service
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.Budget
import space.luminic.budgerapp.models.BudgetCategory
import space.luminic.budgerapp.models.BudgetDTO
import space.luminic.budgerapp.models.BudgetNotFoundException
import space.luminic.budgerapp.models.PushMessage
import space.luminic.budgerapp.models.SortSetting
import space.luminic.budgerapp.models.Transaction
import space.luminic.budgerapp.models.TransactionEvent
import space.luminic.budgerapp.models.TransactionEventType
import space.luminic.budgerapp.models.Warn
import space.luminic.budgerapp.models.WarnSerenity
import space.luminic.budgerapp.repos.BudgetRepo
import space.luminic.budgerapp.repos.WarnRepo
import java.time.LocalDate
import java.util.Optional
import kotlin.collections.get
@@ -57,7 +52,7 @@ class BudgetService(
@CacheEvict(cacheNames = ["budgets"], allEntries = true)
fun handleTransactionEvent(event: TransactionEvent) {
logger.info("Got ${event.eventType} event on transaction ${event.newTransaction.id}")
if (event.newTransaction.category.type?.code == "EXPENSE") {
if (event.newTransaction.category.type.code == "EXPENSE") {
when (event.eventType) {
TransactionEventType.EDIT -> updateBudgetOnEdit(event)
TransactionEventType.CREATE -> updateBudgetOnCreate(event)
@@ -196,23 +191,6 @@ class BudgetService(
}
fun updateBudgetTransactions(budget: Budget): Budget {
// budget.plannedExpenses = getBudgetTransactions(
// budget = budget,
// transactionType = "PLANNED",
// categoryType = "EXPENSE",
// sortBy = SortSetting("date", Direction.ASC)
// )
// budget.plannedIncomes = getBudgetTransactions(
// budget = budget,
// transactionType = "PLANNED",
// categoryType = "INCOME",
// sortBy = SortSetting("date", Direction.ASC)
// )
return budget
}
@Cacheable("budgetsList")
fun getBudgets(sortSetting: SortSetting? = null): Mono<MutableList<Budget>> {
val sort = if (sortSetting != null) {
@@ -277,22 +255,6 @@ class BudgetService(
}
// fun transferBudgets() {
// val budgets = getBudgets()
// budgetRepo.saveAll<Budget>(budgets)
//
// }
//
// fun getBudgets(): List<Budget> {
// val budgetIds = budgetRepoSql.getBudgetsIds()
// var budgets = mutableListOf<Budget>()
// budgetIds.forEach { budgetId ->
// budgets.add(getBudgetSQL(budgetId)!!)
// }
// return budgets
// }
@CacheEvict(cacheNames = ["budgets", "budgetsList"], allEntries = true)
fun createBudget(budget: Budget, createRecurrent: Boolean): Mono<Budget> {
return Mono.zip(
@@ -323,6 +285,7 @@ class BudgetService(
budget.categories = categories
budgetRepo.save(budget)
}
.publishOn(reactor.core.scheduler.Schedulers.boundedElastic())
.doOnNext { savedBudget ->
// Выполнение updateBudgetWarns в фоне
updateBudgetWarns(budget = savedBudget)
@@ -374,27 +337,6 @@ class BudgetService(
}
}
fun getBudgetTransactions(
budget: Budget,
transactionType: String? = null,
isDone: Boolean? = null,
categoryType: String? = null,
sortBy: SortSetting? = null
): Mono<MutableList<Transaction>> {
val defaultSort = SortSetting("date", Sort.Direction.ASC) // Сортировка по умолчанию
return transactionService.getTransactions(
dateFrom = budget.dateFrom,
dateTo = budget.dateTo,
transactionType = transactionType,
isDone = isDone,
categoryType = categoryType,
sortSetting = sortBy ?: defaultSort
).onErrorResume { e ->
Mono.error(RuntimeException("Error fetching transactions: ${e.message}", e))
}
}
@CacheEvict(cacheNames = ["budgets", "budgetsList"], allEntries = true)
fun deleteBudget(budgetId: String): Mono<Void> {
@@ -436,38 +378,14 @@ class BudgetService(
}
fun recalcBudgetCategory(): Mono<Void> {
return budgetRepo.findAll(Sort.by(Direction.DESC, "dateFrom")) // Получаем все бюджеты
// .flatMapIterable { budgets -> budgets } // Преобразуем Flux<Budget> в Flux<Budget> (итерация по бюджетам)
// .flatMap { budget ->
// logger.warn("HERE $budget")
// Flux.fromIterable(budget.categories) // Преобразуем категории в поток
// .flatMap { category ->
// logger.warn("HERE $category")
// Mono.zip(
// transactionService.calcTransactionsSum(budget, category.category.id!!, "PLANNED"),
// transactionService.calcTransactionsSum(budget, category.category.id!!, "INSTANT", isDone = true),
// transactionService.calcTransactionsSum(budget, category.category.id!!, "PLANNED")
// ).map { (plannedSum, spentSum, limitSum) ->
// category.currentPlanned = plannedSum
// category.currentSpent = spentSum
// category.currentLimit = limitSum
// }
// }
// .then() // Завершаем поток категорий
// .flatMap { updateBudgetWarns(budgetId = budget.id!!) } // Обновляем предупреждения
// }
// .collectList() // Собираем все бюджеты
// .flatMap { budgets -> budgetRepo.saveAll(budgets).collectList() } // Сохраняем все бюджеты
.then() // Завершаем метод
}
fun getWarns(budgetId: String, isHide: Boolean? = null): Mono<List<Warn>> {
return warnRepo.findAllByBudgetIdAndIsHide(budgetId, isHide == true).collectList()
}
fun hideWarn(budgetId: String, warnId: String): Mono<Warn> {
fun hideWarn(warnId: String): Mono<Warn> {
return warnRepo.findById(warnId) // Ищем предупреждение
.flatMap { warn ->
warn.isHide = true // Обновляем поле

View File

@@ -5,9 +5,7 @@ import org.bson.Document
import org.slf4j.LoggerFactory
import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.Cacheable
import org.springframework.data.mongodb.core.ReactiveMongoTemplate
import org.springframework.stereotype.Service
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
@@ -22,8 +20,6 @@ import java.time.ZoneId
import java.time.ZoneOffset
import java.util.Date
import kotlin.jvm.optionals.getOrNull
@Service
class CategoryService(
private val categoryRepo: CategoryRepo,
@@ -33,10 +29,6 @@ class CategoryService(
private val logger = LoggerFactory.getLogger(javaClass)
fun getCategoryByName(name: String): Mono<Category> {
return categoryRepo.findByName(name)
}
@Cacheable("getAllCategories")
fun getCategories(): Mono<List<Category>> {

View File

@@ -1,16 +0,0 @@
package space.luminic.budgerapp.services
import org.springframework.security.core.userdetails.ReactiveUserDetailsService
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
@Service
class CustomReactiveUserDetailsService(
private val userDetailsService: UserDetailsService // Ваш синхронный сервис
) : ReactiveUserDetailsService {
override fun findByUsername(username: String): Mono<UserDetails> {
return Mono.fromCallable { userDetailsService.loadUserByUsername(username) }
}
}

View File

@@ -6,7 +6,6 @@ import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.Cacheable
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.Budget
import space.luminic.budgerapp.models.NotFoundException
@@ -15,19 +14,12 @@ import space.luminic.budgerapp.models.Transaction
import space.luminic.budgerapp.models.TransactionType
import space.luminic.budgerapp.repos.RecurrentRepo
import space.luminic.budgerapp.repos.TransactionRepo
import space.luminic.budgerapp.repos.sqlrepo.RecurrentRepoSQL
import java.math.BigDecimal
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.YearMonth
import kotlin.jvm.optionals.getOrNull
@Service
class RecurrentService(
private val recurrentRepo: RecurrentRepo,
private val recurrentRepoSQL: RecurrentRepoSQL,
private val transactionRepo: TransactionRepo,
private val userService: UserService,
) {
@@ -120,9 +112,6 @@ class RecurrentService(
}
fun transferRecurrents() {
recurrentRepo.saveAll(recurrentRepoSQL.getRecurrents()).then().subscribe()
}
}

View File

@@ -1,16 +1,14 @@
package space.luminic.budgerapp.services
import com.interaso.webpush.VapidKeys
import com.interaso.webpush.WebPushService
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.slf4j.LoggerFactory
import org.springframework.dao.DuplicateKeyException
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.PushMessage
import space.luminic.budgerapp.models.Subscription
import space.luminic.budgerapp.models.SubscriptionDTO
@@ -19,7 +17,6 @@ import space.luminic.budgerapp.repos.SubscriptionRepo
import space.luminic.budgerapp.services.VapidConstants.VAPID_PRIVATE_KEY
import space.luminic.budgerapp.services.VapidConstants.VAPID_PUBLIC_KEY
import space.luminic.budgerapp.services.VapidConstants.VAPID_SUBJECT
import java.security.GeneralSecurityException
object VapidConstants {
const val VAPID_PUBLIC_KEY =

View File

@@ -1,6 +1,5 @@
package space.luminic.budgerapp.services
import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.Token
@@ -12,29 +11,28 @@ import java.time.LocalDateTime
class TokenService(private val tokenRepository: TokenRepo) {
@CacheEvict("tokens", allEntries = true)
fun saveToken(token: String, username: String, expiresAt: LocalDateTime) {
fun saveToken(token: String, username: String, expiresAt: LocalDateTime): Mono<Token> {
val newToken = Token(
token = token,
username = username,
issuedAt = LocalDateTime.now(),
expiresAt = expiresAt
)
tokenRepository.save(newToken)
return tokenRepository.save(newToken)
}
@CacheEvict("tokens", allEntries = true)
fun revokeToken(token: String): Mono<Void> {
return tokenRepository.findByToken(token)
.switchIfEmpty(Mono.error(Exception("Token not found")))
.flatMap { existingToken ->
val updatedToken = existingToken.copy(status = TokenStatus.REVOKED)
tokenRepository.save(updatedToken).then()
}
.switchIfEmpty(Mono.error(Exception("Token not found")))
}
@CacheEvict("tokens", allEntries = true)
fun deleteExpiredTokens() {
tokenRepository.deleteByExpiresAtBefore(LocalDateTime.now())

View File

@@ -1,9 +1,6 @@
package space.luminic.budgerapp.services
import com.mongodb.client.model.Aggregates.addFields
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import org.bson.Document
import org.bson.types.ObjectId
import org.slf4j.LoggerFactory
@@ -12,74 +9,44 @@ import org.springframework.cache.annotation.Cacheable
import org.springframework.context.ApplicationEventPublisher
import org.springframework.data.domain.Sort
import org.springframework.data.domain.Sort.Direction
import org.springframework.data.mongodb.MongoExpression
import org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.ReactiveMongoTemplate
import org.springframework.data.mongodb.core.aggregation.AddFieldsOperation
import org.springframework.data.mongodb.core.aggregation.Aggregation
import org.springframework.data.mongodb.core.aggregation.Aggregation.ROOT
import org.springframework.data.mongodb.core.aggregation.Aggregation.group
import org.springframework.data.mongodb.core.aggregation.Aggregation.limit
import org.springframework.data.mongodb.core.aggregation.Aggregation.lookup
import org.springframework.data.mongodb.core.aggregation.Aggregation.match
import org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation
import org.springframework.data.mongodb.core.aggregation.Aggregation.project
import org.springframework.data.mongodb.core.aggregation.Aggregation.skip
import org.springframework.data.mongodb.core.aggregation.Aggregation.sort
import org.springframework.data.mongodb.core.aggregation.Aggregation.unwind
import org.springframework.data.mongodb.core.aggregation.Aggregation.addFields
import org.springframework.data.mongodb.core.aggregation.Aggregation.limit
import org.springframework.data.mongodb.core.aggregation.Aggregation.skip
import org.springframework.data.mongodb.core.aggregation.AggregationExpression
import org.springframework.data.mongodb.core.aggregation.AggregationResults
import org.springframework.data.mongodb.core.aggregation.ArrayOperators
import org.springframework.data.mongodb.core.aggregation.ArrayOperators.Filter.filter
import org.springframework.data.mongodb.core.aggregation.ConditionalOperators
import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.IfNull.ifNull
import org.springframework.data.mongodb.core.aggregation.DateOperators
import org.springframework.data.mongodb.core.aggregation.DateOperators.DateToString
import org.springframework.data.mongodb.core.aggregation.LookupOperation
import org.springframework.data.mongodb.core.aggregation.MatchOperation
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.update
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.Budget
import space.luminic.budgerapp.models.Category
import space.luminic.budgerapp.models.CategoryType
import space.luminic.budgerapp.models.SortSetting
import space.luminic.budgerapp.models.SortTypes
import space.luminic.budgerapp.models.Transaction
import space.luminic.budgerapp.models.TransactionEvent
import space.luminic.budgerapp.models.TransactionEventType
import space.luminic.budgerapp.models.TransactionType
import space.luminic.budgerapp.models.User
import space.luminic.budgerapp.repos.TransactionRepo
import java.math.BigDecimal
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.temporal.TemporalAdjusters
import java.util.ArrayList
import java.util.Arrays
import java.util.Date
import kotlin.jvm.optionals.getOrNull
@Service
class TransactionService(
private val mongoTemplate: MongoTemplate,
private val reactiveMongoTemplate: ReactiveMongoTemplate,
val transactionsRepo: TransactionRepo,
val userService: UserService,
@@ -608,13 +575,6 @@ class TransactionService(
}
fun getCategoriesExplainReactive(pipeline: List<Document>): Mono<Document> {
val command = Document("aggregate", "transactions")
.append("pipeline", pipeline)
.append("explain", true)
return reactiveMongoTemplate.executeCommand(command)
}
private fun extractTransactions(aggregationResult: Document, key: String): Mono<List<Transaction>> {
val resultTransactions = aggregationResult[key] as? List<Document> ?: emptyList()
@@ -658,7 +618,7 @@ class TransactionService(
transactionType["code"] as String,
transactionType["name"] as String
),
user = user!!,
user = user,
category = category,
comment = document["comment"] as String,
date = (document["date"] as Date).toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
@@ -669,116 +629,4 @@ class TransactionService(
)
}
// fun getPlannedForBudget(budget: Budget, transactionType: String? = null): List<Map<String, Any>> {
// // 1) $lookup: "categories"
// val lookupCategories = Aggregation.lookup(
// "categories",
// "category.\$id",
// "_id",
// "categoryDetailed"
// )
//
// // 2) $lookup: "budgets" (pipeline + let)
// val matchBudgetsDoc = Document(
// "\$expr", Document(
// "\$and", listOf(
// Document("\$gte", listOf("\$\$transactionDate", "\$dateFrom")),
// Document("\$lt", listOf("\$\$transactionDate", "\$dateTo"))
// )
// )
// )
// val matchBudgetsOp = MatchOperation(matchBudgetsDoc)
//
// val lookupBudgets = LookupOperation.newLookup()
// .from("budgets")
// .letValueOf("transactionDate").bindTo("date")
// .pipeline(matchBudgetsOp)
// .`as`("budgetDetails")
//
// // 3) $unwind
// val unwindCategory = Aggregation.unwind("categoryDetailed")
// val unwindBudget = Aggregation.unwind("budgetDetails")
//
// // 4) $match: диапазон дат
// val matchDates = Aggregation.match(
// Criteria("date")
// .gte(budget.dateFrom)
// .lt(budget.dateTo)
// )
//
// // 5) $facet (разные ветки: plannedExpenses, plannedExpensesSum, ...)
// // plannedExpenses
// val plannedExpensesMatch = Aggregation.match(
// Criteria().andOperator(
// Criteria("type.code").`is`("PLANNED"),
// Criteria("categoryDetailed.type.code").`is`("EXPENSE")
// )
// )
// val plannedExpensesPipeline = listOf(plannedExpensesMatch)
//
// // plannedExpensesSum
// val plannedExpensesSumPipeline = listOf(
// plannedExpensesMatch,
// group(null).`as`("_id").sum("amount").`as`("sum"),
// project("sum").andExclude("_id")
// )
//
// // plannedIncome
// val plannedIncomeMatch = Aggregation.match(
// Criteria().andOperator(
// Criteria("type.code").`is`("PLANNED"),
// Criteria("categoryDetailed.type.code").`is`("INCOME")
// )
// )
// val plannedIncomePipeline = listOf(plannedIncomeMatch)
//
// // plannedIncomeSum
// val plannedIncomeSumPipeline = listOf(
// plannedIncomeMatch,
// group().`as`("_id").sum("amount").`as`("sum"),
// project("sum").andExclude("_id")
// )
//
// // instantTransactions
// val instantTransactionsMatch = Aggregation.match(
// Criteria("type.code").`is`("INSTANT")
// )
// val instantTransactionsProject = Aggregation.project(
// "_id", "type", "comment", "user", "amount", "date",
// "category", "isDone", "createdAt", "parentId"
// )
// val instantTransactionsPipeline = listOf(instantTransactionsMatch, instantTransactionsProject)
//
// val facetStage = Aggregation.facet(*plannedExpensesPipeline.toTypedArray()).`as`("plannedExpenses")
// .and(*plannedExpensesSumPipeline.toTypedArray()).`as`("plannedExpensesSum")
// .and(*plannedIncomePipeline.toTypedArray()).`as`("plannedIncome")
// .and(*plannedIncomeSumPipeline.toTypedArray()).`as`("plannedIncomeSum")
// .and(*instantTransactionsPipeline.toTypedArray()).`as`("instantTransactions")
//
// // 6) $set: вытаскиваем суммы из массивов
// val setStage = AddFieldsOperation.builder()
// .addField("plannedExpensesSum").withValue(
// ArrayOperators.ArrayElemAt.arrayOf("\$plannedExpensesSum.sum").elementAt(0)
// )
// .addField("plannedIncomeSum").withValue(
// ArrayOperators.ArrayElemAt.arrayOf("\$plannedIncomeSum.sum").elementAt(0)
// )
// .build()
//
// // Собираем все стадии
// val aggregation = Aggregation.newAggregation(
// lookupCategories,
// lookupBudgets,
// unwindCategory,
// unwindBudget,
// matchDates,
// facetStage,
// setStage
// )
//
// val results = mongoTemplate.aggregate(aggregation, "transactions", Map::class.java)
// return results.mappedResults
// }
}

View File

@@ -1,62 +0,0 @@
package space.luminic.budgerapp.services
import org.springframework.stereotype.Service
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.Budget
import space.luminic.budgerapp.models.Category
import space.luminic.budgerapp.models.Recurrent
import space.luminic.budgerapp.models.Transaction
import space.luminic.budgerapp.repos.BudgetRepo
import space.luminic.budgerapp.repos.CategoryRepo
import space.luminic.budgerapp.repos.RecurrentRepo
import space.luminic.budgerapp.repos.TransactionRepo
import space.luminic.budgerapp.repos.sqlrepo.BudgetRepoSQL
import space.luminic.budgerapp.repos.sqlrepo.CategoriesRepoSQL
import space.luminic.budgerapp.repos.sqlrepo.RecurrentRepoSQL
import space.luminic.budgerapp.repos.sqlrepo.TransactionsRepoSQl
@Service
class TransferService(
private val transactionsRepoSQl: TransactionsRepoSQl,
private val categoriesRepoSQL: CategoriesRepoSQL,
private val recurrentRepoSQL: RecurrentRepoSQL,
private val budgetRepoSQL: BudgetRepoSQL,
private val categoryRepo: CategoryRepo,
private val transactionRepo: TransactionRepo,
private val recurrentRepo: RecurrentRepo,
private val budgetService: BudgetService
) {
fun getTransactions(): Mono<List<Transaction>> {
val transactions = transactionsRepoSQl.getTransactions()
return transactionRepo.saveAll(transactions).collectList()
}
fun getCategories(): Mono<List<Category>> {
val categories = categoriesRepoSQL.getCategories()
return Flux.fromIterable(categories)
.flatMap { category -> categoryRepo.save(category) }
.collectList() // Преобразуем Flux<Category> в Mono<List<Category>>
}
fun recurrents(): Mono<List<Recurrent>> {
val recurrents = recurrentRepoSQL.getRecurrents()
return Flux.fromIterable(recurrents).flatMap { recurrent ->
recurrentRepo.save(recurrent)
}.collectList()
}
fun transferBudgets(): Mono<List<Budget>> {
val budgets = budgetRepoSQL.getBudgets()
return Flux.fromIterable(budgets)
.flatMap { budget ->
budgetService.createBudget(budget.budget, budget.createRecurrent)
}.collectList()
}
}

View File

@@ -3,27 +3,17 @@ package space.luminic.budgerapp.services
import org.slf4j.LoggerFactory
import org.springframework.cache.annotation.Cacheable
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.NotFoundException
import space.luminic.budgerapp.models.User
import space.luminic.budgerapp.repos.UserRepo
import kotlin.jvm.optionals.getOrNull
@Service
class UserService(val userRepo: UserRepo, val passwordEncoder: PasswordEncoder) {
class UserService(val userRepo: UserRepo) {
val logger = LoggerFactory.getLogger(javaClass)
// fun regenPass(): List<User>? {
// var users = getUsers()!!.toMutableList()
// for (user in users) {
// user.password = passwordEncoder.encode(user.password)
// }
// userRepo.saveAll<User>(users)
// return users
// }
@Cacheable("users", key = "#username")
fun getByUsername(username: String): Mono<User> {
@@ -47,6 +37,7 @@ class UserService(val userRepo: UserRepo, val passwordEncoder: PasswordEncoder)
return userRepo.findByUsernameWOPassword(username)
}
@Cacheable("usersList")
fun getUsers(): Mono<List<User>> {
return userRepo.findAll()
.map { user -> user.apply { password = null } } // Убираем пароль