+ google drive
This commit is contained in:
@@ -16,4 +16,6 @@ interface TransactionRepo {
|
||||
|
||||
fun setCategory(txId:Int, categoryId: Int)
|
||||
|
||||
fun findByDateAndKind(date: java.time.LocalDate, kind: Transaction.TransactionKind): List<Transaction>
|
||||
|
||||
}
|
||||
@@ -30,6 +30,7 @@ class TransactionRepoImpl(
|
||||
) else null
|
||||
Transaction(
|
||||
id = rs.getInt("t_id"),
|
||||
space = Space(id = rs.getInt("t_space_id"), name = "", owner = User(0, "", "")),
|
||||
parent = parent,
|
||||
type = Transaction.TransactionType.valueOf(rs.getString("t_type")),
|
||||
kind = Transaction.TransactionKind.valueOf(rs.getString("t_kind")),
|
||||
@@ -391,4 +392,44 @@ class TransactionRepoImpl(
|
||||
)
|
||||
jdbcTemplate.update(sql, params)
|
||||
}
|
||||
|
||||
override fun findByDateAndKind(date: java.time.LocalDate, kind: Transaction.TransactionKind): 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.date = :date and t.kind = :kind and t.is_deleted = false""".trimMargin()
|
||||
val params = mapOf(
|
||||
"date" to date,
|
||||
"kind" to kind.name,
|
||||
)
|
||||
return jdbcTemplate.query(sql, params, transactionRowMapper())
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import space.luminic.finance.models.Transaction
|
||||
|
||||
interface NotificationService {
|
||||
fun sendDailyReminder()
|
||||
fun sendPlannedTransactionsReminder()
|
||||
fun sendTXNotification(action: TxActionType, space: Space, userId: Int, tx: Transaction, tx2: Transaction? = null)
|
||||
fun sendTextMessage(chatId: Long, message: String, replyMarkup: ReplyMarkup? = null)
|
||||
fun sendMediaGroup(chatId: Long, group: MediaGroup)
|
||||
|
||||
@@ -12,10 +12,18 @@ import org.springframework.stereotype.Service
|
||||
import org.springframework.context.annotation.Lazy
|
||||
import space.luminic.finance.models.Space
|
||||
import space.luminic.finance.models.Transaction
|
||||
import space.luminic.finance.repos.SpaceRepo
|
||||
import space.luminic.finance.repos.TransactionRepo
|
||||
import java.time.LocalDate
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
@Service
|
||||
class NotificationServiceImpl(private val userService: UserService, private val bot: Bot) : NotificationService {
|
||||
class NotificationServiceImpl(
|
||||
private val userService: UserService,
|
||||
private val bot: Bot,
|
||||
@Lazy private val transactionRepo: TransactionRepo,
|
||||
@Lazy private val spaceRepo: SpaceRepo
|
||||
) : NotificationService {
|
||||
private val logger = LoggerFactory.getLogger(this.javaClass)
|
||||
|
||||
|
||||
@@ -59,6 +67,31 @@ class NotificationServiceImpl(private val userService: UserService, private val
|
||||
}
|
||||
}
|
||||
|
||||
override fun sendPlannedTransactionsReminder() {
|
||||
val today = LocalDate.now()
|
||||
val plannedTxs = transactionRepo.findByDateAndKind(today, Transaction.TransactionKind.PLANNING)
|
||||
|
||||
if (plannedTxs.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
// Группируем по spaceId. У нас нет Space объекта целиком в ответе findByDateAndKind,
|
||||
// но есть t_space_id в маппере (хотя в модели Transaction.space может быть null).
|
||||
// В RepoImpl маппер заполняет space.id
|
||||
val groupedBySpace = plannedTxs.filter { it.space?.id != null }.groupBy { it.space!!.id!! }
|
||||
|
||||
for ((spaceId, txs) in groupedBySpace) {
|
||||
// Чтобы получить владельца, нужно загрузить Space
|
||||
// Используем системного пользователя или просто id для получения
|
||||
val space = spaceRepo.findSpaceById(spaceId, txs.first().createdBy?.id ?: 0)
|
||||
if (space?.owner?.tgId != null) {
|
||||
val txList = txs.joinToString("\n") { "- ${it.comment}: ${it.amount}" }
|
||||
val text = "📅 На сегодня запланированы транзакции:\n\n$txList"
|
||||
sendTextMessage(space.owner.tgId!!, text, createWebAppButton(spaceId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun sendTXNotification(
|
||||
action: TxActionType,
|
||||
space: Space,
|
||||
|
||||
@@ -27,6 +27,12 @@ class Scheduler(
|
||||
notificationService.sendDailyReminder()
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 0 9 * * *")
|
||||
fun sendPlannedTransactionsReminders() {
|
||||
log.info("Sending planned transactions reminders")
|
||||
notificationService.sendPlannedTransactionsReminder()
|
||||
}
|
||||
|
||||
// @Scheduled(cron = "0 0 */3 * * *")
|
||||
@Scheduled(fixedRate = 3, timeUnit =TimeUnit.HOURS)
|
||||
fun analyzePeriodScheduled() {
|
||||
|
||||
Reference in New Issue
Block a user