This commit is contained in:
Vladimir Voronin
2025-01-07 12:35:17 +03:00
commit afd8e9f6d7
72 changed files with 4606 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
package space.luminic.budgerapp.repos
import org.springframework.data.domain.Sort
import org.springframework.data.mongodb.core.aggregation.SortOperation
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.data.mongodb.repository.Query
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.data.repository.PagingAndSortingRepository
import org.springframework.stereotype.Repository
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.Budget
import java.time.LocalDate
import java.util.Date
import java.util.Optional
@Repository
interface BudgetRepo: ReactiveMongoRepository<Budget, String> {
override fun findAll(sort: Sort): Flux<Budget>
fun findByDateFromLessThanEqualAndDateToGreaterThan(dateOne: LocalDate, dateTwo: LocalDate): Mono<Budget>
}

View File

@@ -0,0 +1,15 @@
package space.luminic.budgerapp.repos
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.Category
import java.util.Optional
@Repository
interface CategoryRepo : ReactiveMongoRepository<Category, String> {
fun findByName(name: String): Mono<Category>
}

View File

@@ -0,0 +1,11 @@
package space.luminic.budgerapp.repos
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.stereotype.Repository
import space.luminic.budgerapp.models.Category
@Repository
interface CategoryRepoOld: MongoRepository<Category, String> {
fun findByName(name: String): Category?
}

View File

@@ -0,0 +1,11 @@
package space.luminic.budgerapp.repos
import org.bson.types.ObjectId
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository
import space.luminic.budgerapp.models.Recurrent
@Repository
interface RecurrentRepo: ReactiveMongoRepository<Recurrent, String> {
}

View File

@@ -0,0 +1,11 @@
package space.luminic.budgerapp.repos
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository
import space.luminic.budgerapp.models.Subscription
@Repository
interface SubscriptionRepo : ReactiveMongoRepository<Subscription, String> {
}

View File

@@ -0,0 +1,17 @@
package space.luminic.budgerapp.repos
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.Token
import space.luminic.budgerapp.models.TokenStatus
import java.time.LocalDateTime
@Repository
interface TokenRepo: ReactiveMongoRepository<Token, String> {
fun findByToken(token: String): Mono<Token>
fun findByUsernameAndStatus(username: String, status: TokenStatus): Mono<List<Token>>
fun deleteByExpiresAtBefore(dateTime: LocalDateTime)
}

View File

@@ -0,0 +1,20 @@
package space.luminic.budgerapp.repos
import org.bson.types.ObjectId
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository
import space.luminic.budgerapp.models.Transaction
import java.util.Optional
@Repository
interface TransactionReactiveRepo: ReactiveMongoRepository<Transaction, String> {
// fun findByOldId(transactionId: Int): Optional<Transaction>
fun findByParentId(parentId: String): Optional<Transaction>
}

View File

@@ -0,0 +1,21 @@
package space.luminic.budgerapp.repos
import org.bson.types.ObjectId
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.Transaction
import java.util.Optional
@Repository
interface TransactionRepo: ReactiveMongoRepository<Transaction, String> {
// fun findByOldId(transactionId: Int): Optional<Transaction>
fun findByParentId(parentId: String): Mono<Transaction>
}

View File

@@ -0,0 +1,19 @@
package space.luminic.budgerapp.repos
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.data.mongodb.repository.Query
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.User
import java.util.Optional
@Repository
interface UserRepo : ReactiveMongoRepository<User, String> {
@Query(value = "{ 'username': ?0 }", fields = "{ 'password': 0 }")
fun findByUsernameWOPassword(username: String): Mono<User>
fun findByUsername(username: String): Mono<User>
}

View File

@@ -0,0 +1,9 @@
package space.luminic.budgerapp.repos
import org.springframework.data.mongodb.repository.MongoRepository
import space.luminic.budgerapp.models.User
interface UserRepoOld: MongoRepository<User, String> {
fun findByUsername(username: String): User?
}

View File

@@ -0,0 +1,19 @@
package space.luminic.budgerapp.repos
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import space.luminic.budgerapp.models.Warn
@Repository
interface WarnRepo : ReactiveMongoRepository<Warn, String> {
fun findAllByBudgetIdAndIsHide(budgetId: String, isHide: Boolean): Flux<Warn>
fun deleteAllByBudgetId(budgetId: String)
fun findWarnByContext(context: String): Mono<Warn>
}

View File

@@ -0,0 +1,137 @@
package space.luminic.budgerapp.repos.sqlrepo
import org.slf4j.LoggerFactory
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.core.RowMapper
import org.springframework.stereotype.Repository
import space.luminic.budgerapp.controllers.dtos.BudgetCreationDTO
import space.luminic.budgerapp.models.Budget
import space.luminic.budgerapp.models.BudgetCategory
import space.luminic.budgerapp.models.Category
import space.luminic.budgerapp.models.CategoryType
import space.luminic.budgerapp.models.Transaction
import space.luminic.budgerapp.models.TransactionType
import space.luminic.budgerapp.services.CategoryService
import space.luminic.budgerapp.services.UserService
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.ZoneId
import java.time.ZoneOffset
@Repository
class BudgetRepoSQL(
val jdbcTemplate: JdbcTemplate,
val userService: UserService,
val categoryService: CategoryService,
val transactionsRepoSQl: TransactionsRepoSQl
) {
private val logger = LoggerFactory.getLogger(BudgetRepoSQL::class.java)
fun getBudgetsIds(): List<Int> {
return jdbcTemplate.queryForList("SELECT id FROM budger.budgets", Int::class.java)
}
fun getBudgets(): List<BudgetCreationDTO> {
val sql = "SELECT * FROM budger.budgets"
return jdbcTemplate.query(sql, RowMapper { rs, _ ->
BudgetCreationDTO(
Budget(
// id = rs.getString("id"),
name = rs.getString("name"),
dateFrom = rs.getDate("date_from").toLocalDate(),
dateTo = rs.getDate("date_to").toLocalDate(),
createdAt = LocalDateTime.of(rs.getDate("created_at").toLocalDate(), LocalTime.NOON),
), false
)
})
}
// fun getBudgetCategory(id: Int): List<BudgetCategory> {
// val sql = "SELECT c.*, \n" +
// " COALESCE(SUM(CASE WHEN t.transaction_type_code = 'INSTANT' THEN t.amount END), 0) AS total_instant_expenses,\n" +
// " COALESCE(SUM(CASE WHEN t.transaction_type_code = 'PLANNED' THEN t.amount END), 0) AS total_planned_expenses,\n" +
// " COALESCE(bcs.category_setting_value, 0) AS current_limit,\n" +
// " COALESCE((SELECT AVG(amount) FROM budger.transactions where category_id=c.id AND transaction_type_code='INSTANT'),0) as average\n" +
// "FROM\n" +
// " budger.budget_category_settings bcs\n" +
// "JOIN\n" +
// " budger.budgets b ON bcs.budget_id = b.id\n" +
// "LEFT JOIN\n" +
// " budger.transactions t ON bcs.category_id = t.category_id\n" +
// " AND t.date BETWEEN b.date_from AND b.date_to\n" +
// "JOIN\n" +
// " budger.categories c ON bcs.category_id = c.id\n" +
// "WHERE\n" +
// " b.id = ? -- Укажите ID бюджета, для которого нужно вывести данные\n" +
// "GROUP BY\n" +
// " c.id, bcs.category_setting_value\n" +
// "ORDER BY\n" +
// " c.id;"
// return jdbcTemplate.query(sql, RowMapper { rs, _ ->
// BudgetCategory(
// currentSpent = rs.getBigDecimal("total_instant_expenses"),
// currentLimit = rs.getBigDecimal("current_limit"),
// category = categoryService.getCategoryByName(rs.getString("name"))
// )
// }, id)
// }
fun getBudgetTransactions(id: Int, transactionType: String?, categoryType: String?): List<Transaction> {
val whereConditions = mutableListOf<String>()
val parameters = mutableListOf<Any>()
// Базовое условие
whereConditions.add("b.id = ?")
parameters.add(id)
// Условие для transactionType, если указано
if (transactionType != null) {
whereConditions.add("t.transaction_type_code = ?")
parameters.add(transactionType)
}
// Условие для categoryType, если указано
if (categoryType != null) {
whereConditions.add("c.type_code = ?")
parameters.add(categoryType)
}
// Генерация WHERE
val whereClause = if (whereConditions.isNotEmpty()) "WHERE ${whereConditions.joinToString(" AND ")}" else ""
// SQL запрос
val sql = """
SELECT
tt.code as tt_code,
tt.name as tt_name,
t.comment,
t.date,
t.amount,
t.is_done,
t.created_at,
u.username,
c.name as c_name,
t.id
FROM budger.transactions t
JOIN budger.transaction_types tt ON tt.code = t.transaction_type_code
JOIN budger.categories c ON c.id = t.category_id
JOIN budger.category_types ct ON ct.code = c.type_code
JOIN budger.budgets b ON t.date BETWEEN b.date_from AND b.date_to
LEFT JOIN budger.users u ON t.user_id = u.id
$whereClause
ORDER BY t.date DESC, c.name, t.id
""".trimIndent()
logger.info(parameters.toTypedArray().toString())
// Выполнение запроса
return jdbcTemplate.query(
sql, parameters.toTypedArray(),
transactionsRepoSQl.transactionRowMapper()
)
}
}

View File

@@ -0,0 +1,40 @@
package space.luminic.budgerapp.repos.sqlrepo
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.core.RowMapper
import org.springframework.stereotype.Repository
import space.luminic.budgerapp.models.Category
import space.luminic.budgerapp.models.CategoryType
import space.luminic.budgerapp.models.Transaction
import space.luminic.budgerapp.models.TransactionType
import java.time.LocalDate
import java.time.ZoneId
@Repository
class CategoriesRepoSQL(private val jdbcTemplate: JdbcTemplate) {
fun getCategories(): List<Category> {
val sql = "SELECT * FROM budger.categories"
return jdbcTemplate.query(sql, categoriesRowMapper())
}
fun categoriesRowMapper() = RowMapper { rs, _ ->
val category = Category(
type = if (rs.getString("type_code") == "EXPENSE") CategoryType("EXPENSE", "Траты") else CategoryType(
"INCOME",
"Поступления"
),
name = rs.getString("name"),
description = rs.getString("description"),
icon = rs.getString("icon")
)
return@RowMapper category
}
}

View File

@@ -0,0 +1,38 @@
package space.luminic.budgerapp.repos.sqlrepo
import org.slf4j.LoggerFactory
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.core.RowMapper
import org.springframework.stereotype.Repository
import space.luminic.budgerapp.models.Recurrent
import space.luminic.budgerapp.models.Transaction
import space.luminic.budgerapp.models.TransactionType
import space.luminic.budgerapp.services.CategoryService
@Repository
class RecurrentRepoSQL(
private val jdbcTemplate: JdbcTemplate,
private val categoryService: CategoryService
) {
private val logger = LoggerFactory.getLogger(RecurrentRepoSQL::class.java)
fun getRecurrents(): List<Recurrent> {
return jdbcTemplate.query("SELECT r.*, c.name as c_name FROM budger.recurrent_payments r join budger.categories c on r.category_id = c.id ", recurrentRowMapper())
}
fun recurrentRowMapper() = RowMapper { rs, _ ->
val recurrent = Recurrent(
atDay = rs.getInt("at_day"),
category = categoryService.getCategoryByName(rs.getString("c_name")).block()!!,
name = rs.getString("name"),
description = rs.getString("description"),
amount = rs.getInt("amount")
)
logger.info(recurrent.toString())
return@RowMapper recurrent
}
}

View File

@@ -0,0 +1,65 @@
package space.luminic.budgerapp.repos.sqlrepo
import org.slf4j.LoggerFactory
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.core.RowMapper
import org.springframework.stereotype.Repository
import space.luminic.budgerapp.models.Category
import space.luminic.budgerapp.models.Transaction
import space.luminic.budgerapp.models.TransactionType
import space.luminic.budgerapp.models.User
import space.luminic.budgerapp.repos.CategoryRepoOld
import space.luminic.budgerapp.repos.UserRepoOld
import space.luminic.budgerapp.services.CategoryService
import space.luminic.budgerapp.services.UserService
import java.sql.SQLException
import java.time.LocalDate
import java.time.ZoneId
@Repository
class TransactionsRepoSQl(
private val jdbcTemplate: JdbcTemplate,
private val userRepoOld: UserRepoOld,
private val categoryRepoOld: CategoryRepoOld
) {
private val logger = LoggerFactory.getLogger(TransactionsRepoSQl::class.java)
fun getTransactions(): List<Transaction> {
return jdbcTemplate.query(
"SELECT tt.code as tt_code, tt.name as tt_name, u.username, c.name as c_name, t.comment, t.date, t.amount, t.is_done, t.created_at, t.id" +
" FROM budger.transactions t" +
" JOIN budger.transaction_types tt on t.transaction_type_code = tt.code " +
" JOIN budger.categories c on t.category_id = c.id" +
" LEFT JOIN budger.users u on t.user_id = u.id", transactionRowMapper()
)
}
fun transactionRowMapper() = RowMapper { rs, _ ->
val transaction = Transaction(
type = TransactionType(rs.getString("tt_code"), rs.getString("tt_name")),
user = rs.getString("username")
?.let { userRepoOld.findByUsername(it) }
?: userRepoOld.findByUsername("voroninv"),
category = categoryRepoOld.findByName(rs.getString("c_name"))!!,
comment = rs.getString("comment"),
date = rs.getDate("date").toLocalDate(),
amount = rs.getDouble("amount"),
isDone = rs.getBoolean("is_done"),
createdAt = rs.getTimestamp("created_at").toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime()
)
logger.info(transaction.toString())
return@RowMapper transaction
}
}