This commit is contained in:
xds
2025-10-16 15:06:20 +03:00
commit 040da34ff7
78 changed files with 3934 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
package space.luminic.finance.services
import kotlinx.coroutines.reactive.awaitSingle
import org.bson.Document
import org.bson.types.ObjectId
import org.springframework.data.mongodb.core.ReactiveMongoTemplate
import org.springframework.data.mongodb.core.aggregation.Aggregation.addFields
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.unwind
import org.springframework.data.mongodb.core.aggregation.AggregationOperation
import org.springframework.data.mongodb.core.aggregation.ConvertOperators
import org.springframework.data.mongodb.core.aggregation.LookupOperation
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.stereotype.Service
import space.luminic.finance.dtos.AccountDTO
import space.luminic.finance.models.Account
import space.luminic.finance.models.Transaction
import space.luminic.finance.repos.AccountRepo
@Service
class AccountServiceImpl(
private val accountRepo: AccountRepo,
private val mongoTemplate: ReactiveMongoTemplate,
private val spaceService: SpaceService,
private val transactionService: TransactionService
): AccountService {
private fun basicAggregation(spaceId: String): List<AggregationOperation> {
val addFieldsAsOJ = addFields()
.addField("createdByOI")
.withValue(ConvertOperators.valueOf("createdById").convertToObjectId())
.addField("updatedByOI")
.withValue(ConvertOperators.valueOf("updatedById").convertToObjectId())
.build()
val lookupCreatedBy = lookup("users", "createdByOI", "_id", "createdBy")
val unwindCreatedBy = unwind("createdBy")
val lookupUpdatedBy = lookup("users", "updatedByOI", "_id", "updatedBy")
val unwindUpdatedBy = unwind("updatedBy")
val matchCriteria = mutableListOf<Criteria>()
matchCriteria.add(Criteria.where("spaceId").`is`(spaceId))
matchCriteria.add(Criteria.where("isDeleted").`is`(false))
val matchStage = match(Criteria().andOperator(*matchCriteria.toTypedArray()))
return listOf(addFieldsAsOJ, lookupCreatedBy, unwindCreatedBy, lookupUpdatedBy, unwindUpdatedBy, matchStage)
}
override suspend fun getAccounts(spaceId: String): List<Account> {
val basicAggregation = basicAggregation(spaceId)
val aggregation = newAggregation(*basicAggregation.toTypedArray())
return mongoTemplate.aggregate(aggregation, "accounts", Account::class.java)
.collectList()
.awaitSingle()
}
override suspend fun getAccount(
spaceId: String,
accountId: String
): Account {
val basicAggregation = basicAggregation(spaceId)
val matchStage = match (Criteria.where("_id").`is`(ObjectId(accountId)))
val aggregation = newAggregation(matchStage, *basicAggregation.toTypedArray())
return mongoTemplate.aggregate(aggregation, "accounts", Account::class.java)
.awaitSingle()
}
override suspend fun getAccountTransactions(
spaceId: String,
accountId: String
): List<Transaction> {
val space = spaceService.checkSpace(spaceId)
val filter = TransactionService.TransactionsFilter(
accountId = accountId,
)
return transactionService.getTransactions(spaceId, filter, "date", "ASC")
}
override suspend fun createAccount(
spaceId: String,
account: AccountDTO.CreateAccountDTO
): Account {
val createdAccount = Account(
type = account.type,
spaceId = spaceId,
name = account.name,
currencyCode = account.currencyCode,
amount = account.amount,
goalId = account.goalId,
)
return accountRepo.save(createdAccount).awaitSingle()
}
override suspend fun updateAccount(
spaceId: String,
account: AccountDTO.UpdateAccountDTO
): Account {
val existingAccount = getAccount(spaceId, account.id)
val newAccount = existingAccount.copy(
name = account.name,
type = account.type,
currencyCode = account.currencyCode,
amount = account.amount,
goalId = account.goalId,
)
return accountRepo.save(newAccount).awaitSingle()
}
override suspend fun deleteAccount(spaceId: String, accountId: String) {
val existingAccount = getAccount(spaceId, accountId)
existingAccount.isDeleted = true
accountRepo.save(existingAccount).awaitSingle()
}
}