diff --git a/server/src/main/resources/db/changelog/06-reminders.yml b/server/src/main/resources/db/changelog/06-reminders.yml
new file mode 100644
index 0000000..b314ff1
--- /dev/null
+++ b/server/src/main/resources/db/changelog/06-reminders.yml
@@ -0,0 +1,75 @@
+databaseChangeLog:
+- changeSet:
+ id: 06
+ author: dyrkin
+ preConditions:
+ onFail: MARK_RAN
+ not:
+ tableExists:
+ tableName: reminder
+ changes:
+ - createTable:
+ tableName: reminder
+ columns:
+ - column:
+ autoIncrement: true
+ constraints:
+ primaryKey: true
+ primaryKeyName: bug_pkey
+ name: record_id
+ type: BIGSERIAL
+ - column:
+ constraints:
+ nullable: false
+ name: user_id
+ type: BIGINT
+ - column:
+ constraints:
+ nullable: false
+ name: account_id
+ type: BIGINT
+ - column:
+ constraints:
+ nullable: false
+ name: chat_id
+ type: BIGINT
+ - column:
+ constraints:
+ nullable: false
+ name: source_system_id
+ type: BIGINT
+ - column:
+ constraints:
+ nullable: false
+ name: city_name
+ type: VARCHAR(255)
+ - column:
+ constraints:
+ nullable: false
+ name: clinic_name
+ type: VARCHAR(255)
+ - column:
+ constraints:
+ nullable: false
+ name: service_name
+ type: VARCHAR(255)
+ - column:
+ constraints:
+ nullable: false
+ name: doctor_name
+ type: VARCHAR(255)
+ - column:
+ constraints:
+ nullable: false
+ name: appointment_time
+ type: TIME WITHOUT TIME ZONE
+ - column:
+ constraints:
+ nullable: true
+ name: remind_at_time
+ type: TIME WITHOUT TIME ZONE
+ - column:
+ constraints:
+ nullable: true
+ name: active
+ type: BOOLEAN
\ No newline at end of file
diff --git a/server/src/main/resources/db/liquibase-changelog.yml b/server/src/main/resources/db/liquibase-changelog.yml
index 26bbea4..990a67b 100644
--- a/server/src/main/resources/db/liquibase-changelog.yml
+++ b/server/src/main/resources/db/liquibase-changelog.yml
@@ -16,4 +16,7 @@ databaseChangeLog:
relativeToChangelogFile: true
- include:
file: changelog/05-drop-bugs-table.yml
- relativeToChangelogFile: true
\ No newline at end of file
+ relativeToChangelogFile: true
+- include:
+ file: changelog/06-reminders.yml
+ relativeToChangelogFile: true
\ No newline at end of file
diff --git a/server/src/main/scala/com/lbs/server/BootConfig.scala b/server/src/main/scala/com/lbs/server/BootConfig.scala
index 681a34b..afbd749 100644
--- a/server/src/main/scala/com/lbs/server/BootConfig.scala
+++ b/server/src/main/scala/com/lbs/server/BootConfig.scala
@@ -7,7 +7,7 @@ import com.lbs.bot.telegram.TelegramBot
import com.lbs.server.conversation._
import com.lbs.server.lang.Localization
import com.lbs.server.repository.model.Monitoring
-import com.lbs.server.service.{ApiService, DataService, MonitoringService}
+import com.lbs.server.service.{ApiService, DataService, MonitoringService, ReminderService}
import org.jasypt.util.text.{StrongTextEncryptor, TextEncryptor}
import org.springframework.beans.factory.annotation.{Autowired, Value}
import org.springframework.context.annotation.{Bean, Configuration}
@@ -29,6 +29,9 @@ class BootConfig {
@Autowired
private var monitoringService: MonitoringService = _
+ @Autowired
+ private var reminderService: ReminderService = _
+
@Autowired
private var localization: Localization = _
@@ -123,8 +126,8 @@ class BootConfig {
userId =>
new Chat(
userId,
- dataService,
monitoringService,
+ reminderService,
bookFactory,
helpFactory,
monitoringsFactory,
diff --git a/server/src/main/scala/com/lbs/server/conversation/Chat.scala b/server/src/main/scala/com/lbs/server/conversation/Chat.scala
index 65ca164..c0120d9 100644
--- a/server/src/main/scala/com/lbs/server/conversation/Chat.scala
+++ b/server/src/main/scala/com/lbs/server/conversation/Chat.scala
@@ -5,7 +5,7 @@ import com.lbs.bot.model.Command
import com.lbs.server.conversation.Chat._
import com.lbs.server.conversation.Login.UserId
import com.lbs.server.conversation.base.{Conversation, Interactional}
-import com.lbs.server.service.{DataService, MonitoringService}
+import com.lbs.server.service.{MonitoringService, ReminderService}
import com.lbs.server.util.MessageExtractors._
import com.typesafe.scalalogging.StrictLogging
@@ -13,8 +13,8 @@ import scala.util.matching.Regex
class Chat(
val userId: UserId,
- dataService: DataService,
monitoringService: MonitoringService,
+ reminderService: ReminderService,
bookingFactory: UserIdTo[Book],
helpFactory: UserIdTo[Help],
monitoringsFactory: UserIdTo[Monitorings],
@@ -127,12 +127,12 @@ class Chat(
case Msg(cmd @ TextCommand("/accounts"), _) =>
self ! cmd
goto(accountChat)
- case Msg(TextCommand(ReserveTerm(monitoringIdStr, scheduleIdStr, timeStr)), _) =>
- val monitoringId = monitoringIdStr.toLong
- val scheduleId = scheduleIdStr.toLong
- val time = timeStr.toLong
+ case Msg(TextCommand(ReserveTermRegex(LongString(monitoringId), LongString(scheduleId), LongString(time))), _) =>
monitoringService.bookAppointmentByScheduleId(userId.accountId, monitoringId, scheduleId, time)
stay()
+ case Msg(CallbackCommand(RemindRegexp(LongString(reminderId), LongString(time))), _) =>
+ reminderService.activateReminder(userId.accountId, reminderId, time)
+ stay()
case Msg(cmd: Command, _) =>
interactional ! cmd
stay()
@@ -151,5 +151,6 @@ class Chat(
}
object Chat {
- val ReserveTerm: Regex = s"/reserve_(\\d+)_(\\d+)_(\\d+)".r
+ val ReserveTermRegex: Regex = "/reserve_(\\d+)_(\\d+)_(\\d+)".r
+ val RemindRegexp: Regex = "remind_at_(\\d+)_(\\d+)".r
}
diff --git a/server/src/main/scala/com/lbs/server/lang/En.scala b/server/src/main/scala/com/lbs/server/lang/En.scala
index 9baaa40..8d22143 100644
--- a/server/src/main/scala/com/lbs/server/lang/En.scala
+++ b/server/src/main/scala/com/lbs/server/lang/En.scala
@@ -3,7 +3,7 @@ package com.lbs.server.lang
import com.lbs.api.json.model.{Event, TermExt}
import com.lbs.server.conversation.Book
import com.lbs.server.conversation.StaticData.StaticDataConfig
-import com.lbs.server.repository.model.Monitoring
+import com.lbs.server.repository.model.{Monitoring, Reminder}
import com.lbs.server.util.DateTimeUtil._
import java.time.{LocalDateTime, LocalTime}
@@ -173,7 +173,7 @@ object En extends Lang {
override def help: String =
s"""ℹ Non official bot for Portal Pacjenta LUX MED (v.${Lang.version}).
- |It can help you to book a visit to a doctor, create term monitoring, view upcoming appointments and visit history.
+ |The bot can help you book a visit to a doctor, create term monitorings, view upcoming appointments and visit history.
|
|➡ Supported commands
|/book - reserve a visit, or create a monitoring
@@ -377,4 +377,17 @@ object En extends Lang {
override def canNotDetectPayer(error: String): String = s"Can't determine payer. Reason: $error"
override def pleaseChoosePayer: String = "➡ Can't determine default payer. Please choose one"
+
+ override def youHaveAppointmentAt(reminder: Reminder): String =
+ s"""👍 You have an appointment at ⏱ ${formatTime(reminder.appointmentTime.toLocalTime)}!
+ |
+ |${capitalize(doctor)}: ${reminder.doctorName}
+ |${capitalize(service)}: ${reminder.serviceName}
+ |${capitalize(clinic)}: ${reminder.clinicName}
+ |${capitalize(city)}: ${reminder.cityName}""".stripMargin
+
+ override def remindAt(time: LocalDateTime): String = s"⏱ Remind at ${formatTime(time.toLocalTime)}"
+
+ override def appointmentIsOutdated(appointmentTime: LocalDateTime): String =
+ s"Your appointment has already taken place at ${formatDateTime(appointmentTime, locale)}"
}
diff --git a/server/src/main/scala/com/lbs/server/lang/Lang.scala b/server/src/main/scala/com/lbs/server/lang/Lang.scala
index 030083d..f500812 100644
--- a/server/src/main/scala/com/lbs/server/lang/Lang.scala
+++ b/server/src/main/scala/com/lbs/server/lang/Lang.scala
@@ -3,7 +3,7 @@ package com.lbs.server.lang
import com.lbs.api.json.model.{Event, TermExt}
import com.lbs.server.conversation.Book.BookingData
import com.lbs.server.conversation.StaticData.StaticDataConfig
-import com.lbs.server.repository.model.Monitoring
+import com.lbs.server.repository.model.{Monitoring, Reminder}
import java.time.{LocalDateTime, LocalTime}
import java.util.Locale
@@ -235,4 +235,10 @@ trait Lang {
def pleaseChooseAccount(currentAccountName: String): String
def accountSwitched(username: String): String
+
+ def youHaveAppointmentAt(reminder: Reminder): String
+
+ def remindAt(time: LocalDateTime): String
+
+ def appointmentIsOutdated(appointmentTime: LocalDateTime): String
}
diff --git a/server/src/main/scala/com/lbs/server/lang/Pl.scala b/server/src/main/scala/com/lbs/server/lang/Pl.scala
index 1ea4885..561f23f 100644
--- a/server/src/main/scala/com/lbs/server/lang/Pl.scala
+++ b/server/src/main/scala/com/lbs/server/lang/Pl.scala
@@ -3,7 +3,7 @@ package com.lbs.server.lang
import com.lbs.api.json.model.{Event, TermExt}
import com.lbs.server.conversation.Book
import com.lbs.server.conversation.StaticData.StaticDataConfig
-import com.lbs.server.repository.model.Monitoring
+import com.lbs.server.repository.model.{Monitoring, Reminder}
import com.lbs.server.util.DateTimeUtil._
import java.time.{LocalDateTime, LocalTime}
@@ -379,4 +379,17 @@ object Pl extends Lang {
override def canNotDetectPayer(error: String): String = s"Nie udało się ustalić płatnika. Powód: $error"
override def pleaseChoosePayer: String = "➡ Nie udało się ustalić domyślnego płatnika, wybierz jakiegoś."
+
+ override def youHaveAppointmentAt(reminder: Reminder): String =
+ s"""👍 Macie wizytę o ⏱ ${formatTime(reminder.appointmentTime.toLocalTime)}!
+ |
+ |${capitalize(doctor)}: ${reminder.doctorName}
+ |${capitalize(service)}: ${reminder.serviceName}
+ |${capitalize(clinic)}: ${reminder.clinicName}
+ |${capitalize(city)}: ${reminder.cityName}""".stripMargin
+
+ override def remindAt(time: LocalDateTime): String = s"⏱ Przypomnij o ${formatTime(time.toLocalTime)}"
+
+ override def appointmentIsOutdated(appointmentTime: LocalDateTime): String =
+ s"Twoja wizyta już się odbyła o godzine ${formatDateTime(appointmentTime, locale)}"
}
diff --git a/server/src/main/scala/com/lbs/server/lang/Ua.scala b/server/src/main/scala/com/lbs/server/lang/Ua.scala
index 229b542..65f1cd7 100644
--- a/server/src/main/scala/com/lbs/server/lang/Ua.scala
+++ b/server/src/main/scala/com/lbs/server/lang/Ua.scala
@@ -3,7 +3,7 @@ package com.lbs.server.lang
import com.lbs.api.json.model.{Event, TermExt}
import com.lbs.server.conversation.Book
import com.lbs.server.conversation.StaticData.StaticDataConfig
-import com.lbs.server.repository.model.Monitoring
+import com.lbs.server.repository.model.{Monitoring, Reminder}
import com.lbs.server.util.DateTimeUtil._
import java.time.{LocalDateTime, LocalTime}
@@ -378,4 +378,17 @@ object Ua extends Lang {
override def pleaseChoosePayer: String =
"➡ Не можу визначити платника за замовчуванням. Будь ласка, виберіть платника"
+
+ override def youHaveAppointmentAt(reminder: Reminder): String =
+ s"""👍 У вас є візит о ⏱ ${formatTime(reminder.appointmentTime.toLocalTime)}!
+ |
+ |${capitalize(doctor)}: ${reminder.doctorName}
+ |${capitalize(service)}: ${reminder.serviceName}
+ |${capitalize(clinic)}: ${reminder.clinicName}
+ |${capitalize(city)}: ${reminder.cityName}""".stripMargin
+
+ override def remindAt(time: LocalDateTime): String = s"⏱ Remind at ${formatTime(time.toLocalTime)}"
+
+ override def appointmentIsOutdated(appointmentTime: LocalDateTime): String =
+ s"Your appointment has already taken place at ${formatDateTime(appointmentTime, locale)}"
}
diff --git a/server/src/main/scala/com/lbs/server/repository/DataRepository.scala b/server/src/main/scala/com/lbs/server/repository/DataRepository.scala
index cc7bf8a..11c5bf4 100644
--- a/server/src/main/scala/com/lbs/server/repository/DataRepository.scala
+++ b/server/src/main/scala/com/lbs/server/repository/DataRepository.scala
@@ -1,6 +1,6 @@
package com.lbs.server.repository
-import com.lbs.server.repository.model.{CityHistory, ClinicHistory, Credentials, DoctorHistory, JLong, Monitoring, ServiceHistory, Settings, Source, SystemUser}
+import com.lbs.server.repository.model.{CityHistory, ClinicHistory, Credentials, DoctorHistory, JLong, Monitoring, Reminder, ServiceHistory, Settings, Source, SystemUser}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Repository
@@ -95,6 +95,15 @@ class DataRepository(@Autowired em: EntityManager) {
.toSeq
}
+ def getActiveReminders: Seq[Reminder] = {
+ em.createQuery(
+ """select reminder from Reminder reminder where reminder.active = true""".stripMargin,
+ classOf[Reminder]
+ ).getResultList
+ .asScala
+ .toSeq
+ }
+
def getActiveMonitoringsCount(accountId: Long): JLong = {
em.createQuery(
"""select count(monitoring) from Monitoring monitoring where monitoring.active = true
@@ -177,6 +186,18 @@ class DataRepository(@Autowired em: EntityManager) {
.headOption
}
+ def findReminder(accountId: Long, reminderId: Long): Option[Reminder] = {
+ em.createQuery(
+ """select reminder from Reminder reminder where reminder.accountId = :accountId
+ | and reminder.recordId = :reminderId""".stripMargin,
+ classOf[Reminder]
+ ).setParameter("accountId", accountId)
+ .setParameter("reminderId", reminderId)
+ .getResultList
+ .asScala
+ .headOption
+ }
+
def findSettings(userId: Long): Option[Settings] = {
em.createQuery("select settings from Settings settings where settings.userId = :userId", classOf[Settings])
.setParameter("userId", userId)
diff --git a/server/src/main/scala/com/lbs/server/repository/model/Reminder.scala b/server/src/main/scala/com/lbs/server/repository/model/Reminder.scala
new file mode 100644
index 0000000..cc783a9
--- /dev/null
+++ b/server/src/main/scala/com/lbs/server/repository/model/Reminder.scala
@@ -0,0 +1,83 @@
+package com.lbs.server.repository.model
+
+import java.time.LocalDateTime
+import javax.persistence.{Access, AccessType, Column, Entity}
+import scala.beans.BeanProperty
+
+@Entity
+@Access(AccessType.FIELD)
+class Reminder extends RecordId {
+ @BeanProperty
+ @Column(name = "user_id", nullable = false)
+ var userId: JLong = _
+
+ @BeanProperty
+ @Column(name = "account_id", nullable = false)
+ var accountId: JLong = _
+
+ @BeanProperty
+ @Column(name = "chat_id", nullable = false)
+ var chatId: String = _
+
+ @BeanProperty
+ @Column(name = "source_system_id", nullable = false)
+ var sourceSystemId: JLong = _
+
+ @BeanProperty
+ @Column(name = "city_name", nullable = false)
+ var cityName: String = _
+
+ @BeanProperty
+ @Column(name = "clinic_name", nullable = false)
+ var clinicName: String = _
+
+ @BeanProperty
+ @Column(name = "service_name", nullable = false)
+ var serviceName: String = _
+
+ @BeanProperty
+ @Column(name = "doctor_name", nullable = false)
+ var doctorName: String = _
+
+ @BeanProperty
+ @Column(name = "appointment_time", nullable = false)
+ var appointmentTime: LocalDateTime = _
+
+ @BeanProperty
+ @Column(name = "remind_at_time", nullable = true)
+ var remindAt: LocalDateTime = _
+
+ @BeanProperty
+ @Column(nullable = false)
+ var active: Boolean = false
+}
+
+object Reminder {
+ def apply(
+ userId: Long,
+ accountId: Long,
+ chatId: String,
+ sourceSystemId: Long,
+ cityName: String,
+ clinicName: String,
+ serviceName: String,
+ doctorName: String,
+ appointmentTime: LocalDateTime,
+ remindAt: LocalDateTime,
+ active: Boolean
+ ): Reminder = {
+ val reminder = new Reminder
+ reminder.userId = userId
+ reminder.accountId = accountId
+ reminder.chatId = chatId
+ reminder.sourceSystemId = sourceSystemId
+ reminder.cityName = cityName
+ reminder.clinicName = clinicName
+ reminder.serviceName = serviceName
+ reminder.doctorName = doctorName
+ reminder.appointmentTime = appointmentTime
+ reminder.remindAt = remindAt
+ reminder.active = active
+ reminder
+ }
+}
diff --git a/server/src/main/scala/com/lbs/server/service/DataService.scala b/server/src/main/scala/com/lbs/server/service/DataService.scala
index f521792..ce43210 100644
--- a/server/src/main/scala/com/lbs/server/service/DataService.scala
+++ b/server/src/main/scala/com/lbs/server/service/DataService.scala
@@ -48,6 +48,15 @@ class DataService {
dataRepository.saveEntity(monitoring)
}
+ @Transactional
+ def saveReminder(reminder: Reminder): Reminder = {
+ dataRepository.saveEntity(reminder)
+ }
+
+ def getActiveReminders: Seq[Reminder] = {
+ dataRepository.getActiveReminders
+ }
+
def getActiveMonitorings: Seq[Monitoring] = {
dataRepository.getActiveMonitorings
}
@@ -76,6 +85,10 @@ class DataService {
dataRepository.findMonitoring(accountId, monitoringId)
}
+ def findReminder(accountId: Long, reminderId: Long): Option[Reminder] = {
+ dataRepository.findReminder(accountId, reminderId)
+ }
+
def findSettings(userId: Long): Option[Settings] = {
dataRepository.findSettings(userId)
}
diff --git a/server/src/main/scala/com/lbs/server/service/MonitoringService.scala b/server/src/main/scala/com/lbs/server/service/MonitoringService.scala
index a4f43f3..6f434cc 100644
--- a/server/src/main/scala/com/lbs/server/service/MonitoringService.scala
+++ b/server/src/main/scala/com/lbs/server/service/MonitoringService.scala
@@ -2,8 +2,8 @@ package com.lbs.server.service
import com.lbs.api.exception.InvalidLoginOrPasswordException
import com.lbs.api.json.model._
-import com.lbs.bot.Bot
-import com.lbs.bot.model.{MessageSource, MessageSourceSystem}
+import com.lbs.bot.model.{Button, MessageSource, MessageSourceSystem}
+import com.lbs.bot.{Bot, createInlineKeyboard}
import com.lbs.common.Scheduler
import com.lbs.server.lang.Localization
import com.lbs.server.repository.model._
@@ -13,7 +13,7 @@ import com.typesafe.scalalogging.StrictLogging
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
-import java.time.{LocalDateTime, ZonedDateTime}
+import java.time.{LocalDateTime, ZoneId, ZonedDateTime}
import java.util.concurrent.ScheduledFuture
import javax.annotation.PostConstruct
import scala.collection.mutable
@@ -30,6 +30,8 @@ class MonitoringService extends StrictLogging {
@Autowired
private var apiService: ApiService = _
@Autowired
+ private var reminderService: ReminderService = _
+ @Autowired
private var localization: Localization = _
private var activeMonitorings = mutable.Map.empty[JLong, (Monitoring, ScheduledFuture[_])]
@@ -195,8 +197,23 @@ class MonitoringService extends StrictLogging {
} yield response
bookingResult match {
case Right(_) =>
- bot.sendMessage(monitoring.source, lang(monitoring.userId).appointmentIsBooked(term, monitoring))
deactivateMonitoring(monitoring.accountId, monitoring.recordId)
+ val reminder = reminderService.createInactiveReminder((term.term, monitoring).mapTo[Reminder])
+ val remind1h = term.term.dateTimeFrom.get.minusHours(1)
+ val remind1hMillis = remind1h.atZone(ZoneId.systemDefault()).toInstant.toEpochMilli
+ val remind2h = term.term.dateTimeFrom.get.minusHours(2)
+ val remind2hMillis = remind2h.atZone(ZoneId.systemDefault()).toInstant.toEpochMilli
+ val messages = lang(monitoring.userId)
+ bot.sendMessage(
+ monitoring.source,
+ messages.appointmentIsBooked(term, monitoring),
+ inlineKeyboard = createInlineKeyboard(
+ Seq(
+ Button(messages.remindAt(remind1h), s"remind_at_${reminder.recordId}_$remind1hMillis"),
+ Button(messages.remindAt(remind2h), s"remind_at_${reminder.recordId}_$remind2hMillis")
+ )
+ )
+ )
case Left(ex) =>
logger.error(s"Unable to book appointment by monitoring [${monitoring.recordId}]", ex)
}
@@ -206,7 +223,7 @@ class MonitoringService extends StrictLogging {
accountId: Long,
xsrfToken: XsrfToken,
temporaryReservationId: Long,
- fn: (Long) => Either[Throwable, T]
+ fn: Long => Either[Throwable, T]
): Either[Throwable, T] = {
fn(accountId) match {
case r @ Left(_) =>
diff --git a/server/src/main/scala/com/lbs/server/service/ReminderService.scala b/server/src/main/scala/com/lbs/server/service/ReminderService.scala
new file mode 100644
index 0000000..90c9da1
--- /dev/null
+++ b/server/src/main/scala/com/lbs/server/service/ReminderService.scala
@@ -0,0 +1,94 @@
+package com.lbs.server.service
+
+import com.lbs.bot.Bot
+import com.lbs.bot.model.{MessageSource, MessageSourceSystem}
+import com.lbs.common.Scheduler
+import com.lbs.server.lang.Localization
+import com.lbs.server.repository.model._
+import com.typesafe.scalalogging.StrictLogging
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Service
+
+import java.time.{Instant, LocalDateTime, ZoneId}
+import javax.annotation.PostConstruct
+import scala.concurrent.duration._
+
+@Service
+class ReminderService extends StrictLogging {
+
+ @Autowired
+ private var bot: Bot = _
+ @Autowired
+ private var dataService: DataService = _
+ @Autowired
+ private var localization: Localization = _
+
+ private val dbChecker = new Scheduler(1)
+
+ private def deactivateReminder(accountId: JLong, reminderId: JLong): Unit = {
+ dataService.findReminder(accountId, reminderId).foreach { reminder =>
+ reminder.active = false
+ dataService.saveReminder(reminder)
+ }
+ }
+
+ def remindUserAboutAppointment(reminder: Reminder): Unit = {
+ deactivateReminder(reminder.accountId, reminder.recordId)
+
+ val messages = lang(reminder.userId)
+ val message = messages.youHaveAppointmentAt(reminder)
+
+ bot.sendMessage(reminder.source, message)
+ }
+
+ private def checkReminders(): Unit = {
+ logger.debug(s"Looking for active reminders")
+
+ val activeReminders = dataService.getActiveReminders
+ logger.debug(s"Found [${activeReminders.size}] active reminders")
+ val now = LocalDateTime.now()
+
+ activeReminders.foreach {
+ case reminder if reminder.remindAt.isAfter(now) =>
+ logger.debug(s"Notifying user [${reminder.userId}] about appointment at [${reminder.appointmentTime}]")
+ remindUserAboutAppointment(reminder)
+ }
+ }
+
+ private def initializeDbChecker(): Unit = {
+ dbChecker.schedule(checkReminders(), 20.seconds)
+ }
+
+ def createInactiveReminder(reminder: Reminder): Reminder = {
+ reminder.active = false
+ dataService.saveReminder(reminder)
+ }
+
+ def activateReminder(accountId: Long, reminderId: Long, timeMillis: Long): Unit = {
+ val time = Instant.ofEpochMilli(timeMillis).atZone(ZoneId.systemDefault()).toLocalDateTime
+ val reminderMaybe = dataService.findReminder(accountId, reminderId)
+
+ reminderMaybe.foreach { reminder =>
+ if (reminder.appointmentTime.isBefore(time)) {
+ reminder.active = true
+ reminder.remindAt = time
+ dataService.saveReminder(reminder)
+ } else {
+ val messages = lang(reminder.userId)
+ val message = messages.appointmentIsOutdated(reminder.appointmentTime)
+ bot.sendMessage(reminder.source, message)
+ }
+ }
+ }
+
+ implicit class ReminderAsSource(reminder: Reminder) {
+ def source: MessageSource = MessageSource(MessageSourceSystem(reminder.sourceSystemId), reminder.chatId)
+ }
+
+ private def lang(userId: Long) = localization.lang(userId)
+
+ @PostConstruct
+ private def initialize(): Unit = {
+ initializeDbChecker()
+ }
+}
diff --git a/server/src/main/scala/com/lbs/server/util/package.scala b/server/src/main/scala/com/lbs/server/util/package.scala
index 4017b70..1320961 100644
--- a/server/src/main/scala/com/lbs/server/util/package.scala
+++ b/server/src/main/scala/com/lbs/server/util/package.scala
@@ -5,12 +5,12 @@ import com.lbs.bot.model.Command
import com.lbs.common.ModelConverters
import com.lbs.server.conversation.Book.BookingData
import com.lbs.server.conversation.Login.UserId
-import com.lbs.server.repository.model.{History, Monitoring}
+import com.lbs.server.repository.model.{History, Monitoring, Reminder}
import java.time._
import java.time.format.DateTimeFormatter
import java.util.Locale
-import scala.language.{higherKinds, implicitConversions}
+import scala.language.implicitConversions
import scala.util.Try
package object util {
@@ -109,6 +109,24 @@ package object util {
)
}
+ implicit val TermAndMonitoringToReminder: ObjectConverter[(Term, Monitoring), Reminder] =
+ (data: (Term, Monitoring)) => {
+ val (term, monitoring) = data
+ Reminder(
+ userId = monitoring.userId,
+ accountId = monitoring.accountId,
+ chatId = monitoring.chatId,
+ sourceSystemId = monitoring.sourceSystemId,
+ cityName = monitoring.cityName,
+ clinicName = monitoring.clinicName,
+ serviceName = monitoring.serviceName,
+ doctorName = monitoring.doctorName,
+ appointmentTime = term.dateTimeFrom.get,
+ remindAt = null,
+ active = false
+ )
+ }
+
implicit val HistoryToIdNameConverter: ObjectConverter[History, IdName] =
(history: History) => IdName(history.id, history.name)
}
@@ -167,6 +185,8 @@ package object util {
def formatDateTime(date: LuxmedFunnyDateTime, locale: Locale): String = date.get.format(DateTimeFormat(locale))
+ def formatDateTime(date: LocalDateTime, locale: Locale): String = date.format(DateTimeFormat(locale))
+
private val EpochMinutesTillBeginOf2022: Long = epochMinutes(LocalDateTime.of(2022, 1, 1, 0, 0, 0, 0))
def epochMinutes(time: LocalDateTime): Long = time.toInstant(ZonedDateTime.now().getOffset).getEpochSecond / 60