mirror of
https://github.com/dyrkin/luxmed-bot.git
synced 2025-12-21 13:23:05 +01:00
Multiple account support
This commit is contained in:
@@ -102,10 +102,14 @@ class BootConfig {
|
||||
def settingsActorFactory: ByUserIdActorFactory =
|
||||
userId => actorSystem.actorOf(Settings.props(userId, bot, dataService, localization))
|
||||
|
||||
@Bean
|
||||
def accountActorFactory: ByUserIdActorFactory =
|
||||
userId => actorSystem.actorOf(Account.props(userId, bot, dataService, localization, router))
|
||||
|
||||
@Bean
|
||||
def chatActorFactory: ByUserIdActorFactory =
|
||||
userId => actorSystem.actorOf(Chat.props(userId, dataService, monitoringService, bookingActorFactory, helpActorFactory,
|
||||
monitoringsActorFactory, historyActorFactory, visitsActorFactory, settingsActorFactory, bugActorFactory))
|
||||
monitoringsActorFactory, historyActorFactory, visitsActorFactory, settingsActorFactory, bugActorFactory, accountActorFactory))
|
||||
|
||||
@Bean
|
||||
def datePickerFactory: ByUserIdWithOriginatorActorFactory = (userId, originator) =>
|
||||
|
||||
103
server/src/main/scala/com/lbs/server/actor/Account.scala
Normal file
103
server/src/main/scala/com/lbs/server/actor/Account.scala
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server.actor
|
||||
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import com.lbs.bot.model.{Button, Command}
|
||||
import com.lbs.bot.{Bot, _}
|
||||
import com.lbs.server.actor.Account._
|
||||
import com.lbs.server.actor.Chat.Init
|
||||
import com.lbs.server.actor.Login._
|
||||
import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.service.DataService
|
||||
|
||||
class Account(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization, router: ActorRef) extends SafeFSM[FSMState, FSMData] with Localizable {
|
||||
|
||||
startWith(AskAction, null)
|
||||
|
||||
whenSafe(AskAction) {
|
||||
case Event(Next, _) =>
|
||||
val credentials = dataService.getUserCredentials(userId.userId)
|
||||
val buttons = Seq(Button(lang.addAccount, -1L), Button(lang.deleteAccount, -2L)) ++ credentials.map(c => Button(s"🔐️ ${c.username}", c.accountId))
|
||||
bot.sendMessage(userId.source, lang.pleaseChooseAccount, inlineKeyboard = createInlineKeyboard(buttons, columns = 1))
|
||||
goto(AwaitAction)
|
||||
}
|
||||
|
||||
whenSafe(AwaitAction) {
|
||||
case Event(cmd@Command(_, _, Some(actionStr)), _) =>
|
||||
val action = actionStr.toLong
|
||||
action match {
|
||||
case -1L =>
|
||||
router ! cmd.copy(message = cmd.message.copy(text = Some("/login")))
|
||||
goto(AskAction) using null
|
||||
case -2L =>
|
||||
bot.sendMessage(userId.source, "Not implemented yet")
|
||||
goto(AskAction) using null
|
||||
case accountId =>
|
||||
val accountMaybe = dataService.findUserCredentialsByAccountId(userId.userId, accountId)
|
||||
accountMaybe match {
|
||||
case Some(account) => //account was found
|
||||
val userMaybe = dataService.findUser(userId.userId)
|
||||
userMaybe.foreach { user =>
|
||||
user.activeAccountId = accountId
|
||||
dataService.saveUser(user)
|
||||
router ! SwitchUser(UserId(account.userId, account.accountId, userId.source))
|
||||
bot.sendMessage(userId.source, lang.accountSwitched(account.username))
|
||||
}
|
||||
goto(AskAction) using null
|
||||
case None =>
|
||||
LOG.error(s"This is not user [#${userId.userId}] account [#$accountId]")
|
||||
goto(AskAction) using null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
whenUnhandledSafe {
|
||||
case Event(Init, _) =>
|
||||
invokeNext()
|
||||
goto(AskAction) using null
|
||||
case e: Event =>
|
||||
LOG.error(s"Unhandled event in state:$stateName. Event: $e")
|
||||
stay()
|
||||
}
|
||||
|
||||
initialize()
|
||||
|
||||
}
|
||||
|
||||
object Account {
|
||||
def props(userId: UserId, bot: Bot, dataService: DataService, localization: Localization, router: ActorRef): Props =
|
||||
Props(new Account(userId, bot, dataService, localization, router))
|
||||
|
||||
object AskAction extends FSMState
|
||||
|
||||
object AwaitAction extends FSMState
|
||||
|
||||
object AddAccount extends FSMState
|
||||
|
||||
object RemoveAccount extends FSMState
|
||||
|
||||
case class SwitchUser(userId: UserId)
|
||||
|
||||
}
|
||||
@@ -54,22 +54,22 @@ class Auth(val source: MessageSource, dataService: DataService, unauthorizedHelp
|
||||
case cmd: Command if userId.nonEmpty =>
|
||||
chatActor = getChatActor(userId.get)
|
||||
chatActor ! cmd
|
||||
case LoggedIn(forwardCommand, id) =>
|
||||
val uId = UserId(id, source)
|
||||
case LoggedIn(forwardCommand, uId, aId) =>
|
||||
val id = UserId(uId, aId, source)
|
||||
val cmd = forwardCommand.cmd
|
||||
userId = Some(uId)
|
||||
chatActor = getChatActor(uId, reinit = true)
|
||||
userId = Some(id)
|
||||
chatActor = getChatActor(id, reInit = true)
|
||||
if (!cmd.message.text.contains("/login"))
|
||||
chatActor ! cmd
|
||||
case cmd: Command =>
|
||||
chatActor ! cmd
|
||||
}
|
||||
|
||||
private def getChatActor(userId: UserId, reinit: Boolean = false): ActorRef = {
|
||||
private def getChatActor(userId: UserId, reInit: Boolean = false): ActorRef = {
|
||||
if (chatActor == null) {
|
||||
chatActorFactory(userId)
|
||||
} else {
|
||||
if (reinit) {
|
||||
if (reInit) {
|
||||
chatActor ! PoisonPill
|
||||
chatActorFactory(userId)
|
||||
} else chatActor
|
||||
@@ -77,8 +77,8 @@ class Auth(val source: MessageSource, dataService: DataService, unauthorizedHelp
|
||||
}
|
||||
|
||||
def getUserId: Option[UserId] = {
|
||||
val userIdMaybe = dataService.findUserIdBySource(source)
|
||||
userIdMaybe.map(id => UserId(id, source))
|
||||
val userIdMaybe = dataService.findUserAndAccountIdBySource(source)
|
||||
userIdMaybe.map { case (uId, aId) => UserId(uId, aId, source) }
|
||||
}
|
||||
|
||||
override def postStop(): Unit = {
|
||||
|
||||
@@ -53,29 +53,29 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
requestStaticData(RequestCity, AwaitCity, cityConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestCities(userId.userId),
|
||||
staticOptions = apiService.getAllCities(userId.userId),
|
||||
latestOptions = dataService.getLatestCities(userId.accountId),
|
||||
staticOptions = apiService.getAllCities(userId.accountId),
|
||||
applyId = id => bd.copy(cityId = id))
|
||||
}(requestNext = RequestClinic)
|
||||
|
||||
requestStaticData(RequestClinic, AwaitClinic, clinicConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestClinicsByCityId(userId.userId, bd.cityId.id),
|
||||
staticOptions = apiService.getAllClinics(userId.userId, bd.cityId.id),
|
||||
latestOptions = dataService.getLatestClinicsByCityId(userId.accountId, bd.cityId.id),
|
||||
staticOptions = apiService.getAllClinics(userId.accountId, bd.cityId.id),
|
||||
applyId = id => bd.copy(clinicId = id))
|
||||
}(requestNext = RequestService)
|
||||
|
||||
requestStaticData(RequestService, AwaitService, serviceConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestServicesByCityIdAndClinicId(userId.userId, bd.cityId.id, bd.clinicId.optionalId),
|
||||
staticOptions = apiService.getAllServices(userId.userId, bd.cityId.id, bd.clinicId.optionalId),
|
||||
latestOptions = dataService.getLatestServicesByCityIdAndClinicId(userId.accountId, bd.cityId.id, bd.clinicId.optionalId),
|
||||
staticOptions = apiService.getAllServices(userId.accountId, bd.cityId.id, bd.clinicId.optionalId),
|
||||
applyId = id => bd.copy(serviceId = id))
|
||||
}(requestNext = RequestDoctor)
|
||||
|
||||
requestStaticData(RequestDoctor, AwaitDoctor, doctorConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestDoctorsByCityIdAndClinicIdAndServiceId(userId.userId, bd.cityId.id, bd.clinicId.optionalId, bd.serviceId.id),
|
||||
staticOptions = apiService.getAllDoctors(userId.userId, bd.cityId.id, bd.clinicId.optionalId, bd.serviceId.id),
|
||||
latestOptions = dataService.getLatestDoctorsByCityIdAndClinicIdAndServiceId(userId.accountId, bd.cityId.id, bd.clinicId.optionalId, bd.serviceId.id),
|
||||
staticOptions = apiService.getAllDoctors(userId.accountId, bd.cityId.id, bd.clinicId.optionalId, bd.serviceId.id),
|
||||
applyId = id => bd.copy(doctorId = id))
|
||||
}(requestNext = RequestDateFrom)
|
||||
|
||||
@@ -128,7 +128,7 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
whenSafe(RequestAction) {
|
||||
case Event(Next, bookingData: BookingData) =>
|
||||
dataService.storeAppointment(userId.userId, bookingData)
|
||||
dataService.storeAppointment(userId.accountId, bookingData)
|
||||
bot.sendMessage(userId.source,
|
||||
lang.bookingSummary(bookingData),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.findTerms, Tags.FindTerms), Button(lang.modifyDate, Tags.ModifyDate))))
|
||||
@@ -146,7 +146,7 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
whenSafe(RequestTerm) {
|
||||
case Event(Next, bookingData: BookingData) =>
|
||||
val availableTerms = apiService.getAvailableTerms(userId.userId, bookingData.cityId.id,
|
||||
val availableTerms = apiService.getAvailableTerms(userId.accountId, bookingData.cityId.id,
|
||||
bookingData.clinicId.optionalId, bookingData.serviceId.id, bookingData.doctorId.optionalId,
|
||||
bookingData.dateFrom, Some(bookingData.dateTo), timeOfDay = bookingData.timeOfDay)
|
||||
termsPager ! availableTerms
|
||||
@@ -174,7 +174,7 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
whenSafe(RequestReservation) {
|
||||
case Event(term: AvailableVisitsTermPresentation, bookingData: BookingData) =>
|
||||
val response = apiService.temporaryReservation(userId.userId, term.mapTo[TemporaryReservationRequest], term.mapTo[ValuationsRequest])
|
||||
val response = apiService.temporaryReservation(userId.accountId, term.mapTo[TemporaryReservationRequest], term.mapTo[ValuationsRequest])
|
||||
response match {
|
||||
case Left(ex) =>
|
||||
bot.sendMessage(userId.source, ex.getMessage)
|
||||
@@ -189,7 +189,7 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
whenSafe(AwaitReservation) {
|
||||
case Event(Command(_, _, Some(Tags.Cancel)), bookingData: BookingData) =>
|
||||
apiService.deleteTemporaryReservation(userId.userId, bookingData.temporaryReservationId.get)
|
||||
apiService.deleteTemporaryReservation(userId.accountId, bookingData.temporaryReservationId.get)
|
||||
stay()
|
||||
case Event(Command(_, _, Some(Tags.Book)), bookingData: BookingData) =>
|
||||
val reservationRequestMaybe = for {
|
||||
@@ -201,7 +201,7 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
reservationRequestMaybe match {
|
||||
case Some(reservationRequest) =>
|
||||
apiService.reservation(userId.userId, reservationRequest) match {
|
||||
apiService.reservation(userId.accountId, reservationRequest) match {
|
||||
case Left(ex) =>
|
||||
bot.sendMessage(userId.source, ex.getMessage)
|
||||
invokeNext()
|
||||
|
||||
@@ -36,7 +36,7 @@ import scala.util.matching.Regex
|
||||
class Chat(val userId: UserId, dataService: DataService, monitoringService: MonitoringService, bookingActorFactory: ByUserIdActorFactory, helpActorFactory: ByUserIdActorFactory,
|
||||
monitoringsActorFactory: ByUserIdActorFactory, historyActorFactory: ByUserIdActorFactory,
|
||||
visitsActorFactory: ByUserIdActorFactory, settingsActorFactory: ByUserIdActorFactory,
|
||||
bugActorFactory: ByUserIdActorFactory) extends SafeFSM[FSMState, FSMData] with Logger {
|
||||
bugActorFactory: ByUserIdActorFactory, accountActorFactory: ByUserIdActorFactory) extends SafeFSM[FSMState, FSMData] with Logger {
|
||||
|
||||
private val bookingActor = bookingActorFactory(userId)
|
||||
private val helpActor = helpActorFactory(userId)
|
||||
@@ -45,6 +45,7 @@ class Chat(val userId: UserId, dataService: DataService, monitoringService: Moni
|
||||
private val visitsActor = visitsActorFactory(userId)
|
||||
private val settingsActor = settingsActorFactory(userId)
|
||||
private val bugActor = bugActorFactory(userId)
|
||||
private val accountActor = accountActorFactory(userId)
|
||||
|
||||
startWith(HelpChat, null)
|
||||
|
||||
@@ -93,6 +94,12 @@ class Chat(val userId: UserId, dataService: DataService, monitoringService: Moni
|
||||
stay()
|
||||
}
|
||||
|
||||
when(AccountChat, accountActor) {
|
||||
case Event(Command(_, Text("/accounts"), _), _) =>
|
||||
accountActor ! Init
|
||||
stay()
|
||||
}
|
||||
|
||||
private def when(state: FSMState, actor: ActorRef)(mainStateFunction: StateFunction): Unit = {
|
||||
whenSafe(state) {
|
||||
case event: Event =>
|
||||
@@ -130,11 +137,14 @@ class Chat(val userId: UserId, dataService: DataService, monitoringService: Moni
|
||||
case Event(cmd@Command(_, Text("/settings"), _), _) =>
|
||||
self ! cmd
|
||||
goto(SettingsChat)
|
||||
case Event(cmd@Command(_, Text("/accounts"), _), _) =>
|
||||
self ! cmd
|
||||
goto(AccountChat)
|
||||
case Event(cmd@Command(_, Text(MonitoringId(monitoringIdStr, scheduleIdStr, timeStr)), _), _) =>
|
||||
val monitoringId = monitoringIdStr.toLong
|
||||
val scheduleId = scheduleIdStr.toLong
|
||||
val time = timeStr.toLong
|
||||
monitoringService.bookAppointmentByScheduleId(userId.userId, monitoringId, scheduleId, time)
|
||||
monitoringService.bookAppointmentByScheduleId(userId.accountId, monitoringId, scheduleId, time)
|
||||
stay()
|
||||
case Event(cmd: Command, _) =>
|
||||
actor ! cmd
|
||||
@@ -157,6 +167,7 @@ class Chat(val userId: UserId, dataService: DataService, monitoringService: Moni
|
||||
visitsActor ! PoisonPill
|
||||
settingsActor ! PoisonPill
|
||||
bugActor ! PoisonPill
|
||||
accountActor ! PoisonPill
|
||||
super.postStop()
|
||||
}
|
||||
}
|
||||
@@ -164,9 +175,10 @@ class Chat(val userId: UserId, dataService: DataService, monitoringService: Moni
|
||||
object Chat {
|
||||
def props(userId: UserId, dataService: DataService, monitoringService: MonitoringService, bookingActorFactory: ByUserIdActorFactory, helpActorFactory: ByUserIdActorFactory,
|
||||
monitoringsActorFactory: ByUserIdActorFactory, historyActorFactory: ByUserIdActorFactory,
|
||||
visitsActorFactory: ByUserIdActorFactory, settingsActorFactory: ByUserIdActorFactory, bugActorFactory: ByUserIdActorFactory): Props =
|
||||
visitsActorFactory: ByUserIdActorFactory, settingsActorFactory: ByUserIdActorFactory, bugActorFactory: ByUserIdActorFactory,
|
||||
accountActorFactory: ByUserIdActorFactory): Props =
|
||||
Props(new Chat(userId, dataService, monitoringService, bookingActorFactory, helpActorFactory, monitoringsActorFactory,
|
||||
historyActorFactory, visitsActorFactory, settingsActorFactory, bugActorFactory))
|
||||
historyActorFactory, visitsActorFactory, settingsActorFactory, bugActorFactory, accountActorFactory))
|
||||
|
||||
object HelpChat extends FSMState
|
||||
|
||||
@@ -182,6 +194,8 @@ object Chat {
|
||||
|
||||
object BugChat extends FSMState
|
||||
|
||||
object AccountChat extends FSMState
|
||||
|
||||
object Init
|
||||
|
||||
val MonitoringId: Regex = s"/reserve_(\\d+)_(\\d+)_(\\d+)".r
|
||||
|
||||
@@ -41,7 +41,7 @@ class History(val userId: UserId, bot: Bot, apiService: ApiService, val localiza
|
||||
|
||||
whenSafe(RequestData) {
|
||||
case Event(Next, _) =>
|
||||
val visits = apiService.visitsHistory(userId.userId)
|
||||
val visits = apiService.visitsHistory(userId.accountId)
|
||||
historyPager ! visits
|
||||
goto(AwaitPage)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ package com.lbs.server.actor
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import com.lbs.bot.Bot
|
||||
import com.lbs.bot.model.{Command, MessageSource}
|
||||
import com.lbs.bot.telegram.TelegramBot
|
||||
import com.lbs.server.actor.Chat.Init
|
||||
import com.lbs.server.actor.Login._
|
||||
import com.lbs.server.lang.{Localizable, Localization}
|
||||
@@ -56,10 +55,10 @@ class Login(source: MessageSource, bot: Bot, dataService: DataService, apiServic
|
||||
goto(RequestUsername) using LoginData()
|
||||
case Right(loggedIn) =>
|
||||
val credentials = dataService.saveCredentials(source, username, password)
|
||||
userId = UserId(credentials.userId, source)
|
||||
apiService.addSession(credentials.userId, loggedIn.accessToken, loggedIn.tokenType)
|
||||
userId = UserId(credentials.userId, credentials.accountId, source)
|
||||
apiService.addSession(credentials.accountId, loggedIn.accessToken, loggedIn.tokenType)
|
||||
bot.sendMessage(source, lang.loginAndPasswordAreOk)
|
||||
originator ! LoggedIn(forwardCommand, credentials.userId)
|
||||
originator ! LoggedIn(forwardCommand, credentials.userId, credentials.accountId)
|
||||
stay() using null
|
||||
}
|
||||
}
|
||||
@@ -119,8 +118,8 @@ object Login {
|
||||
|
||||
case class ForwardCommand(cmd: Command)
|
||||
|
||||
case class UserId(userId: Long, source: MessageSource)
|
||||
case class UserId(userId: Long, accountId: Long, source: MessageSource)
|
||||
|
||||
case class LoggedIn(forwardCommand: ForwardCommand, userId: Long)
|
||||
case class LoggedIn(forwardCommand: ForwardCommand, userId: Long, accountId: Long)
|
||||
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class Monitorings(val userId: UserId, bot: Bot, monitoringService: MonitoringSer
|
||||
|
||||
whenSafe(RequestData) {
|
||||
case Event(Next, _) =>
|
||||
val monitorings = monitoringService.getActiveMonitorings(userId.userId)
|
||||
val monitorings = monitoringService.getActiveMonitorings(userId.accountId)
|
||||
monitoringsPager ! Right[Throwable, Seq[Monitoring]](monitorings)
|
||||
goto(AwaitPage)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ package com.lbs.server.actor
|
||||
import akka.actor.{Actor, ActorRef, Cancellable, PoisonPill, Props}
|
||||
import com.lbs.bot.model.{Command, MessageSource}
|
||||
import com.lbs.common.Logger
|
||||
import com.lbs.server.actor.Account.SwitchUser
|
||||
import com.lbs.server.actor.Router.DestroyChat
|
||||
|
||||
import scala.collection.mutable
|
||||
@@ -47,20 +48,34 @@ class Router(authActorFactory: ByMessageSourceActorFactory) extends Actor with L
|
||||
scheduleIdleChatDestroyer(source)
|
||||
val chat = chats.get(source) match {
|
||||
case Some(actor) => actor
|
||||
case None =>
|
||||
val actor = authActorFactory(source)
|
||||
chats += source -> actor
|
||||
actor
|
||||
case None => addNewChatActor(source)
|
||||
}
|
||||
chat ! cmd
|
||||
case DestroyChat(source) =>
|
||||
destroyChat(source)
|
||||
case SwitchUser(userId) =>
|
||||
switchUser(userId)
|
||||
case what => LOG.info(s"Unknown message: $what")
|
||||
}
|
||||
|
||||
private def addNewChatActor(source: MessageSource): ActorRef = {
|
||||
val actor = authActorFactory(source)
|
||||
chats += source -> actor
|
||||
actor
|
||||
}
|
||||
|
||||
private def destroyChat(source: MessageSource): Unit = {
|
||||
LOG.info(s"Destroying chat for $source due to $idleTimeout inactivity")
|
||||
timers.remove(source)
|
||||
removeChat(source)
|
||||
}
|
||||
|
||||
private def switchUser(userId: Login.UserId): Unit = {
|
||||
removeChat(userId.source)
|
||||
addNewChatActor(userId.source)
|
||||
}
|
||||
|
||||
private def removeChat(source: MessageSource): Unit = {
|
||||
chats.remove(source).foreach(_ ! PoisonPill)
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class Visits(val userId: UserId, bot: Bot, apiService: ApiService, val localizat
|
||||
|
||||
whenSafe(RequestData) {
|
||||
case Event(Next, _) =>
|
||||
val visits = apiService.reservedVisits(userId.userId)
|
||||
val visits = apiService.reservedVisits(userId.accountId)
|
||||
reservedVisitsPager ! visits
|
||||
goto(AwaitPage)
|
||||
}
|
||||
@@ -65,7 +65,7 @@ class Visits(val userId: UserId, bot: Bot, apiService: ApiService, val localizat
|
||||
bot.sendMessage(userId.source, lang.appointmentWasNotCancelled)
|
||||
goto(RequestData)
|
||||
case Event(Command(_, _, Some(Tags.Yes)), visit: ReservedVisit) =>
|
||||
apiService.deleteReservation(userId.userId, visit.reservationId) match {
|
||||
apiService.deleteReservation(userId.accountId, visit.reservationId) match {
|
||||
case Left(ex) => bot.sendMessage(userId.source, lang.unableToCancelUpcomingVisit(ex.getMessage))
|
||||
case Right(r) => bot.sendMessage(userId.source, lang.appointmentHasBeenCancelled)
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server.lang
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
@@ -353,4 +353,13 @@ object En extends Lang {
|
||||
override def allDay: String = "All day"
|
||||
|
||||
override def preferredTimeIs(time: Int): String = s"⏱ Preferred time is ${timeOfDay(time)}"
|
||||
|
||||
override def deleteAccount: String = "➖ Delete account"
|
||||
|
||||
override def addAccount: String = "➕ Add account"
|
||||
|
||||
override def accountSwitched(username: String): String =
|
||||
s"✅ Account has been switched to <b>$username</b>"
|
||||
|
||||
override def pleaseChooseAccount: String = "<b>➡</b> Please choose an <b>action</b> or select <b>account</b>"
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server.lang
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
@@ -233,4 +233,12 @@ trait Lang {
|
||||
def allDay: String
|
||||
|
||||
def preferredTimeIs(time: Int): String
|
||||
|
||||
def deleteAccount: String
|
||||
|
||||
def addAccount: String
|
||||
|
||||
def pleaseChooseAccount: String
|
||||
|
||||
def accountSwitched(username: String): String
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server.lang
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
@@ -352,4 +352,13 @@ object Ua extends Lang {
|
||||
override def allDay: String = "Весь день"
|
||||
|
||||
override def preferredTimeIs(time: Int): String = s"⏱ Бажаний час ${timeOfDay(time)}"
|
||||
|
||||
override def deleteAccount: String = "➖ Видалити акаунт"
|
||||
|
||||
override def addAccount: String = "➕ Додати акаунт"
|
||||
|
||||
override def accountSwitched(username: String): String =
|
||||
s"✅ Аккаунт було переключено на <b>$username</b>"
|
||||
|
||||
override def pleaseChooseAccount: String = "<b>➡</b> Будь ласка, оберіть <b>дію</b> або виберіть <b>акаунт</b>"
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server.repository
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
import com.lbs.server.repository.model.{Bug, CityHistory, ClinicHistory, Credentials, DoctorHistory, JLong, Monitoring, ServiceHistory, Settings, Source}
|
||||
import com.lbs.server.repository.model.{Bug, CityHistory, ClinicHistory, Credentials, DoctorHistory, JLong, Monitoring, ServiceHistory, Settings, Source, SystemUser}
|
||||
import javax.persistence.EntityManager
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Repository
|
||||
@@ -37,48 +37,48 @@ class DataRepository(@Autowired em: EntityManager) {
|
||||
|
||||
private val maxHistory = 2
|
||||
|
||||
def getCityHistory(userId: Long): Seq[CityHistory] = {
|
||||
def getCityHistory(accountId: Long): Seq[CityHistory] = {
|
||||
em.createQuery(
|
||||
"""select city from CityHistory city where city.recordId in
|
||||
| (select max(c.recordId) from CityHistory c where c.userId = :userId group by c.name order by MAX(c.time) desc)
|
||||
| (select max(c.recordId) from CityHistory c where c.accountId = :accountId group by c.name order by MAX(c.time) desc)
|
||||
| order by city.time desc""".stripMargin, classOf[CityHistory])
|
||||
.setParameter("userId", userId)
|
||||
.setParameter("accountId", accountId)
|
||||
.setMaxResults(maxHistory)
|
||||
.getResultList.asScala
|
||||
}
|
||||
|
||||
def getClinicHistory(userId: Long, cityId: Long): Seq[ClinicHistory] = {
|
||||
def getClinicHistory(accountId: Long, cityId: Long): Seq[ClinicHistory] = {
|
||||
em.createQuery(
|
||||
"""select clinic from ClinicHistory clinic where clinic.recordId in
|
||||
| (select max(c.recordId) from ClinicHistory c where c.userId = :userId and c.cityId = :cityId group by c.name order by MAX(c.time) desc)
|
||||
| (select max(c.recordId) from ClinicHistory c where c.accountId = :accountId and c.cityId = :cityId group by c.name order by MAX(c.time) desc)
|
||||
| order by clinic.time desc""".stripMargin, classOf[ClinicHistory])
|
||||
.setParameter("userId", userId)
|
||||
.setParameter("accountId", accountId)
|
||||
.setParameter("cityId", cityId)
|
||||
.setMaxResults(maxHistory)
|
||||
.getResultList.asScala
|
||||
}
|
||||
|
||||
def getServiceHistory(userId: Long, cityId: Long, clinicId: Option[Long]): Seq[ServiceHistory] = {
|
||||
def getServiceHistory(accountId: Long, cityId: Long, clinicId: Option[Long]): Seq[ServiceHistory] = {
|
||||
val query = em.createQuery(
|
||||
s"""select service from ServiceHistory service where service.recordId in
|
||||
| (select max(s.recordId) from ServiceHistory s where s.userId = :userId and s.cityId = :cityId
|
||||
| (select max(s.recordId) from ServiceHistory s where s.accountId = :accountId and s.cityId = :cityId
|
||||
| and s.clinicId ${clinicId.map(_ => "= :clinicId").getOrElse("IS NULL")} group by s.name order by MAX(s.time) desc)
|
||||
| order by service.time desc""".stripMargin, classOf[ServiceHistory])
|
||||
.setParameter("userId", userId)
|
||||
.setParameter("accountId", accountId)
|
||||
.setParameter("cityId", cityId)
|
||||
.setMaxResults(maxHistory)
|
||||
|
||||
clinicId.map(id => query.setParameter("clinicId", id)).getOrElse(query).getResultList.asScala
|
||||
}
|
||||
|
||||
def getDoctorHistory(userId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): Seq[DoctorHistory] = {
|
||||
def getDoctorHistory(accountId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): Seq[DoctorHistory] = {
|
||||
val query = em.createQuery(
|
||||
s"""select doctor from DoctorHistory doctor where doctor.recordId in
|
||||
| (select max(d.recordId) from DoctorHistory d where d.userId = :userId
|
||||
| (select max(d.recordId) from DoctorHistory d where d.accountId = :accountId
|
||||
| and d.cityId = :cityId and d.clinicId ${clinicId.map(_ => "= :clinicId").getOrElse("IS NULL")}
|
||||
| and d.serviceId = :serviceId group by d.name order by MAX(d.time) desc)
|
||||
| order by doctor.time desc""".stripMargin, classOf[DoctorHistory])
|
||||
.setParameter("userId", userId)
|
||||
.setParameter("accountId", accountId)
|
||||
.setParameter("cityId", cityId)
|
||||
.setParameter("serviceId", serviceId)
|
||||
.setMaxResults(maxHistory)
|
||||
@@ -86,10 +86,10 @@ class DataRepository(@Autowired em: EntityManager) {
|
||||
clinicId.map(id => query.setParameter("clinicId", id)).getOrElse(query).getResultList.asScala
|
||||
}
|
||||
|
||||
def findCredentials(userId: Long): Option[Credentials] = {
|
||||
def findCredentials(accountId: Long): Option[Credentials] = {
|
||||
em.createQuery(
|
||||
"select credentials from Credentials credentials where credentials.userId = :userId", classOf[Credentials])
|
||||
.setParameter("userId", userId)
|
||||
"select credentials from Credentials credentials where credentials.accountId = :accountId", classOf[Credentials])
|
||||
.setParameter("accountId", accountId)
|
||||
.getResultList.asScala.headOption
|
||||
}
|
||||
|
||||
@@ -107,29 +107,29 @@ class DataRepository(@Autowired em: EntityManager) {
|
||||
.getResultList.asScala
|
||||
}
|
||||
|
||||
def getActiveMonitoringsCount(userId: Long): JLong = {
|
||||
def getActiveMonitoringsCount(accountId: Long): JLong = {
|
||||
em.createQuery(
|
||||
"""select count(monitoring) from Monitoring monitoring where monitoring.active = true
|
||||
| and monitoring.userId = :userId""".stripMargin, classOf[JLong])
|
||||
.setParameter("userId", userId)
|
||||
| and monitoring.accountId = :accountId""".stripMargin, classOf[JLong])
|
||||
.setParameter("accountId", accountId)
|
||||
.getSingleResult
|
||||
}
|
||||
|
||||
def getActiveMonitorings(userId: Long): Seq[Monitoring] = {
|
||||
def getActiveMonitorings(accountId: Long): Seq[Monitoring] = {
|
||||
em.createQuery(
|
||||
"""select monitoring from Monitoring monitoring where monitoring.active = true
|
||||
| and monitoring.userId = :userId order by monitoring.dateTo asc""".stripMargin, classOf[Monitoring])
|
||||
.setParameter("userId", userId)
|
||||
| and monitoring.accountId = :accountId order by monitoring.dateTo asc""".stripMargin, classOf[Monitoring])
|
||||
.setParameter("accountId", accountId)
|
||||
.getResultList.asScala
|
||||
}
|
||||
|
||||
def findActiveMonitoring(userId: Long, cityId: Long, serviceId: Long): Option[Monitoring] = {
|
||||
def findActiveMonitoring(accountId: Long, cityId: Long, serviceId: Long): Option[Monitoring] = {
|
||||
em.createQuery(
|
||||
"""select monitoring from Monitoring monitoring where monitoring.active = true
|
||||
| and monitoring.userId = :userId
|
||||
| and monitoring.accountId = :accountId
|
||||
| and monitoring.cityId = :cityId
|
||||
| and monitoring.serviceId = :serviceId""".stripMargin, classOf[Monitoring])
|
||||
.setParameter("userId", userId)
|
||||
.setParameter("accountId", accountId)
|
||||
.setParameter("cityId", cityId)
|
||||
.setParameter("serviceId", serviceId)
|
||||
.getResultList.asScala.headOption
|
||||
@@ -143,11 +143,11 @@ class DataRepository(@Autowired em: EntityManager) {
|
||||
.getResultList.asScala
|
||||
}
|
||||
|
||||
def findMonitoring(userId: Long, monitoringId: Long): Option[Monitoring] = {
|
||||
def findMonitoring(accountId: Long, monitoringId: Long): Option[Monitoring] = {
|
||||
em.createQuery(
|
||||
"""select monitoring from Monitoring monitoring where monitoring.userId = :userId
|
||||
"""select monitoring from Monitoring monitoring where monitoring.accountId = :accountId
|
||||
| and monitoring.recordId = :monitoringId""".stripMargin, classOf[Monitoring])
|
||||
.setParameter("userId", userId)
|
||||
.setParameter("accountId", accountId)
|
||||
.setParameter("monitoringId", monitoringId)
|
||||
.getResultList.asScala.headOption
|
||||
}
|
||||
@@ -186,6 +186,46 @@ class DataRepository(@Autowired em: EntityManager) {
|
||||
.getResultList.asScala.headOption
|
||||
}
|
||||
|
||||
def findUserIdBySource(chatId: String, sourceSystemId: Long): Option[JLong] = {
|
||||
em.createQuery(
|
||||
"select source.userId from Source source where source.chatId = :chatId" +
|
||||
" and source.sourceSystemId = :sourceSystemId", classOf[JLong])
|
||||
.setParameter("chatId", chatId)
|
||||
.setParameter("sourceSystemId", sourceSystemId)
|
||||
.getResultList.asScala.headOption
|
||||
}
|
||||
|
||||
def findAccountId(userId: Long): Option[JLong] = {
|
||||
em.createQuery(
|
||||
"select systemUser.activeAccountId from SystemUser systemUser where systemUser.recordId = :recordId", classOf[JLong])
|
||||
.setParameter("recordId", userId)
|
||||
.getResultList.asScala.headOption
|
||||
}
|
||||
|
||||
def findUser(userId: Long): Option[SystemUser] = {
|
||||
em.createQuery(
|
||||
"select systemUser from SystemUser systemUser where systemUser.recordId = :recordId", classOf[SystemUser])
|
||||
.setParameter("recordId", userId)
|
||||
.getResultList.asScala.headOption
|
||||
}
|
||||
|
||||
def getUserCredentials(userId: Long): Seq[Credentials] = {
|
||||
em.createQuery(
|
||||
"select credentials from Credentials credentials where credentials.userId = :userId", classOf[Credentials])
|
||||
.setParameter("userId", userId)
|
||||
.getResultList.asScala
|
||||
}
|
||||
|
||||
def findUserCredentialsByUserIdAndAccountId(userId: Long, accountId: Long): Option[Credentials] = {
|
||||
em.createQuery(
|
||||
"""select credentials from Credentials credentials where credentials.userId = :userId
|
||||
| and credentials.accountId = :accountId
|
||||
""".stripMargin, classOf[Credentials])
|
||||
.setParameter("userId", userId)
|
||||
.setParameter("accountId", accountId)
|
||||
.getResultList.asScala.headOption
|
||||
}
|
||||
|
||||
def saveEntity[T](entity: T): T = {
|
||||
em.merge(entity)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
//just a sequence generator
|
||||
class Account extends RecordId
|
||||
@@ -41,8 +41,8 @@ class CityHistory extends History with RecordId {
|
||||
var name: String = _
|
||||
|
||||
@BeanProperty
|
||||
@Column(name = "user_id", nullable = false)
|
||||
var userId: JLong = _
|
||||
@Column(name = "account_id", nullable = false)
|
||||
var accountId: JLong = _
|
||||
|
||||
@BeanProperty
|
||||
@Column(nullable = false)
|
||||
@@ -50,9 +50,9 @@ class CityHistory extends History with RecordId {
|
||||
}
|
||||
|
||||
object CityHistory {
|
||||
def apply(userId: Long, id: Long, name: String, time: ZonedDateTime): CityHistory = {
|
||||
def apply(accountId: Long, id: Long, name: String, time: ZonedDateTime): CityHistory = {
|
||||
val city = new CityHistory
|
||||
city.userId = userId
|
||||
city.accountId = accountId
|
||||
city.id = id
|
||||
city.name = name
|
||||
city.time = time
|
||||
|
||||
@@ -41,8 +41,8 @@ class ClinicHistory extends History with RecordId {
|
||||
var name: String = _
|
||||
|
||||
@BeanProperty
|
||||
@Column(name = "user_id", nullable = false)
|
||||
var userId: JLong = _
|
||||
@Column(name = "account_id", nullable = false)
|
||||
var accountId: JLong = _
|
||||
|
||||
@BeanProperty
|
||||
@Column(name = "city_id", nullable = false)
|
||||
@@ -54,9 +54,9 @@ class ClinicHistory extends History with RecordId {
|
||||
}
|
||||
|
||||
object ClinicHistory {
|
||||
def apply(userId: Long, id: Long, name: String, cityId: Long, time: ZonedDateTime): ClinicHistory = {
|
||||
def apply(accountId: Long, id: Long, name: String, cityId: Long, time: ZonedDateTime): ClinicHistory = {
|
||||
val clinic = new ClinicHistory
|
||||
clinic.userId = userId
|
||||
clinic.accountId = accountId
|
||||
clinic.id = id
|
||||
clinic.name = name
|
||||
clinic.time = time
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
@@ -29,12 +29,15 @@ import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
class Credentials {
|
||||
@Id
|
||||
class Credentials extends RecordId {
|
||||
@BeanProperty
|
||||
@Column(name = "user_id", nullable = false)
|
||||
var userId: JLong = _
|
||||
|
||||
@BeanProperty
|
||||
@Column(name = "account_id", nullable = false)
|
||||
var accountId: JLong = _
|
||||
|
||||
@BeanProperty
|
||||
@Column(nullable = false)
|
||||
var username: String = _
|
||||
@@ -45,9 +48,10 @@ class Credentials {
|
||||
}
|
||||
|
||||
object Credentials {
|
||||
def apply(userId: Long, username: String, password: String): Credentials = {
|
||||
def apply(userId: JLong, accountId: JLong, username: String, password: String): Credentials = {
|
||||
val credentials = new Credentials
|
||||
credentials.userId = userId
|
||||
credentials.accountId = accountId
|
||||
credentials.username = username
|
||||
credentials.password = password
|
||||
credentials
|
||||
|
||||
@@ -41,8 +41,8 @@ class DoctorHistory extends History with RecordId {
|
||||
var name: String = _
|
||||
|
||||
@BeanProperty
|
||||
@Column(name = "user_id", nullable = false)
|
||||
var userId: JLong = _
|
||||
@Column(name = "account_id", nullable = false)
|
||||
var accountId: JLong = _
|
||||
|
||||
@BeanProperty
|
||||
@Column(name = "city_id", nullable = false)
|
||||
@@ -62,9 +62,9 @@ class DoctorHistory extends History with RecordId {
|
||||
}
|
||||
|
||||
object DoctorHistory {
|
||||
def apply(userId: Long, id: Long, name: String, cityId: Long, clinicId: Option[Long], serviceId: Long, time: ZonedDateTime): DoctorHistory = {
|
||||
def apply(accountId: Long, id: Long, name: String, cityId: Long, clinicId: Option[Long], serviceId: Long, time: ZonedDateTime): DoctorHistory = {
|
||||
val doctor = new DoctorHistory
|
||||
doctor.userId = userId
|
||||
doctor.accountId = accountId
|
||||
doctor.id = id
|
||||
doctor.name = name
|
||||
doctor.time = time
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
@@ -36,6 +36,9 @@ class Monitoring extends RecordId {
|
||||
@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)
|
||||
@@ -103,12 +106,13 @@ class Monitoring extends RecordId {
|
||||
}
|
||||
|
||||
object Monitoring {
|
||||
def apply(userId: Long, chatId: String, sourceSystemId: Long, cityId: Long, cityName: String, clinicId: Option[Long], clinicName: String,
|
||||
def apply(userId: Long, accountId: Long, chatId: String, sourceSystemId: Long, cityId: Long, cityName: String, clinicId: Option[Long], clinicName: String,
|
||||
serviceId: Long, serviceName: String, doctorId: Option[Long], doctorName: String, dateFrom: ZonedDateTime,
|
||||
dateTo: ZonedDateTime, autobook: Boolean = false, created: ZonedDateTime = ZonedDateTime.now(), timeOfDay: Int,
|
||||
active: Boolean = true): Monitoring = {
|
||||
val monitoring = new Monitoring
|
||||
monitoring.userId = userId
|
||||
monitoring.accountId = accountId
|
||||
monitoring.chatId = chatId
|
||||
monitoring.sourceSystemId = sourceSystemId
|
||||
monitoring.cityId = cityId
|
||||
|
||||
@@ -41,8 +41,8 @@ class ServiceHistory extends History with RecordId {
|
||||
var name: String = _
|
||||
|
||||
@BeanProperty
|
||||
@Column(name = "userId_id", nullable = false)
|
||||
var userId: JLong = _
|
||||
@Column(name = "account_id", nullable = false)
|
||||
var accountId: JLong = _
|
||||
|
||||
@BeanProperty
|
||||
@Column(name = "city_id", nullable = false)
|
||||
@@ -58,9 +58,9 @@ class ServiceHistory extends History with RecordId {
|
||||
}
|
||||
|
||||
object ServiceHistory {
|
||||
def apply(userId: Long, id: Long, name: String, cityId: Long, clinicId: Option[Long], time: ZonedDateTime): ServiceHistory = {
|
||||
def apply(accountId: Long, id: Long, name: String, cityId: Long, clinicId: Option[Long], time: ZonedDateTime): ServiceHistory = {
|
||||
val service = new ServiceHistory
|
||||
service.userId = userId
|
||||
service.accountId = accountId
|
||||
service.id = id
|
||||
service.name = name
|
||||
service.time = time
|
||||
|
||||
@@ -1,34 +1,44 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
class SystemUser extends RecordId
|
||||
|
||||
|
||||
|
||||
class SystemUser extends RecordId {
|
||||
@BeanProperty
|
||||
@Column(name = "active_account_id", nullable = false)
|
||||
var activeAccountId: JLong = _
|
||||
}
|
||||
|
||||
object SystemUser {
|
||||
def apply(activeAccountId: Long): SystemUser = {
|
||||
val user = new SystemUser
|
||||
user.activeAccountId = activeAccountId
|
||||
user
|
||||
}
|
||||
}
|
||||
@@ -40,53 +40,53 @@ class ApiService extends SessionSupport {
|
||||
@Autowired
|
||||
private var textEncryptor: TextEncryptor = _
|
||||
|
||||
def getAllCities(userId: Long): Either[Throwable, List[IdName]] =
|
||||
withSession(userId) { session =>
|
||||
def getAllCities(accountId: Long): Either[Throwable, List[IdName]] =
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.reservationFilter(session.accessToken, session.tokenType).map(_.cities)
|
||||
}
|
||||
|
||||
def getAllClinics(userId: Long, cityId: Long): Either[Throwable, List[IdName]] =
|
||||
withSession(userId) { session =>
|
||||
def getAllClinics(accountId: Long, cityId: Long): Either[Throwable, List[IdName]] =
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.reservationFilter(session.accessToken,
|
||||
session.tokenType, cityId = Some(cityId)).map(_.clinics)
|
||||
}
|
||||
|
||||
def getAllServices(userId: Long, cityId: Long, clinicId: Option[Long]): Either[Throwable, List[IdName]] =
|
||||
withSession(userId) { session =>
|
||||
def getAllServices(accountId: Long, cityId: Long, clinicId: Option[Long]): Either[Throwable, List[IdName]] =
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.reservationFilter(session.accessToken,
|
||||
session.tokenType, cityId = Some(cityId),
|
||||
clinicId = clinicId).map(_.services)
|
||||
}
|
||||
|
||||
def getAllDoctors(userId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): Either[Throwable, List[IdName]] =
|
||||
withSession(userId) { session =>
|
||||
def getAllDoctors(accountId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): Either[Throwable, List[IdName]] =
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.reservationFilter(session.accessToken,
|
||||
session.tokenType, cityId = Some(cityId),
|
||||
clinicId = clinicId, serviceId = Some(serviceId)).map(_.doctors)
|
||||
}
|
||||
|
||||
def getDefaultPayer(userId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): Either[Throwable, Option[IdName]] =
|
||||
withSession(userId) { session =>
|
||||
def getDefaultPayer(accountId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): Either[Throwable, Option[IdName]] =
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.reservationFilter(session.accessToken,
|
||||
session.tokenType, cityId = Some(cityId),
|
||||
clinicId = clinicId, serviceId = Some(serviceId)).map(_.defaultPayer)
|
||||
}
|
||||
|
||||
def getAvailableTerms(userId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long, doctorId: Option[Long],
|
||||
def getAvailableTerms(accountId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long, doctorId: Option[Long],
|
||||
fromDate: ZonedDateTime = ZonedDateTime.now(), toDate: Option[ZonedDateTime] = None, timeOfDay: Int = 0,
|
||||
languageId: Long = 10, findFirstFreeTerm: Boolean = false): Either[Throwable, List[AvailableVisitsTermPresentation]] =
|
||||
getDefaultPayer(userId, cityId, clinicId, serviceId).flatMap {
|
||||
getDefaultPayer(accountId, cityId, clinicId, serviceId).flatMap {
|
||||
case Some(payerId) =>
|
||||
withSession(userId) { session =>
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.availableTerms(session.accessToken, session.tokenType, payerId.id, cityId, clinicId, serviceId, doctorId,
|
||||
fromDate, toDate, timeOfDay, languageId, findFirstFreeTerm).map(_.availableVisitsTermPresentation)
|
||||
}
|
||||
case None => sys.error(s"Can't determine payer id by user: $userId, city: $cityId, clinic: $clinicId, service: $serviceId")
|
||||
case None => sys.error(s"Can't determine payer id by user: $accountId, city: $cityId, clinic: $clinicId, service: $serviceId")
|
||||
}
|
||||
|
||||
|
||||
def temporaryReservation(userId: Long, temporaryReservationRequest: TemporaryReservationRequest, valuationsRequest: ValuationsRequest): Either[Throwable, (TemporaryReservationResponse, ValuationsResponse)] =
|
||||
withSession(userId) { session =>
|
||||
def temporaryReservation(accountId: Long, temporaryReservationRequest: TemporaryReservationRequest, valuationsRequest: ValuationsRequest): Either[Throwable, (TemporaryReservationResponse, ValuationsResponse)] =
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.temporaryReservation(session.accessToken, session.tokenType, temporaryReservationRequest) match {
|
||||
case Left(ex) => Left(ex)
|
||||
case Right(temporaryReservation) =>
|
||||
@@ -97,30 +97,30 @@ class ApiService extends SessionSupport {
|
||||
}
|
||||
}
|
||||
|
||||
def deleteTemporaryReservation(userId: Long, temporaryReservationId: Long): Either[Throwable, HttpResponse[String]] =
|
||||
withSession(userId) { session =>
|
||||
def deleteTemporaryReservation(accountId: Long, temporaryReservationId: Long): Either[Throwable, HttpResponse[String]] =
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.deleteTemporaryReservation(session.accessToken, session.tokenType, temporaryReservationId)
|
||||
}
|
||||
|
||||
def reservation(userId: Long, reservationRequest: ReservationRequest): Either[Throwable, ReservationResponse] =
|
||||
withSession(userId) { session =>
|
||||
def reservation(accountId: Long, reservationRequest: ReservationRequest): Either[Throwable, ReservationResponse] =
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.reservation(session.accessToken, session.tokenType, reservationRequest)
|
||||
}
|
||||
|
||||
def visitsHistory(userId: Long, fromDate: ZonedDateTime = ZonedDateTime.now().minusYears(1),
|
||||
def visitsHistory(accountId: Long, fromDate: ZonedDateTime = ZonedDateTime.now().minusYears(1),
|
||||
toDate: ZonedDateTime = ZonedDateTime.now(), page: Int = 1, pageSize: Int = 100): Either[Throwable, List[HistoricVisit]] =
|
||||
withSession(userId) { session =>
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.visitsHistory(session.accessToken, session.tokenType, fromDate, toDate, page, pageSize).map(_.historicVisits)
|
||||
}
|
||||
|
||||
def reservedVisits(userId: Long, fromDate: ZonedDateTime = ZonedDateTime.now(),
|
||||
def reservedVisits(accountId: Long, fromDate: ZonedDateTime = ZonedDateTime.now(),
|
||||
toDate: ZonedDateTime = ZonedDateTime.now().plusMonths(3)): Either[Throwable, List[ReservedVisit]] =
|
||||
withSession(userId) { session =>
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.reservedVisits(session.accessToken, session.tokenType, fromDate, toDate).map(_.reservedVisits)
|
||||
}
|
||||
|
||||
def deleteReservation(userId: Long, reservationId: Long): Either[Throwable, HttpResponse[String]] =
|
||||
withSession(userId) { session =>
|
||||
def deleteReservation(accountId: Long, reservationId: Long): Either[Throwable, HttpResponse[String]] =
|
||||
withSession(accountId) { session =>
|
||||
LuxmedApi.deleteReservation(session.accessToken, session.tokenType, reservationId)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server.service
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
@@ -39,10 +39,10 @@ import org.springframework.stereotype.Service
|
||||
class DataService {
|
||||
|
||||
@Autowired
|
||||
private var dataRepository: DataRepository = _
|
||||
private[service] var dataRepository: DataRepository = _
|
||||
|
||||
def getLatestCities(userId: Long): Seq[IdName] = {
|
||||
dataRepository.getCityHistory(userId).mapTo[IdName]
|
||||
def getLatestCities(accountId: Long): Seq[IdName] = {
|
||||
dataRepository.getCityHistory(accountId).mapTo[IdName]
|
||||
}
|
||||
|
||||
def getLatestClinicsByCityId(userId: Long, cityId: Long): Seq[IdName] = {
|
||||
@@ -57,8 +57,8 @@ class DataService {
|
||||
dataRepository.getDoctorHistory(userId, cityId, clinicId, serviceId).mapTo[IdName]
|
||||
}
|
||||
|
||||
def getCredentials(userId: Long): Option[Credentials] = {
|
||||
dataRepository.findCredentials(userId)
|
||||
def getCredentials(accountId: Long): Option[Credentials] = {
|
||||
dataRepository.findCredentials(accountId)
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -79,38 +79,56 @@ class DataService {
|
||||
dataRepository.getActiveMonitorings
|
||||
}
|
||||
|
||||
def getActiveMonitoringsCount(userId: Long): Long = {
|
||||
dataRepository.getActiveMonitoringsCount(userId)
|
||||
def getActiveMonitoringsCount(accountId: Long): Long = {
|
||||
dataRepository.getActiveMonitoringsCount(accountId)
|
||||
}
|
||||
|
||||
def getActiveMonitorings(userId: Long): Seq[Monitoring] = {
|
||||
dataRepository.getActiveMonitorings(userId)
|
||||
def getActiveMonitorings(accountId: Long): Seq[Monitoring] = {
|
||||
dataRepository.getActiveMonitorings(accountId)
|
||||
}
|
||||
|
||||
def findActiveMonitoring(userId: Long, cityId: Long, serviceId: Long): Option[Monitoring] = {
|
||||
dataRepository.findActiveMonitoring(userId, cityId, serviceId)
|
||||
def findActiveMonitoring(accountId: Long, cityId: Long, serviceId: Long): Option[Monitoring] = {
|
||||
dataRepository.findActiveMonitoring(accountId, cityId, serviceId)
|
||||
}
|
||||
|
||||
def getActiveMonitoringsSince(since: ZonedDateTime): Seq[Monitoring] = {
|
||||
dataRepository.getActiveMonitoringsSince(since)
|
||||
}
|
||||
|
||||
def findMonitoring(userId: Long, monitoringId: Long): Option[Monitoring] = {
|
||||
dataRepository.findMonitoring(userId, monitoringId)
|
||||
def findMonitoring(accountId: Long, monitoringId: Long): Option[Monitoring] = {
|
||||
dataRepository.findMonitoring(accountId, monitoringId)
|
||||
}
|
||||
|
||||
def findSettings(userId: Long): Option[Settings] = {
|
||||
dataRepository.findSettings(userId)
|
||||
}
|
||||
|
||||
def findUserIdBySource(source: MessageSource): Option[Long] = {
|
||||
dataRepository.findUserId(source.chatId, source.sourceSystem.id).map(_.toLong)
|
||||
def findUserAndAccountIdBySource(source: MessageSource): Option[(Long, Long)] = {
|
||||
val userIdMaybe = dataRepository.findUserId(source.chatId, source.sourceSystem.id).map(_.toLong)
|
||||
userIdMaybe.flatMap(userId => dataRepository.findAccountId(userId).map(_.toLong).map(accountId => userId -> accountId))
|
||||
}
|
||||
|
||||
def findCredentialsByUsername(username: String): Option[Credentials] = {
|
||||
dataRepository.findCredentialsByUsername(username)
|
||||
}
|
||||
|
||||
def getUserCredentials(userId: Long): Seq[Credentials] = {
|
||||
dataRepository.getUserCredentials(userId)
|
||||
}
|
||||
|
||||
def findUserCredentialsByAccountId(userId: Long, accountId: Long): Option[Credentials] = {
|
||||
dataRepository.findUserCredentialsByUserIdAndAccountId(userId, accountId)
|
||||
}
|
||||
|
||||
def findUser(userId: Long): Option[SystemUser] = {
|
||||
dataRepository.findUser(userId)
|
||||
}
|
||||
|
||||
@Transactional
|
||||
def saveUser(user: SystemUser): SystemUser = {
|
||||
dataRepository.saveEntity(user)
|
||||
}
|
||||
|
||||
@Transactional
|
||||
def saveSettings(settings: Settings): Settings = {
|
||||
dataRepository.saveEntity(settings)
|
||||
@@ -128,36 +146,63 @@ class DataService {
|
||||
val src = Source(source.chatId, source.sourceSystem.id, credentials.userId)
|
||||
dataRepository.saveEntity(src)
|
||||
}
|
||||
val userMaybe = dataRepository.findUser(credentials.userId)
|
||||
userMaybe match {
|
||||
case Some(user) =>
|
||||
user.activeAccountId = credentials.accountId
|
||||
dataRepository.saveEntity(user)
|
||||
case None => sys.error(s"Strange, but user [#${credentials.userId}] not found")
|
||||
}
|
||||
credentials.username = username
|
||||
credentials.password = password
|
||||
dataRepository.saveEntity(credentials)
|
||||
case None => //new user
|
||||
val user = dataRepository.saveEntity(new SystemUser)
|
||||
val src = Source(source.chatId, source.sourceSystem.id, user.recordId)
|
||||
dataRepository.saveEntity(src)
|
||||
val credentials = Credentials(user.recordId, username, password)
|
||||
dataRepository.saveEntity(credentials)
|
||||
case None => //new user or new account?
|
||||
val userMaybe = dataRepository.findUserIdBySource(source.chatId, source.sourceSystem.id).flatMap {
|
||||
userId => dataRepository.findUser(userId)
|
||||
}
|
||||
userMaybe match {
|
||||
case Some(user) => //user already exists, this is just the new credentials
|
||||
val account = dataRepository.saveEntity(new Account)
|
||||
user.activeAccountId = account.recordId
|
||||
dataRepository.saveEntity(user)
|
||||
val sourceMaybe = dataRepository.findSource(source.chatId, source.sourceSystem.id, user.recordId)
|
||||
sourceMaybe match {
|
||||
case Some(_) => //source already exists. Just save credentials
|
||||
case None => //add new source
|
||||
val src = Source(source.chatId, source.sourceSystem.id, user.recordId)
|
||||
dataRepository.saveEntity(src)
|
||||
}
|
||||
val credentials = Credentials(user.recordId, account.recordId, username, password)
|
||||
dataRepository.saveEntity(credentials)
|
||||
case None => //everything is new
|
||||
val account = dataRepository.saveEntity(new Account)
|
||||
val user = dataRepository.saveEntity(SystemUser(account.recordId))
|
||||
val src = Source(source.chatId, source.sourceSystem.id, user.recordId)
|
||||
dataRepository.saveEntity(src)
|
||||
val credentials = Credentials(user.recordId, account.recordId, username, password)
|
||||
dataRepository.saveEntity(credentials)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
def storeAppointment(userId: Long, bookingData: BookingData): Unit = {
|
||||
def storeAppointment(accountId: Long, bookingData: BookingData): Unit = {
|
||||
val time = ZonedDateTime.now()
|
||||
val cityId = bookingData.cityId
|
||||
val clinicId = bookingData.clinicId
|
||||
val serviceId = bookingData.serviceId
|
||||
val doctorId = bookingData.doctorId
|
||||
|
||||
val city = CityHistory(userId, cityId.id, cityId.name, time)
|
||||
val city = CityHistory(accountId, cityId.id, cityId.name, time)
|
||||
dataRepository.saveEntity(city)
|
||||
|
||||
val clinicMaybe = clinicId.optionalId.map(id => ClinicHistory(userId, id, clinicId.name, cityId.id, time))
|
||||
val clinicMaybe = clinicId.optionalId.map(id => ClinicHistory(accountId, id, clinicId.name, cityId.id, time))
|
||||
clinicMaybe.foreach(dataRepository.saveEntity)
|
||||
|
||||
val service = ServiceHistory(userId, serviceId.id, serviceId.name, cityId.id, clinicId.optionalId, time)
|
||||
val service = ServiceHistory(accountId, serviceId.id, serviceId.name, cityId.id, clinicId.optionalId, time)
|
||||
dataRepository.saveEntity(service)
|
||||
|
||||
val doctorMaybe = doctorId.optionalId.map(id => DoctorHistory(userId, id, doctorId.name, cityId.id, clinicId.optionalId, serviceId.id, time))
|
||||
val doctorMaybe = doctorId.optionalId.map(id => DoctorHistory(accountId, id, doctorId.name, cityId.id, clinicId.optionalId, serviceId.id, time))
|
||||
doctorMaybe.foreach(dataRepository.saveEntity)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ class MonitoringService extends Logger {
|
||||
private def monitor(monitoring: Monitoring): Unit = {
|
||||
LOG.debug(s"Looking for available terms. Monitoring [#${monitoring.recordId}]")
|
||||
val dateFrom = optimizeDateFrom(monitoring.dateFrom)
|
||||
val termsEither = apiService.getAvailableTerms(monitoring.userId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId,
|
||||
val termsEither = apiService.getAvailableTerms(monitoring.accountId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId,
|
||||
monitoring.doctorId, dateFrom, Some(monitoring.dateTo))
|
||||
termsEither match {
|
||||
case Right(terms) =>
|
||||
@@ -108,7 +108,7 @@ class MonitoringService extends Logger {
|
||||
case Left(ex: InvalidLoginOrPasswordException) =>
|
||||
LOG.error(s"User entered invalid name or password. Monitoring will be disabled", ex)
|
||||
bot.sendMessage(monitoring.source, lang(monitoring.userId).invalidLoginOrPassword)
|
||||
val activeUserMonitorings = dataService.getActiveMonitorings(monitoring.userId)
|
||||
val activeUserMonitorings = dataService.getActiveMonitorings(monitoring.accountId)
|
||||
activeUserMonitorings.foreach { m =>
|
||||
deactivateMonitoring(m.recordId)
|
||||
}
|
||||
@@ -172,12 +172,12 @@ class MonitoringService extends Logger {
|
||||
val temporaryReservationRequest = term.mapTo[TemporaryReservationRequest]
|
||||
val valuationsRequest = term.mapTo[ValuationsRequest]
|
||||
val reservationMaybe = for {
|
||||
okResponse <- apiService.temporaryReservation(monitoring.userId, temporaryReservationRequest, valuationsRequest)
|
||||
okResponse <- apiService.temporaryReservation(monitoring.accountId, temporaryReservationRequest, valuationsRequest)
|
||||
(temporaryReservation, valuations) = okResponse
|
||||
temporaryReservationId = temporaryReservation.id
|
||||
visitTermVariant = valuations.visitTermVariants.head
|
||||
reservationRequest = (temporaryReservationId, visitTermVariant, term).mapTo[ReservationRequest]
|
||||
reservation <- apiService.reservation(monitoring.userId, reservationRequest)
|
||||
reservation <- apiService.reservation(monitoring.accountId, reservationRequest)
|
||||
} yield reservation
|
||||
|
||||
reservationMaybe match {
|
||||
@@ -203,22 +203,22 @@ class MonitoringService extends Logger {
|
||||
}
|
||||
|
||||
def createMonitoring(monitoring: Monitoring): Monitoring = {
|
||||
val userMonitoringsCount = dataService.getActiveMonitoringsCount(monitoring.userId)
|
||||
val userMonitoringsCount = dataService.getActiveMonitoringsCount(monitoring.accountId)
|
||||
require(userMonitoringsCount + 1 <= 5, lang(monitoring.userId).maximumMonitoringsLimitExceeded)
|
||||
val activeMonitoring = dataService.findActiveMonitoring(monitoring.userId, monitoring.cityId, monitoring.serviceId)
|
||||
val activeMonitoring = dataService.findActiveMonitoring(monitoring.accountId, monitoring.cityId, monitoring.serviceId)
|
||||
require(activeMonitoring.isEmpty, lang(monitoring.userId).monitoringOfTheSameTypeExists)
|
||||
dataService.saveMonitoring(monitoring)
|
||||
}
|
||||
|
||||
def getActiveMonitorings(userId: Long): Seq[Monitoring] = {
|
||||
dataService.getActiveMonitorings(userId)
|
||||
def getActiveMonitorings(accountId: Long): Seq[Monitoring] = {
|
||||
dataService.getActiveMonitorings(accountId)
|
||||
}
|
||||
|
||||
def bookAppointmentByScheduleId(userId: Long, monitoringId: Long, scheduleId: Long, time: Long): Unit = {
|
||||
val monitoringMaybe = dataService.findMonitoring(userId, monitoringId)
|
||||
def bookAppointmentByScheduleId(accountId: Long, monitoringId: Long, scheduleId: Long, time: Long): Unit = {
|
||||
val monitoringMaybe = dataService.findMonitoring(accountId, monitoringId)
|
||||
monitoringMaybe match {
|
||||
case Some(monitoring) =>
|
||||
val termsEither = apiService.getAvailableTerms(monitoring.userId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId,
|
||||
val termsEither = apiService.getAvailableTerms(monitoring.accountId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId,
|
||||
monitoring.doctorId, monitoring.dateFrom, Some(monitoring.dateTo))
|
||||
termsEither match {
|
||||
case Right(terms) =>
|
||||
@@ -254,6 +254,7 @@ class MonitoringService extends Logger {
|
||||
val monitorings = dataService.getActiveMonitorings
|
||||
LOG.debug(s"Active monitorings found: ${monitorings.length}")
|
||||
initializeMonitorings(monitorings)
|
||||
disableOutdated()
|
||||
initializeDbChecker()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,26 +44,26 @@ trait SessionSupport {
|
||||
|
||||
private val lock = new ParametrizedLock[Long]
|
||||
|
||||
protected def withSession[T](userId: Long)(fn: Session => Either[Throwable, T]): Either[Throwable, T] =
|
||||
lock.obtainLock(userId).synchronized {
|
||||
protected def withSession[T](accountId: Long)(fn: Session => Either[Throwable, T]): Either[Throwable, T] =
|
||||
lock.obtainLock(accountId).synchronized {
|
||||
|
||||
def auth: Either[Throwable, Session] = {
|
||||
val credentialsMaybe = dataService.getCredentials(userId)
|
||||
val credentialsMaybe = dataService.getCredentials(accountId)
|
||||
credentialsMaybe match {
|
||||
case Some(credentials) =>
|
||||
val loginResponse = login(credentials.username, credentials.password)
|
||||
loginResponse.map(r => Session(r.accessToken, r.tokenType))
|
||||
case None => Left(UserNotFoundException(userId))
|
||||
case None => Left(UserNotFoundException(accountId))
|
||||
}
|
||||
}
|
||||
|
||||
def session: Either[Throwable, Session] = {
|
||||
sessions.get(userId) match {
|
||||
sessions.get(accountId) match {
|
||||
case Some(sess) => Right(sess)
|
||||
case None =>
|
||||
auth match {
|
||||
case Right(sess) =>
|
||||
sessions.put(userId, sess)
|
||||
sessions.put(accountId, sess)
|
||||
Right(sess)
|
||||
case left => left
|
||||
}
|
||||
@@ -74,8 +74,8 @@ trait SessionSupport {
|
||||
case Right(s) =>
|
||||
fn(s) match {
|
||||
case Left(ex) if ex.getMessage.contains("session has expired") =>
|
||||
Log.debug(s"The session for user [#$userId] has expired. Try to relogin")
|
||||
sessions.remove(userId)
|
||||
Log.debug(s"The session for account [#$accountId] has expired. Try to relogin")
|
||||
sessions.remove(accountId)
|
||||
session.flatMap(fn)
|
||||
case another =>
|
||||
Log.debug(s"Call to remote api function has completed with result:\n$another")
|
||||
@@ -85,8 +85,8 @@ trait SessionSupport {
|
||||
}
|
||||
}
|
||||
|
||||
def addSession(userId: Long, accessToken: String, tokenType: String): Unit =
|
||||
lock.obtainLock(userId).synchronized {
|
||||
sessions.put(userId, Session(accessToken, tokenType))
|
||||
def addSession(accountId: Long, accessToken: String, tokenType: String): Unit =
|
||||
lock.obtainLock(accountId).synchronized {
|
||||
sessions.put(accountId, Session(accessToken, tokenType))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2018 Yevhen Zadyra
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.lbs.server
|
||||
|
||||
import java.time.format.DateTimeFormatter
|
||||
@@ -49,6 +49,7 @@ package object util {
|
||||
val (userId, bookingData) = data.asInstanceOf[(UserId, BookingData)]
|
||||
Monitoring(
|
||||
userId = userId.userId,
|
||||
accountId = userId.accountId,
|
||||
chatId = userId.source.chatId,
|
||||
sourceSystemId = userId.source.sourceSystem.id,
|
||||
cityId = bookingData.cityId.id,
|
||||
|
||||
@@ -13,7 +13,7 @@ class AuthSpec extends AkkaTestKit {
|
||||
"An Auth actor " when {
|
||||
|
||||
val source = MessageSource(TelegramMessageSourceSystem, "1")
|
||||
val userId = UserId(1L, source)
|
||||
val userId = UserId(1L, 1L, source)
|
||||
|
||||
"user is unauthorized" must {
|
||||
val unauthorizedHelpActor = TestProbe()
|
||||
@@ -23,7 +23,7 @@ class AuthSpec extends AkkaTestKit {
|
||||
val loginActorFactory: ByMessageSourceWithOriginatorActorFactory = (_, _) => loginActor.ref
|
||||
val chatActorFactory: UserId => ActorRef = _ => chatActor.ref
|
||||
val dataService = mock(classOf[DataService])
|
||||
when(dataService.findUserIdBySource(source)).thenReturn(None)
|
||||
when(dataService.findUserAndAccountIdBySource(source)).thenReturn(None)
|
||||
val auth = system.actorOf(Auth.props(source, dataService, unauthorizedHelpFactory, loginActorFactory, chatActorFactory))
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ class AuthSpec extends AkkaTestKit {
|
||||
|
||||
"forward initial message to chat actor after the user has logged in" in {
|
||||
val cmd = Command(source, Message("1", Some("any")))
|
||||
val msg = LoggedIn(ForwardCommand(cmd), 1L)
|
||||
val msg = LoggedIn(ForwardCommand(cmd), 1L, 1L)
|
||||
auth ! msg
|
||||
chatActor.expectMsg(cmd)
|
||||
}
|
||||
@@ -79,7 +79,7 @@ class AuthSpec extends AkkaTestKit {
|
||||
val loginActorFactory: ByMessageSourceWithOriginatorActorFactory = (_, _) => loginActor.ref
|
||||
val chatActorFactory: UserId => ActorRef = _ => chatActor.ref
|
||||
val dataService = mock(classOf[DataService])
|
||||
when(dataService.findUserIdBySource(source)).thenReturn(Some(userId.userId))
|
||||
when(dataService.findUserAndAccountIdBySource(source)).thenReturn(Some(userId.userId, userId.accountId))
|
||||
|
||||
val auth = system.actorOf(Auth.props(source, dataService, unauthorizedHelpFactory, loginActorFactory, chatActorFactory))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user