632 lines
29 KiB
Kotlin
632 lines
29 KiB
Kotlin
//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.context.ApplicationEventPublisher
|
|
//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.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.DateOperators.DateToString
|
|
//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.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.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.time.LocalDate
|
|
//import java.time.LocalDateTime
|
|
//import java.time.LocalTime
|
|
//import java.time.ZoneId
|
|
//import java.time.ZoneOffset
|
|
//import java.time.temporal.TemporalAdjusters
|
|
//import java.util.ArrayList
|
|
//import java.util.Date
|
|
//
|
|
//@Service
|
|
//class TransactionService(
|
|
// private val reactiveMongoTemplate: ReactiveMongoTemplate,
|
|
// val transactionsRepo: TransactionRepo,
|
|
// val userService: UserService,
|
|
// private val eventPublisher: ApplicationEventPublisher
|
|
//) {
|
|
//
|
|
// private val logger = LoggerFactory.getLogger(TransactionService::class.java)
|
|
//
|
|
// @Cacheable("transactions")
|
|
// fun getTransactions(
|
|
// dateFrom: LocalDate? = null,
|
|
// dateTo: LocalDate? = null,
|
|
// transactionType: String? = null,
|
|
// isDone: Boolean? = null,
|
|
// categoryId: String? = null,
|
|
// categoryType: String? = null,
|
|
// userId: String? = null,
|
|
// parentId: String? = null,
|
|
// isChild: Boolean? = null,
|
|
// sortSetting: SortSetting? = null,
|
|
// limit: Int? = null,
|
|
// offset: Int? = null,
|
|
// ): Mono<MutableList<Transaction>> {
|
|
// val matchCriteria = mutableListOf<Criteria>()
|
|
//
|
|
// // Добавляем фильтры
|
|
// dateFrom?.let { matchCriteria.add(Criteria.where("date").gte(it)) }
|
|
// dateTo?.let { matchCriteria.add(Criteria.where("date").lt(it)) }
|
|
// transactionType?.let { matchCriteria.add(Criteria.where("type.code").`is`(it)) }
|
|
// isDone?.let { matchCriteria.add(Criteria.where("isDone").`is`(it)) }
|
|
// categoryId?.let { matchCriteria.add(Criteria.where("categoryDetails._id").`is`(it)) }
|
|
// categoryType?.let { matchCriteria.add(Criteria.where("categoryDetails.type.code").`is`(it)) }
|
|
// userId?.let { matchCriteria.add(Criteria.where("userDetails._id").`is`(ObjectId(it))) }
|
|
// parentId?.let { matchCriteria.add(Criteria.where("parentId").`is`(it)) }
|
|
// isChild?.let { matchCriteria.add(Criteria.where("parentId").exists(it)) }
|
|
//
|
|
// // Сборка агрегации
|
|
// val lookup = lookup("categories", "category.\$id", "_id", "categoryDetails")
|
|
// val lookupUsers = lookup("users", "user.\$id", "_id", "userDetails")
|
|
// val match = match(Criteria().andOperator(*matchCriteria.toTypedArray()))
|
|
//
|
|
// var sort = sort(Sort.by(Direction.DESC, "date").and(Sort.by(Direction.DESC, "createdAt")))
|
|
//
|
|
// sortSetting?.let {
|
|
// sort = sort(Sort.by(it.order, it.by).and(Sort.by(Direction.ASC, "createdAt")))
|
|
// }
|
|
//
|
|
// val aggregationBuilder = mutableListOf(
|
|
// lookup,
|
|
// lookupUsers,
|
|
// match.takeIf { matchCriteria.isNotEmpty() },
|
|
// sort,
|
|
// offset?.let { skip(it.toLong()) },
|
|
// limit?.let { limit(it.toLong()) }
|
|
// ).filterNotNull()
|
|
//
|
|
// val aggregation = newAggregation(aggregationBuilder)
|
|
//
|
|
// return reactiveMongoTemplate.aggregate(
|
|
// aggregation, "transactions", Transaction::class.java
|
|
// )
|
|
// .collectList() // Преобразуем Flux<Transaction> в Mono<List<Transaction>>
|
|
// .map { it.toMutableList() }
|
|
// }
|
|
//
|
|
// fun getTransactionsToDelete(dateFrom: LocalDate, dateTo: LocalDate): Mono<List<Transaction>> {
|
|
// val criteria = Criteria().andOperator(
|
|
// Criteria.where("date").gte(dateFrom),
|
|
// Criteria.where("date").lte(dateTo),
|
|
// Criteria().orOperator(
|
|
// Criteria.where("type.code").`is`("PLANNED"),
|
|
// Criteria.where("parentId").exists(true)
|
|
// )
|
|
// )
|
|
//
|
|
//// Пример использования в MongoTemplate:
|
|
// val query = Query(criteria)
|
|
//
|
|
//// Если вы хотите использовать ReactiveMongoTemplate:
|
|
// return reactiveMongoTemplate.find(query, Transaction::class.java)
|
|
// .collectList()
|
|
// .doOnNext { transactions -> println("Found transactions: $transactions") }
|
|
// }
|
|
//
|
|
//
|
|
//
|
|
// @Cacheable("transactions")
|
|
// fun getTransactionById(id: String): Mono<Transaction> {
|
|
// return transactionsRepo.findById(id)
|
|
// .map {
|
|
// it
|
|
// }
|
|
// .switchIfEmpty(
|
|
// Mono.error(IllegalArgumentException("Transaction with id: $id not found"))
|
|
// )
|
|
// }
|
|
//
|
|
//
|
|
// @CacheEvict(cacheNames = ["transactions"], allEntries = true)
|
|
// fun createTransaction(transaction: Transaction): Mono<String> {
|
|
// return ReactiveSecurityContextHolder.getContext()
|
|
// .map { it.authentication } // Получаем Authentication из SecurityContext
|
|
// .flatMap { authentication ->
|
|
// val username = authentication.name // Имя пользователя из токена
|
|
// // Получаем пользователя и сохраняем транзакцию
|
|
// userService.getByUsername(username)
|
|
// .switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
|
|
// .flatMap { user ->
|
|
// transaction.user = user
|
|
// transactionsRepo.save(transaction)
|
|
// .doOnNext { savedTransaction ->
|
|
// // Публикуем событие после сохранения
|
|
// eventPublisher.publishEvent(
|
|
// TransactionEvent(
|
|
// this,
|
|
// TransactionEventType.CREATE,
|
|
// newTransaction = savedTransaction,
|
|
// oldTransaction = savedTransaction
|
|
// )
|
|
// )
|
|
// }
|
|
// .map { it.id!! } // Возвращаем ID сохраненной транзакции
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
//
|
|
// @CacheEvict(cacheNames = ["transactions"], allEntries = true)
|
|
//
|
|
// fun editTransaction(transaction: Transaction): Mono<Transaction> {
|
|
// return transactionsRepo.findById(transaction.id!!)
|
|
// .flatMap { oldStateOfTransaction ->
|
|
// val changed = compareSumDateDoneIsChanged(oldStateOfTransaction, transaction)
|
|
// if (!changed) {
|
|
// return@flatMap transactionsRepo.save(transaction) // Сохраняем, если изменений нет
|
|
// }
|
|
//
|
|
// val amountDifference = transaction.amount - oldStateOfTransaction.amount
|
|
//
|
|
// // Обработка дочерней транзакции
|
|
// handleChildTransaction(oldStateOfTransaction, transaction, amountDifference)
|
|
// .then(transactionsRepo.save(transaction)) // Сохраняем основную транзакцию
|
|
// .doOnSuccess { savedTransaction ->
|
|
// eventPublisher.publishEvent(
|
|
// TransactionEvent(
|
|
// this,
|
|
// TransactionEventType.EDIT,
|
|
// newTransaction = savedTransaction,
|
|
// oldTransaction = oldStateOfTransaction,
|
|
// difference = amountDifference
|
|
// )
|
|
// )
|
|
// }
|
|
// }
|
|
// .switchIfEmpty(
|
|
// Mono.error(IllegalArgumentException("Transaction not found with id: ${transaction.id}"))
|
|
// )
|
|
// }
|
|
//
|
|
// private fun handleChildTransaction(
|
|
// oldTransaction: Transaction,
|
|
// newTransaction: Transaction,
|
|
// amountDifference: Double
|
|
// ): Mono<Void> {
|
|
// return transactionsRepo.findByParentId(newTransaction.id!!)
|
|
// .flatMap { childTransaction ->
|
|
// logger.info(childTransaction.toString())
|
|
// // Если родительская транзакция обновлена, обновляем дочернюю
|
|
// childTransaction.amount = newTransaction.amount
|
|
// childTransaction.category = newTransaction.category
|
|
// childTransaction.comment = newTransaction.comment
|
|
// childTransaction.user = newTransaction.user
|
|
// transactionsRepo.save(childTransaction)
|
|
// }
|
|
// .switchIfEmpty(
|
|
// Mono.defer {
|
|
// // Создание новой дочерней транзакции, если требуется
|
|
// if (!oldTransaction.isDone && newTransaction.isDone) {
|
|
// val newChildTransaction = newTransaction.copy(
|
|
// id = null,
|
|
// type = TransactionType("INSTANT", "Текущие"),
|
|
// parentId = newTransaction.id
|
|
// )
|
|
// transactionsRepo.save(newChildTransaction).doOnSuccess { savedChildTransaction ->
|
|
// eventPublisher.publishEvent(
|
|
// TransactionEvent(
|
|
// this,
|
|
// TransactionEventType.CREATE,
|
|
// newTransaction = savedChildTransaction,
|
|
// oldTransaction = oldTransaction,
|
|
// difference = amountDifference
|
|
// )
|
|
// )
|
|
// }
|
|
// } else Mono.empty()
|
|
// }
|
|
// )
|
|
// .flatMap {
|
|
// // Удаление дочерней транзакции, если родительская помечена как не выполненная
|
|
// if (oldTransaction.isDone && !newTransaction.isDone) {
|
|
// transactionsRepo.findByParentId(newTransaction.id!!)
|
|
// .flatMap { child ->
|
|
// deleteTransaction(child.id!!)
|
|
// }.then()
|
|
// } else {
|
|
// Mono.empty()
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
//
|
|
// fun compareSumDateDoneIsChanged(t1: Transaction, t2: Transaction): Boolean {
|
|
// return if (t1.amount != t2.amount) {
|
|
// true
|
|
// } else if (t1.date != t2.date) {
|
|
// true
|
|
// } else if (t1.isDone != t2.isDone) {
|
|
// true
|
|
// } else if (t1.category.id != t2.category.id) {
|
|
// return true
|
|
// } else {
|
|
// return false
|
|
// }
|
|
// }
|
|
//
|
|
// @CacheEvict(cacheNames = ["transactions"], allEntries = true)
|
|
// fun deleteTransaction(transactionId: String): Mono<Void> {
|
|
// return transactionsRepo.findById(transactionId)
|
|
// .flatMap { transactionToDelete ->
|
|
// transactionsRepo.deleteById(transactionId) // Удаляем транзакцию
|
|
// .then(
|
|
// Mono.fromRunnable<Void> {
|
|
// // Публикуем событие после успешного удаления
|
|
// eventPublisher.publishEvent(
|
|
// TransactionEvent(
|
|
// this,
|
|
// TransactionEventType.DELETE,
|
|
// newTransaction = transactionToDelete,
|
|
// oldTransaction = transactionToDelete
|
|
// )
|
|
// )
|
|
// }
|
|
// )
|
|
// }
|
|
//
|
|
// }
|
|
//
|
|
//
|
|
//// @CacheEvict(cacheNames = ["transactions", "childTransactions"], allEntries = true)
|
|
//// fun setTransactionDone(transaction: Transaction): Transaction {
|
|
//// val oldStateTransaction = transactionsRepo.findById(transaction.id!!)
|
|
//// .orElseThrow { RuntimeException("Transaction ${transaction.id} not found") }
|
|
////
|
|
//// if (transaction.isDone) {
|
|
//// if (oldStateTransaction.isDone) {
|
|
//// throw RuntimeException("Transaction ${transaction.id} is already done")
|
|
//// }
|
|
////
|
|
//// // Создание дочерней транзакции
|
|
//// val childTransaction = transaction.copy(
|
|
//// id = null,
|
|
//// type = TransactionType("INSTANT", "Текущие"),
|
|
//// parentId = transaction.id
|
|
//// )
|
|
//// createTransaction(childTransaction)
|
|
//// } else {
|
|
//// // Удаление дочерней транзакции, если она существует
|
|
//// transactionsRepo.findByParentId(transaction.id!!).getOrNull()?.let {
|
|
//// deleteTransaction(it.id!!)
|
|
//// } ?: logger.warn("Child transaction of parent ${transaction.id} not found")
|
|
//// }
|
|
////
|
|
//// return editTransaction(transaction)
|
|
//// }
|
|
//
|
|
//
|
|
// @Cacheable("childTransactions", key = "#parentId")
|
|
// fun getChildTransaction(parentId: String): Mono<Transaction> {
|
|
// return transactionsRepo.findByParentId(parentId)
|
|
// }
|
|
//
|
|
//// fun getTransactionByOldId(id: Int): Transaction? {
|
|
//// return transactionsRepo.findByOldId(id).getOrNull()
|
|
//// }
|
|
//
|
|
//// fun transferTransactions(): Mono<Void> {
|
|
//// var transactions = transactionsRepoSQl.getTransactions()
|
|
//// return transactionsRepo.saveAll(transactions).then()
|
|
//// }
|
|
////
|
|
//
|
|
// fun calcTransactionsSum(
|
|
// budget: Budget,
|
|
// categoryId: String? = null,
|
|
// categoryType: String? = null,
|
|
// transactionType: String? = null,
|
|
// isDone: Boolean? = null
|
|
// ): Mono<Double> {
|
|
// val matchCriteria = mutableListOf<Criteria>()
|
|
//
|
|
// // Добавляем фильтры
|
|
// matchCriteria.add(Criteria.where("date").gte(budget.dateFrom))
|
|
// matchCriteria.add(Criteria.where("date").lt(budget.dateTo))
|
|
// categoryId?.let { matchCriteria.add(Criteria.where("category.\$id").`is`(ObjectId(it))) }
|
|
// categoryType?.let { matchCriteria.add(Criteria.where("categoryDetails.type.code").`is`(it)) }
|
|
// transactionType?.let { matchCriteria.add(Criteria.where("type.code").`is`(it)) }
|
|
// isDone?.let { matchCriteria.add(Criteria.where("isDone").`is`(it)) }
|
|
//
|
|
// // Сборка агрегации
|
|
// val lookup = lookup("categories", "category.\$id", "_id", "categoryDetails")
|
|
// val unwind = unwind("categoryDetails")
|
|
// val match = match(Criteria().andOperator(*matchCriteria.toTypedArray()))
|
|
// val project = project("category").andExpression("{ \$toDouble: \"\$amount\" }").`as`("amount")
|
|
// val group = group(categoryId ?: "all").sum("amount").`as`("totalSum")
|
|
// val projectSum = project("totalSum")
|
|
// val aggregation = newAggregation(lookup, unwind, match, project, group, projectSum)
|
|
//
|
|
// return reactiveMongoTemplate.aggregate(aggregation, "transactions", Map::class.java)
|
|
// .map { result ->
|
|
// val totalSum = result["totalSum"]
|
|
// if (totalSum is Double) {
|
|
// totalSum
|
|
// } else {
|
|
// 0.0
|
|
// }
|
|
// }
|
|
// .reduce(0.0) { acc, sum -> acc + sum } // Суммируем значения, если несколько результатов
|
|
// }
|
|
//
|
|
//
|
|
// // @Cacheable("transactions")
|
|
// fun getAverageSpendingByCategory(): Mono<Map<String, Double>> {
|
|
// val firstDateOfMonth = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth())
|
|
//
|
|
// val lookup = lookup("categories", "category.\$id", "_id", "categoryDetails")
|
|
// val unwind = unwind("categoryDetails")
|
|
// val match = match(
|
|
// Criteria.where("categoryDetails.type.code").`is`("EXPENSE")
|
|
// .and("type.code").`is`("INSTANT")
|
|
// .and("date").lt(firstDateOfMonth)
|
|
// )
|
|
// val projectDate = project("_id", "category", "amount", "categoryDetails")
|
|
// .and(DateToString.dateOf("date").toString("%Y-%m")).`as`("month")
|
|
// .andExpression("{ \$toDouble: \"\$amount\" }").`as`("amount")
|
|
// val groupByMonthAndCategory = group("month", "category.\$id").sum("amount").`as`("sum")
|
|
// val groupByCategory = group("_id.id").avg("sum").`as`("averageAmount")
|
|
// val project = project()
|
|
// .and("_id").`as`("category")
|
|
// .and("averageAmount").`as`("avgAmount")
|
|
// val sort = sort(Sort.by(Sort.Order.asc("_id")))
|
|
//
|
|
// val aggregation = newAggregation(
|
|
// lookup, unwind, match, projectDate, groupByMonthAndCategory, groupByCategory, project, sort
|
|
// )
|
|
//
|
|
// return reactiveMongoTemplate.aggregate(aggregation, "transactions", Map::class.java)
|
|
// .collectList()
|
|
// .map { results ->
|
|
// results.associate { result ->
|
|
// val category = result["category"]?.toString() ?: "Unknown"
|
|
// val avgAmount = (result["avgAmount"] as? Double) ?: 0.0
|
|
// category to avgAmount
|
|
// }
|
|
// }
|
|
// .defaultIfEmpty(emptyMap()) // Возвращаем пустую карту, если результатов нет
|
|
// }
|
|
//
|
|
//
|
|
// @Cacheable("transactionTypes")
|
|
// fun getTransactionTypes(): List<TransactionType> {
|
|
// var types = mutableListOf<TransactionType>()
|
|
// types.add(TransactionType("PLANNED", "Плановые"))
|
|
// types.add(TransactionType("INSTANT", "Текущие"))
|
|
// return types
|
|
// }
|
|
//
|
|
// fun getAverageIncome(): Mono<Double> {
|
|
// val lookup = lookup("categories", "category.\$id", "_id", "detailedCategory")
|
|
//
|
|
// val unwind = unwind("detailedCategory")
|
|
//
|
|
// val match = match(
|
|
// Criteria.where("detailedCategory.type.code").`is`("INCOME")
|
|
// .and("type.code").`is`("INSTANT")
|
|
// .and("isDone").`is`(true)
|
|
// )
|
|
//
|
|
// val project = project("_id", "category", "detailedCategory")
|
|
// .and(DateToString.dateOf("date").toString("%Y-%m")).`as`("month")
|
|
// .andExpression("{ \$toDouble: \"\$amount\" }").`as`("amount")
|
|
//
|
|
// val groupByMonth = group("month").sum("amount").`as`("sum")
|
|
//
|
|
// val groupForAverage = group("avgIncomeByMonth").avg("sum").`as`("averageAmount")
|
|
//
|
|
// val aggregation = newAggregation(lookup, unwind, match, project, groupByMonth, groupForAverage)
|
|
//
|
|
// return reactiveMongoTemplate.aggregate(aggregation, "transactions", Map::class.java)
|
|
// .singleOrEmpty() // Ожидаем только один результат
|
|
// .map { result ->
|
|
// result["averageAmount"] as? Double ?: 0.0
|
|
// }
|
|
// .defaultIfEmpty(0.0) // Если результат пустой, возвращаем 0.0
|
|
// }
|
|
//
|
|
//
|
|
// fun getTransactionsByTypes(dateFrom: LocalDate, dateTo: LocalDate): Mono<Map<String, List<Transaction>>> {
|
|
// logger.info("here tran starts")
|
|
// val pipeline = listOf(
|
|
// Document(
|
|
// "\$lookup",
|
|
// Document("from", "categories")
|
|
// .append("localField", "category.\$id")
|
|
// .append("foreignField", "_id")
|
|
// .append("as", "categoryDetailed")
|
|
// ),
|
|
// Document(
|
|
// "\$lookup",
|
|
// Document("from", "users")
|
|
// .append("localField", "user.\$id")
|
|
// .append("foreignField", "_id")
|
|
// .append("as", "userDetailed")
|
|
// ),
|
|
// Document(
|
|
// "\$unwind",
|
|
// Document("path", "\$categoryDetailed").append("preserveNullAndEmptyArrays", true)
|
|
// ),
|
|
// Document(
|
|
// "\$unwind",
|
|
// Document("path", "\$userDetailed").append("preserveNullAndEmptyArrays", true)
|
|
// ),
|
|
// Document(
|
|
// "\$match",
|
|
// Document(
|
|
// "\$and", listOf(
|
|
// Document(
|
|
// "date",
|
|
// Document(
|
|
// "\$gte",
|
|
// Date.from(
|
|
// LocalDateTime.of(dateFrom, LocalTime.MIN)
|
|
// .atZone(ZoneId.systemDefault())
|
|
// .withZoneSameInstant(ZoneOffset.UTC)
|
|
// .toInstant()
|
|
// )
|
|
// )
|
|
// ),
|
|
// Document(
|
|
// "date",
|
|
// Document(
|
|
// "\$lt",
|
|
// Date.from(
|
|
// LocalDateTime.of(dateTo, LocalTime.MAX)
|
|
// .atZone(ZoneId.systemDefault())
|
|
// .withZoneSameInstant(ZoneOffset.UTC)
|
|
// .toInstant()
|
|
// )
|
|
// )
|
|
// )
|
|
// )
|
|
// )
|
|
// ),
|
|
// Document(
|
|
// "\$facet",
|
|
// Document(
|
|
// "plannedExpenses",
|
|
// listOf(
|
|
// Document(
|
|
// "\$match",
|
|
// Document("type.code", "PLANNED")
|
|
// .append("categoryDetailed.type.code", "EXPENSE")
|
|
// ),
|
|
// Document("\$sort", Document("date", 1).append("_id", 1))
|
|
// )
|
|
// )
|
|
// .append(
|
|
// "plannedIncomes",
|
|
// listOf(
|
|
// Document(
|
|
// "\$match",
|
|
// Document("type.code", "PLANNED")
|
|
// .append("categoryDetailed.type.code", "INCOME")
|
|
// ),
|
|
// Document("\$sort", Document("date", 1).append("_id", 1))
|
|
// )
|
|
// )
|
|
// .append(
|
|
// "instantTransactions",
|
|
// listOf(
|
|
// Document("\$match", Document("type.code", "INSTANT")),
|
|
// Document("\$sort", Document("date", 1).append("_id", 1))
|
|
// )
|
|
// )
|
|
// )
|
|
// )
|
|
//
|
|
//// getCategoriesExplainReactive(pipeline)
|
|
//// .doOnNext { explainResult ->
|
|
//// logger.info("Explain Result: ${explainResult.toJson()}")
|
|
//// }
|
|
//// .subscribe() // Этот вызов лучше оставить только для отладки
|
|
// return reactiveMongoTemplate.getCollection("transactions")
|
|
// .flatMapMany { it.aggregate(pipeline, Document::class.java) }
|
|
// .single() // Получаем только первый результат агрегации
|
|
// .flatMap { aggregationResult ->
|
|
// Mono.zip(
|
|
// extractTransactions(aggregationResult, "plannedExpenses"),
|
|
// extractTransactions(aggregationResult, "plannedIncomes"),
|
|
// extractTransactions(aggregationResult, "instantTransactions")
|
|
// ).map { tuple ->
|
|
// val plannedExpenses = tuple.t1
|
|
// val plannedIncomes = tuple.t2
|
|
// val instantTransactions = tuple.t3
|
|
// logger.info("here tran ends")
|
|
// mapOf(
|
|
// "plannedExpenses" to plannedExpenses,
|
|
// "plannedIncomes" to plannedIncomes,
|
|
// "instantTransactions" to instantTransactions
|
|
// )
|
|
//
|
|
//
|
|
// }
|
|
//
|
|
// }
|
|
//
|
|
//
|
|
// }
|
|
//
|
|
//
|
|
// private fun extractTransactions(aggregationResult: Document, key: String): Mono<List<Transaction>> {
|
|
// val resultTransactions = aggregationResult[key] as? List<Document> ?: emptyList()
|
|
// return Flux.fromIterable(resultTransactions)
|
|
// .map { documentToTransactionMapper(it) }
|
|
// .collectList()
|
|
// }
|
|
//
|
|
//
|
|
// private fun documentToTransactionMapper(document: Document): Transaction {
|
|
// val transactionType = document["type"] as Document
|
|
// var user: User? = null
|
|
//
|
|
// val userDocument = document["userDetailed"] as Document
|
|
// user = User(
|
|
// id = (userDocument["_id"] as ObjectId).toString(),
|
|
// username = userDocument["username"] as String,
|
|
// firstName = userDocument["firstName"] as String,
|
|
// tgId = userDocument["tgId"] as String,
|
|
// tgUserName = userDocument["tgUserName"]?.let { it as String },
|
|
// password = null,
|
|
// isActive = userDocument["isActive"] as Boolean,
|
|
// regDate = userDocument["regDate"] as Date,
|
|
// createdAt = userDocument["createdAt"] as Date,
|
|
// roles = userDocument["roles"] as ArrayList<String>,
|
|
// )
|
|
//
|
|
//
|
|
// val categoryDocument = document["categoryDetailed"] as Document
|
|
// val categoryTypeDocument = categoryDocument["type"] as Document
|
|
// val category = Category(
|
|
// id = (categoryDocument["_id"] as ObjectId).toString(),
|
|
// type = CategoryType(categoryTypeDocument["code"] as String, categoryTypeDocument["name"] as String),
|
|
// name = categoryDocument["name"] as String,
|
|
// description = categoryDocument["description"] as String,
|
|
// icon = categoryDocument["icon"] as String
|
|
// )
|
|
// return Transaction(
|
|
// (document["_id"] as ObjectId).toString(),
|
|
// TransactionType(
|
|
// transactionType["code"] as String,
|
|
// transactionType["name"] as String
|
|
// ),
|
|
// user = user,
|
|
// category = category,
|
|
// comment = document["comment"] as String,
|
|
// date = (document["date"] as Date).toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
|
|
// amount = document["amount"] as Double,
|
|
// isDone = document["isDone"] as Boolean,
|
|
// parentId = if (document["parentId"] != null) document["parentId"] as String else null,
|
|
// createdAt = LocalDateTime.ofInstant((document["createdAt"] as Date).toInstant(), ZoneOffset.UTC),
|
|
// )
|
|
//
|
|
// }
|
|
//} |