mirror of
https://github.com/dyrkin/luxmed-bot.git
synced 2025-12-26 23:21:40 +01:00
#33 use the latest luxmed api
This commit is contained in:
committed by
Yevhen Zadyra
parent
389b84117d
commit
017be02ba0
@@ -1,7 +1,7 @@
|
||||
dependencies {
|
||||
compile project(':common')
|
||||
|
||||
compile group: "org.scalaj", name: "scalaj-http_2.12", version: "2.4.1"
|
||||
compile group: "org.scalaj", name: "scalaj-http_2.12", version: "2.4.2"
|
||||
compile group: "org.json4s", name: "json4s-jackson_2.12", version: "3.6.0-M3"
|
||||
compile group: "com.softwaremill.quicklens", name: "quicklens_2.12", version: "1.4.12"
|
||||
}
|
||||
|
||||
@@ -1,26 +1,52 @@
|
||||
|
||||
package com.lbs.api
|
||||
|
||||
import com.lbs.api.http.Session
|
||||
import com.lbs.api.http.headers._
|
||||
import scalaj.http.{BaseHttp, HttpRequest}
|
||||
|
||||
import java.net.HttpCookie
|
||||
|
||||
object ApiHttp extends BaseHttp(
|
||||
userAgent = "PatientPortal/4.20.5 (pl.luxmed.pp.LUX-MED; build:853; iOS 13.5.1) Alamofire/4.9.1"
|
||||
userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"
|
||||
)
|
||||
|
||||
trait ApiBase {
|
||||
private val CommonHeaders =
|
||||
Map(
|
||||
Host -> "portalpacjenta.luxmed.pl",
|
||||
`Custom-User-Agent` -> "PatientPortal; 4.20.5; 4380E6AC-D291-4895-8B1B-F774C318BD7D; iOS; 14.5.1; iPhone8,1",
|
||||
Accept -> "*/*",
|
||||
Connection -> "keep-alive",
|
||||
`Accept-Encoding` -> "gzip;q=1.0, compress;q=0.5",
|
||||
`Accept-Language` -> "en;q=1.0, en-PL;q=0.9, pl-PL;q=0.8, ru-PL;q=0.7, uk-PL;q=0.6"
|
||||
Origin -> "https://portalpacjenta.luxmed.pl",
|
||||
`Custom-User-Agent` -> "Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
||||
`User-Agent` -> "Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
||||
Accept -> "application/json, text/plain, */*",
|
||||
`Accept-Encoding` -> "gzip, deflate, br",
|
||||
`Accept-Language` -> "pl;q=1.0, pl;q=0.9, en;q=0.8"
|
||||
)
|
||||
|
||||
|
||||
protected def http(url: String): HttpRequest = {
|
||||
ApiHttp(s"https://portalpacjenta.luxmed.pl/PatientPortalMobileAPI/api/$url").headers(CommonHeaders)
|
||||
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)
|
||||
.cookies(session.cookies)
|
||||
.header(Authorization, s"${session.tokenType} ${session.accessToken}")
|
||||
}
|
||||
|
||||
protected def httpNewApi(url: String, session: Session, cookiesMaybe: Option[Seq[HttpCookie]] = None): HttpRequest = {
|
||||
val req = ApiHttp(s"https://portalpacjenta.luxmed.pl/PatientPortal/$url")
|
||||
.headers(CommonHeaders)
|
||||
.header(Authorization, session.accessToken)
|
||||
cookiesMaybe.map(cookies => req.cookies(cookies)).getOrElse(req.cookies(session.cookies))
|
||||
}
|
||||
|
||||
protected def httpNewApi(url: String, cookies: IndexedSeq[HttpCookie]): HttpRequest = {
|
||||
ApiHttp(s"https://portalpacjenta.luxmed.pl/PatientPortal/$url")
|
||||
.headers(CommonHeaders)
|
||||
.cookies(cookies)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
|
||||
package com.lbs.api
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
import cats.implicits.toFunctorOps
|
||||
import com.lbs.api.ApiResponseMutators._
|
||||
import com.lbs.api.http._
|
||||
import com.lbs.api.http.headers._
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import com.lbs.api.json.model.{AvailableTermsResponse, ReservationFilterResponse, ReservedVisitsResponse, VisitsHistoryResponse, _}
|
||||
import com.lbs.api.json.model.{EventsResponse, TermsIndexResponse, _}
|
||||
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 {
|
||||
|
||||
private val dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
|
||||
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[LoginResponse] = {
|
||||
val request = http("token").
|
||||
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).
|
||||
@@ -29,160 +28,132 @@ class LuxmedApi[F[_] : ThrowableMonad] extends ApiBase {
|
||||
post[LoginResponse](request)
|
||||
}
|
||||
|
||||
def refreshToken(refreshToken: String, clientId: String = "iPhone"): F[LoginResponse] = {
|
||||
val request = http("token").
|
||||
header(`Content-Type`, "application/x-www-form-urlencoded").
|
||||
header(`x-api-client-identifier`, clientId).
|
||||
param("client_id", clientId).
|
||||
param("grant_type", "refresh_token").
|
||||
param("refresh_token", refreshToken)
|
||||
post[LoginResponse](request)
|
||||
def loginToApp(session: Session): F[HttpResponse[Unit]] = {
|
||||
val request = httpNewApi("Account/LogInToApp?app=search&lang=pl&client=2&paymentSupported=true", session)
|
||||
.header(Authorization, session.accessToken)
|
||||
getVoid(request)
|
||||
}
|
||||
|
||||
def reservedVisits(accessToken: String, tokenType: String, fromDate: ZonedDateTime = ZonedDateTime.now(),
|
||||
toDate: ZonedDateTime = ZonedDateTime.now().plusMonths(3)): F[ReservedVisitsResponse] = {
|
||||
val request = http("visits/reserved").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken").
|
||||
param("fromDate", dateFormat.format(fromDate)).
|
||||
param("toDate", dateFormat.format(toDate))
|
||||
get[ReservedVisitsResponse](request).mutate
|
||||
def getForgeryToken(session: Session): F[HttpResponse[ForgeryTokenResponse]] = {
|
||||
val request = httpNewApi("security/getforgerytoken", session)
|
||||
get[ForgeryTokenResponse](request)
|
||||
}
|
||||
|
||||
def visitsHistory(accessToken: String, tokenType: String, fromDate: ZonedDateTime = ZonedDateTime.now().minusYears(1),
|
||||
toDate: ZonedDateTime = ZonedDateTime.now(), page: Int = 1, pageSize: Int = 100): F[VisitsHistoryResponse] = {
|
||||
val request = http("visits/history").
|
||||
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").
|
||||
header(Authorization, s"$tokenType $accessToken").
|
||||
param("fromDate", dateFormat.format(fromDate)).
|
||||
param("toDate", dateFormat.format(toDate)).
|
||||
param("page", page.toString).
|
||||
param("pageSize", pageSize.toString)
|
||||
get[VisitsHistoryResponse](request).mutate
|
||||
param("filter.filterDateFrom", dateFormatEvents.format(fromDate)).
|
||||
param("filter.filterDateTo", dateFormatEvents.format(toDate))
|
||||
get[EventsResponse](request).map(_.body)
|
||||
}
|
||||
|
||||
def reservationFilter(accessToken: String, tokenType: String, fromDate: ZonedDateTime = ZonedDateTime.now(),
|
||||
toDate: Option[ZonedDateTime] = None, cityId: Option[Long] = None, clinicId: Option[Long] = None,
|
||||
serviceId: Option[Long] = None): F[ReservationFilterResponse] = {
|
||||
val request = http("visits/available-terms/reservation-filter").
|
||||
def dictionaryCities(session: Session): F[List[DictionaryCity]] = {
|
||||
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")
|
||||
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").
|
||||
header(Authorization, s"$tokenType $accessToken").
|
||||
param("cityId", cityId.map(_.toString)).
|
||||
param("clinicId", clinicId.map(_.toString)).
|
||||
param("fromDate", dateFormat.format(fromDate)).
|
||||
param("toDate", toDate.map(dateFormat.format)).
|
||||
param("serviceId", serviceId.map(_.toString))
|
||||
get[ReservationFilterResponse](request).mutate
|
||||
param("serviceVariantId", serviceVariantId.map(_.toString))
|
||||
get[FacilitiesAndDoctors](request).map(_.body)
|
||||
}
|
||||
|
||||
def availableTerms(accessToken: String, tokenType: String, payerId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long, doctorId: Option[Long],
|
||||
fromDate: ZonedDateTime = ZonedDateTime.now(), toDate: Option[ZonedDateTime] = None, timeOfDay: Int = 0,
|
||||
languageId: Long = 10, findFirstFreeTerm: Boolean = false): F[AvailableTermsResponse] = {
|
||||
val request = http("visits/available-terms").
|
||||
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").
|
||||
header(Authorization, s"$tokenType $accessToken").
|
||||
param("cityId", cityId.toString).
|
||||
param("doctorId", doctorId.map(_.toString)).
|
||||
param("findFirstFreeTerm", findFirstFreeTerm.toString).
|
||||
param("fromDate", dateFormat.format(fromDate)).
|
||||
param("serviceVariantId", serviceId.toString).
|
||||
param("languageId", languageId.toString).
|
||||
param("payerId", payerId.toString).
|
||||
param("clinicId", clinicId.map(_.toString)).
|
||||
param("serviceId", serviceId.toString).
|
||||
param("timeOfDay", timeOfDay.toString).
|
||||
param("toDate", dateFormat.format(toDate.getOrElse(fromDate.plusMonths(3))))
|
||||
get[AvailableTermsResponse](request).mutate
|
||||
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 temporaryReservation(accessToken: String, tokenType: String, temporaryReservationRequest: TemporaryReservationRequest): F[TemporaryReservationResponse] = {
|
||||
val request = http("visits/temporary-reservation").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken")
|
||||
post[TemporaryReservationResponse](request, bodyOpt = Some(temporaryReservationRequest))
|
||||
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(accessToken: String, tokenType: String, temporaryReservationId: Long): F[HttpResponse[String]] = {
|
||||
val request = http(s"visits/temporary-reservation/$temporaryReservationId").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken")
|
||||
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")
|
||||
.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")
|
||||
.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")
|
||||
.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")
|
||||
delete(request)
|
||||
}
|
||||
|
||||
def valuations(accessToken: String, tokenType: String, valuationsRequest: ValuationsRequest): F[ValuationsResponse] = {
|
||||
val request = http("visits/available-terms/valuations").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken")
|
||||
post[ValuationsResponse](request, bodyOpt = Some(valuationsRequest))
|
||||
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]))
|
||||
}
|
||||
|
||||
def reservation(accessToken: String, tokenType: String, reservationRequest: ReservationRequest): F[ReservationResponse] = {
|
||||
val request = http("visits/reserved").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken")
|
||||
post[ReservationResponse](request, bodyOpt = Some(reservationRequest))
|
||||
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]))
|
||||
}
|
||||
|
||||
def deleteReservation(accessToken: String, tokenType: String, reservationId: Long): F[HttpResponse[String]] = {
|
||||
val request = http(s"visits/reserved/$reservationId").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken")
|
||||
delete(request)
|
||||
private def getVoid[T <: SerializableJsonObject](request: HttpRequest)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[Unit]] = {
|
||||
request.invoke.map(r => r.copy(body = {}))
|
||||
}
|
||||
|
||||
//204 means OK?
|
||||
def canTermBeChanged(accessToken: String, tokenType: String, reservationId: Long): F[HttpResponse[String]] = {
|
||||
val request = http(s"visits/reserved/$reservationId/can-term-be-changed").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken")
|
||||
request.invoke
|
||||
}
|
||||
|
||||
def detailToChangeTerm(accessToken: String, tokenType: String, reservationId: Long): F[ChangeTermDetailsResponse] = {
|
||||
val request = http(s"visits/reserved/$reservationId/details-to-change-term").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken")
|
||||
get[ChangeTermDetailsResponse](request)
|
||||
}
|
||||
|
||||
def temporaryReservationToChangeTerm(accessToken: String, tokenType: String, reservationId: Long, temporaryReservationRequest: TemporaryReservationRequest): F[TemporaryReservationResponse] = {
|
||||
val request = http(s"visits/reserved/$reservationId/temporary-reservation-to-change-term").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken")
|
||||
post[TemporaryReservationResponse](request, bodyOpt = Some(temporaryReservationRequest))
|
||||
}
|
||||
|
||||
def valuationToChangeTerm(accessToken: String, tokenType: String, reservationId: Long, valuationsRequest: ValuationsRequest): F[ValuationsResponse] = {
|
||||
val request = http(s"visits/reserved/$reservationId/valuations-to-change-term").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken")
|
||||
post[ValuationsResponse](request, bodyOpt = Some(valuationsRequest))
|
||||
}
|
||||
|
||||
def changeTerm(accessToken: String, tokenType: String, reservationId: Long, reservationRequest: ReservationRequest): F[ChangeTermResponse] = {
|
||||
val request = http(s"visits/reserved/$reservationId/term").
|
||||
header(`Content-Type`, "application/json").
|
||||
header(Authorization, s"$tokenType $accessToken")
|
||||
put[ChangeTermResponse](request, bodyOpt = Some(reservationRequest))
|
||||
}
|
||||
|
||||
private def get[T <: SerializableJsonObject](request: HttpRequest)(implicit mf: scala.reflect.Manifest[T]): F[T] = {
|
||||
request.invoke.map(_.body.as[T])
|
||||
}
|
||||
|
||||
private def post[T <: SerializableJsonObject](request: HttpRequest, bodyOpt: Option[SerializableJsonObject] = None)(implicit mf: scala.reflect.Manifest[T]): F[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
|
||||
}
|
||||
postRequest.invoke.map(_.body.as[T])
|
||||
postRequest.invoke.map(r => r.copy(body = r.body.as[T]))
|
||||
}
|
||||
|
||||
private def put[T <: SerializableJsonObject](request: HttpRequest, bodyOpt: Option[SerializableJsonObject] = None)(implicit mf: scala.reflect.Manifest[T]): F[T] = {
|
||||
private def put[T <: SerializableJsonObject](request: HttpRequest, bodyOpt: Option[SerializableJsonObject] = None)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[T]] = {
|
||||
val putRequest = bodyOpt match {
|
||||
case Some(body) => request.put(body.asJson)
|
||||
case None => request.method("PUT")
|
||||
}
|
||||
putRequest.invoke.map(_.body.as[T])
|
||||
putRequest.invoke.map(r => r.copy(body = r.body.as[T]))
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
postRequest.invoke.void
|
||||
}
|
||||
|
||||
private def delete(request: HttpRequest): F[HttpResponse[String]] = {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
package com.lbs.api.exception
|
||||
|
||||
class ServiceIsAlreadyBookedException extends ApiException("You have already booked this service")
|
||||
@@ -9,33 +9,31 @@ import com.lbs.api.json.model._
|
||||
import com.lbs.common.Logger
|
||||
import scalaj.http.{HttpRequest, HttpResponse}
|
||||
|
||||
import java.net.HttpCookie
|
||||
import scala.language.higherKinds
|
||||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
package object http extends Logger {
|
||||
|
||||
case class Session(accessToken: String, tokenType: String, cookies: Seq[HttpCookie])
|
||||
|
||||
object headers {
|
||||
val `Content-Type` = "Content-Type"
|
||||
val `xsrf-token` = "xsrf-token"
|
||||
val Host = "Host"
|
||||
val Origin = "Origin"
|
||||
val Accept = "Accept"
|
||||
val Connection = "Connection"
|
||||
val `Accept-Encoding` = "Accept-Encoding"
|
||||
val `User-Agent` = "User-Agent"
|
||||
val `Custom-User-Agent` = "Custom-User-Agent"
|
||||
val `x-api-client-identifier` = "x-api-client-identifier"
|
||||
val `Accept-Language` = "Accept-Language"
|
||||
val `Accept-Language` = "accept-language"
|
||||
val Authorization = "Authorization"
|
||||
}
|
||||
|
||||
private val SensitiveHeaders = List("passw", "access_token", "refresh_token", "authorization")
|
||||
|
||||
implicit class HttpResponseWithJsonDeserializationSupport(httpResponse: HttpResponse[String]) {
|
||||
|
||||
def asEntity[T <: SerializableJsonObject](implicit mf: scala.reflect.Manifest[T]): HttpResponse[T] = {
|
||||
httpResponse.copy(body = httpResponse.body.as[T])
|
||||
}
|
||||
}
|
||||
|
||||
implicit class ExtendedHttpRequest[F[_] : ThrowableMonad](httpRequest: HttpRequest) {
|
||||
def invoke: F[HttpResponse[String]] = {
|
||||
val me = MonadError[F, Throwable]
|
||||
@@ -65,8 +63,6 @@ package object http extends Logger {
|
||||
val errorMessage = message.toLowerCase
|
||||
if (errorMessage.contains("invalid login or password"))
|
||||
new InvalidLoginOrPasswordException
|
||||
else if (errorMessage.contains("already booked this service"))
|
||||
new ServiceIsAlreadyBookedException
|
||||
else if (errorMessage.contains("session has expired"))
|
||||
new SessionExpiredException
|
||||
else
|
||||
@@ -77,7 +73,6 @@ package object http extends Logger {
|
||||
val body = httpResponse.body
|
||||
val code = httpResponse.code
|
||||
Try(body.as[LuxmedErrorsMap])
|
||||
.orElse(Try(body.as[LuxmedErrorsList]))
|
||||
.orElse(Try(body.as[LuxmedError]))
|
||||
.map(error => luxmedErrorToApiException(code, error))
|
||||
.toOption
|
||||
|
||||
@@ -1,31 +1,48 @@
|
||||
|
||||
package com.lbs.api.json
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
import com.lbs.api.json.model.SerializableJsonObject
|
||||
import com.lbs.common.Logger
|
||||
import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.{LocalDateTime, LocalTime, ZonedDateTime}
|
||||
|
||||
object JsonSerializer {
|
||||
|
||||
private val localDateTimeSerializer = new CustomSerializer[ZonedDateTime](_ => ( {
|
||||
object JsonSerializer extends Logger {
|
||||
|
||||
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 implicit val formats: Formats = DefaultFormats.withStrictArrayExtraction + localDateTimeSerializer
|
||||
private val localTimeSerializer = new CustomSerializer[LocalTime](_ => ( {
|
||||
case JString(str) => LocalTime.parse(str)
|
||||
}, {
|
||||
case localTime: LocalTime => JString(localTime.toString)
|
||||
}
|
||||
))
|
||||
|
||||
def extract[T <: SerializableJsonObject](jsonString: String)(implicit mf: scala.reflect.Manifest[T]): T = {
|
||||
private val localDateTimeSerializer = new CustomSerializer[LocalDateTime](_ => ( {
|
||||
case JString(str) => LocalDateTime.parse(str)
|
||||
}, {
|
||||
case localTime: LocalDateTime => JString(localTime.toString)
|
||||
}
|
||||
))
|
||||
|
||||
private implicit val formats: Formats = DefaultFormats.withStrictArrayExtraction + zonedDateTimeSerializer + localTimeSerializer + localDateTimeSerializer
|
||||
|
||||
def extract[T](jsonString: String)(implicit mf: scala.reflect.Manifest[T]): T = {
|
||||
parse(jsonString).camelizeKeys.extract[T]
|
||||
}
|
||||
|
||||
def write[T <: SerializableJsonObject](jsonObject: T): String = {
|
||||
pretty(render(Extraction.decompose(jsonObject).pascalizeKeys))
|
||||
def write[T](jsonObject: T): String = {
|
||||
val json = pretty(render(Extraction.decompose(jsonObject)))
|
||||
info(json)
|
||||
json
|
||||
}
|
||||
|
||||
object extensions {
|
||||
@@ -34,6 +51,10 @@ object JsonSerializer {
|
||||
def as[T <: SerializableJsonObject](implicit mf: scala.reflect.Manifest[T]): T = {
|
||||
extract[T](jsonString)
|
||||
}
|
||||
|
||||
def asList[T <: SerializableJsonObject](implicit mf: scala.reflect.Manifest[T]): List[T] = {
|
||||
extract[List[T]](jsonString)
|
||||
}
|
||||
}
|
||||
|
||||
implicit class JsonObjectToString[T <: SerializableJsonObject](jsonObject: T) {
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
*
|
||||
{
|
||||
"AvailableVisitsTermPresentation": [
|
||||
{
|
||||
"Clinic": {
|
||||
"Id": 6,
|
||||
"Name": "LX Wrocław - Szewska 3A"
|
||||
},
|
||||
"Doctor": {
|
||||
"Id": 38275,
|
||||
"Name": "lek. med. ANNA ABRAMCZYK"
|
||||
},
|
||||
"Impediment": {
|
||||
"ImpedimentText": "",
|
||||
"IsImpediment": false
|
||||
},
|
||||
"IsFree": false,
|
||||
"PayerDetailsList": [
|
||||
{
|
||||
"BrandId": 2,
|
||||
"ContractId": 1111111,
|
||||
"PayerId": 22222,
|
||||
"PayerName": "FIRMA POLAND SP. Z O.O.",
|
||||
"ProductElementId": 3333333,
|
||||
"ProductId": 44444,
|
||||
"ProductInContractId": 555555,
|
||||
"ServaAppId": 0,
|
||||
"ServaId": 6666
|
||||
},
|
||||
{
|
||||
"BrandId": 2,
|
||||
"ContractId": 1111111,
|
||||
"PayerId": 22222,
|
||||
"PayerName": "FIRMA POLAND SP. Z O.O.",
|
||||
"ProductElementId": 8547135,
|
||||
"ProductId": 44444,
|
||||
"ProductInContractId": 555555,
|
||||
"ServaAppId": 1,
|
||||
"ServaId": 6666
|
||||
}
|
||||
],
|
||||
"ReferralRequiredByProduct": false,
|
||||
"ReferralRequiredByService": false,
|
||||
"RoomId": 543,
|
||||
"ScheduleId": 3331908,
|
||||
"ServiceId": 6666,
|
||||
"VisitDate": {
|
||||
"FormattedDate": "26th April, Thu. at 12:40 pm",
|
||||
"StartDateTime": "2018-02-23T11:30:00+02:00"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
*/
|
||||
case class AvailableTermsResponse(availableVisitsTermPresentation: List[AvailableVisitsTermPresentation]) extends SerializableJsonObject
|
||||
|
||||
case class AvailableVisitsTermPresentation(clinic: IdName, doctor: IdName, payerDetailsList: List[PayerDetails],
|
||||
referralRequiredByProduct: Boolean, referralRequiredByService: Boolean,
|
||||
roomId: Long, scheduleId: Long, serviceId: Long, visitDate: VisitDate) extends SerializableJsonObject
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
{
|
||||
"AvailableNewPayers": [
|
||||
{
|
||||
"Id": 45185,
|
||||
"IsFeeForService": false,
|
||||
"Name": "Moja firma SP. Z O.O."
|
||||
}
|
||||
],
|
||||
"CityId": 5,
|
||||
"Payer": {
|
||||
"Id": 45185,
|
||||
"IsFeeForService": false,
|
||||
"Name": "Moja firma SP. Z O.O."
|
||||
}
|
||||
}
|
||||
*/
|
||||
case class ChangeTermDetailsResponse(availableNewPayers: ShortPayerDetails, cityId: Long, payer: ShortPayerDetails) extends SerializableJsonObject
|
||||
|
||||
case class ShortPayerDetails(id: Long, isFeeForService: Boolean, name: String) extends SerializableJsonObject
|
||||
@@ -1,11 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
{
|
||||
"PreparationInfo": {
|
||||
"IsPreparationRequired": true
|
||||
}
|
||||
}
|
||||
*/
|
||||
case class ChangeTermResponse(preparationInfo: PreparationInfo) extends SerializableJsonObject
|
||||
@@ -0,0 +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
|
||||
@@ -0,0 +1,175 @@
|
||||
|
||||
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)
|
||||
}
|
||||
19
api/src/main/scala/com/lbs/api/json/model/Doctor.scala
Normal file
19
api/src/main/scala/com/lbs/api/json/model/Doctor.scala
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
* {
|
||||
"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 {
|
||||
override def name: String = firstName + " " + lastName
|
||||
}
|
||||
7
api/src/main/scala/com/lbs/api/json/model/Empty.scala
Normal file
7
api/src/main/scala/com/lbs/api/json/model/Empty.scala
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
{}
|
||||
*/
|
||||
case class Empty() extends SerializableJsonObject
|
||||
109
api/src/main/scala/com/lbs/api/json/model/EventsResponse.scala
Normal file
109
api/src/main/scala/com/lbs/api/json/model/EventsResponse.scala
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
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"
|
||||
*}
|
||||
*/
|
||||
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 EventClinic(address: String, city: String)
|
||||
|
||||
case class EventDoctor(lastname: String, name: String)
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
*
|
||||
*/
|
||||
case class FacilitiesAndDoctors(doctors: List[Doctor], facilities: List[IdName]) extends SerializableJsonObject
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
* {
|
||||
* "token": "IDtjG_ECOd_ETYE2fwrCoTcC6bW935cn_nUh6d3BaEa-jvPlHfPLOY5AkF",
|
||||
* }
|
||||
*/
|
||||
case class ForgeryTokenResponse(token: String) extends SerializableJsonObject
|
||||
@@ -1,11 +1,16 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
trait Identified {
|
||||
def id: Long
|
||||
def name: String
|
||||
|
||||
def toIdName: IdName = IdName(id, name)
|
||||
}
|
||||
|
||||
case class IdName(id: Long, name: String) extends Identified {
|
||||
def optionalId: Option[Long] = Option(id).filterNot(_ == -1L)
|
||||
}
|
||||
|
||||
object IdName {
|
||||
def from(id: java.lang.Long, name: String): IdName = new IdName(if (id != null) id else -1, name)
|
||||
}
|
||||
|
||||
case class IdName(id: Long, name: String) {
|
||||
def optionalId: Option[Long] = Option(id).filterNot(_ == -1L)
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
case class LuxmedErrorsList(errors: List[LuxmedErrorsListElement]) extends SerializableJsonObject with LuxmedBaseError {
|
||||
override def message: String = errors.map(_.message).mkString("; ")
|
||||
}
|
||||
|
||||
case class LuxmedErrorsListElement(errorCode: Int, message: String, additionalData: Map[String, String]) extends SerializableJsonObject
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
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
|
||||
*}
|
||||
*}
|
||||
*/
|
||||
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
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
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
|
||||
*}
|
||||
*/
|
||||
case class ReservationConfirmRequest(date: String, doctorId: Long, facilityId: Long, roomId: Long, scheduleId: Long, serviceVariantId: Long,
|
||||
temporaryReservationId: Long, timeFrom: LocalTime, valuation: Valuation) extends SerializableJsonObject
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
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": []
|
||||
}
|
||||
*/
|
||||
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
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
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"
|
||||
*}
|
||||
*/
|
||||
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
|
||||
@@ -0,0 +1,74 @@
|
||||
|
||||
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": []
|
||||
*}
|
||||
*/
|
||||
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 RelatedVisit(doctor: Doctor, facilityName: String, isTelemedicine: Boolean, reservationId: Long,
|
||||
timeFrom: LocalTime, timeTo: LocalTime)
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
|
||||
/**
|
||||
{
|
||||
"ClinicId": 6,
|
||||
"DoctorId": 38509,
|
||||
"PayerData": {
|
||||
"ContractId": 1111111,
|
||||
"PayerId": 22222,
|
||||
"PayerName": "FIRMA POLAND SP. Z O.O.",
|
||||
"ProductElementId": 8547100,
|
||||
"ProductId": 44444,
|
||||
"ProductInContractId": 555555,
|
||||
"ServaAppId": 0,
|
||||
"ServaId": 6621
|
||||
},
|
||||
"RoomId": 159,
|
||||
"ServiceId": 6621,
|
||||
"StartDateTime": "2018-06-04T11:00:00+02:00",
|
||||
"TemporaryReservationId": 250303839
|
||||
}
|
||||
*/
|
||||
case class ReservationRequest(clinicId: Long, doctorId: Long, payerData: PayerDetails, roomId: Long, serviceId: Long,
|
||||
startDateTime: ZonedDateTime, temporaryReservationId: Long) extends SerializableJsonObject
|
||||
@@ -1,24 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
|
||||
/**
|
||||
{
|
||||
"PreparationInfo": {
|
||||
"IsPreparationRequired": true
|
||||
},
|
||||
"ReservedVisitsLimitInfo": {
|
||||
"CanReserve": true,
|
||||
"HasPatientLimit": false,
|
||||
"MaxReservedVisitsCount": null,
|
||||
"Message": "",
|
||||
"ReservedVisitsCount": null
|
||||
}
|
||||
}
|
||||
*/
|
||||
case class ReservationResponse(preparationInfo: PreparationInfo, reservedVisitsLimitInfo: ReservedVisitsLimitInfo) extends SerializableJsonObject
|
||||
|
||||
case class PreparationInfo(isPreparationRequired: Boolean) extends SerializableJsonObject
|
||||
|
||||
case class ReservedVisitsLimitInfo(canReserve: Boolean, hasPatientLimit: Boolean, maxReservedVisitsCount: Option[Int],
|
||||
message: String, reservedVisitsCount: Option[Int]) extends SerializableJsonObject
|
||||
@@ -1,44 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
*
|
||||
* {
|
||||
* "ReservedVisits": [
|
||||
*{
|
||||
*"CanBeCanceled": true,
|
||||
*"Clinic": {
|
||||
*"Id": 6,
|
||||
*"Name": "LX Wrocław - Szewska 3A"
|
||||
*},
|
||||
*"DoctorName": "lek. stom. TARAS SHEVCZENKO",
|
||||
*"Impediment": {
|
||||
*"ImpedimentText": "",
|
||||
*"IsImpediment": false
|
||||
*},
|
||||
*"IsAdditional": false,
|
||||
*"IsPreparationRequired": false,
|
||||
*"Links": [
|
||||
*{
|
||||
*"Href": "/PatientPortalMobileAPI/api/visits/preparations/6621",
|
||||
*"Method": "GET",
|
||||
*"Rel": "get_preparations"
|
||||
*}
|
||||
*],
|
||||
*"ReservationId": 888888888,
|
||||
*"Service": {
|
||||
*"Id": 6621,
|
||||
*"Name": "Umówienie wizyty u stomatologa"
|
||||
*},
|
||||
*"VisitDate": {
|
||||
*"FormattedDate": "21rd May, Mon. at 3:00 pm",
|
||||
*"StartDateTime": "2018-05-21T15:00:00+02:00"
|
||||
*}
|
||||
*}
|
||||
*]
|
||||
*}
|
||||
*/
|
||||
case class ReservedVisitsResponse(reservedVisits: List[ReservedVisit]) extends SerializableJsonObject
|
||||
|
||||
case class ReservedVisit(canBeCanceled: Boolean, clinic: IdName, doctorName: String,
|
||||
reservationId: Long, service: IdName, visitDate: VisitDate) extends SerializableJsonObject
|
||||
@@ -1,43 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
|
||||
/**
|
||||
{
|
||||
"ClinicId": 6,
|
||||
"DoctorId": 38275,
|
||||
"PayerDetailsList": [
|
||||
{
|
||||
"BrandId": 2,
|
||||
"ContractId": 1111111,
|
||||
"PayerId": 22222,
|
||||
"PayerName": "FIRMA POLAND SP. Z O.O.",
|
||||
"ProductElementId": 3333333,
|
||||
"ProductId": 44444,
|
||||
"ProductInContractId": 555555,
|
||||
"ServaAppId": 0,
|
||||
"ServaId": 6666
|
||||
},
|
||||
{
|
||||
"BrandId": 2,
|
||||
"ContractId": 1111111,
|
||||
"PayerId": 22222,
|
||||
"PayerName": "FIRMA POLAND SP. Z O.O.",
|
||||
"ProductElementId": 8547135,
|
||||
"ProductId": 44444,
|
||||
"ProductInContractId": 555555,
|
||||
"ServaAppId": 1,
|
||||
"ServaId": 6666
|
||||
}
|
||||
],
|
||||
"ReferralRequiredByService": false,
|
||||
"RoomId": 543,
|
||||
"ServiceId": 6666,
|
||||
"StartDateTime": "2018-02-23T11:30:00+02:00"
|
||||
}
|
||||
*/
|
||||
case class TemporaryReservationRequest(clinicId: Long, doctorId: Long, payerDetailsList: List[PayerDetails],
|
||||
referralRequiredByService: Boolean, roomId: Long, serviceId: Long,
|
||||
startDateTime: ZonedDateTime) extends SerializableJsonObject
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
case class TemporaryReservationResponse(hasReferralRequired: Boolean, id: Long,
|
||||
informationMessages: List[String],
|
||||
mustTermOfReservedVisitBeChanged: Boolean) extends SerializableJsonObject
|
||||
@@ -0,0 +1,134 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.LocalDateTime
|
||||
|
||||
/**
|
||||
*
|
||||
* {
|
||||
* "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",
|
||||
*"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 PreparationItem(header: Option[String], text: Option[String])
|
||||
|
||||
case class AdditionalData(isPreparationRequired: Boolean, preparationItems: List[PreparationItem])
|
||||
|
||||
case class TermsForDay(day: LocalDateTime, terms: List[Term]) extends SerializableJsonObject
|
||||
|
||||
case class Term(clinic: String, clinicId: Long, dateTimeFrom: LocalDateTime, dateTimeTo: LocalDateTime, 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
|
||||
|
||||
23
api/src/main/scala/com/lbs/api/json/model/Valuation.scala
Normal file
23
api/src/main/scala/com/lbs/api/json/model/Valuation.scala
Normal file
@@ -0,0 +1,23 @@
|
||||
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
|
||||
}
|
||||
*/
|
||||
|
||||
case class Valuation(alternativePrice: Option[String], contractId: Long, isExternalReferralAllowed: Boolean,
|
||||
isReferralRequired: Boolean, payerId: Long, price: Double, productElementId: Long, productId: Long,
|
||||
productInContractId: Long, requireReferralForPP: Boolean, valuationType: Long) {
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
|
||||
/**
|
||||
{
|
||||
"ClinicId": 6,
|
||||
"DoctorId": 38275,
|
||||
"PayerDetailsList": [
|
||||
{
|
||||
"BrandId": 2,
|
||||
"ContractId": 1111111,
|
||||
"PayerId": 22222,
|
||||
"PayerName": "FIRMA POLAND SP. Z O.O.",
|
||||
"ProductElementId": 3333333,
|
||||
"ProductId": 44444,
|
||||
"ProductInContractId": 555555,
|
||||
"ServaAppId": 0,
|
||||
"ServaId": 6666
|
||||
},
|
||||
{
|
||||
"BrandId": 2,
|
||||
"ContractId": 1111111,
|
||||
"PayerId": 22222,
|
||||
"PayerName": "FIRMA POLAND SP. Z O.O.",
|
||||
"ProductElementId": 8547135,
|
||||
"ProductId": 44444,
|
||||
"ProductInContractId": 555555,
|
||||
"ServaAppId": 1,
|
||||
"ServaId": 6666
|
||||
}
|
||||
],
|
||||
"ReferralRequiredByService": false,
|
||||
"RoomId": 543,
|
||||
"ServiceId": 6666,
|
||||
"StartDateTime": "2018-02-23T11:30:00+02:00"
|
||||
}
|
||||
*/
|
||||
case class ValuationsRequest(clinicId: Long, doctorId: Long, payerDetailsList: List[PayerDetails],
|
||||
referralRequiredByService: Boolean, roomId: Long, serviceId: Long,
|
||||
startDateTime: ZonedDateTime) extends SerializableJsonObject
|
||||
@@ -1,41 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
|
||||
/**
|
||||
{
|
||||
"OptionsQuestion": "Would you like to confirm your appointment booking?",
|
||||
"VisitTermVariants": [
|
||||
{
|
||||
"CanBeReserve": true,
|
||||
"InfoMessage": "During the appointment, the physician will indicate the services to be provided and will inform you of the relevant fee, if any. The services will be provided in accordance with the scope of the agreement.",
|
||||
"IsStomatology": true,
|
||||
"OptionMessage": "I do not have the required referral",
|
||||
"PaymentMessage": "",
|
||||
"ReferralRequired": false,
|
||||
"ValuationDetail": {
|
||||
"PayerData": {
|
||||
"BrandId": null,
|
||||
"ContractId": 1111111,
|
||||
"PayerId": 22222,
|
||||
"PayerName": "FIRMA POLAND SP. Z O.O.",
|
||||
"ProductElementId": 8547100,
|
||||
"ProductId": 44444,
|
||||
"ProductInContractId": 555555,
|
||||
"ServaAppId": 0,
|
||||
"ServaId": 6621
|
||||
},
|
||||
"Price": 0.0,
|
||||
"ValuationType": 1
|
||||
},
|
||||
"WarningMessage": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
case class ValuationsResponse(optionsQuestion: Option[String], visitTermVariants: List[VisitTermVariant]) extends SerializableJsonObject
|
||||
|
||||
case class VisitTermVariant(canBeReserve: Boolean, infoMessage: String, isStomatology: Boolean, optionMessage: String, paymentMessage: String,
|
||||
referralRequired: Boolean, valuationDetail: ValuationDetail, warningMessage: String) extends SerializableJsonObject
|
||||
|
||||
case class ValuationDetail(payerData: PayerDetails, price: BigDecimal, valuationType: Int) extends SerializableJsonObject
|
||||
@@ -1,77 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
{
|
||||
"AreMoreVisits": false,
|
||||
"HistoricVisits": [
|
||||
{
|
||||
"ClinicName": "LX Wrocław - Szewska 3A",
|
||||
"DoctorName": "lek. stom. TARAS SHEVCZENKO",
|
||||
"HasRecommendations": false,
|
||||
"HasReferrals": false,
|
||||
"IsAdditional": false,
|
||||
"Links": [
|
||||
{
|
||||
"Href": "/PatientPortalMobileAPI/api/visits/recommendations/222222222",
|
||||
"Method": "GET",
|
||||
"Rel": "get_recommendations"
|
||||
}
|
||||
],
|
||||
"QuestionToVisit": {
|
||||
"IsAnswered": false,
|
||||
"IsAsked": false,
|
||||
"IsQuestionToVisitAvailable": false
|
||||
},
|
||||
"RateVisit": {
|
||||
"IsRatingAvailable": false,
|
||||
"IsVisitRated": false
|
||||
},
|
||||
"ReservationId": 222222222,
|
||||
"Service": {
|
||||
"Id": 6621,
|
||||
"Name": "Umówienie wizyty u stomatologa"
|
||||
},
|
||||
"VisitDate": {
|
||||
"FormattedDate": "17th Jan 2018, at 1:00 pm",
|
||||
"StartDateTime": "2018-01-17T13:00:00+02:00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ClinicName": "LX Wrocław - Szewska 3A",
|
||||
"DoctorName": "lek. stom. TARAS SHEVCZENKO",
|
||||
"HasRecommendations": false,
|
||||
"HasReferrals": false,
|
||||
"IsAdditional": false,
|
||||
"Links": [
|
||||
{
|
||||
"Href": "/PatientPortalMobileAPI/api/visits/recommendations/999999999",
|
||||
"Method": "GET",
|
||||
"Rel": "get_recommendations"
|
||||
}
|
||||
],
|
||||
"QuestionToVisit": {
|
||||
"IsAnswered": false,
|
||||
"IsAsked": false,
|
||||
"IsQuestionToVisitAvailable": false
|
||||
},
|
||||
"RateVisit": {
|
||||
"IsRatingAvailable": false,
|
||||
"IsVisitRated": false
|
||||
},
|
||||
"ReservationId": 999999999,
|
||||
"Service": {
|
||||
"Id": 3589,
|
||||
"Name": "Wypełnienie ubytku korony zęba na 2 powierzchniach"
|
||||
},
|
||||
"VisitDate": {
|
||||
"FormattedDate": "17th Jan 2018, at 1:00 pm",
|
||||
"StartDateTime": "2018-01-17T13:00:00+02:00"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
case class VisitsHistoryResponse(areMoreVisits: Boolean, historicVisits: List[HistoricVisit]) extends SerializableJsonObject
|
||||
|
||||
case class HistoricVisit(clinicName: String, doctorName: String, reservationId: Long, service: IdName, visitDate: VisitDate)
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.net.HttpCookie
|
||||
|
||||
case class XsrfToken(token: String, cookies: Seq[HttpCookie])
|
||||
@@ -2,48 +2,11 @@
|
||||
package com.lbs
|
||||
|
||||
import cats.MonadError
|
||||
import cats.implicits._
|
||||
import com.lbs.api.json.model.{AvailableTermsResponse, ReservationFilterResponse, ReservedVisitsResponse, VisitsHistoryResponse}
|
||||
import com.softwaremill.quicklens._
|
||||
|
||||
import scala.language.higherKinds
|
||||
import scala.util.matching.Regex
|
||||
|
||||
package object api {
|
||||
|
||||
type ThrowableMonad[F[_]] = MonadError[F, Throwable]
|
||||
|
||||
object ApiResponseMutators {
|
||||
private val DoctorPrefixes: Regex = """\s*(dr\s*n.\s*med.|dr\s*hab.\s*n.\s*med|lek.\s*med.|lek.\s*stom.)\s*""".r
|
||||
|
||||
private def cleanupDoctorName(name: String) = DoctorPrefixes.replaceFirstIn(name, "")
|
||||
|
||||
trait ResponseMutator[T] {
|
||||
def mutate(response: T): T
|
||||
}
|
||||
|
||||
implicit class ResponseOps[T: ResponseMutator, F[_] : ThrowableMonad](response: F[T]) {
|
||||
def mutate: F[T] = {
|
||||
val mutator = implicitly[ResponseMutator[T]]
|
||||
response.map(mutator.mutate)
|
||||
}
|
||||
}
|
||||
|
||||
implicit val ReservedVisitsResponseMutator: ResponseMutator[ReservedVisitsResponse] = (response: ReservedVisitsResponse) => {
|
||||
response.modify(_.reservedVisits.each.doctorName).using(cleanupDoctorName)
|
||||
}
|
||||
|
||||
implicit val VisitsHistoryResponseMutator: ResponseMutator[VisitsHistoryResponse] = (response: VisitsHistoryResponse) => {
|
||||
response.modify(_.historicVisits.each.doctorName).using(cleanupDoctorName)
|
||||
}
|
||||
|
||||
implicit val ReservationFilterResponseMutator: ResponseMutator[ReservationFilterResponse] = (response: ReservationFilterResponse) => {
|
||||
response.modify(_.doctors.each.name).using(cleanupDoctorName)
|
||||
}
|
||||
|
||||
implicit val AvailableTermsResponseMutator: ResponseMutator[AvailableTermsResponse] = (response: AvailableTermsResponse) => {
|
||||
response.modify(_.availableVisitsTermPresentation.each.doctor.name).using(cleanupDoctorName)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
package com.lbs.api
|
||||
|
||||
import com.lbs.api.json.model.{AvailableTermsResponse, AvailableVisitsTermPresentation, HistoricVisit, IdName, ReservationFilterResponse, ReservedVisit, ReservedVisitsResponse, VisitsHistoryResponse}
|
||||
import org.scalatest.{FunSuiteLike, Matchers}
|
||||
|
||||
class ApiResponseMutatorsSpec extends FunSuiteLike with Matchers {
|
||||
test("ReservationFilterResponseMutator") {
|
||||
val mutated =
|
||||
ApiResponseMutators.ReservationFilterResponseMutator.mutate(
|
||||
ReservationFilterResponse(
|
||||
cities = Nil,
|
||||
clinics = Nil,
|
||||
defaultPayer = None,
|
||||
doctors = List(IdName(1, "AGNIESZKA dr n. med.")),
|
||||
languages = Nil,
|
||||
payers = Nil,
|
||||
services = Nil
|
||||
)
|
||||
)
|
||||
|
||||
assert(mutated.doctors === List(IdName(1, "AGNIESZKA")))
|
||||
}
|
||||
|
||||
test("ReservedVisitsResponseMutator") {
|
||||
val mutated =
|
||||
ApiResponseMutators.ReservedVisitsResponseMutator.mutate(
|
||||
ReservedVisitsResponse(
|
||||
List(
|
||||
ReservedVisit(
|
||||
canBeCanceled = false,
|
||||
clinic = null,
|
||||
doctorName = "AGNIESZKA dr n. med.",
|
||||
reservationId = 1L,
|
||||
service = null,
|
||||
visitDate = null
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
assert(mutated.reservedVisits.head.doctorName === "AGNIESZKA")
|
||||
}
|
||||
|
||||
test("VisitsHistoryResponseMutator") {
|
||||
val mutated =
|
||||
ApiResponseMutators.VisitsHistoryResponseMutator.mutate(
|
||||
VisitsHistoryResponse(
|
||||
areMoreVisits = false,
|
||||
historicVisits = List(
|
||||
HistoricVisit(
|
||||
clinicName = null,
|
||||
doctorName = "AGNIESZKA dr n. med.",
|
||||
reservationId = 1L,
|
||||
service = null,
|
||||
visitDate = null
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
assert(mutated.historicVisits.head.doctorName === "AGNIESZKA")
|
||||
}
|
||||
|
||||
test("AvailableTermsResponseMutator") {
|
||||
val mutated =
|
||||
ApiResponseMutators.AvailableTermsResponseMutator.mutate(
|
||||
AvailableTermsResponse(
|
||||
availableVisitsTermPresentation = List(
|
||||
AvailableVisitsTermPresentation(
|
||||
clinic = null,
|
||||
doctor = IdName(1, "AGNIESZKA dr n. med."),
|
||||
payerDetailsList = Nil,
|
||||
referralRequiredByProduct = false,
|
||||
referralRequiredByService = false,
|
||||
roomId = 1L,
|
||||
scheduleId = 1L,
|
||||
serviceId = 1L,
|
||||
visitDate = null
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
assert(mutated.availableVisitsTermPresentation.head.doctor === IdName(1, "AGNIESZKA"))
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import org.scalatest.Matchers
|
||||
|
||||
trait CommonSpec {
|
||||
_: Matchers =>
|
||||
|
||||
private type SimpleEntity = {val id: Long; val name: String}
|
||||
|
||||
protected def testSimpleEntity(simpleEntity: SimpleEntity, expectedId: Long, expectedName: String): Unit = {
|
||||
simpleEntity.id should be(expectedId)
|
||||
simpleEntity.name should be(expectedName)
|
||||
}
|
||||
|
||||
protected def testSimpleEntities(simpleEntities: List[SimpleEntity], expectedSize: Int, expectedId: Long, expectedName: String): Unit = {
|
||||
simpleEntities.size should be(expectedSize)
|
||||
val simpleEntity = simpleEntities.head
|
||||
testSimpleEntity(simpleEntity, expectedId, expectedName)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import org.scalatest.{FunSuiteLike, Matchers}
|
||||
|
||||
class LoginResponseSpec extends FunSuiteLike with Matchers {
|
||||
test("deserialization") {
|
||||
val json =
|
||||
"""
|
||||
|{
|
||||
| "access_token": "RmC6qccJMJ1uVhqJZ-6sBYdfT_LznEoGuH2di0",
|
||||
| "expires_in": 599,
|
||||
| "refresh_token": "7854cd0b-8545-483e-88d7-d07eda90995d",
|
||||
| "token_type": "bearer"
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val response = json.as[LoginResponse]
|
||||
|
||||
response.accessToken should be("RmC6qccJMJ1uVhqJZ-6sBYdfT_LznEoGuH2di0")
|
||||
response.expiresIn should be(599)
|
||||
response.refreshToken should be("7854cd0b-8545-483e-88d7-d07eda90995d")
|
||||
response.tokenType should be("bearer")
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import org.scalatest.{FunSuiteLike, Matchers}
|
||||
|
||||
class LuxmedErrorsListSpec extends FunSuiteLike with Matchers with CommonSpec {
|
||||
|
||||
test("deserialization") {
|
||||
val json =
|
||||
"""
|
||||
|{"Errors":[{"ErrorCode":16000006,"Message":"You have already booked this service","AdditionalData":{}}]}
|
||||
""".stripMargin
|
||||
|
||||
val response = json.as[LuxmedErrorsList]
|
||||
|
||||
response should be(LuxmedErrorsList(List(LuxmedErrorsListElement(16000006, "You have already booked this service", Map.empty))))
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import org.scalatest.{FunSuiteLike, Matchers}
|
||||
|
||||
class LuxmedErrorsMapSpec extends FunSuiteLike with Matchers with CommonSpec {
|
||||
test("deserialization") {
|
||||
val json =
|
||||
"""
|
||||
|{"Errors":{"ToDate.Date":["'To Date. Date' must be greater than or equal to '06/04/2018 00:00:00'."]}}
|
||||
""".stripMargin
|
||||
|
||||
val response = json.as[LuxmedErrorsMap]
|
||||
|
||||
response should be(LuxmedErrorsMap(Map("toDate.Date" -> List("'To Date. Date' must be greater than or equal to '06/04/2018 00:00:00'."))))
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import org.scalatest.{FunSuiteLike, Matchers}
|
||||
|
||||
class ReservationFilterResponseSpec extends FunSuiteLike with Matchers with CommonSpec {
|
||||
test("deserialization") {
|
||||
val json =
|
||||
"""
|
||||
|{
|
||||
| "Cities": [
|
||||
| {
|
||||
| "Id": 5,
|
||||
| "Name": "Wrocław"
|
||||
| }
|
||||
| ],
|
||||
| "Clinics": [
|
||||
| {
|
||||
| "Id": 1405,
|
||||
| "Name": "Legnicka 40"
|
||||
| },
|
||||
| {
|
||||
| "Id": 7,
|
||||
| "Name": "Kwidzyńska 6"
|
||||
| }
|
||||
| ],
|
||||
| "DefaultPayer": {
|
||||
| "Id": 22222,
|
||||
| "Name": "FIRMA"
|
||||
| },
|
||||
| "Doctors": [
|
||||
| {
|
||||
| "Id": 38275,
|
||||
| "Name": "ANNA ABRAMCZYK"
|
||||
| },
|
||||
| {
|
||||
| "Id": 15565,
|
||||
| "Name": "ANDRZEJ ANDEWSKI"
|
||||
| }
|
||||
| ],
|
||||
| "Languages": [
|
||||
| {
|
||||
| "Id": 11,
|
||||
| "Name": "english"
|
||||
| },
|
||||
| {
|
||||
| "Id": 10,
|
||||
| "Name": "polish"
|
||||
| }
|
||||
| ],
|
||||
| "Payers": [
|
||||
| {
|
||||
| "Id": 22222,
|
||||
| "Name": "FIRMA"
|
||||
| }
|
||||
| ],
|
||||
| "Services": [
|
||||
| {
|
||||
| "Id": 5857,
|
||||
| "Name": "Audiometr standardowy"
|
||||
| },
|
||||
| {
|
||||
| "Id": 7976,
|
||||
| "Name": "Audiometr standardowy - audiometria nadprogowa"
|
||||
| }
|
||||
| ]
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val response = json.as[ReservationFilterResponse]
|
||||
|
||||
testSimpleEntities(response.cities, 1, 5L, "Wrocław")
|
||||
testSimpleEntities(response.clinics, 2, 1405L, "Legnicka 40")
|
||||
response.defaultPayer should be(_: Some[IdName])
|
||||
testSimpleEntity(response.defaultPayer.get, 22222L, "FIRMA")
|
||||
testSimpleEntities(response.doctors, 2, 38275L, "ANNA ABRAMCZYK")
|
||||
testSimpleEntities(response.languages, 2, 11L, "english")
|
||||
testSimpleEntities(response.payers, 1, 22222L, "FIRMA")
|
||||
testSimpleEntities(response.services, 2, 5857L, "Audiometr standardowy")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import org.scalatest.{FunSuiteLike, Matchers}
|
||||
|
||||
class ReservedVisitsResponseSpec extends FunSuiteLike with Matchers with CommonSpec {
|
||||
test("deserialization") {
|
||||
val json =
|
||||
"""
|
||||
|{
|
||||
| "ReservedVisits": [
|
||||
| {
|
||||
| "CanBeCanceled": true,
|
||||
| "Clinic": {
|
||||
| "Id": 6,
|
||||
| "Name": "Szewska 3A"
|
||||
| },
|
||||
| "DoctorName": "TARAS SHEVCZENKO",
|
||||
| "Impediment": {
|
||||
| "ImpedimentText": "",
|
||||
| "IsImpediment": false
|
||||
| },
|
||||
| "IsAdditional": false,
|
||||
| "IsPreparationRequired": false,
|
||||
| "Links": [
|
||||
| {
|
||||
| "Href": "/PatientPortalMobileAPI/api/visits/preparations/6621",
|
||||
| "Method": "GET",
|
||||
| "Rel": "get_preparations"
|
||||
| }
|
||||
| ],
|
||||
| "ReservationId": 888888888,
|
||||
| "Service": {
|
||||
| "Id": 6621,
|
||||
| "Name": "stomatolog"
|
||||
| },
|
||||
| "VisitDate": {
|
||||
| "FormattedDate": "21rd May, Mon. at 3:00 pm",
|
||||
| "StartDateTime": "2018-05-21T15:00:00+02:00"
|
||||
| }
|
||||
| }
|
||||
| ]
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val response = json.as[ReservedVisitsResponse]
|
||||
|
||||
response.reservedVisits.size should be(1)
|
||||
val reservedVisit = response.reservedVisits.head
|
||||
reservedVisit.canBeCanceled should be(true)
|
||||
testSimpleEntity(reservedVisit.clinic, 6L, "Szewska 3A")
|
||||
reservedVisit.doctorName should be("TARAS SHEVCZENKO")
|
||||
reservedVisit.reservationId should be(888888888L)
|
||||
testSimpleEntity(reservedVisit.service, 6621L, "stomatolog")
|
||||
reservedVisit.visitDate.formattedDate should be("21rd May, Mon. at 3:00 pm")
|
||||
reservedVisit.visitDate.startDateTime should be(ZonedDateTime.parse("2018-05-21T15:00:00+02:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME))
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import org.scalatest.{FunSuiteLike, Matchers}
|
||||
|
||||
class TemporaryReservationRequestSpec extends FunSuiteLike with Matchers with CommonSpec {
|
||||
test("serialization") {
|
||||
val json =
|
||||
"""
|
||||
|{
|
||||
| "ClinicId": 6,
|
||||
| "DoctorId": 38275,
|
||||
| "PayerDetailsList": [
|
||||
| {
|
||||
| "BrandId": 2,
|
||||
| "ContractId": 1111111,
|
||||
| "PayerId": 22222,
|
||||
| "PayerName": "FIRMA",
|
||||
| "ProductElementId": 3333333,
|
||||
| "ProductId": 44444,
|
||||
| "ProductInContractId": 555555,
|
||||
| "ServaAppId": 0,
|
||||
| "ServaId": 6666
|
||||
| }
|
||||
| ],
|
||||
| "ReferralRequiredByService": false,
|
||||
| "RoomId": 543,
|
||||
| "ServiceId": 6666,
|
||||
| "StartDateTime": "2018-02-23T11:30:00+02:00"
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val request = TemporaryReservationRequest(clinicId = 6L, doctorId = 38275L, payerDetailsList = List(
|
||||
PayerDetails(brandId = Some(2L), contractId = 1111111L, payerId = 22222L, payerName = "FIRMA",
|
||||
productElementId = Some(3333333L), productId = 44444L, productInContractId = 555555L, servaAppId = 0L, servaId = 6666L)
|
||||
), referralRequiredByService = false, roomId = 543L, serviceId = 6666L,
|
||||
startDateTime = ZonedDateTime.parse("2018-02-23T11:30:00+02:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME))
|
||||
|
||||
val requestJson = request.asJson
|
||||
val requestActual = requestJson.as[TemporaryReservationRequest]
|
||||
val requestExpected = json.as[TemporaryReservationRequest]
|
||||
|
||||
requestActual should be(requestExpected)
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import org.scalatest.{FunSuiteLike, Matchers}
|
||||
|
||||
class ValuationsRequestSpec extends FunSuiteLike with Matchers with CommonSpec {
|
||||
test("serialization") {
|
||||
val json =
|
||||
"""
|
||||
|{
|
||||
| "ClinicId": 6,
|
||||
| "DoctorId": 38275,
|
||||
| "PayerDetailsList": [
|
||||
| {
|
||||
| "BrandId": 2,
|
||||
| "ContractId": 1111111,
|
||||
| "PayerId": 22222,
|
||||
| "PayerName": "FIRMA",
|
||||
| "ProductElementId": 3333333,
|
||||
| "ProductId": 44444,
|
||||
| "ProductInContractId": 555555,
|
||||
| "ServaAppId": 0,
|
||||
| "ServaId": 6666
|
||||
| }
|
||||
| ],
|
||||
| "ReferralRequiredByService": false,
|
||||
| "RoomId": 543,
|
||||
| "ServiceId": 6666,
|
||||
| "StartDateTime": "2018-02-23T11:30:00+02:00"
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val request = ValuationsRequest(clinicId = 6L, doctorId = 38275L, payerDetailsList = List(
|
||||
PayerDetails(brandId = Some(2L), contractId = 1111111L, payerId = 22222L, payerName = "FIRMA",
|
||||
productElementId = Some(3333333L), productId = 44444L, productInContractId = 555555L, servaAppId = 0L, servaId = 6666L)
|
||||
), referralRequiredByService = false, roomId = 543L, serviceId = 6666L,
|
||||
startDateTime = ZonedDateTime.parse("2018-02-23T11:30:00+02:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME))
|
||||
|
||||
val requestJson = request.asJson
|
||||
val requestActual = requestJson.as[ValuationsRequest]
|
||||
val requestExpected = json.as[ValuationsRequest]
|
||||
|
||||
requestActual should be(requestExpected)
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import org.scalatest.{FunSuiteLike, Matchers}
|
||||
|
||||
class ValuationsResponseSpec extends FunSuiteLike with Matchers with CommonSpec {
|
||||
test("deserialization") {
|
||||
val json =
|
||||
"""
|
||||
|{
|
||||
| "VisitTermVariants": [
|
||||
| {
|
||||
| "ValuationDetail": {
|
||||
| "PayerData": {
|
||||
| "PayerId": 12345,
|
||||
| "PayerName": "ZBIGNEW",
|
||||
| "ContractId": 123456,
|
||||
| "ProductInContractId": 234567,
|
||||
| "ProductId": 34567,
|
||||
| "BrandId": null,
|
||||
| "ProductElementId": 2536352,
|
||||
| "ServaId": 12345,
|
||||
| "ServaAppId": 0
|
||||
| },
|
||||
| "ValuationType": 1,
|
||||
| "Price": 0.000000
|
||||
| },
|
||||
| "InfoMessage": "Package-covered service",
|
||||
| "PaymentMessage": "Price with a valid referral: 0.00 zł \r\nPrice without a valid referral: 10.30 zł",
|
||||
| "OptionMessage": "Yes, from a LUX MED Group or a subcontractor facility physician",
|
||||
| "WarningMessage": "In accordance with your medical package terms and conditions, you must have a valid referral from a LUX MED Group or a subcontractor facility physician",
|
||||
| "CanBeReserve": true,
|
||||
| "ReferralRequired": true,
|
||||
| "IsStomatology": false
|
||||
| },
|
||||
| {
|
||||
| "ValuationDetail": {
|
||||
| "PayerData": {
|
||||
| "PayerId": 123456,
|
||||
| "PayerName": "ZBIGNEW",
|
||||
| "ContractId": 12345,
|
||||
| "ProductInContractId": 345678,
|
||||
| "ProductId": 23467,
|
||||
| "BrandId": null,
|
||||
| "ProductElementId": null,
|
||||
| "ServaId": 1234,
|
||||
| "ServaAppId": 0
|
||||
| },
|
||||
| "ValuationType": 4,
|
||||
| "Price": 10.30
|
||||
| },
|
||||
| "InfoMessage": "Out-of-package service",
|
||||
| "PaymentMessage": "Price: 10.30 zł",
|
||||
| "OptionMessage": "I do not have the required referral",
|
||||
| "WarningMessage": "",
|
||||
| "CanBeReserve": true,
|
||||
| "ReferralRequired": false,
|
||||
| "IsStomatology": false
|
||||
| }
|
||||
| ],
|
||||
| "OptionsQuestion": "Do you have a valid referral for this service?",
|
||||
| "IsReferralRequired": false
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val responseActual = json.as[ValuationsResponse]
|
||||
|
||||
val responseExpected = ValuationsResponse(
|
||||
Some("Do you have a valid referral for this service?"),
|
||||
List(
|
||||
VisitTermVariant(
|
||||
canBeReserve = true,
|
||||
"Package-covered service",
|
||||
isStomatology = false,
|
||||
"Yes, from a LUX MED Group or a subcontractor facility physician", "Price with a valid referral: 0.00 zł \r\nPrice without a valid referral: 10.30 zł",
|
||||
referralRequired = true,
|
||||
ValuationDetail(PayerDetails(None, 123456, 12345, "ZBIGNEW", Some(2536352), 34567, 234567, 0, 12345), 0.0, 1),
|
||||
"In accordance with your medical package terms and conditions, you must have a valid referral from a LUX MED Group or a subcontractor facility physician"
|
||||
),
|
||||
VisitTermVariant(
|
||||
canBeReserve = true,
|
||||
"Out-of-package service",
|
||||
isStomatology = false,
|
||||
"I do not have the required referral",
|
||||
"Price: 10.30 zł",
|
||||
referralRequired = false,
|
||||
ValuationDetail(PayerDetails(None, 12345, 123456, "ZBIGNEW", None, 23467, 345678, 0, 1234), 10.3, 4),
|
||||
"")
|
||||
)
|
||||
)
|
||||
|
||||
responseActual should be(responseExpected)
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import org.scalatest.{FunSuiteLike, Matchers}
|
||||
|
||||
class VisitsHistoryResponseSpec extends FunSuiteLike with Matchers with CommonSpec {
|
||||
test("deserialization") {
|
||||
val json =
|
||||
"""
|
||||
|{
|
||||
| "AreMoreVisits": false,
|
||||
| "HistoricVisits": [
|
||||
| {
|
||||
| "ClinicName": "Szewska 3A",
|
||||
| "DoctorName": "TARAS SHEVCZENKO",
|
||||
| "HasRecommendations": false,
|
||||
| "HasReferrals": false,
|
||||
| "IsAdditional": false,
|
||||
| "Links": [
|
||||
| {
|
||||
| "Href": "/PatientPortalMobileAPI/api/visits/recommendations/222222222",
|
||||
| "Method": "GET",
|
||||
| "Rel": "get_recommendations"
|
||||
| }
|
||||
| ],
|
||||
| "QuestionToVisit": {
|
||||
| "IsAnswered": false,
|
||||
| "IsAsked": false,
|
||||
| "IsQuestionToVisitAvailable": false
|
||||
| },
|
||||
| "RateVisit": {
|
||||
| "IsRatingAvailable": false,
|
||||
| "IsVisitRated": false
|
||||
| },
|
||||
| "ReservationId": 222222222,
|
||||
| "Service": {
|
||||
| "Id": 6621,
|
||||
| "Name": "stomatolog"
|
||||
| },
|
||||
| "VisitDate": {
|
||||
| "FormattedDate": "17th Jan 2018, at 1:00 pm",
|
||||
| "StartDateTime": "2018-01-17T13:00:00+02:00"
|
||||
| }
|
||||
| },
|
||||
| {
|
||||
| "ClinicName": "LX Wrocław - Szewska 3A",
|
||||
| "DoctorName": "lek. stom. TARAS SHEVCZENKO",
|
||||
| "HasRecommendations": false,
|
||||
| "HasReferrals": false,
|
||||
| "IsAdditional": false,
|
||||
| "Links": [
|
||||
| {
|
||||
| "Href": "/PatientPortalMobileAPI/api/visits/recommendations/999999999",
|
||||
| "Method": "GET",
|
||||
| "Rel": "get_recommendations"
|
||||
| }
|
||||
| ],
|
||||
| "QuestionToVisit": {
|
||||
| "IsAnswered": false,
|
||||
| "IsAsked": false,
|
||||
| "IsQuestionToVisitAvailable": false
|
||||
| },
|
||||
| "RateVisit": {
|
||||
| "IsRatingAvailable": false,
|
||||
| "IsVisitRated": false
|
||||
| },
|
||||
| "ReservationId": 999999999,
|
||||
| "Service": {
|
||||
| "Id": 3589,
|
||||
| "Name": "Wypełnienie ubytku korony zęba na 2 powierzchniach"
|
||||
| },
|
||||
| "VisitDate": {
|
||||
| "FormattedDate": "17th Jan 2018, at 1:00 pm",
|
||||
| "StartDateTime": "2018-01-17T13:00:00+02:00"
|
||||
| }
|
||||
| }
|
||||
| ]
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val response = json.as[VisitsHistoryResponse]
|
||||
|
||||
response.areMoreVisits should be(false)
|
||||
response.historicVisits.size should be(2)
|
||||
val historicVisit = response.historicVisits.head
|
||||
historicVisit.clinicName should be("Szewska 3A")
|
||||
historicVisit.doctorName should be("TARAS SHEVCZENKO")
|
||||
historicVisit.reservationId should be(222222222L)
|
||||
testSimpleEntity(historicVisit.service, 6621L, "stomatolog")
|
||||
historicVisit.visitDate.formattedDate should be("17th Jan 2018, at 1:00 pm")
|
||||
historicVisit.visitDate.startDateTime should be(ZonedDateTime.parse("2018-01-17T13:00:00+02:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME))
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
dependencies {
|
||||
compile project(':common')
|
||||
|
||||
compile group: "com.bot4s", name: "telegram-core_2.12", version: "5.1.0"
|
||||
compile group: "com.bot4s", name: "telegram-akka_2.12", version: "4.0.0-RC2"
|
||||
compile group: "com.bot4s", name: "telegram-core_2.12", version: "5.6.0"
|
||||
compile group: "com.bot4s", name: "telegram-akka_2.12", version: "5.6.0"
|
||||
}
|
||||
@@ -2,22 +2,19 @@
|
||||
package com.lbs.bot.telegram
|
||||
|
||||
import cats.implicits.toFunctorOps
|
||||
import com.bot4s.telegram.api.RequestHandler
|
||||
import com.bot4s.telegram.api.declarative.{Callbacks, Commands}
|
||||
import com.bot4s.telegram.clients.FutureSttpClient
|
||||
import com.bot4s.telegram.api.{AkkaTelegramBot, RequestHandler}
|
||||
import com.bot4s.telegram.clients.AkkaHttpClient
|
||||
import com.bot4s.telegram.future.{Polling, TelegramBot => TelegramBoT}
|
||||
import com.bot4s.telegram.methods._
|
||||
import com.bot4s.telegram.models.{InlineKeyboardMarkup, InputFile, Message}
|
||||
import com.lbs.common.Logger
|
||||
import sttp.client3.SttpBackend
|
||||
import sttp.client3.okhttp.OkHttpFutureBackend
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) extends TelegramBoT with Polling with Commands[Future] with Callbacks[Future] with Logger {
|
||||
class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) extends AkkaTelegramBot with TelegramBoT with Polling with Commands[Future] with Callbacks[Future] with Logger {
|
||||
|
||||
private implicit val backend: SttpBackend[Future, Any] = OkHttpFutureBackend()
|
||||
override val client: RequestHandler[Future] = new FutureSttpClient(botToken)
|
||||
override val client: RequestHandler[Future] = new AkkaHttpClient(botToken)
|
||||
|
||||
def sendMessage(chatId: Long, text: String): Future[Message] =
|
||||
loggingRequest(SendMessage(chatId, text, parseMode = Some(ParseMode.HTML)))
|
||||
@@ -32,7 +29,7 @@ class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) extends
|
||||
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))
|
||||
loggingRequest(SendDocument(chatId, InputFile(filename, contents), caption = caption))
|
||||
|
||||
private def loggingRequest[R: Manifest](req: Request[R]): Future[R] = {
|
||||
debug(s"Sending telegram request: $req")
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.lbs.common
|
||||
|
||||
import java.util.Optional
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
object Implicits {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.lbs.common
|
||||
|
||||
import java.util.concurrent.{Executors, ScheduledFuture}
|
||||
|
||||
import scala.concurrent.duration.FiniteDuration
|
||||
|
||||
class Scheduler(poolSize: Int) extends Logger {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package com.lbs.server
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.api.json.model.{AvailableVisitsTermPresentation, HistoricVisit, ReservedVisit}
|
||||
import com.lbs.api.json.model.{Event, TermExt}
|
||||
import com.lbs.bot.Bot
|
||||
import com.lbs.bot.telegram.TelegramBot
|
||||
import com.lbs.server.conversation._
|
||||
@@ -74,12 +74,12 @@ class BootConfig {
|
||||
userId => new MonitoringsHistory(userId, bot, monitoringService, localization, monitoringsHistoryPagerFactory, bookWithTemplateFactory)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def historyFactory: UserIdTo[History] =
|
||||
userId => new History(userId, bot, apiService, localization, historyPagerFactory)(actorSystem)
|
||||
def historyFactory: UserIdTo[HistoryViewer] =
|
||||
userId => new HistoryViewer(userId, bot, apiService, localization, historyPagerFactory)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def visitsFactory: UserIdTo[Visits] =
|
||||
userId => new Visits(userId, bot, apiService, localization, visitsPagerFactory)(actorSystem)
|
||||
def reservedVisitsFactory: UserIdTo[ReservedVisitsViewer] =
|
||||
userId => new ReservedVisitsViewer(userId, bot, apiService, localization, reservedVisitsPagerFactory)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def settingsFactory: UserIdTo[Settings] =
|
||||
@@ -92,7 +92,7 @@ class BootConfig {
|
||||
@Bean
|
||||
def chatFactory: UserIdTo[Chat] =
|
||||
userId => new Chat(userId, dataService, monitoringService, bookFactory, helpFactory,
|
||||
monitoringsFactory, monitoringsHistoryFactory, historyFactory, visitsFactory, settingsFactory, accountFactory)(actorSystem)
|
||||
monitoringsFactory, monitoringsHistoryFactory, historyFactory, reservedVisitsFactory, settingsFactory, accountFactory)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def datePickerFactory: UserIdWithOriginatorTo[DatePicker] = (userId, originator) =>
|
||||
@@ -107,24 +107,24 @@ class BootConfig {
|
||||
new StaticData(userId, bot, localization, originator)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def termsPagerFactory: UserIdWithOriginatorTo[Pager[AvailableVisitsTermPresentation]] = (userId, originator) =>
|
||||
new Pager[AvailableVisitsTermPresentation](userId, bot,
|
||||
(term: AvailableVisitsTermPresentation, page: Int, index: Int) => lang(userId).termEntry(term, page, index),
|
||||
def termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]] = (userId, originator) =>
|
||||
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)
|
||||
|
||||
|
||||
@Bean
|
||||
def visitsPagerFactory: UserIdWithOriginatorTo[Pager[ReservedVisit]] = (userId, originator) =>
|
||||
new Pager[ReservedVisit](userId, bot,
|
||||
(visit: ReservedVisit, page: Int, index: Int) => lang(userId).upcomingVisitEntry(visit, page, index),
|
||||
(page: Int, pages: Int) => lang(userId).upcomingVisitsHeader(page, pages),
|
||||
def reservedVisitsPagerFactory: UserIdWithOriginatorTo[Pager[Event]] = (userId, originator) =>
|
||||
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)
|
||||
|
||||
@Bean
|
||||
def historyPagerFactory: UserIdWithOriginatorTo[Pager[HistoricVisit]] = (userId, originator) =>
|
||||
new Pager[HistoricVisit](userId, bot,
|
||||
(visit: HistoricVisit, page: Int, index: Int) => lang(userId).historyEntry(visit, page, index),
|
||||
def historyPagerFactory: UserIdWithOriginatorTo[Pager[Event]] = (userId, originator) =>
|
||||
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)
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import java.time.{LocalTime, ZonedDateTime}
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.api.json.model._
|
||||
import com.lbs.bot._
|
||||
@@ -20,9 +18,11 @@ import com.lbs.server.service.{ApiService, DataService, MonitoringService}
|
||||
import com.lbs.server.util.MessageExtractors._
|
||||
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[AvailableVisitsTermPresentation]])(implicit val actorSystem: ActorSystem) extends Conversation[BookingData] with StaticDataForBooking with Localizable {
|
||||
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)
|
||||
@@ -33,66 +33,37 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
private def askCity: Step =
|
||||
staticData(cityConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
withFunctions[DictionaryCity](
|
||||
latestOptions = dataService.getLatestCities(userId.accountId),
|
||||
staticOptions = apiService.getAllCities(userId.accountId),
|
||||
applyId = id => bd.copy(cityId = id))
|
||||
}(requestNext = askClinic)
|
||||
|
||||
private def askClinic: Step =
|
||||
staticData(clinicConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestClinicsByCityId(userId.accountId, bd.cityId.id),
|
||||
staticOptions = apiService.getAllClinics(userId.accountId, bd.cityId.id),
|
||||
applyId = id => bd.copy(clinicId = id))
|
||||
applyId = id => bd.copy(cityId = id.toIdName))
|
||||
}(requestNext = askService)
|
||||
|
||||
private def askService: Step =
|
||||
staticData(serviceConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestServicesByCityIdAndClinicId(userId.accountId, bd.cityId.id, bd.clinicId.optionalId),
|
||||
staticOptions = apiService.getAllServices(userId.accountId, bd.cityId.id, bd.clinicId.optionalId),
|
||||
applyId = id => bd.copy(serviceId = id))
|
||||
withFunctions[DictionaryServiceVariants](
|
||||
latestOptions = dataService.getLatestServicesByCityIdAndClinicId(userId.accountId, bd.cityId.id, None),
|
||||
staticOptions = apiService.getAllServices(userId.accountId),
|
||||
applyId = id => bd.copy(serviceId = id.toIdName))
|
||||
}(requestNext = askClinic)
|
||||
|
||||
private def askClinic: Step =
|
||||
staticData(clinicConfig) { bd: BookingData =>
|
||||
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))
|
||||
}(requestNext = askDoctor)
|
||||
|
||||
private def askDoctor: Step =
|
||||
staticData(doctorConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
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.clinicId.optionalId, bd.serviceId.id),
|
||||
applyId = id => bd.copy(doctorId = id))
|
||||
}(requestNext = determinePayer)
|
||||
|
||||
private def determinePayer: Step =
|
||||
process { bookingData =>
|
||||
val response = apiService.getPayers(userId.accountId, bookingData.cityId.id, bookingData.clinicId.optionalId, bookingData.serviceId.id)
|
||||
response match {
|
||||
case Left(ex) =>
|
||||
warn(s"Can't determine payers for account ${userId.accountId}, city ${bookingData.cityId.id}, " +
|
||||
s"clinic ${bookingData.clinicId.optionalId} and service ${bookingData.serviceId.id}", ex)
|
||||
bot.sendMessage(userId.source, lang.canNotDetectPayer(ex.getMessage))
|
||||
end()
|
||||
case Right((defaultPayerMaybe, payers)) =>
|
||||
defaultPayerMaybe match {
|
||||
case Some(defaultPayer) =>
|
||||
goto(requestDateFrom) using bookingData.copy(payerId = defaultPayer.id)
|
||||
case None =>
|
||||
goto(askPayer) using bookingData.copy(payers = payers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def askPayer: Step =
|
||||
ask { bookingData =>
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.pleaseChoosePayer,
|
||||
inlineKeyboard = createInlineKeyboard(bookingData.payers.map(payer => Button(payer.name, payer.id)))
|
||||
)
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(LongString(payerId)), bookingData) =>
|
||||
goto(requestDateFrom) using bookingData.copy(payerId = payerId)
|
||||
}
|
||||
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 =
|
||||
ask { bookingData =>
|
||||
@@ -103,7 +74,7 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
case Msg(cmd: Command, _) =>
|
||||
datePicker ! cmd
|
||||
stay()
|
||||
case Msg(date: ZonedDateTime, bookingData: BookingData) =>
|
||||
case Msg(date: LocalDateTime, bookingData: BookingData) =>
|
||||
goto(requestDateTo) using bookingData.copy(dateFrom = date)
|
||||
}
|
||||
|
||||
@@ -116,7 +87,7 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
case Msg(cmd: Command, _) =>
|
||||
datePicker ! cmd
|
||||
stay()
|
||||
case Msg(date: ZonedDateTime, bookingData: BookingData) =>
|
||||
case Msg(date: LocalDateTime, bookingData: BookingData) =>
|
||||
goto(requestTimeFrom) using bookingData.copy(dateTo = date)
|
||||
}
|
||||
|
||||
@@ -158,33 +129,42 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
case Msg(CallbackCommand(Tags.FindTerms), _) =>
|
||||
goto(requestTerm)
|
||||
case Msg(CallbackCommand(Tags.ModifyDate), bookingData) =>
|
||||
goto(requestDateFrom) using bookingData.copy(dateFrom = ZonedDateTime.now(),
|
||||
dateTo = ZonedDateTime.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.payerId, bookingData.cityId.id,
|
||||
val availableTerms = apiService.getAvailableTerms(userId.accountId, bookingData.cityId.id,
|
||||
bookingData.clinicId.optionalId, bookingData.serviceId.id, bookingData.doctorId.optionalId,
|
||||
bookingData.dateFrom, Some(bookingData.dateTo), timeFrom = bookingData.timeFrom, timeTo = bookingData.timeTo)
|
||||
bookingData.dateFrom, bookingData.dateTo, timeFrom = bookingData.timeFrom, timeTo = bookingData.timeTo)
|
||||
termsPager.restart()
|
||||
termsPager ! availableTerms.map(new SimpleItemsProvider(_))
|
||||
} onReply {
|
||||
case Msg(cmd: Command, _) =>
|
||||
termsPager ! cmd
|
||||
stay()
|
||||
case Msg(term: AvailableVisitsTermPresentation, bookingData) =>
|
||||
val response = apiService.temporaryReservation(userId.accountId, term.mapTo[TemporaryReservationRequest], term.mapTo[ValuationsRequest])
|
||||
case Msg(term: TermExt, bookingData) =>
|
||||
val response = for {
|
||||
xsrfToken <- apiService.getXsrfToken(userId.accountId)
|
||||
lockTermResponse <- apiService.reservationLockterm(userId.accountId, xsrfToken, term.mapTo[ReservationLocktermRequest])
|
||||
} yield (lockTermResponse, xsrfToken)
|
||||
response match {
|
||||
case Left(ex) =>
|
||||
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))))
|
||||
goto(awaitRebookDecision) using bookingData.copy(term = Some(term))
|
||||
case Right((temporaryReservation, valuations)) =>
|
||||
bot.sendMessage(userId.source, lang.confirmAppointment(term, valuations),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book))))
|
||||
goto(awaitReservation) using bookingData.copy(term = Some(term), temporaryReservationId = Some(temporaryReservation.id), valuations = Some(valuations))
|
||||
error("Can not lock term", ex)
|
||||
bot.sendMessage(userId.source, ex.getMessage)
|
||||
end()
|
||||
case Right((reservationLocktermResponse, xsrfToken)) =>
|
||||
if (reservationLocktermResponse.value.changeTermAvailable) {
|
||||
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))
|
||||
} 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))
|
||||
}
|
||||
}
|
||||
case Msg(Pager.NoItemsFound, _) =>
|
||||
goto(askNoTermsAction)
|
||||
@@ -196,8 +176,8 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
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 = ZonedDateTime.now(),
|
||||
dateTo = ZonedDateTime.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 {
|
||||
@@ -212,7 +192,8 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
private def awaitRebookDecision: Step =
|
||||
monologue {
|
||||
case Msg(CallbackCommand(Tags.Yes), bookingData: BookingData) =>
|
||||
apiService.updateReservedVisit(userId.accountId, bookingData.term.get) match {
|
||||
apiService.reservationChangeTerm(userId.accountId, bookingData.xsrfToken.get,
|
||||
(bookingData.reservationLocktermResponse.get, bookingData.term.get).mapTo[ReservationChangetermRequest]) match {
|
||||
case Right(success) =>
|
||||
debug(s"Successfully confirmed: $success")
|
||||
bot.sendMessage(userId.source, lang.appointmentIsConfirmed)
|
||||
@@ -229,7 +210,7 @@ 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.temporaryReservationId.get)
|
||||
apiService.deleteTemporaryReservation(userId.accountId, bookingData.xsrfToken.get, bookingData.reservationLocktermResponse.get.value.temporaryReservationId)
|
||||
stay()
|
||||
case Msg(CallbackCommand(Tags.Book), bookingData: BookingData) =>
|
||||
makeReservation(bookingData)
|
||||
@@ -238,15 +219,13 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
private def makeReservation(bookingData: BookingData): Unit = {
|
||||
val reservationRequestMaybe = for {
|
||||
tmpReservationId <- bookingData.temporaryReservationId
|
||||
valuations <- bookingData.valuations
|
||||
visitTermVariant <- valuations.visitTermVariants.headOption
|
||||
reservationLocktermResponse <- bookingData.reservationLocktermResponse
|
||||
term <- bookingData.term
|
||||
} yield (tmpReservationId, visitTermVariant, term).mapTo[ReservationRequest]
|
||||
} yield (reservationLocktermResponse, term).mapTo[ReservationConfirmRequest]
|
||||
|
||||
reservationRequestMaybe match {
|
||||
case Some(reservationRequest) =>
|
||||
apiService.reservation(userId.accountId, reservationRequest) match {
|
||||
apiService.reservationConfirm(userId.accountId, bookingData.xsrfToken.get, reservationRequest) match {
|
||||
case Left(ex) =>
|
||||
error("Error during reservation", ex)
|
||||
bot.sendMessage(userId.source, ex.getMessage)
|
||||
@@ -322,11 +301,11 @@ 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: ZonedDateTime = ZonedDateTime.now(),
|
||||
dateTo: ZonedDateTime = ZonedDateTime.now().plusDays(1L), timeFrom: LocalTime = LocalTime.of(7, 0),
|
||||
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[AvailableVisitsTermPresentation] = None, temporaryReservationId: Option[Long] = None,
|
||||
valuations: Option[ValuationsResponse] = None, offset: Int = 0, payerId: Long = 0, payers: Seq[IdName] = Seq())
|
||||
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"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import java.time.{LocalTime, ZonedDateTime}
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.api.json.model._
|
||||
import com.lbs.bot._
|
||||
@@ -19,9 +17,11 @@ import com.lbs.server.service.{ApiService, DataService, MonitoringService}
|
||||
import com.lbs.server.util.MessageExtractors._
|
||||
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[AvailableVisitsTermPresentation]])(implicit val actorSystem: ActorSystem) extends Conversation[BookingData] with Localizable {
|
||||
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)
|
||||
@@ -37,42 +37,11 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
clinicId = IdName.from(monitoring.clinicId, monitoring.clinicName),
|
||||
serviceId = IdName.from(monitoring.serviceId, monitoring.serviceName),
|
||||
doctorId = IdName.from(monitoring.doctorId, monitoring.doctorName),
|
||||
dateFrom = monitoring.dateFrom,
|
||||
dateTo = monitoring.dateTo,
|
||||
dateFrom = monitoring.dateFrom.toLocalDateTime,
|
||||
dateTo = monitoring.dateTo.toLocalDateTime,
|
||||
timeFrom = monitoring.timeFrom,
|
||||
timeTo = monitoring.timeTo)
|
||||
goto(determinePayer) using bookingData
|
||||
}
|
||||
|
||||
private def determinePayer: Step =
|
||||
process { bookingData =>
|
||||
val response = apiService.getPayers(userId.accountId, bookingData.cityId.id, bookingData.clinicId.optionalId, bookingData.serviceId.id)
|
||||
response match {
|
||||
case Left(ex) =>
|
||||
warn(s"Can't determine payers for account ${userId.accountId}, city ${bookingData.cityId.id}, " +
|
||||
s"clinic ${bookingData.clinicId.optionalId} and service ${bookingData.serviceId.id}", ex)
|
||||
bot.sendMessage(userId.source, lang.canNotDetectPayer(ex.getMessage))
|
||||
end()
|
||||
case Right((defaultPayerMaybe, payers)) =>
|
||||
defaultPayerMaybe match {
|
||||
case Some(defaultPayer) =>
|
||||
goto(requestDateFrom) using bookingData.copy(payerId = defaultPayer.id)
|
||||
case None =>
|
||||
goto(askPayer) using bookingData.copy(payers = payers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def askPayer: Step =
|
||||
ask { bookingData =>
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.pleaseChoosePayer,
|
||||
inlineKeyboard = createInlineKeyboard(bookingData.payers.map(payer => Button(payer.name, payer.id)))
|
||||
)
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(LongString(payerId)), bookingData) =>
|
||||
goto(requestDateFrom) using bookingData.copy(payerId = payerId)
|
||||
goto(requestDateFrom) using bookingData
|
||||
}
|
||||
|
||||
private def requestDateFrom: Step =
|
||||
@@ -84,7 +53,7 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
case Msg(cmd: Command, _) =>
|
||||
datePicker ! cmd
|
||||
stay()
|
||||
case Msg(date: ZonedDateTime, bookingData: BookingData) =>
|
||||
case Msg(date: LocalDateTime, bookingData: BookingData) =>
|
||||
goto(requestDateTo) using bookingData.copy(dateFrom = date)
|
||||
}
|
||||
|
||||
@@ -97,7 +66,7 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
case Msg(cmd: Command, _) =>
|
||||
datePicker ! cmd
|
||||
stay()
|
||||
case Msg(date: ZonedDateTime, bookingData: BookingData) =>
|
||||
case Msg(date: LocalDateTime, bookingData: BookingData) =>
|
||||
goto(requestTimeFrom) using bookingData.copy(dateTo = date)
|
||||
}
|
||||
|
||||
@@ -139,33 +108,36 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
case Msg(CallbackCommand(Tags.FindTerms), _) =>
|
||||
goto(requestTerm)
|
||||
case Msg(CallbackCommand(Tags.ModifyDate), bookingData) =>
|
||||
goto(requestDateFrom) using bookingData.copy(dateFrom = ZonedDateTime.now(),
|
||||
dateTo = ZonedDateTime.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.payerId, bookingData.cityId.id,
|
||||
val availableTerms = apiService.getAvailableTerms(userId.accountId, bookingData.cityId.id,
|
||||
bookingData.clinicId.optionalId, bookingData.serviceId.id, bookingData.doctorId.optionalId,
|
||||
bookingData.dateFrom, Some(bookingData.dateTo), timeFrom = bookingData.timeFrom, timeTo = bookingData.timeTo)
|
||||
bookingData.dateFrom, bookingData.dateTo, timeFrom = bookingData.timeFrom, timeTo = bookingData.timeTo)
|
||||
termsPager.restart()
|
||||
termsPager ! availableTerms.map(new SimpleItemsProvider(_))
|
||||
} onReply {
|
||||
case Msg(cmd: Command, _) =>
|
||||
termsPager ! cmd
|
||||
stay()
|
||||
case Msg(term: AvailableVisitsTermPresentation, bookingData) =>
|
||||
val response = apiService.temporaryReservation(userId.accountId, term.mapTo[TemporaryReservationRequest], term.mapTo[ValuationsRequest])
|
||||
case Msg(term: TermExt, bookingData) =>
|
||||
val response = for {
|
||||
xsrfToken <- apiService.getXsrfToken(userId.accountId)
|
||||
lockTermResponse <- apiService.reservationLockterm(userId.accountId, xsrfToken, term.mapTo[ReservationLocktermRequest])
|
||||
} yield (lockTermResponse, xsrfToken)
|
||||
response match {
|
||||
case Left(ex) =>
|
||||
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))))
|
||||
goto(awaitRebookDecision) using bookingData.copy(term = Some(term))
|
||||
case Right((temporaryReservation, valuations)) =>
|
||||
bot.sendMessage(userId.source, lang.confirmAppointment(term, valuations),
|
||||
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), temporaryReservationId = Some(temporaryReservation.id), valuations = Some(valuations))
|
||||
goto(awaitReservation) using bookingData.copy(term = Some(term), xsrfToken = Some(xsrfToken), reservationLocktermResponse = Some(reservationLocktermResponse))
|
||||
}
|
||||
case Msg(Pager.NoItemsFound, _) =>
|
||||
goto(askNoTermsAction)
|
||||
@@ -177,8 +149,8 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
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 = ZonedDateTime.now(),
|
||||
dateTo = ZonedDateTime.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 {
|
||||
@@ -193,7 +165,7 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
private def awaitRebookDecision: Step =
|
||||
monologue {
|
||||
case Msg(CallbackCommand(Tags.Yes), bookingData: BookingData) =>
|
||||
apiService.updateReservedVisit(userId.accountId, bookingData.term.get) match {
|
||||
apiService.reservationChangeTerm(userId.accountId, bookingData.xsrfToken.get, (bookingData.reservationLocktermResponse.get, bookingData.term.get).mapTo[ReservationChangetermRequest]) match {
|
||||
case Right(success) =>
|
||||
debug(s"Successfully confirmed: $success")
|
||||
bot.sendMessage(userId.source, lang.appointmentIsConfirmed)
|
||||
@@ -210,7 +182,7 @@ 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.temporaryReservationId.get)
|
||||
apiService.deleteTemporaryReservation(userId.accountId, bookingData.xsrfToken.get, bookingData.reservationLocktermResponse.get.value.temporaryReservationId)
|
||||
stay()
|
||||
case Msg(CallbackCommand(Tags.Book), bookingData: BookingData) =>
|
||||
makeReservation(bookingData)
|
||||
@@ -219,15 +191,13 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
|
||||
private def makeReservation(bookingData: BookingData): Unit = {
|
||||
val reservationRequestMaybe = for {
|
||||
tmpReservationId <- bookingData.temporaryReservationId
|
||||
valuations <- bookingData.valuations
|
||||
visitTermVariant <- valuations.visitTermVariants.headOption
|
||||
reservationLocktermResponse <- bookingData.reservationLocktermResponse
|
||||
term <- bookingData.term
|
||||
} yield (tmpReservationId, visitTermVariant, term).mapTo[ReservationRequest]
|
||||
} yield (reservationLocktermResponse, term).mapTo[ReservationConfirmRequest]
|
||||
|
||||
reservationRequestMaybe match {
|
||||
case Some(reservationRequest) =>
|
||||
apiService.reservation(userId.accountId, reservationRequest) match {
|
||||
apiService.reservationConfirm(userId.accountId, bookingData.xsrfToken.get, reservationRequest) match {
|
||||
case Left(ex) =>
|
||||
error("Error during reservation", ex)
|
||||
bot.sendMessage(userId.source, ex.getMessage)
|
||||
|
||||
@@ -13,8 +13,8 @@ import com.lbs.server.util.MessageExtractors._
|
||||
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[History],
|
||||
visitsFactory: UserIdTo[Visits], settingsFactory: UserIdTo[Settings], accountFactory: UserIdTo[Account])(val actorSystem: ActorSystem) extends Conversation[Unit] with Logger {
|
||||
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 Logger {
|
||||
|
||||
private val book = bookingFactory(userId)
|
||||
private val help = helpFactory(userId)
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import java.time.format.TextStyle
|
||||
import java.time.{LocalTime, ZonedDateTime}
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.bot.model.Button
|
||||
import com.lbs.bot.{Bot, _}
|
||||
@@ -14,18 +11,20 @@ import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.util.DateTimeUtil._
|
||||
import com.lbs.server.util.MessageExtractors.{CallbackCommand, TextCommand}
|
||||
|
||||
import java.time.format.TextStyle
|
||||
import java.time.{LocalDateTime, LocalTime}
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
/**
|
||||
* Date picker Inline Keyboard
|
||||
*
|
||||
* ⬆ ⬆ ⬆
|
||||
* dd MM yyyy
|
||||
* ⬇ ⬇ ⬇
|
||||
*
|
||||
*/
|
||||
* 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[ZonedDateTime] with Localizable {
|
||||
(val actorSystem: ActorSystem) extends Conversation[LocalDateTime] with Localizable {
|
||||
|
||||
private var mode: Mode = DateFromMode
|
||||
|
||||
@@ -36,7 +35,7 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio
|
||||
case Msg(newMode: Mode, _) =>
|
||||
mode = newMode
|
||||
stay()
|
||||
case Msg(initialDate: ZonedDateTime, _) =>
|
||||
case Msg(initialDate: LocalDateTime, _) =>
|
||||
goto(requestDate) using initialDate
|
||||
}
|
||||
|
||||
@@ -52,7 +51,7 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio
|
||||
val (message, updatedDate) = mode match {
|
||||
case DateFromMode =>
|
||||
val startOfTheDay = finalDate.`with`(LocalTime.MIN)
|
||||
val dateFrom = if (startOfTheDay.isBefore(ZonedDateTime.now())) finalDate else startOfTheDay
|
||||
val dateFrom = if (startOfTheDay.isBefore(LocalDateTime.now())) finalDate else startOfTheDay
|
||||
lang.dateFromIs(dateFrom) -> dateFrom
|
||||
case DateToMode =>
|
||||
val dateTo = finalDate.`with`(LocalTime.MAX).minusHours(2)
|
||||
@@ -85,7 +84,7 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio
|
||||
stay() using modifiedDate
|
||||
}
|
||||
|
||||
private def modifyDate(date: ZonedDateTime, tag: String) = {
|
||||
private def modifyDate(date: LocalDateTime, tag: String) = {
|
||||
val dateModifier = tag match {
|
||||
case Tags.DayInc => date.plusDays _
|
||||
case Tags.MonthInc => date.plusMonths _
|
||||
@@ -97,7 +96,7 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio
|
||||
dateModifier(1)
|
||||
}
|
||||
|
||||
private def dateButtons(date: ZonedDateTime) = {
|
||||
private def dateButtons(date: LocalDateTime) = {
|
||||
val day = date.getDayOfMonth.toString
|
||||
val dayOfWeek = date.getDayOfWeek.getDisplayName(TextStyle.SHORT, lang.locale)
|
||||
val month = date.getMonth.getDisplayName(TextStyle.SHORT, lang.locale)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.api.json.model.HistoricVisit
|
||||
import com.lbs.api.json.model.Event
|
||||
import com.lbs.bot.Bot
|
||||
import com.lbs.bot.model.Command
|
||||
import com.lbs.server.conversation.Login.UserId
|
||||
@@ -11,8 +11,8 @@ import com.lbs.server.conversation.base.Conversation
|
||||
import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.service.ApiService
|
||||
|
||||
class History(val userId: UserId, bot: Bot, apiService: ApiService, val localization: Localization,
|
||||
historyPagerFactory: UserIdWithOriginatorTo[Pager[HistoricVisit]])(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)
|
||||
|
||||
@@ -20,7 +20,7 @@ class History(val userId: UserId, bot: Bot, apiService: ApiService, val localiza
|
||||
|
||||
def prepareData: Step =
|
||||
process { _ =>
|
||||
val visits = apiService.visitsHistory(userId.accountId)
|
||||
val visits = apiService.history(userId.accountId)
|
||||
historyPager.restart()
|
||||
historyPager ! visits.map(new SimpleItemsProvider(_))
|
||||
goto(processResponseFromPager)
|
||||
@@ -32,9 +32,9 @@ class History(val userId: UserId, bot: Bot, apiService: ApiService, val localiza
|
||||
historyPager ! cmd
|
||||
stay()
|
||||
case Msg(Pager.NoItemsFound, _) =>
|
||||
bot.sendMessage(userId.source, lang.visitsHistoryIsEmpty)
|
||||
bot.sendMessage(userId.source, lang.eventsListIsEmpty)
|
||||
end()
|
||||
case Msg(_: HistoricVisit, _) =>
|
||||
case Msg(_: Event, _) =>
|
||||
end()
|
||||
}
|
||||
|
||||
@@ -41,15 +41,14 @@ class Login(source: MessageSource, bot: Bot, dataService: DataService, apiServic
|
||||
} onReply {
|
||||
case Msg(MessageExtractors.TextCommand(plainPassword), username) =>
|
||||
val password = textEncryptor.encrypt(plainPassword)
|
||||
val loginResult = apiService.login(username, password)
|
||||
loginResult match {
|
||||
apiService.fullLogin(username, password) match {
|
||||
case Left(error) =>
|
||||
bot.sendMessage(source, error.getMessage)
|
||||
goto(requestUsername)
|
||||
case Right(loggedIn) =>
|
||||
case Right(session) =>
|
||||
val credentials = dataService.saveCredentials(source, username, password)
|
||||
userId = UserId(credentials.userId, credentials.accountId, source)
|
||||
apiService.addSession(credentials.accountId, loggedIn.accessToken, loggedIn.tokenType)
|
||||
apiService.addSession(credentials.accountId, session)
|
||||
bot.sendMessage(source, lang.loginAndPasswordAreOk)
|
||||
originator ! LoggedIn(forwardCommand, credentials.userId, credentials.accountId)
|
||||
end()
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.api.json.model.ReservedVisit
|
||||
import com.lbs.api.json.model.Event
|
||||
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.Visits.Tags
|
||||
import com.lbs.server.conversation.ReservedVisitsViewer.Tags
|
||||
import com.lbs.server.conversation.base.Conversation
|
||||
import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.service.ApiService
|
||||
|
||||
class Visits(val userId: UserId, bot: Bot, apiService: ApiService, val localization: Localization,
|
||||
visitsPagerFactory: UserIdWithOriginatorTo[Pager[ReservedVisit]])(val actorSystem: ActorSystem) extends Conversation[ReservedVisit] 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)
|
||||
|
||||
@@ -21,7 +21,7 @@ class Visits(val userId: UserId, bot: Bot, apiService: ApiService, val localizat
|
||||
|
||||
def prepareData: Step =
|
||||
process { _ =>
|
||||
val visits = apiService.reservedVisits(userId.accountId)
|
||||
val visits = apiService.reserved(userId.accountId)
|
||||
reservedVisitsPager.restart()
|
||||
reservedVisitsPager ! visits.map(new SimpleItemsProvider(_))
|
||||
goto(processResponseFromPager)
|
||||
@@ -35,7 +35,7 @@ class Visits(val userId: UserId, bot: Bot, apiService: ApiService, val localizat
|
||||
case Msg(Pager.NoItemsFound, _) =>
|
||||
bot.sendMessage(userId.source, lang.noUpcomingVisits)
|
||||
end()
|
||||
case Msg(visit: ReservedVisit, _) =>
|
||||
case Msg(visit: Event, _) =>
|
||||
goto(askToCancelVisit) using visit
|
||||
}
|
||||
|
||||
@@ -47,10 +47,10 @@ class Visits(val userId: UserId, bot: Bot, apiService: ApiService, val localizat
|
||||
case Msg(Command(_, _, Some(Tags.No)), _) =>
|
||||
bot.sendMessage(userId.source, lang.appointmentWasNotCancelled)
|
||||
end()
|
||||
case Msg(Command(_, _, Some(Tags.Yes)), visit: ReservedVisit) =>
|
||||
apiService.deleteReservation(userId.accountId, visit.reservationId) match {
|
||||
case Msg(Command(_, _, Some(Tags.Yes)), visit: Event) =>
|
||||
apiService.deleteReservation(userId.accountId, visit.eventId) match {
|
||||
case Left(ex) => bot.sendMessage(userId.source, lang.unableToCancelUpcomingVisit(ex.getMessage))
|
||||
case Right(r) => bot.sendMessage(userId.source, lang.appointmentHasBeenCancelled)
|
||||
case Right(_) => bot.sendMessage(userId.source, lang.appointmentHasBeenCancelled)
|
||||
}
|
||||
end()
|
||||
}
|
||||
@@ -60,7 +60,7 @@ class Visits(val userId: UserId, bot: Bot, apiService: ApiService, val localizat
|
||||
}
|
||||
}
|
||||
|
||||
object Visits {
|
||||
object ReservedVisitsViewer {
|
||||
|
||||
object Tags {
|
||||
val Yes = "yes"
|
||||
@@ -8,9 +8,9 @@ import com.lbs.server.conversation.Login.UserId
|
||||
import com.lbs.server.conversation.Settings._
|
||||
import com.lbs.server.conversation.base.Conversation
|
||||
import com.lbs.server.lang.{Lang, Localizable, Localization}
|
||||
import com.lbs.server.repository.model
|
||||
import com.lbs.server.service.DataService
|
||||
import com.lbs.server.util.MessageExtractors.{CallbackCommand, IntString, TextCommand}
|
||||
import com.lbs.server.repository.model
|
||||
|
||||
class Settings(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization)(val actorSystem: ActorSystem) extends Conversation[Unit] with Localizable {
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.api.json.model.IdName
|
||||
import com.lbs.api.json.model.{IdName, Identified}
|
||||
import com.lbs.bot.model.{Button, Command, TaggedButton}
|
||||
import com.lbs.bot.{Bot, _}
|
||||
import com.lbs.server.ThrowableOr
|
||||
@@ -79,6 +79,6 @@ object StaticData {
|
||||
|
||||
case class FindOptions(searchText: String)
|
||||
|
||||
case class FoundOptions(option: ThrowableOr[List[IdName]])
|
||||
case class FoundOptions[T <: Identified](option: ThrowableOr[List[T]])
|
||||
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import com.lbs.api.json.model.IdName
|
||||
import com.lbs.api.json.model.{IdName, Identified}
|
||||
import com.lbs.bot.model.Command
|
||||
import com.lbs.server.ThrowableOr
|
||||
import com.lbs.server.conversation.Book.BookingData
|
||||
import com.lbs.server.conversation.StaticData.{FindOptions, FoundOptions, LatestOptions, StaticDataConfig}
|
||||
import com.lbs.server.conversation.base.Conversation
|
||||
import com.lbs.server.ThrowableOr
|
||||
|
||||
trait StaticDataForBooking extends Conversation[BookingData] {
|
||||
|
||||
private[conversation] def staticData: StaticData
|
||||
|
||||
protected def withFunctions(latestOptions: => Seq[IdName], staticOptions: => ThrowableOr[List[IdName]], applyId: IdName => BookingData): Step => MessageProcessorFn = {
|
||||
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
|
||||
@@ -39,7 +39,7 @@ trait StaticDataForBooking extends Conversation[BookingData] {
|
||||
}
|
||||
}
|
||||
|
||||
private def filterOptions(options: ThrowableOr[List[IdName]], searchText: String) = {
|
||||
private def filterOptions[T <: Identified](options: ThrowableOr[List[T]], searchText: String) = {
|
||||
options.map(opt => opt.filter(c => c.name.toLowerCase.contains(searchText)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import java.time.LocalTime
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.bot.model.Button
|
||||
import com.lbs.bot.{Bot, _}
|
||||
@@ -13,6 +11,7 @@ import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.util.DateTimeUtil.applyHourMinute
|
||||
import com.lbs.server.util.MessageExtractors.{CallbackCommand, TextCommand}
|
||||
|
||||
import java.time.LocalTime
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import com.lbs.api.json.model.{AvailableVisitsTermPresentation, HistoricVisit, ReservedVisit, ValuationsResponse}
|
||||
import com.lbs.api.json.model.{Event, TermExt}
|
||||
import com.lbs.server.conversation.Book
|
||||
import com.lbs.server.conversation.StaticData.StaticDataConfig
|
||||
import com.lbs.server.repository.model.Monitoring
|
||||
import com.lbs.server.util.DateTimeUtil._
|
||||
|
||||
import java.time.{LocalTime, ZonedDateTime}
|
||||
import java.time.{LocalDateTime, LocalTime}
|
||||
import java.util.Locale
|
||||
|
||||
object En extends Lang {
|
||||
@@ -36,18 +36,18 @@ object En extends Lang {
|
||||
override def noUpcomingVisits: String =
|
||||
"ℹ No upcoming visits found"
|
||||
|
||||
override def areYouSureToCancelAppointment(visit: ReservedVisit): String =
|
||||
override def areYouSureToCancelAppointment(event: Event): String =
|
||||
s"""<b>➡</b> Are you sure want to cancel appointment?
|
||||
|
|
||||
|⏱ <b>${formatDateTime(visit.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${visit.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${visit.service.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${visit.clinic.name}
|
||||
|⏱ <b>${formatDateTime(event.date, locale)}</b>
|
||||
|${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")}
|
||||
|""".stripMargin
|
||||
|
||||
override def chooseDateFrom(exampleDate: ZonedDateTime): String = s"<b>➡</b> Please choose date from or write it manually using format dd-MM, e.g. ${formatDateShort(exampleDate)}"
|
||||
override def chooseDateFrom(exampleDate: LocalDateTime): String = s"<b>➡</b> Please choose date from or write it manually using format dd-MM, e.g. ${formatDateShort(exampleDate)}"
|
||||
|
||||
override def chooseDateTo(exampleDate: ZonedDateTime): String = s"<b>➡</b> Please choose date to or write it manually using format dd-MM, e.g. ${formatDateShort(exampleDate)}"
|
||||
override def chooseDateTo(exampleDate: LocalDateTime): String = s"<b>➡</b> Please choose date to or write it manually using format dd-MM, e.g. ${formatDateShort(exampleDate)}"
|
||||
|
||||
override def findTerms: String = "🔍 Find terms"
|
||||
|
||||
@@ -73,15 +73,13 @@ object En extends Lang {
|
||||
|
||||
override def book: String = "Book"
|
||||
|
||||
override def confirmAppointment(term: AvailableVisitsTermPresentation, valuations: ValuationsResponse): String =
|
||||
override def confirmAppointment(term: TermExt): String =
|
||||
|
||||
s"""<b>➡</b> ${valuations.optionsQuestion.getOrElse("Would you like to confirm your appointment booking?")}
|
||||
s"""<b>➡</b> Would you like to confirm your appointment booking?
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
|
|
||||
|ℹ${valuations.visitTermVariants.head.infoMessage}""".stripMargin
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}""".stripMargin
|
||||
|
||||
override def appointmentIsConfirmed: String = "👍 Your appointment has been confirmed!"
|
||||
|
||||
@@ -165,7 +163,7 @@ object En extends Lang {
|
||||
|
||||
override def providePassword: String = "<b>➡</b> Please provide password"
|
||||
|
||||
override def visitsHistoryIsEmpty: String = "ℹ No visits in your history"
|
||||
override def eventsListIsEmpty: String = "ℹ No visits in your history"
|
||||
|
||||
override def help: String =
|
||||
s"""ℹ Non official bot for <b>Portal Pacjenta LUX MED (v.${Lang.version})</b>.
|
||||
@@ -182,14 +180,14 @@ object En extends Lang {
|
||||
|/settings - settings, e.g. lang
|
||||
|/help - the help""".stripMargin
|
||||
|
||||
override def dateFromIs(dateFrom: ZonedDateTime): String = s"📅 Date from is ${formatDate(dateFrom, locale)}"
|
||||
override def dateFromIs(dateFrom: LocalDateTime): String = s"📅 Date from is ${formatDate(dateFrom, locale)}"
|
||||
|
||||
override def dateToIs(dateTo: ZonedDateTime): String = s"📅 Date to is ${formatDate(dateTo, locale)}"
|
||||
override def dateToIs(dateTo: LocalDateTime): String = s"📅 Date to is ${formatDate(dateTo, locale)}"
|
||||
|
||||
override def termEntry(term: AvailableVisitsTermPresentation, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
override def termEntry(term: TermExt, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|<b>➡</b> /book_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -197,27 +195,27 @@ object En extends Lang {
|
||||
override def termsHeader(page: Int, pages: Int): String =
|
||||
withPages("<b>➡</b> Available terms", page, pages)
|
||||
|
||||
override def historyEntry(visit: HistoricVisit, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(visit.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${visit.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${visit.service.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${visit.clinicName}
|
||||
override def historyEntry(event: Event, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(event.date, locale)}</b>
|
||||
|${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")}
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
override def historyHeader(page: Int, pages: Int): String =
|
||||
withPages("<b>➡</b> Conducted visits", page, pages)
|
||||
|
||||
override def upcomingVisitEntry(visit: ReservedVisit, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(visit.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${visit.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${visit.service.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${visit.clinic.name}
|
||||
override def reservedVisitEntry(event: Event, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(event.date, locale)}</b>
|
||||
|${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")}
|
||||
|<b>➡</b> /cancel_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
override def upcomingVisitsHeader(page: Int, pages: Int): String =
|
||||
override def reservedVisitsHeader(page: Int, pages: Int): String =
|
||||
withPages("<b>➡</b> Reserved visits", page, pages)
|
||||
|
||||
override def bugsHeader(page: Int, pages: Int): String =
|
||||
@@ -258,13 +256,13 @@ object En extends Lang {
|
||||
|Your monitorings were removed. Please /login again and create new monitorings.
|
||||
""".stripMargin
|
||||
|
||||
override def availableTermEntry(term: AvailableVisitsTermPresentation, monitoring: Monitoring, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
override def availableTermEntry(term: TermExt, monitoring: Monitoring, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|/reserve_${monitoring.recordId}_${term.scheduleId}_${minutesSinceBeginOf2018(term.visitDate.startDateTime)}
|
||||
|/reserve_${monitoring.recordId}_${term.term.scheduleId}_${minutesSinceBeginOf2018(term.term.dateTimeFrom)}
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
@@ -285,13 +283,13 @@ object En extends Lang {
|
||||
|
|
||||
|<b>➡</b> Create new monitoring /book""".stripMargin
|
||||
|
||||
override def appointmentIsBooked(term: AvailableVisitsTermPresentation, monitoring: Monitoring): String =
|
||||
override def appointmentIsBooked(term: TermExt, monitoring: Monitoring): String =
|
||||
s"""👍 We just booked an appointment for you!
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}""".stripMargin
|
||||
|
||||
override def maximumMonitoringsLimitExceeded: String = "Maximum monitorings per user is 10"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import com.lbs.api.json.model.{AvailableVisitsTermPresentation, HistoricVisit, ReservedVisit, ValuationsResponse}
|
||||
import com.lbs.api.json.model.{Event, TermExt}
|
||||
import com.lbs.server.conversation.Book.BookingData
|
||||
import com.lbs.server.conversation.StaticData.StaticDataConfig
|
||||
import com.lbs.server.repository.model.Monitoring
|
||||
|
||||
import java.time.{LocalTime, ZonedDateTime}
|
||||
import java.time.{LocalDateTime, LocalTime}
|
||||
import java.util.Locale
|
||||
import scala.io.Source
|
||||
import scala.util.Try
|
||||
@@ -33,8 +33,10 @@ trait Lang {
|
||||
def label: String
|
||||
|
||||
protected def capitalizeFirstLetter(str: String): String = {
|
||||
val fistCapitalLetter = str.head.toTitleCase
|
||||
fistCapitalLetter + str.tail
|
||||
if (str != null && str != "") {
|
||||
val fistCapitalLetter = str.head.toTitleCase
|
||||
fistCapitalLetter + str.tail.toLowerCase
|
||||
} else ""
|
||||
}
|
||||
|
||||
protected def withPages(message: String, page: Int, pages: Int): String
|
||||
@@ -49,11 +51,11 @@ trait Lang {
|
||||
|
||||
def noUpcomingVisits: String
|
||||
|
||||
def areYouSureToCancelAppointment(visit: ReservedVisit): String
|
||||
def areYouSureToCancelAppointment(visit: Event): String
|
||||
|
||||
def chooseDateFrom(exampleDate: ZonedDateTime): String
|
||||
def chooseDateFrom(exampleDate: LocalDateTime): String
|
||||
|
||||
def chooseDateTo(exampleDate: ZonedDateTime): String
|
||||
def chooseDateTo(exampleDate: LocalDateTime): String
|
||||
|
||||
def chooseTimeFrom(exampleTime: LocalTime): String
|
||||
|
||||
@@ -75,7 +77,7 @@ trait Lang {
|
||||
|
||||
def book: String
|
||||
|
||||
def confirmAppointment(term: AvailableVisitsTermPresentation, valuations: ValuationsResponse): String
|
||||
def confirmAppointment(term: TermExt): String
|
||||
|
||||
def appointmentIsConfirmed: String
|
||||
|
||||
@@ -143,29 +145,29 @@ trait Lang {
|
||||
|
||||
def providePassword: String
|
||||
|
||||
def visitsHistoryIsEmpty: String
|
||||
def eventsListIsEmpty: String
|
||||
|
||||
def help: String
|
||||
|
||||
def dateFromIs(dateFrom: ZonedDateTime): String
|
||||
def dateFromIs(dateFrom: LocalDateTime): String
|
||||
|
||||
def dateToIs(dateTo: ZonedDateTime): String
|
||||
def dateToIs(dateTo: LocalDateTime): String
|
||||
|
||||
def timeFromIs(timeFrom: LocalTime): String
|
||||
|
||||
def timeToIs(timeTo: LocalTime): String
|
||||
|
||||
def termEntry(term: AvailableVisitsTermPresentation, page: Int, index: Int): String
|
||||
def termEntry(term: TermExt, page: Int, index: Int): String
|
||||
|
||||
def termsHeader(page: Int, pages: Int): String
|
||||
|
||||
def historyEntry(visit: HistoricVisit, page: Int, index: Int): String
|
||||
def historyEntry(event: Event, page: Int, index: Int): String
|
||||
|
||||
def historyHeader(page: Int, pages: Int): String
|
||||
|
||||
def upcomingVisitEntry(visit: ReservedVisit, page: Int, index: Int): String
|
||||
def reservedVisitEntry(visit: Event, page: Int, index: Int): String
|
||||
|
||||
def upcomingVisitsHeader(page: Int, pages: Int): String
|
||||
def reservedVisitsHeader(page: Int, pages: Int): String
|
||||
|
||||
def bugsHeader(page: Int, pages: Int): String
|
||||
|
||||
@@ -179,13 +181,13 @@ trait Lang {
|
||||
|
||||
def invalidLoginOrPassword: String
|
||||
|
||||
def availableTermEntry(term: AvailableVisitsTermPresentation, monitoring: Monitoring, index: Int): String
|
||||
def availableTermEntry(term: TermExt, monitoring: Monitoring, index: Int): String
|
||||
|
||||
def availableTermsHeader(size: Int): String
|
||||
|
||||
def nothingWasFoundByMonitoring(monitoring: Monitoring): String
|
||||
|
||||
def appointmentIsBooked(term: AvailableVisitsTermPresentation, monitoring: Monitoring): String
|
||||
def appointmentIsBooked(term: TermExt, monitoring: Monitoring): String
|
||||
|
||||
def maximumMonitoringsLimitExceeded: String
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
import com.lbs.server.repository.model
|
||||
import com.lbs.server.service.DataService
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@Component
|
||||
class Localization {
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import com.lbs.api.json.model.{AvailableVisitsTermPresentation, HistoricVisit, ReservedVisit, ValuationsResponse}
|
||||
import com.lbs.api.json.model.{Event, TermExt}
|
||||
import com.lbs.server.conversation.Book
|
||||
import com.lbs.server.conversation.StaticData.StaticDataConfig
|
||||
import com.lbs.server.repository.model.Monitoring
|
||||
import com.lbs.server.util.DateTimeUtil._
|
||||
|
||||
import java.time.{LocalTime, ZonedDateTime}
|
||||
import java.time.{LocalDateTime, LocalTime}
|
||||
import java.util.Locale
|
||||
|
||||
object Pl extends Lang {
|
||||
@@ -36,18 +36,18 @@ object Pl extends Lang {
|
||||
override def noUpcomingVisits: String =
|
||||
"ℹ Nie znaleziono wizyt"
|
||||
|
||||
override def areYouSureToCancelAppointment(visit: ReservedVisit): String =
|
||||
override def areYouSureToCancelAppointment(event: Event): String =
|
||||
s"""<b>➡</b> Czy na pewno chcesz anulować wizytę?
|
||||
|
|
||||
|⏱ <b>${formatDateTime(visit.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${visit.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${visit.service.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${visit.clinic.name}
|
||||
|⏱ <b>${formatDateTime(event.date, locale)}</b>
|
||||
|${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")}
|
||||
|""".stripMargin
|
||||
|
||||
override def chooseDateFrom(exampleDate: ZonedDateTime): String = s"<b>➡</b> Wybierz datę albo zapisz ją w formacie dd-MM, np. ${formatDateShort(exampleDate)}"
|
||||
override def chooseDateFrom(exampleDate: LocalDateTime): String = s"<b>➡</b> Wybierz datę albo zapisz ją w formacie dd-MM, np. ${formatDateShort(exampleDate)}"
|
||||
|
||||
override def chooseDateTo(exampleDate: ZonedDateTime): String = s"<b>➡</b> Wybierz datę albo zapisz ją w formacie dd-MM, np. ${formatDateShort(exampleDate)}"
|
||||
override def chooseDateTo(exampleDate: LocalDateTime): String = s"<b>➡</b> Wybierz datę albo zapisz ją w formacie dd-MM, np. ${formatDateShort(exampleDate)}"
|
||||
|
||||
override def findTerms: String = "🔍 Szukaj terminów"
|
||||
|
||||
@@ -73,15 +73,13 @@ object Pl extends Lang {
|
||||
|
||||
override def book: String = "Zarezerwuj"
|
||||
|
||||
override def confirmAppointment(term: AvailableVisitsTermPresentation, valuations: ValuationsResponse): String =
|
||||
override def confirmAppointment(term: TermExt): String =
|
||||
|
||||
s"""<b>➡</b> ${valuations.optionsQuestion.getOrElse("Czy potwierdzasz wizytę?")}
|
||||
s"""<b>➡</b> Czy potwierdzasz wizytę?
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
|
|
||||
|ℹ${valuations.visitTermVariants.head.infoMessage}""".stripMargin
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}""".stripMargin
|
||||
|
||||
override def appointmentIsConfirmed: String = "👍 Twoja wizyta została potwierdzona!"
|
||||
|
||||
@@ -165,7 +163,7 @@ object Pl extends Lang {
|
||||
|
||||
override def providePassword: String = "<b>➡</b> Podaj hasło"
|
||||
|
||||
override def visitsHistoryIsEmpty: String = "ℹ Brak wizyt w historii"
|
||||
override def eventsListIsEmpty: String = "ℹ Brak wizyt"
|
||||
|
||||
override def help: String =
|
||||
s"""ℹ Nieoficjalny Bot do <b>Portal Pacjenta LUX MED (v.${Lang.version})</b>.
|
||||
@@ -182,14 +180,14 @@ object Pl extends Lang {
|
||||
|/settings - ustawienia, np. język
|
||||
|/help - pomoc""".stripMargin
|
||||
|
||||
override def dateFromIs(dateFrom: ZonedDateTime): String = s"📅 Data od ${formatDate(dateFrom, locale)}"
|
||||
override def dateFromIs(dateFrom: LocalDateTime): String = s"📅 Data od ${formatDate(dateFrom, locale)}"
|
||||
|
||||
override def dateToIs(dateTo: ZonedDateTime): String = s"📅 Data do ${formatDate(dateTo, locale)}"
|
||||
override def dateToIs(dateTo: LocalDateTime): String = s"📅 Data do ${formatDate(dateTo, locale)}"
|
||||
|
||||
override def termEntry(term: AvailableVisitsTermPresentation, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
override def termEntry(term: TermExt, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|<b>➡</b> /book_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -197,27 +195,27 @@ object Pl extends Lang {
|
||||
override def termsHeader(page: Int, pages: Int): String =
|
||||
withPages("<b>➡</b> Dostępne terminy", page, pages)
|
||||
|
||||
override def historyEntry(visit: HistoricVisit, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(visit.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${visit.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${visit.service.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${visit.clinicName}
|
||||
override def historyEntry(event: Event, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(event.date, locale)}</b>
|
||||
|${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")}
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
override def historyHeader(page: Int, pages: Int): String =
|
||||
withPages("<b>➡</b> Odbyte wizyty", page, pages)
|
||||
|
||||
override def upcomingVisitEntry(visit: ReservedVisit, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(visit.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${visit.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${visit.service.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${visit.clinic.name}
|
||||
override def reservedVisitEntry(event: Event, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(event.date, locale)}</b>
|
||||
|${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")}
|
||||
|<b>➡</b> /cancel_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
override def upcomingVisitsHeader(page: Int, pages: Int): String =
|
||||
override def reservedVisitsHeader(page: Int, pages: Int): String =
|
||||
withPages("<b>➡</b> Zarezerwowane wizyty", page, pages)
|
||||
|
||||
override def bugsHeader(page: Int, pages: Int): String =
|
||||
@@ -258,13 +256,13 @@ object Pl extends Lang {
|
||||
|Usunięto monitoringi. Zaloguj się przez /login i stwórz nowe monitoringi.
|
||||
""".stripMargin
|
||||
|
||||
override def availableTermEntry(term: AvailableVisitsTermPresentation, monitoring: Monitoring, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
override def availableTermEntry(term: TermExt, monitoring: Monitoring, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|/reserve_${monitoring.recordId}_${term.scheduleId}_${minutesSinceBeginOf2018(term.visitDate.startDateTime)}
|
||||
|/reserve_${monitoring.recordId}_${term.term.scheduleId}_${minutesSinceBeginOf2018(term.term.dateTimeFrom)}
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
@@ -285,13 +283,13 @@ object Pl extends Lang {
|
||||
|
|
||||
|<b>➡</b> Stwórz nowy monitoring przez /book""".stripMargin
|
||||
|
||||
override def appointmentIsBooked(term: AvailableVisitsTermPresentation, monitoring: Monitoring): String =
|
||||
override def appointmentIsBooked(term: TermExt, monitoring: Monitoring): String =
|
||||
s"""👍 Zarezerwowaliśmy za Ciebie termin!
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}""".stripMargin
|
||||
|
||||
override def maximumMonitoringsLimitExceeded: String = "Maksymalna liczba monitoringów uzytkownika to 10"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import com.lbs.api.json.model.{AvailableVisitsTermPresentation, HistoricVisit, ReservedVisit, ValuationsResponse}
|
||||
import com.lbs.api.json.model.{Event, TermExt}
|
||||
import com.lbs.server.conversation.Book
|
||||
import com.lbs.server.conversation.StaticData.StaticDataConfig
|
||||
import com.lbs.server.repository.model.Monitoring
|
||||
import com.lbs.server.util.DateTimeUtil._
|
||||
|
||||
import java.time.{LocalTime, ZonedDateTime}
|
||||
import java.time.{LocalDateTime, LocalTime}
|
||||
import java.util.Locale
|
||||
|
||||
object Ua extends Lang {
|
||||
@@ -36,18 +36,18 @@ object Ua extends Lang {
|
||||
override def noUpcomingVisits: String =
|
||||
"ℹ Не знайдено жодного майбутнього візиту"
|
||||
|
||||
override def areYouSureToCancelAppointment(visit: ReservedVisit): String =
|
||||
override def areYouSureToCancelAppointment(event: Event): String =
|
||||
s"""<b>➡</b> Ви впевнені, що хочете скасувати візит?
|
||||
|
|
||||
|⏱ <b>${formatDateTime(visit.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${visit.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${visit.service.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${visit.clinic.name}
|
||||
|⏱ <b>${formatDateTime(event.date, locale)}</b>
|
||||
|${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")}
|
||||
|""".stripMargin
|
||||
|
||||
override def chooseDateFrom(exampleDate: ZonedDateTime): String = s"<b>➡</b> Будь ласка, виберіть початкову дату або введіть її, використовуючи формат dd-MM, наприклад ${formatDateShort(exampleDate)}"
|
||||
override def chooseDateFrom(exampleDate: LocalDateTime): String = s"<b>➡</b> Будь ласка, виберіть початкову дату або введіть її, використовуючи формат dd-MM, наприклад ${formatDateShort(exampleDate)}"
|
||||
|
||||
override def chooseDateTo(exampleDate: ZonedDateTime): String = s"<b>➡</b> Будь ласка, виберіть кінцеву дату або введіть її, використовуючи формат dd-MM, наприклад ${formatDateShort(exampleDate)}"
|
||||
override def chooseDateTo(exampleDate: LocalDateTime): String = s"<b>➡</b> Будь ласка, виберіть кінцеву дату або введіть її, використовуючи формат dd-MM, наприклад ${formatDateShort(exampleDate)}"
|
||||
|
||||
override def findTerms: String = "🔍 Знайти терміни"
|
||||
|
||||
@@ -73,15 +73,13 @@ object Ua extends Lang {
|
||||
|
||||
override def book: String = "Зарезервувати"
|
||||
|
||||
override def confirmAppointment(term: AvailableVisitsTermPresentation, valuations: ValuationsResponse): String =
|
||||
override def confirmAppointment(term: TermExt): String =
|
||||
|
||||
s"""<b>➡</b> ${valuations.optionsQuestion.getOrElse("Ви хотіли б підтвердити резервацію візиту?")}
|
||||
s"""<b>➡</b> Ви хотіли б підтвердити резервацію візиту?
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
|
|
||||
|ℹ${valuations.visitTermVariants.head.infoMessage}""".stripMargin
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}""".stripMargin
|
||||
|
||||
override def appointmentIsConfirmed: String = "👍 Ваш візит було підтверджено!"
|
||||
|
||||
@@ -164,7 +162,7 @@ object Ua extends Lang {
|
||||
|
||||
override def providePassword: String = "<b>➡</b> Будь ласка, введіть пароль"
|
||||
|
||||
override def visitsHistoryIsEmpty: String = "ℹ Немає візитів в вашій історії"
|
||||
override def eventsListIsEmpty: String = "ℹ Немає візитів в вашій історії"
|
||||
|
||||
override def help: String =
|
||||
s"""ℹ Це неофіційний бот для <b>Порталу Пацієнта LUX MED (v.${Lang.version})</b>.
|
||||
@@ -181,14 +179,14 @@ object Ua extends Lang {
|
||||
|/settings - налаштування
|
||||
|/help - допомога""".stripMargin
|
||||
|
||||
override def dateFromIs(dateFrom: ZonedDateTime): String = s"📅 Початкова дата ${formatDate(dateFrom, locale)}"
|
||||
override def dateFromIs(dateFrom: LocalDateTime): String = s"📅 Початкова дата ${formatDate(dateFrom, locale)}"
|
||||
|
||||
override def dateToIs(dateTo: ZonedDateTime): String = s"📅 Кінцева дата ${formatDate(dateTo, locale)}"
|
||||
override def dateToIs(dateTo: LocalDateTime): String = s"📅 Кінцева дата ${formatDate(dateTo, locale)}"
|
||||
|
||||
override def termEntry(term: AvailableVisitsTermPresentation, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
override def termEntry(term: TermExt, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|<b>➡</b> /book_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -196,27 +194,27 @@ object Ua extends Lang {
|
||||
override def termsHeader(page: Int, pages: Int): String =
|
||||
withPages("<b>➡</b> Доступні терміни", page, pages)
|
||||
|
||||
override def historyEntry(visit: HistoricVisit, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(visit.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${visit.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${visit.service.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${visit.clinicName}
|
||||
override def historyEntry(event: Event, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(event.date, locale)}</b>
|
||||
|${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")}
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
override def historyHeader(page: Int, pages: Int): String =
|
||||
withPages("<b>➡</b> Завершені візити", page, pages)
|
||||
|
||||
override def upcomingVisitEntry(visit: ReservedVisit, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(visit.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${visit.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${visit.service.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${visit.clinic.name}
|
||||
override def reservedVisitEntry(event: Event, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(event.date, locale)}</b>
|
||||
|${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")}
|
||||
|<b>➡</b> /cancel_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
override def upcomingVisitsHeader(page: Int, pages: Int): String =
|
||||
override def reservedVisitsHeader(page: Int, pages: Int): String =
|
||||
withPages("<b>➡</b> Зарезервовані візити", page, pages)
|
||||
|
||||
override def bugsHeader(page: Int, pages: Int): String =
|
||||
@@ -257,13 +255,13 @@ object Ua extends Lang {
|
||||
|Ваші моніторинги були видалені. Будь ласка, /login знову і створіть нові моніторинги.
|
||||
""".stripMargin
|
||||
|
||||
override def availableTermEntry(term: AvailableVisitsTermPresentation, monitoring: Monitoring, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
override def availableTermEntry(term: TermExt, monitoring: Monitoring, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|/reserve_${monitoring.recordId}_${term.scheduleId}_${minutesSinceBeginOf2018(term.visitDate.startDateTime)}
|
||||
|/reserve_${monitoring.recordId}_${term.term.scheduleId}_${minutesSinceBeginOf2018(term.term.dateTimeFrom)}
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
@@ -284,13 +282,13 @@ object Ua extends Lang {
|
||||
|
|
||||
|<b>➡</b> Створити новий моніторінг /book""".stripMargin
|
||||
|
||||
override def appointmentIsBooked(term: AvailableVisitsTermPresentation, monitoring: Monitoring): String =
|
||||
override def appointmentIsBooked(term: TermExt, monitoring: Monitoring): String =
|
||||
s"""👍 Ми зерезевували візит для вас!
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.visitDate.startDateTime, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.doctor.name}
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.clinic.name}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}""".stripMargin
|
||||
|
||||
override def maximumMonitoringsLimitExceeded: String = "Максимальна кількість моніторінгів 10"
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
|
||||
package com.lbs.server.repository
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
import com.lbs.server.repository.model.{CityHistory, ClinicHistory, Credentials, DoctorHistory, JLong, Monitoring, ServiceHistory, Settings, Source, SystemUser}
|
||||
import javax.persistence.EntityManager
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import javax.persistence.EntityManager
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
@Repository
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
import javax.persistence.{Access, AccessType, Column, Entity}
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
import javax.persistence.{Access, AccessType, Column, Entity}
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
import javax.persistence.{Access, AccessType, Column, Entity}
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.{LocalTime, ZonedDateTime}
|
||||
|
||||
import javax.persistence.{Access, AccessType, Column, Entity}
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Access(AccessType.FIELD)
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
import javax.persistence.{Access, AccessType, Column, Entity}
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence.{Access, AccessType, Column, Entity}
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
import scala.beans.BeanProperty
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
|
||||
package com.lbs.server.service
|
||||
|
||||
import java.time.{LocalTime, ZonedDateTime}
|
||||
|
||||
import cats.instances.either._
|
||||
import com.lbs.api.LuxmedApi
|
||||
import com.lbs.api.http.Session
|
||||
import com.lbs.api.json.model._
|
||||
import com.lbs.server.ThrowableOr
|
||||
import com.lbs.server.util.ServerModelConverters._
|
||||
import org.jasypt.util.text.TextEncryptor
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Service
|
||||
import scalaj.http.HttpResponse
|
||||
|
||||
import java.time.{LocalDateTime, LocalTime, ZonedDateTime}
|
||||
|
||||
@Service
|
||||
class ApiService extends SessionSupport {
|
||||
|
||||
@@ -23,161 +23,100 @@ class ApiService extends SessionSupport {
|
||||
|
||||
private val luxmedApi = new LuxmedApi[ThrowableOr]
|
||||
|
||||
def getAllCities(accountId: Long): ThrowableOr[List[IdName]] =
|
||||
def getAllCities(accountId: Long): ThrowableOr[List[DictionaryCity]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.reservationFilter(session.accessToken, session.tokenType).map(_.cities)
|
||||
luxmedApi.dictionaryCities(session)
|
||||
|
||||
}
|
||||
|
||||
def getAllClinics(accountId: Long, cityId: Long): ThrowableOr[List[IdName]] =
|
||||
def getAllFacilities(accountId: Long, cityId: Long, serviceVariantId: Long): ThrowableOr[List[IdName]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.reservationFilter(session.accessToken,
|
||||
session.tokenType, cityId = Some(cityId)).map(_.clinics)
|
||||
luxmedApi.dictionaryFacilitiesAndDoctors(session, cityId = Some(cityId), serviceVariantId = Some(serviceVariantId)).map(_.facilities)
|
||||
}
|
||||
|
||||
def getAllServices(accountId: Long, cityId: Long, clinicId: Option[Long]): ThrowableOr[List[IdName]] =
|
||||
def getAllServices(accountId: Long): ThrowableOr[List[DictionaryServiceVariants]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.reservationFilter(session.accessToken,
|
||||
session.tokenType, cityId = Some(cityId),
|
||||
clinicId = clinicId).map(_.services)
|
||||
luxmedApi.dictionaryServiceVariants(session).map(s => s.flatMap(_.flatten.filterNot(_.children.nonEmpty)))
|
||||
}
|
||||
|
||||
def getAllDoctors(accountId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): ThrowableOr[List[IdName]] =
|
||||
def getAllDoctors(accountId: Long, cityId: Long, serviceVariantId: Long): ThrowableOr[List[Doctor]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.reservationFilter(session.accessToken,
|
||||
session.tokenType, cityId = Some(cityId),
|
||||
clinicId = clinicId, serviceId = Some(serviceId)).map(_.doctors)
|
||||
luxmedApi.dictionaryFacilitiesAndDoctors(session, cityId = Some(cityId), serviceVariantId = Some(serviceVariantId)).map(_.doctors)
|
||||
}
|
||||
|
||||
def getPayers(accountId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): ThrowableOr[(Option[IdName], Seq[IdName])] =
|
||||
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 reservationFilterResponse = luxmedApi.reservationFilter(session.accessToken,
|
||||
session.tokenType, cityId = Some(cityId),
|
||||
clinicId = clinicId, serviceId = Some(serviceId))
|
||||
reservationFilterResponse.map { response =>
|
||||
response.defaultPayer -> response.payers
|
||||
}
|
||||
}
|
||||
|
||||
def getAvailableTerms(accountId: Long, payerId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long, doctorId: Option[Long],
|
||||
fromDate: ZonedDateTime = ZonedDateTime.now(), toDate: Option[ZonedDateTime] = None, timeFrom: LocalTime, timeTo: LocalTime,
|
||||
languageId: Long = 10, findFirstFreeTerm: Boolean = false): ThrowableOr[List[AvailableVisitsTermPresentation]] =
|
||||
withSession(accountId) { session =>
|
||||
val termsEither = luxmedApi.availableTerms(session.accessToken, session.tokenType, payerId, cityId, clinicId, serviceId, doctorId,
|
||||
fromDate, toDate, languageId = languageId, findFirstFreeTerm = findFirstFreeTerm).map(_.availableVisitsTermPresentation)
|
||||
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.visitDate.startDateTime.toLocalTime
|
||||
time == timeFrom || time == timeTo || (time.isAfter(timeFrom) && time.isBefore(timeTo))
|
||||
val time = term.term.dateTimeFrom.toLocalTime
|
||||
val date = term.term.dateTimeFrom
|
||||
(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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def temporaryReservation(accountId: Long, temporaryReservationRequest: TemporaryReservationRequest, valuationsRequest: ValuationsRequest): ThrowableOr[(TemporaryReservationResponse, ValuationsResponse)] =
|
||||
def reservationLockterm(accountId: Long, xsrfToken: XsrfToken, reservationLocktermRequest: ReservationLocktermRequest): ThrowableOr[ReservationLocktermResponse] =
|
||||
withSession(accountId) { session =>
|
||||
for {
|
||||
temporaryReservation <- luxmedApi.temporaryReservation(session.accessToken, session.tokenType, temporaryReservationRequest)
|
||||
valuationsResponse <- luxmedApi.valuations(session.accessToken, session.tokenType, valuationsRequest)
|
||||
} yield temporaryReservation -> valuationsResponse
|
||||
luxmedApi.reservationLockterm(session, xsrfToken, reservationLocktermRequest)
|
||||
}
|
||||
|
||||
def deleteTemporaryReservation(accountId: Long, temporaryReservationId: Long): ThrowableOr[HttpResponse[String]] =
|
||||
def deleteTemporaryReservation(accountId: Long, xsrfToken: XsrfToken, temporaryReservationId: Long): ThrowableOr[Unit] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.deleteTemporaryReservation(session.accessToken, session.tokenType, temporaryReservationId)
|
||||
luxmedApi.deleteTemporaryReservation(session, xsrfToken, temporaryReservationId)
|
||||
}
|
||||
|
||||
def reservation(accountId: Long, reservationRequest: ReservationRequest): ThrowableOr[ReservationResponse] =
|
||||
def reservationConfirm(accountId: Long, xsrfToken: XsrfToken, reservationConfirmRequest: ReservationConfirmRequest): ThrowableOr[ReservationConfirmResponse] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.reservation(session.accessToken, session.tokenType, reservationRequest)
|
||||
luxmedApi.reservationConfirm(session, xsrfToken, reservationConfirmRequest)
|
||||
}
|
||||
|
||||
def reserveVisit(accountId: Long, term: AvailableVisitsTermPresentation): ThrowableOr[ReservationResponse] = {
|
||||
val temporaryReservationRequest = term.mapTo[TemporaryReservationRequest]
|
||||
val valuationsRequest = term.mapTo[ValuationsRequest]
|
||||
for {
|
||||
okResponse <- temporaryReservation(accountId, temporaryReservationRequest, valuationsRequest)
|
||||
(temporaryReservation, valuations) = okResponse
|
||||
temporaryReservationId = temporaryReservation.id
|
||||
visitTermVariant = valuations.visitTermVariants.head
|
||||
reservationRequest = (temporaryReservationId, visitTermVariant, term).mapTo[ReservationRequest]
|
||||
reservation <- reservation(accountId, reservationRequest)
|
||||
} yield reservation
|
||||
}
|
||||
|
||||
def canTermBeChanged(accountId: Long, reservationId: Long): ThrowableOr[HttpResponse[String]] =
|
||||
def reservationChangeTerm(accountId: Long, xsrfToken: XsrfToken, reservationChangetermRequest: ReservationChangetermRequest): ThrowableOr[ReservationConfirmResponse] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.canTermBeChanged(session.accessToken, session.tokenType, reservationId)
|
||||
luxmedApi.reservationChangeTerm(session, xsrfToken, reservationChangetermRequest)
|
||||
}
|
||||
|
||||
|
||||
def detailToChangeTerm(accountId: Long, reservationId: Long): ThrowableOr[ChangeTermDetailsResponse] =
|
||||
def history(accountId: Long, fromDate: ZonedDateTime = ZonedDateTime.now().minusYears(1),
|
||||
toDate: ZonedDateTime = ZonedDateTime.now()): ThrowableOr[List[Event]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.detailToChangeTerm(session.accessToken, session.tokenType, reservationId)
|
||||
luxmedApi.events(session, fromDate, toDate).map(_.events.filter(_.status == "Realized"))
|
||||
}
|
||||
|
||||
def temporaryReservationToChangeTerm(accountId: Long, reservationId: Long, temporaryReservationRequest: TemporaryReservationRequest, valuationsRequest: ValuationsRequest): ThrowableOr[(TemporaryReservationResponse, ValuationsResponse)] =
|
||||
def reserved(accountId: Long, fromDate: ZonedDateTime = ZonedDateTime.now(),
|
||||
toDate: ZonedDateTime = ZonedDateTime.now().plusMonths(3)): ThrowableOr[List[Event]] =
|
||||
withSession(accountId) { session =>
|
||||
for {
|
||||
temporaryReservation <- luxmedApi.temporaryReservationToChangeTerm(session.accessToken, session.tokenType, reservationId, temporaryReservationRequest)
|
||||
valuationsResponse <- luxmedApi.valuationToChangeTerm(session.accessToken, session.tokenType, reservationId, valuationsRequest)
|
||||
} yield temporaryReservation -> valuationsResponse
|
||||
}
|
||||
|
||||
def valuationToChangeTerm(accountId: Long, reservationId: Long, valuationsRequest: ValuationsRequest): ThrowableOr[ValuationsResponse] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.valuationToChangeTerm(session.accessToken, session.tokenType, reservationId, valuationsRequest)
|
||||
}
|
||||
|
||||
def changeTerm(accountId: Long, reservationId: Long, reservationRequest: ReservationRequest): ThrowableOr[ChangeTermResponse] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.changeTerm(session.accessToken, session.tokenType, reservationId, reservationRequest)
|
||||
}
|
||||
|
||||
def updateReservedVisit(accountId: Long, term: AvailableVisitsTermPresentation): ThrowableOr[ChangeTermResponse] = {
|
||||
val reservedVisitMaybe = reservedVisits(accountId, toDate = ZonedDateTime.now().plusMonths(6)).map(_.find(_.service.id == term.serviceId))
|
||||
reservedVisitMaybe match {
|
||||
case Right(Some(reservedVisit: ReservedVisit)) =>
|
||||
val reservationId = reservedVisit.reservationId
|
||||
val temporaryReservationRequest = term.mapTo[TemporaryReservationRequest]
|
||||
val valuationsRequest = term.mapTo[ValuationsRequest]
|
||||
val canTermBeChangedResponse = canTermBeChanged(accountId, reservationId)
|
||||
if (canTermBeChangedResponse.exists(_.code == 204)) {
|
||||
for {
|
||||
okResponse <- temporaryReservationToChangeTerm(accountId, reservationId, temporaryReservationRequest, valuationsRequest)
|
||||
(temporaryReservation, valuations) = okResponse
|
||||
temporaryReservationId = temporaryReservation.id
|
||||
visitTermVariant = valuations.visitTermVariants.head
|
||||
reservationRequest = (temporaryReservationId, visitTermVariant, term).mapTo[ReservationRequest]
|
||||
reservation <- changeTerm(accountId, reservationId, reservationRequest)
|
||||
} yield reservation
|
||||
} else left(s"Term for reservation [$reservationId] can't be changed")
|
||||
case Left(ex) =>
|
||||
Left(ex)
|
||||
case _ =>
|
||||
left(s"Existing reservation for service [${term.serviceId}] not found. Nothing to update")
|
||||
}
|
||||
}
|
||||
|
||||
def visitsHistory(accountId: Long, fromDate: ZonedDateTime = ZonedDateTime.now().minusYears(1),
|
||||
toDate: ZonedDateTime = ZonedDateTime.now(), page: Int = 1, pageSize: Int = 100): ThrowableOr[List[HistoricVisit]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.visitsHistory(session.accessToken, session.tokenType, fromDate, toDate, page, pageSize).map(_.historicVisits)
|
||||
}
|
||||
|
||||
def reservedVisits(accountId: Long, fromDate: ZonedDateTime = ZonedDateTime.now(),
|
||||
toDate: ZonedDateTime = ZonedDateTime.now().plusMonths(3)): ThrowableOr[List[ReservedVisit]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.reservedVisits(session.accessToken, session.tokenType, fromDate, toDate).map(_.reservedVisits)
|
||||
luxmedApi.events(session, fromDate, toDate).map(_.events.filter(_.status == "Reserved"))
|
||||
}
|
||||
|
||||
def deleteReservation(accountId: Long, reservationId: Long): ThrowableOr[HttpResponse[String]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.deleteReservation(session.accessToken, session.tokenType, reservationId)
|
||||
luxmedApi.reservationDelete(session, reservationId)
|
||||
}
|
||||
|
||||
def login(username: String, password: String): ThrowableOr[LoginResponse] = {
|
||||
luxmedApi.login(username, textEncryptor.decrypt(password))
|
||||
override def fullLogin(username: String, encryptedPassword: String): ThrowableOr[Session] = {
|
||||
val password = textEncryptor.decrypt(encryptedPassword)
|
||||
for {
|
||||
r1 <- luxmedApi.login(username, password)
|
||||
tmpSession = Session(r1.body.accessToken, r1.body.accessToken, r1.cookies)
|
||||
r2 <- luxmedApi.loginToApp(tmpSession)
|
||||
cookies = r1.cookies ++ r2.cookies
|
||||
accessToken = r1.body.accessToken
|
||||
tokenType = r1.body.tokenType
|
||||
} yield Session(accessToken, tokenType, cookies)
|
||||
}
|
||||
|
||||
private def left(msg: String) = Left(new RuntimeException(msg))
|
||||
|
||||
def getXsrfToken(accountId: Long): ThrowableOr[XsrfToken] = {
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.getForgeryToken(session).map(ft => XsrfToken(ft.body.token, ft.cookies))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
|
||||
package com.lbs.server.service
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
import com.lbs.api.json.model.IdName
|
||||
import com.lbs.bot.model.MessageSource
|
||||
import com.lbs.server.conversation.Book.BookingData
|
||||
import com.lbs.server.repository.DataRepository
|
||||
import com.lbs.server.repository.model._
|
||||
import com.lbs.server.util.ServerModelConverters._
|
||||
import javax.transaction.Transactional
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import javax.transaction.Transactional
|
||||
|
||||
@Service
|
||||
class DataService {
|
||||
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
|
||||
package com.lbs.server.service
|
||||
|
||||
import com.lbs.api.exception.{InvalidLoginOrPasswordException, ServiceIsAlreadyBookedException}
|
||||
import com.lbs.api.json.model.AvailableVisitsTermPresentation
|
||||
import com.lbs.api.exception.InvalidLoginOrPasswordException
|
||||
import com.lbs.api.json.model._
|
||||
import com.lbs.bot.Bot
|
||||
import com.lbs.bot.model.{MessageSource, MessageSourceSystem}
|
||||
import com.lbs.common.{Logger, Scheduler}
|
||||
import com.lbs.server.lang.Localization
|
||||
import com.lbs.server.repository.model._
|
||||
import com.lbs.server.util.DateTimeUtil._
|
||||
import com.lbs.server.util.ServerModelConverters._
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.{LocalDateTime, ZonedDateTime}
|
||||
import java.util.concurrent.ScheduledFuture
|
||||
import javax.annotation.PostConstruct
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.duration._
|
||||
import scala.util.{Failure, Random}
|
||||
import scala.util.Random
|
||||
|
||||
@Service
|
||||
class MonitoringService extends Logger {
|
||||
@@ -49,7 +50,7 @@ class MonitoringService extends Logger {
|
||||
|
||||
private var checkedOn: ZonedDateTime = _
|
||||
|
||||
def notifyUserAboutTerms(terms: Seq[AvailableVisitsTermPresentation], monitoring: Monitoring): Unit = {
|
||||
def notifyUserAboutTerms(terms: Seq[TermExt], monitoring: Monitoring): Unit = {
|
||||
deactivateMonitoring(monitoring.accountId, monitoring.recordId)
|
||||
|
||||
val fiveTerms = terms.take(5).zipWithIndex //send only 5 closest terms
|
||||
@@ -65,9 +66,9 @@ class MonitoringService extends Logger {
|
||||
|
||||
private def monitor(monitoring: Monitoring): Unit = {
|
||||
debug(s"Looking for available terms. Monitoring [#${monitoring.recordId}]")
|
||||
val dateFrom = optimizeDateFrom(monitoring.dateFrom, monitoring.offset)
|
||||
val termsEither = apiService.getAvailableTerms(monitoring.accountId, monitoring.payerId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId,
|
||||
monitoring.doctorId, dateFrom, Some(monitoring.dateTo), timeFrom = monitoring.timeFrom, timeTo = monitoring.timeTo)
|
||||
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)
|
||||
termsEither match {
|
||||
case Right(terms) =>
|
||||
if (terms.nonEmpty) {
|
||||
@@ -92,8 +93,8 @@ class MonitoringService extends Logger {
|
||||
}
|
||||
}
|
||||
|
||||
private def optimizeDateFrom(date: ZonedDateTime, offset: Int) = {
|
||||
val nowWithOffset = ZonedDateTime.now().plusHours(offset)
|
||||
private def optimizeDateFrom(date: LocalDateTime, offset: Int) = {
|
||||
val nowWithOffset = LocalDateTime.now().plusHours(offset)
|
||||
if (date.isBefore(nowWithOffset)) nowWithOffset else date
|
||||
}
|
||||
|
||||
@@ -144,13 +145,19 @@ class MonitoringService extends Logger {
|
||||
dbChecker.schedule(updateMonitorings(), 1.minute)
|
||||
}
|
||||
|
||||
private def bookAppointment(term: AvailableVisitsTermPresentation, monitoring: Monitoring, rebookIfExists: Boolean): Unit = {
|
||||
apiService.reserveVisit(monitoring.accountId, term).toTry.recoverWith {
|
||||
case _: ServiceIsAlreadyBookedException if rebookIfExists =>
|
||||
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])
|
||||
temporaryReservationId = reservationLocktermResponse.value.temporaryReservationId
|
||||
response <- if (reservationLocktermResponse.value.changeTermAvailable && rebookIfExists) {
|
||||
info(s"Service [${monitoring.serviceName}] is already booked. Trying to update term")
|
||||
apiService.updateReservedVisit(monitoring.accountId, term).toTry
|
||||
case ex => Failure(ex)
|
||||
}.toEither match {
|
||||
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(_) =>
|
||||
bot.sendMessage(monitoring.source, lang(monitoring.userId).appointmentIsBooked(term, monitoring))
|
||||
deactivateMonitoring(monitoring.accountId, monitoring.recordId)
|
||||
@@ -159,6 +166,15 @@ class MonitoringService extends Logger {
|
||||
}
|
||||
}
|
||||
|
||||
private def bookOrUnlockTerm[T](accountId: Long, xsrfToken: XsrfToken, temporaryReservationId: Long, fn: (Long) => Either[Throwable, T]): Either[Throwable, T] = {
|
||||
fn(accountId) match {
|
||||
case r@Left(_) =>
|
||||
apiService.deleteTemporaryReservation(accountId, xsrfToken, temporaryReservationId)
|
||||
r
|
||||
case r => r
|
||||
}
|
||||
}
|
||||
|
||||
def deactivateMonitoring(accountId: JLong, monitoringId: JLong): Unit = {
|
||||
val activeMonitoringMaybe = activeMonitorings.remove(monitoringId)
|
||||
activeMonitoringMaybe match {
|
||||
@@ -200,11 +216,11 @@ class MonitoringService extends Logger {
|
||||
val monitoringMaybe = dataService.findMonitoring(accountId, monitoringId)
|
||||
monitoringMaybe match {
|
||||
case Some(monitoring) =>
|
||||
val termsEither = apiService.getAvailableTerms(monitoring.accountId, monitoring.payerId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId,
|
||||
monitoring.doctorId, monitoring.dateFrom, Some(monitoring.dateTo), 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.scheduleId == scheduleId && minutesSinceBeginOf2018(term.visitDate.startDateTime) == time)
|
||||
val termMaybe = terms.find(term => term.term.scheduleId == scheduleId && minutesSinceBeginOf2018(term.term.dateTimeFrom) == time)
|
||||
termMaybe match {
|
||||
case Some(term) =>
|
||||
bookAppointment(term, monitoring, rebookIfExists = true)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package com.lbs.server.service
|
||||
|
||||
import com.lbs.api.exception.SessionExpiredException
|
||||
import com.lbs.api.json.model.LoginResponse
|
||||
import com.lbs.api.http.Session
|
||||
import com.lbs.common.{Logger, ParametrizedLock}
|
||||
import com.lbs.server.ThrowableOr
|
||||
import com.lbs.server.exception.UserNotFoundException
|
||||
@@ -11,9 +11,7 @@ import scala.collection.mutable
|
||||
|
||||
trait SessionSupport extends Logger {
|
||||
|
||||
case class Session(accessToken: String, tokenType: String)
|
||||
|
||||
def login(username: String, password: String): ThrowableOr[LoginResponse]
|
||||
def fullLogin(username: String, password: String): ThrowableOr[Session]
|
||||
|
||||
protected def dataService: DataService
|
||||
|
||||
@@ -27,9 +25,7 @@ trait SessionSupport extends Logger {
|
||||
def auth: ThrowableOr[Session] = {
|
||||
val credentialsMaybe = dataService.getCredentials(accountId)
|
||||
credentialsMaybe match {
|
||||
case Some(credentials) =>
|
||||
val loginResponse = login(credentials.username, credentials.password)
|
||||
loginResponse.map(r => Session(r.accessToken, r.tokenType))
|
||||
case Some(credentials) => fullLogin(credentials.username, credentials.password)
|
||||
case None => Left(UserNotFoundException(accountId))
|
||||
}
|
||||
}
|
||||
@@ -67,8 +63,8 @@ trait SessionSupport extends Logger {
|
||||
} yield result
|
||||
}
|
||||
|
||||
def addSession(accountId: Long, accessToken: String, tokenType: String): Unit =
|
||||
def addSession(accountId: Long, session: Session): Unit =
|
||||
lock.obtainLock(accountId).synchronized {
|
||||
sessions.put(accountId, Session(accessToken, tokenType))
|
||||
sessions.put(accountId, session)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
|
||||
package com.lbs.server
|
||||
|
||||
import java.time._
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.Locale
|
||||
|
||||
import com.lbs.api.json.model._
|
||||
import com.lbs.bot.model.Command
|
||||
import com.lbs.common.ModelConverters
|
||||
@@ -12,6 +8,9 @@ import com.lbs.server.conversation.Book.BookingData
|
||||
import com.lbs.server.conversation.Login.UserId
|
||||
import com.lbs.server.repository.model.{History, Monitoring}
|
||||
|
||||
import java.time._
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.Locale
|
||||
import scala.language.{higherKinds, implicitConversions}
|
||||
import scala.util.Try
|
||||
|
||||
@@ -38,8 +37,8 @@ package object util {
|
||||
serviceName = bookingData.serviceId.name,
|
||||
doctorId = bookingData.doctorId.optionalId,
|
||||
doctorName = bookingData.doctorId.name,
|
||||
dateFrom = bookingData.dateFrom,
|
||||
dateTo = bookingData.dateTo,
|
||||
dateFrom = bookingData.dateFrom.atZone(DateTimeUtil.Zone),
|
||||
dateTo = bookingData.dateTo.atZone(DateTimeUtil.Zone),
|
||||
timeFrom = bookingData.timeFrom,
|
||||
timeTo = bookingData.timeTo,
|
||||
autobook = bookingData.autobook,
|
||||
@@ -48,49 +47,73 @@ package object util {
|
||||
)
|
||||
}
|
||||
|
||||
implicit val AvailableVisitsTermPresentationToTemporaryReservationRequestConverter:
|
||||
ObjectConverter[AvailableVisitsTermPresentation, TemporaryReservationRequest] =
|
||||
(term: AvailableVisitsTermPresentation) => {
|
||||
TemporaryReservationRequest(
|
||||
clinicId = term.clinic.id,
|
||||
implicit val ReservationLocktermResponseAndTermToReservationConfirmRequestConverter:
|
||||
ObjectConverter[(ReservationLocktermResponse, TermExt), ReservationConfirmRequest] =
|
||||
(data: (ReservationLocktermResponse, TermExt)) => {
|
||||
val (reservationLocktermResponse, termExt) = data
|
||||
val term = termExt.term
|
||||
ReservationConfirmRequest(
|
||||
date = term.dateTimeFrom.minusHours(2).toString + ":00.000Z",
|
||||
doctorId = term.doctor.id,
|
||||
payerDetailsList = term.payerDetailsList,
|
||||
referralRequiredByService = term.referralRequiredByService,
|
||||
facilityId = term.clinicId,
|
||||
roomId = term.roomId,
|
||||
serviceId = term.serviceId,
|
||||
startDateTime = term.visitDate.startDateTime
|
||||
scheduleId = term.scheduleId,
|
||||
serviceVariantId = term.serviceId,
|
||||
temporaryReservationId = reservationLocktermResponse.value.temporaryReservationId,
|
||||
timeFrom = term.dateTimeFrom.toLocalTime,
|
||||
valuation = reservationLocktermResponse.value.valuations.head
|
||||
)
|
||||
}
|
||||
|
||||
implicit val TmpReservationIdWithValuationsToReservationRequestConverter:
|
||||
ObjectConverter[(Long, VisitTermVariant, AvailableVisitsTermPresentation), ReservationRequest] =
|
||||
(any: (Long, VisitTermVariant, AvailableVisitsTermPresentation)) => {
|
||||
val (tmpReservationId, valuations, term) = any
|
||||
ReservationRequest(
|
||||
clinicId = term.clinic.id,
|
||||
doctorId = term.doctor.id,
|
||||
payerData = valuations.valuationDetail.payerData,
|
||||
roomId = term.roomId,
|
||||
serviceId = term.serviceId,
|
||||
startDateTime = term.visitDate.startDateTime,
|
||||
temporaryReservationId = tmpReservationId
|
||||
implicit val ReservationLocktermResponseAndTermToReservationChangeTermRequestConverter:
|
||||
ObjectConverter[(ReservationLocktermResponse, TermExt), ReservationChangetermRequest] =
|
||||
(data: (ReservationLocktermResponse, TermExt)) => {
|
||||
val (reservationLocktermResponse, termExt) = data
|
||||
val term = termExt.term
|
||||
val existingReservationId = reservationLocktermResponse.value.relatedVisits.head.reservationId
|
||||
ReservationChangetermRequest(
|
||||
existingReservationId = existingReservationId,
|
||||
term = NewTerm(
|
||||
date = term.dateTimeFrom.minusHours(2).toString + ":00.000Z",
|
||||
doctorId = term.doctor.id,
|
||||
facilityId = term.clinicId,
|
||||
parentReservationId = existingReservationId,
|
||||
referralRequired = reservationLocktermResponse.value.valuations.head.isReferralRequired,
|
||||
roomId = term.roomId,
|
||||
scheduleId = term.scheduleId,
|
||||
serviceVariantId = term.serviceId,
|
||||
temporaryReservationId = reservationLocktermResponse.value.temporaryReservationId,
|
||||
timeFrom = term.dateTimeFrom.toLocalTime,
|
||||
valuation = reservationLocktermResponse.value.valuations.head
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
implicit val AvailableVisitsTermPresentationToValuationRequestConverter:
|
||||
ObjectConverter[AvailableVisitsTermPresentation, ValuationsRequest] =
|
||||
(term: AvailableVisitsTermPresentation) => {
|
||||
ValuationsRequest(
|
||||
clinicId = term.clinic.id,
|
||||
implicit val TermToReservationLocktermRequest:
|
||||
ObjectConverter[TermExt, ReservationLocktermRequest] =
|
||||
termExt => {
|
||||
val term = termExt.term
|
||||
val additionalData = termExt.additionalData
|
||||
ReservationLocktermRequest(
|
||||
date = term.dateTimeFrom.minusHours(2).toString + ":00.000Z",
|
||||
doctor = term.doctor,
|
||||
doctorId = term.doctor.id,
|
||||
payerDetailsList = term.payerDetailsList,
|
||||
referralRequiredByService = term.referralRequiredByService,
|
||||
facilityId = term.clinicId,
|
||||
impedimentText = term.impedimentText,
|
||||
isAdditional = term.isAdditional,
|
||||
isImpediment = term.isImpediment,
|
||||
isPreparationRequired = additionalData.isPreparationRequired,
|
||||
isTelemedicine = term.isTelemedicine,
|
||||
preparationItems = additionalData.preparationItems,
|
||||
roomId = term.roomId,
|
||||
serviceId = term.serviceId,
|
||||
startDateTime = term.visitDate.startDateTime
|
||||
scheduleId = term.scheduleId,
|
||||
serviceVariantId = term.serviceId,
|
||||
timeFrom = term.dateTimeFrom.toLocalTime.toString,
|
||||
timeTo = term.dateTimeTo.toLocalTime.toString
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
implicit val HistoryToIdNameConverter: ObjectConverter[History, IdName] =
|
||||
(history: History) => IdName(history.id, history.name)
|
||||
}
|
||||
@@ -124,6 +147,8 @@ package object util {
|
||||
}
|
||||
|
||||
object DateTimeUtil {
|
||||
val Zone: ZoneId = ZoneId.of("Europe/Warsaw")
|
||||
|
||||
private val DateFormat: Locale => DateTimeFormatter = locale => DateTimeFormatter.ofPattern("dd MMM yyyy", locale)
|
||||
|
||||
private val DateShortFormat = DateTimeFormatter.ofPattern("dd-MM")
|
||||
@@ -132,21 +157,25 @@ package object util {
|
||||
|
||||
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))
|
||||
|
||||
def formatDate(date: ZonedDateTime, locale: Locale): String = date.format(DateFormat(locale))
|
||||
|
||||
def formatDateShort(date: ZonedDateTime): String = date.format(DateShortFormat)
|
||||
def formatDateShort(date: LocalDateTime): String = date.format(DateShortFormat)
|
||||
|
||||
def formatTime(time: LocalTime): String = time.format(TimeFormat)
|
||||
|
||||
def formatDateTime(date: ZonedDateTime, locale: Locale): String = date.format(DateTimeFormat(locale))
|
||||
|
||||
private val EpochMinutesTillBeginOf2018: Long = epochMinutes(ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()))
|
||||
def formatDateTime(date: LocalDateTime, locale: Locale): String = date.format(DateTimeFormat(locale))
|
||||
|
||||
def epochMinutes(time: ZonedDateTime): Long = time.toInstant.getEpochSecond / 60
|
||||
private val EpochMinutesTillBeginOf2022: Long = epochMinutes(LocalDateTime.of(2022, 1, 1, 0, 0, 0, 0))
|
||||
|
||||
def minutesSinceBeginOf2018(time: ZonedDateTime): Long = epochMinutes(time) - EpochMinutesTillBeginOf2018
|
||||
def epochMinutes(time: LocalDateTime): Long = time.toInstant(ZonedDateTime.now().getOffset).getEpochSecond / 60
|
||||
|
||||
def applyDayMonth(dayMonthStr: String, date: ZonedDateTime): ZonedDateTime = {
|
||||
def minutesSinceBeginOf2018(time: LocalDateTime): Long = epochMinutes(time) - EpochMinutesTillBeginOf2022
|
||||
|
||||
def applyDayMonth(dayMonthStr: String, date: LocalDateTime): LocalDateTime = {
|
||||
val dayMonth = MonthDay.parse(dayMonthStr, DateShortFormat)
|
||||
val newDate = date.withDayOfMonth(dayMonth.getDayOfMonth).withMonth(dayMonth.getMonthValue)
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package com.lbs.server.repository
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
import com.lbs.server.repository.model.{CityHistory, ClinicHistory, Credentials, DoctorHistory, ServiceHistory}
|
||||
import javax.persistence.EntityManager
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -13,6 +10,9 @@ import org.springframework.boot.test.context.TestConfiguration
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.test.context.junit4.SpringRunner
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import javax.persistence.EntityManager
|
||||
|
||||
object DataRepositorySpec {
|
||||
|
||||
@TestConfiguration
|
||||
|
||||
Reference in New Issue
Block a user