From e870e404e15c8fe70505a30e107fed81f687f007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Siatkowski?= Date: Wed, 10 Aug 2022 00:04:19 +0200 Subject: [PATCH] Use scalafmt --- .drone.yml | 2 +- .scalafmt.conf | 11 + README.md | 2 +- api/src/main/scala/com/lbs/api/ApiBase.scala | 11 +- .../main/scala/com/lbs/api/LuxmedApi.scala | 153 +++++--- .../com/lbs/api/exception/ApiException.scala | 3 +- .../lbs/api/exception/GenericException.scala | 1 - .../InvalidLoginOrPasswordException.scala | 1 - .../exception/SessionExpiredException.scala | 1 - .../main/scala/com/lbs/api/http/package.scala | 7 +- .../com/lbs/api/json/JsonSerializer.scala | 78 ++-- .../lbs/api/json/model/DictionaryCity.scala | 36 +- .../model/DictionaryServiceVariants.scala | 348 +++++++++--------- .../scala/com/lbs/api/json/model/Doctor.scala | 33 +- .../scala/com/lbs/api/json/model/Empty.scala | 5 +- .../lbs/api/json/model/EventsResponse.scala | 200 +++++----- .../api/json/model/FacilitiesAndDoctors.scala | 74 ++-- .../api/json/model/ForgeryTokenResponse.scala | 1 - .../lbs/api/json/model/LoginResponse.scala | 4 +- .../lbs/api/json/model/LuxmedBaseError.scala | 1 - .../com/lbs/api/json/model/LuxmedError.scala | 3 +- .../lbs/api/json/model/LuxmedErrorsMap.scala | 3 +- .../model/ReservationChangetermRequest.scala | 78 ++-- .../model/ReservationConfirmRequest.scala | 71 ++-- .../model/ReservationConfirmResponse.scala | 49 ++- .../model/ReservationLocktermRequest.scala | 88 +++-- .../model/ReservationLocktermResponse.scala | 146 ++++---- .../json/model/SerializableJsonObject.scala | 1 - .../api/json/model/TermsIndexResponse.scala | 246 +++++++------ .../com/lbs/api/json/model/Valuation.scala | 46 ++- api/src/main/scala/com/lbs/api/package.scala | 1 - .../api/http/ExtendedHttpRequestSpec.scala | 10 +- bot/src/main/scala/com/lbs/bot/Bot.scala | 10 +- bot/src/main/scala/com/lbs/bot/PollBot.scala | 1 - .../main/scala/com/lbs/bot/WebhookBot.scala | 1 - .../main/scala/com/lbs/bot/model/Button.scala | 3 +- .../scala/com/lbs/bot/model/Command.scala | 3 +- .../main/scala/com/lbs/bot/model/Event.scala | 1 - .../com/lbs/bot/model/InlineKeyboard.scala | 1 - .../com/lbs/bot/model/MessageSource.scala | 1 - .../lbs/bot/model/MessageSourceSystem.scala | 6 +- bot/src/main/scala/com/lbs/bot/package.scala | 1 - .../com/lbs/bot/telegram/TelegramBot.scala | 16 +- .../com/lbs/bot/telegram/TelegramClient.scala | 35 +- .../com/lbs/bot/telegram/TelegramEvent.scala | 1 - .../scala/com/lbs/bot/telegram/package.scala | 12 +- build.gradle | 3 +- .../main/scala/com/lbs/common/Implicits.scala | 1 - .../com/lbs/common/ModelConverters.scala | 8 +- .../com/lbs/common/ParametrizedLock.scala | 1 - .../main/scala/com/lbs/common/Scheduler.scala | 16 +- .../src/main/scala/com/lbs/server/Boot.scala | 2 - .../scala/com/lbs/server/BootConfig.scala | 113 ++++-- .../com/lbs/server/conversation/Account.scala | 45 ++- .../com/lbs/server/conversation/Auth.scala | 20 +- .../com/lbs/server/conversation/Book.scala | 201 +++++++--- .../conversation/BookWithTemplate.scala | 165 ++++++--- .../com/lbs/server/conversation/Chat.scala | 105 +++--- .../lbs/server/conversation/DatePicker.scala | 52 +-- .../com/lbs/server/conversation/Help.scala | 14 +- .../server/conversation/HistoryViewer.scala | 14 +- .../com/lbs/server/conversation/Login.scala | 57 +-- .../lbs/server/conversation/Monitorings.scala | 20 +- .../conversation/MonitoringsHistory.scala | 23 +- .../com/lbs/server/conversation/Pager.scala | 32 +- .../conversation/ReservedVisitsViewer.scala | 23 +- .../com/lbs/server/conversation/Router.scala | 9 +- .../lbs/server/conversation/Settings.scala | 80 ++-- .../lbs/server/conversation/StaticData.scala | 27 +- .../conversation/StaticDataForBooking.scala | 20 +- .../lbs/server/conversation/TimePicker.scala | 34 +- .../conversation/UnauthorizedHelp.scala | 10 +- .../conversation/base/Conversation.scala | 19 +- .../conversation/base/Interactional.scala | 5 +- .../com/lbs/server/conversation/package.scala | 1 - .../exception/UserNotFoundException.scala | 1 - .../main/scala/com/lbs/server/lang/En.scala | 107 +++--- .../main/scala/com/lbs/server/lang/Lang.scala | 3 +- .../com/lbs/server/lang/Localizable.scala | 1 - .../com/lbs/server/lang/Localization.scala | 12 +- .../main/scala/com/lbs/server/lang/Pl.scala | 113 +++--- .../main/scala/com/lbs/server/lang/Ua.scala | 113 +++--- .../server/repository/DataRepository.scala | 193 ++++++---- .../lbs/server/repository/model/Account.scala | 3 +- .../server/repository/model/CityHistory.scala | 3 +- .../repository/model/ClinicHistory.scala | 1 - .../server/repository/model/Credentials.scala | 1 - .../repository/model/DoctorHistory.scala | 11 +- .../lbs/server/repository/model/History.scala | 2 - .../server/repository/model/Monitoring.scala | 31 +- .../server/repository/model/RecordId.scala | 3 +- .../repository/model/ServiceHistory.scala | 10 +- .../server/repository/model/Settings.scala | 5 +- .../lbs/server/repository/model/Source.scala | 3 +- .../server/repository/model/SystemUser.scala | 3 +- .../lbs/server/repository/model/package.scala | 1 - .../com/lbs/server/service/ApiService.scala | 85 +++-- .../com/lbs/server/service/DataService.scala | 32 +- .../server/service/MonitoringService.scala | 95 +++-- .../lbs/server/service/SessionSupport.scala | 3 +- .../scala/com/lbs/server/util/package.scala | 26 +- .../lbs/server/conversation/AkkaTestKit.scala | 6 +- .../lbs/server/conversation/AuthSpec.scala | 2 - .../conversation/base/ConversationSpec.scala | 35 +- .../base/ConversationTestProbe.scala | 7 +- 105 files changed, 2255 insertions(+), 1582 deletions(-) create mode 100644 .scalafmt.conf diff --git a/.drone.yml b/.drone.yml index 8d50306..23fa92b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -13,7 +13,7 @@ steps: GRADLE_USER_HOME: ~/.gradle command: [ /bin/bash ] commands: - - ./gradlew test + - ./gradlew checkScalafmtAll test - ./gradlew prepare - echo -n "1.0.$DRONE_BUILD_NUMBER,latest" > .tags - echo -n "1.0.$DRONE_BUILD_NUMBER" > ./docker/version diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 0000000..315a7b2 --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,11 @@ +version = 3.5.8 +runner.dialect = scala213 +preset = IntelliJ +maxColumn = 120 +project.git = true + +align.preset = some +docstrings.style = SpaceAsterisk +docstrings.oneline = fold +docstrings.wrap = no +docstrings.blankFirstLine = yes \ No newline at end of file diff --git a/README.md b/README.md index 7b681e3..b2ada76 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ to the same folder and rename it to **secrets.env** ### Develop run 1. Run `docker-compose up` to launch PostgreSQL database -2. Set env `TELEGRAM_TOKEN="YOUR_TOKEN"` +2. Set env `TELEGRAM_TOKEN=YOUR_TOKEN` 3. Run `Boot.scala` app diff --git a/api/src/main/scala/com/lbs/api/ApiBase.scala b/api/src/main/scala/com/lbs/api/ApiBase.scala index e8ea7a2..e787803 100644 --- a/api/src/main/scala/com/lbs/api/ApiBase.scala +++ b/api/src/main/scala/com/lbs/api/ApiBase.scala @@ -1,4 +1,3 @@ - package com.lbs.api import com.lbs.api.http.Session @@ -7,9 +6,11 @@ import scalaj.http.{BaseHttp, HttpRequest} import java.net.HttpCookie -object ApiHttp extends BaseHttp( - userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" -) +object ApiHttp + extends BaseHttp( + userAgent = + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" + ) trait ApiBase { private val CommonHeaders = @@ -22,13 +23,11 @@ trait ApiBase { `Accept-Language` -> "pl;q=1.0, pl;q=0.9, en;q=0.8" ) - protected def httpUnauthorized(url: String): HttpRequest = { ApiHttp(s"https://portalpacjenta.luxmed.pl/PatientPortalMobileAPI/api/$url") .headers(CommonHeaders) } - protected def http(url: String, session: Session): HttpRequest = { ApiHttp(s"https://portalpacjenta.luxmed.pl/PatientPortalMobileAPI/api/$url") .headers(CommonHeaders) diff --git a/api/src/main/scala/com/lbs/api/LuxmedApi.scala b/api/src/main/scala/com/lbs/api/LuxmedApi.scala index 53ad6ca..0bf392b 100644 --- a/api/src/main/scala/com/lbs/api/LuxmedApi.scala +++ b/api/src/main/scala/com/lbs/api/LuxmedApi.scala @@ -1,30 +1,28 @@ - package com.lbs.api import cats.implicits.toFunctorOps import com.lbs.api.http._ import com.lbs.api.http.headers._ import com.lbs.api.json.JsonSerializer.extensions._ -import com.lbs.api.json.model.{EventsResponse, TermsIndexResponse, _} +import com.lbs.api.json.model._ import scalaj.http.{HttpRequest, HttpResponse} import java.time.format.DateTimeFormatter import java.time.{LocalDateTime, ZonedDateTime} -import scala.language.higherKinds -class LuxmedApi[F[_] : ThrowableMonad] extends ApiBase { +class LuxmedApi[F[_]: ThrowableMonad] extends ApiBase { private val dateFormatNewPortal = DateTimeFormatter.ofPattern("yyyy-MM-dd") private val dateFormatEvents = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ") def login(username: String, password: String, clientId: String = "iPhone"): F[HttpResponse[LoginResponse]] = { - val request = httpUnauthorized("token"). - header(`Content-Type`, "application/x-www-form-urlencoded"). - header(`x-api-client-identifier`, clientId). - param("client_id", clientId). - param("grant_type", "password"). - param("password", password). - param("username", username) + val request = httpUnauthorized("token") + .header(`Content-Type`, "application/x-www-form-urlencoded") + .header(`x-api-client-identifier`, clientId) + .param("client_id", clientId) + .param("grant_type", "password") + .param("password", password) + .param("username", username) post[LoginResponse](request) } @@ -39,102 +37,139 @@ class LuxmedApi[F[_] : ThrowableMonad] extends ApiBase { get[ForgeryTokenResponse](request) } - def events(session: Session, fromDate: ZonedDateTime = ZonedDateTime.now().minusYears(1), - toDate: ZonedDateTime = ZonedDateTime.now()): F[EventsResponse] = { - val request = http("Events", session). - header(`Content-Type`, "application/json"). - param("filter.filterDateFrom", dateFormatEvents.format(fromDate)). - param("filter.filterDateTo", dateFormatEvents.format(toDate)) + def events( + session: Session, + fromDate: ZonedDateTime = ZonedDateTime.now().minusYears(1), + toDate: ZonedDateTime = ZonedDateTime.now() + ): F[EventsResponse] = { + val request = http("Events", session) + .header(`Content-Type`, "application/json") + .param("filter.filterDateFrom", dateFormatEvents.format(fromDate)) + .param("filter.filterDateTo", dateFormatEvents.format(toDate)) get[EventsResponse](request).map(_.body) } def dictionaryCities(session: Session): F[List[DictionaryCity]] = { - val request = httpNewApi("NewPortal/Dictionary/cities", session). - header(`Content-Type`, "application/json") + val request = httpNewApi("NewPortal/Dictionary/cities", session).header(`Content-Type`, "application/json") getList[DictionaryCity](request).map(_.body) } def dictionaryServiceVariants(session: Session): F[List[DictionaryServiceVariants]] = { - val request = httpNewApi("NewPortal/Dictionary/serviceVariantsGroups", session). - header(`Content-Type`, "application/json") + val request = + httpNewApi("NewPortal/Dictionary/serviceVariantsGroups", session).header(`Content-Type`, "application/json") getList[DictionaryServiceVariants](request).map(_.body) } - def dictionaryFacilitiesAndDoctors(session: Session, cityId: Option[Long], serviceVariantId: Option[Long]): F[FacilitiesAndDoctors] = { - val request = httpNewApi("NewPortal/Dictionary/facilitiesAndDoctors", session). - header(`Content-Type`, "application/json"). - param("cityId", cityId.map(_.toString)). - param("serviceVariantId", serviceVariantId.map(_.toString)) + def dictionaryFacilitiesAndDoctors( + session: Session, + cityId: Option[Long], + serviceVariantId: Option[Long] + ): F[FacilitiesAndDoctors] = { + val request = httpNewApi("NewPortal/Dictionary/facilitiesAndDoctors", session) + .header(`Content-Type`, "application/json") + .param("cityId", cityId.map(_.toString)) + .param("serviceVariantId", serviceVariantId.map(_.toString)) get[FacilitiesAndDoctors](request).map(_.body) } - def termsIndex(session: Session, cityId: Long, clinicId: Option[Long], serviceId: Long, doctorId: Option[Long], - fromDate: LocalDateTime = LocalDateTime.now(), toDate: LocalDateTime, languageId: Long = 10): F[TermsIndexResponse] = { - val request = httpNewApi("NewPortal/terms/index", session). - header(`Content-Type`, "application/json"). - param("cityId", cityId.toString). - param("serviceVariantId", serviceId.toString). - param("languageId", languageId.toString). - param("searchDateFrom", dateFormatNewPortal.format(fromDate)). - param("searchDateTo", dateFormatNewPortal.format(toDate)). - param("searchDatePreset", 14.toString). - param("facilitiesIds", clinicId.map(_.toString)). - param("doctorsIds", doctorId.map(_.toString)). - param("nextSearch", false.toString). - param("searchByMedicalSpecialist", false.toString) + def termsIndex( + session: Session, + cityId: Long, + clinicId: Option[Long], + serviceId: Long, + doctorId: Option[Long], + fromDate: LocalDateTime = LocalDateTime.now(), + toDate: LocalDateTime, + languageId: Long = 10 + ): F[TermsIndexResponse] = { + val request = httpNewApi("NewPortal/terms/index", session) + .header(`Content-Type`, "application/json") + .param("cityId", cityId.toString) + .param("serviceVariantId", serviceId.toString) + .param("languageId", languageId.toString) + .param("searchDateFrom", dateFormatNewPortal.format(fromDate)) + .param("searchDateTo", dateFormatNewPortal.format(toDate)) + .param("searchDatePreset", 14.toString) + .param("facilitiesIds", clinicId.map(_.toString)) + .param("doctorsIds", doctorId.map(_.toString)) + .param("nextSearch", false.toString) + .param("searchByMedicalSpecialist", false.toString) get[TermsIndexResponse](request).map(_.body) } - def reservationLockterm(session: Session, xsrfToken: XsrfToken, reservationLocktermRequest: ReservationLocktermRequest): F[ReservationLocktermResponse] = { - val request = httpNewApi("NewPortal/reservation/lockterm", session, Some(session.cookies ++ xsrfToken.cookies)). - header(`Content-Type`, "application/json") + def reservationLockterm( + session: Session, + xsrfToken: XsrfToken, + reservationLocktermRequest: ReservationLocktermRequest + ): F[ReservationLocktermResponse] = { + val request = httpNewApi("NewPortal/reservation/lockterm", session, Some(session.cookies ++ xsrfToken.cookies)) + .header(`Content-Type`, "application/json") .header(`xsrf-token`, xsrfToken.token) post[ReservationLocktermResponse](request, bodyOpt = Some(reservationLocktermRequest)).map(_.body) } def deleteTemporaryReservation(session: Session, xsrfToken: XsrfToken, temporaryReservationId: Long): F[Unit] = { - val request = httpNewApi(s"NewPortal/reservation/releaseterm?reservationId=$temporaryReservationId", session, Some(session.cookies ++ xsrfToken.cookies)). - header(`Content-Type`, "application/json") + val request = httpNewApi( + s"NewPortal/reservation/releaseterm?reservationId=$temporaryReservationId", + session, + Some(session.cookies ++ xsrfToken.cookies) + ) + .header(`Content-Type`, "application/json") .header(`xsrf-token`, xsrfToken.token) postVoid(request, bodyOpt = Some(Empty())) } - def reservationConfirm(session: Session, xsrfToken: XsrfToken, reservationConfirmRequest: ReservationConfirmRequest): F[ReservationConfirmResponse] = { - val request = httpNewApi("NewPortal/reservation/confirm", session, Some(session.cookies ++ xsrfToken.cookies)). - header(`Content-Type`, "application/json") + def reservationConfirm( + session: Session, + xsrfToken: XsrfToken, + reservationConfirmRequest: ReservationConfirmRequest + ): F[ReservationConfirmResponse] = { + val request = httpNewApi("NewPortal/reservation/confirm", session, Some(session.cookies ++ xsrfToken.cookies)) + .header(`Content-Type`, "application/json") .header(`xsrf-token`, xsrfToken.token) post[ReservationConfirmResponse](request, bodyOpt = Some(reservationConfirmRequest)).map(_.body) } - def reservationChangeTerm(session: Session, xsrfToken: XsrfToken, reservationChangetermRequest: ReservationChangetermRequest): F[ReservationConfirmResponse] = { - val request = httpNewApi("NewPortal/reservation/changeterm", session, Some(session.cookies ++ xsrfToken.cookies)). - header(`Content-Type`, "application/json") + def reservationChangeTerm( + session: Session, + xsrfToken: XsrfToken, + reservationChangetermRequest: ReservationChangetermRequest + ): F[ReservationConfirmResponse] = { + val request = httpNewApi("NewPortal/reservation/changeterm", session, Some(session.cookies ++ xsrfToken.cookies)) + .header(`Content-Type`, "application/json") .header(`xsrf-token`, xsrfToken.token) post[ReservationConfirmResponse](request, bodyOpt = Some(reservationChangetermRequest)).map(_.body) } def reservationDelete(session: Session, reservationId: Long): F[HttpResponse[String]] = { - val request = http(s"events/Visit/$reservationId", session). - header(`Content-Type`, "application/json") + val request = http(s"events/Visit/$reservationId", session).header(`Content-Type`, "application/json") delete(request) } - private def get[T <: SerializableJsonObject](request: HttpRequest)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[T]] = { + private def get[T <: SerializableJsonObject]( + request: HttpRequest + )(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[T]] = { request.invoke.map(r => r.copy(body = r.body.as[T])) } - private def getList[T <: SerializableJsonObject](request: HttpRequest)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[List[T]]] = { + private def getList[T <: SerializableJsonObject]( + request: HttpRequest + )(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[List[T]]] = { request.invoke.map(r => r.copy(body = r.body.asList[T])) } - private def getVoid[T <: SerializableJsonObject](request: HttpRequest)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[Unit]] = { + private def getVoid[T <: SerializableJsonObject]( + request: HttpRequest + )(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[Unit]] = { request.invoke.map(r => r.copy(body = {})) } - private def post[T <: SerializableJsonObject](request: HttpRequest, bodyOpt: Option[SerializableJsonObject] = None)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[T]] = { + private def post[T <: SerializableJsonObject](request: HttpRequest, bodyOpt: Option[SerializableJsonObject] = None)( + implicit mf: scala.reflect.Manifest[T] + ): F[HttpResponse[T]] = { val postRequest = bodyOpt match { case Some(body) => request.postData(body.asJson) - case None => request.postForm + case None => request.postForm } postRequest.invoke.map(r => r.copy(body = r.body.as[T])) } @@ -142,7 +177,7 @@ class LuxmedApi[F[_] : ThrowableMonad] extends ApiBase { private def postVoid(request: HttpRequest, bodyOpt: Option[SerializableJsonObject] = None): F[Unit] = { val postRequest = bodyOpt match { case Some(body) => request.postData(body.asJson) - case None => request.postForm + case None => request.postForm } postRequest.invoke.void } diff --git a/api/src/main/scala/com/lbs/api/exception/ApiException.scala b/api/src/main/scala/com/lbs/api/exception/ApiException.scala index 5e30b34..95359e8 100644 --- a/api/src/main/scala/com/lbs/api/exception/ApiException.scala +++ b/api/src/main/scala/com/lbs/api/exception/ApiException.scala @@ -1,4 +1,3 @@ - package com.lbs.api.exception -abstract class ApiException(message: String) extends Exception(s"Luxmed API exception: $message") \ No newline at end of file +abstract class ApiException(message: String) extends Exception(s"Luxmed API exception: $message") diff --git a/api/src/main/scala/com/lbs/api/exception/GenericException.scala b/api/src/main/scala/com/lbs/api/exception/GenericException.scala index 457c075..24125fa 100644 --- a/api/src/main/scala/com/lbs/api/exception/GenericException.scala +++ b/api/src/main/scala/com/lbs/api/exception/GenericException.scala @@ -1,4 +1,3 @@ - package com.lbs.api.exception case class GenericException(code: Int, message: String) extends ApiException(message) { diff --git a/api/src/main/scala/com/lbs/api/exception/InvalidLoginOrPasswordException.scala b/api/src/main/scala/com/lbs/api/exception/InvalidLoginOrPasswordException.scala index c7fc409..0bebf2c 100644 --- a/api/src/main/scala/com/lbs/api/exception/InvalidLoginOrPasswordException.scala +++ b/api/src/main/scala/com/lbs/api/exception/InvalidLoginOrPasswordException.scala @@ -1,4 +1,3 @@ - package com.lbs.api.exception class InvalidLoginOrPasswordException extends ApiException("Invalid login or password") diff --git a/api/src/main/scala/com/lbs/api/exception/SessionExpiredException.scala b/api/src/main/scala/com/lbs/api/exception/SessionExpiredException.scala index 6e979ee..1d1e92d 100644 --- a/api/src/main/scala/com/lbs/api/exception/SessionExpiredException.scala +++ b/api/src/main/scala/com/lbs/api/exception/SessionExpiredException.scala @@ -1,4 +1,3 @@ - package com.lbs.api.exception class SessionExpiredException extends ApiException("Session expired") diff --git a/api/src/main/scala/com/lbs/api/http/package.scala b/api/src/main/scala/com/lbs/api/http/package.scala index 96861e9..6a49f77 100644 --- a/api/src/main/scala/com/lbs/api/http/package.scala +++ b/api/src/main/scala/com/lbs/api/http/package.scala @@ -1,4 +1,3 @@ - package com.lbs.api import cats.MonadError @@ -33,7 +32,7 @@ package object http extends StrictLogging { private val SensitiveHeaders = List("passw", "access_token", "refresh_token", "authorization") - implicit class ExtendedHttpRequest[F[_] : ThrowableMonad](httpRequest: HttpRequest) { + implicit class ExtendedHttpRequest[F[_]: ThrowableMonad](httpRequest: HttpRequest) { def invoke: F[HttpResponse[String]] = { val me = MonadError[F, Throwable] logger.debug(s"Sending request:\n${hideSensitive(httpRequest)}") @@ -75,7 +74,9 @@ package object http extends StrictLogging { code match { case HttpURLConnection.HTTP_MOVED_TEMP if httpResponse.header("Location").exists(_.contains("/LogOn")) => Some(new SessionExpiredException) - case HttpURLConnection.HTTP_CONFLICT if lowercasedBody.contains("nieprawidłowy login lub hasło") || lowercasedBody.contains("invalid login or password") => + case HttpURLConnection.HTTP_CONFLICT + if lowercasedBody + .contains("nieprawidłowy login lub hasło") || lowercasedBody.contains("invalid login or password") => Some(new InvalidLoginOrPasswordException) case _ => Try(body.as[LuxmedErrorsMap]) diff --git a/api/src/main/scala/com/lbs/api/json/JsonSerializer.scala b/api/src/main/scala/com/lbs/api/json/JsonSerializer.scala index 6378c2f..46c3bc5 100644 --- a/api/src/main/scala/com/lbs/api/json/JsonSerializer.scala +++ b/api/src/main/scala/com/lbs/api/json/JsonSerializer.scala @@ -1,4 +1,3 @@ - package com.lbs.api.json import com.lbs.api.json.model.{LuxmedFunnyDateTime, SerializableJsonObject} @@ -10,43 +9,58 @@ import java.time.format.DateTimeFormatter import java.time.{LocalDateTime, LocalTime, ZonedDateTime} import scala.util.Try - object JsonSerializer extends StrictLogging { - private val zonedDateTimeSerializer = new CustomSerializer[ZonedDateTime](_ => ( { - case JString(str) => ZonedDateTime.parse(str, DateTimeFormatter.ISO_OFFSET_DATE_TIME) - }, { - case zonedDateTime: ZonedDateTime => JString(zonedDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)) - } - )) + private val zonedDateTimeSerializer = new CustomSerializer[ZonedDateTime](_ => + ( + { case JString(str) => + ZonedDateTime.parse(str, DateTimeFormatter.ISO_OFFSET_DATE_TIME) + }, + { case zonedDateTime: ZonedDateTime => + JString(zonedDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)) + } + ) + ) - private val localTimeSerializer = new CustomSerializer[LocalTime](_ => ( { - case JString(str) => LocalTime.parse(str) - }, { - case localTime: LocalTime => JString(localTime.toString) - } - )) + private val localTimeSerializer = new CustomSerializer[LocalTime](_ => + ( + { case JString(str) => + LocalTime.parse(str) + }, + { case localTime: LocalTime => + JString(localTime.toString) + } + ) + ) - private val localDateTimeSerializer = new CustomSerializer[LocalDateTime](_ => ( { - case JString(str) => LocalDateTime.parse(str) - }, { - case localTime: LocalDateTime => JString(localTime.toString) - } - )) + private val localDateTimeSerializer = new CustomSerializer[LocalDateTime](_ => + ( + { case JString(str) => + LocalDateTime.parse(str) + }, + { case localTime: LocalDateTime => + JString(localTime.toString) + } + ) + ) - private val luxmedFunnyDateTimeSerializer = new CustomSerializer[LuxmedFunnyDateTime](_ => ( { - case JString(str) => - Try(LocalDateTime.parse(str)) - .map(v => LuxmedFunnyDateTime(dateTimeLocal = Some(v))) - .recoverWith{case _ => Try(ZonedDateTime.parse(str)).map(v => LuxmedFunnyDateTime(dateTimeTz = Some(v)))} - .getOrElse(sys.error(s"can't parse date $str")) - }, { - case time: LocalDateTime => JString(time.toString) - case time: ZonedDateTime => JString(time.toString) - } - )) + private val luxmedFunnyDateTimeSerializer = new CustomSerializer[LuxmedFunnyDateTime](_ => + ( + { case JString(str) => + Try(LocalDateTime.parse(str)) + .map(v => LuxmedFunnyDateTime(dateTimeLocal = Some(v))) + .recoverWith { case _ => Try(ZonedDateTime.parse(str)).map(v => LuxmedFunnyDateTime(dateTimeTz = Some(v))) } + .getOrElse(sys.error(s"can't parse date $str")) + }, + { + case time: LocalDateTime => JString(time.toString) + case time: ZonedDateTime => JString(time.toString) + } + ) + ) - private implicit val formats: Formats = DefaultFormats.withStrictArrayExtraction + zonedDateTimeSerializer + localTimeSerializer + localDateTimeSerializer + luxmedFunnyDateTimeSerializer + private implicit val formats: Formats = + DefaultFormats.withStrictArrayExtraction + zonedDateTimeSerializer + localTimeSerializer + localDateTimeSerializer + luxmedFunnyDateTimeSerializer def extract[T](jsonString: String)(implicit mf: scala.reflect.Manifest[T]): T = { parse(jsonString).camelizeKeys.extract[T] diff --git a/api/src/main/scala/com/lbs/api/json/model/DictionaryCity.scala b/api/src/main/scala/com/lbs/api/json/model/DictionaryCity.scala index 7ecf40e..bf23dc6 100644 --- a/api/src/main/scala/com/lbs/api/json/model/DictionaryCity.scala +++ b/api/src/main/scala/com/lbs/api/json/model/DictionaryCity.scala @@ -1,21 +1,21 @@ - package com.lbs.api.json.model /** -[ - { - "id": 70, - "name": "Białystok" - }, - { - "id": 12, - "name": "Bielsk Podlaski" - }, - { - "id": 100, - "name": "Bielsko-Biała" - } -] - * - */ -case class DictionaryCity(override val id: Long, override val name: String) extends Identified with SerializableJsonObject + * [ + * { + * "id": 70, + * "name": "Białystok" + * }, + * { + * "id": 12, + * "name": "Bielsk Podlaski" + * }, + * { + * "id": 100, + * "name": "Bielsko-Biała" + * } + * ] + */ +case class DictionaryCity(override val id: Long, override val name: String) + extends Identified + with SerializableJsonObject diff --git a/api/src/main/scala/com/lbs/api/json/model/DictionaryServiceVariants.scala b/api/src/main/scala/com/lbs/api/json/model/DictionaryServiceVariants.scala index fe783d7..419c810 100644 --- a/api/src/main/scala/com/lbs/api/json/model/DictionaryServiceVariants.scala +++ b/api/src/main/scala/com/lbs/api/json/model/DictionaryServiceVariants.scala @@ -1,175 +1,181 @@ - package com.lbs.api.json.model /** -[ - { - "actionCode": "", - "children": [ - { - "actionCode": null, - "children": [], - "expanded": false, - "id": 4502, - "isTelemedicine": false, - "name": "Consultation with a general practitioner", - "paymentType": 2, - "type": 0 - }, - { - "actionCode": null, - "children": [], - "expanded": false, - "id": 4480, - "isTelemedicine": false, - "name": "Gynaecological consultation", - "paymentType": 2, - "type": 0 - } - ], - "expanded": true, - "id": 2, - "isTelemedicine": false, - "name": "Most popular", - "paymentType": 0, - "type": 2 - }, - { - "actionCode": "", - "children": [ - { - "actionCode": null, - "children": [], - "expanded": false, - "id": 4387, - "isTelemedicine": false, - "name": "Allergologist consultation", - "paymentType": 2, - "type": 0 - } - ], - "expanded": true, - "id": 1, - "isTelemedicine": false, - "name": "On-site consultations", - "paymentType": 0, - "type": 1 - }, - { - "actionCode": "", - "children": [ - { - "actionCode": null, - "children": [], - "expanded": false, - "id": 13764, - "isTelemedicine": true, - "name": "Telephone consultation - Allergist", - "paymentType": 2, - "type": 0 - }, - { - "actionCode": null, - "children": [], - "expanded": false, - "id": 13775, - "isTelemedicine": true, - "name": "Telephone consultation - Cardiologist", - "paymentType": 2, - "type": 0 - }, - { - "actionCode": null, - "children": [], - "expanded": false, - "id": 13800, - "isTelemedicine": true, - "name": "Telephone consultation - Dentist", - "paymentType": 2, - "type": 0 - }, - { - "actionCode": null, - "children": [], - "expanded": false, - "id": 13766, - "isTelemedicine": true, - "name": "Telephone consultation - Dermatologist", - "paymentType": 2, - "type": 0 - } - ], - "expanded": false, - "id": 13, - "isTelemedicine": false, - "name": "Telephone consultations", - "paymentType": 0, - "type": 1 - }, - { - "actionCode": "", - "children": [ - { - "actionCode": null, - "children": [], - "expanded": false, - "id": 8904, - "isTelemedicine": false, - "name": "Arranging an appointment with a dental surgeon", - "paymentType": 2, - "type": 0 - }, - { - "actionCode": null, - "children": [], - "expanded": false, - "id": 6817, - "isTelemedicine": false, - "name": "Arranging an appointment with a dental hygienist", - "paymentType": 2, - "type": 0 - }, - { - "actionCode": null, - "children": [], - "expanded": false, - "id": 6621, - "isTelemedicine": false, - "name": "Arranging an appointment with a dentist", - "paymentType": 2, - "type": 0 - } - ], - "expanded": false, - "id": 4, - "isTelemedicine": false, - "name": "Dentist", - "paymentType": 0, - "type": 1 - }, - { - "actionCode": "WIZYTY_DOMOWE", - "children": [], - "expanded": false, - "id": 14, - "isTelemedicine": false, - "name": "Home visits", - "paymentType": 0, - "type": 0 - }, - { - "actionCode": "NFZ", - "children": [], - "expanded": false, - "id": 12, - "isTelemedicine": false, - "name": "NHF visits", - "paymentType": 0, - "type": 0 - } -] - * - */ -case class DictionaryServiceVariants(override val id: Long, override val name: String, expanded: Boolean, children: List[DictionaryServiceVariants], isTelemedicine: Boolean, paymentType: Long) extends Identified with SerializableJsonObject { - def flatten: List[DictionaryServiceVariants] = List(this) ::: children.flatMap(_.flatten) + * [ + * { + * "actionCode": "", + * "children": [ + * { + * "actionCode": null, + * "children": [], + * "expanded": false, + * "id": 4502, + * "isTelemedicine": false, + * "name": "Consultation with a general practitioner", + * "paymentType": 2, + * "type": 0 + * }, + * { + * "actionCode": null, + * "children": [], + * "expanded": false, + * "id": 4480, + * "isTelemedicine": false, + * "name": "Gynaecological consultation", + * "paymentType": 2, + * "type": 0 + * } + * ], + * "expanded": true, + * "id": 2, + * "isTelemedicine": false, + * "name": "Most popular", + * "paymentType": 0, + * "type": 2 + * }, + * { + * "actionCode": "", + * "children": [ + * { + * "actionCode": null, + * "children": [], + * "expanded": false, + * "id": 4387, + * "isTelemedicine": false, + * "name": "Allergologist consultation", + * "paymentType": 2, + * "type": 0 + * } + * ], + * "expanded": true, + * "id": 1, + * "isTelemedicine": false, + * "name": "On-site consultations", + * "paymentType": 0, + * "type": 1 + * }, + * { + * "actionCode": "", + * "children": [ + * { + * "actionCode": null, + * "children": [], + * "expanded": false, + * "id": 13764, + * "isTelemedicine": true, + * "name": "Telephone consultation - Allergist", + * "paymentType": 2, + * "type": 0 + * }, + * { + * "actionCode": null, + * "children": [], + * "expanded": false, + * "id": 13775, + * "isTelemedicine": true, + * "name": "Telephone consultation - Cardiologist", + * "paymentType": 2, + * "type": 0 + * }, + * { + * "actionCode": null, + * "children": [], + * "expanded": false, + * "id": 13800, + * "isTelemedicine": true, + * "name": "Telephone consultation - Dentist", + * "paymentType": 2, + * "type": 0 + * }, + * { + * "actionCode": null, + * "children": [], + * "expanded": false, + * "id": 13766, + * "isTelemedicine": true, + * "name": "Telephone consultation - Dermatologist", + * "paymentType": 2, + * "type": 0 + * } + * ], + * "expanded": false, + * "id": 13, + * "isTelemedicine": false, + * "name": "Telephone consultations", + * "paymentType": 0, + * "type": 1 + * }, + * { + * "actionCode": "", + * "children": [ + * { + * "actionCode": null, + * "children": [], + * "expanded": false, + * "id": 8904, + * "isTelemedicine": false, + * "name": "Arranging an appointment with a dental surgeon", + * "paymentType": 2, + * "type": 0 + * }, + * { + * "actionCode": null, + * "children": [], + * "expanded": false, + * "id": 6817, + * "isTelemedicine": false, + * "name": "Arranging an appointment with a dental hygienist", + * "paymentType": 2, + * "type": 0 + * }, + * { + * "actionCode": null, + * "children": [], + * "expanded": false, + * "id": 6621, + * "isTelemedicine": false, + * "name": "Arranging an appointment with a dentist", + * "paymentType": 2, + * "type": 0 + * } + * ], + * "expanded": false, + * "id": 4, + * "isTelemedicine": false, + * "name": "Dentist", + * "paymentType": 0, + * "type": 1 + * }, + * { + * "actionCode": "WIZYTY_DOMOWE", + * "children": [], + * "expanded": false, + * "id": 14, + * "isTelemedicine": false, + * "name": "Home visits", + * "paymentType": 0, + * "type": 0 + * }, + * { + * "actionCode": "NFZ", + * "children": [], + * "expanded": false, + * "id": 12, + * "isTelemedicine": false, + * "name": "NHF visits", + * "paymentType": 0, + * "type": 0 + * } + * ] + */ +case class DictionaryServiceVariants( + override val id: Long, + override val name: String, + expanded: Boolean, + children: List[DictionaryServiceVariants], + isTelemedicine: Boolean, + paymentType: Long +) extends Identified + with SerializableJsonObject { + def flatten: List[DictionaryServiceVariants] = List(this) ::: children.flatMap(_.flatten) } diff --git a/api/src/main/scala/com/lbs/api/json/model/Doctor.scala b/api/src/main/scala/com/lbs/api/json/model/Doctor.scala index ab44d5c..efa4ba4 100644 --- a/api/src/main/scala/com/lbs/api/json/model/Doctor.scala +++ b/api/src/main/scala/com/lbs/api/json/model/Doctor.scala @@ -1,19 +1,26 @@ package com.lbs.api.json.model /** - * { - "academicTitle": "dr n. med.", - "facilityGroupIds": [ - 78 - ], - "firstName": "TARAS", - "id": 11111, - "isEnglishSpeaker": true, - "lastName": "SHEVCHENKO" - } - */ + * { + * "academicTitle": "dr n. med.", + * "facilityGroupIds": [ + * 78 + * ], + * "firstName": "TARAS", + * "id": 11111, + * "isEnglishSpeaker": true, + * "lastName": "SHEVCHENKO" + * } + */ -case class Doctor(academicTitle: String, facilityGroupIds: Option[List[Long]], firstName: String, isEnglishSpeaker: Option[Boolean], - genderId: Option[Long], id: Long, lastName: String) extends Identified { +case class Doctor( + academicTitle: String, + facilityGroupIds: Option[List[Long]], + firstName: String, + isEnglishSpeaker: Option[Boolean], + genderId: Option[Long], + id: Long, + lastName: String +) extends Identified { override def name: String = firstName + " " + lastName } diff --git a/api/src/main/scala/com/lbs/api/json/model/Empty.scala b/api/src/main/scala/com/lbs/api/json/model/Empty.scala index 59fdcb6..97b9c7d 100644 --- a/api/src/main/scala/com/lbs/api/json/model/Empty.scala +++ b/api/src/main/scala/com/lbs/api/json/model/Empty.scala @@ -1,7 +1,4 @@ - package com.lbs.api.json.model -/** -{} - */ +/** {} */ case class Empty() extends SerializableJsonObject diff --git a/api/src/main/scala/com/lbs/api/json/model/EventsResponse.scala b/api/src/main/scala/com/lbs/api/json/model/EventsResponse.scala index 9aabdf3..4ebd0b1 100644 --- a/api/src/main/scala/com/lbs/api/json/model/EventsResponse.scala +++ b/api/src/main/scala/com/lbs/api/json/model/EventsResponse.scala @@ -1,108 +1,114 @@ - package com.lbs.api.json.model import java.time.ZonedDateTime /** - * { - * "DataAvailableFrom": "2016-09-01T00:00:00+02:00", - * "Events": [ - * { - *"AutoConfirmationInfo": { - *"Message": null, - *"Type": "None" - *}, - *"Clinic": { - *"Address": "WOŁOWSKA 20", - *"City": "WROCŁAW", - *"Id": 42, - *"Name": "LX Wrocław - Wołowska 20" - *}, - *"ConfirmationInfo": null, - *"Date": "2021-06-02T07:45:00+02:00", - *"DateTo": "2021-06-02T08:15:00+02:00", - *"Doctor": { - *"Id": 111111, - *"Lastname": "SHEVCHENKO", - *"Name": "TARAS", - *"Sex": "Male", - *"Title": "lek. med." - *}, - *"DownloadLinks": [], - *"EventId": 2222222, - *"EventType": "Visit", - *"FromEreferral": false, - *"HasImpediments": false, - *"HasQuestionnaireBeforeService": false, - *"IsOverbooked": false, - *"IsPaymentRequired": false, - *"IsPreparationRequired": false, - *"IsServiceWithOverbookingRegularDistribution": true, - *"Links": [ - *{ - *"ApiVersion": 1, - *"Href": "/PatientPortalMobileAPI/api/events/reservation/Visit/2222222/detail", - *"Method": "GET", - *"Rel": "events_detail" - *}, - *{ - *"ApiVersion": 1, - *"Href": "/PatientPortalMobileAPI/api/events/Visit/2222222", - *"Method": "DELETE", - *"Rel": "delete_reservation" - *}, - *{ - *"ApiVersion": 1, - *"Href": "/PatientPortalMobileAPI/api/visits/reserved/2222222/can-term-be-changed", - *"Method": "GET", - *"Rel": "get_can_term_be_changed" - *} - *], - *"OnlinePaymentType": "Possible", - *"PaymentState": "None", - *"ReferralType": "None", - *"Status": "Reserved", - *"Title": "Internista", - *"Type": "Timeline_Visit_ReservedVisit" - *}, - *{ - *"Date": "2021-03-27T16:45:00+02:00", - *"DateTo": "2021-03-27T17:15:00+02:00", - *"Doctor": { - *"Id": 11111, - *"Lastname": "LESJA", - *"Name": "UKRAINKA", - *"Sex": "Female", - *"Title": "lek. med." - *}, - *"DownloadLinks": [], - *"EventId": 3333333, - *"EventType": "Telemedicine", - *"HasPrescription": false, - *"HasRecommendations": true, - *"HasReferrals": false, - *"IsServiceWithOverbookingRegularDistribution": true, - *"Links": [ - *{ - *"ApiVersion": 1, - *"Href": "/PatientPortalMobileAPI/api/events/reservation/Telemedicine/3333333/detail", - *"Method": "GET", - *"Rel": "events_detail" - *} - *], - *"ReferralType": "None", - *"Status": "Realized", - *"Title": "Centrum Leczenia Infekcji - konsultacja telefoniczna", - *"Type": "Timeline_Telemedicine_RealizedTelemedicineVisit" - *} - *], - *"IsEndOfList": false, - *"ServerDateTime": "2021-07-01T14:32:00+02:00" -*} + * { + * "DataAvailableFrom": "2016-09-01T00:00:00+02:00", + * "Events": [ + * { + * "AutoConfirmationInfo": { + * "Message": null, + * "Type": "None" + * }, + * "Clinic": { + * "Address": "WOŁOWSKA 20", + * "City": "WROCŁAW", + * "Id": 42, + * "Name": "LX Wrocław - Wołowska 20" + * }, + * "ConfirmationInfo": null, + * "Date": "2021-06-02T07:45:00+02:00", + * "DateTo": "2021-06-02T08:15:00+02:00", + * "Doctor": { + * "Id": 111111, + * "Lastname": "SHEVCHENKO", + * "Name": "TARAS", + * "Sex": "Male", + * "Title": "lek. med." + * }, + * "DownloadLinks": [], + * "EventId": 2222222, + * "EventType": "Visit", + * "FromEreferral": false, + * "HasImpediments": false, + * "HasQuestionnaireBeforeService": false, + * "IsOverbooked": false, + * "IsPaymentRequired": false, + * "IsPreparationRequired": false, + * "IsServiceWithOverbookingRegularDistribution": true, + * "Links": [ + * { + * "ApiVersion": 1, + * "Href": "/PatientPortalMobileAPI/api/events/reservation/Visit/2222222/detail", + * "Method": "GET", + * "Rel": "events_detail" + * }, + * { + * "ApiVersion": 1, + * "Href": "/PatientPortalMobileAPI/api/events/Visit/2222222", + * "Method": "DELETE", + * "Rel": "delete_reservation" + * }, + * { + * "ApiVersion": 1, + * "Href": "/PatientPortalMobileAPI/api/visits/reserved/2222222/can-term-be-changed", + * "Method": "GET", + * "Rel": "get_can_term_be_changed" + * } + * ], + * "OnlinePaymentType": "Possible", + * "PaymentState": "None", + * "ReferralType": "None", + * "Status": "Reserved", + * "Title": "Internista", + * "Type": "Timeline_Visit_ReservedVisit" + * }, + * { + * "Date": "2021-03-27T16:45:00+02:00", + * "DateTo": "2021-03-27T17:15:00+02:00", + * "Doctor": { + * "Id": 11111, + * "Lastname": "LESJA", + * "Name": "UKRAINKA", + * "Sex": "Female", + * "Title": "lek. med." + * }, + * "DownloadLinks": [], + * "EventId": 3333333, + * "EventType": "Telemedicine", + * "HasPrescription": false, + * "HasRecommendations": true, + * "HasReferrals": false, + * "IsServiceWithOverbookingRegularDistribution": true, + * "Links": [ + * { + * "ApiVersion": 1, + * "Href": "/PatientPortalMobileAPI/api/events/reservation/Telemedicine/3333333/detail", + * "Method": "GET", + * "Rel": "events_detail" + * } + * ], + * "ReferralType": "None", + * "Status": "Realized", + * "Title": "Centrum Leczenia Infekcji - konsultacja telefoniczna", + * "Type": "Timeline_Telemedicine_RealizedTelemedicineVisit" + * } + * ], + * "IsEndOfList": false, + * "ServerDateTime": "2021-07-01T14:32:00+02:00" + * } */ case class EventsResponse(events: List[Event]) extends SerializableJsonObject -case class Event(date: ZonedDateTime, clinic: Option[EventClinic], doctor: EventDoctor, eventId: Long, status: String, title: String) +case class Event( + date: ZonedDateTime, + clinic: Option[EventClinic], + doctor: EventDoctor, + eventId: Long, + status: String, + title: String +) case class EventClinic(address: String, city: String) diff --git a/api/src/main/scala/com/lbs/api/json/model/FacilitiesAndDoctors.scala b/api/src/main/scala/com/lbs/api/json/model/FacilitiesAndDoctors.scala index c826301..dc5fa87 100644 --- a/api/src/main/scala/com/lbs/api/json/model/FacilitiesAndDoctors.scala +++ b/api/src/main/scala/com/lbs/api/json/model/FacilitiesAndDoctors.scala @@ -1,42 +1,40 @@ - package com.lbs.api.json.model /** -{ - "doctors": [ - { - "academicTitle": "dr n. med.", - "facilityGroupIds": [ - 78 - ], - "firstName": "TARAS", - "id": 111111, - "isEnglishSpeaker": true, - "lastName": "SHEVCHENKO" - }, - { - "academicTitle": "lek. med.", - "facilityGroupIds": [ - 78, - 127 - ], - "firstName": "VLADIMIR", - "id": 22222, - "isEnglishSpeaker": false, - "lastName": "ZELENSKIY" - } - ], - "facilities": [ - { - "id": 78, - "name": "ul. Fabryczna 6" - }, - { - "id": 127, - "name": "ul. Kwidzyńska 6" - } - ] -} - * - */ + * { + * "doctors": [ + * { + * "academicTitle": "dr n. med.", + * "facilityGroupIds": [ + * 78 + * ], + * "firstName": "TARAS", + * "id": 111111, + * "isEnglishSpeaker": true, + * "lastName": "SHEVCHENKO" + * }, + * { + * "academicTitle": "lek. med.", + * "facilityGroupIds": [ + * 78, + * 127 + * ], + * "firstName": "VLADIMIR", + * "id": 22222, + * "isEnglishSpeaker": false, + * "lastName": "ZELENSKIY" + * } + * ], + * "facilities": [ + * { + * "id": 78, + * "name": "ul. Fabryczna 6" + * }, + * { + * "id": 127, + * "name": "ul. Kwidzyńska 6" + * } + * ] + * } + */ case class FacilitiesAndDoctors(doctors: List[Doctor], facilities: List[IdName]) extends SerializableJsonObject diff --git a/api/src/main/scala/com/lbs/api/json/model/ForgeryTokenResponse.scala b/api/src/main/scala/com/lbs/api/json/model/ForgeryTokenResponse.scala index 7d640c5..969b166 100644 --- a/api/src/main/scala/com/lbs/api/json/model/ForgeryTokenResponse.scala +++ b/api/src/main/scala/com/lbs/api/json/model/ForgeryTokenResponse.scala @@ -1,4 +1,3 @@ - package com.lbs.api.json.model /** diff --git a/api/src/main/scala/com/lbs/api/json/model/LoginResponse.scala b/api/src/main/scala/com/lbs/api/json/model/LoginResponse.scala index 48116ad..7ececab 100644 --- a/api/src/main/scala/com/lbs/api/json/model/LoginResponse.scala +++ b/api/src/main/scala/com/lbs/api/json/model/LoginResponse.scala @@ -1,4 +1,3 @@ - package com.lbs.api.json.model /** @@ -9,4 +8,5 @@ package com.lbs.api.json.model * "token_type": "bearer" * } */ -case class LoginResponse(accessToken: String, expiresIn: Int, refreshToken: String, tokenType: String) extends SerializableJsonObject +case class LoginResponse(accessToken: String, expiresIn: Int, refreshToken: String, tokenType: String) + extends SerializableJsonObject diff --git a/api/src/main/scala/com/lbs/api/json/model/LuxmedBaseError.scala b/api/src/main/scala/com/lbs/api/json/model/LuxmedBaseError.scala index f7c02b7..7abf093 100644 --- a/api/src/main/scala/com/lbs/api/json/model/LuxmedBaseError.scala +++ b/api/src/main/scala/com/lbs/api/json/model/LuxmedBaseError.scala @@ -1,4 +1,3 @@ - package com.lbs.api.json.model trait LuxmedBaseError { diff --git a/api/src/main/scala/com/lbs/api/json/model/LuxmedError.scala b/api/src/main/scala/com/lbs/api/json/model/LuxmedError.scala index c16d20f..273adc2 100644 --- a/api/src/main/scala/com/lbs/api/json/model/LuxmedError.scala +++ b/api/src/main/scala/com/lbs/api/json/model/LuxmedError.scala @@ -1,4 +1,3 @@ - package com.lbs.api.json.model -case class LuxmedError(message: String) extends SerializableJsonObject with LuxmedBaseError \ No newline at end of file +case class LuxmedError(message: String) extends SerializableJsonObject with LuxmedBaseError diff --git a/api/src/main/scala/com/lbs/api/json/model/LuxmedErrorsMap.scala b/api/src/main/scala/com/lbs/api/json/model/LuxmedErrorsMap.scala index 22c5bc3..e2fa48f 100644 --- a/api/src/main/scala/com/lbs/api/json/model/LuxmedErrorsMap.scala +++ b/api/src/main/scala/com/lbs/api/json/model/LuxmedErrorsMap.scala @@ -1,6 +1,5 @@ - package com.lbs.api.json.model case class LuxmedErrorsMap(errors: Map[String, List[String]]) extends SerializableJsonObject with LuxmedBaseError { override def message: String = errors.values.map(_.mkString("; ")).mkString("; ") -} \ No newline at end of file +} diff --git a/api/src/main/scala/com/lbs/api/json/model/ReservationChangetermRequest.scala b/api/src/main/scala/com/lbs/api/json/model/ReservationChangetermRequest.scala index cc124b6..1b25baf 100644 --- a/api/src/main/scala/com/lbs/api/json/model/ReservationChangetermRequest.scala +++ b/api/src/main/scala/com/lbs/api/json/model/ReservationChangetermRequest.scala @@ -1,43 +1,51 @@ - package com.lbs.api.json.model import java.time.LocalTime /** - * { - * "existingReservationId": 987654321, - *"term": { - *"date": "2021-07-03T05:30:00.000Z", - *"doctorId": 22222, - *"eReferralId": null, - *"facilityId": 33333, - *"parentReservationId": 987654321, - *"referralId": null, - *"referralRequired": false, - *"roomId": 55555, - *"scheduleId": 666666, - *"serviceVariantId": 777777, - *"temporaryReservationId": 8888888, - *"timeFrom": "08:30", - *"valuation": { - *"alternativePrice": null, - *"contractId": 99999, - *"isExternalReferralAllowed": false, - *"isReferralRequired": false, - *"payerId": 9111111, - *"price": 0, - *"productElementId": 9222222, - *"productId": 93333333, - *"productInContractId": 9444444, - *"requireReferralForPP": false, - *"valuationType": 1 - *}, - *"valuationId": null - *} -*} + * { + * "existingReservationId": 987654321, + * "term": { + * "date": "2021-07-03T05:30:00.000Z", + * "doctorId": 22222, + * "eReferralId": null, + * "facilityId": 33333, + * "parentReservationId": 987654321, + * "referralId": null, + * "referralRequired": false, + * "roomId": 55555, + * "scheduleId": 666666, + * "serviceVariantId": 777777, + * "temporaryReservationId": 8888888, + * "timeFrom": "08:30", + * "valuation": { + * "alternativePrice": null, + * "contractId": 99999, + * "isExternalReferralAllowed": false, + * "isReferralRequired": false, + * "payerId": 9111111, + * "price": 0, + * "productElementId": 9222222, + * "productId": 93333333, + * "productInContractId": 9444444, + * "requireReferralForPP": false, + * "valuationType": 1 + * }, + * "valuationId": null + * } */ case class ReservationChangetermRequest(existingReservationId: Long, term: NewTerm) extends SerializableJsonObject -case class NewTerm(date: String, doctorId: Long, facilityId: Long, parentReservationId: Long, referralRequired: Boolean, roomId: Long, - scheduleId: Long, serviceVariantId: Long, temporaryReservationId: Long, timeFrom: LocalTime, - valuation: Valuation) extends SerializableJsonObject +case class NewTerm( + date: String, + doctorId: Long, + facilityId: Long, + parentReservationId: Long, + referralRequired: Boolean, + roomId: Long, + scheduleId: Long, + serviceVariantId: Long, + temporaryReservationId: Long, + timeFrom: LocalTime, + valuation: Valuation +) extends SerializableJsonObject diff --git a/api/src/main/scala/com/lbs/api/json/model/ReservationConfirmRequest.scala b/api/src/main/scala/com/lbs/api/json/model/ReservationConfirmRequest.scala index c1f34f5..627cfb3 100644 --- a/api/src/main/scala/com/lbs/api/json/model/ReservationConfirmRequest.scala +++ b/api/src/main/scala/com/lbs/api/json/model/ReservationConfirmRequest.scala @@ -1,38 +1,45 @@ - package com.lbs.api.json.model import java.time.LocalTime - /** - * { - * "date": "2021-05-19T08:00:00.000Z", - *"doctorId": 111111, - *"eReferralId": null, - *"facilityId": 2222, - *"parentReservationId": null, - *"referralId": null, - *"referralRequired": false, - *"roomId": 1248, - *"scheduleId": 333333, - *"serviceVariantId": 444444, - *"temporaryReservationId": 4111111, - *"timeFrom": "18:45", - *"valuation": { - *"alternativePrice": null, - *"contractId": 555555, - *"isExternalReferralAllowed": false, - *"isReferralRequired": false, false, - *"payerId": 66666, - *"price": 0.0, - *"productElementId": 7777777, - *"productId": 888888, - *"productInContractId": 9999999, - *"requireReferralForPP": false, - *"valuationType": 1 - *}, - *"valuationId": null -*} + * { + * "date": "2021-05-19T08:00:00.000Z", + * "doctorId": 111111, + * "eReferralId": null, + * "facilityId": 2222, + * "parentReservationId": null, + * "referralId": null, + * "referralRequired": false, + * "roomId": 1248, + * "scheduleId": 333333, + * "serviceVariantId": 444444, + * "temporaryReservationId": 4111111, + * "timeFrom": "18:45", + * "valuation": { + * "alternativePrice": null, + * "contractId": 555555, + * "isExternalReferralAllowed": false, + * "isReferralRequired": false, false, + * "payerId": 66666, + * "price": 0.0, + * "productElementId": 7777777, + * "productId": 888888, + * "productInContractId": 9999999, + * "requireReferralForPP": false, + * "valuationType": 1 + * }, + * "valuationId": null + * } */ -case class ReservationConfirmRequest(date: String, doctorId: Long, facilityId: Long, roomId: Long, scheduleId: Long, serviceVariantId: Long, - temporaryReservationId: Long, timeFrom: LocalTime, valuation: Valuation) extends SerializableJsonObject +case class ReservationConfirmRequest( + date: String, + doctorId: Long, + facilityId: Long, + roomId: Long, + scheduleId: Long, + serviceVariantId: Long, + temporaryReservationId: Long, + timeFrom: LocalTime, + valuation: Valuation +) extends SerializableJsonObject diff --git a/api/src/main/scala/com/lbs/api/json/model/ReservationConfirmResponse.scala b/api/src/main/scala/com/lbs/api/json/model/ReservationConfirmResponse.scala index e9db58a..fa2c776 100644 --- a/api/src/main/scala/com/lbs/api/json/model/ReservationConfirmResponse.scala +++ b/api/src/main/scala/com/lbs/api/json/model/ReservationConfirmResponse.scala @@ -1,25 +1,34 @@ - package com.lbs.api.json.model - /** -{ - "errors": [], - "hasErrors": false, - "hasWarnings": false, - "value": { - "canSelfConfirm": false, - "eventType": 1, - "isTelemedicine": false, - "npsToken": "babababa-9282-1662-a525-ababbabaa", - "reservationId": 2222222, - "serviceInstanceId": 33333333 - }, - "warnings": [] -} + * { + * "errors": [], + * "hasErrors": false, + * "hasWarnings": false, + * "value": { + * "canSelfConfirm": false, + * "eventType": 1, + * "isTelemedicine": false, + * "npsToken": "babababa-9282-1662-a525-ababbabaa", + * "reservationId": 2222222, + * "serviceInstanceId": 33333333 + * }, + * "warnings": [] + * } */ -case class ReservationConfirmResponse(errors: List[String], warnings: List[String], hasErrors: Boolean, hasWarnings: Boolean, - value: ReservationConfirmValue) extends SerializableJsonObject +case class ReservationConfirmResponse( + errors: List[String], + warnings: List[String], + hasErrors: Boolean, + hasWarnings: Boolean, + value: ReservationConfirmValue +) extends SerializableJsonObject -case class ReservationConfirmValue(canSelfConfirm: Boolean, eventType: Long, isTelemedicine: Boolean, npsToken: String, - reservationId: Long, serviceInstanceId: Long) extends SerializableJsonObject +case class ReservationConfirmValue( + canSelfConfirm: Boolean, + eventType: Long, + isTelemedicine: Boolean, + npsToken: String, + reservationId: Long, + serviceInstanceId: Long +) extends SerializableJsonObject diff --git a/api/src/main/scala/com/lbs/api/json/model/ReservationLocktermRequest.scala b/api/src/main/scala/com/lbs/api/json/model/ReservationLocktermRequest.scala index 74fc2ea..a4f216d 100644 --- a/api/src/main/scala/com/lbs/api/json/model/ReservationLocktermRequest.scala +++ b/api/src/main/scala/com/lbs/api/json/model/ReservationLocktermRequest.scala @@ -1,42 +1,54 @@ - package com.lbs.api.json.model - /** - * { - * "correlationId": "00000000-0000-0000-0000-000000000000", - *"date": "2021-05-19T08:00:00.000Z", - *"doctor": { - *"academicTitle": "dr n.med.", - *"firstName": "TARAS", - *"id": 11111, - *"lastName": "SHEVCHENKO" - *}, - *"doctorId": 22222, - *"eReferralId": null, - *"facilityId": 33, - *"facilityName": "Telephone consultation", - *"impedimentText": "", - *"isAdditional": false, - *"isImpediment": false, - *"isPreparationRequired": false, - *"isTelemedicine": true, - *"parentReservationId": null, - *"preparationItems": [], - *"referralId": null, - *"referralTypeId": null, - *"roomId": 3333, - *"scheduleId": 444444, - *"serviceVariantId": 555555, - *"serviceVariantName": "Telephone consultation - General practitioner", - *"timeFrom": "12:00", - *"timeTo": "12:15" -*} + * { + * "correlationId": "00000000-0000-0000-0000-000000000000", + * "date": "2021-05-19T08:00:00.000Z", + * "doctor": { + * "academicTitle": "dr n.med.", + * "firstName": "TARAS", + * "id": 11111, + * "lastName": "SHEVCHENKO" + * }, + * "doctorId": 22222, + * "eReferralId": null, + * "facilityId": 33, + * "facilityName": "Telephone consultation", + * "impedimentText": "", + * "isAdditional": false, + * "isImpediment": false, + * "isPreparationRequired": false, + * "isTelemedicine": true, + * "parentReservationId": null, + * "preparationItems": [], + * "referralId": null, + * "referralTypeId": null, + * "roomId": 3333, + * "scheduleId": 444444, + * "serviceVariantId": 555555, + * "serviceVariantName": "Telephone consultation - General practitioner", + * "timeFrom": "12:00", + * "timeTo": "12:15" + * } */ -case class ReservationLocktermRequest(date: String, doctor: Doctor, doctorId: Long, eReferralId: String = null, - facilityId: Long, - impedimentText:String, isAdditional: Boolean, isImpediment: Boolean, - isPreparationRequired: Boolean, isTelemedicine: Boolean, parentReservationId: String = null, - preparationItems: List[PreparationItem], referralId: String = null, referralTypeId: String = null, - roomId: Long, scheduleId: Long, serviceVariantId: Long, - timeFrom: String, timeTo: String) extends SerializableJsonObject +case class ReservationLocktermRequest( + date: String, + doctor: Doctor, + doctorId: Long, + eReferralId: String = null, + facilityId: Long, + impedimentText: String, + isAdditional: Boolean, + isImpediment: Boolean, + isPreparationRequired: Boolean, + isTelemedicine: Boolean, + parentReservationId: String = null, + preparationItems: List[PreparationItem], + referralId: String = null, + referralTypeId: String = null, + roomId: Long, + scheduleId: Long, + serviceVariantId: Long, + timeFrom: String, + timeTo: String +) extends SerializableJsonObject diff --git a/api/src/main/scala/com/lbs/api/json/model/ReservationLocktermResponse.scala b/api/src/main/scala/com/lbs/api/json/model/ReservationLocktermResponse.scala index cbcdd35..f0e13b5 100644 --- a/api/src/main/scala/com/lbs/api/json/model/ReservationLocktermResponse.scala +++ b/api/src/main/scala/com/lbs/api/json/model/ReservationLocktermResponse.scala @@ -1,74 +1,88 @@ - package com.lbs.api.json.model import java.time.LocalTime - /** - * { - * "errors": [], - * "hasErrors": false, - * "hasWarnings": false, - *"value": { - *"askForReferral": false, - *"changeTermAvailable": true, - *"conflictedVisit": null, - *"doctorDetails": { - *"academicTitle": "lek. med.", - *"firstName": "TARAS", - *"genderId": 1, - *"id": 11111, - *"lastName": "SHEVCHENKO" - *}, - *"isBloodExamination": false, - *"isStomatology": false, - *"relatedVisits": [ - *{ - *"date": "2021-06-03T05:20:00", - *"doctor": { - *"academicTitle": "lek. med.", - *"firstName": "LESYA", - *"genderId": 2, - *"id": 0, - *"lastName": "UKRAINKA" - *}, - *"facilityName": "LX Wrocław - Szewska 3A", - *"isAsdk": false, - *"isTelemedicine": false, - *"payerName": null, - *"reservationId": 333333, - *"serviceInstanceId": 9999999, - *"serviceVariantId": 111111, - *"serviceVariantName": "Consultation with a general practitioner", - *"timeFrom": "07:30:00", - *"timeTo": "07:45:00" - *} - *], - *"temporaryReservationId": 222222, - *"valuations": [ - *{ - *"alternativePrice": null, - *"contractId": 333333, - *"isExternalReferralAllowed": false, - *"isReferralRequired": false, - *"payerId": 44444, - *"price": 0.0, - *"productElementId": 555555, - *"productId": 666666, - *"productInContractId": 777777, - *"requireReferralForPP": false, - *"valuationType": 1 - *} - *] - *}, - *"warnings": [] -*} + * { + * "errors": [], + * "hasErrors": false, + * "hasWarnings": false, + * "value": { + * "askForReferral": false, + * "changeTermAvailable": true, + * "conflictedVisit": null, + * "doctorDetails": { + * "academicTitle": "lek. med.", + * "firstName": "TARAS", + * "genderId": 1, + * "id": 11111, + * "lastName": "SHEVCHENKO" + * }, + * "isBloodExamination": false, + * "isStomatology": false, + * "relatedVisits": [ + * { + * "date": "2021-06-03T05:20:00", + * "doctor": { + * "academicTitle": "lek. med.", + * "firstName": "LESYA", + * "genderId": 2, + * "id": 0, + * "lastName": "UKRAINKA" + * }, + * "facilityName": "LX Wrocław - Szewska 3A", + * "isAsdk": false, + * "isTelemedicine": false, + * "payerName": null, + * "reservationId": 333333, + * "serviceInstanceId": 9999999, + * "serviceVariantId": 111111, + * "serviceVariantName": "Consultation with a general practitioner", + * "timeFrom": "07:30:00", + * "timeTo": "07:45:00" + * }], + * "temporaryReservationId": 222222, + * "valuations": [ + * { + * "alternativePrice": null, + * "contractId": 333333, + * "isExternalReferralAllowed": false, + * "isReferralRequired": false, + * "payerId": 44444, + * "price": 0.0, + * "productElementId": 555555, + * "productId": 666666, + * "productInContractId": 777777, + * "requireReferralForPP": false, + * "valuationType": 1 + * } + * ] + * }, + * "warnings": [] + * } */ -case class ReservationLocktermResponse(errors: List[String], warnings: List[String], hasErrors: Boolean, hasWarnings: Boolean, - value: ReservationLocktermResponseValue) extends SerializableJsonObject +case class ReservationLocktermResponse( + errors: List[String], + warnings: List[String], + hasErrors: Boolean, + hasWarnings: Boolean, + value: ReservationLocktermResponseValue +) extends SerializableJsonObject -case class ReservationLocktermResponseValue(changeTermAvailable: Boolean, conflictedVisit: Option[String], doctorDetails: Doctor, - relatedVisits: List[RelatedVisit], temporaryReservationId: Long, valuations: List[Valuation]) extends SerializableJsonObject +case class ReservationLocktermResponseValue( + changeTermAvailable: Boolean, + conflictedVisit: Option[String], + doctorDetails: Doctor, + relatedVisits: List[RelatedVisit], + temporaryReservationId: Long, + valuations: List[Valuation] +) extends SerializableJsonObject -case class RelatedVisit(doctor: Doctor, facilityName: String, isTelemedicine: Boolean, reservationId: Long, - timeFrom: LocalTime, timeTo: LocalTime) +case class RelatedVisit( + doctor: Doctor, + facilityName: String, + isTelemedicine: Boolean, + reservationId: Long, + timeFrom: LocalTime, + timeTo: LocalTime +) diff --git a/api/src/main/scala/com/lbs/api/json/model/SerializableJsonObject.scala b/api/src/main/scala/com/lbs/api/json/model/SerializableJsonObject.scala index 3a1ddf2..d019c41 100644 --- a/api/src/main/scala/com/lbs/api/json/model/SerializableJsonObject.scala +++ b/api/src/main/scala/com/lbs/api/json/model/SerializableJsonObject.scala @@ -1,4 +1,3 @@ - package com.lbs.api.json.model trait SerializableJsonObject diff --git a/api/src/main/scala/com/lbs/api/json/model/TermsIndexResponse.scala b/api/src/main/scala/com/lbs/api/json/model/TermsIndexResponse.scala index 080ca43..a2574b5 100644 --- a/api/src/main/scala/com/lbs/api/json/model/TermsIndexResponse.scala +++ b/api/src/main/scala/com/lbs/api/json/model/TermsIndexResponse.scala @@ -1,124 +1,122 @@ - package com.lbs.api.json.model import java.time.{LocalDateTime, ZonedDateTime} /** - * - * { - * "correlationId": "00000000-0000-0000-0000-000000000000", - * "pMode": 500, - * "termsForService": { - *"additionalData": { - *"anyTermForFacilityVisit": false, - *"anyTermForTelemedicine": true, - *"isPreparationRequired": false, - *"nextTermsAvailable": false, - *"preparationItems": [], - *"previousTermsAvailable": false - *}, - *"serviceVariantId": 111111, - *"termsForDays": [ - *{ - *"correlationId": "00000000-0000-0000-0000-000000000000", - *"day": "2022-05-31T00:00:00", - *"terms": [ - *{ - *"clinic": "LX Wrocław - Fabryczna 6", - *"clinicGroup": "ul. Fabryczna 6", - *"clinicGroupId": 11, - *"clinicId": 2222, - *"dateTimeFrom": "2021-05-21T18:45:00", or 2021-05-21T18:45:00+02:00 sometimes!!!! - *"dateTimeTo": "2021-05-21T19:00:00", - *"doctor": { - *"academicTitle": "lek. med.", - *"firstName": "TARAS", - *"genderId": 0, - *"id": 33333, - *"lastName": "GRYGORYCH" - *}, - *"impedimentText": "", - *"isAdditional": false, - *"isImpediment": false, - *"isInfectionTreatmentCenter": false, - *"isTelemedicine": true, - *"partOfDay": 3, - *"roomId": 4444, - *"scheduleId": 555555, - *"serviceId": 66666 - *}, - *{ - *"clinic": "LX Wrocław - Fabryczna 6", - *"clinicGroup": "ul. Fabryczna 6", - *"clinicGroupId": 77, - *"clinicId": 88888, - *"dateTimeFrom": "2021-05-21T18:45:00", - *"dateTimeTo": "2021-05-21T19:10:00", - *"doctor": { - *"academicTitle": "lek. med.", - *"firstName": "VASYL", - *"genderId": 0, - *"id": 99999, - *"lastName": "STUS" - *}, - *"impedimentText": "", - *"isAdditional": false, - *"isImpediment": false, - *"isInfectionTreatmentCenter": false, - *"isTelemedicine": true, - *"partOfDay": 3, - *"roomId": 11111, - *"scheduleId": 1222222, - *"serviceId": 133333 - *} - *] - *} - *], - *"termsInfoForDays": [ - *{ - *"day": "2021-05-22T00:00:00", - *"isLastDayWithLoadedTerms": true, - *"isLimitedDay": false, - *"isMoreTermsThanCounter": null, - *"message": "We can propose visits on the searched day but in other locations, at other doctors or another hour range.", - *"termsCounter": { - *"partialTermsCounters": [], - *"termsNumber": 41 - *}, - *"termsStatus": 0 - *}, - *{ - *"day": "2021-05-23T00:00:00", - *"isLastDayWithLoadedTerms": false, - *"isLimitedDay": false, - *"isMoreTermsThanCounter": null, - *"message": "Available visits have been already booked. Check later, additonal visits appear regularly.", - *"termsCounter": { - *"partialTermsCounters": [], - *"termsNumber": 0 - *}, - *"termsStatus": 5 - *}, - *{ - *"day": "2021-05-24T00:00:00", - *"isLastDayWithLoadedTerms": false, - *"isLimitedDay": false, - *"isMoreTermsThanCounter": null, - *"message": "Schedules for that day are not available yet. Check in 1 day.", - *"termsCounter": { - *"partialTermsCounters": [], - *"termsNumber": 0 - *}, - *"termsStatus": 4 - *} - *] - *} -*} - * - */ + * { + * "correlationId": "00000000-0000-0000-0000-000000000000", + * "pMode": 500, + * "termsForService": { + * "additionalData": { + * "anyTermForFacilityVisit": false, + * "anyTermForTelemedicine": true, + * "isPreparationRequired": false, + * "nextTermsAvailable": false, + * "preparationItems": [], + * "previousTermsAvailable": false + * }, + * "serviceVariantId": 111111, + * "termsForDays": [ + * { + * "correlationId": "00000000-0000-0000-0000-000000000000", + * "day": "2022-05-31T00:00:00", + * "terms": [ + * { + * "clinic": "LX Wrocław - Fabryczna 6", + * "clinicGroup": "ul. Fabryczna 6", + * "clinicGroupId": 11, + * "clinicId": 2222, + * "dateTimeFrom": "2021-05-21T18:45:00", or 2021-05-21T18:45:00+02:00 sometimes!!!! + * "dateTimeTo": "2021-05-21T19:00:00", + * "doctor": { + * "academicTitle": "lek. med.", + * "firstName": "TARAS", + * "genderId": 0, + * "id": 33333, + * "lastName": "GRYGORYCH" + * }, + * "impedimentText": "", + * "isAdditional": false, + * "isImpediment": false, + * "isInfectionTreatmentCenter": false, + * "isTelemedicine": true, + * "partOfDay": 3, + * "roomId": 4444, + * "scheduleId": 555555, + * "serviceId": 66666 + * }, + * { + * "clinic": "LX Wrocław - Fabryczna 6", + * "clinicGroup": "ul. Fabryczna 6", + * "clinicGroupId": 77, + * "clinicId": 88888, + * "dateTimeFrom": "2021-05-21T18:45:00", + * "dateTimeTo": "2021-05-21T19:10:00", + * "doctor": { + * "academicTitle": "lek. med.", + * "firstName": "VASYL", + * "genderId": 0, + * "id": 99999, + * "lastName": "STUS" + * }, + * "impedimentText": "", + * "isAdditional": false, + * "isImpediment": false, + * "isInfectionTreatmentCenter": false, + * "isTelemedicine": true, + * "partOfDay": 3, + * "roomId": 11111, + * "scheduleId": 1222222, + * "serviceId": 133333 + * } + * ] + * } + * ], + * "termsInfoForDays": [ + * { + * "day": "2021-05-22T00:00:00", + * "isLastDayWithLoadedTerms": true, + * "isLimitedDay": false, + * "isMoreTermsThanCounter": null, + * "message": "We can propose visits on the searched day but in other locations, at other doctors or another hour range.", + * "termsCounter": { + * "partialTermsCounters": [], + * "termsNumber": 41 + * }, + * "termsStatus": 0 + * }, + * { + * "day": "2021-05-23T00:00:00", + * "isLastDayWithLoadedTerms": false, + * "isLimitedDay": false, + * "isMoreTermsThanCounter": null, + * "message": "Available visits have been already booked. Check later, additonal visits appear regularly.", + * "termsCounter": { + * "partialTermsCounters": [], + * "termsNumber": 0 + * }, + * "termsStatus": 5 + * }, + * { + * "day": "2021-05-24T00:00:00", + * "isLastDayWithLoadedTerms": false, + * "isLimitedDay": false, + * "isMoreTermsThanCounter": null, + * "message": "Schedules for that day are not available yet. Check in 1 day.", + * "termsCounter": { + * "partialTermsCounters": [], + * "termsNumber": 0 + * }, + * "termsStatus": 4 + * } + * ] + * } + * } + */ case class TermsIndexResponse(correlationId: String, termsForService: TermsForService) extends SerializableJsonObject -case class TermsForService(additionalData: AdditionalData, termsForDays: List[TermsForDay]) extends SerializableJsonObject +case class TermsForService(additionalData: AdditionalData, termsForDays: List[TermsForDay]) + extends SerializableJsonObject case class PreparationItem(header: Option[String], text: Option[String]) @@ -126,13 +124,23 @@ case class AdditionalData(isPreparationRequired: Boolean, preparationItems: List case class TermsForDay(day: LuxmedFunnyDateTime, terms: List[Term]) extends SerializableJsonObject -case class Term(clinic: String, clinicId: Long, dateTimeFrom: LuxmedFunnyDateTime, dateTimeTo: LuxmedFunnyDateTime, doctor: Doctor, - impedimentText: String, isAdditional: Boolean, isImpediment: Boolean, isTelemedicine: Boolean, roomId: Long, - scheduleId: Long, serviceId: Long) extends SerializableJsonObject +case class Term( + clinic: String, + clinicId: Long, + dateTimeFrom: LuxmedFunnyDateTime, + dateTimeTo: LuxmedFunnyDateTime, + doctor: Doctor, + impedimentText: String, + isAdditional: Boolean, + isImpediment: Boolean, + isTelemedicine: Boolean, + roomId: Long, + scheduleId: Long, + serviceId: Long +) extends SerializableJsonObject -case class TermExt(additionalData: AdditionalData, term: Term) extends SerializableJsonObject +case class TermExt(additionalData: AdditionalData, term: Term) extends SerializableJsonObject case class LuxmedFunnyDateTime(dateTimeTz: Option[ZonedDateTime] = None, dateTimeLocal: Option[LocalDateTime] = None) { def get: LocalDateTime = dateTimeLocal.getOrElse(dateTimeTz.map(_.toLocalDateTime).get) } - diff --git a/api/src/main/scala/com/lbs/api/json/model/Valuation.scala b/api/src/main/scala/com/lbs/api/json/model/Valuation.scala index 55e24d5..2d1edf3 100644 --- a/api/src/main/scala/com/lbs/api/json/model/Valuation.scala +++ b/api/src/main/scala/com/lbs/api/json/model/Valuation.scala @@ -1,23 +1,31 @@ package com.lbs.api.json.model /** - * { - "alternativePrice": null, - "contractId": 555555, - "isExternalReferralAllowed": false, - "isReferralRequired": false, false, - "payerId": 66666, - "price": 0.0, - "productElementId": 7777777, - "productId": 888888, - "productInContractId": 9999999, - "requireReferralForPP": false, - "valuationType": 1 - } - */ + * { + * "alternativePrice": null, + * "contractId": 555555, + * "isExternalReferralAllowed": false, + * "isReferralRequired": false, false, + * "payerId": 66666, + * "price": 0.0, + * "productElementId": 7777777, + * "productId": 888888, + * "productInContractId": 9999999, + * "requireReferralForPP": false, + * "valuationType": 1 + * } + */ -case class Valuation(alternativePrice: Option[String], contractId: Long, isExternalReferralAllowed: Boolean, - isReferralRequired: Boolean, payerId: Long, price: Double, productElementId: Option[Long], productId: Long, - productInContractId: Long, requireReferralForPP: Boolean, valuationType: Long) { - -} +case class Valuation( + alternativePrice: Option[String], + contractId: Long, + isExternalReferralAllowed: Boolean, + isReferralRequired: Boolean, + payerId: Long, + price: Double, + productElementId: Option[Long], + productId: Long, + productInContractId: Long, + requireReferralForPP: Boolean, + valuationType: Long +) {} diff --git a/api/src/main/scala/com/lbs/api/package.scala b/api/src/main/scala/com/lbs/api/package.scala index 1812967..126e3cf 100644 --- a/api/src/main/scala/com/lbs/api/package.scala +++ b/api/src/main/scala/com/lbs/api/package.scala @@ -1,4 +1,3 @@ - package com.lbs import cats.MonadError diff --git a/api/src/test/scala/com/lbs/api/http/ExtendedHttpRequestSpec.scala b/api/src/test/scala/com/lbs/api/http/ExtendedHttpRequestSpec.scala index 43d2655..d4a936d 100644 --- a/api/src/test/scala/com/lbs/api/http/ExtendedHttpRequestSpec.scala +++ b/api/src/test/scala/com/lbs/api/http/ExtendedHttpRequestSpec.scala @@ -27,11 +27,17 @@ class ExtendedHttpRequestSpec extends AnyFunSuite with Matchers with MockitoSuga } test("error response") { - val errorResponse = HttpResponse("""{"Errors":{"ToDate.Date":["'To Date. Date' must be greater than or equal to '06/04/2018 00:00:00'."]}}""", 200, Map()) + val errorResponse = HttpResponse( + """{"Errors":{"ToDate.Date":["'To Date. Date' must be greater than or equal to '06/04/2018 00:00:00'."]}}""", + 200, + Map() + ) when(request.asString).thenReturn(errorResponse) val result = invoke(request) - assert(result == Left(GenericException(200, "'To Date. Date' must be greater than or equal to '06/04/2018 00:00:00'."))) + assert( + result == Left(GenericException(200, "'To Date. Date' must be greater than or equal to '06/04/2018 00:00:00'.")) + ) } private def invoke(request: HttpRequest) = { diff --git a/bot/src/main/scala/com/lbs/bot/Bot.scala b/bot/src/main/scala/com/lbs/bot/Bot.scala index 8caebef..99c186f 100644 --- a/bot/src/main/scala/com/lbs/bot/Bot.scala +++ b/bot/src/main/scala/com/lbs/bot/Bot.scala @@ -1,11 +1,10 @@ - package com.lbs.bot import com.lbs.bot.model._ import com.lbs.bot.telegram.TelegramBot import com.typesafe.scalalogging.LazyLogging -class Bot(telegram: TelegramBot /* other bots */) extends LazyLogging { +class Bot(telegram: TelegramBot /* other bots */ ) extends LazyLogging { def sendMessage(source: MessageSource, text: String): Unit = resolveAdapter(source).sendMessage(source.chatId, text) @@ -15,7 +14,12 @@ class Bot(telegram: TelegramBot /* other bots */) extends LazyLogging { def sendEditMessage(source: MessageSource, messageId: String, inlineKeyboard: Option[InlineKeyboard]): Unit = resolveAdapter(source).sendEditMessage(source.chatId, messageId, inlineKeyboard) - def sendEditMessage(source: MessageSource, messageId: String, text: String, inlineKeyboard: Option[InlineKeyboard] = None): Unit = + def sendEditMessage( + source: MessageSource, + messageId: String, + text: String, + inlineKeyboard: Option[InlineKeyboard] = None + ): Unit = resolveAdapter(source).sendEditMessage(source.chatId, messageId, text, inlineKeyboard) def sendFile(source: MessageSource, filename: String, contents: Array[Byte], caption: Option[String] = None): Unit = diff --git a/bot/src/main/scala/com/lbs/bot/PollBot.scala b/bot/src/main/scala/com/lbs/bot/PollBot.scala index 5227fea..1e4c54f 100644 --- a/bot/src/main/scala/com/lbs/bot/PollBot.scala +++ b/bot/src/main/scala/com/lbs/bot/PollBot.scala @@ -1,4 +1,3 @@ - package com.lbs.bot import com.lbs.bot.model.{Event, InlineKeyboard} diff --git a/bot/src/main/scala/com/lbs/bot/WebhookBot.scala b/bot/src/main/scala/com/lbs/bot/WebhookBot.scala index cd6abc1..b0336b7 100644 --- a/bot/src/main/scala/com/lbs/bot/WebhookBot.scala +++ b/bot/src/main/scala/com/lbs/bot/WebhookBot.scala @@ -1,4 +1,3 @@ - package com.lbs.bot import com.lbs.bot.model.Event diff --git a/bot/src/main/scala/com/lbs/bot/model/Button.scala b/bot/src/main/scala/com/lbs/bot/model/Button.scala index c117a28..e64ec3e 100644 --- a/bot/src/main/scala/com/lbs/bot/model/Button.scala +++ b/bot/src/main/scala/com/lbs/bot/model/Button.scala @@ -1,4 +1,3 @@ - package com.lbs.bot.model object Button { @@ -13,4 +12,4 @@ trait Button class TaggedButton(val label: String, val tag: String) extends Button -class LabeledButton(val label: String) extends Button \ No newline at end of file +class LabeledButton(val label: String) extends Button diff --git a/bot/src/main/scala/com/lbs/bot/model/Command.scala b/bot/src/main/scala/com/lbs/bot/model/Command.scala index 14f9b3e..4866d04 100644 --- a/bot/src/main/scala/com/lbs/bot/model/Command.scala +++ b/bot/src/main/scala/com/lbs/bot/model/Command.scala @@ -1,6 +1,5 @@ - package com.lbs.bot.model case class Message(messageId: String, text: Option[String] = None) -case class Command(source: MessageSource, message: Message, callbackData: Option[String] = None) \ No newline at end of file +case class Command(source: MessageSource, message: Message, callbackData: Option[String] = None) diff --git a/bot/src/main/scala/com/lbs/bot/model/Event.scala b/bot/src/main/scala/com/lbs/bot/model/Event.scala index 402d160..67c932d 100644 --- a/bot/src/main/scala/com/lbs/bot/model/Event.scala +++ b/bot/src/main/scala/com/lbs/bot/model/Event.scala @@ -1,4 +1,3 @@ - package com.lbs.bot.model trait Event diff --git a/bot/src/main/scala/com/lbs/bot/model/InlineKeyboard.scala b/bot/src/main/scala/com/lbs/bot/model/InlineKeyboard.scala index cfb7455..094a3fc 100644 --- a/bot/src/main/scala/com/lbs/bot/model/InlineKeyboard.scala +++ b/bot/src/main/scala/com/lbs/bot/model/InlineKeyboard.scala @@ -1,4 +1,3 @@ - package com.lbs.bot.model case class InlineKeyboard(buttons: Seq[Seq[Button]]) diff --git a/bot/src/main/scala/com/lbs/bot/model/MessageSource.scala b/bot/src/main/scala/com/lbs/bot/model/MessageSource.scala index 71e516e..baa9614 100644 --- a/bot/src/main/scala/com/lbs/bot/model/MessageSource.scala +++ b/bot/src/main/scala/com/lbs/bot/model/MessageSource.scala @@ -1,4 +1,3 @@ - package com.lbs.bot.model case class MessageSource(sourceSystem: MessageSourceSystem, chatId: String) diff --git a/bot/src/main/scala/com/lbs/bot/model/MessageSourceSystem.scala b/bot/src/main/scala/com/lbs/bot/model/MessageSourceSystem.scala index e426505..6fad02a 100644 --- a/bot/src/main/scala/com/lbs/bot/model/MessageSourceSystem.scala +++ b/bot/src/main/scala/com/lbs/bot/model/MessageSourceSystem.scala @@ -1,4 +1,3 @@ - package com.lbs.bot.model trait MessageSourceSystem { @@ -10,10 +9,7 @@ trait MessageSourceSystem { } object MessageSourceSystem { - val MessageSourceSystems: Seq[MessageSourceSystem] = Seq( - TelegramMessageSourceSystem, - FacebookMessageSourceSystem - ) + val MessageSourceSystems: Seq[MessageSourceSystem] = Seq(TelegramMessageSourceSystem, FacebookMessageSourceSystem) private val MessageSourceSystemsMap = MessageSourceSystems.map(e => e.id -> e).toMap diff --git a/bot/src/main/scala/com/lbs/bot/package.scala b/bot/src/main/scala/com/lbs/bot/package.scala index 31c11d9..a0a4ad5 100644 --- a/bot/src/main/scala/com/lbs/bot/package.scala +++ b/bot/src/main/scala/com/lbs/bot/package.scala @@ -1,4 +1,3 @@ - package com.lbs import com.lbs.bot.model.{Button, InlineKeyboard} diff --git a/bot/src/main/scala/com/lbs/bot/telegram/TelegramBot.scala b/bot/src/main/scala/com/lbs/bot/telegram/TelegramBot.scala index c6f21c1..54313b0 100644 --- a/bot/src/main/scala/com/lbs/bot/telegram/TelegramBot.scala +++ b/bot/src/main/scala/com/lbs/bot/telegram/TelegramBot.scala @@ -1,4 +1,3 @@ - package com.lbs.bot.telegram import com.bot4s.telegram.models.InlineKeyboardMarkup @@ -18,10 +17,19 @@ class TelegramBot(onCommand: Command => Unit, botToken: String) extends PollBot[ telegramBot.sendMessage(chatId.toLong, text, replyMarkup = buttons.map(_.mapTo[InlineKeyboardMarkup])) def sendEditMessage(chatId: String, messageId: String, buttons: Option[InlineKeyboard]): Unit = - telegramBot.sendEditMessage(chatId.toLong, messageId.toInt, replyMarkup = buttons.map(_.mapTo[InlineKeyboardMarkup])) + telegramBot.sendEditMessage( + chatId.toLong, + messageId.toInt, + replyMarkup = buttons.map(_.mapTo[InlineKeyboardMarkup]) + ) def sendEditMessage(chatId: String, messageId: String, text: String, buttons: Option[InlineKeyboard] = None): Unit = - telegramBot.sendEditMessage(chatId.toLong, messageId.toInt, text, replyMarkup = buttons.map(_.mapTo[InlineKeyboardMarkup])) + telegramBot.sendEditMessage( + chatId.toLong, + messageId.toInt, + text, + replyMarkup = buttons.map(_.mapTo[InlineKeyboardMarkup]) + ) def sendFile(chatId: String, filename: String, contents: Array[Byte], caption: Option[String] = None): Unit = telegramBot.sendFile(chatId.toLong, filename, contents, caption) @@ -29,4 +37,4 @@ class TelegramBot(onCommand: Command => Unit, botToken: String) extends PollBot[ override protected def onReceive(command: TelegramEvent): Unit = { onCommand(command.mapTo[Command]) } -} \ No newline at end of file +} diff --git a/bot/src/main/scala/com/lbs/bot/telegram/TelegramClient.scala b/bot/src/main/scala/com/lbs/bot/telegram/TelegramClient.scala index 0e12ad1..995ae01 100644 --- a/bot/src/main/scala/com/lbs/bot/telegram/TelegramClient.scala +++ b/bot/src/main/scala/com/lbs/bot/telegram/TelegramClient.scala @@ -1,4 +1,3 @@ - package com.lbs.bot.telegram import cats.implicits.toFunctorOps @@ -12,7 +11,13 @@ import com.typesafe.scalalogging.StrictLogging import scala.concurrent.Future -class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) extends AkkaTelegramBot with TelegramBoT with Polling with Commands[Future] with Callbacks[Future] with StrictLogging { +class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) + extends AkkaTelegramBot + with TelegramBoT + with Polling + with Commands[Future] + with Callbacks[Future] + with StrictLogging { override val client: RequestHandler[Future] = new AkkaHttpClient(botToken) @@ -22,11 +27,28 @@ class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) extends def sendMessage(chatId: Long, text: String, replyMarkup: Option[InlineKeyboardMarkup] = None): Future[Message] = loggingRequest(SendMessage(chatId, text, parseMode = Some(ParseMode.HTML), replyMarkup = replyMarkup)) - def sendEditMessage(chatId: Long, messageId: Int, replyMarkup: Option[InlineKeyboardMarkup]): Future[Either[Boolean, Message]] = + def sendEditMessage( + chatId: Long, + messageId: Int, + replyMarkup: Option[InlineKeyboardMarkup] + ): Future[Either[Boolean, Message]] = loggingRequest(EditMessageReplyMarkup(Some(chatId), Some(messageId), replyMarkup = replyMarkup)) - def sendEditMessage(chatId: Long, messageId: Int, text: String, replyMarkup: Option[InlineKeyboardMarkup] = None): Future[Either[Boolean, Message]] = - loggingRequest(EditMessageText(Some(chatId), Some(messageId), text = text, parseMode = Some(ParseMode.HTML), replyMarkup = replyMarkup)) + def sendEditMessage( + chatId: Long, + messageId: Int, + text: String, + replyMarkup: Option[InlineKeyboardMarkup] = None + ): Future[Either[Boolean, Message]] = + loggingRequest( + EditMessageText( + Some(chatId), + Some(messageId), + text = text, + parseMode = Some(ParseMode.HTML), + replyMarkup = replyMarkup + ) + ) def sendFile(chatId: Long, filename: String, contents: Array[Byte], caption: Option[String] = None): Future[Message] = loggingRequest(SendDocument(chatId, InputFile(filename, contents), caption = caption)) @@ -36,7 +58,6 @@ class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) extends request(req) } - override def receiveMessage(msg: Message): Future[Unit] = { logger.debug(s"Received telegram message: $msg") Future.successful(onReceive(TelegramEvent(msg, None))) @@ -51,4 +72,4 @@ class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) extends } yield onReceive(TelegramEvent(msg, Some(data))) ack.zip(Future.successful(maybeOnReceive)).void } -} \ No newline at end of file +} diff --git a/bot/src/main/scala/com/lbs/bot/telegram/TelegramEvent.scala b/bot/src/main/scala/com/lbs/bot/telegram/TelegramEvent.scala index 09f2137..5581c51 100644 --- a/bot/src/main/scala/com/lbs/bot/telegram/TelegramEvent.scala +++ b/bot/src/main/scala/com/lbs/bot/telegram/TelegramEvent.scala @@ -1,4 +1,3 @@ - package com.lbs.bot.telegram import com.bot4s.telegram.models.Message diff --git a/bot/src/main/scala/com/lbs/bot/telegram/package.scala b/bot/src/main/scala/com/lbs/bot/telegram/package.scala index 4e3a567..3e5ae2f 100644 --- a/bot/src/main/scala/com/lbs/bot/telegram/package.scala +++ b/bot/src/main/scala/com/lbs/bot/telegram/package.scala @@ -1,4 +1,3 @@ - package com.lbs.bot import com.bot4s.telegram.models.{InlineKeyboardButton, InlineKeyboardMarkup, Message => BMessage} @@ -10,8 +9,7 @@ package object telegram { protected[bot] val TagPrefix = "callback" object TelegramModelConverters extends ModelConverters { - implicit val TelegramCommandToCommandConverter: - ObjectConverter[TelegramEvent, Command] = + implicit val TelegramCommandToCommandConverter: ObjectConverter[TelegramEvent, Command] = (data: TelegramEvent) => { Command( source = MessageSource(TelegramMessageSourceSystem, data.msg.chat.id.toString), @@ -20,14 +18,12 @@ package object telegram { ) } - implicit val TelegramMessageToMessageConverter: - ObjectConverter[BMessage, Message] = + implicit val TelegramMessageToMessageConverter: ObjectConverter[BMessage, Message] = (data: BMessage) => { Message(data.messageId.toString, data.text) } - implicit val InlineKeyboardToInlineKeyboardMarkup: - ObjectConverter[InlineKeyboard, InlineKeyboardMarkup] = + implicit val InlineKeyboardToInlineKeyboardMarkup: ObjectConverter[InlineKeyboard, InlineKeyboardMarkup] = (inlineKeyboard: InlineKeyboard) => { val buttons = inlineKeyboard.buttons.map { row => row.map(createInlineKeyboardButton) @@ -37,7 +33,7 @@ package object telegram { private def createInlineKeyboardButton(button: Button) = { button match { - case b: TaggedButton => InlineKeyboardButton.callbackData(b.label, tag(b.tag)) + case b: TaggedButton => InlineKeyboardButton.callbackData(b.label, tag(b.tag)) case b: LabeledButton => InlineKeyboardButton.callbackData(b.label, b.label) } } diff --git a/build.gradle b/build.gradle index 2ba043a..3647942 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ plugins { id "com.github.maiflai.scalatest" version "0.32" id "org.springframework.boot" version "2.7.2" + id "cz.alenkacz.gradle.scalafmt" version "1.16.2" } allprojects { @@ -17,7 +18,7 @@ allprojects { compileOnly "org.scala-lang:scala-library:$scala.$scala_minor" testImplementation "org.scalatest:scalatest_$scala:3.2.11" - testRuntimeOnly 'com.vladsch.flexmark:flexmark-all:0.62.2' // version depends on scalatest dependency + testRuntimeOnly "com.vladsch.flexmark:flexmark-all:0.62.2" // version depends on scalatest dependency testImplementation "org.scalatestplus:mockito-4-2_$scala:3.2.11.0" testImplementation "org.pegdown:pegdown:1.6.0" diff --git a/common/src/main/scala/com/lbs/common/Implicits.scala b/common/src/main/scala/com/lbs/common/Implicits.scala index ff6abb8..1bcca14 100644 --- a/common/src/main/scala/com/lbs/common/Implicits.scala +++ b/common/src/main/scala/com/lbs/common/Implicits.scala @@ -1,4 +1,3 @@ - package com.lbs.common import java.util.Optional diff --git a/common/src/main/scala/com/lbs/common/ModelConverters.scala b/common/src/main/scala/com/lbs/common/ModelConverters.scala index a9ad3c7..5fbedda 100644 --- a/common/src/main/scala/com/lbs/common/ModelConverters.scala +++ b/common/src/main/scala/com/lbs/common/ModelConverters.scala @@ -1,7 +1,6 @@ - package com.lbs.common -import scala.collection.{BuildFrom, IterableOps} +import scala.collection.IterableOps import scala.language.implicitConversions trait ModelConverters { @@ -14,8 +13,9 @@ trait ModelConverters { def mapTo[To](implicit converter: ObjectConverter[From, To]): To = converter.convert(anyRef) } - implicit def sequenceConverters[From, To, Col[+X] <: IterableOps[X, Col, Col[X]]] - (implicit objectConverter: ObjectConverter[From, To]): ObjectConverter[Col[From], Col[To]] = + implicit def sequenceConverters[From, To, Col[+X] <: IterableOps[X, Col, Col[X]]](implicit + objectConverter: ObjectConverter[From, To] + ): ObjectConverter[Col[From], Col[To]] = (col: Col[From]) => col.map(objectConverter.convert) } diff --git a/common/src/main/scala/com/lbs/common/ParametrizedLock.scala b/common/src/main/scala/com/lbs/common/ParametrizedLock.scala index dc6f82a..56c9c6e 100644 --- a/common/src/main/scala/com/lbs/common/ParametrizedLock.scala +++ b/common/src/main/scala/com/lbs/common/ParametrizedLock.scala @@ -1,4 +1,3 @@ - package com.lbs.common import java.util.concurrent.ConcurrentHashMap diff --git a/common/src/main/scala/com/lbs/common/Scheduler.scala b/common/src/main/scala/com/lbs/common/Scheduler.scala index bca6a98..4fe9045 100644 --- a/common/src/main/scala/com/lbs/common/Scheduler.scala +++ b/common/src/main/scala/com/lbs/common/Scheduler.scala @@ -1,4 +1,3 @@ - package com.lbs.common import com.typesafe.scalalogging.LazyLogging @@ -18,13 +17,12 @@ class Scheduler(poolSize: Int) extends LazyLogging { scheduledThreadPool.scheduleAtFixedRate(silentFn(fn), delay.length, period.length, period.unit) } - private def silentFn(fn: => Unit): Runnable = { - () => - try { - fn - } catch { - case ex: Exception => - logger.error(s"Unable to execute scheduler task", ex) - } + private def silentFn(fn: => Unit): Runnable = { () => + try { + fn + } catch { + case ex: Exception => + logger.error(s"Unable to execute scheduler task", ex) + } } } diff --git a/server/src/main/scala/com/lbs/server/Boot.scala b/server/src/main/scala/com/lbs/server/Boot.scala index 9cd9263..178c36d 100644 --- a/server/src/main/scala/com/lbs/server/Boot.scala +++ b/server/src/main/scala/com/lbs/server/Boot.scala @@ -1,11 +1,9 @@ - package com.lbs.server import com.typesafe.scalalogging.StrictLogging import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication - @SpringBootApplication class Boot diff --git a/server/src/main/scala/com/lbs/server/BootConfig.scala b/server/src/main/scala/com/lbs/server/BootConfig.scala index f4df7a7..681a34b 100644 --- a/server/src/main/scala/com/lbs/server/BootConfig.scala +++ b/server/src/main/scala/com/lbs/server/BootConfig.scala @@ -1,4 +1,3 @@ - package com.lbs.server import akka.actor.ActorSystem @@ -44,23 +43,45 @@ class BootConfig { } @Bean - def authFactory: MessageSourceTo[Auth] = source => new Auth(source, - dataService, unauthorizedHelpFactory, loginFactory, chatFactory)(actorSystem) + def authFactory: MessageSourceTo[Auth] = source => + new Auth(source, dataService, unauthorizedHelpFactory, loginFactory, chatFactory)(actorSystem) @Bean - def loginFactory: MessageSourceWithOriginatorTo[Login] = (source, originator) => new Login(source, bot, - dataService, apiService, textEncryptor, localization, originator)(actorSystem) + def loginFactory: MessageSourceWithOriginatorTo[Login] = (source, originator) => + new Login(source, bot, dataService, apiService, textEncryptor, localization, originator)(actorSystem) @Bean - def bookFactory: UserIdTo[Book] = userId => new Book(userId, bot, apiService, dataService, - monitoringService, localization, datePickerFactory, timePickerFactory, staticDataFactory, termsPagerFactory)(actorSystem) + def bookFactory: UserIdTo[Book] = userId => + new Book( + userId, + bot, + apiService, + dataService, + monitoringService, + localization, + datePickerFactory, + timePickerFactory, + staticDataFactory, + termsPagerFactory + )(actorSystem) @Bean - def bookWithTemplateFactory: UserIdTo[BookWithTemplate] = userId => new BookWithTemplate(userId, bot, apiService, dataService, - monitoringService, localization, datePickerFactory, timePickerFactory, termsPagerFactory)(actorSystem) + def bookWithTemplateFactory: UserIdTo[BookWithTemplate] = userId => + new BookWithTemplate( + userId, + bot, + apiService, + dataService, + monitoringService, + localization, + datePickerFactory, + timePickerFactory, + termsPagerFactory + )(actorSystem) @Bean - def unauthorizedHelpFactory: MessageSourceTo[UnauthorizedHelp] = source => new UnauthorizedHelp(source, bot)(actorSystem) + def unauthorizedHelpFactory: MessageSourceTo[UnauthorizedHelp] = source => + new UnauthorizedHelp(source, bot)(actorSystem) @Bean def helpFactory: UserIdTo[Help] = userId => new Help(userId, bot, localization)(actorSystem) @@ -71,7 +92,15 @@ class BootConfig { @Bean def monitoringsHistoryFactory: UserIdTo[MonitoringsHistory] = - userId => new MonitoringsHistory(userId, bot, monitoringService, localization, monitoringsHistoryPagerFactory, bookWithTemplateFactory)(actorSystem) + userId => + new MonitoringsHistory( + userId, + bot, + monitoringService, + localization, + monitoringsHistoryPagerFactory, + bookWithTemplateFactory + )(actorSystem) @Bean def historyFactory: UserIdTo[HistoryViewer] = @@ -91,8 +120,20 @@ class BootConfig { @Bean def chatFactory: UserIdTo[Chat] = - userId => new Chat(userId, dataService, monitoringService, bookFactory, helpFactory, - monitoringsFactory, monitoringsHistoryFactory, historyFactory, reservedVisitsFactory, settingsFactory, accountFactory)(actorSystem) + userId => + new Chat( + userId, + dataService, + monitoringService, + bookFactory, + helpFactory, + monitoringsFactory, + monitoringsHistoryFactory, + historyFactory, + reservedVisitsFactory, + settingsFactory, + accountFactory + )(actorSystem) @Bean def datePickerFactory: UserIdWithOriginatorTo[DatePicker] = (userId, originator) => @@ -108,39 +149,63 @@ class BootConfig { @Bean def termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]] = (userId, originator) => - new Pager[TermExt](userId, bot, + new Pager[TermExt]( + userId, + bot, (term: TermExt, page: Int, index: Int) => lang(userId).termEntry(term, page, index), (page: Int, pages: Int) => lang(userId).termsHeader(page, pages), - Some("book"), localization, originator)(actorSystem) - + Some("book"), + localization, + originator + )(actorSystem) @Bean def reservedVisitsPagerFactory: UserIdWithOriginatorTo[Pager[Event]] = (userId, originator) => - new Pager[Event](userId, bot, + new Pager[Event]( + userId, + bot, (visit: Event, page: Int, index: Int) => lang(userId).reservedVisitEntry(visit, page, index), (page: Int, pages: Int) => lang(userId).reservedVisitsHeader(page, pages), - Some("cancel"), localization, originator)(actorSystem) + Some("cancel"), + localization, + originator + )(actorSystem) @Bean def historyPagerFactory: UserIdWithOriginatorTo[Pager[Event]] = (userId, originator) => - new Pager[Event](userId, bot, + new Pager[Event]( + userId, + bot, (event: Event, page: Int, index: Int) => lang(userId).historyEntry(event, page, index), (page: Int, pages: Int) => lang(userId).historyHeader(page, pages), - None, localization, originator)(actorSystem) + None, + localization, + originator + )(actorSystem) @Bean def monitoringsPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]] = (userId, originator) => - new Pager[Monitoring](userId, bot, + new Pager[Monitoring]( + userId, + bot, (monitoring: Monitoring, page: Int, index: Int) => lang(userId).monitoringEntry(monitoring, page, index), (page: Int, pages: Int) => lang(userId).monitoringsHeader(page, pages), - Some("cancel"), localization, originator)(actorSystem) + Some("cancel"), + localization, + originator + )(actorSystem) @Bean def monitoringsHistoryPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]] = (userId, originator) => - new Pager[Monitoring](userId, bot, + new Pager[Monitoring]( + userId, + bot, (monitoring: Monitoring, page: Int, index: Int) => lang(userId).monitoringHistoryEntry(monitoring, page, index), (page: Int, pages: Int) => lang(userId).monitoringsHistoryHeader(page, pages), - Some("repeat"), localization, originator)(actorSystem) + Some("repeat"), + localization, + originator + )(actorSystem) @Bean def router: Router = new Router(authFactory)(actorSystem) diff --git a/server/src/main/scala/com/lbs/server/conversation/Account.scala b/server/src/main/scala/com/lbs/server/conversation/Account.scala index bf204fe..5e02e8f 100644 --- a/server/src/main/scala/com/lbs/server/conversation/Account.scala +++ b/server/src/main/scala/com/lbs/server/conversation/Account.scala @@ -1,9 +1,8 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem +import com.lbs.bot._ import com.lbs.bot.model.Button -import com.lbs.bot.{Bot, _} import com.lbs.server.conversation.Account._ import com.lbs.server.conversation.Login._ import com.lbs.server.conversation.base.Conversation @@ -11,27 +10,37 @@ import com.lbs.server.lang.{Localizable, Localization} import com.lbs.server.service.DataService import com.lbs.server.util.MessageExtractors.CallbackCommand -class Account(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization, router: Router)(val actorSystem: ActorSystem) extends Conversation[Unit] with Localizable { +class Account(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization, router: Router)( + val actorSystem: ActorSystem +) extends Conversation[Unit] + with Localizable { entryPoint(askAction) def askAction: Step = ask { _ => val credentials = dataService.getUserCredentials(userId.userId) - val currentAccount = credentials.find(c => c.accountId == userId.accountId).getOrElse(sys.error("Can't determine current account")) - val buttons = Seq(Button(lang.addAccount, Tags.AddAccount), Button(lang.deleteAccount, Tags.DeleteAccount)) ++ credentials.map(c => Button(s"🔐️ ${c.username}", c.accountId)) - bot.sendMessage(userId.source, lang.pleaseChooseAccount(currentAccount.username), inlineKeyboard = createInlineKeyboard(buttons, columns = 1)) - } onReply { - case Msg(cmd@CallbackCommand(action), _) => - action match { - case Tags.AddAccount => - router ! cmd.copy(message = cmd.message.copy(text = Some("/login")), callbackData = None) - case Tags.DeleteAccount => - bot.sendMessage(userId.source, "Not implemented yet") - case accountId => - switchAccount(accountId.toLong) - } - end() + val currentAccount = + credentials.find(c => c.accountId == userId.accountId).getOrElse(sys.error("Can't determine current account")) + val buttons = Seq( + Button(lang.addAccount, Tags.AddAccount), + Button(lang.deleteAccount, Tags.DeleteAccount) + ) ++ credentials.map(c => Button(s"🔐️ ${c.username}", c.accountId)) + bot.sendMessage( + userId.source, + lang.pleaseChooseAccount(currentAccount.username), + inlineKeyboard = createInlineKeyboard(buttons, columns = 1) + ) + } onReply { case Msg(cmd @ CallbackCommand(action), _) => + action match { + case Tags.AddAccount => + router ! cmd.copy(message = cmd.message.copy(text = Some("/login")), callbackData = None) + case Tags.DeleteAccount => + bot.sendMessage(userId.source, "Not implemented yet") + case accountId => + switchAccount(accountId.toLong) + } + end() } private def switchAccount(accountId: Long): Unit = { @@ -60,4 +69,4 @@ object Account { val DeleteAccount = "delete_account" } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/Auth.scala b/server/src/main/scala/com/lbs/server/conversation/Auth.scala index bfdfdc4..1b4dff6 100644 --- a/server/src/main/scala/com/lbs/server/conversation/Auth.scala +++ b/server/src/main/scala/com/lbs/server/conversation/Auth.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem @@ -9,8 +8,15 @@ import com.lbs.server.service.DataService import com.lbs.server.util.MessageExtractors._ import com.typesafe.scalalogging.StrictLogging -class Auth(val source: MessageSource, dataService: DataService, unauthorizedHelpFactory: MessageSourceTo[UnauthorizedHelp], - loginFactory: MessageSourceWithOriginatorTo[Login], chatFactory: UserIdTo[Chat])(val actorSystem: ActorSystem) extends Conversation[Unit] with StrictLogging { +class Auth( + val source: MessageSource, + dataService: DataService, + unauthorizedHelpFactory: MessageSourceTo[UnauthorizedHelp], + loginFactory: MessageSourceWithOriginatorTo[Login], + chatFactory: UserIdTo[Chat] +)(val actorSystem: ActorSystem) + extends Conversation[Unit] + with StrictLogging { private val login = loginFactory(source, self) private val unauthorizedHelp = unauthorizedHelpFactory(source) @@ -22,13 +28,13 @@ class Auth(val source: MessageSource, dataService: DataService, unauthorizedHelp private def processIncoming = monologue { - case Msg(cmd@TextCommand("/help"), _) if userId.isEmpty => + case Msg(cmd @ TextCommand("/help"), _) if userId.isEmpty => unauthorizedHelp ! cmd stay() - case Msg(cmd@TextCommand("/start"), _) if userId.isEmpty => + case Msg(cmd @ TextCommand("/start"), _) if userId.isEmpty => unauthorizedHelp ! cmd stay() - case Msg(cmd@TextCommand("/login"), _) => + case Msg(cmd @ TextCommand("/login"), _) => userId = None login.restart() login ! cmd @@ -74,4 +80,4 @@ class Auth(val source: MessageSource, dataService: DataService, unauthorizedHelp unauthorizedHelp.destroy() if (chat != null) chat.destroy() } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/Book.scala b/server/src/main/scala/com/lbs/server/conversation/Book.scala index aa9bc0d..0af08c4 100644 --- a/server/src/main/scala/com/lbs/server/conversation/Book.scala +++ b/server/src/main/scala/com/lbs/server/conversation/Book.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem @@ -20,9 +19,21 @@ import com.lbs.server.util.ServerModelConverters._ import java.time.{LocalDateTime, LocalTime} -class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: DataService, monitoringService: MonitoringService, - val localization: Localization, datePickerFactory: UserIdWithOriginatorTo[DatePicker], timePickerFactory: UserIdWithOriginatorTo[TimePicker], - staticDataFactory: UserIdWithOriginatorTo[StaticData], termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]])(implicit val actorSystem: ActorSystem) extends Conversation[BookingData] with StaticDataForBooking with Localizable { +class Book( + val userId: UserId, + bot: Bot, + apiService: ApiService, + dataService: DataService, + monitoringService: MonitoringService, + val localization: Localization, + datePickerFactory: UserIdWithOriginatorTo[DatePicker], + timePickerFactory: UserIdWithOriginatorTo[TimePicker], + staticDataFactory: UserIdWithOriginatorTo[StaticData], + termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]] +)(implicit val actorSystem: ActorSystem) + extends Conversation[BookingData] + with StaticDataForBooking + with Localizable { private val datePicker = datePickerFactory(userId, self) private val timePicker = timePickerFactory(userId, self) @@ -36,7 +47,8 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da withFunctions[DictionaryCity]( latestOptions = dataService.getLatestCities(userId.accountId), staticOptions = apiService.getAllCities(userId.accountId), - applyId = id => bd.copy(cityId = id.toIdName)) + applyId = id => bd.copy(cityId = id.toIdName) + ) }(requestNext = askService) private def askService: Step = @@ -44,7 +56,8 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da withFunctions[DictionaryServiceVariants]( latestOptions = dataService.getLatestServicesByCityIdAndClinicId(userId.accountId, bd.cityId.id, None), staticOptions = apiService.getAllServices(userId.accountId), - applyId = id => bd.copy(serviceId = id.toIdName)) + applyId = id => bd.copy(serviceId = id.toIdName) + ) }(requestNext = askClinic) private def askClinic: Step = @@ -52,17 +65,27 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da withFunctions[IdName]( latestOptions = dataService.getLatestClinicsByCityId(userId.accountId, bd.cityId.id), staticOptions = apiService.getAllFacilities(userId.accountId, bd.cityId.id, bd.serviceId.id), - applyId = id => bd.copy(clinicId = id)) + applyId = id => bd.copy(clinicId = id) + ) }(requestNext = askDoctor) private def askDoctor: Step = staticData(doctorConfig) { bd: BookingData => withFunctions[IdName]( - latestOptions = dataService.getLatestDoctorsByCityIdAndClinicIdAndServiceId(userId.accountId, bd.cityId.id, bd.clinicId.optionalId, bd.serviceId.id), - staticOptions = apiService.getAllDoctors(userId.accountId, bd.cityId.id, bd.serviceId.id) - .map(_.filterNot(_.facilityGroupIds.exists(z => bd.clinicId == null || z.contains(bd.clinicId.id))) - .map(_.toIdName)), - applyId = id => bd.copy(doctorId = id.toIdName)) + latestOptions = dataService.getLatestDoctorsByCityIdAndClinicIdAndServiceId( + userId.accountId, + bd.cityId.id, + bd.clinicId.optionalId, + bd.serviceId.id + ), + staticOptions = apiService + .getAllDoctors(userId.accountId, bd.cityId.id, bd.serviceId.id) + .map( + _.filterNot(_.facilityGroupIds.exists(z => bd.clinicId == null || z.contains(bd.clinicId.id))) + .map(_.toIdName) + ), + applyId = id => bd.copy(doctorId = id.toIdName) + ) }(requestNext = requestDateFrom) private def requestDateFrom: Step = @@ -120,24 +143,35 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da private def requestAction: Step = ask { bookingData => dataService.storeAppointment(userId.accountId, bookingData) - bot.sendMessage(userId.source, + bot.sendMessage( + userId.source, lang.bookingSummary(bookingData), - inlineKeyboard = createInlineKeyboard( - Seq(Button(lang.findTerms, Tags.FindTerms), Button(lang.modifyDate, Tags.ModifyDate)) - )) + inlineKeyboard = + createInlineKeyboard(Seq(Button(lang.findTerms, Tags.FindTerms), Button(lang.modifyDate, Tags.ModifyDate))) + ) } onReply { case Msg(CallbackCommand(Tags.FindTerms), _) => goto(requestTerm) case Msg(CallbackCommand(Tags.ModifyDate), bookingData) => - goto(requestDateFrom) using bookingData.copy(dateFrom = LocalDateTime.now(), - dateTo = LocalDateTime.now().plusDays(1L)) + goto(requestDateFrom) using bookingData.copy( + dateFrom = LocalDateTime.now(), + dateTo = LocalDateTime.now().plusDays(1L) + ) } private def requestTerm: Step = ask { bookingData => - val availableTerms = apiService.getAvailableTerms(userId.accountId, bookingData.cityId.id, - bookingData.clinicId.optionalId, bookingData.serviceId.id, bookingData.doctorId.optionalId, - bookingData.dateFrom, bookingData.dateTo, timeFrom = bookingData.timeFrom, timeTo = bookingData.timeTo) + val availableTerms = apiService.getAvailableTerms( + userId.accountId, + bookingData.cityId.id, + bookingData.clinicId.optionalId, + bookingData.serviceId.id, + bookingData.doctorId.optionalId, + bookingData.dateFrom, + bookingData.dateTo, + timeFrom = bookingData.timeFrom, + timeTo = bookingData.timeTo + ) termsPager.restart() termsPager ! availableTerms.map(new SimpleItemsProvider(_)) } onReply { @@ -147,7 +181,11 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da case Msg(term: TermExt, bookingData) => val response = for { xsrfToken <- apiService.getXsrfToken(userId.accountId) - lockTermResponse <- apiService.reservationLockterm(userId.accountId, xsrfToken, term.mapTo[ReservationLocktermRequest]) + lockTermResponse <- apiService.reservationLockterm( + userId.accountId, + xsrfToken, + term.mapTo[ReservationLocktermRequest] + ) } yield (lockTermResponse, xsrfToken) response match { case Left(ex) => @@ -157,13 +195,28 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da case Right((reservationLocktermResponse, xsrfToken)) => if (reservationLocktermResponse.value.changeTermAvailable) { logger.warn(s"Service [${bookingData.serviceId.name}] is already booked. Ask to update term") - bot.sendMessage(userId.source, lang.visitAlreadyExists, - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))) - goto(awaitRebookDecision) using bookingData.copy(term = Some(term), xsrfToken = Some(xsrfToken), reservationLocktermResponse = Some(reservationLocktermResponse)) + bot.sendMessage( + userId.source, + lang.visitAlreadyExists, + inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))) + ) + goto(awaitRebookDecision) using bookingData.copy( + term = Some(term), + xsrfToken = Some(xsrfToken), + reservationLocktermResponse = Some(reservationLocktermResponse) + ) } else { - bot.sendMessage(userId.source, lang.confirmAppointment(term), - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book)))) - goto(awaitReservation) using bookingData.copy(term = Some(term), xsrfToken = Some(xsrfToken), reservationLocktermResponse = Some(reservationLocktermResponse)) + bot.sendMessage( + userId.source, + lang.confirmAppointment(term), + inlineKeyboard = + createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book))) + ) + goto(awaitReservation) using bookingData.copy( + term = Some(term), + xsrfToken = Some(xsrfToken), + reservationLocktermResponse = Some(reservationLocktermResponse) + ) } } case Msg(Pager.NoItemsFound, _) => @@ -172,17 +225,24 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da private def askNoTermsAction: Step = ask { _ => - bot.sendMessage(userId.source, lang.noTermsFound, inlineKeyboard = - createInlineKeyboard(Seq(Button(lang.modifyDate, Tags.ModifyDate), Button(lang.createMonitoring, Tags.CreateMonitoring)))) + bot.sendMessage( + userId.source, + lang.noTermsFound, + inlineKeyboard = createInlineKeyboard( + Seq(Button(lang.modifyDate, Tags.ModifyDate), Button(lang.createMonitoring, Tags.CreateMonitoring)) + ) + ) } onReply { case Msg(CallbackCommand(Tags.ModifyDate), bookingData) => - goto(requestDateFrom) using bookingData.copy(dateFrom = LocalDateTime.now(), - dateTo = LocalDateTime.now().plusDays(1L)) + goto(requestDateFrom) using bookingData.copy( + dateFrom = LocalDateTime.now(), + dateTo = LocalDateTime.now().plusDays(1L) + ) case Msg(CallbackCommand(Tags.CreateMonitoring), bookingData) => val settingsMaybe = dataService.findSettings(userId.userId) val (defaultOffset, askOffset) = settingsMaybe match { case Some(settings) => (settings.defaultOffset, settings.alwaysAskOffset) - case None => (0, false) + case None => (0, false) } val newData = bookingData.copy(offset = defaultOffset) if (askOffset) goto(askMonitoringOffsetOption) using newData @@ -192,8 +252,11 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da private def awaitRebookDecision: Step = monologue { case Msg(CallbackCommand(Tags.Yes), bookingData: BookingData) => - apiService.reservationChangeTerm(userId.accountId, bookingData.xsrfToken.get, - (bookingData.reservationLocktermResponse.get, bookingData.term.get).mapTo[ReservationChangetermRequest]) match { + apiService.reservationChangeTerm( + userId.accountId, + bookingData.xsrfToken.get, + (bookingData.reservationLocktermResponse.get, bookingData.term.get).mapTo[ReservationChangetermRequest] + ) match { case Right(success) => logger.debug(s"Successfully confirmed: $success") bot.sendMessage(userId.source, lang.appointmentIsConfirmed) @@ -210,7 +273,11 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da private def awaitReservation: Step = monologue { case Msg(CallbackCommand(Tags.Cancel), bookingData: BookingData) => - apiService.deleteTemporaryReservation(userId.accountId, bookingData.xsrfToken.get, bookingData.reservationLocktermResponse.get.value.temporaryReservationId) + apiService.deleteTemporaryReservation( + userId.accountId, + bookingData.xsrfToken.get, + bookingData.reservationLocktermResponse.get.value.temporaryReservationId + ) stay() case Msg(CallbackCommand(Tags.Book), bookingData: BookingData) => makeReservation(bookingData) @@ -239,8 +306,11 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da private def askMonitoringOffsetOption: Step = ask { _ => - bot.sendMessage(userId.source, lang.pleaseSpecifyOffset, - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No)))) + bot.sendMessage( + userId.source, + lang.pleaseSpecifyOffset, + inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No))) + ) } onReply { case Msg(TextCommand(IntString(offset)), bookingData: BookingData) => goto(askMonitoringAutobookOption) using bookingData.copy(offset = offset) @@ -250,22 +320,29 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da private def askMonitoringAutobookOption: Step = ask { _ => - bot.sendMessage(userId.source, lang.chooseTypeOfMonitoring, - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.bookByApplication, Tags.BookByApplication), Button(lang.bookManually, Tags.BookManually)), columns = 1)) - } onReply { - case Msg(CallbackCommand(BooleanString(autobook)), bookingData: BookingData) => - val data = bookingData.copy(autobook = autobook) - if (autobook) goto(askMonitoringRebookOption) using data - else goto(createMonitoring) using data + bot.sendMessage( + userId.source, + lang.chooseTypeOfMonitoring, + inlineKeyboard = createInlineKeyboard( + Seq(Button(lang.bookByApplication, Tags.BookByApplication), Button(lang.bookManually, Tags.BookManually)), + columns = 1 + ) + ) + } onReply { case Msg(CallbackCommand(BooleanString(autobook)), bookingData: BookingData) => + val data = bookingData.copy(autobook = autobook) + if (autobook) goto(askMonitoringRebookOption) using data + else goto(createMonitoring) using data } private def askMonitoringRebookOption: Step = ask { _ => - bot.sendMessage(userId.source, lang.rebookIfExists, - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))) - } onReply { - case Msg(CallbackCommand(BooleanString(rebookIfExists)), bookingData: BookingData) => - goto(createMonitoring) using bookingData.copy(rebookIfExists = rebookIfExists) + bot.sendMessage( + userId.source, + lang.rebookIfExists, + inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))) + ) + } onReply { case Msg(CallbackCommand(BooleanString(rebookIfExists)), bookingData: BookingData) => + goto(createMonitoring) using bookingData.copy(rebookIfExists = rebookIfExists) } private def createMonitoring: Step = @@ -300,12 +377,24 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da object Book { - case class BookingData(cityId: IdName = null, clinicId: IdName = null, - serviceId: IdName = null, doctorId: IdName = null, dateFrom: LocalDateTime = LocalDateTime.now(), - dateTo: LocalDateTime = LocalDateTime.now().plusDays(1L), timeFrom: LocalTime = LocalTime.of(7, 0), - timeTo: LocalTime = LocalTime.of(21, 0), autobook: Boolean = false, rebookIfExists: Boolean = false, - term: Option[TermExt] = None, reservationLocktermResponse: Option[ReservationLocktermResponse] = None, - offset: Int = 0, payerId: Long = 0, payers: Seq[IdName] = Seq(), xsrfToken: Option[XsrfToken] = None) + case class BookingData( + cityId: IdName = null, + clinicId: IdName = null, + serviceId: IdName = null, + doctorId: IdName = null, + dateFrom: LocalDateTime = LocalDateTime.now(), + dateTo: LocalDateTime = LocalDateTime.now().plusDays(1L), + timeFrom: LocalTime = LocalTime.of(7, 0), + timeTo: LocalTime = LocalTime.of(21, 0), + autobook: Boolean = false, + rebookIfExists: Boolean = false, + term: Option[TermExt] = None, + reservationLocktermResponse: Option[ReservationLocktermResponse] = None, + offset: Int = 0, + payerId: Long = 0, + payers: Seq[IdName] = Seq(), + xsrfToken: Option[XsrfToken] = None + ) object Tags { val Cancel = "cancel" diff --git a/server/src/main/scala/com/lbs/server/conversation/BookWithTemplate.scala b/server/src/main/scala/com/lbs/server/conversation/BookWithTemplate.scala index 633c227..d772064 100644 --- a/server/src/main/scala/com/lbs/server/conversation/BookWithTemplate.scala +++ b/server/src/main/scala/com/lbs/server/conversation/BookWithTemplate.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem @@ -19,9 +18,19 @@ import com.lbs.server.util.ServerModelConverters._ import java.time.{LocalDateTime, LocalTime} -class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dataService: DataService, monitoringService: MonitoringService, - val localization: Localization, datePickerFactory: UserIdWithOriginatorTo[DatePicker], timePickerFactory: UserIdWithOriginatorTo[TimePicker], - termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]])(implicit val actorSystem: ActorSystem) extends Conversation[BookingData] with Localizable { +class BookWithTemplate( + val userId: UserId, + bot: Bot, + apiService: ApiService, + dataService: DataService, + monitoringService: MonitoringService, + val localization: Localization, + datePickerFactory: UserIdWithOriginatorTo[DatePicker], + timePickerFactory: UserIdWithOriginatorTo[TimePicker], + termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]] +)(implicit val actorSystem: ActorSystem) + extends Conversation[BookingData] + with Localizable { private val datePicker = datePickerFactory(userId, self) private val timePicker = timePickerFactory(userId, self) @@ -30,18 +39,18 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat entryPoint(awaitMonitoring) private def awaitMonitoring: Step = - monologue { - case Msg(monitoring: Monitoring, _) => - val bookingData = BookingData( - cityId = IdName.from(monitoring.cityId, monitoring.cityName), - clinicId = IdName.from(monitoring.clinicId, monitoring.clinicName), - serviceId = IdName.from(monitoring.serviceId, monitoring.serviceName), - doctorId = IdName.from(monitoring.doctorId, monitoring.doctorName), - dateFrom = monitoring.dateFrom.toLocalDateTime, - dateTo = monitoring.dateTo.toLocalDateTime, - timeFrom = monitoring.timeFrom, - timeTo = monitoring.timeTo) - goto(requestDateFrom) using bookingData + monologue { case Msg(monitoring: Monitoring, _) => + val bookingData = BookingData( + cityId = IdName.from(monitoring.cityId, monitoring.cityName), + clinicId = IdName.from(monitoring.clinicId, monitoring.clinicName), + serviceId = IdName.from(monitoring.serviceId, monitoring.serviceName), + doctorId = IdName.from(monitoring.doctorId, monitoring.doctorName), + dateFrom = monitoring.dateFrom.toLocalDateTime, + dateTo = monitoring.dateTo.toLocalDateTime, + timeFrom = monitoring.timeFrom, + timeTo = monitoring.timeTo + ) + goto(requestDateFrom) using bookingData } private def requestDateFrom: Step = @@ -99,24 +108,35 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat private def requestAction: Step = ask { bookingData => dataService.storeAppointment(userId.accountId, bookingData) - bot.sendMessage(userId.source, + bot.sendMessage( + userId.source, lang.bookingSummary(bookingData), - inlineKeyboard = createInlineKeyboard( - Seq(Button(lang.findTerms, Tags.FindTerms), Button(lang.modifyDate, Tags.ModifyDate)) - )) + inlineKeyboard = + createInlineKeyboard(Seq(Button(lang.findTerms, Tags.FindTerms), Button(lang.modifyDate, Tags.ModifyDate))) + ) } onReply { case Msg(CallbackCommand(Tags.FindTerms), _) => goto(requestTerm) case Msg(CallbackCommand(Tags.ModifyDate), bookingData) => - goto(requestDateFrom) using bookingData.copy(dateFrom = LocalDateTime.now(), - dateTo = LocalDateTime.now().plusDays(1L)) + goto(requestDateFrom) using bookingData.copy( + dateFrom = LocalDateTime.now(), + dateTo = LocalDateTime.now().plusDays(1L) + ) } private def requestTerm: Step = ask { bookingData => - val availableTerms = apiService.getAvailableTerms(userId.accountId, bookingData.cityId.id, - bookingData.clinicId.optionalId, bookingData.serviceId.id, bookingData.doctorId.optionalId, - bookingData.dateFrom, bookingData.dateTo, timeFrom = bookingData.timeFrom, timeTo = bookingData.timeTo) + val availableTerms = apiService.getAvailableTerms( + userId.accountId, + bookingData.cityId.id, + bookingData.clinicId.optionalId, + bookingData.serviceId.id, + bookingData.doctorId.optionalId, + bookingData.dateFrom, + bookingData.dateTo, + timeFrom = bookingData.timeFrom, + timeTo = bookingData.timeTo + ) termsPager.restart() termsPager ! availableTerms.map(new SimpleItemsProvider(_)) } onReply { @@ -126,18 +146,32 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat case Msg(term: TermExt, bookingData) => val response = for { xsrfToken <- apiService.getXsrfToken(userId.accountId) - lockTermResponse <- apiService.reservationLockterm(userId.accountId, xsrfToken, term.mapTo[ReservationLocktermRequest]) + lockTermResponse <- apiService.reservationLockterm( + userId.accountId, + xsrfToken, + term.mapTo[ReservationLocktermRequest] + ) } yield (lockTermResponse, xsrfToken) response match { case Left(ex) => logger.warn(s"Service [${bookingData.serviceId.name}] is already booked. Ask to update term", ex) - bot.sendMessage(userId.source, lang.visitAlreadyExists, - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))) + bot.sendMessage( + userId.source, + lang.visitAlreadyExists, + inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))) + ) goto(awaitRebookDecision) using bookingData.copy(term = Some(term)) case Right((reservationLocktermResponse, xsrfToken)) => - bot.sendMessage(userId.source, lang.confirmAppointment(term), - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book)))) - goto(awaitReservation) using bookingData.copy(term = Some(term), xsrfToken = Some(xsrfToken), reservationLocktermResponse = Some(reservationLocktermResponse)) + bot.sendMessage( + userId.source, + lang.confirmAppointment(term), + inlineKeyboard = createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book))) + ) + goto(awaitReservation) using bookingData.copy( + term = Some(term), + xsrfToken = Some(xsrfToken), + reservationLocktermResponse = Some(reservationLocktermResponse) + ) } case Msg(Pager.NoItemsFound, _) => goto(askNoTermsAction) @@ -145,17 +179,24 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat private def askNoTermsAction: Step = ask { _ => - bot.sendMessage(userId.source, lang.noTermsFound, inlineKeyboard = - createInlineKeyboard(Seq(Button(lang.modifyDate, Tags.ModifyDate), Button(lang.createMonitoring, Tags.CreateMonitoring)))) + bot.sendMessage( + userId.source, + lang.noTermsFound, + inlineKeyboard = createInlineKeyboard( + Seq(Button(lang.modifyDate, Tags.ModifyDate), Button(lang.createMonitoring, Tags.CreateMonitoring)) + ) + ) } onReply { case Msg(CallbackCommand(Tags.ModifyDate), bookingData) => - goto(requestDateFrom) using bookingData.copy(dateFrom = LocalDateTime.now(), - dateTo = LocalDateTime.now().plusDays(1L)) + goto(requestDateFrom) using bookingData.copy( + dateFrom = LocalDateTime.now(), + dateTo = LocalDateTime.now().plusDays(1L) + ) case Msg(CallbackCommand(Tags.CreateMonitoring), bookingData) => val settingsMaybe = dataService.findSettings(userId.userId) val (defaultOffset, askOffset) = settingsMaybe match { case Some(settings) => (settings.defaultOffset, settings.alwaysAskOffset) - case None => (0, false) + case None => (0, false) } val newData = bookingData.copy(offset = defaultOffset) if (askOffset) goto(askMonitoringOffsetOption) using newData @@ -165,7 +206,11 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat private def awaitRebookDecision: Step = monologue { case Msg(CallbackCommand(Tags.Yes), bookingData: BookingData) => - apiService.reservationChangeTerm(userId.accountId, bookingData.xsrfToken.get, (bookingData.reservationLocktermResponse.get, bookingData.term.get).mapTo[ReservationChangetermRequest]) match { + apiService.reservationChangeTerm( + userId.accountId, + bookingData.xsrfToken.get, + (bookingData.reservationLocktermResponse.get, bookingData.term.get).mapTo[ReservationChangetermRequest] + ) match { case Right(success) => logger.debug(s"Successfully confirmed: $success") bot.sendMessage(userId.source, lang.appointmentIsConfirmed) @@ -182,7 +227,11 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat private def awaitReservation: Step = monologue { case Msg(CallbackCommand(Tags.Cancel), bookingData: BookingData) => - apiService.deleteTemporaryReservation(userId.accountId, bookingData.xsrfToken.get, bookingData.reservationLocktermResponse.get.value.temporaryReservationId) + apiService.deleteTemporaryReservation( + userId.accountId, + bookingData.xsrfToken.get, + bookingData.reservationLocktermResponse.get.value.temporaryReservationId + ) stay() case Msg(CallbackCommand(Tags.Book), bookingData: BookingData) => makeReservation(bookingData) @@ -211,8 +260,11 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat private def askMonitoringOffsetOption: Step = ask { _ => - bot.sendMessage(userId.source, lang.pleaseSpecifyOffset, - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No)))) + bot.sendMessage( + userId.source, + lang.pleaseSpecifyOffset, + inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No))) + ) } onReply { case Msg(TextCommand(IntString(offset)), bookingData: BookingData) => goto(askMonitoringAutobookOption) using bookingData.copy(offset = offset) @@ -222,22 +274,29 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat private def askMonitoringAutobookOption: Step = ask { _ => - bot.sendMessage(userId.source, lang.chooseTypeOfMonitoring, - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.bookByApplication, Tags.BookByApplication), Button(lang.bookManually, Tags.BookManually)), columns = 1)) - } onReply { - case Msg(CallbackCommand(BooleanString(autobook)), bookingData: BookingData) => - val data = bookingData.copy(autobook = autobook) - if (autobook) goto(askMonitoringRebookOption) using data - else goto(createMonitoring) using data + bot.sendMessage( + userId.source, + lang.chooseTypeOfMonitoring, + inlineKeyboard = createInlineKeyboard( + Seq(Button(lang.bookByApplication, Tags.BookByApplication), Button(lang.bookManually, Tags.BookManually)), + columns = 1 + ) + ) + } onReply { case Msg(CallbackCommand(BooleanString(autobook)), bookingData: BookingData) => + val data = bookingData.copy(autobook = autobook) + if (autobook) goto(askMonitoringRebookOption) using data + else goto(createMonitoring) using data } private def askMonitoringRebookOption: Step = ask { _ => - bot.sendMessage(userId.source, lang.rebookIfExists, - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))) - } onReply { - case Msg(CallbackCommand(BooleanString(rebookIfExists)), bookingData: BookingData) => - goto(createMonitoring) using bookingData.copy(rebookIfExists = rebookIfExists) + bot.sendMessage( + userId.source, + lang.rebookIfExists, + inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))) + ) + } onReply { case Msg(CallbackCommand(BooleanString(rebookIfExists)), bookingData: BookingData) => + goto(createMonitoring) using bookingData.copy(rebookIfExists = rebookIfExists) } private def createMonitoring: Step = @@ -260,5 +319,3 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat timePicker.destroy() } } - - diff --git a/server/src/main/scala/com/lbs/server/conversation/Chat.scala b/server/src/main/scala/com/lbs/server/conversation/Chat.scala index 05b55ab..65ca164 100644 --- a/server/src/main/scala/com/lbs/server/conversation/Chat.scala +++ b/server/src/main/scala/com/lbs/server/conversation/Chat.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem @@ -12,9 +11,21 @@ import com.typesafe.scalalogging.StrictLogging import scala.util.matching.Regex -class Chat(val userId: UserId, dataService: DataService, monitoringService: MonitoringService, bookingFactory: UserIdTo[Book], - helpFactory: UserIdTo[Help], monitoringsFactory: UserIdTo[Monitorings], monitoringsHistoryFactory: UserIdTo[MonitoringsHistory], historyFactory: UserIdTo[HistoryViewer], - visitsFactory: UserIdTo[ReservedVisitsViewer], settingsFactory: UserIdTo[Settings], accountFactory: UserIdTo[Account])(val actorSystem: ActorSystem) extends Conversation[Unit] with StrictLogging { +class Chat( + val userId: UserId, + dataService: DataService, + monitoringService: MonitoringService, + bookingFactory: UserIdTo[Book], + helpFactory: UserIdTo[Help], + monitoringsFactory: UserIdTo[Monitorings], + monitoringsHistoryFactory: UserIdTo[MonitoringsHistory], + historyFactory: UserIdTo[HistoryViewer], + visitsFactory: UserIdTo[ReservedVisitsViewer], + settingsFactory: UserIdTo[Settings], + accountFactory: UserIdTo[Account] +)(val actorSystem: ActorSystem) + extends Conversation[Unit] + with StrictLogging { private val book = bookingFactory(userId) private val help = helpFactory(userId) @@ -29,99 +40,91 @@ class Chat(val userId: UserId, dataService: DataService, monitoringService: Moni private def helpChat: Step = dialogue(help) { - case Msg(cmd@TextCommand("/help"), _) => + case Msg(cmd @ TextCommand("/help"), _) => help ! cmd stay() - case Msg(cmd@TextCommand("/start"), _) => + case Msg(cmd @ TextCommand("/start"), _) => help ! cmd stay() } private def bookChat: Step = - dialogue(book) { - case Msg(TextCommand("/book"), _) => - book.restart() - stay() + dialogue(book) { case Msg(TextCommand("/book"), _) => + book.restart() + stay() } private def historyChat: Step = - dialogue(history) { - case Msg(TextCommand("/history"), _) => - history.restart() - stay() + dialogue(history) { case Msg(TextCommand("/history"), _) => + history.restart() + stay() } private def visitsChat: Step = - dialogue(visits) { - case Msg(TextCommand("/reserved"), _) => - visits.restart() - stay() + dialogue(visits) { case Msg(TextCommand("/reserved"), _) => + visits.restart() + stay() } private def monitoringsChat: Step = - dialogue(monitorings) { - case Msg(TextCommand("/monitorings"), _) => - monitorings.restart() - stay() + dialogue(monitorings) { case Msg(TextCommand("/monitorings"), _) => + monitorings.restart() + stay() } private def monitoringsHistoryChat: Step = - dialogue(monitoringsHistory) { - case Msg(TextCommand("/monitorings_history"), _) => - monitoringsHistory.restart() - stay() + dialogue(monitoringsHistory) { case Msg(TextCommand("/monitorings_history"), _) => + monitoringsHistory.restart() + stay() } private def settingsChat: Step = - dialogue(settings) { - case Msg(TextCommand("/settings"), _) => - settings.restart() - stay() + dialogue(settings) { case Msg(TextCommand("/settings"), _) => + settings.restart() + stay() } private def accountChat: Step = - dialogue(account) { - case Msg(TextCommand("/accounts"), _) => - account.restart() - stay() + dialogue(account) { case Msg(TextCommand("/accounts"), _) => + account.restart() + stay() } private def dialogue(interactional: Interactional)(mainMessageProcessor: MessageProcessorFn): Step = - monologue { - case event: Msg => - if (mainMessageProcessor.isDefinedAt(event)) mainMessageProcessor(event) - else { - val defaultMessageProcessor = secondaryState(interactional) - defaultMessageProcessor(event) - } + monologue { case event: Msg => + if (mainMessageProcessor.isDefinedAt(event)) mainMessageProcessor(event) + else { + val defaultMessageProcessor = secondaryState(interactional) + defaultMessageProcessor(event) + } } private def secondaryState(interactional: Interactional): MessageProcessorFn = { - case Msg(cmd@TextCommand("/help"), _) => + case Msg(cmd @ TextCommand("/help"), _) => self ! cmd goto(helpChat) - case Msg(cmd@TextCommand("/start"), _) => + case Msg(cmd @ TextCommand("/start"), _) => self ! cmd goto(helpChat) - case Msg(cmd@TextCommand("/book"), _) => + case Msg(cmd @ TextCommand("/book"), _) => self ! cmd goto(bookChat) - case Msg(cmd@TextCommand("/monitorings"), _) => + case Msg(cmd @ TextCommand("/monitorings"), _) => self ! cmd goto(monitoringsChat) - case Msg(cmd@TextCommand("/monitorings_history"), _) => + case Msg(cmd @ TextCommand("/monitorings_history"), _) => self ! cmd goto(monitoringsHistoryChat) - case Msg(cmd@TextCommand("/history"), _) => + case Msg(cmd @ TextCommand("/history"), _) => self ! cmd goto(historyChat) - case Msg(cmd@TextCommand("/reserved"), _) => + case Msg(cmd @ TextCommand("/reserved"), _) => self ! cmd goto(visitsChat) - case Msg(cmd@TextCommand("/settings"), _) => + case Msg(cmd @ TextCommand("/settings"), _) => self ! cmd goto(settingsChat) - case Msg(cmd@TextCommand("/accounts"), _) => + case Msg(cmd @ TextCommand("/accounts"), _) => self ! cmd goto(accountChat) case Msg(TextCommand(ReserveTerm(monitoringIdStr, scheduleIdStr, timeStr)), _) => @@ -149,4 +152,4 @@ class Chat(val userId: UserId, dataService: DataService, monitoringService: Moni object Chat { val ReserveTerm: Regex = s"/reserve_(\\d+)_(\\d+)_(\\d+)".r -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/DatePicker.scala b/server/src/main/scala/com/lbs/server/conversation/DatePicker.scala index f181fb3..01e81bd 100644 --- a/server/src/main/scala/com/lbs/server/conversation/DatePicker.scala +++ b/server/src/main/scala/com/lbs/server/conversation/DatePicker.scala @@ -1,9 +1,8 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem +import com.lbs.bot._ import com.lbs.bot.model.Button -import com.lbs.bot.{Bot, _} import com.lbs.server.conversation.DatePicker._ import com.lbs.server.conversation.Login.UserId import com.lbs.server.conversation.base.{Conversation, Interactional} @@ -16,15 +15,16 @@ import java.time.{LocalDateTime, LocalTime} import scala.util.control.NonFatal /** - * Date picker Inline Keyboard - * - * ⬆ ⬆ ⬆ - * dd MM yyyy - * ⬇ ⬇ ⬇ - * - */ -class DatePicker(val userId: UserId, val bot: Bot, val localization: Localization, originator: Interactional) - (val actorSystem: ActorSystem) extends Conversation[LocalDateTime] with Localizable { + * Date picker Inline Keyboard + * + * ⬆ ⬆ ⬆ + * dd MM yyyy + * ⬇ ⬇ ⬇ + */ +class DatePicker(val userId: UserId, val bot: Bot, val localization: Localization, originator: Interactional)( + val actorSystem: ActorSystem +) extends Conversation[LocalDateTime] + with Localizable { private var mode: Mode = DateFromMode @@ -43,11 +43,11 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio ask { initialDate => val message = mode match { case DateFromMode => lang.chooseDateFrom(initialDate) - case DateToMode => lang.chooseDateTo(initialDate) + case DateToMode => lang.chooseDateTo(initialDate) } bot.sendMessage(userId.source, message, inlineKeyboard = dateButtons(initialDate)) } onReply { - case Msg(cmd@CallbackCommand(Tags.Done), finalDate) => + case Msg(cmd @ CallbackCommand(Tags.Done), finalDate) => val (message, updatedDate) = mode match { case DateFromMode => val startOfTheDay = finalDate.`with`(LocalTime.MIN) @@ -78,7 +78,7 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio bot.sendMessage(userId.source, "Incorrect date. Please use format dd-MM") goto(requestDate) } - case Msg(cmd@CallbackCommand(tag), date) => + case Msg(cmd @ CallbackCommand(tag), date) => val modifiedDate = modifyDate(date, tag) bot.sendEditMessage(userId.source, cmd.message.messageId, inlineKeyboard = dateButtons(modifiedDate)) stay() using modifiedDate @@ -86,12 +86,12 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio private def modifyDate(date: LocalDateTime, tag: String) = { val dateModifier = tag match { - case Tags.DayInc => date.plusDays _ + case Tags.DayInc => date.plusDays _ case Tags.MonthInc => date.plusMonths _ - case Tags.YearInc => date.plusYears _ - case Tags.DayDec => date.minusDays _ + case Tags.YearInc => date.plusYears _ + case Tags.DayDec => date.minusDays _ case Tags.MonthDec => date.minusMonths _ - case Tags.YearDec => date.minusYears _ + case Tags.YearDec => date.minusYears _ } dateModifier(1) } @@ -102,12 +102,14 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio val month = date.getMonth.getDisplayName(TextStyle.SHORT, lang.locale) val year = date.getYear.toString - createInlineKeyboard(Seq( - Seq(Button("⬆", Tags.DayInc), Button("⬆", Tags.MonthInc), Button("⬆", Tags.YearInc)), - Seq(Button(s"$day ($dayOfWeek)"), Button(month), Button(year)), - Seq(Button("⬇", Tags.DayDec), Button("⬇", Tags.MonthDec), Button("⬇", Tags.YearDec)), - Seq(Button("Done", Tags.Done)) - )) + createInlineKeyboard( + Seq( + Seq(Button("⬆", Tags.DayInc), Button("⬆", Tags.MonthInc), Button("⬆", Tags.YearInc)), + Seq(Button(s"$day ($dayOfWeek)"), Button(month), Button(year)), + Seq(Button("⬇", Tags.DayDec), Button("⬇", Tags.MonthDec), Button("⬇", Tags.YearDec)), + Seq(Button("Done", Tags.Done)) + ) + ) } } @@ -129,4 +131,4 @@ object DatePicker { val Done = "done" } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/Help.scala b/server/src/main/scala/com/lbs/server/conversation/Help.scala index aed07be..85f009d 100644 --- a/server/src/main/scala/com/lbs/server/conversation/Help.scala +++ b/server/src/main/scala/com/lbs/server/conversation/Help.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem @@ -8,14 +7,15 @@ import com.lbs.server.conversation.Login.UserId import com.lbs.server.conversation.base.Conversation import com.lbs.server.lang.{Localizable, Localization} -class Help(val userId: UserId, bot: Bot, val localization: Localization)(val actorSystem: ActorSystem) extends Conversation[Unit] with Localizable { +class Help(val userId: UserId, bot: Bot, val localization: Localization)(val actorSystem: ActorSystem) + extends Conversation[Unit] + with Localizable { entryPoint(displayHelp) def displayHelp: Step = - monologue { - case Msg(_: Command, _) => - bot.sendMessage(userId.source, lang.help) - stay() + monologue { case Msg(_: Command, _) => + bot.sendMessage(userId.source, lang.help) + stay() } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/HistoryViewer.scala b/server/src/main/scala/com/lbs/server/conversation/HistoryViewer.scala index b19d4d8..1b76ea9 100644 --- a/server/src/main/scala/com/lbs/server/conversation/HistoryViewer.scala +++ b/server/src/main/scala/com/lbs/server/conversation/HistoryViewer.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem @@ -11,8 +10,15 @@ import com.lbs.server.conversation.base.Conversation import com.lbs.server.lang.{Localizable, Localization} import com.lbs.server.service.ApiService -class HistoryViewer(val userId: UserId, bot: Bot, apiService: ApiService, val localization: Localization, - historyPagerFactory: UserIdWithOriginatorTo[Pager[Event]])(val actorSystem: ActorSystem) extends Conversation[Unit] with Localizable { +class HistoryViewer( + val userId: UserId, + bot: Bot, + apiService: ApiService, + val localization: Localization, + historyPagerFactory: UserIdWithOriginatorTo[Pager[Event]] +)(val actorSystem: ActorSystem) + extends Conversation[Unit] + with Localizable { private val historyPager = historyPagerFactory(userId, self) @@ -41,4 +47,4 @@ class HistoryViewer(val userId: UserId, bot: Bot, apiService: ApiService, val lo beforeDestroy { historyPager.destroy() } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/Login.scala b/server/src/main/scala/com/lbs/server/conversation/Login.scala index a42e5ca..05b8c34 100644 --- a/server/src/main/scala/com/lbs/server/conversation/Login.scala +++ b/server/src/main/scala/com/lbs/server/conversation/Login.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem @@ -11,8 +10,17 @@ import com.lbs.server.service.{ApiService, DataService} import com.lbs.server.util.MessageExtractors import org.jasypt.util.text.TextEncryptor -class Login(source: MessageSource, bot: Bot, dataService: DataService, apiService: ApiService, textEncryptor: TextEncryptor, - val localization: Localization, originator: Interactional)(val actorSystem: ActorSystem) extends Conversation[String] with Localizable { +class Login( + source: MessageSource, + bot: Bot, + dataService: DataService, + apiService: ApiService, + textEncryptor: TextEncryptor, + val localization: Localization, + originator: Interactional +)(val actorSystem: ActorSystem) + extends Conversation[String] + with Localizable { protected var userId: UserId = _ @@ -21,38 +29,35 @@ class Login(source: MessageSource, bot: Bot, dataService: DataService, apiServic private var forwardCommand: ForwardCommand = _ def logIn: Step = - monologue { - case Msg(cmd: Command, _) => - forwardCommand = ForwardCommand(cmd) - goto(requestUsername) + monologue { case Msg(cmd: Command, _) => + forwardCommand = ForwardCommand(cmd) + goto(requestUsername) } def requestUsername: Step = ask { _ => bot.sendMessage(source, lang.provideUsername) - } onReply { - case Msg(MessageExtractors.TextCommand(username), _) => - goto(requestPassword) using username + } onReply { case Msg(MessageExtractors.TextCommand(username), _) => + goto(requestPassword) using username } def requestPassword: Step = ask { _ => bot.sendMessage(source, lang.providePassword) - } onReply { - case Msg(MessageExtractors.TextCommand(plainPassword), username) => - val password = textEncryptor.encrypt(plainPassword) - apiService.fullLogin(username, password) match { - case Left(error) => - bot.sendMessage(source, error.getMessage) - goto(requestUsername) - case Right(session) => - val credentials = dataService.saveCredentials(source, username, password) - userId = UserId(credentials.userId, credentials.accountId, source) - apiService.addSession(credentials.accountId, session) - bot.sendMessage(source, lang.loginAndPasswordAreOk) - originator ! LoggedIn(forwardCommand, credentials.userId, credentials.accountId) - end() - } + } onReply { case Msg(MessageExtractors.TextCommand(plainPassword), username) => + val password = textEncryptor.encrypt(plainPassword) + apiService.fullLogin(username, password) match { + case Left(error) => + bot.sendMessage(source, error.getMessage) + goto(requestUsername) + case Right(session) => + val credentials = dataService.saveCredentials(source, username, password) + userId = UserId(credentials.userId, credentials.accountId, source) + apiService.addSession(credentials.accountId, session) + bot.sendMessage(source, lang.loginAndPasswordAreOk) + originator ! LoggedIn(forwardCommand, credentials.userId, credentials.accountId) + end() + } } } @@ -64,4 +69,4 @@ object Login { case class LoggedIn(forwardCommand: ForwardCommand, userId: Long, accountId: Long) -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/Monitorings.scala b/server/src/main/scala/com/lbs/server/conversation/Monitorings.scala index 7502226..fb8706c 100644 --- a/server/src/main/scala/com/lbs/server/conversation/Monitorings.scala +++ b/server/src/main/scala/com/lbs/server/conversation/Monitorings.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem @@ -12,7 +11,15 @@ import com.lbs.server.lang.{Localizable, Localization} import com.lbs.server.repository.model.Monitoring import com.lbs.server.service.MonitoringService -class Monitorings(val userId: UserId, bot: Bot, monitoringService: MonitoringService, val localization: Localization, monitoringsPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]])(val actorSystem: ActorSystem) extends Conversation[Monitoring] with Localizable { +class Monitorings( + val userId: UserId, + bot: Bot, + monitoringService: MonitoringService, + val localization: Localization, + monitoringsPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]] +)(val actorSystem: ActorSystem) + extends Conversation[Monitoring] + with Localizable { private val monitoringsPager = monitoringsPagerFactory(userId, self) @@ -40,8 +47,11 @@ class Monitorings(val userId: UserId, bot: Bot, monitoringService: MonitoringSer def askToDeactivateMonitoring: Step = ask { monitoring => - bot.sendMessage(userId.source, lang.deactivateMonitoring(monitoring), inlineKeyboard = - createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))) + bot.sendMessage( + userId.source, + lang.deactivateMonitoring(monitoring), + inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))) + ) } onReply { case Msg(Command(_, _, Some(Tags.No)), _) => bot.sendMessage(userId.source, lang.monitoringWasNotDeactivated) @@ -64,4 +74,4 @@ object Monitorings { val No = "no" } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/MonitoringsHistory.scala b/server/src/main/scala/com/lbs/server/conversation/MonitoringsHistory.scala index 0a186e1..9cf9237 100644 --- a/server/src/main/scala/com/lbs/server/conversation/MonitoringsHistory.scala +++ b/server/src/main/scala/com/lbs/server/conversation/MonitoringsHistory.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem @@ -11,7 +10,16 @@ import com.lbs.server.lang.{Localizable, Localization} import com.lbs.server.repository.model.Monitoring import com.lbs.server.service.MonitoringService -class MonitoringsHistory(val userId: UserId, bot: Bot, monitoringService: MonitoringService, val localization: Localization, monitoringsPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]], bookWithTemplateFactory: UserIdTo[BookWithTemplate])(val actorSystem: ActorSystem) extends Conversation[Monitoring] with Localizable { +class MonitoringsHistory( + val userId: UserId, + bot: Bot, + monitoringService: MonitoringService, + val localization: Localization, + monitoringsPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]], + bookWithTemplateFactory: UserIdTo[BookWithTemplate] +)(val actorSystem: ActorSystem) + extends Conversation[Monitoring] + with Localizable { private val monitoringsPager = monitoringsPagerFactory(userId, self) private val bookWithTemplate = bookWithTemplateFactory(userId) @@ -42,10 +50,9 @@ class MonitoringsHistory(val userId: UserId, bot: Bot, monitoringService: Monito ask { monitoring => bookWithTemplate.restart() bookWithTemplate ! monitoring - } onReply { - case Msg(cmd: Command, _) => - bookWithTemplate ! cmd - stay() + } onReply { case Msg(cmd: Command, _) => + bookWithTemplate ! cmd + stay() } beforeDestroy { @@ -62,7 +69,8 @@ class MonitoringsHistory(val userId: UserId, bot: Bot, monitoringService: Monito override def previous(): Unit = index -= 1 - override def items: Seq[Monitoring] = monitoringService.getMonitoringsPage(userId.accountId, index * Pager.PageSize, Pager.PageSize) + override def items: Seq[Monitoring] = + monitoringService.getMonitoringsPage(userId.accountId, index * Pager.PageSize, Pager.PageSize) override def currentPage: Int = index @@ -70,4 +78,3 @@ class MonitoringsHistory(val userId: UserId, bot: Bot, monitoringService: Monito } } - diff --git a/server/src/main/scala/com/lbs/server/conversation/Pager.scala b/server/src/main/scala/com/lbs/server/conversation/Pager.scala index 9246977..5e4b496 100644 --- a/server/src/main/scala/com/lbs/server/conversation/Pager.scala +++ b/server/src/main/scala/com/lbs/server/conversation/Pager.scala @@ -1,9 +1,8 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem -import com.lbs.bot.model.{Button, Command} import com.lbs.bot._ +import com.lbs.bot.model.{Button, Command} import com.lbs.server.conversation.Login.UserId import com.lbs.server.conversation.Pager._ import com.lbs.server.conversation.base.{Conversation, Interactional} @@ -11,10 +10,18 @@ import com.lbs.server.lang.{Localizable, Localization} import com.lbs.server.util.MessageExtractors import com.typesafe.scalalogging.StrictLogging -class Pager[Data](val userId: UserId, bot: Bot, makeMessage: (Data, Int, Int) => String, - makeHeader: (Int, Int) => String, selectionPrefix: Option[String], - val localization: Localization, originator: Interactional)(val actorSystem: ActorSystem) - extends Conversation[(ItemsProvider[Data], Option[String])] with Localizable with StrictLogging { +class Pager[Data]( + val userId: UserId, + bot: Bot, + makeMessage: (Data, Int, Int) => String, + makeHeader: (Int, Int) => String, + selectionPrefix: Option[String], + val localization: Localization, + originator: Interactional +)(val actorSystem: ActorSystem) + extends Conversation[(ItemsProvider[Data], Option[String])] + with Localizable + with StrictLogging { private val Selection = s"/${selectionPrefix.getOrElse("")}_(\\d+)".r @@ -49,10 +56,17 @@ class Pager[Data](val userId: UserId, bot: Bot, makeMessage: (Data, Int, Int) => } private def sendPage(itemsProvider: ItemsProvider[Data], messageId: Option[String] = None): Unit = { - val message = makeHeader(itemsProvider.currentPage, itemsProvider.pages) + "\n\n" + itemsProvider.items.zipWithIndex.map { case (d, index) => makeMessage(d, itemsProvider.currentPage, index) }.mkString + val message = + makeHeader(itemsProvider.currentPage, itemsProvider.pages) + "\n\n" + itemsProvider.items.zipWithIndex.map { + case (d, index) => + makeMessage(d, itemsProvider.currentPage, index) + }.mkString val previousButton = if (itemsProvider.currentPage > 0) Some(Button(lang.previous, Tags.Previous)) else None - val nextButton = if (itemsProvider.currentPage >= 0 && itemsProvider.currentPage < itemsProvider.pages - 1) Some(Button(lang.next, Tags.Next)) else None + val nextButton = + if (itemsProvider.currentPage >= 0 && itemsProvider.currentPage < itemsProvider.pages - 1) + Some(Button(lang.next, Tags.Next)) + else None val buttons = previousButton.toSeq ++ nextButton.toSeq messageId match { @@ -110,4 +124,4 @@ object Pager { val Next = "next" } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/ReservedVisitsViewer.scala b/server/src/main/scala/com/lbs/server/conversation/ReservedVisitsViewer.scala index 393218f..428cb69 100644 --- a/server/src/main/scala/com/lbs/server/conversation/ReservedVisitsViewer.scala +++ b/server/src/main/scala/com/lbs/server/conversation/ReservedVisitsViewer.scala @@ -1,10 +1,9 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem import com.lbs.api.json.model.Event +import com.lbs.bot._ import com.lbs.bot.model.{Button, Command} -import com.lbs.bot.{Bot, _} import com.lbs.server.conversation.Login.UserId import com.lbs.server.conversation.Pager.SimpleItemsProvider import com.lbs.server.conversation.ReservedVisitsViewer.Tags @@ -12,8 +11,15 @@ import com.lbs.server.conversation.base.Conversation import com.lbs.server.lang.{Localizable, Localization} import com.lbs.server.service.ApiService -class ReservedVisitsViewer(val userId: UserId, bot: Bot, apiService: ApiService, val localization: Localization, - visitsPagerFactory: UserIdWithOriginatorTo[Pager[Event]])(val actorSystem: ActorSystem) extends Conversation[Event] with Localizable { +class ReservedVisitsViewer( + val userId: UserId, + bot: Bot, + apiService: ApiService, + val localization: Localization, + visitsPagerFactory: UserIdWithOriginatorTo[Pager[Event]] +)(val actorSystem: ActorSystem) + extends Conversation[Event] + with Localizable { private val reservedVisitsPager = visitsPagerFactory(userId, self) @@ -41,8 +47,11 @@ class ReservedVisitsViewer(val userId: UserId, bot: Bot, apiService: ApiService, def askToCancelVisit: Step = ask { visit => - bot.sendMessage(userId.source, lang.areYouSureToCancelAppointment(visit), - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))) + bot.sendMessage( + userId.source, + lang.areYouSureToCancelAppointment(visit), + inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))) + ) } onReply { case Msg(Command(_, _, Some(Tags.No)), _) => bot.sendMessage(userId.source, lang.appointmentWasNotCancelled) @@ -67,4 +76,4 @@ object ReservedVisitsViewer { val No = "no" } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/Router.scala b/server/src/main/scala/com/lbs/server/conversation/Router.scala index 48915e6..c0ac4bd 100644 --- a/server/src/main/scala/com/lbs/server/conversation/Router.scala +++ b/server/src/main/scala/com/lbs/server/conversation/Router.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.{ActorSystem, Cancellable} @@ -11,7 +10,9 @@ import scala.collection.mutable import scala.concurrent.ExecutionContextExecutor import scala.concurrent.duration.DurationLong -class Router(authFactory: MessageSourceTo[Auth])(val actorSystem: ActorSystem) extends Conversation[Unit] with StrictLogging { +class Router(authFactory: MessageSourceTo[Auth])(val actorSystem: ActorSystem) + extends Conversation[Unit] + with StrictLogging { private case class DestroyChat(source: MessageSource) @@ -27,7 +28,7 @@ class Router(authFactory: MessageSourceTo[Auth])(val actorSystem: ActorSystem) e private def routeMessage: Step = monologue { - case Msg(cmd@Command(source, _, _), _) => + case Msg(cmd @ Command(source, _, _), _) => val chat = instantiateChatOrGet(source) chat ! cmd stay() @@ -73,4 +74,4 @@ class Router(authFactory: MessageSourceTo[Auth])(val actorSystem: ActorSystem) e beforeDestroy { chats.foreach(chat => destroyChat(chat._1)) } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/Settings.scala b/server/src/main/scala/com/lbs/server/conversation/Settings.scala index f62c02a..62b2c8f 100644 --- a/server/src/main/scala/com/lbs/server/conversation/Settings.scala +++ b/server/src/main/scala/com/lbs/server/conversation/Settings.scala @@ -1,9 +1,8 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem +import com.lbs.bot._ import com.lbs.bot.model.{Button, Command} -import com.lbs.bot.{Bot, _} import com.lbs.server.conversation.Login.UserId import com.lbs.server.conversation.Settings._ import com.lbs.server.conversation.base.Conversation @@ -12,15 +11,21 @@ import com.lbs.server.repository.model import com.lbs.server.service.DataService import com.lbs.server.util.MessageExtractors.{CallbackCommand, IntString, TextCommand} -class Settings(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization)(val actorSystem: ActorSystem) extends Conversation[Unit] with Localizable { +class Settings(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization)( + val actorSystem: ActorSystem +) extends Conversation[Unit] + with Localizable { entryPoint(askForAction) def askForAction: Step = ask { _ => - bot.sendMessage(userId.source, lang.settingsHeader, inlineKeyboard = - createInlineKeyboard(Seq(Button(lang.language, Tags.Language), - Button(lang.offset, Tags.Offset)), columns = 1)) + bot.sendMessage( + userId.source, + lang.settingsHeader, + inlineKeyboard = + createInlineKeyboard(Seq(Button(lang.language, Tags.Language), Button(lang.offset, Tags.Offset)), columns = 1) + ) } onReply { case Msg(Command(_, _, Some(Tags.Language)), _) => goto(askLanguage) @@ -30,29 +35,47 @@ class Settings(val userId: UserId, bot: Bot, dataService: DataService, val local def askLanguage: Step = ask { _ => - bot.sendMessage(userId.source, lang.chooseLanguage, - inlineKeyboard = createInlineKeyboard(Lang.Langs.map(l => Button(l.label, l.id)), columns = 1)) - } onReply { - case Msg(CallbackCommand(IntString(langId)), _) => - localization.updateLanguage(userId.userId, Lang(langId)) - bot.sendMessage(userId.source, lang.languageUpdated) - end() + bot.sendMessage( + userId.source, + lang.chooseLanguage, + inlineKeyboard = createInlineKeyboard(Lang.Langs.map(l => Button(l.label, l.id)), columns = 1) + ) + } onReply { case Msg(CallbackCommand(IntString(langId)), _) => + localization.updateLanguage(userId.userId, Lang(langId)) + bot.sendMessage(userId.source, lang.languageUpdated) + end() } def showOffsetOptions: Step = { ask { _ => val settings = getSettings - bot.sendMessage(userId.source, lang.configureOffset, - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.alwaysAskOffset(settings.alwaysAskOffset), Tags.ToggleAskOffsetOnOff), - Button(lang.changeDefaultOffset(settings.defaultOffset), Tags.ChangeDefaultOffset)), columns = 1)) + bot.sendMessage( + userId.source, + lang.configureOffset, + inlineKeyboard = createInlineKeyboard( + Seq( + Button(lang.alwaysAskOffset(settings.alwaysAskOffset), Tags.ToggleAskOffsetOnOff), + Button(lang.changeDefaultOffset(settings.defaultOffset), Tags.ChangeDefaultOffset) + ), + columns = 1 + ) + ) } onReply { - case Msg(cmd@CallbackCommand(Tags.ToggleAskOffsetOnOff), _) => + case Msg(cmd @ CallbackCommand(Tags.ToggleAskOffsetOnOff), _) => val settings = getSettings settings.alwaysAskOffset = !settings.alwaysAskOffset dataService.saveSettings(settings) - bot.sendEditMessage(userId.source, cmd.message.messageId, - inlineKeyboard = createInlineKeyboard(Seq(Button(lang.alwaysAskOffset(settings.alwaysAskOffset), Tags.ToggleAskOffsetOnOff), - Button(lang.changeDefaultOffset(settings.defaultOffset), Tags.ChangeDefaultOffset)), columns = 1)) + bot.sendEditMessage( + userId.source, + cmd.message.messageId, + inlineKeyboard = createInlineKeyboard( + Seq( + Button(lang.alwaysAskOffset(settings.alwaysAskOffset), Tags.ToggleAskOffsetOnOff), + Button(lang.changeDefaultOffset(settings.defaultOffset), Tags.ChangeDefaultOffset) + ), + columns = 1 + ) + ) stay() case Msg(CallbackCommand(Tags.ChangeDefaultOffset), _) => goto(askDefaultOffset) @@ -63,17 +86,18 @@ class Settings(val userId: UserId, bot: Bot, dataService: DataService, val local ask { _ => val settings = getSettings bot.sendMessage(userId.source, lang.pleaseEnterOffset(settings.defaultOffset)) - } onReply { - case Msg(TextCommand(IntString(offset)), _) => - val settings = getSettings - settings.defaultOffset = offset - dataService.saveSettings(settings) - goto(showOffsetOptions) + } onReply { case Msg(TextCommand(IntString(offset)), _) => + val settings = getSettings + settings.defaultOffset = offset + dataService.saveSettings(settings) + goto(showOffsetOptions) } } private def getSettings = { - dataService.findSettings(userId.userId).getOrElse(model.Settings(userId.userId, lang.id, 0, alwaysAskOffset = false)) + dataService + .findSettings(userId.userId) + .getOrElse(model.Settings(userId.userId, lang.id, 0, alwaysAskOffset = false)) } } @@ -86,4 +110,4 @@ object Settings { val ChangeDefaultOffset = "change_default_offset" } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/StaticData.scala b/server/src/main/scala/com/lbs/server/conversation/StaticData.scala index 7db57d6..66b1805 100644 --- a/server/src/main/scala/com/lbs/server/conversation/StaticData.scala +++ b/server/src/main/scala/com/lbs/server/conversation/StaticData.scala @@ -1,17 +1,19 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem import com.lbs.api.json.model.{IdName, Identified} +import com.lbs.bot._ import com.lbs.bot.model.{Button, Command, TaggedButton} -import com.lbs.bot.{Bot, _} import com.lbs.server.ThrowableOr import com.lbs.server.conversation.Login.UserId import com.lbs.server.conversation.StaticData._ import com.lbs.server.conversation.base.{Conversation, Interactional} import com.lbs.server.lang.{Localizable, Localization} -class StaticData(val userId: UserId, bot: Bot, val localization: Localization, originator: Interactional)(val actorSystem: ActorSystem) extends Conversation[List[TaggedButton]] with Localizable { +class StaticData(val userId: UserId, bot: Bot, val localization: Localization, originator: Interactional)( + val actorSystem: ActorSystem +) extends Conversation[List[TaggedButton]] + with Localizable { private def anySelectOption: List[TaggedButton] = if (config.isAnyAllowed) List(Button(lang.any, -1L)) else List() @@ -20,10 +22,9 @@ class StaticData(val userId: UserId, bot: Bot, val localization: Localization, o entryPoint(AwaitConfig) def AwaitConfig: Step = - monologue { - case Msg(newConfig: StaticDataConfig, _) => - config = newConfig - goto(askForLatestOption) + monologue { case Msg(newConfig: StaticDataConfig, _) => + config = newConfig + goto(askForLatestOption) } def askForLatestOption: Step = @@ -40,12 +41,16 @@ class StaticData(val userId: UserId, bot: Bot, val localization: Localization, o def askForUserInput: Step = ask { callbackTags => - bot.sendMessage(userId.source, lang.pleaseEnterStaticDataNameOrPrevious(config), - inlineKeyboard = createInlineKeyboard(callbackTags, columns = 1)) + bot.sendMessage( + userId.source, + lang.pleaseEnterStaticDataNameOrPrevious(config), + inlineKeyboard = createInlineKeyboard(callbackTags, columns = 1) + ) } onReply { case Msg(Command(_, msg, Some(tag)), callbackTags) => val id = tag.toLong - val label = callbackTags.find(_.tag == tag).map(_.label).getOrElse(sys.error("Unable to get callback tag label")) + val label = + callbackTags.find(_.tag == tag).map(_.label).getOrElse(sys.error("Unable to get callback tag label")) bot.sendEditMessage(userId.source, msg.messageId, lang.staticDataIs(config, label)) originator ! IdName(id, label) end() @@ -81,4 +86,4 @@ object StaticData { case class FoundOptions[T <: Identified](option: ThrowableOr[List[T]]) -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/StaticDataForBooking.scala b/server/src/main/scala/com/lbs/server/conversation/StaticDataForBooking.scala index c151e84..50342ae 100644 --- a/server/src/main/scala/com/lbs/server/conversation/StaticDataForBooking.scala +++ b/server/src/main/scala/com/lbs/server/conversation/StaticDataForBooking.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import com.lbs.api.json.model.{IdName, Identified} @@ -12,8 +11,12 @@ trait StaticDataForBooking extends Conversation[BookingData] { private[conversation] def staticData: StaticData - protected def withFunctions[T <: Identified](latestOptions: => Seq[IdName], staticOptions: => ThrowableOr[List[T]], applyId: IdName => BookingData): Step => MessageProcessorFn = { - nextStep: Step => { + protected def withFunctions[T <: Identified]( + latestOptions: => Seq[IdName], + staticOptions: => ThrowableOr[List[T]], + applyId: IdName => BookingData + ): Step => MessageProcessorFn = { nextStep: Step => + { case Msg(cmd: Command, _) => staticData ! cmd stay() @@ -28,14 +31,15 @@ trait StaticDataForBooking extends Conversation[BookingData] { } } - protected def staticData(staticDataConfig: => StaticDataConfig)(functions: BookingData => Step => MessageProcessorFn)(requestNext: Step)(implicit functionName: sourcecode.Name): Step = { + protected def staticData(staticDataConfig: => StaticDataConfig)( + functions: BookingData => Step => MessageProcessorFn + )(requestNext: Step)(implicit functionName: sourcecode.Name): Step = { ask { _ => staticData.restart() staticData ! staticDataConfig - } onReply { - case msg@Msg(_, bookingData: BookingData) => - val fn = functions(bookingData)(requestNext) - fn(msg) + } onReply { case msg @ Msg(_, bookingData: BookingData) => + val fn = functions(bookingData)(requestNext) + fn(msg) } } diff --git a/server/src/main/scala/com/lbs/server/conversation/TimePicker.scala b/server/src/main/scala/com/lbs/server/conversation/TimePicker.scala index b7caf91..abd0bba 100644 --- a/server/src/main/scala/com/lbs/server/conversation/TimePicker.scala +++ b/server/src/main/scala/com/lbs/server/conversation/TimePicker.scala @@ -1,9 +1,8 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem +import com.lbs.bot._ import com.lbs.bot.model.Button -import com.lbs.bot.{Bot, _} import com.lbs.server.conversation.Login.UserId import com.lbs.server.conversation.TimePicker.{Mode, Tags, TimeFromMode, TimeToMode} import com.lbs.server.conversation.base.{Conversation, Interactional} @@ -20,9 +19,11 @@ import scala.util.control.NonFatal * ⬆ ⬆ * HH mm * ⬇ ⬇ - * */ -class TimePicker(val userId: UserId, val bot: Bot, val localization: Localization, originator: Interactional)(val actorSystem: ActorSystem) extends Conversation[LocalTime] with Localizable { +class TimePicker(val userId: UserId, val bot: Bot, val localization: Localization, originator: Interactional)( + val actorSystem: ActorSystem +) extends Conversation[LocalTime] + with Localizable { private var mode: Mode = TimeFromMode @@ -41,11 +42,11 @@ class TimePicker(val userId: UserId, val bot: Bot, val localization: Localizatio ask { initialTime => val message = mode match { case TimeFromMode => lang.chooseTimeFrom(initialTime) - case TimeToMode => lang.chooseTimeTo(initialTime) + case TimeToMode => lang.chooseTimeTo(initialTime) } bot.sendMessage(userId.source, message, inlineKeyboard = timeButtons(initialTime)) } onReply { - case Msg(cmd@CallbackCommand(Tags.Done), selectedTime) => + case Msg(cmd @ CallbackCommand(Tags.Done), selectedTime) => val message = mode match { case TimeFromMode => lang.timeFromIs(selectedTime) @@ -73,7 +74,7 @@ class TimePicker(val userId: UserId, val bot: Bot, val localization: Localizatio bot.sendMessage(userId.source, "Incorrect time. Please use format HH:mm") goto(requestTime) } - case Msg(cmd@CallbackCommand(tag), time) => + case Msg(cmd @ CallbackCommand(tag), time) => val modifiedTime = modifyTime(time, tag) bot.sendEditMessage(userId.source, cmd.message.messageId, inlineKeyboard = timeButtons(modifiedTime)) stay() using modifiedTime @@ -81,9 +82,9 @@ class TimePicker(val userId: UserId, val bot: Bot, val localization: Localizatio private def modifyTime(time: LocalTime, tag: String) = { tag match { - case Tags.HourInc => time.plusHours(1) + case Tags.HourInc => time.plusHours(1) case Tags.MinuteInc => time.plusMinutes(30) - case Tags.HourDec => time.minusHours(1) + case Tags.HourDec => time.minusHours(1) case Tags.MinuteDec => time.minusMinutes(30) } } @@ -92,12 +93,14 @@ class TimePicker(val userId: UserId, val bot: Bot, val localization: Localizatio 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)) - )) + 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)) + ) + ) } } @@ -118,4 +121,3 @@ object TimePicker { } } - diff --git a/server/src/main/scala/com/lbs/server/conversation/UnauthorizedHelp.scala b/server/src/main/scala/com/lbs/server/conversation/UnauthorizedHelp.scala index b992e8c..a2ce10f 100644 --- a/server/src/main/scala/com/lbs/server/conversation/UnauthorizedHelp.scala +++ b/server/src/main/scala/com/lbs/server/conversation/UnauthorizedHelp.scala @@ -1,4 +1,3 @@ - package com.lbs.server.conversation import akka.actor.ActorSystem @@ -11,9 +10,8 @@ class UnauthorizedHelp(source: MessageSource, bot: Bot)(val actorSystem: ActorSy entryPoint(displayHelp) def displayHelp: Step = - monologue { - case Msg(_: Command, _) => - bot.sendMessage(source, En.help) - stay() + monologue { case Msg(_: Command, _) => + bot.sendMessage(source, En.help) + stay() } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/conversation/base/Conversation.scala b/server/src/main/scala/com/lbs/server/conversation/base/Conversation.scala index 8644c5a..4c38652 100644 --- a/server/src/main/scala/com/lbs/server/conversation/base/Conversation.scala +++ b/server/src/main/scala/com/lbs/server/conversation/base/Conversation.scala @@ -14,10 +14,9 @@ trait Conversation[D] extends Domain[D] with Interactional with StrictLogging { private var initialStep: Step = _ - private val defaultMsgHandler: MessageProcessorFn = { - case Msg(any, data) => - logger.warn(s"Unhandled message received in step '${currentStep.name}'. Message: [$any]. Data: [$data]") - NextStep(currentStep, Some(data)) + private val defaultMsgHandler: MessageProcessorFn = { case Msg(any, data) => + logger.warn(s"Unhandled message received in step '${currentStep.name}'. Message: [$any]. Data: [$data]") + NextStep(currentStep, Some(data)) } private var msgHandler: MessageProcessorFn = defaultMsgHandler @@ -29,7 +28,7 @@ trait Conversation[D] extends Domain[D] with Interactional with StrictLogging { case Process(_, fn) => val nextStep = fn(currentData) moveToNextStep(nextStep) - case _ => //do nothing + case _ => // do nothing } } catch { case NonFatal(ex) => logger.error("Step execution failed", ex) @@ -53,7 +52,7 @@ trait Conversation[D] extends Domain[D] with Interactional with StrictLogging { case Monologue(_, fn) => val fact = Msg(any, currentData) handle(fact, fn, msgHandler) - case _ => //do nothing + case _ => // do nothing } } @@ -71,12 +70,13 @@ trait Conversation[D] extends Domain[D] with Interactional with StrictLogging { currentData = initialData } - - protected def monologue(answerFn: MessageProcessorFn)(implicit functionName: sourcecode.Name): Monologue = Monologue(functionName.value, answerFn) + protected def monologue(answerFn: MessageProcessorFn)(implicit functionName: sourcecode.Name): Monologue = + Monologue(functionName.value, answerFn) protected def ask(askFn: D => Unit): Ask = Ask(askFn) - protected def process(processFn: ProcessFn)(implicit functionName: sourcecode.Name): Process = Process(functionName.value, processFn) + protected def process(processFn: ProcessFn)(implicit functionName: sourcecode.Name): Process = + Process(functionName.value, processFn) protected def end(): NextStep = NextStep(End) @@ -106,4 +106,3 @@ trait Conversation[D] extends Domain[D] with Interactional with StrictLogging { entryPoint(step, null.asInstanceOf[D]) } } - diff --git a/server/src/main/scala/com/lbs/server/conversation/base/Interactional.scala b/server/src/main/scala/com/lbs/server/conversation/base/Interactional.scala index d4c9ac6..904b7d7 100644 --- a/server/src/main/scala/com/lbs/server/conversation/base/Interactional.scala +++ b/server/src/main/scala/com/lbs/server/conversation/base/Interactional.scala @@ -29,9 +29,9 @@ trait Interactional extends StrictLogging { private implicit val dispatcher: ExecutionContextExecutor = context.system.dispatcher override def receive: Receive = { - case InitConversation => initializeConversation() + case InitConversation => initializeConversation() case StartConversation | ContinueConversation => executeCurrentStep() - case any => makeStepTransition(any) + case any => makeStepTransition(any) } override def preStart(): Unit = { @@ -71,4 +71,3 @@ trait Interactional extends StrictLogging { ref ! PoisonPill } } - diff --git a/server/src/main/scala/com/lbs/server/conversation/package.scala b/server/src/main/scala/com/lbs/server/conversation/package.scala index 15ea320..b9bb16f 100644 --- a/server/src/main/scala/com/lbs/server/conversation/package.scala +++ b/server/src/main/scala/com/lbs/server/conversation/package.scala @@ -1,4 +1,3 @@ - package com.lbs.server import com.lbs.bot.model.MessageSource diff --git a/server/src/main/scala/com/lbs/server/exception/UserNotFoundException.scala b/server/src/main/scala/com/lbs/server/exception/UserNotFoundException.scala index b615646..020a496 100644 --- a/server/src/main/scala/com/lbs/server/exception/UserNotFoundException.scala +++ b/server/src/main/scala/com/lbs/server/exception/UserNotFoundException.scala @@ -1,4 +1,3 @@ - package com.lbs.server.exception case class UserNotFoundException(chatId: Long) extends Exception(s"Luxmed username for chat with id $chatId") 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 599968d..9baaa40 100644 --- a/server/src/main/scala/com/lbs/server/lang/En.scala +++ b/server/src/main/scala/com/lbs/server/lang/En.scala @@ -1,4 +1,3 @@ - package com.lbs.server.lang import com.lbs.api.json.model.{Event, TermExt} @@ -40,14 +39,18 @@ object En extends Lang { s""" Are you sure want to cancel appointment? | |⏱ ${formatDateTime(event.date, locale)} - |${capitalizeFirstLetter(doctor)}: ${capitalizeFirstLetter(event.doctor.name)} ${capitalizeFirstLetter(event.doctor.lastname)} - |${capitalizeFirstLetter(service)}: ${event.title} - |${capitalizeFirstLetter(clinic)}: ${event.clinic.map(c => s"${capitalizeFirstLetter(c.city)} - ${capitalizeFirstLetter(c.address)}").getOrElse("Telemedicine")} + |${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)} + |${capitalize(service)}: ${event.title} + |${capitalize(clinic)}: ${event.clinic + .map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}") + .getOrElse("Telemedicine")} |""".stripMargin - override def chooseDateFrom(exampleDate: LocalDateTime): String = s" Please choose date from or write it manually using format dd-MM, e.g. ${formatDateShort(exampleDate)}" + override def chooseDateFrom(exampleDate: LocalDateTime): String = + s" Please choose date from or write it manually using format dd-MM, e.g. ${formatDateShort(exampleDate)}" - override def chooseDateTo(exampleDate: LocalDateTime): String = s" Please choose date to or write it manually using format dd-MM, e.g. ${formatDateShort(exampleDate)}" + override def chooseDateTo(exampleDate: LocalDateTime): String = + s" Please choose date to or write it manually using format dd-MM, e.g. ${formatDateShort(exampleDate)}" override def findTerms: String = "🔍 Find terms" @@ -74,12 +77,11 @@ object En extends Lang { override def book: String = "Book" override def confirmAppointment(term: TermExt): String = - s""" Would you like to confirm your appointment booking? | |⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic}""".stripMargin + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(clinic)}: ${term.term.clinic}""".stripMargin override def appointmentIsConfirmed: String = "👍 Your appointment has been confirmed!" @@ -97,7 +99,8 @@ object En extends Lang { override def pleaseSpecifyOffset: String = " Please send me offset in hours or press No button" - override def visitAlreadyExists: String = " The same service is already booked. Do you want to update the term?" + override def visitAlreadyExists: String = + " The same service is already booked. Do you want to update the term?" override def city: String = "city" @@ -118,9 +121,9 @@ object En extends Lang { | |📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}""".stripMargin + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName}""".stripMargin override def deactivated: String = "👍 Deactivated! List of active /monitorings" @@ -132,7 +135,8 @@ object En extends Lang { withAnyVariant( s""" Please enter a partial ${config.name} name |For example: ${config.partialExample} if you are looking for ${config.example}""".stripMargin, - config.isAnyAllowed) + config.isAnyAllowed + ) override def pleaseEnterStaticDataNameOrPrevious(config: StaticDataConfig): String = s""" Please enter a partial ${config.name} name @@ -141,7 +145,7 @@ object En extends Lang { |or choose a ${config.name} from previous searches""".stripMargin override def staticDataIs(config: StaticDataConfig, label: String): String = - s" ${capitalizeFirstLetter(config.name)} is $label" + s" ${capitalize(config.name)} is $label" override def pleaseChooseStaticDataNameOrAny(config: StaticDataConfig): String = withAnyVariant(s" Please choose a ${config.name}", config.isAnyAllowed) @@ -149,7 +153,9 @@ object En extends Lang { override def staticNotFound(config: StaticDataConfig): String = withAnyVariant( s""" Nothing was found 😔 - |Please enter a ${config.name} name again""", config.isAnyAllowed) + |Please enter a ${config.name} name again""", + config.isAnyAllowed + ) override def loginAndPasswordAreOk: String = s"""✅ Congrats! Login and password are OK! @@ -186,8 +192,8 @@ object En extends Lang { override def termEntry(term: TermExt, page: Int, index: Int): String = s"""⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic} + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(clinic)}: ${term.term.clinic} | /book_$index | |""".stripMargin @@ -197,9 +203,11 @@ object En extends Lang { override def historyEntry(event: Event, page: Int, index: Int): String = s"""⏱ ${formatDateTime(event.date, locale)} - |${capitalizeFirstLetter(doctor)}: ${capitalizeFirstLetter(event.doctor.name)} ${capitalizeFirstLetter(event.doctor.lastname)} - |${capitalizeFirstLetter(service)}: ${event.title} - |${capitalizeFirstLetter(clinic)}: ${event.clinic.map(c => s"${capitalizeFirstLetter(c.city)} - ${capitalizeFirstLetter(c.address)}").getOrElse("Telemedicine")} + |${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)} + |${capitalize(service)}: ${event.title} + |${capitalize(clinic)}: ${event.clinic + .map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}") + .getOrElse("Telemedicine")} | |""".stripMargin @@ -208,9 +216,11 @@ object En extends Lang { override def reservedVisitEntry(event: Event, page: Int, index: Int): String = s"""⏱ ${formatDateTime(event.date, locale)} - |${capitalizeFirstLetter(doctor)}: ${capitalizeFirstLetter(event.doctor.name)} ${capitalizeFirstLetter(event.doctor.lastname)} - |${capitalizeFirstLetter(service)}: ${event.title} - |${capitalizeFirstLetter(clinic)}: ${event.clinic.map(c => s"${capitalizeFirstLetter(c.city)} - ${capitalizeFirstLetter(c.address)}").getOrElse("Telemedicine")} + |${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)} + |${capitalize(service)}: ${event.title} + |${capitalize(clinic)}: ${event.clinic + .map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}") + .getOrElse("Telemedicine")} | /cancel_$index | |""".stripMargin @@ -224,10 +234,10 @@ object En extends Lang { override def monitoringEntry(monitoring: Monitoring, page: Int, index: Int): String = s"""📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName} + |${capitalize(city)}: ${monitoring.cityName} |Type: ${if (monitoring.autobook) "Auto" else "Manual"} | /cancel_$index | @@ -236,10 +246,10 @@ object En extends Lang { override def monitoringHistoryEntry(monitoring: Monitoring, page: Int, index: Int): String = s"""📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName} + |${capitalize(city)}: ${monitoring.cityName} |Type: ${if (monitoring.autobook) "Auto" else "Manual"} | /repeat_$index | @@ -258,10 +268,10 @@ object En extends Lang { override def availableTermEntry(term: TermExt, monitoring: Monitoring, index: Int): String = s"""⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${term.term.clinic} + |${capitalize(city)}: ${monitoring.cityName} |/reserve_${monitoring.recordId}_${term.term.scheduleId}_${minutesSinceBeginOf2018(term.term.dateTimeFrom.get)} | |""".stripMargin @@ -276,10 +286,10 @@ object En extends Lang { | |📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName} + |${capitalize(city)}: ${monitoring.cityName} | | Create new monitoring /book""".stripMargin @@ -287,10 +297,10 @@ object En extends Lang { s"""👍 We just booked an appointment for you! | |⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName}""".stripMargin + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${term.term.clinic} + |${capitalize(city)}: ${monitoring.cityName}""".stripMargin override def maximumMonitoringsLimitExceeded: String = "Maximum monitorings per user is 10" @@ -315,7 +325,8 @@ object En extends Lang { override def configureOffset: String = " Please specify offset options" - override def pleaseEnterOffset(current: Int): String = s" Please enter default offset. Current: $current" + override def pleaseEnterOffset(current: Int): String = + s" Please enter default offset. Current: $current" override def alwaysAskOffset(enabled: Boolean): String = s"${if (enabled) "✅ " else ""}Always ask offset" @@ -353,9 +364,11 @@ object En extends Lang { override def moreParameters: String = "🛠 More parameters" - override def chooseTimeFrom(exampleTime: LocalTime): String = s" Please choose time from or write time using format HH:mm, e.g. ${formatTime(exampleTime)}" + override def chooseTimeFrom(exampleTime: LocalTime): String = + s" Please choose time from or write time using format HH:mm, e.g. ${formatTime(exampleTime)}" - override def chooseTimeTo(exampleTime: LocalTime): String = s" Please choose time to or write time using format HH:mm, e.g. ${formatTime(exampleTime)}" + override def chooseTimeTo(exampleTime: LocalTime): String = + s" Please choose time to or write time using format HH:mm, e.g. ${formatTime(exampleTime)}" override def timeFromIs(timeFrom: LocalTime): String = s"⏱ Time from is ${formatTime(timeFrom)}" 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 135602e..030083d 100644 --- a/server/src/main/scala/com/lbs/server/lang/Lang.scala +++ b/server/src/main/scala/com/lbs/server/lang/Lang.scala @@ -1,4 +1,3 @@ - package com.lbs.server.lang import com.lbs.api.json.model.{Event, TermExt} @@ -32,7 +31,7 @@ trait Lang { def label: String - protected def capitalizeFirstLetter(str: String): String = { + protected def capitalize(str: String): String = { if (str != null && str != "") { val fistCapitalLetter = str.head.toTitleCase s"$fistCapitalLetter${str.tail.toLowerCase}" diff --git a/server/src/main/scala/com/lbs/server/lang/Localizable.scala b/server/src/main/scala/com/lbs/server/lang/Localizable.scala index 767eb49..53e4c25 100644 --- a/server/src/main/scala/com/lbs/server/lang/Localizable.scala +++ b/server/src/main/scala/com/lbs/server/lang/Localizable.scala @@ -1,4 +1,3 @@ - package com.lbs.server.lang import com.lbs.server.conversation.Login.UserId diff --git a/server/src/main/scala/com/lbs/server/lang/Localization.scala b/server/src/main/scala/com/lbs/server/lang/Localization.scala index 7685397..0bd93fb 100644 --- a/server/src/main/scala/com/lbs/server/lang/Localization.scala +++ b/server/src/main/scala/com/lbs/server/lang/Localization.scala @@ -1,4 +1,3 @@ - package com.lbs.server.lang import com.lbs.server.repository.model @@ -17,10 +16,13 @@ class Localization { private val cachedLangs = new ConcurrentHashMap[Long, Lang] def lang(userId: Long): Lang = { - cachedLangs.computeIfAbsent(userId, _ => { - val settings = dataService.findSettings(userId) - settings.map(s => Lang(s.lang)).getOrElse(En) - }) + cachedLangs.computeIfAbsent( + userId, + _ => { + val settings = dataService.findSettings(userId) + settings.map(s => Lang(s.lang)).getOrElse(En) + } + ) } diff --git a/server/src/main/scala/com/lbs/server/lang/Pl.scala b/server/src/main/scala/com/lbs/server/lang/Pl.scala index 79b7086..1ea4885 100644 --- a/server/src/main/scala/com/lbs/server/lang/Pl.scala +++ b/server/src/main/scala/com/lbs/server/lang/Pl.scala @@ -1,4 +1,3 @@ - package com.lbs.server.lang import com.lbs.api.json.model.{Event, TermExt} @@ -40,14 +39,18 @@ object Pl extends Lang { s""" Czy na pewno chcesz anulować wizytę? | |⏱ ${formatDateTime(event.date, locale)} - |${capitalizeFirstLetter(doctor)}: ${capitalizeFirstLetter(event.doctor.name)} ${capitalizeFirstLetter(event.doctor.lastname)} - |${capitalizeFirstLetter(service)}: ${event.title} - |${capitalizeFirstLetter(clinic)}: ${event.clinic.map(c => s"${capitalizeFirstLetter(c.city)} - ${capitalizeFirstLetter(c.address)}").getOrElse("Telemedicine")} + |${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)} + |${capitalize(service)}: ${event.title} + |${capitalize(clinic)}: ${event.clinic + .map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}") + .getOrElse("Telemedicine")} |""".stripMargin - override def chooseDateFrom(exampleDate: LocalDateTime): String = s" Wybierz datę albo zapisz ją w formacie dd-MM, np. ${formatDateShort(exampleDate)}" + override def chooseDateFrom(exampleDate: LocalDateTime): String = + s" Wybierz datę albo zapisz ją w formacie dd-MM, np. ${formatDateShort(exampleDate)}" - override def chooseDateTo(exampleDate: LocalDateTime): String = s" Wybierz datę albo zapisz ją w formacie dd-MM, np. ${formatDateShort(exampleDate)}" + override def chooseDateTo(exampleDate: LocalDateTime): String = + s" Wybierz datę albo zapisz ją w formacie dd-MM, np. ${formatDateShort(exampleDate)}" override def findTerms: String = "🔍 Szukaj terminów" @@ -74,18 +77,19 @@ object Pl extends Lang { override def book: String = "Zarezerwuj" override def confirmAppointment(term: TermExt): String = - s""" Czy potwierdzasz wizytę? | |⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic}""".stripMargin + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(clinic)}: ${term.term.clinic}""".stripMargin override def appointmentIsConfirmed: String = "👍 Twoja wizyta została potwierdzona!" - override def monitoringHasBeenCreated: String = "👍 Stworzono monitoring! Sprawdź aktywne monitoringi przez /monitorings" + override def monitoringHasBeenCreated: String = + "👍 Stworzono monitoring! Sprawdź aktywne monitoringi przez /monitorings" - override def unableToCreateMonitoring(reason: String): String = s"👎 Nie udało się stworzyć monitoringu. Powód: $reason." + override def unableToCreateMonitoring(reason: String): String = + s"👎 Nie udało się stworzyć monitoringu. Powód: $reason." override def chooseTypeOfMonitoring: String = " Wybierz typ monitoringu" @@ -97,7 +101,8 @@ object Pl extends Lang { override def pleaseSpecifyOffset: String = " Podaj offset w godzinach albo kliknij Nie" - override def visitAlreadyExists: String = " Wizyta została juz zarezerwowana. Czy chcesz zaktualizować jej termin?" + override def visitAlreadyExists: String = + " Wizyta została juz zarezerwowana. Czy chcesz zaktualizować jej termin?" override def city: String = "miasto" @@ -118,9 +123,9 @@ object Pl extends Lang { | |📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}""".stripMargin + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName}""".stripMargin override def deactivated: String = "👍 Wyłączony! Sprawdź aktywne monitoringi przez /monitorings" @@ -132,7 +137,8 @@ object Pl extends Lang { withAnyVariant( s""" Podaj fragment nazwy ${config.name} |Na przykład: ${config.partialExample} jeśli szukasz ${config.example}""".stripMargin, - config.isAnyAllowed) + config.isAnyAllowed + ) override def pleaseEnterStaticDataNameOrPrevious(config: StaticDataConfig): String = s""" Podaj fragment nazwy ${config.name} @@ -141,7 +147,7 @@ object Pl extends Lang { |lub wybierz ${config.name} z poprzednich wyszukiwań""".stripMargin override def staticDataIs(config: StaticDataConfig, label: String): String = - s" ${capitalizeFirstLetter(config.name)} jest $label" + s" ${capitalize(config.name)} jest $label" override def pleaseChooseStaticDataNameOrAny(config: StaticDataConfig): String = withAnyVariant(s" Wybierz ${config.name}", config.isAnyAllowed) @@ -149,7 +155,9 @@ object Pl extends Lang { override def staticNotFound(config: StaticDataConfig): String = withAnyVariant( s""" Brak wyników 😔 - |Proszę podaj nazwę ${config.name} jeszcze raz""", config.isAnyAllowed) + |Proszę podaj nazwę ${config.name} jeszcze raz""", + config.isAnyAllowed + ) override def loginAndPasswordAreOk: String = s"""✅ Brawo! Login i hasło są OK! @@ -186,8 +194,8 @@ object Pl extends Lang { override def termEntry(term: TermExt, page: Int, index: Int): String = s"""⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic} + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(clinic)}: ${term.term.clinic} | /book_$index | |""".stripMargin @@ -197,9 +205,11 @@ object Pl extends Lang { override def historyEntry(event: Event, page: Int, index: Int): String = s"""⏱ ${formatDateTime(event.date, locale)} - |${capitalizeFirstLetter(doctor)}: ${capitalizeFirstLetter(event.doctor.name)} ${capitalizeFirstLetter(event.doctor.lastname)} - |${capitalizeFirstLetter(service)}: ${event.title} - |${capitalizeFirstLetter(clinic)}: ${event.clinic.map(c => s"${capitalizeFirstLetter(c.city)} - ${capitalizeFirstLetter(c.address)}").getOrElse("Telemedicine")} + |${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)} + |${capitalize(service)}: ${event.title} + |${capitalize(clinic)}: ${event.clinic + .map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}") + .getOrElse("Telemedicine")} | |""".stripMargin @@ -208,9 +218,11 @@ object Pl extends Lang { override def reservedVisitEntry(event: Event, page: Int, index: Int): String = s"""⏱ ${formatDateTime(event.date, locale)} - |${capitalizeFirstLetter(doctor)}: ${capitalizeFirstLetter(event.doctor.name)} ${capitalizeFirstLetter(event.doctor.lastname)} - |${capitalizeFirstLetter(service)}: ${event.title} - |${capitalizeFirstLetter(clinic)}: ${event.clinic.map(c => s"${capitalizeFirstLetter(c.city)} - ${capitalizeFirstLetter(c.address)}").getOrElse("Telemedicine")} + |${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)} + |${capitalize(service)}: ${event.title} + |${capitalize(clinic)}: ${event.clinic + .map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}") + .getOrElse("Telemedicine")} | /cancel_$index | |""".stripMargin @@ -224,10 +236,10 @@ object Pl extends Lang { override def monitoringEntry(monitoring: Monitoring, page: Int, index: Int): String = s"""📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName} + |${capitalize(city)}: ${monitoring.cityName} |Sposób rejestracji: ${if (monitoring.autobook) "Automatyczny" else "Ręczny"} | /cancel_$index | @@ -236,10 +248,10 @@ object Pl extends Lang { override def monitoringHistoryEntry(monitoring: Monitoring, page: Int, index: Int): String = s"""📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName} + |${capitalize(city)}: ${monitoring.cityName} |Sposób rejestracji: ${if (monitoring.autobook) "Automatyczny" else "Ręczny"} | /repeat_$index | @@ -258,10 +270,10 @@ object Pl extends Lang { override def availableTermEntry(term: TermExt, monitoring: Monitoring, index: Int): String = s"""⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${term.term.clinic} + |${capitalize(city)}: ${monitoring.cityName} |/reserve_${monitoring.recordId}_${term.term.scheduleId}_${minutesSinceBeginOf2018(term.term.dateTimeFrom.get)} | |""".stripMargin @@ -276,10 +288,10 @@ object Pl extends Lang { | |📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName} + |${capitalize(city)}: ${monitoring.cityName} | | Stwórz nowy monitoring przez /book""".stripMargin @@ -287,10 +299,10 @@ object Pl extends Lang { s"""👍 Zarezerwowaliśmy za Ciebie termin! | |⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName}""".stripMargin + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${term.term.clinic} + |${capitalize(city)}: ${monitoring.cityName}""".stripMargin override def maximumMonitoringsLimitExceeded: String = "Maksymalna liczba monitoringów uzytkownika to 10" @@ -315,7 +327,8 @@ object Pl extends Lang { override def configureOffset: String = " Wybierz opcje offsetu" - override def pleaseEnterOffset(current: Int): String = s" Podaj domyślny offset. Obecny offset: $current" + override def pleaseEnterOffset(current: Int): String = + s" Podaj domyślny offset. Obecny offset: $current" override def alwaysAskOffset(enabled: Boolean): String = s"${if (enabled) "✅ " else ""}Zawsze pytaj o offset" @@ -353,9 +366,11 @@ object Pl extends Lang { override def moreParameters: String = "🛠 Więcej opcji" - override def chooseTimeFrom(exampleTime: LocalTime): String = s" Wybierz godzinę OD albo zapisz w formacie HH:mm, np. ${formatTime(exampleTime)}" + override def chooseTimeFrom(exampleTime: LocalTime): String = + s" Wybierz godzinę OD albo zapisz w formacie HH:mm, np. ${formatTime(exampleTime)}" - override def chooseTimeTo(exampleTime: LocalTime): String = s" Wybierz godzinę DO albo zapisz w formacie HH:mm ${formatTime(exampleTime)}" + override def chooseTimeTo(exampleTime: LocalTime): String = + s" Wybierz godzinę DO albo zapisz w formacie HH:mm ${formatTime(exampleTime)}" override def timeFromIs(timeFrom: LocalTime): String = s"⏱ Godzina OD: ${formatTime(timeFrom)}" 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 e3a7f7d..229b542 100644 --- a/server/src/main/scala/com/lbs/server/lang/Ua.scala +++ b/server/src/main/scala/com/lbs/server/lang/Ua.scala @@ -1,4 +1,3 @@ - package com.lbs.server.lang import com.lbs.api.json.model.{Event, TermExt} @@ -40,14 +39,18 @@ object Ua extends Lang { s""" Ви впевнені, що хочете скасувати візит? | |⏱ ${formatDateTime(event.date, locale)} - |${capitalizeFirstLetter(doctor)}: ${capitalizeFirstLetter(event.doctor.name)} ${capitalizeFirstLetter(event.doctor.lastname)} - |${capitalizeFirstLetter(service)}: ${event.title} - |${capitalizeFirstLetter(clinic)}: ${event.clinic.map(c => s"${capitalizeFirstLetter(c.city)} - ${capitalizeFirstLetter(c.address)}").getOrElse("Telemedicine")} + |${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)} + |${capitalize(service)}: ${event.title} + |${capitalize(clinic)}: ${event.clinic + .map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}") + .getOrElse("Telemedicine")} |""".stripMargin - override def chooseDateFrom(exampleDate: LocalDateTime): String = s" Будь ласка, виберіть початкову дату або введіть її, використовуючи формат dd-MM, наприклад ${formatDateShort(exampleDate)}" + override def chooseDateFrom(exampleDate: LocalDateTime): String = + s" Будь ласка, виберіть початкову дату або введіть її, використовуючи формат dd-MM, наприклад ${formatDateShort(exampleDate)}" - override def chooseDateTo(exampleDate: LocalDateTime): String = s" Будь ласка, виберіть кінцеву дату або введіть її, використовуючи формат dd-MM, наприклад ${formatDateShort(exampleDate)}" + override def chooseDateTo(exampleDate: LocalDateTime): String = + s" Будь ласка, виберіть кінцеву дату або введіть її, використовуючи формат dd-MM, наприклад ${formatDateShort(exampleDate)}" override def findTerms: String = "🔍 Знайти терміни" @@ -74,18 +77,18 @@ object Ua extends Lang { override def book: String = "Зарезервувати" override def confirmAppointment(term: TermExt): String = - s""" Ви хотіли б підтвердити резервацію візиту? | |⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic}""".stripMargin + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(clinic)}: ${term.term.clinic}""".stripMargin override def appointmentIsConfirmed: String = "👍 Ваш візит було підтверджено!" override def monitoringHasBeenCreated: String = "👍 Моніторинг був створений! Список активних /monitorings" - override def unableToCreateMonitoring(reason: String): String = s"👎 Не вдається створити моніторинг. Причина: $reason." + override def unableToCreateMonitoring(reason: String): String = + s"👎 Не вдається створити моніторинг. Причина: $reason." override def chooseTypeOfMonitoring: String = " Будь ласка, виберіть тип моніторингу" @@ -97,7 +100,8 @@ object Ua extends Lang { override def pleaseSpecifyOffset: String = " Будь ласка, надішліть мені зміщення в годинах, або натисніть Ні" - override def visitAlreadyExists: String = " Резервація для такого сервісу вже існує. Чі хотіли би ви змінити термін?" + override def visitAlreadyExists: String = + " Резервація для такого сервісу вже існує. Чі хотіли би ви змінити термін?" override def city: String = "місто" @@ -118,9 +122,9 @@ object Ua extends Lang { | |📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}""".stripMargin + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName}""".stripMargin override def deactivated: String = "👍 Деактивовано! Список активних /monitorings" @@ -132,7 +136,8 @@ object Ua extends Lang { withAnyVariant( s""" Будь ласка, введіть частково ${config.name} |Наприклад: ${config.partialExample} якщо ви шукаете ${config.example}""".stripMargin, - config.isAnyAllowed) + config.isAnyAllowed + ) override def pleaseEnterStaticDataNameOrPrevious(config: StaticDataConfig): String = s""" Будь ласка, введіть частково ${config.name} @@ -141,7 +146,7 @@ object Ua extends Lang { |або оберіть ${config.name} з попередніх пошуків""".stripMargin override def staticDataIs(config: StaticDataConfig, label: String): String = - s" ${capitalizeFirstLetter(config.name)} $label" + s" ${capitalize(config.name)} $label" override def pleaseChooseStaticDataNameOrAny(config: StaticDataConfig): String = withAnyVariant(s" Будь ласка, виберіть ${config.name}", config.isAnyAllowed) @@ -149,7 +154,9 @@ object Ua extends Lang { override def staticNotFound(config: StaticDataConfig): String = withAnyVariant( s""" Нічого не знайдено 😔 - |Будь ласка, введіть ${config.name} знову""".stripMargin, config.isAnyAllowed) + |Будь ласка, введіть ${config.name} знову""".stripMargin, + config.isAnyAllowed + ) override def loginAndPasswordAreOk: String = s"""✅ Супер! Логін і пароль збережено @@ -185,8 +192,8 @@ object Ua extends Lang { override def termEntry(term: TermExt, page: Int, index: Int): String = s"""⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic} + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(clinic)}: ${term.term.clinic} | /book_$index | |""".stripMargin @@ -196,9 +203,11 @@ object Ua extends Lang { override def historyEntry(event: Event, page: Int, index: Int): String = s"""⏱ ${formatDateTime(event.date, locale)} - |${capitalizeFirstLetter(doctor)}: ${capitalizeFirstLetter(event.doctor.name)} ${capitalizeFirstLetter(event.doctor.lastname)} - |${capitalizeFirstLetter(service)}: ${event.title} - |${capitalizeFirstLetter(clinic)}: ${event.clinic.map(c => s"${capitalizeFirstLetter(c.city)} - ${capitalizeFirstLetter(c.address)}").getOrElse("Telemedicine")} + |${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)} + |${capitalize(service)}: ${event.title} + |${capitalize(clinic)}: ${event.clinic + .map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}") + .getOrElse("Telemedicine")} | |""".stripMargin @@ -207,9 +216,11 @@ object Ua extends Lang { override def reservedVisitEntry(event: Event, page: Int, index: Int): String = s"""⏱ ${formatDateTime(event.date, locale)} - |${capitalizeFirstLetter(doctor)}: ${capitalizeFirstLetter(event.doctor.name)} ${capitalizeFirstLetter(event.doctor.lastname)} - |${capitalizeFirstLetter(service)}: ${event.title} - |${capitalizeFirstLetter(clinic)}: ${event.clinic.map(c => s"${capitalizeFirstLetter(c.city)} - ${capitalizeFirstLetter(c.address)}").getOrElse("Telemedicine")} + |${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)} + |${capitalize(service)}: ${event.title} + |${capitalize(clinic)}: ${event.clinic + .map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}") + .getOrElse("Telemedicine")} | /cancel_$index | |""".stripMargin @@ -223,10 +234,10 @@ object Ua extends Lang { override def monitoringEntry(monitoring: Monitoring, page: Int, index: Int): String = s"""📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName} + |${capitalize(city)}: ${monitoring.cityName} |Тип: ${if (monitoring.autobook) "Автоматичний" else "Ручний"} | /cancel_$index | @@ -235,10 +246,10 @@ object Ua extends Lang { override def monitoringHistoryEntry(monitoring: Monitoring, page: Int, index: Int): String = s"""📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName} + |${capitalize(city)}: ${monitoring.cityName} |Тип: ${if (monitoring.autobook) "Автоматичний" else "Ручний"} | /repeat_$index | @@ -257,10 +268,10 @@ object Ua extends Lang { override def availableTermEntry(term: TermExt, monitoring: Monitoring, index: Int): String = s"""⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${term.term.clinic} + |${capitalize(city)}: ${monitoring.cityName} |/reserve_${monitoring.recordId}_${term.term.scheduleId}_${minutesSinceBeginOf2018(term.term.dateTimeFrom.get)} | |""".stripMargin @@ -275,10 +286,10 @@ object Ua extends Lang { | |📅 ${formatDate(monitoring.dateFrom, locale)} -> ${formatDate(monitoring.dateTo, locale)} |⏱ ${formatTime(monitoring.timeFrom)} -> ${formatTime(monitoring.timeTo)} - |${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName} + |${capitalize(doctor)}: ${monitoring.doctorName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${monitoring.clinicName} + |${capitalize(city)}: ${monitoring.cityName} | | Створити новий моніторінг /book""".stripMargin @@ -286,10 +297,10 @@ object Ua extends Lang { s"""👍 Ми зерезевували візит для вас! | |⏱ ${formatDateTime(term.term.dateTimeFrom, locale)} - |${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} - |${capitalizeFirstLetter(service)}: ${monitoring.serviceName} - |${capitalizeFirstLetter(clinic)}: ${term.term.clinic} - |${capitalizeFirstLetter(city)}: ${monitoring.cityName}""".stripMargin + |${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName} + |${capitalize(service)}: ${monitoring.serviceName} + |${capitalize(clinic)}: ${term.term.clinic} + |${capitalize(city)}: ${monitoring.cityName}""".stripMargin override def maximumMonitoringsLimitExceeded: String = "Максимальна кількість моніторінгів 10" @@ -314,7 +325,8 @@ object Ua extends Lang { override def configureOffset: String = " Будь ласка, сконфігуруйте зміщення" - override def pleaseEnterOffset(current: Int): String = s" Будь ласка, введіть зміщення за замовчуванням. Поточне: $current" + override def pleaseEnterOffset(current: Int): String = + s" Будь ласка, введіть зміщення за замовчуванням. Поточне: $current" override def alwaysAskOffset(enabled: Boolean): String = s"${if (enabled) "✅ " else ""}Завжди питати зміщення" @@ -352,9 +364,11 @@ object Ua extends Lang { override def moreParameters: String = "🛠 Більше налаштувань" - override def chooseTimeFrom(exampleTime: LocalTime): String = s" Будь ласка, виберіть початковий час або введіть час, використовуючи формат HH:mm, наприклад ${formatTime(exampleTime)}" + override def chooseTimeFrom(exampleTime: LocalTime): String = + s" Будь ласка, виберіть початковий час або введіть час, використовуючи формат HH:mm, наприклад ${formatTime(exampleTime)}" - override def chooseTimeTo(exampleTime: LocalTime): String = s" Будь ласка, виберіть кінцевий час або введіть час, використовуючи формат HH:mm, наприклад ${formatTime(exampleTime)}" + override def chooseTimeTo(exampleTime: LocalTime): String = + s" Будь ласка, виберіть кінцевий час або введіть час, використовуючи формат HH:mm, наприклад ${formatTime(exampleTime)}" override def timeFromIs(timeFrom: LocalTime): String = s"⏱ Початковий час ${formatTime(timeFrom)}" @@ -362,5 +376,6 @@ object Ua extends Lang { override def canNotDetectPayer(error: String): String = s"Не можу визначити платника. Причина: $error" - override def pleaseChoosePayer: String = " Не можу визначити платника за замовчуванням. Будь ласка, виберіть платника" + override def pleaseChoosePayer: String = + " Не можу визначити платника за замовчуванням. Будь ласка, виберіть платника" } diff --git a/server/src/main/scala/com/lbs/server/repository/DataRepository.scala b/server/src/main/scala/com/lbs/server/repository/DataRepository.scala index 983a6b0..cc7bf8a 100644 --- a/server/src/main/scala/com/lbs/server/repository/DataRepository.scala +++ b/server/src/main/scala/com/lbs/server/repository/DataRepository.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository import com.lbs.server.repository.model.{CityHistory, ClinicHistory, Credentials, DoctorHistory, JLong, Monitoring, ServiceHistory, Settings, Source, SystemUser} @@ -18,29 +17,40 @@ class DataRepository(@Autowired em: EntityManager) { em.createQuery( """select city from CityHistory city where city.recordId in | (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("accountId", accountId) + | order by city.time desc""".stripMargin, + classOf[CityHistory] + ).setParameter("accountId", accountId) .setMaxResults(maxHistory) - .getResultList.asScala.toSeq + .getResultList + .asScala + .toSeq } 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.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("accountId", accountId) + | order by clinic.time desc""".stripMargin, + classOf[ClinicHistory] + ).setParameter("accountId", accountId) .setParameter("cityId", cityId) .setMaxResults(maxHistory) - .getResultList.asScala.toSeq + .getResultList + .asScala + .toSeq } 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 + val query = em + .createQuery( + s"""select service from ServiceHistory service where service.recordId in | (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]) + | 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("accountId", accountId) .setParameter("cityId", cityId) .setMaxResults(maxHistory) @@ -49,12 +59,15 @@ class DataRepository(@Autowired em: EntityManager) { } 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 + val query = em + .createQuery( + s"""select doctor from DoctorHistory doctor where doctor.recordId in | (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]) + | order by doctor.time desc""".stripMargin, + classOf[DoctorHistory] + ) .setParameter("accountId", accountId) .setParameter("cityId", cityId) .setParameter("serviceId", serviceId) @@ -65,158 +78,204 @@ class DataRepository(@Autowired em: EntityManager) { def findCredentials(accountId: Long): Option[Credentials] = { em.createQuery( - "select credentials from Credentials credentials where credentials.accountId = :accountId", classOf[Credentials]) - .setParameter("accountId", accountId) - .getResultList.asScala.headOption + "select credentials from Credentials credentials where credentials.accountId = :accountId", + classOf[Credentials] + ).setParameter("accountId", accountId) + .getResultList + .asScala + .headOption } def getActiveMonitorings: Seq[Monitoring] = { em.createQuery( - """select monitoring from Monitoring monitoring where monitoring.active = true""".stripMargin, classOf[Monitoring]) - .getResultList.asScala.toSeq + """select monitoring from Monitoring monitoring where monitoring.active = true""".stripMargin, + classOf[Monitoring] + ).getResultList + .asScala + .toSeq } def getActiveMonitoringsCount(accountId: Long): JLong = { em.createQuery( """select count(monitoring) from Monitoring monitoring where monitoring.active = true - | and monitoring.accountId = :accountId""".stripMargin, classOf[JLong]) - .setParameter("accountId", accountId) + | and monitoring.accountId = :accountId""".stripMargin, + classOf[JLong] + ).setParameter("accountId", accountId) .getSingleResult } def getActiveMonitorings(accountId: Long): Seq[Monitoring] = { em.createQuery( """select monitoring from Monitoring monitoring where monitoring.active = true - | and monitoring.accountId = :accountId order by monitoring.dateTo asc""".stripMargin, classOf[Monitoring]) - .setParameter("accountId", accountId) - .getResultList.asScala.toSeq + | and monitoring.accountId = :accountId order by monitoring.dateTo asc""".stripMargin, + classOf[Monitoring] + ).setParameter("accountId", accountId) + .getResultList + .asScala + .toSeq } def getAllMonitoringsCount(accountId: Long): JLong = { em.createQuery( """select count(monitoring) from Monitoring monitoring where - | monitoring.accountId = :accountId""".stripMargin, classOf[JLong]) - .setParameter("accountId", accountId) + | monitoring.accountId = :accountId""".stripMargin, + classOf[JLong] + ).setParameter("accountId", accountId) .getSingleResult } def getMonitoringsPage(accountId: Long, start: Int, count: Int): Seq[Monitoring] = { em.createQuery( """select monitoring from Monitoring monitoring where monitoring.accountId = :accountId - | order by monitoring.created desc""".stripMargin, classOf[Monitoring]) - .setParameter("accountId", accountId) + | order by monitoring.created desc""".stripMargin, + classOf[Monitoring] + ).setParameter("accountId", accountId) .setFirstResult(start) .setMaxResults(count) - .getResultList.asScala.toSeq + .getResultList + .asScala + .toSeq } - - def findActiveMonitoring(accountId: Long, cityId: Long, serviceId: Long, doctorId: Long): Option[Monitoring] = { em.createQuery( """select monitoring from Monitoring monitoring where monitoring.active = true | and monitoring.accountId = :accountId | and monitoring.cityId = :cityId | and monitoring.serviceId = :serviceId - | and monitoring.doctorId = :doctorId""".stripMargin, classOf[Monitoring]) - .setParameter("accountId", accountId) + | and monitoring.doctorId = :doctorId""".stripMargin, + classOf[Monitoring] + ).setParameter("accountId", accountId) .setParameter("cityId", cityId) .setParameter("serviceId", serviceId) .setParameter("doctorId", doctorId) - .getResultList.asScala.headOption + .getResultList + .asScala + .headOption } def getActiveMonitoringsSince(since: ZonedDateTime): Seq[Monitoring] = { em.createQuery( """select monitoring from Monitoring monitoring where monitoring.active = true - | and monitoring.created > :since""".stripMargin, classOf[Monitoring]) - .setParameter("since", since) - .getResultList.asScala.toSeq + | and monitoring.created > :since""".stripMargin, + classOf[Monitoring] + ).setParameter("since", since) + .getResultList + .asScala + .toSeq } def findMonitoring(accountId: Long, monitoringId: Long): Option[Monitoring] = { em.createQuery( """select monitoring from Monitoring monitoring where monitoring.accountId = :accountId - | and monitoring.recordId = :monitoringId""".stripMargin, classOf[Monitoring]) - .setParameter("accountId", accountId) + | and monitoring.recordId = :monitoringId""".stripMargin, + classOf[Monitoring] + ).setParameter("accountId", accountId) .setParameter("monitoringId", monitoringId) - .getResultList.asScala.headOption + .getResultList + .asScala + .headOption } def findSettings(userId: Long): Option[Settings] = { - em.createQuery( - "select settings from Settings settings where settings.userId = :userId", classOf[Settings]) + em.createQuery("select settings from Settings settings where settings.userId = :userId", classOf[Settings]) .setParameter("userId", userId) - .getResultList.asScala.headOption + .getResultList + .asScala + .headOption } def findUserId(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) + " and source.sourceSystemId = :sourceSystemId", + classOf[JLong] + ).setParameter("chatId", chatId) .setParameter("sourceSystemId", sourceSystemId) - .getResultList.asScala.headOption + .getResultList + .asScala + .headOption } def findCredentialsByUsername(username: String, userId: Long): Option[Credentials] = { em.createQuery( "select credentials from Credentials credentials where credentials.username = :username" + - " and credentials.userId = :userId", classOf[Credentials]) - .setParameter("username", username) + " and credentials.userId = :userId", + classOf[Credentials] + ).setParameter("username", username) .setParameter("userId", userId) - .getResultList.asScala.headOption + .getResultList + .asScala + .headOption } def findSource(chatId: String, sourceSystemId: Long, userId: Long): Option[Source] = { em.createQuery( "select source from Source source where source.chatId = :chatId" + " and source.sourceSystemId = :sourceSystemId" + - " and userId = :userId", classOf[Source]) - .setParameter("chatId", chatId) + " and userId = :userId", + classOf[Source] + ).setParameter("chatId", chatId) .setParameter("sourceSystemId", sourceSystemId) .setParameter("userId", userId) - .getResultList.asScala.headOption + .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) + " and source.sourceSystemId = :sourceSystemId", + classOf[JLong] + ).setParameter("chatId", chatId) .setParameter("sourceSystemId", sourceSystemId) - .getResultList.asScala.headOption + .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 + "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 + "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.toSeq + "select credentials from Credentials credentials where credentials.userId = :userId", + classOf[Credentials] + ).setParameter("userId", userId) + .getResultList + .asScala + .toSeq } 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) + """.stripMargin, + classOf[Credentials] + ).setParameter("userId", userId) .setParameter("accountId", accountId) - .getResultList.asScala.headOption + .getResultList + .asScala + .headOption } def saveEntity[T](entity: T): T = { diff --git a/server/src/main/scala/com/lbs/server/repository/model/Account.scala b/server/src/main/scala/com/lbs/server/repository/model/Account.scala index cfc10c8..c4ec02f 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/Account.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/Account.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import javax.persistence._ @@ -6,4 +5,4 @@ import javax.persistence._ @Entity @Access(AccessType.FIELD) //just a sequence generator -class Account extends RecordId \ No newline at end of file +class Account extends RecordId diff --git a/server/src/main/scala/com/lbs/server/repository/model/CityHistory.scala b/server/src/main/scala/com/lbs/server/repository/model/CityHistory.scala index c3c946a..56986d8 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/CityHistory.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/CityHistory.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import java.time.ZonedDateTime @@ -34,4 +33,4 @@ object CityHistory { city.time = time city } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/repository/model/ClinicHistory.scala b/server/src/main/scala/com/lbs/server/repository/model/ClinicHistory.scala index 30e9ddd..0009c2d 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/ClinicHistory.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/ClinicHistory.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import java.time.ZonedDateTime diff --git a/server/src/main/scala/com/lbs/server/repository/model/Credentials.scala b/server/src/main/scala/com/lbs/server/repository/model/Credentials.scala index 4fa9da7..a89ab5c 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/Credentials.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/Credentials.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import javax.persistence._ diff --git a/server/src/main/scala/com/lbs/server/repository/model/DoctorHistory.scala b/server/src/main/scala/com/lbs/server/repository/model/DoctorHistory.scala index 3fdc903..44fe323 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/DoctorHistory.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/DoctorHistory.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import java.time.ZonedDateTime @@ -38,7 +37,15 @@ class DoctorHistory extends History with RecordId { } object DoctorHistory { - def apply(accountId: 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.accountId = accountId doctor.id = id diff --git a/server/src/main/scala/com/lbs/server/repository/model/History.scala b/server/src/main/scala/com/lbs/server/repository/model/History.scala index 0d3fc16..3ef34f6 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/History.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/History.scala @@ -1,7 +1,5 @@ - package com.lbs.server.repository.model - trait History { def id: JLong 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 d2618e2..f916029 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 @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import java.time.{LocalTime, ZonedDateTime} @@ -98,10 +97,30 @@ class Monitoring extends RecordId { } object Monitoring { - def apply(userId: Long, accountId: Long, chatId: String, sourceSystemId: Long, payerId: 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, rebookIfExists: Boolean = false, created: ZonedDateTime = ZonedDateTime.now(), timeFrom: LocalTime, timeTo: LocalTime, - active: Boolean = true, offset: Int): Monitoring = { + def apply( + userId: Long, + accountId: Long, + chatId: String, + sourceSystemId: Long, + payerId: 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, + rebookIfExists: Boolean = false, + created: ZonedDateTime = ZonedDateTime.now(), + timeFrom: LocalTime, + timeTo: LocalTime, + active: Boolean = true, + offset: Int + ): Monitoring = { val monitoring = new Monitoring monitoring.userId = userId monitoring.accountId = accountId @@ -127,4 +146,4 @@ object Monitoring { monitoring.offset = offset monitoring } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/repository/model/RecordId.scala b/server/src/main/scala/com/lbs/server/repository/model/RecordId.scala index 9dcf75e..2bc2607 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/RecordId.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/RecordId.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import javax.persistence._ @@ -10,4 +9,4 @@ trait RecordId extends Serializable { @GeneratedValue(strategy = GenerationType.IDENTITY) @BeanProperty var recordId: JLong = _ -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/repository/model/ServiceHistory.scala b/server/src/main/scala/com/lbs/server/repository/model/ServiceHistory.scala index e0a810e..480627a 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/ServiceHistory.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/ServiceHistory.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import java.time.ZonedDateTime @@ -34,7 +33,14 @@ class ServiceHistory extends History with RecordId { } object ServiceHistory { - def apply(accountId: 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.accountId = accountId service.id = id diff --git a/server/src/main/scala/com/lbs/server/repository/model/Settings.scala b/server/src/main/scala/com/lbs/server/repository/model/Settings.scala index 8646a80..682c9b8 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/Settings.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/Settings.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import javax.persistence.{Access, AccessType, Column, Entity} @@ -13,7 +12,7 @@ class Settings extends RecordId { @BeanProperty @Column(nullable = false) - var lang: Int = 0 //En by default + var lang: Int = 0 // En by default @BeanProperty @Column(nullable = false) @@ -33,4 +32,4 @@ object Settings { settings.alwaysAskOffset = alwaysAskOffset settings } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/repository/model/Source.scala b/server/src/main/scala/com/lbs/server/repository/model/Source.scala index 2337f9c..5598548 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/Source.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/Source.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import javax.persistence._ @@ -28,4 +27,4 @@ object Source { source.userId = userId source } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/repository/model/SystemUser.scala b/server/src/main/scala/com/lbs/server/repository/model/SystemUser.scala index 8b2be82..cb16899 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/SystemUser.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/SystemUser.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository.model import javax.persistence._ @@ -18,4 +17,4 @@ object SystemUser { user.activeAccountId = activeAccountId user } -} \ No newline at end of file +} diff --git a/server/src/main/scala/com/lbs/server/repository/model/package.scala b/server/src/main/scala/com/lbs/server/repository/model/package.scala index 0cb68f6..9df3853 100644 --- a/server/src/main/scala/com/lbs/server/repository/model/package.scala +++ b/server/src/main/scala/com/lbs/server/repository/model/package.scala @@ -1,4 +1,3 @@ - package com.lbs.server.repository import scala.language.implicitConversions 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 b550c22..4a98f49 100644 --- a/server/src/main/scala/com/lbs/server/service/ApiService.scala +++ b/server/src/main/scala/com/lbs/server/service/ApiService.scala @@ -1,4 +1,3 @@ - package com.lbs.server.service import cats.instances.either._ @@ -32,7 +31,9 @@ class ApiService extends SessionSupport { def getAllFacilities(accountId: Long, cityId: Long, serviceVariantId: Long): ThrowableOr[List[IdName]] = withSession(accountId) { session => - luxmedApi.dictionaryFacilitiesAndDoctors(session, cityId = Some(cityId), serviceVariantId = Some(serviceVariantId)).map(_.facilities) + luxmedApi + .dictionaryFacilitiesAndDoctors(session, cityId = Some(cityId), serviceVariantId = Some(serviceVariantId)) + .map(_.facilities) } def getAllServices(accountId: Long): ThrowableOr[List[DictionaryServiceVariants]] = @@ -42,60 +43,98 @@ class ApiService extends SessionSupport { def getAllDoctors(accountId: Long, cityId: Long, serviceVariantId: Long): ThrowableOr[List[Doctor]] = withSession(accountId) { session => - luxmedApi.dictionaryFacilitiesAndDoctors(session, cityId = Some(cityId), serviceVariantId = Some(serviceVariantId)).map(_.doctors) + luxmedApi + .dictionaryFacilitiesAndDoctors(session, cityId = Some(cityId), serviceVariantId = Some(serviceVariantId)) + .map(_.doctors) } - def getAvailableTerms(accountId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long, doctorId: Option[Long], - fromDate: LocalDateTime, toDate: LocalDateTime, timeFrom: LocalTime, timeTo: LocalTime, - languageId: Long = 10): ThrowableOr[List[TermExt]] = + def getAvailableTerms( + accountId: Long, + cityId: Long, + clinicId: Option[Long], + serviceId: Long, + doctorId: Option[Long], + fromDate: LocalDateTime, + toDate: LocalDateTime, + timeFrom: LocalTime, + timeTo: LocalTime, + languageId: Long = 10 + ): ThrowableOr[List[TermExt]] = withSession(accountId) { session => - val termsEither = luxmedApi.termsIndex(session, cityId, clinicId, serviceId, doctorId, - fromDate, toDate, languageId = languageId) - .map(termsIndexResponse => termsIndexResponse.termsForService.termsForDays - .flatMap(_.terms.map(term => TermExt(termsIndexResponse.termsForService.additionalData, term))) + val termsEither = luxmedApi + .termsIndex(session, cityId, clinicId, serviceId, doctorId, fromDate, toDate, languageId = languageId) + .map(termsIndexResponse => + termsIndexResponse.termsForService.termsForDays + .flatMap(_.terms.map(term => TermExt(termsIndexResponse.termsForService.additionalData, term))) ) termsEither.map { terms => terms.filter { term => val time = term.term.dateTimeFrom.get.toLocalTime val date = term.term.dateTimeFrom.get (doctorId.isEmpty || doctorId.contains(term.term.doctor.id)) && - (clinicId.isEmpty || clinicId.contains(term.term.clinicId)) && - (time == timeFrom || time == timeTo || (time.isAfter(timeFrom) && time.isBefore(timeTo))) && - (date == fromDate || date == toDate || (date.isAfter(fromDate) && date.isBefore(toDate))) + (clinicId.isEmpty || clinicId.contains(term.term.clinicId)) && + (time == timeFrom || time == timeTo || (time.isAfter(timeFrom) && time.isBefore(timeTo))) && + (date == fromDate || date == toDate || (date.isAfter(fromDate) && date.isBefore(toDate))) } } } - def reservationLockterm(accountId: Long, xsrfToken: XsrfToken, reservationLocktermRequest: ReservationLocktermRequest): ThrowableOr[ReservationLocktermResponse] = + def reservationLockterm( + accountId: Long, + xsrfToken: XsrfToken, + reservationLocktermRequest: ReservationLocktermRequest + ): ThrowableOr[ReservationLocktermResponse] = withSession(accountId) { session => luxmedApi.reservationLockterm(session, xsrfToken, reservationLocktermRequest) } - def deleteTemporaryReservation(accountId: Long, xsrfToken: XsrfToken, temporaryReservationId: Long): ThrowableOr[Unit] = + def deleteTemporaryReservation( + accountId: Long, + xsrfToken: XsrfToken, + temporaryReservationId: Long + ): ThrowableOr[Unit] = withSession(accountId) { session => luxmedApi.deleteTemporaryReservation(session, xsrfToken, temporaryReservationId) } - def reservationConfirm(accountId: Long, xsrfToken: XsrfToken, reservationConfirmRequest: ReservationConfirmRequest): ThrowableOr[ReservationConfirmResponse] = + def reservationConfirm( + accountId: Long, + xsrfToken: XsrfToken, + reservationConfirmRequest: ReservationConfirmRequest + ): ThrowableOr[ReservationConfirmResponse] = withSession(accountId) { session => luxmedApi.reservationConfirm(session, xsrfToken, reservationConfirmRequest) } - def reservationChangeTerm(accountId: Long, xsrfToken: XsrfToken, reservationChangetermRequest: ReservationChangetermRequest): ThrowableOr[ReservationConfirmResponse] = + def reservationChangeTerm( + accountId: Long, + xsrfToken: XsrfToken, + reservationChangetermRequest: ReservationChangetermRequest + ): ThrowableOr[ReservationConfirmResponse] = withSession(accountId) { session => luxmedApi.reservationChangeTerm(session, xsrfToken, reservationChangetermRequest) } - def history(accountId: Long, fromDate: LocalDateTime = LocalDateTime.now().minusYears(1), - toDate: LocalDateTime = LocalDateTime.now()): ThrowableOr[List[Event]] = + def history( + accountId: Long, + fromDate: LocalDateTime = LocalDateTime.now().minusYears(1), + toDate: LocalDateTime = LocalDateTime.now() + ): ThrowableOr[List[Event]] = withSession(accountId) { session => - luxmedApi.events(session, fromDate.atZone(DateTimeUtil.Zone), toDate.atZone(DateTimeUtil.Zone)).map(_.events.filter(_.status == "Realized")) + luxmedApi + .events(session, fromDate.atZone(DateTimeUtil.Zone), toDate.atZone(DateTimeUtil.Zone)) + .map(_.events.filter(_.status == "Realized")) } - def reserved(accountId: Long, fromDate: LocalDateTime = LocalDateTime.now(), - toDate: LocalDateTime = LocalDateTime.now().plusMonths(3)): ThrowableOr[List[Event]] = + def reserved( + accountId: Long, + fromDate: LocalDateTime = LocalDateTime.now(), + toDate: LocalDateTime = LocalDateTime.now().plusMonths(3) + ): ThrowableOr[List[Event]] = withSession(accountId) { session => - luxmedApi.events(session, fromDate.atZone(DateTimeUtil.Zone), toDate.atZone(DateTimeUtil.Zone)).map(_.events.filter(_.status == "Reserved")) + luxmedApi + .events(session, fromDate.atZone(DateTimeUtil.Zone), toDate.atZone(DateTimeUtil.Zone)) + .map(_.events.filter(_.status == "Reserved")) } def deleteReservation(accountId: Long, reservationId: Long): ThrowableOr[HttpResponse[String]] = diff --git a/server/src/main/scala/com/lbs/server/service/DataService.scala b/server/src/main/scala/com/lbs/server/service/DataService.scala index c404a01..f521792 100644 --- a/server/src/main/scala/com/lbs/server/service/DataService.scala +++ b/server/src/main/scala/com/lbs/server/service/DataService.scala @@ -1,4 +1,3 @@ - package com.lbs.server.service import com.lbs.api.json.model.IdName @@ -31,7 +30,12 @@ class DataService { dataRepository.getServiceHistory(userId, cityId, clinicId).mapTo[Seq[IdName]] } - def getLatestDoctorsByCityIdAndClinicIdAndServiceId(userId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): Seq[IdName] = { + def getLatestDoctorsByCityIdAndClinicIdAndServiceId( + userId: Long, + cityId: Long, + clinicId: Option[Long], + serviceId: Long + ): Seq[IdName] = { dataRepository.getDoctorHistory(userId, cityId, clinicId, serviceId).mapTo[Seq[IdName]] } @@ -78,7 +82,9 @@ class DataService { 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)) + userIdMaybe.flatMap(userId => + dataRepository.findAccountId(userId).map(_.toLong).map(accountId => userId -> accountId) + ) } def findCredentialsByUsername(username: String, userId: Long): Option[Credentials] = { @@ -109,18 +115,18 @@ class DataService { @Transactional def saveCredentials(source: MessageSource, username: String, password: String): Credentials = { - val userMaybe = dataRepository.findUserIdBySource(source.chatId, source.sourceSystem.id).flatMap { - userId => dataRepository.findUser(userId).map(_ -> userId) + val userMaybe = dataRepository.findUserIdBySource(source.chatId, source.sourceSystem.id).flatMap { userId => + dataRepository.findUser(userId).map(_ -> userId) } userMaybe match { case Some((user, userId)) => val credentialsMaybe = findCredentialsByUsername(username, userId) credentialsMaybe match { - case Some(credentials) => //user already exists + case Some(credentials) => // user already exists val sourceMaybe = dataRepository.findSource(source.chatId, source.sourceSystem.id, credentials.userId) sourceMaybe match { - case Some(_) => //source already exists. Just update credentials - case None => //add new source + case Some(_) => // source already exists. Just update credentials + case None => // add new source val src = Source(source.chatId, source.sourceSystem.id, credentials.userId) dataRepository.saveEntity(src) } @@ -135,8 +141,8 @@ class DataService { 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 + 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) } @@ -144,7 +150,7 @@ class DataService { dataRepository.saveEntity(credentials) } - case None => //everything is new + 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) @@ -171,7 +177,9 @@ class DataService { val service = ServiceHistory(accountId, serviceId.id, serviceId.name, cityId.id, clinicId.optionalId, time) dataRepository.saveEntity(service) - val doctorMaybe = doctorId.optionalId.map(id => DoctorHistory(accountId, 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) } } 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 f2bb361..a4f43f3 100644 --- a/server/src/main/scala/com/lbs/server/service/MonitoringService.scala +++ b/server/src/main/scala/com/lbs/server/service/MonitoringService.scala @@ -1,4 +1,3 @@ - package com.lbs.server.service import com.lbs.api.exception.InvalidLoginOrPasswordException @@ -54,7 +53,7 @@ class MonitoringService extends StrictLogging { def notifyUserAboutTerms(terms: Seq[TermExt], monitoring: Monitoring): Unit = { deactivateMonitoring(monitoring.accountId, monitoring.recordId) - val fiveTerms = terms.take(5).zipWithIndex //send only 5 closest terms + val fiveTerms = terms.take(5).zipWithIndex // send only 5 closest terms val messages = lang(monitoring.userId) val message = messages.availableTermsHeader(terms.length) + "\n\n" + @@ -68,8 +67,17 @@ class MonitoringService extends StrictLogging { private def monitor(monitoring: Monitoring): Unit = { logger.debug(s"Looking for available terms. Monitoring [#${monitoring.recordId}]") val dateFrom = optimizeDateFrom(monitoring.dateFrom.toLocalDateTime, monitoring.offset) - val termsEither = apiService.getAvailableTerms(monitoring.accountId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId, - monitoring.doctorId, dateFrom, monitoring.dateTo.toLocalDateTime, timeFrom = monitoring.timeFrom, timeTo = monitoring.timeTo) + val termsEither = apiService.getAvailableTerms( + monitoring.accountId, + monitoring.cityId, + monitoring.clinicId, + monitoring.serviceId, + monitoring.doctorId, + dateFrom, + monitoring.dateTo.toLocalDateTime, + timeFrom = monitoring.timeFrom, + timeTo = monitoring.timeTo + ) termsEither match { case Right(terms) => if (terms.nonEmpty) { @@ -105,7 +113,9 @@ class MonitoringService extends StrictLogging { val delaySnapshot = delay val periodSnapshot = period val future = monitoringExecutor.schedule(monitor(monitoring), delaySnapshot, periodSnapshot) - logger.debug(s"Scheduled monitoring: [#${monitoring.recordId}] with delay: $delaySnapshot and period: $periodSnapshot") + logger.debug( + s"Scheduled monitoring: [#${monitoring.recordId}] with delay: $delaySnapshot and period: $periodSnapshot" + ) activeMonitorings += (monitoring.recordId -> (monitoring -> future)) } } @@ -127,8 +137,9 @@ class MonitoringService extends StrictLogging { private def disableOutdated(): Unit = { val now = ZonedDateTime.now() - val toDisable = activeMonitorings.collect { case (id, (monitoring, _)) if monitoring.dateTo.isBefore(now) => - id -> monitoring + val toDisable = activeMonitorings.collect { + case (id, (monitoring, _)) if monitoring.dateTo.isBefore(now) => + id -> monitoring } toDisable.foreach { case (id, monitoring) => @@ -150,14 +161,37 @@ class MonitoringService extends StrictLogging { private def bookAppointment(term: TermExt, monitoring: Monitoring, rebookIfExists: Boolean): Unit = { val bookingResult = for { xsrfToken <- apiService.getXsrfToken(monitoring.accountId) - reservationLocktermResponse <- apiService.reservationLockterm(monitoring.accountId, xsrfToken, term.mapTo[ReservationLocktermRequest]) + reservationLocktermResponse <- apiService.reservationLockterm( + monitoring.accountId, + xsrfToken, + term.mapTo[ReservationLocktermRequest] + ) temporaryReservationId = reservationLocktermResponse.value.temporaryReservationId - response <- if (reservationLocktermResponse.value.changeTermAvailable && rebookIfExists) { - logger.info(s"Service [${monitoring.serviceName}] is already booked. Trying to update term") - bookOrUnlockTerm(monitoring.accountId, xsrfToken, temporaryReservationId, apiService.reservationChangeTerm(_, xsrfToken, (reservationLocktermResponse, term).mapTo[ReservationChangetermRequest])) - } else { - bookOrUnlockTerm(monitoring.accountId, xsrfToken, temporaryReservationId, apiService.reservationConfirm(_, xsrfToken, (reservationLocktermResponse, term).mapTo[ReservationConfirmRequest])) - } + response <- + if (reservationLocktermResponse.value.changeTermAvailable && rebookIfExists) { + logger.info(s"Service [${monitoring.serviceName}] is already booked. Trying to update term") + bookOrUnlockTerm( + monitoring.accountId, + xsrfToken, + temporaryReservationId, + apiService.reservationChangeTerm( + _, + xsrfToken, + (reservationLocktermResponse, term).mapTo[ReservationChangetermRequest] + ) + ) + } else { + bookOrUnlockTerm( + monitoring.accountId, + xsrfToken, + temporaryReservationId, + apiService.reservationConfirm( + _, + xsrfToken, + (reservationLocktermResponse, term).mapTo[ReservationConfirmRequest] + ) + ) + } } yield response bookingResult match { case Right(_) => @@ -168,9 +202,14 @@ class MonitoringService extends StrictLogging { } } - private def bookOrUnlockTerm[T](accountId: Long, xsrfToken: XsrfToken, temporaryReservationId: Long, fn: (Long) => Either[Throwable, T]): Either[Throwable, T] = { + private def bookOrUnlockTerm[T]( + accountId: Long, + xsrfToken: XsrfToken, + temporaryReservationId: Long, + fn: (Long) => Either[Throwable, T] + ): Either[Throwable, T] = { fn(accountId) match { - case r@Left(_) => + case r @ Left(_) => apiService.deleteTemporaryReservation(accountId, xsrfToken, temporaryReservationId) r case r => r @@ -218,11 +257,22 @@ class MonitoringService extends StrictLogging { val monitoringMaybe = dataService.findMonitoring(accountId, monitoringId) monitoringMaybe match { case Some(monitoring) => - val termsEither = apiService.getAvailableTerms(monitoring.accountId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId, - monitoring.doctorId, monitoring.dateFrom.toLocalDateTime, monitoring.dateTo.toLocalDateTime, timeFrom = monitoring.timeFrom, timeTo = monitoring.timeTo) + val termsEither = apiService.getAvailableTerms( + monitoring.accountId, + monitoring.cityId, + monitoring.clinicId, + monitoring.serviceId, + monitoring.doctorId, + monitoring.dateFrom.toLocalDateTime, + monitoring.dateTo.toLocalDateTime, + timeFrom = monitoring.timeFrom, + timeTo = monitoring.timeTo + ) termsEither match { case Right(terms) => - val termMaybe = terms.find(term => term.term.scheduleId == scheduleId && minutesSinceBeginOf2018(term.term.dateTimeFrom.get) == time) + val termMaybe = terms.find(term => + term.term.scheduleId == scheduleId && minutesSinceBeginOf2018(term.term.dateTimeFrom.get) == time + ) termMaybe match { case Some(term) => bookAppointment(term, monitoring, rebookIfExists = true) @@ -232,7 +282,8 @@ class MonitoringService extends StrictLogging { case Left(ex: InvalidLoginOrPasswordException) => logger.error(s"User entered invalid name or password. Monitoring will be disabled", ex) bot.sendMessage(monitoring.source, lang(monitoring.userId).loginHasChangedOrWrong) - case Left(ex) => logger.error(s"Error occurred during receiving terms for monitoring [#${monitoring.recordId}]", ex) + case Left(ex) => + logger.error(s"Error occurred during receiving terms for monitoring [#${monitoring.recordId}]", ex) } case None => logger.debug(s"Monitoring [#$monitoringId] not found in db") @@ -240,9 +291,7 @@ class MonitoringService extends StrictLogging { } implicit class MonitoringAsSource(monitoring: Monitoring) { - def source: MessageSource = MessageSource( - MessageSourceSystem(monitoring.sourceSystemId), monitoring.chatId - ) + def source: MessageSource = MessageSource(MessageSourceSystem(monitoring.sourceSystemId), monitoring.chatId) } private def lang(userId: Long) = localization.lang(userId) diff --git a/server/src/main/scala/com/lbs/server/service/SessionSupport.scala b/server/src/main/scala/com/lbs/server/service/SessionSupport.scala index c8d39db..0041d66 100644 --- a/server/src/main/scala/com/lbs/server/service/SessionSupport.scala +++ b/server/src/main/scala/com/lbs/server/service/SessionSupport.scala @@ -1,4 +1,3 @@ - package com.lbs.server.service import com.lbs.api.exception.SessionExpiredException @@ -27,7 +26,7 @@ trait SessionSupport extends StrictLogging { val credentialsMaybe = dataService.getCredentials(accountId) credentialsMaybe match { case Some(credentials) => fullLogin(credentials.username, credentials.password) - case None => Left(UserNotFoundException(accountId)) + case None => Left(UserNotFoundException(accountId)) } } 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 35cef5e..4017b70 100644 --- a/server/src/main/scala/com/lbs/server/util/package.scala +++ b/server/src/main/scala/com/lbs/server/util/package.scala @@ -1,4 +1,3 @@ - package com.lbs.server import com.lbs.api.json.model._ @@ -14,13 +13,11 @@ import java.util.Locale import scala.language.{higherKinds, implicitConversions} import scala.util.Try - package object util { object ServerModelConverters extends ModelConverters { - implicit val BookingDataToMonitoringConverter: - ObjectConverter[(UserId, BookingData), Monitoring] = + implicit val BookingDataToMonitoringConverter: ObjectConverter[(UserId, BookingData), Monitoring] = (data: (UserId, BookingData)) => { val (userId, bookingData) = data Monitoring( @@ -47,8 +44,8 @@ package object util { ) } - implicit val ReservationLocktermResponseAndTermToReservationConfirmRequestConverter: - ObjectConverter[(ReservationLocktermResponse, TermExt), ReservationConfirmRequest] = + implicit val ReservationLocktermResponseAndTermToReservationConfirmRequestConverter + : ObjectConverter[(ReservationLocktermResponse, TermExt), ReservationConfirmRequest] = (data: (ReservationLocktermResponse, TermExt)) => { val (reservationLocktermResponse, termExt) = data val term = termExt.term @@ -65,8 +62,8 @@ package object util { ) } - implicit val ReservationLocktermResponseAndTermToReservationChangeTermRequestConverter: - ObjectConverter[(ReservationLocktermResponse, TermExt), ReservationChangetermRequest] = + implicit val ReservationLocktermResponseAndTermToReservationChangeTermRequestConverter + : ObjectConverter[(ReservationLocktermResponse, TermExt), ReservationChangetermRequest] = (data: (ReservationLocktermResponse, TermExt)) => { val (reservationLocktermResponse, termExt) = data val term = termExt.term @@ -89,8 +86,7 @@ package object util { ) } - implicit val TermToReservationLocktermRequest: - ObjectConverter[TermExt, ReservationLocktermRequest] = + implicit val TermToReservationLocktermRequest: ObjectConverter[TermExt, ReservationLocktermRequest] = termExt => { val term = termExt.term val additionalData = termExt.additionalData @@ -113,7 +109,6 @@ package object util { ) } - implicit val HistoryToIdNameConverter: ObjectConverter[History, IdName] = (history: History) => IdName(history.id, history.name) } @@ -121,11 +116,13 @@ package object util { object MessageExtractors { object TextCommand { - def unapply(cmd: Command): Option[String] = if (cmd.callbackData.isEmpty) cmd.message.text.filter(_.nonEmpty) else None + def unapply(cmd: Command): Option[String] = + if (cmd.callbackData.isEmpty) cmd.message.text.filter(_.nonEmpty) else None } object OptionalTextCommand { - def unapply(cmd: Command): Option[Option[String]] = if (cmd.callbackData.isEmpty) Some(TextCommand.unapply(cmd)) else None + def unapply(cmd: Command): Option[Option[String]] = + if (cmd.callbackData.isEmpty) Some(TextCommand.unapply(cmd)) else None } object CallbackCommand { @@ -155,7 +152,8 @@ package object util { private val TimeFormat: DateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm") - private val DateTimeFormat: Locale => DateTimeFormatter = locale => DateTimeFormatter.ofPattern("EEE',' dd MMM yyyy',' HH:mm", locale) + private val DateTimeFormat: Locale => DateTimeFormatter = locale => + DateTimeFormatter.ofPattern("EEE',' dd MMM yyyy',' HH:mm", locale) def formatDate(date: LocalDateTime, locale: Locale): String = date.format(DateFormat(locale)) diff --git a/server/src/test/scala/com/lbs/server/conversation/AkkaTestKit.scala b/server/src/test/scala/com/lbs/server/conversation/AkkaTestKit.scala index 5fd7523..6a7799e 100644 --- a/server/src/test/scala/com/lbs/server/conversation/AkkaTestKit.scala +++ b/server/src/test/scala/com/lbs/server/conversation/AkkaTestKit.scala @@ -5,7 +5,11 @@ import akka.testkit.{ImplicitSender, TestKit} import org.scalatest.BeforeAndAfterAll import org.scalatest.wordspec.AnyWordSpecLike -abstract class AkkaTestKit extends TestKit(ActorSystem()) with ImplicitSender with AnyWordSpecLike with BeforeAndAfterAll { +abstract class AkkaTestKit + extends TestKit(ActorSystem()) + with ImplicitSender + with AnyWordSpecLike + with BeforeAndAfterAll { override def afterAll(): Unit = { TestKit.shutdownActorSystem(system) } diff --git a/server/src/test/scala/com/lbs/server/conversation/AuthSpec.scala b/server/src/test/scala/com/lbs/server/conversation/AuthSpec.scala index 117f38e..d9fe5dd 100644 --- a/server/src/test/scala/com/lbs/server/conversation/AuthSpec.scala +++ b/server/src/test/scala/com/lbs/server/conversation/AuthSpec.scala @@ -24,7 +24,6 @@ class AuthSpec extends AkkaTestKit { when(dataService.findUserAndAccountIdBySource(source)).thenReturn(None) val auth = new Auth(source, dataService, unauthorizedHelpFactory, loginActorFactory, chatActorFactory)(system) - "send english help on /start command" in { val cmd = Command(source, Message("1", Some("/start"))) auth ! cmd @@ -80,7 +79,6 @@ class AuthSpec extends AkkaTestKit { val auth = new Auth(source, dataService, unauthorizedHelpFactory, loginActorFactory, chatActorFactory)(system) - "forward all commands to chat actor" in { val cmd = Command(source, Message("1", Some("any"))) auth ! cmd diff --git a/server/src/test/scala/com/lbs/server/conversation/base/ConversationSpec.scala b/server/src/test/scala/com/lbs/server/conversation/base/ConversationSpec.scala index bfa1ab9..b489e36 100644 --- a/server/src/test/scala/com/lbs/server/conversation/base/ConversationSpec.scala +++ b/server/src/test/scala/com/lbs/server/conversation/base/ConversationSpec.scala @@ -22,35 +22,31 @@ class ConversationSpec extends AkkaTestKit { private var conf: String = _ def configure: Step = - monologue { - case Msg(confStr: String, data) => - conf = confStr - goto(askHello) using data.copy(configured = true) + monologue { case Msg(confStr: String, data) => + conf = confStr + goto(askHello) using data.copy(configured = true) } def askHello: Step = ask { data => self ! Hello - } onReply { - case Msg(Hello, data) => - goto(askWorld) using data.copy(hello = "hello") + } onReply { case Msg(Hello, data) => + goto(askWorld) using data.copy(hello = "hello") } def askWorld: Step = ask { data => self ! World - } onReply { - case Msg(World, data) => - goto(askDialogue) using data.copy(world = "world") + } onReply { case Msg(World, data) => + goto(askDialogue) using data.copy(world = "world") } def askDialogue: Step = ask { data => self ! Dialogue - } onReply { - case Msg(Dialogue, data) => - originator ! data.copy(people = "dialogue") -> conf - end() + } onReply { case Msg(Dialogue, data) => + originator ! data.copy(people = "dialogue") -> conf + end() } entryPoint(configure, Data()) @@ -64,7 +60,7 @@ class ConversationSpec extends AkkaTestKit { testConversation ! expected._2 originator.expectMsg(expected) - //reinit + // reinit testConversation.restart() testConversation ! expected._2 originator.expectMsg(expected) @@ -91,10 +87,9 @@ class ConversationSpec extends AkkaTestKit { def askMessage2: Step = ask { _ => self ! InvokeEnrichMessage - } onReply { - case Msg(InvokeEnrichMessage, data) => - originator ! data.copy(message2 = "world") - end() + } onReply { case Msg(InvokeEnrichMessage, data) => + originator ! data.copy(message2 = "world") + end() } entryPoint(configure1, Data()) @@ -107,7 +102,7 @@ class ConversationSpec extends AkkaTestKit { actor.start() originator.expectMsg(expected) - //reinit + // reinit actor.restart() originator.expectMsg(expected) } diff --git a/server/src/test/scala/com/lbs/server/conversation/base/ConversationTestProbe.scala b/server/src/test/scala/com/lbs/server/conversation/base/ConversationTestProbe.scala index 35cc5cb..0871683 100644 --- a/server/src/test/scala/com/lbs/server/conversation/base/ConversationTestProbe.scala +++ b/server/src/test/scala/com/lbs/server/conversation/base/ConversationTestProbe.scala @@ -10,7 +10,8 @@ import scala.reflect.ClassTag object ConversationTestProbe extends MockitoSugar { - class ConversationTestProbe[T <: Interactional](actorSystem: ActorSystem, conversationMock: T) extends TestProbe(actorSystem) { + class ConversationTestProbe[T <: Interactional](actorSystem: ActorSystem, conversationMock: T) + extends TestProbe(actorSystem) { when(conversationMock.ref).thenReturn(ref) when(conversationMock.!(any())(any())).thenCallRealMethod() when(conversationMock.start()).thenCallRealMethod() @@ -23,8 +24,8 @@ object ConversationTestProbe extends MockitoSugar { when(conversationMock.ContinueConversation).thenCallRealMethod() ignoreMsg { - case conversationMock.InitConversation => true - case conversationMock.StartConversation => true + case conversationMock.InitConversation => true + case conversationMock.StartConversation => true case conversationMock.ContinueConversation => true }