wishlists + statics + some fixes
This commit is contained in:
@@ -23,7 +23,7 @@ import org.springframework.data.mongodb.core.ReactiveMongoTemplate
|
||||
import org.springframework.data.mongodb.core.aggregation.Aggregation.*
|
||||
import org.springframework.data.mongodb.core.aggregation.DateOperators.DateToString
|
||||
import org.springframework.data.mongodb.core.query.Criteria
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder
|
||||
import org.springframework.stereotype.Service
|
||||
import reactor.core.publisher.Flux
|
||||
import reactor.core.publisher.Mono
|
||||
@@ -169,16 +169,34 @@ class FinancialService(
|
||||
}
|
||||
}
|
||||
|
||||
private fun findBudgetCategory(transaction: Transaction, budget: Budget): BudgetCategory {
|
||||
private suspend fun findBudgetCategory(transaction: Transaction, budget: Budget): BudgetCategory {
|
||||
return if (transaction.category.type.code == "EXPENSE") {
|
||||
budget.categories.firstOrNull { it.category.id == transaction.category.id }
|
||||
?: throw RuntimeException("Budget category not found for expense")
|
||||
?: addCategoryToBudget(transaction.category, budget)
|
||||
|
||||
} else {
|
||||
budget.incomeCategories.firstOrNull { it.category.id == transaction.category.id }
|
||||
?: throw RuntimeException("Budget category not found for income")
|
||||
?:addCategoryToBudget(transaction.category, budget)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun addCategoryToBudget(category: Category, budget: Budget): BudgetCategory {
|
||||
val sums = getBudgetSumsByCategory(category.id!!, budget)
|
||||
val categoryBudget = BudgetCategory(
|
||||
currentSpent = sums.getDouble("instantAmount"),
|
||||
currentPlanned = sums.getDouble("plannedAmount"),
|
||||
currentLimit = sums.getDouble("plannedAmount"),
|
||||
category = category
|
||||
)
|
||||
if (category.type.code == "EXPENSE") {
|
||||
budget.categories.add(categoryBudget)
|
||||
} else {
|
||||
budget.incomeCategories.add(categoryBudget)
|
||||
}
|
||||
budgetRepo.save(budget).awaitSingle()
|
||||
return categoryBudget
|
||||
}
|
||||
|
||||
private suspend fun updateBudgetCategory(
|
||||
transaction: Transaction,
|
||||
budget: Budget,
|
||||
@@ -826,7 +844,7 @@ class FinancialService(
|
||||
|
||||
|
||||
suspend fun createTransaction(space: Space, transaction: Transaction): Transaction {
|
||||
val securityContextHolder = SecurityContextHolder.getContext()
|
||||
val securityContextHolder = ReactiveSecurityContextHolder.getContext().awaitSingle()
|
||||
val user = userService.getByUserNameWoPass(securityContextHolder.authentication.name)
|
||||
if (space.users.none { it.id.toString() == user.id }) {
|
||||
throw IllegalArgumentException("User does not have access to this Space")
|
||||
@@ -903,7 +921,7 @@ class FinancialService(
|
||||
|
||||
|
||||
suspend fun deleteTransaction(transaction: Transaction) = coroutineScope {
|
||||
transactionsRepo.deleteById(transaction.id!!).awaitSingle()
|
||||
transactionsRepo.deleteById(transaction.id!!).awaitFirstOrNull()
|
||||
launch { updateBudgetOnDelete(transaction) }
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package space.luminic.budgerapp.services
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.reactor.awaitSingleOrNull
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.springframework.http.codec.multipart.FilePart
|
||||
import org.springframework.stereotype.Service
|
||||
import space.luminic.budgerapp.configs.StorageConfig
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
|
||||
@Service
|
||||
class StaticService(private val storageConfig: StorageConfig) {
|
||||
|
||||
suspend fun saveFile(spaceId: String, wishListItemId: String, filePart: FilePart): String {
|
||||
|
||||
val folder = Paths.get(storageConfig.rootLocation.toString(), spaceId, "wishlists", wishListItemId)
|
||||
withContext(Dispatchers.IO) {
|
||||
Files.createDirectories(folder)
|
||||
}
|
||||
val filename = UUID.randomUUID().toString().split("-")[0] + "." + filePart.filename().split(".").last()
|
||||
val filePath =
|
||||
folder.resolve(filename)
|
||||
filePart.transferTo(filePath).awaitSingleOrNull()
|
||||
return filePath.toString()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package space.luminic.budgerapp.services
|
||||
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.reactive.asFlow
|
||||
import kotlinx.coroutines.reactor.awaitSingle
|
||||
import kotlinx.coroutines.reactor.awaitSingleOrNull
|
||||
import org.bson.Document
|
||||
import org.bson.types.ObjectId
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate
|
||||
import org.springframework.data.mongodb.core.aggregation.Aggregation.*
|
||||
import org.springframework.data.mongodb.core.aggregation.AggregationOperation
|
||||
import org.springframework.data.mongodb.core.query.Criteria
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder
|
||||
import org.springframework.stereotype.Service
|
||||
import space.luminic.budgerapp.mappers.WishListMapper
|
||||
import space.luminic.budgerapp.models.NotFoundException
|
||||
import space.luminic.budgerapp.models.Space
|
||||
import space.luminic.budgerapp.models.WishList
|
||||
import space.luminic.budgerapp.models.WishListItem
|
||||
import space.luminic.budgerapp.repos.WishListItemRepo
|
||||
import space.luminic.budgerapp.repos.WishListRepo
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Service
|
||||
class WishListService(
|
||||
private val reactiveMongoTemplate: ReactiveMongoTemplate,
|
||||
private val wishListMapper: WishListMapper,
|
||||
private val wishListRepo: WishListRepo,
|
||||
private val wishListItemRepo: WishListItemRepo,
|
||||
private val userService: UserService
|
||||
) {
|
||||
private fun getLookupsAndUnwinds(): List<AggregationOperation> {
|
||||
val aggregationOperation = mutableListOf<AggregationOperation>()
|
||||
aggregationOperation.add(lookup("spaces", "space.\$id", "_id", "spaceDetails"))
|
||||
aggregationOperation.add(unwind("spaceDetails"))
|
||||
aggregationOperation.add(lookup("users", "owner.\$id", "_id", "ownerDetails"))
|
||||
aggregationOperation.add(unwind("ownerDetails"))
|
||||
aggregationOperation.add(lookup("wishlistItems", "items.\$id", "_id", "itemsDetails"))
|
||||
return aggregationOperation
|
||||
|
||||
}
|
||||
|
||||
suspend fun findWishLists(spaceId: String): List<WishList> {
|
||||
val user = userService.getByUserNameWoPass(
|
||||
ReactiveSecurityContextHolder.getContext().awaitSingle().authentication.name
|
||||
)
|
||||
val match = match(
|
||||
Criteria.where("spaceDetails._id").`is`(ObjectId(spaceId))
|
||||
.andOperator(
|
||||
Criteria.where("ownerDetails._id").`is`(ObjectId(user.id))
|
||||
.orOperator(Criteria.where("isPrivate").`is`(false))
|
||||
)
|
||||
)
|
||||
|
||||
val aggregation = newAggregation(*(getLookupsAndUnwinds().toTypedArray()), match)
|
||||
return reactiveMongoTemplate.aggregate(aggregation, "wishlists", Document::class.java)
|
||||
.asFlow().map {
|
||||
wishListMapper.fromDocument(it)
|
||||
}.toList()
|
||||
}
|
||||
|
||||
suspend fun getList(listId: String): WishList {
|
||||
val user = userService.getByUserNameWoPass(
|
||||
ReactiveSecurityContextHolder.getContext().awaitSingle().authentication.name
|
||||
)
|
||||
val match = match(
|
||||
Criteria.where("_id").`is`(ObjectId(listId))
|
||||
.andOperator(Criteria.where("ownerDetails._id").`is`(ObjectId(user.id)))
|
||||
)
|
||||
|
||||
|
||||
val aggregation = newAggregation(*(getLookupsAndUnwinds().toTypedArray()), match)
|
||||
// val aggregation = newAggregation(lookupSpace, unwindSpace, lookupOwner, unwindOwner, lookupItems, match)
|
||||
return reactiveMongoTemplate.aggregate(aggregation, "wishlists", Document::class.java)
|
||||
.next().map {
|
||||
wishListMapper.fromDocument(it)
|
||||
}.awaitSingleOrNull() ?: throw NotFoundException("WishList with id $listId does not exist")
|
||||
}
|
||||
|
||||
suspend fun createWishList(space: Space, wishList: WishList): WishList {
|
||||
val user = userService.getByUserNameWoPass(
|
||||
ReactiveSecurityContextHolder.getContext().awaitSingle().authentication.name
|
||||
)
|
||||
wishList.owner = user
|
||||
wishList.space = space
|
||||
return wishListRepo.save(wishList).awaitSingle()
|
||||
}
|
||||
|
||||
suspend fun updateWishListInfo(wishList: WishList): WishList {
|
||||
val oldStateOfWishList = getList(wishList.id!!)
|
||||
val newStateOfWishList = oldStateOfWishList.copy(
|
||||
name = wishList.name,
|
||||
description = wishList.description,
|
||||
isPrivate = wishList.isPrivate,
|
||||
updatedAt = LocalDateTime.now()
|
||||
)
|
||||
return wishListRepo.save(newStateOfWishList).awaitSingle()
|
||||
}
|
||||
|
||||
suspend fun updateWishListItemInfo(wishListId: String, wishListItem: WishListItem): WishList {
|
||||
wishListItemRepo.save(wishListItem).awaitSingle()
|
||||
return getList(wishListId)
|
||||
}
|
||||
|
||||
suspend fun addItemToWishList(wishListId: String, item: WishListItem): WishList {
|
||||
val wishList = getList(wishListId)
|
||||
val savedItem = wishListItemRepo.save(item).awaitSingle()
|
||||
wishList.items.add(savedItem)
|
||||
return wishListRepo.save(wishList).awaitSingle()
|
||||
}
|
||||
|
||||
suspend fun removeItemFromWishList(wishListId: String, itemId: String): WishList {
|
||||
val wishList = getList(wishListId)
|
||||
return if (wishList.items.removeIf { it.id == itemId }) wishListRepo.save(wishList).awaitSingle() else wishList
|
||||
}
|
||||
|
||||
suspend fun deleteWishList(wishListId: String) {
|
||||
wishListRepo.deleteById(wishListId).awaitSingleOrNull()
|
||||
}
|
||||
|
||||
suspend fun cancelReserve(wishListId: String, wishlistItemId: String): WishList {
|
||||
val wishList = getList(wishListId)
|
||||
val wishlistItem = wishList.items.first { it.id == wishlistItemId }
|
||||
return if (wishlistItem.reservedBy != null) {
|
||||
wishlistItem.reservedBy = null
|
||||
wishListItemRepo.save(wishlistItem).awaitSingle()
|
||||
wishList
|
||||
} else wishList
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package space.luminic.budgerapp.services
|
||||
|
||||
import kotlinx.coroutines.reactor.awaitSingle
|
||||
import kotlinx.coroutines.reactor.awaitSingleOrNull
|
||||
import org.bson.Document
|
||||
import org.bson.types.ObjectId
|
||||
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.stereotype.Service
|
||||
import space.luminic.budgerapp.mappers.WishListMapper
|
||||
import space.luminic.budgerapp.models.NotFoundException
|
||||
import space.luminic.budgerapp.models.Reserve
|
||||
import space.luminic.budgerapp.models.WishList
|
||||
import space.luminic.budgerapp.models.WishListItem
|
||||
import space.luminic.budgerapp.repos.WishListItemRepo
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Service
|
||||
class WishlistExternalService(
|
||||
private val reactiveMongoTemplate: ReactiveMongoTemplate,
|
||||
private val wishListMapper: WishListMapper,
|
||||
private val wishListItemRepo: WishListItemRepo
|
||||
) {
|
||||
suspend fun getWishListInfo(wishListId: String): WishList {
|
||||
val lookupSpace = lookup("spaces", "space.\$id", "_id", "spaceDetails")
|
||||
val unwindSpace = unwind("spaceDetails")
|
||||
val lookupOwner = lookup("users", "owner.\$id", "_id", "ownerDetails")
|
||||
val unwindOwner = unwind("ownerDetails")
|
||||
val lookupItems = lookup("wishlistItems", "items.\$id", "_id", "itemsDetails")
|
||||
val match = match(
|
||||
Criteria.where("_id").`is`(ObjectId(wishListId))
|
||||
)
|
||||
|
||||
val aggregation = newAggregation(lookupSpace, unwindSpace, lookupOwner, unwindOwner, lookupItems, match)
|
||||
return reactiveMongoTemplate.aggregate(aggregation, "wishlists", Document::class.java)
|
||||
.next().map {
|
||||
wishListMapper.fromDocument(it)
|
||||
}.awaitSingleOrNull() ?: throw NotFoundException("WishList with id $wishListId does not exist")
|
||||
}
|
||||
|
||||
suspend fun reserveWishlistItem(wishListId: String, wishlistItemId: String, reservedBy: Reserve): WishListItem {
|
||||
val wishlist = getWishListInfo(wishListId)
|
||||
val wishlistItem = wishlist.items.first { wishlistItem -> wishlistItem.id == wishlistItemId }
|
||||
return if (wishlistItem.reservedBy == null) {
|
||||
wishlistItem.reservedBy = reservedBy
|
||||
wishlistItem.updatedAt = LocalDateTime.now()
|
||||
wishListItemRepo.save(wishlistItem).awaitSingle()
|
||||
} else throw IllegalArgumentException("Wishlist item already reserved")
|
||||
}
|
||||
|
||||
suspend fun cancelReserve(wishListId: String, wishlistItemId: String, reservedBy: Reserve): WishListItem {
|
||||
val wishlist = getWishListInfo(wishListId)
|
||||
val wishlistItem = wishlist.items.first { wishlistItem -> wishlistItem.id == wishlistItemId }
|
||||
return if (wishlistItem.reservedBy?.aid == reservedBy.aid) {
|
||||
wishlistItem.reservedBy = null
|
||||
wishListItemRepo.save(wishlistItem).awaitSingle()
|
||||
} else if (wishlistItem.reservedBy == null) {
|
||||
wishlistItem
|
||||
} else throw IllegalArgumentException("Вы не можете отменить не свою бронь")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user