diff --git a/server/src/main/scala/com/lbs/server/BootConfig.scala b/server/src/main/scala/com/lbs/server/BootConfig.scala index 71edf75..2cb729f 100644 --- a/server/src/main/scala/com/lbs/server/BootConfig.scala +++ b/server/src/main/scala/com/lbs/server/BootConfig.scala @@ -74,7 +74,7 @@ class BootConfig { @Bean def bookingActorFactory: ByUserIdActorFactory = userId => actorSystem.actorOf(Book.props(userId, bot, apiService, dataService, - monitoringService, localization, datePickerFactory, staticDataActorFactory, termsPagerActorFactory)) + monitoringService, localization, datePickerFactory, timePickerFactory, staticDataActorFactory, termsPagerActorFactory)) @Bean def unauthorizedHelpActorFactory: ByMessageSourceActorFactory = source => actorSystem.actorOf(UnauthorizedHelp.props(source, bot)) @@ -115,6 +115,10 @@ class BootConfig { def datePickerFactory: ByUserIdWithOriginatorActorFactory = (userId, originator) => actorSystem.actorOf(DatePicker.props(userId, bot, localization, originator)) + @Bean + def timePickerFactory: ByUserIdWithOriginatorActorFactory = (userId, originator) => + actorSystem.actorOf(TimePicker.props(userId, bot, localization, originator)) + @Bean def staticDataActorFactory: ByUserIdWithOriginatorActorFactory = (userId, originator) => actorSystem.actorOf(StaticData.props(userId, bot, localization, originator)) diff --git a/server/src/main/scala/com/lbs/server/actor/Book.scala b/server/src/main/scala/com/lbs/server/actor/Book.scala index 8ebbe9a..3e58ed2 100644 --- a/server/src/main/scala/com/lbs/server/actor/Book.scala +++ b/server/src/main/scala/com/lbs/server/actor/Book.scala @@ -23,7 +23,7 @@ */ package com.lbs.server.actor -import java.time.ZonedDateTime +import java.time.{LocalTime, ZonedDateTime} import akka.actor.{PoisonPill, Props} import com.lbs.api.json.model._ @@ -33,6 +33,7 @@ import com.lbs.server.actor.Book._ import com.lbs.server.actor.DatePicker.{DateFromMode, DateToMode} import com.lbs.server.actor.Login.UserId import com.lbs.server.actor.StaticData.StaticDataConfig +import com.lbs.server.actor.TimePicker.{TimeFromMode, TimeToMode} import com.lbs.server.actor.conversation.Conversation import com.lbs.server.actor.conversation.Conversation.{InitConversation, StartConversation} import com.lbs.server.lang.{Localizable, Localization} @@ -42,10 +43,11 @@ import com.lbs.server.util.MessageExtractors.CallbackCommand import com.lbs.server.util.ServerModelConverters._ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: DataService, monitoringService: MonitoringService, - val localization: Localization, datePickerActorFactory: ByUserIdWithOriginatorActorFactory, staticDataActorFactory: ByUserIdWithOriginatorActorFactory, - termsPagerActorFactory: ByUserIdWithOriginatorActorFactory) extends Conversation[BookingData] with StaticDataForBooking with Localizable { + val localization: Localization, datePickerActorFactory: ByUserIdWithOriginatorActorFactory, timePickerActorFactory: ByUserIdWithOriginatorActorFactory, + staticDataActorFactory: ByUserIdWithOriginatorActorFactory, termsPagerActorFactory: ByUserIdWithOriginatorActorFactory) extends Conversation[BookingData] with StaticDataForBooking with Localizable { private val datePicker = datePickerActorFactory(userId, self) + private val timePicker = timePickerActorFactory(userId, self) private[actor] val staticData = staticDataActorFactory(userId, self) private val termsPager = termsPagerActorFactory(userId, self) @@ -108,7 +110,35 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da datePicker ! cmd stay() case Msg(date: ZonedDateTime, bookingData: BookingData) => - goto(requestAction) using bookingData.copy(dateTo = date) + goto(requestTimeFrom) using bookingData.copy(dateTo = date) + } + + private def requestTimeFrom: Step = + ask { bookingData => + timePicker ! InitConversation + timePicker ! StartConversation + timePicker ! TimeFromMode + timePicker ! bookingData.timeFrom + } onReply { + case Msg(cmd: Command, _) => + timePicker ! cmd + stay() + case Msg(time: LocalTime, bookingData: BookingData) => + goto(requestTimeTo) using bookingData.copy(timeFrom = time) + } + + private def requestTimeTo: Step = + ask { bookingData => + timePicker ! InitConversation + timePicker ! StartConversation + timePicker ! TimeToMode + timePicker ! bookingData.timeTo + } onReply { + case Msg(cmd: Command, _) => + timePicker ! cmd + stay() + case Msg(time: LocalTime, bookingData: BookingData) => + goto(requestAction) using bookingData.copy(timeTo = time) } private def requestAction: Step = @@ -130,7 +160,7 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da ask { bookingData => 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) + bookingData.dateFrom, Some(bookingData.dateTo), timeFrom = bookingData.timeFrom, timeTo = bookingData.timeTo) termsPager ! InitConversation termsPager ! StartConversation termsPager ! availableTerms @@ -229,6 +259,7 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da datePicker ! PoisonPill staticData ! PoisonPill termsPager ! PoisonPill + timePicker ! PoisonPill super.postStop() } } @@ -237,13 +268,14 @@ object Book { def props(userId: UserId, bot: Bot, apiService: ApiService, dataService: DataService, monitoringService: MonitoringService, localization: Localization, datePickerActorFactory: ByUserIdWithOriginatorActorFactory, + timePickerFactory: ByUserIdWithOriginatorActorFactory, staticDataActorFactory: ByUserIdWithOriginatorActorFactory, termsPagerActorFactory: ByUserIdWithOriginatorActorFactory): Props = Props(new Book(userId, bot, apiService, dataService, monitoringService, localization, datePickerActorFactory, - staticDataActorFactory, termsPagerActorFactory)) + timePickerFactory, staticDataActorFactory, termsPagerActorFactory)) case class BookingData(cityId: IdName = null, clinicId: IdName = null, serviceId: IdName = null, doctorId: IdName = null, dateFrom: ZonedDateTime = ZonedDateTime.now(), - dateTo: ZonedDateTime = ZonedDateTime.now().plusDays(1L), timeOfDay: Int = 0, autobook: Boolean = false, term: Option[AvailableVisitsTermPresentation] = None, + dateTo: ZonedDateTime = ZonedDateTime.now().plusDays(1L), timeFrom: LocalTime = LocalTime.of(7, 0), timeTo: LocalTime = LocalTime.of(21, 0), autobook: Boolean = false, term: Option[AvailableVisitsTermPresentation] = None, temporaryReservationId: Option[Long] = None, valuations: Option[ValuationsResponse] = None) object Tags { diff --git a/server/src/main/scala/com/lbs/server/actor/TimePicker.scala b/server/src/main/scala/com/lbs/server/actor/TimePicker.scala new file mode 100644 index 0000000..4f2f9cc --- /dev/null +++ b/server/src/main/scala/com/lbs/server/actor/TimePicker.scala @@ -0,0 +1,128 @@ +/** + * 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 java.time.LocalTime + +import akka.actor.{ActorRef, Props} +import com.lbs.bot.model.{Button, Command} +import com.lbs.bot.{Bot, _} +import com.lbs.server.actor.Login.UserId +import com.lbs.server.actor.TimePicker.{Mode, Tags, TimeFromMode, TimeToMode} +import com.lbs.server.actor.conversation.Conversation +import com.lbs.server.lang.{Localizable, Localization} + +/** + * Time picker Inline Keyboard + * + * ⬆ ⬆ + * HH mm + * ⬇ ⬇ + * + */ +class TimePicker(val userId: UserId, val bot: Bot, val localization: Localization, originator: ActorRef) extends Conversation[LocalTime] with Localizable { + + private var mode: Mode = TimeFromMode + + entryPoint(configure) + + def configure: Step = + monologue { + case Msg(newMode: Mode, _) => + mode = newMode + stay() + case Msg(initialTime: LocalTime, _) => + goto(requestTime) using initialTime + } + + def requestTime: Step = + ask { initialDate => + val message = mode match { + case TimeFromMode => lang.chooseTimeFrom + case TimeToMode => lang.chooseTimeTo + } + bot.sendMessage(userId.source, message, inlineKeyboard = timeButtons(initialDate)) + } onReply { + case Msg(Command(_, msg, Some(Tags.Done)), finalTime) => + val (message, updateTime) = mode match { + case TimeFromMode => + val startOfTheWorkingDay = LocalTime.of(7, 0) + val timeFrom = if (startOfTheWorkingDay.isBefore(LocalTime.now())) finalTime else startOfTheWorkingDay + lang.timeFromIs(timeFrom) -> timeFrom + case TimeToMode => + val timeTo = finalTime + lang.timeToIs(timeTo) -> timeTo + } + bot.sendEditMessage(userId.source, msg.messageId, message) + originator ! updateTime + goto(configure) using null + + case Msg(Command(_, msg, Some(tag)), time) => + val modifiedTime = modifyTime(time, tag) + bot.sendEditMessage(userId.source, msg.messageId, inlineKeyboard = timeButtons(modifiedTime)) + stay() using modifiedTime + } + + private def modifyTime(time: LocalTime, tag: String) = { + tag match { + case Tags.HourInc => time.plusHours(1) + case Tags.MinuteInc => time.plusMinutes(30) + case Tags.HourDec => time.minusHours(1) + case Tags.MinuteDec => time.minusMinutes(30) + } + } + + private def timeButtons(time: LocalTime) = { + val hour = f"${time.getHour}%02d" + val minute = f"${time.getMinute}%02d" + + createInlineKeyboard(Seq( + Seq(Button("⬆", Tags.HourInc), Button("⬆", Tags.MinuteInc)), + Seq(Button(hour), Button(minute)), + Seq(Button("⬇", Tags.HourDec), Button("⬇", Tags.MinuteDec)), + Seq(Button("Done", Tags.Done)) + )) + } +} + +object TimePicker { + def props(userId: UserId, bot: Bot, localization: Localization, originator: ActorRef): Props = + Props(new TimePicker(userId, bot, localization, originator)) + + trait Mode + + object TimeFromMode extends Mode + + object TimeToMode extends Mode + + object Tags { + val HourInc = "hour_inc" + val MinuteInc = "minute_inc" + val HourDec = "hour_dec" + val MinuteDec = "minute_dec" + val Done = "done" + } + +} + 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 8ade5c3..65d326c 100644 --- a/server/src/main/scala/com/lbs/server/lang/En.scala +++ b/server/src/main/scala/com/lbs/server/lang/En.scala @@ -23,14 +23,14 @@ */ package com.lbs.server.lang -import java.time.ZonedDateTime +import java.time.{LocalTime, ZonedDateTime} import java.util.Locale import com.lbs.api.json.model.{AvailableVisitsTermPresentation, HistoricVisit, ReservedVisit, ValuationsResponse} import com.lbs.server.actor.Book import com.lbs.server.actor.StaticData.StaticDataConfig import com.lbs.server.repository.model.{Bug, Monitoring} -import com.lbs.server.util.DateTimeUtil.{formatDate, formatDateTime, minutesSinceBeginOf2018} +import com.lbs.server.util.DateTimeUtil.{formatDate, formatDateTime, formatTime, minutesSinceBeginOf2018} object En extends Lang { @@ -81,7 +81,7 @@ object En extends Lang { s" in ${bookingData.clinicId.name} clinic" + s" of the ${bookingData.cityId.name} city." + s"\nDesired dates: ${formatDate(bookingData.dateFrom, locale)} -> ${formatDate(bookingData.dateTo, locale)}" + - s"\nTime: ${timeOfDay(bookingData.timeOfDay)}" + + s"\nTime: ${formatTime(bookingData.timeFrom)} -> ${formatTime(bookingData.timeTo)}" + s"\n\n Now choose your action" override def noTermsFound: String = @@ -135,7 +135,7 @@ object En extends Lang { s""" Are you sure want to deactivate monitoring? | |📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} - |⏱ ${timeOfDay(monitoring.timeOfDay)} + |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}""".stripMargin @@ -249,7 +249,7 @@ object En extends Lang { override def monitoringEntry(monitoring: Monitoring, page: Int, index: Int): String = s"""📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} - |⏱ ${timeOfDay(monitoring.timeOfDay)} + |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} @@ -286,7 +286,7 @@ object En extends Lang { s"""❗ Nothing was found by your monitoring. Monitoring has been disabled as outdated. | |📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} - |⏱ ${timeOfDay(monitoring.timeOfDay)} + |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} @@ -342,8 +342,6 @@ object En extends Lang { override def bugHasBeenCreated(bugId: Long): String = s"✅ Thank you for submitting bug #$bugId!" - override def chooseTimeOfDay: String = " Please choose preferred time of day" - override def afterFive: String = "After 17:00" override def nineToFive: String = "From 09:00 to 17:00" @@ -352,8 +350,6 @@ 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" @@ -367,4 +363,12 @@ object En extends Lang { | Please choose an action or select account""".stripMargin override def moreParameters: String = "🛠 More parameters" + + override def chooseTimeFrom: String = " Please choose time from" + + override def chooseTimeTo: String = " Please choose time to" + + override def timeFromIs(timeFrom: LocalTime): String = s"⏱ Time from is ${formatTime(timeFrom)}" + + override def timeToIs(timeTo: LocalTime): String = s"⏱ Date to is ${formatTime(timeTo)}" } 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 34f9e05..1a7eca5 100644 --- a/server/src/main/scala/com/lbs/server/lang/Lang.scala +++ b/server/src/main/scala/com/lbs/server/lang/Lang.scala @@ -23,7 +23,7 @@ */ package com.lbs.server.lang -import java.time.ZonedDateTime +import java.time.{LocalTime, ZonedDateTime} import java.util.Locale import com.lbs.api.json.model.{AvailableVisitsTermPresentation, HistoricVisit, ReservedVisit, ValuationsResponse} @@ -50,13 +50,6 @@ trait Lang { def label: String - val timeOfDay = Map( - 0 -> allDay, - 1 -> beforeNine, - 2 -> nineToFive, - 3 -> afterFive - ) - protected def capitalizeFirstLetter(str: String): String = { val fistCapitalLetter = str.head.toTitleCase fistCapitalLetter + str.tail @@ -80,6 +73,10 @@ trait Lang { def chooseDateTo: String + def chooseTimeFrom: String + + def chooseTimeTo: String + def findTerms: String def modifyDate: String @@ -162,6 +159,10 @@ trait Lang { def dateToIs(dateTo: ZonedDateTime): String + def timeFromIs(timeFrom: LocalTime): String + + def timeToIs(timeTo: LocalTime): String + def termEntry(term: AvailableVisitsTermPresentation, page: Int, index: Int): String def termsHeader(page: Int, pages: Int): String @@ -224,8 +225,6 @@ trait Lang { def enterIssueDetails: String - def chooseTimeOfDay: String - def afterFive: String def nineToFive: String @@ -234,8 +233,6 @@ trait Lang { def allDay: String - def preferredTimeIs(time: Int): String - def deleteAccount: String def addAccount: String 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 1d60f27..2402bf1 100644 --- a/server/src/main/scala/com/lbs/server/lang/Ua.scala +++ b/server/src/main/scala/com/lbs/server/lang/Ua.scala @@ -23,14 +23,14 @@ */ package com.lbs.server.lang -import java.time.ZonedDateTime +import java.time.{LocalTime, ZonedDateTime} import java.util.Locale import com.lbs.api.json.model.{AvailableVisitsTermPresentation, HistoricVisit, ReservedVisit, ValuationsResponse} import com.lbs.server.actor.Book import com.lbs.server.actor.StaticData.StaticDataConfig import com.lbs.server.repository.model.{Bug, Monitoring} -import com.lbs.server.util.DateTimeUtil.{formatDate, formatDateTime, minutesSinceBeginOf2018} +import com.lbs.server.util.DateTimeUtil.{formatDate, formatDateTime, formatTime, minutesSinceBeginOf2018} object Ua extends Lang { @@ -81,7 +81,7 @@ object Ua extends Lang { s" в ${bookingData.clinicId.name} клініці" + s" міста ${bookingData.cityId.name}." + s"\nБажані дати: ${formatDate(bookingData.dateFrom, locale)} -> ${formatDate(bookingData.dateTo, locale)}" + - s"\nЧас: ${timeOfDay(bookingData.timeOfDay)}" + + s"\nЧас: ${formatTime(bookingData.timeFrom)} -> ${formatTime(bookingData.timeTo)}" + s"\n\n Тепер оберіть наступну дію" override def noTermsFound: String = @@ -135,7 +135,7 @@ object Ua extends Lang { s""" Ви впевнені, що хочете вимкнути моніторинг? | |📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} - |⏱ ${timeOfDay(monitoring.timeOfDay)} + |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}""".stripMargin @@ -248,7 +248,7 @@ object Ua extends Lang { override def monitoringEntry(monitoring: Monitoring, page: Int, index: Int): String = s"""📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} - |⏱ ${timeOfDay(monitoring.timeOfDay)} + |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} @@ -285,7 +285,7 @@ object Ua extends Lang { s"""❗ Нічого не знайдено за вашим моніторингом. Моніторинг був вимкнений як застарілий. | |📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} - |⏱ ${timeOfDay(monitoring.timeOfDay)} + |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} @@ -341,8 +341,6 @@ object Ua extends Lang { override def bugHasBeenCreated(bugId: Long): String = s"✅ Дякуємо за відправлений баг #$bugId!" - override def chooseTimeOfDay: String = " Будь ласка, оберіть бажаний час" - override def afterFive: String = "Після 17:00" override def nineToFive: String = "Від 09:00 до 17:00" @@ -351,8 +349,6 @@ 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 = "➕ Додати акаунт" @@ -366,4 +362,12 @@ object Ua extends Lang { | Будь ласка, оберіть дію або виберіть акаунт""".stripMargin override def moreParameters: String = "🛠 Більше налаштувань" + + override def chooseTimeFrom: String = " Будь ласка, виберіть початковий час" + + override def chooseTimeTo: String = " Будь ласка, виберіть кінцевий час" + + override def timeFromIs(timeFrom: LocalTime): String = s"⏱ Початковий час ${formatTime(timeFrom)}" + + override def timeToIs(timeTo: LocalTime): String = s"⏱ Кінцевий час ${formatTime(timeTo)}" } diff --git a/server/src/main/scala/com/lbs/server/repository/model/Monitoring.scala b/server/src/main/scala/com/lbs/server/repository/model/Monitoring.scala index 53dfa47..c083fa5 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/Monitoring.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/Monitoring.scala @@ -23,7 +23,7 @@ */ package com.lbs.server.repository.model -import java.time.ZonedDateTime +import java.time.{LocalTime, ZonedDateTime} import javax.persistence.{Access, AccessType, Column, Entity} @@ -89,8 +89,12 @@ class Monitoring extends RecordId { var dateTo: ZonedDateTime = _ @BeanProperty - @Column(name = "time_of_day", nullable = true) - var timeOfDay: JInt = 0 + @Column(name = "time_from", nullable = false) + var timeFrom: LocalTime = _ + + @BeanProperty + @Column(name = "time_to", nullable = false) + var timeTo: LocalTime = _ @BeanProperty @Column(nullable = false) @@ -108,7 +112,7 @@ class Monitoring extends RecordId { object Monitoring { 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, + dateTo: ZonedDateTime, autobook: Boolean = false, created: ZonedDateTime = ZonedDateTime.now(), timeFrom: LocalTime, timeTo: LocalTime, active: Boolean = true): Monitoring = { val monitoring = new Monitoring monitoring.userId = userId @@ -125,7 +129,8 @@ object Monitoring { monitoring.doctorName = doctorName monitoring.dateFrom = dateFrom monitoring.dateTo = dateTo - monitoring.timeOfDay = timeOfDay + monitoring.timeFrom = timeFrom + monitoring.timeTo = timeTo monitoring.autobook = autobook monitoring.created = created monitoring.active = active diff --git a/server/src/main/scala/com/lbs/server/service/ApiService.scala b/server/src/main/scala/com/lbs/server/service/ApiService.scala index a6e4e31..010225b 100644 --- a/server/src/main/scala/com/lbs/server/service/ApiService.scala +++ b/server/src/main/scala/com/lbs/server/service/ApiService.scala @@ -23,7 +23,7 @@ */ package com.lbs.server.service -import java.time.ZonedDateTime +import java.time.{LocalTime, ZonedDateTime} import com.lbs.api.LuxmedApi import com.lbs.api.json.model._ @@ -73,13 +73,19 @@ class ApiService extends SessionSupport { } 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, + fromDate: ZonedDateTime = ZonedDateTime.now(), toDate: Option[ZonedDateTime] = None, timeFrom: LocalTime, timeTo: LocalTime, languageId: Long = 10, findFirstFreeTerm: Boolean = false): Either[Throwable, List[AvailableVisitsTermPresentation]] = getDefaultPayer(accountId, cityId, clinicId, serviceId).flatMap { case Some(payerId) => withSession(accountId) { session => - LuxmedApi.availableTerms(session.accessToken, session.tokenType, payerId.id, cityId, clinicId, serviceId, doctorId, - fromDate, toDate, timeOfDay, languageId, findFirstFreeTerm).map(_.availableVisitsTermPresentation) + val termsEither = LuxmedApi.availableTerms(session.accessToken, session.tokenType, payerId.id, cityId, clinicId, serviceId, doctorId, + fromDate, toDate, languageId = languageId, findFirstFreeTerm = findFirstFreeTerm).map(_.availableVisitsTermPresentation) + termsEither.map { terms => + terms.filter { term => + val time = term.visitDate.startDateTime.toLocalTime + time == timeFrom || time == timeTo || (time.isAfter(timeFrom) && time.isBefore(timeTo)) + } + } } case None => sys.error(s"Can't determine payer id by user: $accountId, city: $cityId, clinic: $clinicId, service: $serviceId") } 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 7ba0cbe..78b2b29 100644 --- a/server/src/main/scala/com/lbs/server/service/MonitoringService.scala +++ b/server/src/main/scala/com/lbs/server/service/MonitoringService.scala @@ -91,7 +91,7 @@ class MonitoringService extends Logger { debug(s"Looking for available terms. Monitoring [#${monitoring.recordId}]") val dateFrom = optimizeDateFrom(monitoring.dateFrom) val termsEither = apiService.getAvailableTerms(monitoring.accountId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId, - monitoring.doctorId, dateFrom, Some(monitoring.dateTo)) + monitoring.doctorId, dateFrom, Some(monitoring.dateTo), timeFrom = monitoring.timeFrom, timeTo = monitoring.timeTo) termsEither match { case Right(terms) => if (terms.nonEmpty) { @@ -219,7 +219,7 @@ class MonitoringService extends Logger { monitoringMaybe match { case Some(monitoring) => val termsEither = apiService.getAvailableTerms(monitoring.accountId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId, - monitoring.doctorId, monitoring.dateFrom, Some(monitoring.dateTo)) + monitoring.doctorId, monitoring.dateFrom, Some(monitoring.dateTo), timeFrom = monitoring.timeFrom, timeTo = monitoring.timeTo) termsEither match { case Right(terms) => val termMaybe = terms.find(term => term.scheduleId == scheduleId && minutesSinceBeginOf2018(term.visitDate.startDateTime) == time) 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 b61d13b..1ac13f1 100644 --- a/server/src/main/scala/com/lbs/server/util/package.scala +++ b/server/src/main/scala/com/lbs/server/util/package.scala @@ -24,11 +24,11 @@ package com.lbs.server import java.time.format.DateTimeFormatter -import java.time.{ZoneId, ZonedDateTime} +import java.time.{LocalTime, ZoneId, ZonedDateTime} import java.util.Locale import com.lbs.api.json.model._ -import com.lbs.bot.model.{Command, Message} +import com.lbs.bot.model.Command import com.lbs.common.ModelConverters import com.lbs.server.actor.Book.BookingData import com.lbs.server.actor.Login.UserId @@ -62,7 +62,8 @@ package object util { doctorName = bookingData.doctorId.name, dateFrom = bookingData.dateFrom, dateTo = bookingData.dateTo, - timeOfDay = bookingData.timeOfDay, + timeFrom = bookingData.timeFrom, + timeTo = bookingData.timeTo, autobook = bookingData.autobook ) } @@ -143,10 +144,14 @@ package object util { object DateTimeUtil { private val DateFormat: Locale => DateTimeFormatter = locale => DateTimeFormatter.ofPattern("dd MMM yyyy", locale) + private val TimeFormat: DateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm") + private val DateTimeFormat: Locale => DateTimeFormatter = locale => DateTimeFormatter.ofPattern("EEE',' dd MMM yyyy',' HH:mm", locale) def formatDate(date: ZonedDateTime, locale: Locale): String = date.format(DateFormat(locale)) + def formatTime(time: LocalTime): String = time.format(TimeFormat) + def formatDateTime(date: ZonedDateTime, locale: Locale): String = date.format(DateTimeFormat(locale)) private val EpochMinutesTillBeginOf2018: Long = epochMinutes(ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()))