From 5d9cc167fc609fb3ab94da9213ea3d475382f9d8 Mon Sep 17 00:00:00 2001 From: xds Date: Tue, 8 Apr 2025 12:13:20 +0300 Subject: [PATCH] + nlp reatech --- .../budgerapp/controllers/SpaceController.kt | 30 +++++----------- .../luminic/budgerapp/services/BotService.kt | 2 +- .../budgerapp/services/CategoryService.kt | 9 ++--- .../budgerapp/services/FinancialService.kt | 35 +++++++++++++++++++ .../luminic/budgerapp/services/NLPService.kt | 10 ++++-- 5 files changed, 58 insertions(+), 28 deletions(-) diff --git a/src/main/kotlin/space/luminic/budgerapp/controllers/SpaceController.kt b/src/main/kotlin/space/luminic/budgerapp/controllers/SpaceController.kt index cd41f70..8c6a62d 100644 --- a/src/main/kotlin/space/luminic/budgerapp/controllers/SpaceController.kt +++ b/src/main/kotlin/space/luminic/budgerapp/controllers/SpaceController.kt @@ -179,31 +179,17 @@ class SpaceController( } } - @GetMapping("/{spaceId}/transactions/csv") + @GetMapping("/transactions/csv") suspend fun getTransactionsCSV( - @PathVariable spaceId: String, - @RequestParam(value = "transaction_type") transactionType: String? = null, - @RequestParam(value = "category_type") categoryType: String? = null, - @RequestParam(value = "user_id") userId: String? = null, - @RequestParam(value = "is_child") isChild: Boolean? = null, - @RequestParam(value = "limit") limit: Int = 20000, - @RequestParam(value = "offset") offset: Int = 0 ): ResponseEntity { try { val bos = ByteArrayOutputStream() val writer = CSVWriter(OutputStreamWriter(bos)) - val CSVHeaders = arrayOf("id", "name", "category") + val CSVHeaders = arrayOf("id", "comment", "category") writer.writeNext(CSVHeaders) - financialService.getTransactions( - spaceId = spaceId, - transactionType = transactionType, - categoryType = categoryType, - userId = userId, - isChild = isChild, - limit = limit, - offset = offset - ).awaitSingle().map { - val data = arrayOf(it.id, it.comment, it.category.name) + financialService.getAllTransactions( + ).map { + val data = arrayOf(it.id, it.comment, it.category.id) writer.writeNext(data) } writer.close() @@ -224,7 +210,8 @@ class SpaceController( @GetMapping("/{spaceId}/category-predict") suspend fun getTransactionCategoryPredict( @PathVariable spaceId: String, - @RequestParam comment: String + @RequestParam comment: String, + @RequestParam cloud: Int ): List { val user = authService.getSecurityUser() spaceService.isValidRequest(spaceId, user) @@ -233,7 +220,8 @@ class SpaceController( "EXPENSE", sortBy = "name", direction = "ASC", - predict = comment + predict = comment, + cloud = cloud ) } diff --git a/src/main/kotlin/space/luminic/budgerapp/services/BotService.kt b/src/main/kotlin/space/luminic/budgerapp/services/BotService.kt index f08519b..9a4ea11 100644 --- a/src/main/kotlin/space/luminic/budgerapp/services/BotService.kt +++ b/src/main/kotlin/space/luminic/budgerapp/services/BotService.kt @@ -64,7 +64,7 @@ class BotService( for (category in predictedCategories) { - filteredCategories.add(categories.first { it.name == category.category }) + filteredCategories.add(categories.first { it.id == category.category }) } } else { filteredCategories.addAll(categories) diff --git a/src/main/kotlin/space/luminic/budgerapp/services/CategoryService.kt b/src/main/kotlin/space/luminic/budgerapp/services/CategoryService.kt index d2dfdab..57a37c9 100644 --- a/src/main/kotlin/space/luminic/budgerapp/services/CategoryService.kt +++ b/src/main/kotlin/space/luminic/budgerapp/services/CategoryService.kt @@ -75,7 +75,8 @@ class CategoryService( sortBy: String, direction: String, tagCode: String? = null, - predict: String? = null + predict: String? = null, + cloud: Int? = null ): MutableList { val lookupSpaces = lookup("spaces", "space.\$id", "_id", "spaceDetails") val unwindSpace = unwind("spaceDetails") @@ -112,12 +113,12 @@ class CategoryService( }.awaitSingle().toMutableList() val predictedCategories = mutableListOf() - if (!predict.isNullOrBlank()) { - predictedCategories.addAll(nlpService.predictCategory(predict, 1)) + if (!predict.isNullOrBlank() && cloud != null) { + predictedCategories.addAll(nlpService.predictCategory(predict, cloud)) } val filteredCategories = mutableListOf() for (category in predictedCategories) { - categories.find { it.name == category.category }?.let { filteredCategories.add(it) } + categories.find { it.id == category.category }?.let { filteredCategories.add(it) } } return if (filteredCategories.isEmpty()) categories else filteredCategories } diff --git a/src/main/kotlin/space/luminic/budgerapp/services/FinancialService.kt b/src/main/kotlin/space/luminic/budgerapp/services/FinancialService.kt index e6cab11..61b4c83 100644 --- a/src/main/kotlin/space/luminic/budgerapp/services/FinancialService.kt +++ b/src/main/kotlin/space/luminic/budgerapp/services/FinancialService.kt @@ -48,6 +48,7 @@ class FinancialService( val transactionsMapper: TransactionsMapper, val budgetMapper: BudgetMapper, private val subscriptionService: SubscriptionService, + private val nlpService: NLPService ) { private val logger = LoggerFactory.getLogger(FinancialService::class.java) @@ -761,6 +762,37 @@ class FinancialService( } } + suspend fun getAllTransactions(): List{ + + // Сборка агрегации + val lookup = lookup("categories", "category.\$id", "_id", "categoryDetails") + val unwindCategory = unwind("categoryDetails") + val lookupSpaces = lookup("spaces", "space.\$id", "_id", "spaceDetails") + val unwindSpace = unwind("spaceDetails") + val lookupUsers = lookup("users", "user.\$id", "_id", "userDetails") + val unwindUser = unwind("userDetails") + val sort = + sort(Sort.by(Direction.DESC, "date").and(Sort.by(Direction.DESC, "createdAt"))) + + val aggregationBuilder = mutableListOf( + lookup, + unwindCategory, + lookupSpaces, + unwindSpace, + lookupUsers, + unwindUser, + sort + ) + + val aggregation = newAggregation(aggregationBuilder) + + return reactiveMongoTemplate.aggregate( + aggregation, "transactions", Document::class.java + ).collectList().awaitSingle().map { doc -> + transactionsMapper.fromDocument(doc) + } + } + suspend fun getTransactionByParentId(parentId: String): Transaction? { // Сборка агрегации @@ -885,6 +917,9 @@ class FinancialService( ) ) } + scope.launch { + nlpService.reteach() + } return savedTransaction } diff --git a/src/main/kotlin/space/luminic/budgerapp/services/NLPService.kt b/src/main/kotlin/space/luminic/budgerapp/services/NLPService.kt index 3805aa8..00f0003 100644 --- a/src/main/kotlin/space/luminic/budgerapp/services/NLPService.kt +++ b/src/main/kotlin/space/luminic/budgerapp/services/NLPService.kt @@ -1,8 +1,11 @@ package space.luminic.budgerapp.services import kotlinx.coroutines.reactive.awaitSingle +import kotlinx.coroutines.reactor.awaitSingleOrNull +import org.slf4j.LoggerFactory import org.springframework.stereotype.Service import org.springframework.web.reactive.function.client.WebClient +import org.springframework.web.reactive.function.client.bodyToMono import space.luminic.budgerapp.configs.NLPConfig import space.luminic.budgerapp.models.CategoryPrediction @@ -14,9 +17,12 @@ class NLPService( // .defaultHeader("Authorization", "Bearer YOUR_API_KEY") .build(), ) { + private val logging = LoggerFactory.getLogger(NLPService::class.java) - - + suspend fun reteach() { + logging.info("Reteaching NLP") + webClient.get().uri("/reteach").retrieve().bodyToMono().awaitSingleOrNull() + } suspend fun predictCategory(category: String, cloud: Int): List { val response = webClient.get().uri("/predict?req=$category&cloud=$cloud")