Compare commits
6 Commits
recurrents
...
targets
| Author | SHA1 | Date | |
|---|---|---|---|
| 2452e5935f | |||
| 195bdd83f0 | |||
| 42cbf30bd8 | |||
| 5803fc208b | |||
| a79dbffe3f | |||
| 9d7c385654 |
@@ -5,7 +5,6 @@ USER root
|
|||||||
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
|
||||||
RUN groupadd --system --gid 1001 app && useradd --system --gid app --uid 1001 --shell /bin/bash --create-home app
|
RUN groupadd --system --gid 1001 app && useradd --system --gid app --uid 1001 --shell /bin/bash --create-home app
|
||||||
RUN mkdir -p /app/static && chown -R app:app /app
|
RUN mkdir -p /app/static && chown -R app:app /app
|
||||||
COPY build/libs/luminic-space-v2.jar /app/luminic-space-v2.jar
|
|
||||||
USER app
|
USER app
|
||||||
|
|
||||||
ENV JAVA_TOOL_OPTIONS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
|
ENV JAVA_TOOL_OPTIONS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package space.luminic.finance.api
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
|
||||||
import org.springframework.web.bind.annotation.RestController
|
|
||||||
import space.luminic.finance.dtos.GoalDTO
|
|
||||||
import space.luminic.finance.mappers.GoalMapper.toDto
|
|
||||||
import space.luminic.finance.services.GoalService
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/spaces/{spaceId}/goals")
|
|
||||||
class GoalController(private val goalService: GoalService) {
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
fun findAll(@PathVariable spaceId: Int): List<GoalDTO> {
|
|
||||||
return goalService.findAllBySpaceId(spaceId).map { it.toDto() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package space.luminic.finance.api
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
import space.luminic.finance.dtos.TargetDTO
|
||||||
|
import space.luminic.finance.mappers.TargetMapper.toDto
|
||||||
|
import space.luminic.finance.services.TargetService
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/spaces/{spaceId}/targets")
|
||||||
|
class TargetController(private val targetService: TargetService) {
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
fun findAll(@PathVariable spaceId: Int): List<TargetDTO> {
|
||||||
|
return targetService.findAllBySpaceId(spaceId).map { it.toDto() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,9 +21,9 @@ class TransactionController (
|
|||||||
){
|
){
|
||||||
|
|
||||||
|
|
||||||
@GetMapping
|
@PostMapping("/_search")
|
||||||
fun getTransactions(@PathVariable spaceId: Int) : List<TransactionDTO>{
|
fun getTransactions(@PathVariable spaceId: Int, @RequestBody filter: TransactionService.TransactionsFilter) : List<TransactionDTO>{
|
||||||
return transactionService.getTransactions(spaceId, TransactionService.TransactionsFilter(),"date", "DESC").map { it.toDto() }
|
return transactionService.getTransactions(spaceId, filter,"date", "DESC").map { it.toDto() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{transactionId}")
|
@GetMapping("/{transactionId}")
|
||||||
|
|||||||
@@ -1,36 +1,37 @@
|
|||||||
package space.luminic.finance.dtos
|
package space.luminic.finance.dtos
|
||||||
|
|
||||||
import space.luminic.finance.models.Goal
|
import space.luminic.finance.models.Target
|
||||||
import space.luminic.finance.models.Goal.GoalType
|
import space.luminic.finance.models.Target.TargetType
|
||||||
import space.luminic.finance.models.Transaction
|
import space.luminic.finance.models.Transaction
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
|
||||||
data class GoalDTO(
|
data class TargetDTO(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val type: GoalType,
|
val type: TargetType,
|
||||||
val name: String,
|
val name: String,
|
||||||
val description: String? = null,
|
val description: String? = null,
|
||||||
val amount: BigDecimal,
|
val amount: BigDecimal,
|
||||||
|
val currentAmount: BigDecimal,
|
||||||
val date: LocalDate,
|
val date: LocalDate,
|
||||||
val components: List<Goal.GoalComponent>,
|
val components: List<Target.TargetComponent>,
|
||||||
val transactions: List<Transaction>,
|
val transactions: List<Transaction>,
|
||||||
val createdBy: UserDTO,
|
val createdBy: UserDTO,
|
||||||
val createdAt: Instant,
|
val createdAt: Instant,
|
||||||
val updatedBy: UserDTO? = null,
|
val updatedBy: UserDTO? = null,
|
||||||
val updatedAt: Instant? = null,
|
val updatedAt: Instant? = null,
|
||||||
) {
|
) {
|
||||||
data class CreateGoalDTO(
|
data class CreateTargetDTO(
|
||||||
val type: GoalType,
|
val type: TargetType,
|
||||||
val name: String,
|
val name: String,
|
||||||
val description: String?,
|
val description: String?,
|
||||||
val amount: BigDecimal,
|
val amount: BigDecimal,
|
||||||
val date: LocalDate
|
val date: LocalDate
|
||||||
)
|
)
|
||||||
|
|
||||||
data class UpdateGoalDTO(
|
data class UpdateTargetDTO(
|
||||||
val type: GoalType,
|
val type: TargetType,
|
||||||
val name: String,
|
val name: String,
|
||||||
val description: String?,
|
val description: String?,
|
||||||
val amount: BigDecimal,
|
val amount: BigDecimal,
|
||||||
@@ -1,22 +1,26 @@
|
|||||||
package space.luminic.finance.mappers
|
package space.luminic.finance.mappers
|
||||||
|
|
||||||
import space.luminic.finance.dtos.GoalDTO
|
import space.luminic.finance.dtos.TargetDTO
|
||||||
import space.luminic.finance.mappers.UserMapper.toDto
|
import space.luminic.finance.mappers.UserMapper.toDto
|
||||||
import space.luminic.finance.models.Goal
|
import space.luminic.finance.models.Target
|
||||||
|
|
||||||
object GoalMapper {
|
object TargetMapper {
|
||||||
|
|
||||||
fun Goal.toDto() = GoalDTO(
|
fun Target.toDto() = TargetDTO(
|
||||||
id = this.id ?: throw IllegalArgumentException("Goal id is not provided"),
|
id = this.id ?: throw IllegalArgumentException("Target id is not provided"),
|
||||||
type = this.type,
|
type = this.type,
|
||||||
name = this.name,
|
name = this.name,
|
||||||
|
description = this.description,
|
||||||
amount = this.amount,
|
amount = this.amount,
|
||||||
|
currentAmount = this.currentAmount,
|
||||||
date = this.untilDate,
|
date = this.untilDate,
|
||||||
components = this.components,
|
components = this.components,
|
||||||
transactions = this.transactions,
|
transactions = this.transactions,
|
||||||
createdBy = (this.createdBy ?: throw IllegalArgumentException("created by not provided")).toDto(),
|
createdBy = (this.createdBy ?: throw IllegalArgumentException("created by not provided")).toDto(),
|
||||||
createdAt = this.createdAt ?: throw IllegalArgumentException("created at not provided"),
|
createdAt = this.createdAt ?: throw IllegalArgumentException("created at not provided"),
|
||||||
updatedBy = this.updatedBy?.toDto() ,
|
updatedBy = this.updatedBy?.toDto(),
|
||||||
updatedAt = this.updatedAt
|
updatedAt = this.updatedAt,
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -8,30 +8,30 @@ import java.math.BigDecimal
|
|||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
|
||||||
data class Goal(
|
data class Target(
|
||||||
var id: Int? = null,
|
var id: Int? = null,
|
||||||
val space: Space? = null,
|
val space: Space? = null,
|
||||||
val type: GoalType,
|
val type: TargetType,
|
||||||
val name: String,
|
val name: String,
|
||||||
val description: String? = null,
|
val description: String? = null,
|
||||||
val amount: BigDecimal,
|
val amount: BigDecimal,
|
||||||
val components: List<GoalComponent> = emptyList(),
|
val components: List<TargetComponent> = emptyList(),
|
||||||
val transactions: List<Transaction> = emptyList(),
|
val transactions: List<Transaction> = emptyList(),
|
||||||
val untilDate: LocalDate,
|
val untilDate: LocalDate,
|
||||||
@CreatedBy var createdBy: User? = null,
|
var createdBy: User? = null,
|
||||||
|
|
||||||
@CreatedDate var createdAt: Instant? = null,
|
var createdAt: Instant? = null,
|
||||||
@LastModifiedBy var updatedBy: User? = null,
|
var updatedBy: User? = null,
|
||||||
|
|
||||||
@LastModifiedDate var updatedAt: Instant? = null,
|
var updatedAt: Instant? = null,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var currentAmount: BigDecimal = {
|
var currentAmount: BigDecimal = {
|
||||||
this.transactions.sumOf { it.amount }
|
this.transactions.sumOf { it.amount }
|
||||||
} as BigDecimal
|
} as BigDecimal
|
||||||
|
|
||||||
|
|
||||||
data class GoalComponent(
|
data class TargetComponent(
|
||||||
val id: Int? = null,
|
val id: Int? = null,
|
||||||
val name: String,
|
val name: String,
|
||||||
val amount: BigDecimal,
|
val amount: BigDecimal,
|
||||||
@@ -39,8 +39,9 @@ data class Goal(
|
|||||||
val date: LocalDate = LocalDate.now(),
|
val date: LocalDate = LocalDate.now(),
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class GoalType(val displayName: String, val icon: String) {
|
enum class TargetType(val displayName: String, val icon: String) {
|
||||||
AUTO("Авто", "🏎️"),
|
AUTO("Авто", "🏎️"),
|
||||||
|
LEISURE("Досуг", "💃"),
|
||||||
VACATION("Отпуск", "🏖️"),
|
VACATION("Отпуск", "🏖️"),
|
||||||
GOODS("Покупка", "🛍️"),
|
GOODS("Покупка", "🛍️"),
|
||||||
OTHER("Прочее", "💸")
|
OTHER("Прочее", "💸")
|
||||||
@@ -15,7 +15,7 @@ data class Transaction(
|
|||||||
val type: TransactionType = TransactionType.EXPENSE,
|
val type: TransactionType = TransactionType.EXPENSE,
|
||||||
val kind: TransactionKind = TransactionKind.INSTANT,
|
val kind: TransactionKind = TransactionKind.INSTANT,
|
||||||
val category: Category? = null,
|
val category: Category? = null,
|
||||||
val comment: String,
|
var comment: String,
|
||||||
val amount: BigDecimal,
|
val amount: BigDecimal,
|
||||||
val fees: BigDecimal = BigDecimal.ZERO,
|
val fees: BigDecimal = BigDecimal.ZERO,
|
||||||
val date: LocalDate = LocalDate.now(),
|
val date: LocalDate = LocalDate.now(),
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package space.luminic.finance.repos
|
|
||||||
|
|
||||||
import space.luminic.finance.models.Goal
|
|
||||||
|
|
||||||
interface GoalRepo {
|
|
||||||
|
|
||||||
fun findAllBySpaceId(spaceId: Int) : List<Goal>
|
|
||||||
fun findBySpaceIdAndId(spaceId: Int, id: Int) : Goal?
|
|
||||||
fun create(goal: Goal, createdById: Int): Int
|
|
||||||
fun update(goal: Goal, updatedById: Int)
|
|
||||||
fun delete(spaceId: Int, id: Int)
|
|
||||||
fun getComponents(spaceId: Int, goalId: Int): List<Goal.GoalComponent>
|
|
||||||
fun getComponent(spaceId: Int, goalId: Int, id: Int): Goal.GoalComponent?
|
|
||||||
fun createComponent(goalId: Int, component: Goal.GoalComponent, createdById: Int): Int
|
|
||||||
fun updateComponent(goalId: Int, componentId: Int, component: Goal.GoalComponent, updatedById: Int)
|
|
||||||
fun deleteComponent(goalId: Int, componentId: Int)
|
|
||||||
|
|
||||||
fun assignTransaction(goalId: Int, transactionId: Int)
|
|
||||||
fun refuseTransaction(goalId: Int, transactionId: Int)
|
|
||||||
}
|
|
||||||
@@ -74,7 +74,7 @@ class RecurrentOperationRepoImpl(
|
|||||||
join finance.categories c on ro.category_id = c.id
|
join finance.categories c on ro.category_id = c.id
|
||||||
join finance.users r_created_by on ro.created_by_id = r_created_by.id
|
join finance.users r_created_by on ro.created_by_id = r_created_by.id
|
||||||
where ro.space_id = :spaceId
|
where ro.space_id = :spaceId
|
||||||
order by ro.date
|
order by ro.date, ro.id
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf("spaceId" to spaceId)
|
val params = mapOf("spaceId" to spaceId)
|
||||||
return jdbcTemplate.query(sql, params, operationRowMapper())
|
return jdbcTemplate.query(sql, params, operationRowMapper())
|
||||||
|
|||||||
20
src/main/kotlin/space/luminic/finance/repos/TargetRepo.kt
Normal file
20
src/main/kotlin/space/luminic/finance/repos/TargetRepo.kt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package space.luminic.finance.repos
|
||||||
|
|
||||||
|
import space.luminic.finance.models.Target
|
||||||
|
|
||||||
|
interface TargetRepo {
|
||||||
|
|
||||||
|
fun findAllBySpaceId(spaceId: Int) : List<Target>
|
||||||
|
fun findBySpaceIdAndId(spaceId: Int, id: Int) : Target?
|
||||||
|
fun create(target: Target, createdById: Int): Int
|
||||||
|
fun update(target: Target, updatedById: Int)
|
||||||
|
fun delete(spaceId: Int, id: Int)
|
||||||
|
fun getComponents(spaceId: Int, targetId: Int): List<Target.TargetComponent>
|
||||||
|
fun getComponent(spaceId: Int, targetId: Int, id: Int): Target.TargetComponent?
|
||||||
|
fun createComponent(targetId: Int, component: Target.TargetComponent, createdById: Int): Int
|
||||||
|
fun updateComponent(targetId: Int, componentId: Int, component: Target.TargetComponent, updatedById: Int)
|
||||||
|
fun deleteComponent(targetId: Int, componentId: Int)
|
||||||
|
|
||||||
|
fun assignTransaction(targetId: Int, transactionId: Int)
|
||||||
|
fun refuseTransaction(targetId: Int, transactionId: Int)
|
||||||
|
}
|
||||||
@@ -3,17 +3,17 @@ package space.luminic.finance.repos
|
|||||||
import org.springframework.jdbc.core.RowMapper
|
import org.springframework.jdbc.core.RowMapper
|
||||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
|
||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
import space.luminic.finance.models.Goal
|
import space.luminic.finance.models.Target
|
||||||
import space.luminic.finance.models.User
|
import space.luminic.finance.models.User
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
class GoalRepoImpl(
|
class TargetRepoImpl(
|
||||||
private val jdbcTemplate: NamedParameterJdbcTemplate
|
private val jdbcTemplate: NamedParameterJdbcTemplate
|
||||||
) : GoalRepo {
|
) : TargetRepo {
|
||||||
private val goalRowMapper = RowMapper { rs, _ ->
|
private val targetRowMapper = RowMapper { rs, _ ->
|
||||||
Goal(
|
Target(
|
||||||
id = rs.getInt("g_id"),
|
id = rs.getInt("g_id"),
|
||||||
type = Goal.GoalType.valueOf(rs.getString("g_type")),
|
type = Target.TargetType.valueOf(rs.getString("g_type")),
|
||||||
name = rs.getString("g_name"),
|
name = rs.getString("g_name"),
|
||||||
description = rs.getString("g_description"),
|
description = rs.getString("g_description"),
|
||||||
amount = rs.getBigDecimal("g_amount"),
|
amount = rs.getBigDecimal("g_amount"),
|
||||||
@@ -30,7 +30,7 @@ class GoalRepoImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val componentRowMapper = RowMapper { rs, _ ->
|
private val componentRowMapper = RowMapper { rs, _ ->
|
||||||
Goal.GoalComponent(
|
Target.TargetComponent(
|
||||||
id = rs.getInt("gc_id"),
|
id = rs.getInt("gc_id"),
|
||||||
name = rs.getString("gc_name"),
|
name = rs.getString("gc_name"),
|
||||||
amount = rs.getBigDecimal("gc_amount"),
|
amount = rs.getBigDecimal("gc_amount"),
|
||||||
@@ -39,7 +39,7 @@ class GoalRepoImpl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findAllBySpaceId(spaceId: Int): List<Goal> {
|
override fun findAllBySpaceId(spaceId: Int): List<Target> {
|
||||||
val sql = """
|
val sql = """
|
||||||
select
|
select
|
||||||
g.id as g_id,
|
g.id as g_id,
|
||||||
@@ -51,7 +51,7 @@ class GoalRepoImpl(
|
|||||||
created_by.username as created_by_username,
|
created_by.username as created_by_username,
|
||||||
created_by.first_name as created_by_first_name,
|
created_by.first_name as created_by_first_name,
|
||||||
g.created_at as g_created_at
|
g.created_at as g_created_at
|
||||||
from finance.goals g
|
from finance.targets g
|
||||||
join finance.users created_by on g.created_by_id = created_by.id
|
join finance.users created_by on g.created_by_id = created_by.id
|
||||||
where g.space_id = :spaceId
|
where g.space_id = :spaceId
|
||||||
|
|
||||||
@@ -60,10 +60,10 @@ class GoalRepoImpl(
|
|||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
"space_id" to spaceId,
|
"space_id" to spaceId,
|
||||||
)
|
)
|
||||||
return jdbcTemplate.query(sql, params, goalRowMapper)
|
return jdbcTemplate.query(sql, params, targetRowMapper)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findBySpaceIdAndId(spaceId: Int, id: Int): Goal? {
|
override fun findBySpaceIdAndId(spaceId: Int, id: Int): Target? {
|
||||||
val sql = """
|
val sql = """
|
||||||
select
|
select
|
||||||
g.id as g_id,
|
g.id as g_id,
|
||||||
@@ -75,7 +75,7 @@ class GoalRepoImpl(
|
|||||||
created_by.username as created_by_username,
|
created_by.username as created_by_username,
|
||||||
created_by.first_name as created_by_first_name,
|
created_by.first_name as created_by_first_name,
|
||||||
g.created_at as g_created_at
|
g.created_at as g_created_at
|
||||||
from finance.goals g
|
from finance.targets g
|
||||||
join finance.users created_by on g.created_by_id = created_by.id
|
join finance.users created_by on g.created_by_id = created_by.id
|
||||||
where g.space_id = :spaceId and g.id = :id
|
where g.space_id = :spaceId and g.id = :id
|
||||||
|
|
||||||
@@ -85,12 +85,12 @@ class GoalRepoImpl(
|
|||||||
"space_id" to spaceId,
|
"space_id" to spaceId,
|
||||||
"id" to id,
|
"id" to id,
|
||||||
)
|
)
|
||||||
return jdbcTemplate.query(sql, params, goalRowMapper).firstOrNull()
|
return jdbcTemplate.query(sql, params, targetRowMapper).firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun create(goal: Goal, createdById: Int): Int {
|
override fun create(target: Target, createdById: Int): Int {
|
||||||
val sql = """
|
val sql = """
|
||||||
insert into finance.goals(
|
insert into finance.targets(
|
||||||
type,
|
type,
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
@@ -108,19 +108,19 @@ class GoalRepoImpl(
|
|||||||
returning id
|
returning id
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
"type" to goal.type,
|
"type" to target.type,
|
||||||
"name" to goal.name,
|
"name" to target.name,
|
||||||
"description" to goal.description,
|
"description" to target.description,
|
||||||
"amount" to goal.amount,
|
"amount" to target.amount,
|
||||||
"until_date" to goal.untilDate,
|
"until_date" to target.untilDate,
|
||||||
"created_by_id" to createdById
|
"created_by_id" to createdById
|
||||||
)
|
)
|
||||||
return jdbcTemplate.queryForObject(sql, params, Int::class.java)!!
|
return jdbcTemplate.queryForObject(sql, params, Int::class.java)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(goal: Goal, updatedById: Int) {
|
override fun update(target: Target, updatedById: Int) {
|
||||||
val sql = """
|
val sql = """
|
||||||
update finance.goals set
|
update finance.targets set
|
||||||
type = :type,
|
type = :type,
|
||||||
name = :name,
|
name = :name,
|
||||||
description = :description,
|
description = :description,
|
||||||
@@ -131,12 +131,12 @@ class GoalRepoImpl(
|
|||||||
where id = :id
|
where id = :id
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
"id" to goal.id,
|
"id" to target.id,
|
||||||
"type" to goal.type.name,
|
"type" to target.type.name,
|
||||||
"name" to goal.name,
|
"name" to target.name,
|
||||||
"description" to goal.description,
|
"description" to target.description,
|
||||||
"amount" to goal.amount,
|
"amount" to target.amount,
|
||||||
"until_date" to goal.untilDate,
|
"until_date" to target.untilDate,
|
||||||
"updated_by_id" to updatedById
|
"updated_by_id" to updatedById
|
||||||
|
|
||||||
)
|
)
|
||||||
@@ -145,7 +145,7 @@ class GoalRepoImpl(
|
|||||||
|
|
||||||
override fun delete(spaceId: Int, id: Int) {
|
override fun delete(spaceId: Int, id: Int) {
|
||||||
val sql = """
|
val sql = """
|
||||||
delete from finance.goals where id = :id
|
delete from finance.targets where id = :id
|
||||||
|
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
@@ -156,8 +156,8 @@ class GoalRepoImpl(
|
|||||||
|
|
||||||
override fun getComponents(
|
override fun getComponents(
|
||||||
spaceId: Int,
|
spaceId: Int,
|
||||||
goalId: Int
|
targetId: Int
|
||||||
): List<Goal.GoalComponent> {
|
): List<Target.TargetComponent> {
|
||||||
val sql = """
|
val sql = """
|
||||||
select
|
select
|
||||||
gc.id as gc_id,
|
gc.id as gc_id,
|
||||||
@@ -165,11 +165,11 @@ class GoalRepoImpl(
|
|||||||
gc.amount as gc_amount,
|
gc.amount as gc_amount,
|
||||||
gc.is_done as gc_is_done,
|
gc.is_done as gc_is_done,
|
||||||
gc.date as gc_date
|
gc.date as gc_date
|
||||||
from finance.goals_components gc
|
from finance.targets_components gc
|
||||||
where gc.goal_id = :goal_id
|
where gc.target_id = :target_id
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
"goal_id" to goalId
|
"target_id" to targetId
|
||||||
)
|
)
|
||||||
return jdbcTemplate.query(sql, params, componentRowMapper)
|
return jdbcTemplate.query(sql, params, componentRowMapper)
|
||||||
|
|
||||||
@@ -177,9 +177,9 @@ class GoalRepoImpl(
|
|||||||
|
|
||||||
override fun getComponent(
|
override fun getComponent(
|
||||||
spaceId: Int,
|
spaceId: Int,
|
||||||
goalId: Int,
|
targetId: Int,
|
||||||
id: Int
|
id: Int
|
||||||
): Goal.GoalComponent? {
|
): Target.TargetComponent? {
|
||||||
val sql = """
|
val sql = """
|
||||||
select
|
select
|
||||||
gc.id as gc_id,
|
gc.id as gc_id,
|
||||||
@@ -187,27 +187,27 @@ class GoalRepoImpl(
|
|||||||
gc.amount as gc_amount,
|
gc.amount as gc_amount,
|
||||||
gc.is_done as gc_is_done,
|
gc.is_done as gc_is_done,
|
||||||
gc.date as gc_date
|
gc.date as gc_date
|
||||||
from finance.goals_components gc
|
from finance.targets_components gc
|
||||||
where gc.goal_id = :goal_id and gc.id = :id
|
where gc.target_id = :target_id and gc.id = :id
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
"goal_id" to goalId,
|
"target_id" to targetId,
|
||||||
"id" to id
|
"id" to id
|
||||||
)
|
)
|
||||||
return jdbcTemplate.query(sql, params, componentRowMapper).firstOrNull()
|
return jdbcTemplate.query(sql, params, componentRowMapper).firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createComponent(goalId: Int, component: Goal.GoalComponent, createdById: Int): Int {
|
override fun createComponent(targetId: Int, component: Target.TargetComponent, createdById: Int): Int {
|
||||||
val sql = """
|
val sql = """
|
||||||
insert into finance.goals_components(
|
insert into finance.targets_components(
|
||||||
goal_id,
|
target_id,
|
||||||
name,
|
name,
|
||||||
amount,
|
amount,
|
||||||
is_done,
|
is_done,
|
||||||
date,
|
date,
|
||||||
created_by_id
|
created_by_id
|
||||||
) values (
|
) values (
|
||||||
:goal_id,
|
:target_id,
|
||||||
:name,
|
:name,
|
||||||
:amount,
|
:amount,
|
||||||
:is_done,
|
:is_done,
|
||||||
@@ -216,7 +216,7 @@ class GoalRepoImpl(
|
|||||||
returning id
|
returning id
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
"goal_id" to goalId,
|
"target_id" to targetId,
|
||||||
"name" to component.name,
|
"name" to component.name,
|
||||||
"amount" to component.amount,
|
"amount" to component.amount,
|
||||||
"is_done" to component.isDone,
|
"is_done" to component.isDone,
|
||||||
@@ -226,17 +226,17 @@ class GoalRepoImpl(
|
|||||||
return jdbcTemplate.queryForObject(sql, params, Int::class.java)!!
|
return jdbcTemplate.queryForObject(sql, params, Int::class.java)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateComponent(goalId: Int, componentId: Int, component: Goal.GoalComponent, updatedById: Int) {
|
override fun updateComponent(targetId: Int, componentId: Int, component: Target.TargetComponent, updatedById: Int) {
|
||||||
val sql = """
|
val sql = """
|
||||||
update finance.goals_components set
|
update finance.targets_components set
|
||||||
name = :name,
|
name = :name,
|
||||||
amount = :amount,
|
amount = :amount,
|
||||||
is_done = :is_done,
|
is_done = :is_done,
|
||||||
updated_by_id = :updated_by_id
|
updated_by_id = :updated_by_id
|
||||||
where goal_id = :goalId and id = :componentId
|
where target_id = :targetId and id = :componentId
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
"goalId" to goalId,
|
"targetId" to targetId,
|
||||||
"componentId" to componentId,
|
"componentId" to componentId,
|
||||||
"name" to component.name,
|
"name" to component.name,
|
||||||
"amount" to component.amount,
|
"amount" to component.amount,
|
||||||
@@ -247,35 +247,35 @@ class GoalRepoImpl(
|
|||||||
jdbcTemplate.update(sql, params)
|
jdbcTemplate.update(sql, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun deleteComponent(goalId: Int, componentId: Int) {
|
override fun deleteComponent(targetId: Int, componentId: Int) {
|
||||||
val sql = """
|
val sql = """
|
||||||
delete from finance.goals_components where goal_id = :goalId and id = :componentId
|
delete from finance.targets_components where target_id = :targetId and id = :componentId
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
"goalId" to goalId,
|
"targetId" to targetId,
|
||||||
"componentId" to componentId
|
"componentId" to componentId
|
||||||
)
|
)
|
||||||
jdbcTemplate.update(sql, params)
|
jdbcTemplate.update(sql, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun assignTransaction(goalId: Int, transactionId: Int) {
|
override fun assignTransaction(targetId: Int, transactionId: Int) {
|
||||||
val sql = """
|
val sql = """
|
||||||
insert into finance.goals_transactions(goal_id, transactions_id)
|
insert into finance.targets_transactions(target_id, transactions_id)
|
||||||
values (:goal_id, :transaction_id)
|
values (:targetId, :transaction_id)
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
"goal_id" to goalId,
|
"targetId" to targetId,
|
||||||
"transaction_id" to transactionId
|
"transaction_id" to transactionId
|
||||||
)
|
)
|
||||||
jdbcTemplate.update(sql, params)
|
jdbcTemplate.update(sql, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun refuseTransaction(goalId: Int, transactionId: Int) {
|
override fun refuseTransaction(targetId: Int, transactionId: Int) {
|
||||||
val sql = """
|
val sql = """
|
||||||
delete from finance.goals_transactions where goal_id = :goalId and transactions_id = :transactionId
|
delete from finance.targets_transactions where target_id = :goalId and transactions_id = :transactionId
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mapOf(
|
||||||
"goal_id" to goalId,
|
"target_id" to targetId,
|
||||||
"transaction_id" to transactionId
|
"transaction_id" to transactionId
|
||||||
)
|
)
|
||||||
jdbcTemplate.update(sql, params)
|
jdbcTemplate.update(sql, params)
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
package space.luminic.finance.repos
|
package space.luminic.finance.repos
|
||||||
|
|
||||||
import space.luminic.finance.models.Transaction
|
import space.luminic.finance.models.Transaction
|
||||||
|
import space.luminic.finance.services.TransactionService
|
||||||
|
|
||||||
interface TransactionRepo {
|
interface TransactionRepo {
|
||||||
fun findAllBySpaceId(spaceId: Int): List<Transaction>
|
fun findAllBySpaceId(spaceId: Int, filters: TransactionService.TransactionsFilter): List<Transaction>
|
||||||
fun findBySpaceIdAndId(spaceId: Int, id: Int): Transaction?
|
fun findBySpaceIdAndId(spaceId: Int, id: Int): Transaction?
|
||||||
|
fun findBySpaceIdAndRecurrentId(spaceId: Int, recurrentId: Int): List<Transaction>
|
||||||
fun create(transaction: Transaction, userId: Int): Int
|
fun create(transaction: Transaction, userId: Int): Int
|
||||||
fun createBatch(transactions: List<Transaction>, userId: Int)
|
fun createBatch(transactions: List<Transaction>, userId: Int)
|
||||||
fun update(transaction: Transaction): Int
|
fun update(transaction: Transaction): Int
|
||||||
|
fun updateBatch(transactions: List<Transaction>, userId: Int)
|
||||||
fun delete(transactionId: Int)
|
fun delete(transactionId: Int)
|
||||||
fun deleteByRecurrentId(spaceId: Int, recurrentId: Int)
|
fun deleteByRecurrentId(spaceId: Int, recurrentId: Int)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import org.springframework.stereotype.Repository
|
|||||||
import space.luminic.finance.models.Category
|
import space.luminic.finance.models.Category
|
||||||
import space.luminic.finance.models.Transaction
|
import space.luminic.finance.models.Transaction
|
||||||
import space.luminic.finance.models.User
|
import space.luminic.finance.models.User
|
||||||
|
import space.luminic.finance.services.TransactionService
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
class TransactionRepoImpl(
|
class TransactionRepoImpl(
|
||||||
@@ -52,8 +55,8 @@ class TransactionRepoImpl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findAllBySpaceId(spaceId: Int): List<Transaction> {
|
override fun findAllBySpaceId(spaceId: Int, filters: TransactionService.TransactionsFilter): List<Transaction> {
|
||||||
val sql = """
|
var sql = """
|
||||||
SELECT
|
SELECT
|
||||||
t.id AS t_id,
|
t.id AS t_id,
|
||||||
t.parent_id AS t_parent_id,
|
t.parent_id AS t_parent_id,
|
||||||
@@ -86,11 +89,42 @@ class TransactionRepoImpl(
|
|||||||
LEFT JOIN finance.categories c ON t.category_id = c.id
|
LEFT JOIN finance.categories c ON t.category_id = c.id
|
||||||
JOIN finance.users u ON u.id = t.created_by_id
|
JOIN finance.users u ON u.id = t.created_by_id
|
||||||
WHERE t.space_id = :spaceId and t.is_deleted = false
|
WHERE t.space_id = :spaceId and t.is_deleted = false
|
||||||
ORDER BY t.date, t.id
|
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mapOf(
|
val params = mutableMapOf<String, Any?>(
|
||||||
"spaceId" to spaceId,
|
"spaceId" to spaceId,
|
||||||
|
"offset" to filters.offset,
|
||||||
|
"limit" to filters.limit,
|
||||||
)
|
)
|
||||||
|
filters.type?.let {
|
||||||
|
sql += " AND t.type = :type"
|
||||||
|
params.put("type", it.name)
|
||||||
|
}
|
||||||
|
filters.kind?.let {
|
||||||
|
sql += " AND t.kind = :kind"
|
||||||
|
params.put("kind", it.name)
|
||||||
|
}
|
||||||
|
filters.isDone?.let {
|
||||||
|
sql += " AND t.is_done = :isDone"
|
||||||
|
params.put("isDone", it)
|
||||||
|
}
|
||||||
|
filters.dateFrom?.let {
|
||||||
|
sql += " AND t.date >= :dateFrom"
|
||||||
|
params.put("dateFrom", it)
|
||||||
|
} ?: {
|
||||||
|
sql += " AND t.date >= :dateFrom"
|
||||||
|
params.put("dateFrom", LocalDate.now().minusMonths(1))
|
||||||
|
}
|
||||||
|
filters.dateTo?.let {
|
||||||
|
sql += " AND t.date <= :dateTo"
|
||||||
|
params.put("dateTo", it)
|
||||||
|
}
|
||||||
|
sql += """
|
||||||
|
ORDER BY t.date, t.id
|
||||||
|
OFFSET :offset ROWS
|
||||||
|
FETCH FIRST :limit ROWS ONLY"""
|
||||||
|
|
||||||
|
|
||||||
return jdbcTemplate.query(sql, params, transactionRowMapper())
|
return jdbcTemplate.query(sql, params, transactionRowMapper())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,6 +168,49 @@ class TransactionRepoImpl(
|
|||||||
return jdbcTemplate.query(sql, params, transactionRowMapper()).firstOrNull()
|
return jdbcTemplate.query(sql, params, transactionRowMapper()).firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findBySpaceIdAndRecurrentId(
|
||||||
|
spaceId: Int,
|
||||||
|
recurrentId: Int
|
||||||
|
): List<Transaction> {
|
||||||
|
val sql = """SELECT
|
||||||
|
t.id AS t_id,
|
||||||
|
t.parent_id AS t_parent_id,
|
||||||
|
t.space_id AS t_space_id,
|
||||||
|
t.type AS t_type,
|
||||||
|
t.kind AS t_kind,
|
||||||
|
t.comment AS t_comment,
|
||||||
|
t.amount AS t_amount,
|
||||||
|
t.fees AS t_fees,
|
||||||
|
t.date AS t_date,
|
||||||
|
t.is_deleted AS t_is_deleted,
|
||||||
|
t.is_done AS t_is_done,
|
||||||
|
t.created_at AS t_created_at,
|
||||||
|
t.updated_at AS t_updated_at,
|
||||||
|
t.tg_chat_id AS tg_chat_id,
|
||||||
|
t.tg_message_id AS tg_message_id,
|
||||||
|
c.id AS c_id,
|
||||||
|
c.type AS c_type,
|
||||||
|
c.name AS c_name,
|
||||||
|
c.description AS c_description,
|
||||||
|
c.icon AS c_icon,
|
||||||
|
c.is_deleted AS c_is_deleted,
|
||||||
|
c.created_at AS c_created_at,
|
||||||
|
c.updated_at AS c_updated_at,
|
||||||
|
u.id AS u_id,
|
||||||
|
u.username AS u_username,
|
||||||
|
u.first_name AS u_first_name,
|
||||||
|
t.recurrent_id AS t_recurrent_id
|
||||||
|
FROM finance.transactions t
|
||||||
|
LEFT JOIN finance.categories c ON t.category_id = c.id
|
||||||
|
JOIN finance.users u ON u.id = t.created_by_id
|
||||||
|
WHERE t.space_id = :spaceId and t.recurrent_id = :recurrentId and t.is_deleted = false""".trimMargin()
|
||||||
|
val params = mapOf(
|
||||||
|
"spaceId" to spaceId,
|
||||||
|
"recurrentId" to recurrentId,
|
||||||
|
)
|
||||||
|
return jdbcTemplate.query(sql, params, transactionRowMapper())
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(transaction: Transaction, userId: Int): Int {
|
override fun create(transaction: Transaction, userId: Int): Int {
|
||||||
val sql = """
|
val sql = """
|
||||||
INSERT INTO finance.transactions (space_id, parent_id, type, kind, category_id, comment, amount, fees, date, is_deleted, is_done, created_by_id, tg_chat_id, tg_message_id, recurrent_id) VALUES (
|
INSERT INTO finance.transactions (space_id, parent_id, type, kind, category_id, comment, amount, fees, date, is_deleted, is_done, created_by_id, tg_chat_id, tg_message_id, recurrent_id) VALUES (
|
||||||
@@ -211,14 +288,6 @@ class TransactionRepoImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun update(transaction: Transaction): Int {
|
override fun update(transaction: Transaction): Int {
|
||||||
// val type: TransactionType = TransactionType.EXPENSE,
|
|
||||||
// val kind: TransactionKind = TransactionKind.INSTANT,
|
|
||||||
// val category: Int,
|
|
||||||
// val comment: String,
|
|
||||||
// val amount: BigDecimal,
|
|
||||||
// val fees: BigDecimal = BigDecimal.ZERO,
|
|
||||||
// val isDone: Boolean,
|
|
||||||
// val date: Instant
|
|
||||||
|
|
||||||
val sql = """
|
val sql = """
|
||||||
UPDATE finance.transactions
|
UPDATE finance.transactions
|
||||||
@@ -247,6 +316,39 @@ class TransactionRepoImpl(
|
|||||||
return transaction.id!!
|
return transaction.id!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun updateBatch(transactions: List<Transaction>, userId: Int) {
|
||||||
|
val sql = """
|
||||||
|
UPDATE finance.transactions
|
||||||
|
set type = :type,
|
||||||
|
kind = :kind,
|
||||||
|
category_id = :categoryId,
|
||||||
|
comment = :comment,
|
||||||
|
amount = :amount,
|
||||||
|
fees = :fees,
|
||||||
|
is_done = :is_done,
|
||||||
|
date = :date,
|
||||||
|
updated_by_id = :updatedById,
|
||||||
|
updated_at = now()
|
||||||
|
where id = :id
|
||||||
|
""".trimIndent()
|
||||||
|
val batchValues = transactions.map { transaction ->
|
||||||
|
mapOf(
|
||||||
|
"id" to transaction.id,
|
||||||
|
"type" to transaction.type.name,
|
||||||
|
"kind" to transaction.kind.name,
|
||||||
|
"categoryId" to transaction.category?.id,
|
||||||
|
"comment" to transaction.comment,
|
||||||
|
"amount" to transaction.amount,
|
||||||
|
"fees" to transaction.fees,
|
||||||
|
"date" to transaction.date,
|
||||||
|
"is_done" to transaction.isDone,
|
||||||
|
"updatedById" to userId,
|
||||||
|
)
|
||||||
|
}.toTypedArray()
|
||||||
|
jdbcTemplate.batchUpdate(sql, batchValues)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
override fun delete(transactionId: Int) {
|
override fun delete(transactionId: Int) {
|
||||||
val sql = """
|
val sql = """
|
||||||
update finance.transactions set is_deleted = true where id = :id
|
update finance.transactions set is_deleted = true where id = :id
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
//package space.luminic.finance.services
|
|
||||||
//
|
|
||||||
//import kotlinx.coroutines.reactive.awaitSingle
|
|
||||||
//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.query.Criteria
|
|
||||||
//import org.springframework.stereotype.Service
|
|
||||||
//import space.luminic.finance.dtos.CategoryDTO
|
|
||||||
//import space.luminic.finance.models.Category
|
|
||||||
//import space.luminic.finance.repos.CategoryEtalonRepo
|
|
||||||
//import space.luminic.finance.repos.CategoryRepo
|
|
||||||
//
|
|
||||||
//@Service
|
|
||||||
//class CategoryServiceMongoImpl(
|
|
||||||
// private val categoryRepo: CategoryRepo,
|
|
||||||
// private val categoryEtalonRepo: CategoryEtalonRepo,
|
|
||||||
// private val reactiveMongoTemplate: ReactiveMongoTemplate,
|
|
||||||
// private val authService: AuthService,
|
|
||||||
//) : CategoryService {
|
|
||||||
//
|
|
||||||
// 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 getCategories(spaceId: String): List<Category> {
|
|
||||||
// val basicAggregation = basicAggregation(spaceId)
|
|
||||||
// val aggregation = newAggregation(*basicAggregation.toTypedArray())
|
|
||||||
// return reactiveMongoTemplate.aggregate(aggregation, "categories", Category::class.java).collectList().awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun getCategory(spaceId: String, id: String): Category {
|
|
||||||
// val basicAggregation = basicAggregation(spaceId)
|
|
||||||
// val match = match(Criteria.where("_id").`is`(ObjectId(id)))
|
|
||||||
// val aggregation = newAggregation(*basicAggregation.toTypedArray(), match)
|
|
||||||
// return reactiveMongoTemplate.aggregate(aggregation, "categories", Category::class.java).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// override suspend fun createCategory(
|
|
||||||
// spaceId: String,
|
|
||||||
// category: CategoryDTO.CreateCategoryDTO
|
|
||||||
// ): Category {
|
|
||||||
// val createdCategory = Category(
|
|
||||||
// spaceId = spaceId,
|
|
||||||
// type = category.type,
|
|
||||||
// name = category.name,
|
|
||||||
// icon = category.icon
|
|
||||||
// )
|
|
||||||
// return categoryRepo.save(createdCategory).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun updateCategory(
|
|
||||||
// spaceId: String,
|
|
||||||
// category: CategoryDTO.UpdateCategoryDTO
|
|
||||||
// ): Category {
|
|
||||||
// val existingCategory = getCategory(spaceId, category.id)
|
|
||||||
// val updatedCategory = existingCategory.copy(
|
|
||||||
// type = category.type,
|
|
||||||
// name = category.name,
|
|
||||||
// icon = category.icon,
|
|
||||||
// )
|
|
||||||
// return categoryRepo.save(updatedCategory).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun deleteCategory(spaceId: String, id: String) {
|
|
||||||
// val existingCategory = getCategory(spaceId, id)
|
|
||||||
// existingCategory.isDeleted = true
|
|
||||||
// categoryRepo.save(existingCategory).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun createCategoriesForSpace(spaceId: String): List<Category> {
|
|
||||||
// val etalonCategories = categoryEtalonRepo.findAll().collectList().awaitSingle()
|
|
||||||
// val toCreate = etalonCategories.map {
|
|
||||||
// Category(
|
|
||||||
// spaceId = spaceId,
|
|
||||||
// type = it.type,
|
|
||||||
// name = it.name,
|
|
||||||
// icon = it.icon
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// return categoryRepo.saveAll(toCreate).collectList().awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
//package space.luminic.finance.services
|
|
||||||
//
|
|
||||||
//import kotlinx.coroutines.reactive.awaitSingle
|
|
||||||
//import org.springframework.stereotype.Service
|
|
||||||
//import space.luminic.finance.dtos.CurrencyDTO
|
|
||||||
//import space.luminic.finance.models.Currency
|
|
||||||
//import space.luminic.finance.models.CurrencyRate
|
|
||||||
//import space.luminic.finance.repos.CurrencyRateRepo
|
|
||||||
//import space.luminic.finance.repos.CurrencyRepo
|
|
||||||
//import java.math.BigDecimal
|
|
||||||
//import java.time.LocalDate
|
|
||||||
//
|
|
||||||
//@Service
|
|
||||||
//class CurrencyServiceMongoImpl(
|
|
||||||
// private val currencyRepo: CurrencyRepo,
|
|
||||||
// private val currencyRateRepo: CurrencyRateRepo
|
|
||||||
//) : CurrencyService {
|
|
||||||
//
|
|
||||||
// override suspend fun getCurrencies(): List<Currency> {
|
|
||||||
// return currencyRepo.findAll().collectList().awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun getCurrency(currencyCode: String): Currency {
|
|
||||||
// return currencyRepo.findById(currencyCode).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun createCurrency(currency: CurrencyDTO): Currency {
|
|
||||||
// val createdCurrency = Currency(currency.code, currency.name, currency.symbol)
|
|
||||||
// return currencyRepo.save(createdCurrency).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun updateCurrency(currency: CurrencyDTO): Currency {
|
|
||||||
// val existingCurrency = currencyRepo.findById(currency.code).awaitSingle()
|
|
||||||
// val newCurrency = existingCurrency.copy(name = currency.name, symbol = currency.symbol)
|
|
||||||
// return currencyRepo.save(newCurrency).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun deleteCurrency(currencyCode: String) {
|
|
||||||
// currencyRepo.deleteById(currencyCode).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun createCurrencyRate(currencyCode: String): CurrencyRate {
|
|
||||||
// return currencyRateRepo.save(
|
|
||||||
// CurrencyRate(
|
|
||||||
// currencyCode = currencyCode,
|
|
||||||
// rate = BigDecimal(12.0),
|
|
||||||
// date = LocalDate.now(),
|
|
||||||
// )
|
|
||||||
// ).awaitSingle()
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package space.luminic.finance.services
|
|
||||||
|
|
||||||
import space.luminic.finance.dtos.GoalDTO
|
|
||||||
import space.luminic.finance.models.Goal
|
|
||||||
|
|
||||||
interface GoalService {
|
|
||||||
fun findAllBySpaceId(spaceId: Int): List<Goal>
|
|
||||||
fun findBySpaceIdAndId(spaceId: Int, id: Int): Goal
|
|
||||||
fun create(spaceId: Int,goal: GoalDTO.CreateGoalDTO): Int
|
|
||||||
fun update(spaceId: Int, goalId: Int, goal: GoalDTO.UpdateGoalDTO)
|
|
||||||
fun delete(spaceId: Int, id: Int)
|
|
||||||
|
|
||||||
fun getComponents(spaceId: Int, goalId: Int): List<Goal.GoalComponent>
|
|
||||||
fun getComponent(spaceId: Int, goalId: Int, id: Int): Goal.GoalComponent?
|
|
||||||
fun createComponent(spaceId: Int, goalId: Int, component: Goal.GoalComponent): Int
|
|
||||||
fun updateComponent(spaceId: Int, goalId: Int, component: Goal.GoalComponent)
|
|
||||||
fun deleteComponent(spaceId: Int, goalId: Int, id: Int)
|
|
||||||
|
|
||||||
fun assignTransaction(spaceId: Int, goalId: Int, transactionId: Int)
|
|
||||||
fun refuseTransaction(spaceId: Int,goalId: Int, transactionId: Int)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
package space.luminic.finance.services
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service
|
|
||||||
import space.luminic.finance.dtos.GoalDTO
|
|
||||||
import space.luminic.finance.models.Goal
|
|
||||||
import space.luminic.finance.models.NotFoundException
|
|
||||||
import space.luminic.finance.repos.GoalRepo
|
|
||||||
import space.luminic.finance.repos.SpaceRepo
|
|
||||||
import space.luminic.finance.repos.TransactionRepo
|
|
||||||
|
|
||||||
@Service
|
|
||||||
class GoalServiceImpl(
|
|
||||||
private val goalRepo: GoalRepo,
|
|
||||||
private val spaceRepo: SpaceRepo,
|
|
||||||
private val authService: AuthService,
|
|
||||||
private val transactionRepo: TransactionRepo
|
|
||||||
) : GoalService {
|
|
||||||
override fun findAllBySpaceId(spaceId: Int): List<Goal> {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
return goalRepo.findAllBySpaceId(spaceId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun findBySpaceIdAndId(spaceId: Int, id: Int): Goal {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
return goalRepo.findBySpaceIdAndId(spaceId, userId) ?: throw NotFoundException("Goal $id not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun create(spaceId: Int, goal: GoalDTO.CreateGoalDTO): Int {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
val creatingGoal = Goal(
|
|
||||||
type = goal.type,
|
|
||||||
name = goal.name,
|
|
||||||
amount = goal.amount,
|
|
||||||
untilDate = goal.date
|
|
||||||
)
|
|
||||||
return goalRepo.create(creatingGoal, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(spaceId: Int, goalId: Int, goal: GoalDTO.UpdateGoalDTO) {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
val existingGoal =
|
|
||||||
goalRepo.findBySpaceIdAndId(spaceId, goalId) ?: throw NotFoundException("Goal $goalId not found")
|
|
||||||
val updatedGoal = existingGoal.copy(
|
|
||||||
type = goal.type,
|
|
||||||
name = goal.name,
|
|
||||||
description = goal.description,
|
|
||||||
amount = goal.amount,
|
|
||||||
untilDate = goal.date
|
|
||||||
)
|
|
||||||
goalRepo.update(updatedGoal, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun delete(spaceId: Int, id: Int) {
|
|
||||||
goalRepo.delete(spaceId, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getComponents(
|
|
||||||
spaceId: Int,
|
|
||||||
goalId: Int
|
|
||||||
): List<Goal.GoalComponent> {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
goalRepo.findBySpaceIdAndId(spaceId, goalId) ?: throw NotFoundException("Goal $goalId not found")
|
|
||||||
return goalRepo.getComponents(spaceId, goalId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getComponent(
|
|
||||||
spaceId: Int,
|
|
||||||
goalId: Int,
|
|
||||||
id: Int
|
|
||||||
): Goal.GoalComponent? {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
goalRepo.findBySpaceIdAndId(spaceId, goalId) ?: throw NotFoundException("Goal $goalId not found")
|
|
||||||
return goalRepo.getComponent(spaceId, goalId, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createComponent(
|
|
||||||
spaceId: Int,
|
|
||||||
goalId: Int,
|
|
||||||
component: Goal.GoalComponent
|
|
||||||
): Int {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
goalRepo.findBySpaceIdAndId(spaceId, goalId) ?: throw NotFoundException("Goal $goalId not found")
|
|
||||||
return goalRepo.createComponent(goalId, component, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateComponent(
|
|
||||||
spaceId: Int,
|
|
||||||
goalId: Int,
|
|
||||||
component: Goal.GoalComponent
|
|
||||||
) {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
goalRepo.findBySpaceIdAndId(spaceId, goalId) ?: throw NotFoundException("Goal $goalId not found")
|
|
||||||
val existingComponent = goalRepo.getComponent(spaceId, goalId, component.id!!)
|
|
||||||
?: throw NotFoundException("Component $goalId not found")
|
|
||||||
val updatedComponent = existingComponent.copy(
|
|
||||||
name = component.name,
|
|
||||||
amount = component.amount,
|
|
||||||
isDone = component.isDone,
|
|
||||||
date = component.date
|
|
||||||
)
|
|
||||||
goalRepo.updateComponent(goalId, updatedComponent.id!!, updatedComponent, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deleteComponent(spaceId: Int, goalId: Int, id: Int) {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
goalRepo.findBySpaceIdAndId(spaceId, goalId) ?: throw NotFoundException("Goal $goalId not found")
|
|
||||||
goalRepo.getComponent(spaceId, goalId, id) ?: throw NotFoundException("Component $goalId not found")
|
|
||||||
goalRepo.deleteComponent(goalId, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun assignTransaction(spaceId: Int, goalId: Int, transactionId: Int) {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
goalRepo.findBySpaceIdAndId(spaceId, goalId) ?: throw NotFoundException("Goal $goalId not found")
|
|
||||||
transactionRepo.findBySpaceIdAndId(spaceId, transactionId) ?: throw NotFoundException(
|
|
||||||
"Transaction $transactionId not found"
|
|
||||||
)
|
|
||||||
goalRepo.assignTransaction(goalId, transactionId)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun refuseTransaction(spaceId: Int, goalId: Int, transactionId: Int) {
|
|
||||||
val userId = authService.getSecurityUserId()
|
|
||||||
spaceRepo.findSpaceById(spaceId, userId)
|
|
||||||
goalRepo.findBySpaceIdAndId(spaceId, goalId) ?: throw NotFoundException("Goal $goalId not found")
|
|
||||||
transactionRepo.findBySpaceIdAndId(spaceId, transactionId) ?: throw NotFoundException(
|
|
||||||
"Transaction $transactionId not found"
|
|
||||||
)
|
|
||||||
goalRepo.refuseTransaction(goalId, transactionId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,6 +15,7 @@ import space.luminic.finance.repos.RecurrentOperationRepo
|
|||||||
import space.luminic.finance.repos.SpaceRepo
|
import space.luminic.finance.repos.SpaceRepo
|
||||||
import space.luminic.finance.repos.TransactionRepo
|
import space.luminic.finance.repos.TransactionRepo
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class RecurrentOperationServiceImpl(
|
class RecurrentOperationServiceImpl(
|
||||||
@@ -22,7 +23,6 @@ class RecurrentOperationServiceImpl(
|
|||||||
private val spaceRepo: SpaceRepo,
|
private val spaceRepo: SpaceRepo,
|
||||||
private val recurrentOperationRepo: RecurrentOperationRepo,
|
private val recurrentOperationRepo: RecurrentOperationRepo,
|
||||||
private val categoryService: CategoryService,
|
private val categoryService: CategoryService,
|
||||||
private val transactionService: TransactionService,
|
|
||||||
private val transactionRepo: TransactionRepo
|
private val transactionRepo: TransactionRepo
|
||||||
) : RecurrentOperationService {
|
) : RecurrentOperationService {
|
||||||
private val logger = LoggerFactory.getLogger(this.javaClass)
|
private val logger = LoggerFactory.getLogger(this.javaClass)
|
||||||
@@ -61,7 +61,8 @@ class RecurrentOperationServiceImpl(
|
|||||||
val transactionsToCreate = mutableListOf<Transaction>()
|
val transactionsToCreate = mutableListOf<Transaction>()
|
||||||
serviceScope.launch {
|
serviceScope.launch {
|
||||||
runCatching {
|
runCatching {
|
||||||
val date = LocalDate.now()
|
val now = LocalDate.now()
|
||||||
|
val date = now.withDayOfMonth(min(operation.date, now.lengthOfMonth()))
|
||||||
for (i in 1..12) {
|
for (i in 1..12) {
|
||||||
transactionsToCreate.add(
|
transactionsToCreate.add(
|
||||||
Transaction(
|
Transaction(
|
||||||
@@ -99,7 +100,31 @@ class RecurrentOperationServiceImpl(
|
|||||||
date = operation.date
|
date = operation.date
|
||||||
)
|
)
|
||||||
recurrentOperationRepo.update(updatedOperation, userId)
|
recurrentOperationRepo.update(updatedOperation, userId)
|
||||||
|
serviceScope.launch {
|
||||||
|
val transactionsToUpdate = mutableListOf<Transaction>()
|
||||||
|
runCatching {
|
||||||
|
val txs = transactionRepo.findBySpaceIdAndRecurrentId(spaceId, operationId)
|
||||||
|
txs.forEach {
|
||||||
|
transactionsToUpdate.add(
|
||||||
|
it.copy(
|
||||||
|
type = if (it.category?.type == Category.CategoryType.EXPENSE) Transaction.TransactionType.EXPENSE else Transaction.TransactionType.INCOME,
|
||||||
|
category = updatedOperation.category,
|
||||||
|
comment = operation.name,
|
||||||
|
amount = updatedOperation.amount,
|
||||||
|
date = LocalDate.of(
|
||||||
|
it.date.year,
|
||||||
|
it.date.monthValue,
|
||||||
|
min(it.date.lengthOfMonth(), updatedOperation.date)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
transactionRepo.updateBatch(transactionsToUpdate, userId)
|
||||||
|
}.onFailure {
|
||||||
|
logger.error("Error creating recurring operation", it)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun delete(spaceId: Int, id: Int) {
|
override fun delete(spaceId: Int, id: Int) {
|
||||||
|
|||||||
@@ -1,145 +0,0 @@
|
|||||||
//package space.luminic.finance.services
|
|
||||||
//
|
|
||||||
//import com.mongodb.client.model.Aggregates.sort
|
|
||||||
//import kotlinx.coroutines.reactive.awaitFirst
|
|
||||||
//import kotlinx.coroutines.reactive.awaitFirstOrNull
|
|
||||||
//import kotlinx.coroutines.reactive.awaitSingle
|
|
||||||
//import org.springframework.data.domain.Sort
|
|
||||||
//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.aggregation.ConvertOperators
|
|
||||||
//import org.springframework.data.mongodb.core.aggregation.VariableOperators
|
|
||||||
//import org.springframework.data.mongodb.core.query.Criteria
|
|
||||||
//import org.springframework.stereotype.Service
|
|
||||||
//import space.luminic.finance.dtos.SpaceDTO
|
|
||||||
//import space.luminic.finance.models.NotFoundException
|
|
||||||
//import space.luminic.finance.models.Space
|
|
||||||
//import space.luminic.finance.models.User
|
|
||||||
//import space.luminic.finance.repos.SpaceRepo
|
|
||||||
//
|
|
||||||
//@Service
|
|
||||||
//class SpaceServiceMongoImpl(
|
|
||||||
// private val authService: AuthService,
|
|
||||||
// private val spaceRepo: SpaceRepo,
|
|
||||||
// private val mongoTemplate: ReactiveMongoTemplate,
|
|
||||||
//) : SpaceService {
|
|
||||||
//
|
|
||||||
// private fun basicAggregation(user: User): 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().orOperator(
|
|
||||||
// Criteria.where("ownerId").`is`(user.id),
|
|
||||||
// Criteria.where("participantsIds").`is`(user.id)
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
// matchCriteria.add(Criteria.where("isDeleted").`is`(false))
|
|
||||||
// val matchStage = match(Criteria().andOperator(*matchCriteria.toTypedArray()))
|
|
||||||
//
|
|
||||||
// return listOf(addFieldsAsOJ, lookupCreatedBy, unwindCreatedBy, lookupUpdatedBy, unwindUpdatedBy, matchStage)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private fun ownerAndParticipantsLookups(): List<AggregationOperation>{
|
|
||||||
// val addOwnerAsOJ = addFields()
|
|
||||||
// .addField("ownerIdAsObjectId")
|
|
||||||
// .withValue(ConvertOperators.valueOf("ownerId").convertToObjectId())
|
|
||||||
// .addField("participantsIdsAsObjectId")
|
|
||||||
// .withValue(
|
|
||||||
// VariableOperators.Map.itemsOf("participantsIds")
|
|
||||||
// .`as`("id")
|
|
||||||
// .andApply(
|
|
||||||
// ConvertOperators.valueOf("$\$id").convertToObjectId()
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
// .build()
|
|
||||||
// val lookupOwner = lookup("users", "ownerIdAsObjectId", "_id", "owner")
|
|
||||||
// val unwindOwner = unwind("owner")
|
|
||||||
// val lookupUsers = lookup("users", "participantsIdsAsObjectId", "_id", "participants")
|
|
||||||
// return listOf(addOwnerAsOJ, lookupOwner, unwindOwner, lookupUsers)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun checkSpace(spaceId: String): Space {
|
|
||||||
// val user = authService.getSecurityUser()
|
|
||||||
// val space = getSpace(spaceId)
|
|
||||||
//
|
|
||||||
// // Проверяем доступ пользователя к пространству
|
|
||||||
// return if (space.participants!!.none { it.id.toString() == user.id }) {
|
|
||||||
// throw IllegalArgumentException("User does not have access to this Space")
|
|
||||||
// } else space
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun getSpaces(): List<Space> {
|
|
||||||
// val user = authService.getSecurityUser()
|
|
||||||
// val basicAggregation = basicAggregation(user)
|
|
||||||
// val ownerAndParticipantsLookup = ownerAndParticipantsLookups()
|
|
||||||
//
|
|
||||||
// val sort = sort(Sort.by(Sort.Direction.DESC, "createdAt"))
|
|
||||||
// val aggregation = newAggregation(
|
|
||||||
// *basicAggregation.toTypedArray(),
|
|
||||||
// *ownerAndParticipantsLookup.toTypedArray(),
|
|
||||||
// sort,
|
|
||||||
// )
|
|
||||||
// return mongoTemplate.aggregate(aggregation, "spaces", Space::class.java).collectList().awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun getSpace(id: String): Space {
|
|
||||||
// val user = authService.getSecurityUser()
|
|
||||||
// val basicAggregation = basicAggregation(user)
|
|
||||||
// val ownerAndParticipantsLookup = ownerAndParticipantsLookups()
|
|
||||||
//
|
|
||||||
// val aggregation = newAggregation(
|
|
||||||
// *basicAggregation.toTypedArray(),
|
|
||||||
// *ownerAndParticipantsLookup.toTypedArray(),
|
|
||||||
// )
|
|
||||||
// return mongoTemplate.aggregate(aggregation, "spaces", Space::class.java).awaitFirstOrNull()
|
|
||||||
// ?: throw NotFoundException("Space not found")
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun createSpace(space: SpaceDTO.CreateSpaceDTO): Space {
|
|
||||||
// val owner = authService.getSecurityUser()
|
|
||||||
// val createdSpace = Space(
|
|
||||||
// name = space.name,
|
|
||||||
// ownerId = owner.id!!,
|
|
||||||
//
|
|
||||||
// participantsIds = listOf(owner.id!!),
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// )
|
|
||||||
// createdSpace.owner = owner
|
|
||||||
// createdSpace.participants?.toMutableList()?.add(owner)
|
|
||||||
// val savedSpace = spaceRepo.save(createdSpace).awaitSingle()
|
|
||||||
// return savedSpace
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun updateSpace(spaceId: String, space: SpaceDTO.UpdateSpaceDTO): Space {
|
|
||||||
// val existingSpace = spaceRepo.findById(spaceId).awaitFirstOrNull() ?: throw NotFoundException("Space not found")
|
|
||||||
// val updatedSpace = existingSpace.copy(
|
|
||||||
// name = space.name,
|
|
||||||
// )
|
|
||||||
// updatedSpace.owner = existingSpace.owner
|
|
||||||
// updatedSpace.participants = existingSpace.participants
|
|
||||||
// return spaceRepo.save(updatedSpace).awaitFirst()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun deleteSpace(spaceId: String) {
|
|
||||||
// val space = spaceRepo.findById(spaceId).awaitFirstOrNull() ?: throw NotFoundException("Space not found")
|
|
||||||
// space.isDeleted = true
|
|
||||||
// spaceRepo.save(space).awaitFirst()
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package space.luminic.finance.services
|
||||||
|
|
||||||
|
import space.luminic.finance.dtos.TargetDTO
|
||||||
|
import space.luminic.finance.models.Target
|
||||||
|
|
||||||
|
interface TargetService {
|
||||||
|
fun findAllBySpaceId(spaceId: Int): List<Target>
|
||||||
|
fun findBySpaceIdAndId(spaceId: Int, id: Int): Target
|
||||||
|
fun create(spaceId: Int,target: TargetDTO.CreateTargetDTO): Int
|
||||||
|
fun update(spaceId: Int, targetId: Int, target: TargetDTO.UpdateTargetDTO)
|
||||||
|
fun delete(spaceId: Int, id: Int)
|
||||||
|
|
||||||
|
fun getComponents(spaceId: Int, targetId: Int): List<Target.TargetComponent>
|
||||||
|
fun getComponent(spaceId: Int, targetId: Int, id: Int): Target.TargetComponent?
|
||||||
|
fun createComponent(spaceId: Int, targetId: Int, component: Target.TargetComponent): Int
|
||||||
|
fun updateComponent(spaceId: Int, targetId: Int, component: Target.TargetComponent)
|
||||||
|
fun deleteComponent(spaceId: Int, targetId: Int, id: Int)
|
||||||
|
|
||||||
|
fun assignTransaction(spaceId: Int, targetId: Int, transactionId: Int)
|
||||||
|
fun refuseTransaction(spaceId: Int,targetId: Int, transactionId: Int)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
package space.luminic.finance.services
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
import space.luminic.finance.dtos.TargetDTO
|
||||||
|
import space.luminic.finance.models.Target
|
||||||
|
import space.luminic.finance.models.NotFoundException
|
||||||
|
import space.luminic.finance.repos.TargetRepo
|
||||||
|
import space.luminic.finance.repos.SpaceRepo
|
||||||
|
import space.luminic.finance.repos.TransactionRepo
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class TargetServiceImpl(
|
||||||
|
private val targetRepo: TargetRepo,
|
||||||
|
private val spaceRepo: SpaceRepo,
|
||||||
|
private val authService: AuthService,
|
||||||
|
private val transactionRepo: TransactionRepo
|
||||||
|
) : TargetService {
|
||||||
|
override fun findAllBySpaceId(spaceId: Int): List<Target> {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
return targetRepo.findAllBySpaceId(spaceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findBySpaceIdAndId(spaceId: Int, id: Int): Target {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
return targetRepo.findBySpaceIdAndId(spaceId, userId) ?: throw NotFoundException("Goal $id not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun create(spaceId: Int, target: TargetDTO.CreateTargetDTO): Int {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
val creatingTarget = Target(
|
||||||
|
type = target.type,
|
||||||
|
name = target.name,
|
||||||
|
amount = target.amount,
|
||||||
|
untilDate = target.date
|
||||||
|
)
|
||||||
|
return targetRepo.create(creatingTarget, userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(spaceId: Int, targetId: Int, target: TargetDTO.UpdateTargetDTO) {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
val existingGoal =
|
||||||
|
targetRepo.findBySpaceIdAndId(spaceId, targetId) ?: throw NotFoundException("Goal $targetId not found")
|
||||||
|
val updatedGoal = existingGoal.copy(
|
||||||
|
type = target.type,
|
||||||
|
name = target.name,
|
||||||
|
description = target.description,
|
||||||
|
amount = target.amount,
|
||||||
|
untilDate = target.date
|
||||||
|
)
|
||||||
|
targetRepo.update(updatedGoal, userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete(spaceId: Int, id: Int) {
|
||||||
|
targetRepo.delete(spaceId, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getComponents(
|
||||||
|
spaceId: Int,
|
||||||
|
targetId: Int
|
||||||
|
): List<Target.TargetComponent> {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
targetRepo.findBySpaceIdAndId(spaceId, targetId) ?: throw NotFoundException("Goal $targetId not found")
|
||||||
|
return targetRepo.getComponents(spaceId, targetId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getComponent(
|
||||||
|
spaceId: Int,
|
||||||
|
targetId: Int,
|
||||||
|
id: Int
|
||||||
|
): Target.TargetComponent? {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
targetRepo.findBySpaceIdAndId(spaceId, targetId) ?: throw NotFoundException("Target $targetId not found")
|
||||||
|
return targetRepo.getComponent(spaceId, targetId, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createComponent(
|
||||||
|
spaceId: Int,
|
||||||
|
targetId: Int,
|
||||||
|
component: Target.TargetComponent
|
||||||
|
): Int {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
targetRepo.findBySpaceIdAndId(spaceId, targetId) ?: throw NotFoundException("Target $targetId not found")
|
||||||
|
return targetRepo.createComponent(targetId, component, userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateComponent(
|
||||||
|
spaceId: Int,
|
||||||
|
targetId: Int,
|
||||||
|
component: Target.TargetComponent
|
||||||
|
) {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
targetRepo.findBySpaceIdAndId(spaceId, targetId) ?: throw NotFoundException("Target $targetId not found")
|
||||||
|
val existingComponent = targetRepo.getComponent(spaceId, targetId, component.id!!)
|
||||||
|
?: throw NotFoundException("Component $targetId not found")
|
||||||
|
val updatedComponent = existingComponent.copy(
|
||||||
|
name = component.name,
|
||||||
|
amount = component.amount,
|
||||||
|
isDone = component.isDone,
|
||||||
|
date = component.date
|
||||||
|
)
|
||||||
|
targetRepo.updateComponent(targetId, updatedComponent.id!!, updatedComponent, userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deleteComponent(spaceId: Int, targetId: Int, id: Int) {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
targetRepo.findBySpaceIdAndId(spaceId, targetId) ?: throw NotFoundException("Target $targetId not found")
|
||||||
|
targetRepo.getComponent(spaceId, targetId, id) ?: throw NotFoundException("Component $targetId not found")
|
||||||
|
targetRepo.deleteComponent(targetId, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun assignTransaction(spaceId: Int, targetId: Int, transactionId: Int) {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
targetRepo.findBySpaceIdAndId(spaceId, targetId) ?: throw NotFoundException("Target $targetId not found")
|
||||||
|
transactionRepo.findBySpaceIdAndId(spaceId, transactionId) ?: throw NotFoundException(
|
||||||
|
"Transaction $transactionId not found"
|
||||||
|
)
|
||||||
|
targetRepo.assignTransaction(targetId, transactionId)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refuseTransaction(spaceId: Int, targetId: Int, transactionId: Int) {
|
||||||
|
val userId = authService.getSecurityUserId()
|
||||||
|
spaceRepo.findSpaceById(spaceId, userId)
|
||||||
|
targetRepo.findBySpaceIdAndId(spaceId, targetId) ?: throw NotFoundException("Target $targetId not found")
|
||||||
|
transactionRepo.findBySpaceIdAndId(spaceId, transactionId) ?: throw NotFoundException(
|
||||||
|
"Transaction $transactionId not found"
|
||||||
|
)
|
||||||
|
targetRepo.refuseTransaction(targetId, transactionId)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,8 +7,13 @@ import java.time.LocalDate
|
|||||||
interface TransactionService {
|
interface TransactionService {
|
||||||
|
|
||||||
data class TransactionsFilter(
|
data class TransactionsFilter(
|
||||||
|
val type: Transaction.TransactionType? = null,
|
||||||
|
val kind: Transaction.TransactionKind? = null,
|
||||||
val dateFrom: LocalDate? = null,
|
val dateFrom: LocalDate? = null,
|
||||||
val dateTo: LocalDate? = null,
|
val dateTo: LocalDate? = null,
|
||||||
|
val isDone: Boolean? = null,
|
||||||
|
val offset: Int = 0,
|
||||||
|
val limit: Int = 10,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getTransactions(
|
fun getTransactions(
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class TransactionServiceImpl(
|
|||||||
sortBy: String,
|
sortBy: String,
|
||||||
sortDirection: String
|
sortDirection: String
|
||||||
): List<Transaction> {
|
): List<Transaction> {
|
||||||
val transactions = transactionRepo.findAllBySpaceId(spaceId)
|
val transactions = transactionRepo.findAllBySpaceId(spaceId, filter)
|
||||||
return transactions
|
return transactions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,9 +106,10 @@ class TransactionServiceImpl(
|
|||||||
tgChatId = existingTransaction.tgChatId,
|
tgChatId = existingTransaction.tgChatId,
|
||||||
tgMessageId = existingTransaction.tgMessageId,
|
tgMessageId = existingTransaction.tgMessageId,
|
||||||
)
|
)
|
||||||
if (existingTransaction.category == null && updatedTransaction.category != null) {
|
if ((existingTransaction.category == null && updatedTransaction.category != null) || (existingTransaction.category?.id != updatedTransaction.category?.id)) {
|
||||||
categorizeService.notifyThatCategorySelected(updatedTransaction)
|
categorizeService.notifyThatCategorySelected(updatedTransaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
return transactionRepo.update(updatedTransaction)
|
return transactionRepo.update(updatedTransaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,185 +0,0 @@
|
|||||||
//package space.luminic.finance.services
|
|
||||||
//
|
|
||||||
//import kotlinx.coroutines.reactive.awaitFirstOrNull
|
|
||||||
//import kotlinx.coroutines.reactive.awaitSingle
|
|
||||||
//import org.bson.types.ObjectId
|
|
||||||
//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.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.sort
|
|
||||||
//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.query.Criteria
|
|
||||||
//import org.springframework.stereotype.Service
|
|
||||||
//import space.luminic.finance.dtos.TransactionDTO
|
|
||||||
//import space.luminic.finance.models.NotFoundException
|
|
||||||
//import space.luminic.finance.models.Transaction
|
|
||||||
//import space.luminic.finance.repos.TransactionRepo
|
|
||||||
//
|
|
||||||
//@Service
|
|
||||||
//class TransactionServiceMongoImpl(
|
|
||||||
// private val mongoTemplate: ReactiveMongoTemplate,
|
|
||||||
// private val transactionRepo: TransactionRepo,
|
|
||||||
// private val categoryService: CategoryService,
|
|
||||||
//) : TransactionService {
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// private fun basicAggregation(spaceId: String): List<AggregationOperation> {
|
|
||||||
// val addFieldsOI = addFields()
|
|
||||||
// .addField("createdByOI")
|
|
||||||
// .withValue(ConvertOperators.valueOf("createdById").convertToObjectId())
|
|
||||||
// .addField("updatedByOI")
|
|
||||||
// .withValue(ConvertOperators.valueOf("updatedById").convertToObjectId())
|
|
||||||
// .addField("fromAccountIdOI")
|
|
||||||
// .withValue(ConvertOperators.valueOf("fromAccountId").convertToObjectId())
|
|
||||||
// .addField("toAccountIdOI")
|
|
||||||
// .withValue(ConvertOperators.valueOf("toAccountId").convertToObjectId())
|
|
||||||
// .addField("categoryIdOI")
|
|
||||||
// .withValue(ConvertOperators.valueOf("categoryId").convertToObjectId())
|
|
||||||
// .build()
|
|
||||||
//
|
|
||||||
// val lookupFromAccount = lookup("accounts", "fromAccountIdOI", "_id", "fromAccount")
|
|
||||||
// val unwindFromAccount = unwind("fromAccount")
|
|
||||||
// val lookupToAccount = lookup("accounts", "toAccountIdOI", "_id", "toAccount")
|
|
||||||
// val unwindToAccount = unwind("toAccount", true)
|
|
||||||
//
|
|
||||||
// val lookupCategory = lookup("categories", "categoryIdOI", "_id", "category")
|
|
||||||
// val unwindCategory = unwind("category")
|
|
||||||
//
|
|
||||||
// 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))
|
|
||||||
// val matchStage = match(Criteria().andOperator(*matchCriteria.toTypedArray()))
|
|
||||||
//
|
|
||||||
// return listOf(
|
|
||||||
// matchStage,
|
|
||||||
// addFieldsOI,
|
|
||||||
// lookupFromAccount,
|
|
||||||
// unwindFromAccount,
|
|
||||||
// lookupToAccount,
|
|
||||||
// unwindToAccount,
|
|
||||||
// lookupCategory,
|
|
||||||
// unwindCategory,
|
|
||||||
// lookupCreatedBy,
|
|
||||||
// unwindCreatedBy,
|
|
||||||
// lookupUpdatedBy,
|
|
||||||
// unwindUpdatedBy
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun getTransactions(
|
|
||||||
// spaceId: String,
|
|
||||||
// filter: TransactionService.TransactionsFilter,
|
|
||||||
// sortBy: String,
|
|
||||||
// sortDirection: String
|
|
||||||
// ): List<Transaction> {
|
|
||||||
// val allowedSortFields = setOf("date", "amount", "category.name", "createdAt")
|
|
||||||
// require(sortBy in allowedSortFields) { "Invalid sort field: $sortBy" }
|
|
||||||
//
|
|
||||||
// val direction = when (sortDirection.uppercase()) {
|
|
||||||
// "ASC" -> Direction.ASC
|
|
||||||
// "DESC" -> Direction.DESC
|
|
||||||
// else -> throw IllegalArgumentException("Sort direction must be 'ASC' or 'DESC'")
|
|
||||||
// }
|
|
||||||
// val basicAggregation = basicAggregation(spaceId)
|
|
||||||
//
|
|
||||||
// val sort = sort(Sort.by(direction, sortBy))
|
|
||||||
// val matchCriteria = mutableListOf<Criteria>()
|
|
||||||
// filter.dateFrom?.let { matchCriteria.add(Criteria.where("date").gte(it)) }
|
|
||||||
// filter.dateTo?.let { matchCriteria.add(Criteria.where("date").lte(it)) }
|
|
||||||
// val matchStage = match(Criteria().andOperator(*matchCriteria.toTypedArray()))
|
|
||||||
// val aggregation =
|
|
||||||
// newAggregation(
|
|
||||||
// matchStage,
|
|
||||||
// *basicAggregation.toTypedArray(),
|
|
||||||
// sort
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// return mongoTemplate.aggregate(aggregation, "transactions", Transaction::class.java)
|
|
||||||
// .collectList()
|
|
||||||
// .awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun getTransaction(
|
|
||||||
// spaceId: String,
|
|
||||||
// transactionId: String
|
|
||||||
// ): Transaction {
|
|
||||||
// val matchCriteria = mutableListOf<Criteria>()
|
|
||||||
// matchCriteria.add(Criteria.where("spaceId").`is`(spaceId))
|
|
||||||
// matchCriteria.add(Criteria.where("_id").`is`(ObjectId(transactionId)))
|
|
||||||
// val matchStage = match(Criteria().andOperator(*matchCriteria.toTypedArray()))
|
|
||||||
//
|
|
||||||
// val aggregation =
|
|
||||||
// newAggregation(
|
|
||||||
// matchStage,
|
|
||||||
// )
|
|
||||||
// return mongoTemplate.aggregate(aggregation, "transactions", Transaction::class.java)
|
|
||||||
// .awaitFirstOrNull() ?: throw NotFoundException("Transaction with ID $transactionId not found")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun createTransaction(
|
|
||||||
// spaceId: String,
|
|
||||||
// transaction: TransactionDTO.CreateTransactionDTO
|
|
||||||
// ): Transaction {
|
|
||||||
// if (transaction.type == Transaction.TransactionType.TRANSFER && transaction.toAccountId == null) {
|
|
||||||
// throw IllegalArgumentException("Cannot create a transaction with type TRANSFER without a toAccountId")
|
|
||||||
// }
|
|
||||||
// val category = categoryService.getCategory(spaceId, transaction.categoryId)
|
|
||||||
// if (transaction.type != Transaction.TransactionType.TRANSFER && transaction.type.name != category.type.name) {
|
|
||||||
// throw IllegalArgumentException("Transaction type should match with category type")
|
|
||||||
// }
|
|
||||||
// val transaction = Transaction(
|
|
||||||
// spaceId = spaceId,
|
|
||||||
// type = transaction.type,
|
|
||||||
// kind = transaction.kind,
|
|
||||||
// categoryId = transaction.categoryId,
|
|
||||||
// comment = transaction.comment,
|
|
||||||
// amount = transaction.amount,
|
|
||||||
// fees = transaction.fees,
|
|
||||||
// date = transaction.date,
|
|
||||||
// fromAccountId = transaction.fromAccountId,
|
|
||||||
// toAccountId = transaction.toAccountId,
|
|
||||||
// )
|
|
||||||
// return transactionRepo.save(transaction).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun updateTransaction(
|
|
||||||
// spaceId: String,
|
|
||||||
// transaction: TransactionDTO.UpdateTransactionDTO
|
|
||||||
// ): Transaction {
|
|
||||||
// if (transaction.type == Transaction.TransactionType.TRANSFER && transaction.toAccountId == null) {
|
|
||||||
// throw IllegalArgumentException("Cannot edit a transaction with type TRANSFER without a toAccountId")
|
|
||||||
// }
|
|
||||||
// val exitingTx = getTransaction(spaceId, transaction.id)
|
|
||||||
// val transaction = exitingTx.copy(
|
|
||||||
// spaceId = exitingTx.spaceId,
|
|
||||||
// type = transaction.type,
|
|
||||||
// kind = transaction.kind,
|
|
||||||
// categoryId = transaction.category,
|
|
||||||
// comment = transaction.comment,
|
|
||||||
// amount = transaction.amount,
|
|
||||||
// fees = transaction.fees,
|
|
||||||
// date = transaction.date,
|
|
||||||
// fromAccountId = transaction.fromAccountId,
|
|
||||||
// toAccountId = transaction.toAccountId,
|
|
||||||
// )
|
|
||||||
// return transactionRepo.save(transaction).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override suspend fun deleteTransaction(spaceId: String, transactionId: String) {
|
|
||||||
// val transaction = getTransaction(spaceId, transactionId)
|
|
||||||
// transaction.isDeleted = true
|
|
||||||
// transactionRepo.save(transaction).awaitSingle()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
@@ -4,7 +4,6 @@ import com.github.kotlintelegrambot.Bot
|
|||||||
import com.github.kotlintelegrambot.entities.ChatId
|
import com.github.kotlintelegrambot.entities.ChatId
|
||||||
import com.github.kotlintelegrambot.entities.InlineKeyboardMarkup
|
import com.github.kotlintelegrambot.entities.InlineKeyboardMarkup
|
||||||
import com.github.kotlintelegrambot.entities.Message
|
import com.github.kotlintelegrambot.entities.Message
|
||||||
import com.github.kotlintelegrambot.entities.MessageId
|
|
||||||
import com.github.kotlintelegrambot.entities.ParseMode
|
import com.github.kotlintelegrambot.entities.ParseMode
|
||||||
import com.github.kotlintelegrambot.entities.keyboard.InlineKeyboardButton
|
import com.github.kotlintelegrambot.entities.keyboard.InlineKeyboardButton
|
||||||
import com.github.kotlintelegrambot.entities.keyboard.WebAppInfo
|
import com.github.kotlintelegrambot.entities.keyboard.WebAppInfo
|
||||||
@@ -12,10 +11,7 @@ import com.github.kotlintelegrambot.entities.reaction.ReactionType
|
|||||||
import com.github.kotlintelegrambot.types.TelegramBotResult
|
import com.github.kotlintelegrambot.types.TelegramBotResult
|
||||||
import org.springframework.beans.factory.annotation.Qualifier
|
import org.springframework.beans.factory.annotation.Qualifier
|
||||||
import org.springframework.beans.factory.annotation.Value
|
import org.springframework.beans.factory.annotation.Value
|
||||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
|
|
||||||
import org.springframework.stereotype.Repository
|
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import org.springframework.transaction.annotation.Transactional
|
|
||||||
import space.luminic.finance.models.Transaction
|
import space.luminic.finance.models.Transaction
|
||||||
import space.luminic.finance.repos.CategoryRepo
|
import space.luminic.finance.repos.CategoryRepo
|
||||||
import space.luminic.finance.repos.TransactionRepo
|
import space.luminic.finance.repos.TransactionRepo
|
||||||
@@ -46,7 +42,7 @@ class CategorizeService(
|
|||||||
tx,
|
tx,
|
||||||
categoriesRepo.findBySpaceId(job.spaceId)
|
categoriesRepo.findBySpaceId(job.spaceId)
|
||||||
) // тут твой вызов GPT
|
) // тут твой вызов GPT
|
||||||
var unsuccessMessage: TelegramBotResult<Message>? = null
|
var message: TelegramBotResult<Message>? = null
|
||||||
|
|
||||||
if (res.categoryId == 0) {
|
if (res.categoryId == 0) {
|
||||||
if (tx.tgChatId != null && tx.tgMessageId != null) {
|
if (tx.tgChatId != null && tx.tgMessageId != null) {
|
||||||
@@ -56,7 +52,7 @@ class CategorizeService(
|
|||||||
listOf(ReactionType.Emoji("💔")),
|
listOf(ReactionType.Emoji("💔")),
|
||||||
isBig = false
|
isBig = false
|
||||||
)
|
)
|
||||||
unsuccessMessage = bot.sendMessage(
|
message = bot.sendMessage(
|
||||||
ChatId.fromId(tx.tgChatId),
|
ChatId.fromId(tx.tgChatId),
|
||||||
replyToMessageId = tx.tgMessageId,
|
replyToMessageId = tx.tgMessageId,
|
||||||
text = "К сожалению, мы не смогли распознать категорию.\n\nПопробуйте выставить ее самостоятельно.",
|
text = "К сожалению, мы не смогли распознать категорию.\n\nПопробуйте выставить ее самостоятельно.",
|
||||||
@@ -64,7 +60,7 @@ class CategorizeService(
|
|||||||
listOf(
|
listOf(
|
||||||
InlineKeyboardButton.WebApp(
|
InlineKeyboardButton.WebApp(
|
||||||
"Открыть в WebApp",
|
"Открыть в WebApp",
|
||||||
WebAppInfo("https://app.luminic.space/transactions/${tx.id}/edit")
|
WebAppInfo("https://app.luminic.space/transactions/${tx.id}/edit?mode=from_bot")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -81,7 +77,7 @@ class CategorizeService(
|
|||||||
)
|
)
|
||||||
val category = categoriesRepo.findBySpaceIdAndId(job.spaceId, res.categoryId)
|
val category = categoriesRepo.findBySpaceIdAndId(job.spaceId, res.categoryId)
|
||||||
if (category != null) {
|
if (category != null) {
|
||||||
bot.sendMessage(
|
message = bot.sendMessage(
|
||||||
ChatId.fromId(tx.tgChatId),
|
ChatId.fromId(tx.tgChatId),
|
||||||
replyToMessageId = tx.tgMessageId,
|
replyToMessageId = tx.tgMessageId,
|
||||||
text = "Определили категорию: <b>${category.name}</b>.\n\nЕсли это не так, исправьте это в WebApp.",
|
text = "Определили категорию: <b>${category.name}</b>.\n\nЕсли это не так, исправьте это в WebApp.",
|
||||||
@@ -89,7 +85,7 @@ class CategorizeService(
|
|||||||
listOf(
|
listOf(
|
||||||
InlineKeyboardButton.WebApp(
|
InlineKeyboardButton.WebApp(
|
||||||
"Открыть в WebApp",
|
"Открыть в WebApp",
|
||||||
WebAppInfo("https://app.luminic.space/transactions/${tx.id}/edit")
|
WebAppInfo("https://app.luminic.space/transactions/${tx.id}/edit?mode=from_bot")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -98,11 +94,11 @@ class CategorizeService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unsuccessMessage != null) {
|
if (message != null) {
|
||||||
categoryJobRepo.successJob(
|
categoryJobRepo.successJob(
|
||||||
job.id,
|
job.id,
|
||||||
unsuccessMessage.get().chat.id,
|
message.get().chat.id,
|
||||||
unsuccessMessage.get().messageId
|
message.get().messageId
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
categoryJobRepo.successJob(job.id)
|
categoryJobRepo.successJob(job.id)
|
||||||
@@ -135,7 +131,7 @@ class CategorizeService(
|
|||||||
listOf(
|
listOf(
|
||||||
InlineKeyboardButton.WebApp(
|
InlineKeyboardButton.WebApp(
|
||||||
"Открыть в WebApp",
|
"Открыть в WebApp",
|
||||||
WebAppInfo("https://app.luminic.space/transactions/${tx.id}/edit")
|
WebAppInfo("https://app.luminic.space/transactions/${tx.id}/edit?mode=from_bot")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ class DeepSeekCategorizationService(
|
|||||||
|
|
||||||
Задача:
|
Задача:
|
||||||
1. Определите наиболее подходящую категорию из списка выше для транзакции пользователя.
|
1. Определите наиболее подходящую категорию из списка выше для транзакции пользователя.
|
||||||
2. Верните ответ в формате: "ID категории", например "3".
|
2. Верните ответ в формате: ID категории", например 3.
|
||||||
3. Если ни одна категория из списка не подходит, верните: "0".
|
3. Если ни одна категория из списка не подходит, верните: 0.
|
||||||
|
|
||||||
Ответ должен быть кратким, одной строкой, без дополнительных пояснений.
|
Ответ должен быть кратким, одной строкой, без дополнительных пояснений.
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ class TransactionsServiceImpl(
|
|||||||
tgChatId = chatId,
|
tgChatId = chatId,
|
||||||
tgMessageId = messageId,
|
tgMessageId = messageId,
|
||||||
)
|
)
|
||||||
print(transaction)
|
|
||||||
return transactionRepo.create(transaction, userId)
|
return transactionRepo.create(transaction, userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
59
src/main/resources/db/migration/V31__.sql
Normal file
59
src/main/resources/db/migration/V31__.sql
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
DROP table if exists finance.goals cascade;
|
||||||
|
DROP table if exists finance.goals_components cascade;
|
||||||
|
DROP table if exists finance.goals_transactions cascade;
|
||||||
|
|
||||||
|
DROP table if exists finance.targets cascade;
|
||||||
|
DROP table if exists finance.targets_components cascade;
|
||||||
|
DROP table if exists finance.targets_transactions cascade;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE finance.targets
|
||||||
|
(
|
||||||
|
id integer generated by default as identity not null,
|
||||||
|
space_id INTEGER,
|
||||||
|
type SMALLINT,
|
||||||
|
name VARCHAR(255),
|
||||||
|
description VARCHAR(255),
|
||||||
|
amount DECIMAL,
|
||||||
|
until_date date,
|
||||||
|
created_by_id INTEGER,
|
||||||
|
created_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
updated_by_id INTEGER,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE,
|
||||||
|
CONSTRAINT pk_targets PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE finance.targets
|
||||||
|
ADD CONSTRAINT FK_TARGETS_ON_CREATEDBY FOREIGN KEY (created_by_id) REFERENCES finance.users (id);
|
||||||
|
|
||||||
|
ALTER TABLE finance.targets
|
||||||
|
ADD CONSTRAINT FK_TARGETS_ON_SPACE FOREIGN KEY (space_id) REFERENCES finance.spaces (id);
|
||||||
|
|
||||||
|
ALTER TABLE finance.targets
|
||||||
|
ADD CONSTRAINT FK_TARGETS_ON_UPDATEDBY FOREIGN KEY (updated_by_id) REFERENCES finance.users (id);
|
||||||
|
|
||||||
|
CREATE TABLE finance.targets_transactions
|
||||||
|
(
|
||||||
|
target_id INTEGER NOT NULL,
|
||||||
|
transactions_id INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
ALTER TABLE finance.targets_transactions
|
||||||
|
ADD CONSTRAINT fk_targettx_on_target FOREIGN KEY (target_id) REFERENCES finance.targets (id);
|
||||||
|
|
||||||
|
ALTER TABLE finance.targets_transactions
|
||||||
|
ADD CONSTRAINT fk_targettx_on_tx FOREIGN KEY (transactions_id) REFERENCES finance.transactions (id);
|
||||||
|
|
||||||
|
create table if not exists finance.targets_components
|
||||||
|
(
|
||||||
|
id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL,
|
||||||
|
target_id INTEGER NOT NULL,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
amount NUMERIC NOT NULL,
|
||||||
|
is_done BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
date TIMESTAMP WITH TIME ZONE NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
alter table finance.targets_components
|
||||||
|
add constraint fk_target_on_components foreign key (target_id) references finance.targets (id);
|
||||||
|
|
||||||
Reference in New Issue
Block a user