some
This commit is contained in:
@@ -37,7 +37,7 @@ class AuthController(
|
|||||||
fun getMe(@RequestHeader("Authorization") token: String): Mono<User> {
|
fun getMe(@RequestHeader("Authorization") token: String): Mono<User> {
|
||||||
return authService.isTokenValid(token.removePrefix("Bearer "))
|
return authService.isTokenValid(token.removePrefix("Bearer "))
|
||||||
.flatMap { username ->
|
.flatMap { username ->
|
||||||
userService.getByUserNameWoPass(username.username)
|
userService.getByUserNameWoPass(username.username!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ import org.springframework.http.HttpStatus
|
|||||||
import org.springframework.http.ResponseEntity
|
import org.springframework.http.ResponseEntity
|
||||||
import org.springframework.web.bind.annotation.*
|
import org.springframework.web.bind.annotation.*
|
||||||
import org.springframework.web.client.HttpClientErrorException
|
import org.springframework.web.client.HttpClientErrorException
|
||||||
import reactor.core.publisher.Flux
|
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
import space.luminic.budgerapp.controllers.BudgetController.LimitValue
|
import space.luminic.budgerapp.controllers.BudgetController.LimitValue
|
||||||
import space.luminic.budgerapp.controllers.dtos.BudgetCreationDTO
|
|
||||||
import space.luminic.budgerapp.models.*
|
import space.luminic.budgerapp.models.*
|
||||||
import space.luminic.budgerapp.services.CategoryService
|
import space.luminic.budgerapp.services.CategoryService
|
||||||
import space.luminic.budgerapp.services.FinancialService
|
import space.luminic.budgerapp.services.FinancialService
|
||||||
@@ -103,10 +101,10 @@ class SpaceController(
|
|||||||
@PostMapping("/{spaceId}/budgets")
|
@PostMapping("/{spaceId}/budgets")
|
||||||
fun createBudget(
|
fun createBudget(
|
||||||
@PathVariable spaceId: String,
|
@PathVariable spaceId: String,
|
||||||
@RequestBody budgetCreationDTO: BudgetCreationDTO,
|
@RequestBody budget: Budget
|
||||||
): Mono<Budget> {
|
): Mono<Budget> {
|
||||||
return spaceService.isValidRequest(spaceId).flatMap {
|
return spaceService.isValidRequest(spaceId).flatMap {
|
||||||
financialService.createBudget(it, budgetCreationDTO.budget, budgetCreationDTO.createRecurrent)
|
financialService.createBudget(it, budget)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -304,7 +302,7 @@ class SpaceController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/{spaceId}/recurrent")
|
@PostMapping("/{spaceId}/recurrents")
|
||||||
fun createRecurrent(@PathVariable spaceId: String, @RequestBody recurrent: Recurrent): Mono<Recurrent> {
|
fun createRecurrent(@PathVariable spaceId: String, @RequestBody recurrent: Recurrent): Mono<Recurrent> {
|
||||||
return spaceService.isValidRequest(spaceId).flatMap {
|
return spaceService.isValidRequest(spaceId).flatMap {
|
||||||
recurrentService.createRecurrent(it, recurrent)
|
recurrentService.createRecurrent(it, recurrent)
|
||||||
@@ -312,7 +310,7 @@ class SpaceController(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{spaceId}/recurrent/{id}")
|
@PutMapping("/{spaceId}/recurrents/{id}")
|
||||||
fun editRecurrent(
|
fun editRecurrent(
|
||||||
@PathVariable spaceId: String,
|
@PathVariable spaceId: String,
|
||||||
@PathVariable id: String,
|
@PathVariable id: String,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class CategoryMapper : FromDocumentMapper {
|
|||||||
override fun fromDocument(document: Document): Category {
|
override fun fromDocument(document: Document): Category {
|
||||||
val categoryTypeDocument = document["type"] as Document
|
val categoryTypeDocument = document["type"] as Document
|
||||||
val spaceDocument = document.get("spaceDetails", Document::class.java) ?: Document()
|
val spaceDocument = document.get("spaceDetails", Document::class.java) ?: Document()
|
||||||
val spaceId = spaceDocument.get("_id", String::class.java)?:null
|
val spaceId = spaceDocument.get("_id", ObjectId::class.java)?:null
|
||||||
val tags = document.getList("tags", Document::class.java) ?: emptyList()
|
val tags = document.getList("tags", Document::class.java) ?: emptyList()
|
||||||
|
|
||||||
val categoryTags = tags.map { tag ->
|
val categoryTags = tags.map { tag ->
|
||||||
@@ -22,7 +22,7 @@ class CategoryMapper : FromDocumentMapper {
|
|||||||
}.toMutableSet()
|
}.toMutableSet()
|
||||||
return Category(
|
return Category(
|
||||||
id = (document["_id"] as ObjectId).toString(),
|
id = (document["_id"] as ObjectId).toString(),
|
||||||
space = Space(id = spaceId),
|
space = Space(id = spaceId.toString()),
|
||||||
type = CategoryType(
|
type = CategoryType(
|
||||||
categoryTypeDocument["code"] as String,
|
categoryTypeDocument["code"] as String,
|
||||||
categoryTypeDocument["name"] as String
|
categoryTypeDocument["name"] as String
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
package space.luminic.budgerapp.models
|
package space.luminic.budgerapp.models
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||||
import jakarta.validation.constraints.NotBlank
|
|
||||||
import org.springframework.data.annotation.Id
|
import org.springframework.data.annotation.Id
|
||||||
import org.springframework.data.mongodb.core.mapping.Document
|
import org.springframework.data.mongodb.core.mapping.Document
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
@Document("users")
|
@Document("users")
|
||||||
data class User (
|
data class User(
|
||||||
@Id
|
@Id
|
||||||
var id: String? = null,
|
var id: String? = null,
|
||||||
@field:NotBlank val username: String,
|
val username: String? = null,
|
||||||
var firstName: String,
|
var firstName: String? = null,
|
||||||
var tgId: String? = null,
|
var tgId: String? = null,
|
||||||
var tgUserName: String? = null,
|
var tgUserName: String? = null,
|
||||||
@JsonIgnore // Скрывает пароль при сериализации
|
@JsonIgnore // Скрывает пароль при сериализации
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class AuthService(
|
|||||||
return userRepository.findByUsername(username)
|
return userRepository.findByUsername(username)
|
||||||
.flatMap { user ->
|
.flatMap { user ->
|
||||||
if (passwordEncoder.matches(password, user.password)) {
|
if (passwordEncoder.matches(password, user.password)) {
|
||||||
val token = jwtUtil.generateToken(user.username)
|
val token = jwtUtil.generateToken(user.username!!)
|
||||||
val expireAt = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 10)
|
val expireAt = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 10)
|
||||||
tokenService.saveToken(
|
tokenService.saveToken(
|
||||||
token = token,
|
token = token,
|
||||||
@@ -48,7 +48,7 @@ class AuthService(
|
|||||||
.switchIfEmpty(Mono.error(AuthException("Invalid credentials")))
|
.switchIfEmpty(Mono.error(AuthException("Invalid credentials")))
|
||||||
.flatMap { user ->
|
.flatMap { user ->
|
||||||
println("here")
|
println("here")
|
||||||
val token = jwtUtil.generateToken(user.username)
|
val token = jwtUtil.generateToken(user.username!!)
|
||||||
val expireAt = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 10)
|
val expireAt = Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 10)
|
||||||
tokenService.saveToken(
|
tokenService.saveToken(
|
||||||
token = token,
|
token = token,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import reactor.core.publisher.Flux
|
|||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
import space.luminic.budgerapp.mappers.CategoryMapper
|
import space.luminic.budgerapp.mappers.CategoryMapper
|
||||||
import space.luminic.budgerapp.models.*
|
import space.luminic.budgerapp.models.*
|
||||||
|
import space.luminic.budgerapp.repos.BudgetRepo
|
||||||
import space.luminic.budgerapp.repos.CategoryRepo
|
import space.luminic.budgerapp.repos.CategoryRepo
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -24,16 +25,14 @@ class CategoryService(
|
|||||||
private val categoryRepo: CategoryRepo,
|
private val categoryRepo: CategoryRepo,
|
||||||
private val financialService: FinancialService,
|
private val financialService: FinancialService,
|
||||||
private val mongoTemplate: ReactiveMongoTemplate,
|
private val mongoTemplate: ReactiveMongoTemplate,
|
||||||
private val eventPublisher: ApplicationEventPublisher,
|
|
||||||
private val categoryMapper: CategoryMapper,
|
private val categoryMapper: CategoryMapper,
|
||||||
|
private val budgetRepo: BudgetRepo,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(javaClass)
|
private val logger = LoggerFactory.getLogger(javaClass)
|
||||||
|
|
||||||
fun getCategory(id: String): Mono<Category> {
|
|
||||||
return categoryRepo.findById(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun findCategory(
|
fun findCategory(
|
||||||
space: Space? = null,
|
space: Space? = null,
|
||||||
@@ -115,7 +114,7 @@ class CategoryService(
|
|||||||
|
|
||||||
@Cacheable("categoryTypes")
|
@Cacheable("categoryTypes")
|
||||||
fun getCategoryTypes(): List<CategoryType> {
|
fun getCategoryTypes(): List<CategoryType> {
|
||||||
var types = mutableListOf<CategoryType>()
|
val types = mutableListOf<CategoryType>()
|
||||||
types.add(CategoryType("EXPENSE", "Траты"))
|
types.add(CategoryType("EXPENSE", "Траты"))
|
||||||
types.add(CategoryType("INCOME", "Поступления"))
|
types.add(CategoryType("INCOME", "Поступления"))
|
||||||
return types
|
return types
|
||||||
@@ -135,12 +134,13 @@ class CategoryService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun deleteCategory(space: Space, categoryId: String): Mono<String> {
|
fun deleteCategory(space: Space, categoryId: String): Mono<String> {
|
||||||
return findCategory(space, id = categoryId).switchIfEmpty(
|
return findCategory(space, categoryId).switchIfEmpty(
|
||||||
Mono.error(IllegalArgumentException("Category with id: $categoryId not found"))
|
Mono.error(IllegalArgumentException("Category with id: $categoryId not found"))
|
||||||
).flatMap {
|
).flatMap { categoryToDelete ->
|
||||||
financialService.getTransactions(space.id!!, categoryId = categoryId)
|
financialService.getTransactions(space.id!!, categoryId = categoryId)
|
||||||
.flatMapMany { transactions ->
|
.flatMapMany { transactions ->
|
||||||
findCategory(space, name = "Другое").switchIfEmpty(
|
findCategory(space, name = "Другое")
|
||||||
|
.switchIfEmpty(
|
||||||
categoryRepo.save(
|
categoryRepo.save(
|
||||||
Category(
|
Category(
|
||||||
space = space,
|
space = space,
|
||||||
@@ -150,15 +150,25 @@ class CategoryService(
|
|||||||
icon = "🚮"
|
icon = "🚮"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).flatMapMany { category ->
|
)
|
||||||
|
.flatMapMany { otherCategory ->
|
||||||
Flux.fromIterable(transactions).flatMap { transaction ->
|
Flux.fromIterable(transactions).flatMap { transaction ->
|
||||||
transaction.category = category // Присваиваем конкретный объект категории
|
transaction.category = otherCategory
|
||||||
financialService.editTransaction(transaction) // Сохраняем изменения
|
financialService.editTransaction(transaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.then(categoryRepo.deleteById(categoryId)) // Удаляем старую категорию
|
.then(
|
||||||
.thenReturn(categoryId) // Возвращаем удалённую категорию
|
financialService.findProjectedBudgets(ObjectId(space.id))
|
||||||
|
.flatMapMany { budgets ->
|
||||||
|
Flux.fromIterable(budgets).flatMap { budget ->
|
||||||
|
budget.categories.removeIf { it.category.id == categoryId }
|
||||||
|
budgetRepo.save(budget)
|
||||||
|
}
|
||||||
|
}.collectList()
|
||||||
|
)
|
||||||
|
.then(categoryRepo.deleteById(categoryId)) // Удаление категории
|
||||||
|
.thenReturn(categoryId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package space.luminic.budgerapp.services
|
package space.luminic.budgerapp.services
|
||||||
|
|
||||||
import com.mongodb.DBRef
|
|
||||||
import org.bson.BsonNull
|
import org.bson.BsonNull
|
||||||
import org.bson.Document
|
import org.bson.Document
|
||||||
import org.bson.types.ObjectId
|
import org.bson.types.ObjectId
|
||||||
@@ -12,9 +11,7 @@ import org.springframework.data.domain.Sort.Direction
|
|||||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate
|
import org.springframework.data.mongodb.core.ReactiveMongoTemplate
|
||||||
import org.springframework.data.mongodb.core.aggregation.Aggregation.*
|
import org.springframework.data.mongodb.core.aggregation.Aggregation.*
|
||||||
import org.springframework.data.mongodb.core.aggregation.DateOperators.DateToString
|
import org.springframework.data.mongodb.core.aggregation.DateOperators.DateToString
|
||||||
import org.springframework.data.mongodb.core.aggregation.SortOperation
|
|
||||||
import org.springframework.data.mongodb.core.query.Criteria
|
import org.springframework.data.mongodb.core.query.Criteria
|
||||||
import org.springframework.data.mongodb.core.query.Query
|
|
||||||
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.Flux
|
||||||
@@ -36,7 +33,6 @@ class FinancialService(
|
|||||||
val budgetRepo: BudgetRepo,
|
val budgetRepo: BudgetRepo,
|
||||||
val warnRepo: WarnRepo,
|
val warnRepo: WarnRepo,
|
||||||
val transactionsRepo: TransactionRepo,
|
val transactionsRepo: TransactionRepo,
|
||||||
val recurrentService: RecurrentService,
|
|
||||||
val userService: UserService,
|
val userService: UserService,
|
||||||
val reactiveMongoTemplate: ReactiveMongoTemplate,
|
val reactiveMongoTemplate: ReactiveMongoTemplate,
|
||||||
private val categoryRepo: CategoryRepo,
|
private val categoryRepo: CategoryRepo,
|
||||||
@@ -211,7 +207,6 @@ class FinancialService(
|
|||||||
val unwindSpace = unwind("spaceDetails")
|
val unwindSpace = unwind("spaceDetails")
|
||||||
val matchStage = match(Criteria.where("spaceDetails._id").`is`(spaceId))
|
val matchStage = match(Criteria.where("spaceDetails._id").`is`(spaceId))
|
||||||
// matchCriteria.add(Criteria.where("spaceDetails._id").`is`(ObjectId(spaceId)))
|
// matchCriteria.add(Criteria.where("spaceDetails._id").`is`(ObjectId(spaceId)))
|
||||||
val projectStage = project("_id", "name", "dateFrom", "dateTo") // Оставляем только нужные поля
|
|
||||||
val sort = sortRequested?.let { sort(it) } ?: sort(
|
val sort = sortRequested?.let { sort(it) } ?: sort(
|
||||||
Sort.by(Direction.DESC, "date").and(Sort.by(Direction.DESC, "createdAt"))
|
Sort.by(Direction.DESC, "date").and(Sort.by(Direction.DESC, "createdAt"))
|
||||||
)
|
)
|
||||||
@@ -229,11 +224,9 @@ class FinancialService(
|
|||||||
spaceId: String, budgetId: String? = null, dateFrom: LocalDate? = null, dateTo: LocalDate? = null
|
spaceId: String, budgetId: String? = null, dateFrom: LocalDate? = null, dateTo: LocalDate? = null
|
||||||
): Mono<Budget> {
|
): Mono<Budget> {
|
||||||
val lookupCategories = lookup("categories", "categories.category.\$id", "_id", "categoriesDetails")
|
val lookupCategories = lookup("categories", "categories.category.\$id", "_id", "categoriesDetails")
|
||||||
val unwindCategories = unwind("categoriesDetails")
|
|
||||||
|
|
||||||
val lookupIncomeCategories =
|
val lookupIncomeCategories =
|
||||||
lookup("categories", "incomeCategories.category.\$id", "_id", "incomeCategoriesDetails")
|
lookup("categories", "incomeCategories.category.\$id", "_id", "incomeCategoriesDetails")
|
||||||
val unwindIncomeCategories = unwind("incomeCategoriesDetails")
|
|
||||||
val lookupSpace = lookup("spaces", "space.\$id", "_id", "spaceDetails")
|
val lookupSpace = lookup("spaces", "space.\$id", "_id", "spaceDetails")
|
||||||
val unwindSpace = unwind("spaceDetails")
|
val unwindSpace = unwind("spaceDetails")
|
||||||
val matchCriteria = mutableListOf<Criteria>()
|
val matchCriteria = mutableListOf<Criteria>()
|
||||||
@@ -354,7 +347,7 @@ class FinancialService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun createBudget(space: Space, budget: Budget, createRecurrent: Boolean): Mono<Budget> {
|
fun createBudget(space: Space, budget: Budget): Mono<Budget> {
|
||||||
return Mono.zip(getBudgetByDate(budget.dateFrom, space.id!!).map { Optional.ofNullable(it) }
|
return Mono.zip(getBudgetByDate(budget.dateFrom, space.id!!).map { Optional.ofNullable(it) }
|
||||||
.switchIfEmpty(Mono.just(Optional.empty())),
|
.switchIfEmpty(Mono.just(Optional.empty())),
|
||||||
getBudgetByDate(budget.dateTo, space.id!!).map { Optional.ofNullable(it) }
|
getBudgetByDate(budget.dateTo, space.id!!).map { Optional.ofNullable(it) }
|
||||||
@@ -367,21 +360,8 @@ class FinancialService(
|
|||||||
return@flatMap Mono.error<Budget>(IllegalArgumentException("Бюджет с теми же датами найден"))
|
return@flatMap Mono.error<Budget>(IllegalArgumentException("Бюджет с теми же датами найден"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Получаем Space по spaceId
|
|
||||||
|
|
||||||
|
|
||||||
// Присваиваем Space бюджету
|
|
||||||
budget.space = space
|
budget.space = space
|
||||||
|
|
||||||
// Если createRecurrent=true, создаем рекуррентные транзакции
|
|
||||||
val recurrentsCreation = if (createRecurrent) {
|
|
||||||
recurrentService.createRecurrentsForBudget(space, budget)
|
|
||||||
} else {
|
|
||||||
Mono.empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Создаем бюджет после возможного создания рекуррентных транзакций
|
|
||||||
recurrentsCreation.then(
|
|
||||||
getCategoryTransactionPipeline(
|
getCategoryTransactionPipeline(
|
||||||
space.id!!,
|
space.id!!,
|
||||||
budget.dateFrom,
|
budget.dateFrom,
|
||||||
@@ -395,7 +375,7 @@ class FinancialService(
|
|||||||
// Логируем ошибку, если произошла
|
// Логируем ошибку, если произошла
|
||||||
logger.error("Error during updateBudgetWarns: ${error.message}")
|
logger.error("Error during updateBudgetWarns: ${error.message}")
|
||||||
}.subscribe()
|
}.subscribe()
|
||||||
}).then(
|
}.then(
|
||||||
getCategoryTransactionPipeline(
|
getCategoryTransactionPipeline(
|
||||||
space.id!!,
|
space.id!!,
|
||||||
budget.dateFrom,
|
budget.dateFrom,
|
||||||
@@ -636,7 +616,7 @@ class FinancialService(
|
|||||||
dateTo?.let { matchCriteria.add(Criteria.where("date").lt(it)) }
|
dateTo?.let { matchCriteria.add(Criteria.where("date").lt(it)) }
|
||||||
transactionType?.let { matchCriteria.add(Criteria.where("type.code").`is`(it)) }
|
transactionType?.let { matchCriteria.add(Criteria.where("type.code").`is`(it)) }
|
||||||
isDone?.let { matchCriteria.add(Criteria.where("isDone").`is`(it)) }
|
isDone?.let { matchCriteria.add(Criteria.where("isDone").`is`(it)) }
|
||||||
categoryId?.let { matchCriteria.add(Criteria.where("categoryDetails._id").`is`(it)) }
|
categoryId?.let { matchCriteria.add(Criteria.where("categoryDetails._id").`is`(ObjectId(it))) }
|
||||||
categoryType?.let {
|
categoryType?.let {
|
||||||
matchCriteria.add(
|
matchCriteria.add(
|
||||||
Criteria.where("categoryDetails.type.code").`is`(it)
|
Criteria.where("categoryDetails.type.code").`is`(it)
|
||||||
@@ -1144,7 +1124,6 @@ class FinancialService(
|
|||||||
|
|
||||||
private fun documentToTransactionMapper(document: Document): Transaction {
|
private fun documentToTransactionMapper(document: Document): Transaction {
|
||||||
val transactionType = document["type"] as Document
|
val transactionType = document["type"] as Document
|
||||||
var user: User?
|
|
||||||
|
|
||||||
val userDocument = document["userDetailed"] as Document
|
val userDocument = document["userDetailed"] as Document
|
||||||
user = User(
|
user = User(
|
||||||
@@ -1345,7 +1324,7 @@ class FinancialService(
|
|||||||
|
|
||||||
|
|
||||||
fun getCategoryTransactionPipeline(
|
fun getCategoryTransactionPipeline(
|
||||||
spaceId: String, dateFrom: LocalDate, dateTo: LocalDate, catType: String? = "EXPENSE"
|
spaceId: String, dateFrom: LocalDate, dateTo: LocalDate, categoryType: String? = "EXPENSE"
|
||||||
): Mono<MutableList<BudgetCategory>> {
|
): Mono<MutableList<BudgetCategory>> {
|
||||||
val pipeline = listOf(
|
val pipeline = listOf(
|
||||||
Document(
|
Document(
|
||||||
@@ -1358,7 +1337,7 @@ class FinancialService(
|
|||||||
"\$match", Document(
|
"\$match", Document(
|
||||||
Document("spaceDetailed._id", ObjectId(spaceId))
|
Document("spaceDetailed._id", ObjectId(spaceId))
|
||||||
)
|
)
|
||||||
), Document("\$match", Document("type.code", catType)), Document(
|
), Document("\$match", Document("type.code", categoryType)), Document(
|
||||||
"\$lookup", Document("from", "transactions").append(
|
"\$lookup", Document("from", "transactions").append(
|
||||||
"let", Document("categoryId", "\$_id")
|
"let", Document("categoryId", "\$_id")
|
||||||
).append(
|
).append(
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ 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.Flux
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
import space.luminic.budgerapp.models.Category
|
import space.luminic.budgerapp.models.*
|
||||||
import space.luminic.budgerapp.models.Space
|
|
||||||
import space.luminic.budgerapp.models.SpaceInvite
|
|
||||||
import space.luminic.budgerapp.models.Tag
|
|
||||||
import space.luminic.budgerapp.repos.*
|
import space.luminic.budgerapp.repos.*
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
@@ -23,7 +20,6 @@ class SpaceService(
|
|||||||
private val spaceRepo: SpaceRepo,
|
private val spaceRepo: SpaceRepo,
|
||||||
private val userService: UserService,
|
private val userService: UserService,
|
||||||
private val budgetRepo: BudgetRepo,
|
private val budgetRepo: BudgetRepo,
|
||||||
private val userRepo: UserRepo,
|
|
||||||
private val reactiveMongoTemplate: ReactiveMongoTemplate,
|
private val reactiveMongoTemplate: ReactiveMongoTemplate,
|
||||||
private val categoryRepo: CategoryRepo,
|
private val categoryRepo: CategoryRepo,
|
||||||
private val recurrentRepo: RecurrentRepo,
|
private val recurrentRepo: RecurrentRepo,
|
||||||
@@ -44,7 +40,7 @@ class SpaceService(
|
|||||||
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
|
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
|
||||||
.flatMap { user ->
|
.flatMap { user ->
|
||||||
// Получаем пространство по ID
|
// Получаем пространство по ID
|
||||||
spaceRepo.findById(spaceId)
|
getSpace(spaceId)
|
||||||
.switchIfEmpty(Mono.error(IllegalArgumentException("Space not found for id: $spaceId")))
|
.switchIfEmpty(Mono.error(IllegalArgumentException("Space not found for id: $spaceId")))
|
||||||
.flatMap { space ->
|
.flatMap { space ->
|
||||||
// Проверяем доступ пользователя к пространству
|
// Проверяем доступ пользователя к пространству
|
||||||
@@ -65,10 +61,51 @@ class SpaceService(
|
|||||||
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 ->
|
.flatMap { user ->
|
||||||
spaceRepo.findByArrayElement(ObjectId(user.id!!))
|
val userId = ObjectId(user.id!!)
|
||||||
|
|
||||||
|
// Поиск пространств пользователя
|
||||||
|
|
||||||
|
|
||||||
|
// Агрегация для загрузки владельца и пользователей
|
||||||
|
val lookupOwner = lookup("users", "owner.\$id", "_id", "ownerDetails")
|
||||||
|
val unwindOwner = unwind("ownerDetails")
|
||||||
|
|
||||||
|
val lookupUsers = lookup("users", "users.\$id", "_id", "usersDetails")
|
||||||
|
// val unwindUsers = unwind("usersDetails")
|
||||||
|
|
||||||
|
val matchStage = match(Criteria.where("usersDetails._id").`is`(userId))
|
||||||
|
val aggregation = newAggregation(lookupOwner, unwindOwner, lookupUsers, matchStage)
|
||||||
|
|
||||||
|
reactiveMongoTemplate.aggregate(aggregation, "spaces", Document::class.java)
|
||||||
|
.collectList()
|
||||||
|
.map { docs ->
|
||||||
|
docs.map { doc ->
|
||||||
|
val ownerDoc = doc.get("ownerDetails", Document::class.java)
|
||||||
|
val usersDocList = doc.getList("usersDetails", Document::class.java)
|
||||||
|
|
||||||
|
Space(
|
||||||
|
id = doc.getObjectId("_id").toString(),
|
||||||
|
name = doc.getString("name"),
|
||||||
|
description = doc.getString("description"),
|
||||||
|
owner = User(
|
||||||
|
id = ownerDoc.getObjectId("_id").toString(),
|
||||||
|
username = ownerDoc.getString("username"),
|
||||||
|
firstName = ownerDoc.getString("firstName")
|
||||||
|
),
|
||||||
|
users = usersDocList.map { userDoc ->
|
||||||
|
User(
|
||||||
|
id = userDoc.getObjectId("_id").toString(),
|
||||||
|
username = userDoc.getString("username"),
|
||||||
|
firstName = userDoc.getString("firstName")
|
||||||
|
)
|
||||||
|
}.toMutableList()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.collectList() // Возвращаем Mono<List<Space>>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,12 +131,10 @@ class SpaceService(
|
|||||||
|
|
||||||
reactiveMongoTemplate.find(Query(), Category::class.java, "categories-etalon")
|
reactiveMongoTemplate.find(Query(), Category::class.java, "categories-etalon")
|
||||||
.map { category ->
|
.map { category ->
|
||||||
category.copy(
|
category.copy(id = null, space = savedSpace) // Создаем новую копию
|
||||||
id = null,
|
|
||||||
space = savedSpace
|
|
||||||
) // Создаем новую копию без id (чтобы создать новый документ)
|
|
||||||
}
|
}
|
||||||
.flatMap { categoryRepo.save(it) }
|
.collectList() // Собираем в список перед сохранением
|
||||||
|
.flatMap { categoryRepo.saveAll(it).collectList() } // Сохраняем и возвращаем список
|
||||||
.then(Mono.just(savedSpace)) // После сохранения всех категорий, возвращаем пространство
|
.then(Mono.just(savedSpace)) // После сохранения всех категорий, возвращаем пространство
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,25 +146,17 @@ class SpaceService(
|
|||||||
|
|
||||||
return Mono.`when`(
|
return Mono.`when`(
|
||||||
financialService.findProjectedBudgets(objectId)
|
financialService.findProjectedBudgets(objectId)
|
||||||
.flatMapMany { Flux.fromIterable(it) }
|
.flatMap { budgetRepo.deleteAll(it) },
|
||||||
.flatMap { budgetRepo.deleteById(it.id!!) }
|
|
||||||
.then(),
|
|
||||||
|
|
||||||
financialService.getTransactions(objectId.toString())
|
financialService.getTransactions(objectId.toString())
|
||||||
.flatMapMany { Flux.fromIterable(it) }
|
.flatMap { transactionRepo.deleteAll(it) },
|
||||||
.flatMap { transactionRepo.deleteById(it.id!!) }
|
|
||||||
.then(),
|
|
||||||
|
|
||||||
categoryService.getCategories(objectId.toString(), null, "name", "ASC")
|
categoryService.getCategories(objectId.toString(), null, "name", "ASC")
|
||||||
.flatMapMany { Flux.fromIterable(it) }
|
.flatMap { categoryRepo.deleteAll(it) },
|
||||||
.flatMap { categoryRepo.deleteById(it.id!!) }
|
|
||||||
.then(),
|
|
||||||
|
|
||||||
recurrentService.getRecurrents(objectId.toString())
|
recurrentService.getRecurrents(objectId.toString())
|
||||||
.flatMapMany { Flux.fromIterable(it) }
|
.flatMap { recurrentRepo.deleteAll(it) }
|
||||||
.flatMap { recurrentRepo.deleteById(it.id!!) }
|
).then(spaceRepo.deleteById(space.id!!)) // Удаление Space после завершения всех операций
|
||||||
.then()
|
|
||||||
).then(spaceRepo.deleteById(space.id!!)) // Исправлено: удаление по ID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -331,7 +358,7 @@ class SpaceService(
|
|||||||
return reactiveMongoTemplate.aggregate(
|
return reactiveMongoTemplate.aggregate(
|
||||||
aggregation, "tags", Document::class.java
|
aggregation, "tags", Document::class.java
|
||||||
)
|
)
|
||||||
.collectList() // Преобразуем Flux<Transaction> в Mono<List<Transaction>>
|
.collectList()
|
||||||
.map { docs ->
|
.map { docs ->
|
||||||
docs.map { doc ->
|
docs.map { doc ->
|
||||||
Tag(
|
Tag(
|
||||||
@@ -347,7 +374,7 @@ class SpaceService(
|
|||||||
fun regenSpaceCategory(): Mono<Category> {
|
fun regenSpaceCategory(): Mono<Category> {
|
||||||
return getSpace("67af3c0f652da946a7dd9931")
|
return getSpace("67af3c0f652da946a7dd9931")
|
||||||
.flatMap { space ->
|
.flatMap { space ->
|
||||||
categoryService.findCategory(id= "677bc767c7857460a491bd4f")
|
categoryService.findCategory(id = "677bc767c7857460a491bd4f")
|
||||||
.flatMap { category -> // заменил map на flatMap
|
.flatMap { category -> // заменил map на flatMap
|
||||||
category.space = space
|
category.space = space
|
||||||
category.name = "Сбережения"
|
category.name = "Сбережения"
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
"as": "categoryDetails"
|
"as": "categoryDetails"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$unwind": "$categoryDetails"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$lookup": {
|
"$lookup": {
|
||||||
"from": "spaces",
|
"from": "spaces",
|
||||||
@@ -15,6 +18,9 @@
|
|||||||
"as": "spaceDetails"
|
"as": "spaceDetails"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$unwind": "$spaceDetails"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$lookup": {
|
"$lookup": {
|
||||||
"from": "users",
|
"from": "users",
|
||||||
@@ -23,16 +29,19 @@
|
|||||||
"as": "userDetails"
|
"as": "userDetails"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$unwind": "$userDetails"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$match": {
|
"$match": {
|
||||||
"$and": [
|
"$and": [
|
||||||
{
|
{
|
||||||
"spaceDetails._id": {
|
"spaceDetails._id": {
|
||||||
"$oid": "67af52e8b0aa7b0f7f74b491"
|
"$oid": "67af3c0f652da946a7dd9931"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type.code": "INSTANT"
|
"categoryDetails._id": "67b83f3c1fc0575a3f0a3847"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -42,11 +51,5 @@
|
|||||||
"date": -1,
|
"date": -1,
|
||||||
"createdAt": -1
|
"createdAt": -1
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"$skip": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$limit": 10
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
Reference in New Issue
Block a user