package space.luminic.finance.repos import org.springframework.jdbc.core.RowMapper import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate import org.springframework.stereotype.Repository import space.luminic.finance.models.Goal import space.luminic.finance.models.User @Repository class GoalRepoImpl( private val jdbcTemplate: NamedParameterJdbcTemplate ) : GoalRepo { private val goalRowMapper = RowMapper { rs, _ -> Goal( id = rs.getInt("g_id"), type = Goal.GoalType.valueOf(rs.getString("g_type")), name = rs.getString("g_name"), description = rs.getString("g_description"), amount = rs.getBigDecimal("g_amount"), components = listOf(), transactions = listOf(), untilDate = rs.getDate("g_until_date").toLocalDate(), createdBy = User( id = rs.getInt("created_by_id"), username = rs.getString("created_by_username"), firstName = rs.getString("created_by_first_name"), ), createdAt = rs.getTimestamp("g_created_at").toInstant() ) } private val componentRowMapper = RowMapper { rs, _ -> Goal.GoalComponent( id = rs.getInt("gc_id"), name = rs.getString("gc_name"), amount = rs.getBigDecimal("gc_amount"), isDone = rs.getBoolean("gc_is_done"), date = rs.getDate("gc_date").toLocalDate() ) } override fun findAllBySpaceId(spaceId: Int): List { val sql = """ select g.id as g_id, g.type as g_type, g.name as g_name, g.description as g_description, g.amount as g_amount, created_by.id as created_by_id, created_by.username as created_by_username, created_by.first_name as created_by_first_name, g.created_at as g_created_at from finance.goals g join finance.users created_by on g.created_by_id = created_by.id where g.space_id = :spaceId """.trimIndent() val params = mapOf( "space_id" to spaceId, ) return jdbcTemplate.query(sql, params, goalRowMapper) } override fun findBySpaceIdAndId(spaceId: Int, id: Int): Goal? { val sql = """ select g.id as g_id, g.type as g_type, g.name as g_name, g.description as g_description, g.amount as g_amount, created_by.id as created_by_id, created_by.username as created_by_username, created_by.first_name as created_by_first_name, g.created_at as g_created_at from finance.goals g join finance.users created_by on g.created_by_id = created_by.id where g.space_id = :spaceId and g.id = :id """.trimIndent() val params = mapOf( "space_id" to spaceId, "id" to id, ) return jdbcTemplate.query(sql, params, goalRowMapper).firstOrNull() } override fun create(goal: Goal, createdById: Int): Int { val sql = """ insert into finance.goals( type, name, description, amount, until_date, created_by_id ) values ( :type, :name, :description, :amount, :until_date, :created_by_id ) returning id """.trimIndent() val params = mapOf( "type" to goal.type, "name" to goal.name, "description" to goal.description, "amount" to goal.amount, "until_date" to goal.untilDate, "created_by_id" to createdById ) return jdbcTemplate.queryForObject(sql, params, Int::class.java)!! } override fun update(goal: Goal, updatedById: Int) { val sql = """ update finance.goals set type = :type, name = :name, description = :description, amount = :amount, until_date = :until_date, updated_by_id = :updated_by_id, updated_at = now() where id = :id """.trimIndent() val params = mapOf( "id" to goal.id, "type" to goal.type.name, "name" to goal.name, "description" to goal.description, "amount" to goal.amount, "until_date" to goal.untilDate, "updated_by_id" to updatedById ) jdbcTemplate.update(sql, params) } override fun delete(spaceId: Int, id: Int) { val sql = """ delete from finance.goals where id = :id """.trimIndent() val params = mapOf( "id" to id ) jdbcTemplate.update(sql, params) } override fun getComponents( spaceId: Int, goalId: Int ): List { val sql = """ select gc.id as gc_id, gc.name as gc_name, gc.amount as gc_amount, gc.is_done as gc_is_done, gc.date as gc_date from finance.goals_components gc where gc.goal_id = :goal_id """.trimIndent() val params = mapOf( "goal_id" to goalId ) return jdbcTemplate.query(sql, params, componentRowMapper) } override fun getComponent( spaceId: Int, goalId: Int, id: Int ): Goal.GoalComponent? { val sql = """ select gc.id as gc_id, gc.name as gc_name, gc.amount as gc_amount, gc.is_done as gc_is_done, gc.date as gc_date from finance.goals_components gc where gc.goal_id = :goal_id and gc.id = :id """.trimIndent() val params = mapOf( "goal_id" to goalId, "id" to id ) return jdbcTemplate.query(sql, params, componentRowMapper).firstOrNull() } override fun createComponent(goalId: Int, component: Goal.GoalComponent, createdById: Int): Int { val sql = """ insert into finance.goals_components( goal_id, name, amount, is_done, date, created_by_id ) values ( :goal_id, :name, :amount, :is_done, :date, :created_by_id) returning id """.trimIndent() val params = mapOf( "goal_id" to goalId, "name" to component.name, "amount" to component.amount, "is_done" to component.isDone, "date" to component.date, "created_by_id" to createdById ) return jdbcTemplate.queryForObject(sql, params, Int::class.java)!! } override fun updateComponent(goalId: Int, componentId: Int, component: Goal.GoalComponent, updatedById: Int) { val sql = """ update finance.goals_components set name = :name, amount = :amount, is_done = :is_done, updated_by_id = :updated_by_id where goal_id = :goalId and id = :componentId """.trimIndent() val params = mapOf( "goalId" to goalId, "componentId" to componentId, "name" to component.name, "amount" to component.amount, "is_done" to component.isDone, "date" to component.date, "updated_by_id" to updatedById ) jdbcTemplate.update(sql, params) } override fun deleteComponent(goalId: Int, componentId: Int) { val sql = """ delete from finance.goals_components where goal_id = :goalId and id = :componentId """.trimIndent() val params = mapOf( "goalId" to goalId, "componentId" to componentId ) jdbcTemplate.update(sql, params) } override fun assignTransaction(goalId: Int, transactionId: Int) { val sql = """ insert into finance.goals_transactions(goal_id, transactions_id) values (:goal_id, :transaction_id) """.trimIndent() val params = mapOf( "goal_id" to goalId, "transaction_id" to transactionId ) jdbcTemplate.update(sql, params) } override fun refuseTransaction(goalId: Int, transactionId: Int) { val sql = """ delete from finance.goals_transactions where goal_id = :goalId and transactions_id = :transactionId """.trimIndent() val params = mapOf( "goal_id" to goalId, "transaction_id" to transactionId ) jdbcTemplate.update(sql, params) } }