mirror of
https://github.com/dyrkin/luxmed-bot.git
synced 2025-12-21 21:33:12 +01:00
Use scalafmt
This commit is contained in:
committed by
Yevhen Zadyra
parent
327bdfe6d7
commit
e870e404e1
@@ -13,7 +13,7 @@ steps:
|
||||
GRADLE_USER_HOME: ~/.gradle
|
||||
command: [ /bin/bash ]
|
||||
commands:
|
||||
- ./gradlew test
|
||||
- ./gradlew checkScalafmtAll test
|
||||
- ./gradlew prepare
|
||||
- echo -n "1.0.$DRONE_BUILD_NUMBER,latest" > .tags
|
||||
- echo -n "1.0.$DRONE_BUILD_NUMBER" > ./docker/version
|
||||
|
||||
11
.scalafmt.conf
Normal file
11
.scalafmt.conf
Normal file
@@ -0,0 +1,11 @@
|
||||
version = 3.5.8
|
||||
runner.dialect = scala213
|
||||
preset = IntelliJ
|
||||
maxColumn = 120
|
||||
project.git = true
|
||||
|
||||
align.preset = some
|
||||
docstrings.style = SpaceAsterisk
|
||||
docstrings.oneline = fold
|
||||
docstrings.wrap = no
|
||||
docstrings.blankFirstLine = yes
|
||||
@@ -32,7 +32,7 @@ to the same folder and rename it to **secrets.env**
|
||||
### Develop run
|
||||
|
||||
1. Run `docker-compose up` to launch PostgreSQL database
|
||||
2. Set env `TELEGRAM_TOKEN="YOUR_TOKEN"`
|
||||
2. Set env `TELEGRAM_TOKEN=YOUR_TOKEN`
|
||||
3. Run `Boot.scala` app
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api
|
||||
|
||||
import com.lbs.api.http.Session
|
||||
@@ -7,8 +6,10 @@ import scalaj.http.{BaseHttp, HttpRequest}
|
||||
|
||||
import java.net.HttpCookie
|
||||
|
||||
object ApiHttp extends BaseHttp(
|
||||
userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"
|
||||
object ApiHttp
|
||||
extends BaseHttp(
|
||||
userAgent =
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"
|
||||
)
|
||||
|
||||
trait ApiBase {
|
||||
@@ -22,13 +23,11 @@ trait ApiBase {
|
||||
`Accept-Language` -> "pl;q=1.0, pl;q=0.9, en;q=0.8"
|
||||
)
|
||||
|
||||
|
||||
protected def httpUnauthorized(url: String): HttpRequest = {
|
||||
ApiHttp(s"https://portalpacjenta.luxmed.pl/PatientPortalMobileAPI/api/$url")
|
||||
.headers(CommonHeaders)
|
||||
}
|
||||
|
||||
|
||||
protected def http(url: String, session: Session): HttpRequest = {
|
||||
ApiHttp(s"https://portalpacjenta.luxmed.pl/PatientPortalMobileAPI/api/$url")
|
||||
.headers(CommonHeaders)
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
|
||||
package com.lbs.api
|
||||
|
||||
import cats.implicits.toFunctorOps
|
||||
import com.lbs.api.http._
|
||||
import com.lbs.api.http.headers._
|
||||
import com.lbs.api.json.JsonSerializer.extensions._
|
||||
import com.lbs.api.json.model.{EventsResponse, TermsIndexResponse, _}
|
||||
import com.lbs.api.json.model._
|
||||
import scalaj.http.{HttpRequest, HttpResponse}
|
||||
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.{LocalDateTime, ZonedDateTime}
|
||||
import scala.language.higherKinds
|
||||
|
||||
class LuxmedApi[F[_]: ThrowableMonad] extends ApiBase {
|
||||
|
||||
@@ -18,13 +16,13 @@ class LuxmedApi[F[_] : ThrowableMonad] extends ApiBase {
|
||||
private val dateFormatEvents = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||
|
||||
def login(username: String, password: String, clientId: String = "iPhone"): F[HttpResponse[LoginResponse]] = {
|
||||
val request = httpUnauthorized("token").
|
||||
header(`Content-Type`, "application/x-www-form-urlencoded").
|
||||
header(`x-api-client-identifier`, clientId).
|
||||
param("client_id", clientId).
|
||||
param("grant_type", "password").
|
||||
param("password", password).
|
||||
param("username", username)
|
||||
val request = httpUnauthorized("token")
|
||||
.header(`Content-Type`, "application/x-www-form-urlencoded")
|
||||
.header(`x-api-client-identifier`, clientId)
|
||||
.param("client_id", clientId)
|
||||
.param("grant_type", "password")
|
||||
.param("password", password)
|
||||
.param("username", username)
|
||||
post[LoginResponse](request)
|
||||
}
|
||||
|
||||
@@ -39,99 +37,136 @@ class LuxmedApi[F[_] : ThrowableMonad] extends ApiBase {
|
||||
get[ForgeryTokenResponse](request)
|
||||
}
|
||||
|
||||
def events(session: Session, fromDate: ZonedDateTime = ZonedDateTime.now().minusYears(1),
|
||||
toDate: ZonedDateTime = ZonedDateTime.now()): F[EventsResponse] = {
|
||||
val request = http("Events", session).
|
||||
header(`Content-Type`, "application/json").
|
||||
param("filter.filterDateFrom", dateFormatEvents.format(fromDate)).
|
||||
param("filter.filterDateTo", dateFormatEvents.format(toDate))
|
||||
def events(
|
||||
session: Session,
|
||||
fromDate: ZonedDateTime = ZonedDateTime.now().minusYears(1),
|
||||
toDate: ZonedDateTime = ZonedDateTime.now()
|
||||
): F[EventsResponse] = {
|
||||
val request = http("Events", session)
|
||||
.header(`Content-Type`, "application/json")
|
||||
.param("filter.filterDateFrom", dateFormatEvents.format(fromDate))
|
||||
.param("filter.filterDateTo", dateFormatEvents.format(toDate))
|
||||
get[EventsResponse](request).map(_.body)
|
||||
}
|
||||
|
||||
def dictionaryCities(session: Session): F[List[DictionaryCity]] = {
|
||||
val request = httpNewApi("NewPortal/Dictionary/cities", session).
|
||||
header(`Content-Type`, "application/json")
|
||||
val request = httpNewApi("NewPortal/Dictionary/cities", session).header(`Content-Type`, "application/json")
|
||||
getList[DictionaryCity](request).map(_.body)
|
||||
}
|
||||
|
||||
def dictionaryServiceVariants(session: Session): F[List[DictionaryServiceVariants]] = {
|
||||
val request = httpNewApi("NewPortal/Dictionary/serviceVariantsGroups", session).
|
||||
header(`Content-Type`, "application/json")
|
||||
val request =
|
||||
httpNewApi("NewPortal/Dictionary/serviceVariantsGroups", session).header(`Content-Type`, "application/json")
|
||||
getList[DictionaryServiceVariants](request).map(_.body)
|
||||
}
|
||||
|
||||
def dictionaryFacilitiesAndDoctors(session: Session, cityId: Option[Long], serviceVariantId: Option[Long]): F[FacilitiesAndDoctors] = {
|
||||
val request = httpNewApi("NewPortal/Dictionary/facilitiesAndDoctors", session).
|
||||
header(`Content-Type`, "application/json").
|
||||
param("cityId", cityId.map(_.toString)).
|
||||
param("serviceVariantId", serviceVariantId.map(_.toString))
|
||||
def dictionaryFacilitiesAndDoctors(
|
||||
session: Session,
|
||||
cityId: Option[Long],
|
||||
serviceVariantId: Option[Long]
|
||||
): F[FacilitiesAndDoctors] = {
|
||||
val request = httpNewApi("NewPortal/Dictionary/facilitiesAndDoctors", session)
|
||||
.header(`Content-Type`, "application/json")
|
||||
.param("cityId", cityId.map(_.toString))
|
||||
.param("serviceVariantId", serviceVariantId.map(_.toString))
|
||||
get[FacilitiesAndDoctors](request).map(_.body)
|
||||
}
|
||||
|
||||
def termsIndex(session: Session, cityId: Long, clinicId: Option[Long], serviceId: Long, doctorId: Option[Long],
|
||||
fromDate: LocalDateTime = LocalDateTime.now(), toDate: LocalDateTime, languageId: Long = 10): F[TermsIndexResponse] = {
|
||||
val request = httpNewApi("NewPortal/terms/index", session).
|
||||
header(`Content-Type`, "application/json").
|
||||
param("cityId", cityId.toString).
|
||||
param("serviceVariantId", serviceId.toString).
|
||||
param("languageId", languageId.toString).
|
||||
param("searchDateFrom", dateFormatNewPortal.format(fromDate)).
|
||||
param("searchDateTo", dateFormatNewPortal.format(toDate)).
|
||||
param("searchDatePreset", 14.toString).
|
||||
param("facilitiesIds", clinicId.map(_.toString)).
|
||||
param("doctorsIds", doctorId.map(_.toString)).
|
||||
param("nextSearch", false.toString).
|
||||
param("searchByMedicalSpecialist", false.toString)
|
||||
def termsIndex(
|
||||
session: Session,
|
||||
cityId: Long,
|
||||
clinicId: Option[Long],
|
||||
serviceId: Long,
|
||||
doctorId: Option[Long],
|
||||
fromDate: LocalDateTime = LocalDateTime.now(),
|
||||
toDate: LocalDateTime,
|
||||
languageId: Long = 10
|
||||
): F[TermsIndexResponse] = {
|
||||
val request = httpNewApi("NewPortal/terms/index", session)
|
||||
.header(`Content-Type`, "application/json")
|
||||
.param("cityId", cityId.toString)
|
||||
.param("serviceVariantId", serviceId.toString)
|
||||
.param("languageId", languageId.toString)
|
||||
.param("searchDateFrom", dateFormatNewPortal.format(fromDate))
|
||||
.param("searchDateTo", dateFormatNewPortal.format(toDate))
|
||||
.param("searchDatePreset", 14.toString)
|
||||
.param("facilitiesIds", clinicId.map(_.toString))
|
||||
.param("doctorsIds", doctorId.map(_.toString))
|
||||
.param("nextSearch", false.toString)
|
||||
.param("searchByMedicalSpecialist", false.toString)
|
||||
get[TermsIndexResponse](request).map(_.body)
|
||||
}
|
||||
|
||||
def reservationLockterm(session: Session, xsrfToken: XsrfToken, reservationLocktermRequest: ReservationLocktermRequest): F[ReservationLocktermResponse] = {
|
||||
val request = httpNewApi("NewPortal/reservation/lockterm", session, Some(session.cookies ++ xsrfToken.cookies)).
|
||||
header(`Content-Type`, "application/json")
|
||||
def reservationLockterm(
|
||||
session: Session,
|
||||
xsrfToken: XsrfToken,
|
||||
reservationLocktermRequest: ReservationLocktermRequest
|
||||
): F[ReservationLocktermResponse] = {
|
||||
val request = httpNewApi("NewPortal/reservation/lockterm", session, Some(session.cookies ++ xsrfToken.cookies))
|
||||
.header(`Content-Type`, "application/json")
|
||||
.header(`xsrf-token`, xsrfToken.token)
|
||||
post[ReservationLocktermResponse](request, bodyOpt = Some(reservationLocktermRequest)).map(_.body)
|
||||
}
|
||||
|
||||
def deleteTemporaryReservation(session: Session, xsrfToken: XsrfToken, temporaryReservationId: Long): F[Unit] = {
|
||||
val request = httpNewApi(s"NewPortal/reservation/releaseterm?reservationId=$temporaryReservationId", session, Some(session.cookies ++ xsrfToken.cookies)).
|
||||
header(`Content-Type`, "application/json")
|
||||
val request = httpNewApi(
|
||||
s"NewPortal/reservation/releaseterm?reservationId=$temporaryReservationId",
|
||||
session,
|
||||
Some(session.cookies ++ xsrfToken.cookies)
|
||||
)
|
||||
.header(`Content-Type`, "application/json")
|
||||
.header(`xsrf-token`, xsrfToken.token)
|
||||
postVoid(request, bodyOpt = Some(Empty()))
|
||||
}
|
||||
|
||||
def reservationConfirm(session: Session, xsrfToken: XsrfToken, reservationConfirmRequest: ReservationConfirmRequest): F[ReservationConfirmResponse] = {
|
||||
val request = httpNewApi("NewPortal/reservation/confirm", session, Some(session.cookies ++ xsrfToken.cookies)).
|
||||
header(`Content-Type`, "application/json")
|
||||
def reservationConfirm(
|
||||
session: Session,
|
||||
xsrfToken: XsrfToken,
|
||||
reservationConfirmRequest: ReservationConfirmRequest
|
||||
): F[ReservationConfirmResponse] = {
|
||||
val request = httpNewApi("NewPortal/reservation/confirm", session, Some(session.cookies ++ xsrfToken.cookies))
|
||||
.header(`Content-Type`, "application/json")
|
||||
.header(`xsrf-token`, xsrfToken.token)
|
||||
post[ReservationConfirmResponse](request, bodyOpt = Some(reservationConfirmRequest)).map(_.body)
|
||||
}
|
||||
|
||||
def reservationChangeTerm(session: Session, xsrfToken: XsrfToken, reservationChangetermRequest: ReservationChangetermRequest): F[ReservationConfirmResponse] = {
|
||||
val request = httpNewApi("NewPortal/reservation/changeterm", session, Some(session.cookies ++ xsrfToken.cookies)).
|
||||
header(`Content-Type`, "application/json")
|
||||
def reservationChangeTerm(
|
||||
session: Session,
|
||||
xsrfToken: XsrfToken,
|
||||
reservationChangetermRequest: ReservationChangetermRequest
|
||||
): F[ReservationConfirmResponse] = {
|
||||
val request = httpNewApi("NewPortal/reservation/changeterm", session, Some(session.cookies ++ xsrfToken.cookies))
|
||||
.header(`Content-Type`, "application/json")
|
||||
.header(`xsrf-token`, xsrfToken.token)
|
||||
post[ReservationConfirmResponse](request, bodyOpt = Some(reservationChangetermRequest)).map(_.body)
|
||||
}
|
||||
|
||||
def reservationDelete(session: Session, reservationId: Long): F[HttpResponse[String]] = {
|
||||
val request = http(s"events/Visit/$reservationId", session).
|
||||
header(`Content-Type`, "application/json")
|
||||
val request = http(s"events/Visit/$reservationId", session).header(`Content-Type`, "application/json")
|
||||
delete(request)
|
||||
}
|
||||
|
||||
private def get[T <: SerializableJsonObject](request: HttpRequest)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[T]] = {
|
||||
private def get[T <: SerializableJsonObject](
|
||||
request: HttpRequest
|
||||
)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[T]] = {
|
||||
request.invoke.map(r => r.copy(body = r.body.as[T]))
|
||||
}
|
||||
|
||||
private def getList[T <: SerializableJsonObject](request: HttpRequest)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[List[T]]] = {
|
||||
private def getList[T <: SerializableJsonObject](
|
||||
request: HttpRequest
|
||||
)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[List[T]]] = {
|
||||
request.invoke.map(r => r.copy(body = r.body.asList[T]))
|
||||
}
|
||||
|
||||
private def getVoid[T <: SerializableJsonObject](request: HttpRequest)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[Unit]] = {
|
||||
private def getVoid[T <: SerializableJsonObject](
|
||||
request: HttpRequest
|
||||
)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[Unit]] = {
|
||||
request.invoke.map(r => r.copy(body = {}))
|
||||
}
|
||||
|
||||
private def post[T <: SerializableJsonObject](request: HttpRequest, bodyOpt: Option[SerializableJsonObject] = None)(implicit mf: scala.reflect.Manifest[T]): F[HttpResponse[T]] = {
|
||||
private def post[T <: SerializableJsonObject](request: HttpRequest, bodyOpt: Option[SerializableJsonObject] = None)(
|
||||
implicit mf: scala.reflect.Manifest[T]
|
||||
): F[HttpResponse[T]] = {
|
||||
val postRequest = bodyOpt match {
|
||||
case Some(body) => request.postData(body.asJson)
|
||||
case None => request.postForm
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.exception
|
||||
|
||||
abstract class ApiException(message: String) extends Exception(s"Luxmed API exception: $message")
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.exception
|
||||
|
||||
case class GenericException(code: Int, message: String) extends ApiException(message) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.exception
|
||||
|
||||
class InvalidLoginOrPasswordException extends ApiException("Invalid login or password")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.exception
|
||||
|
||||
class SessionExpiredException extends ApiException("Session expired")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api
|
||||
|
||||
import cats.MonadError
|
||||
@@ -75,7 +74,9 @@ package object http extends StrictLogging {
|
||||
code match {
|
||||
case HttpURLConnection.HTTP_MOVED_TEMP if httpResponse.header("Location").exists(_.contains("/LogOn")) =>
|
||||
Some(new SessionExpiredException)
|
||||
case HttpURLConnection.HTTP_CONFLICT if lowercasedBody.contains("nieprawidłowy login lub hasło") || lowercasedBody.contains("invalid login or password") =>
|
||||
case HttpURLConnection.HTTP_CONFLICT
|
||||
if lowercasedBody
|
||||
.contains("nieprawidłowy login lub hasło") || lowercasedBody.contains("invalid login or password") =>
|
||||
Some(new InvalidLoginOrPasswordException)
|
||||
case _ =>
|
||||
Try(body.as[LuxmedErrorsMap])
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.json
|
||||
|
||||
import com.lbs.api.json.model.{LuxmedFunnyDateTime, SerializableJsonObject}
|
||||
@@ -10,43 +9,58 @@ import java.time.format.DateTimeFormatter
|
||||
import java.time.{LocalDateTime, LocalTime, ZonedDateTime}
|
||||
import scala.util.Try
|
||||
|
||||
|
||||
object JsonSerializer extends StrictLogging {
|
||||
|
||||
private val zonedDateTimeSerializer = new CustomSerializer[ZonedDateTime](_ => ( {
|
||||
case JString(str) => ZonedDateTime.parse(str, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
|
||||
}, {
|
||||
case zonedDateTime: ZonedDateTime => JString(zonedDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME))
|
||||
private val zonedDateTimeSerializer = new CustomSerializer[ZonedDateTime](_ =>
|
||||
(
|
||||
{ case JString(str) =>
|
||||
ZonedDateTime.parse(str, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
|
||||
},
|
||||
{ case zonedDateTime: ZonedDateTime =>
|
||||
JString(zonedDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME))
|
||||
}
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private val localTimeSerializer = new CustomSerializer[LocalTime](_ => ( {
|
||||
case JString(str) => LocalTime.parse(str)
|
||||
}, {
|
||||
case localTime: LocalTime => JString(localTime.toString)
|
||||
private val localTimeSerializer = new CustomSerializer[LocalTime](_ =>
|
||||
(
|
||||
{ case JString(str) =>
|
||||
LocalTime.parse(str)
|
||||
},
|
||||
{ case localTime: LocalTime =>
|
||||
JString(localTime.toString)
|
||||
}
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private val localDateTimeSerializer = new CustomSerializer[LocalDateTime](_ => ( {
|
||||
case JString(str) => LocalDateTime.parse(str)
|
||||
}, {
|
||||
case localTime: LocalDateTime => JString(localTime.toString)
|
||||
private val localDateTimeSerializer = new CustomSerializer[LocalDateTime](_ =>
|
||||
(
|
||||
{ case JString(str) =>
|
||||
LocalDateTime.parse(str)
|
||||
},
|
||||
{ case localTime: LocalDateTime =>
|
||||
JString(localTime.toString)
|
||||
}
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private val luxmedFunnyDateTimeSerializer = new CustomSerializer[LuxmedFunnyDateTime](_ => ( {
|
||||
case JString(str) =>
|
||||
private val luxmedFunnyDateTimeSerializer = new CustomSerializer[LuxmedFunnyDateTime](_ =>
|
||||
(
|
||||
{ case JString(str) =>
|
||||
Try(LocalDateTime.parse(str))
|
||||
.map(v => LuxmedFunnyDateTime(dateTimeLocal = Some(v)))
|
||||
.recoverWith { case _ => Try(ZonedDateTime.parse(str)).map(v => LuxmedFunnyDateTime(dateTimeTz = Some(v))) }
|
||||
.getOrElse(sys.error(s"can't parse date $str"))
|
||||
}, {
|
||||
},
|
||||
{
|
||||
case time: LocalDateTime => JString(time.toString)
|
||||
case time: ZonedDateTime => JString(time.toString)
|
||||
}
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private implicit val formats: Formats = DefaultFormats.withStrictArrayExtraction + zonedDateTimeSerializer + localTimeSerializer + localDateTimeSerializer + luxmedFunnyDateTimeSerializer
|
||||
private implicit val formats: Formats =
|
||||
DefaultFormats.withStrictArrayExtraction + zonedDateTimeSerializer + localTimeSerializer + localDateTimeSerializer + luxmedFunnyDateTimeSerializer
|
||||
|
||||
def extract[T](jsonString: String)(implicit mf: scala.reflect.Manifest[T]): T = {
|
||||
parse(jsonString).camelizeKeys.extract[T]
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
[
|
||||
{
|
||||
"id": 70,
|
||||
"name": "Białystok"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Bielsk Podlaski"
|
||||
},
|
||||
{
|
||||
"id": 100,
|
||||
"name": "Bielsko-Biała"
|
||||
}
|
||||
]
|
||||
*
|
||||
* [
|
||||
* {
|
||||
* "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
|
||||
case class DictionaryCity(override val id: Long, override val name: String)
|
||||
extends Identified
|
||||
with SerializableJsonObject
|
||||
|
||||
@@ -1,175 +1,181 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
[
|
||||
{
|
||||
"actionCode": "",
|
||||
"children": [
|
||||
{
|
||||
"actionCode": null,
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 4502,
|
||||
"isTelemedicine": false,
|
||||
"name": "Consultation with a general practitioner",
|
||||
"paymentType": 2,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"actionCode": null,
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 4480,
|
||||
"isTelemedicine": false,
|
||||
"name": "Gynaecological consultation",
|
||||
"paymentType": 2,
|
||||
"type": 0
|
||||
}
|
||||
],
|
||||
"expanded": true,
|
||||
"id": 2,
|
||||
"isTelemedicine": false,
|
||||
"name": "Most popular",
|
||||
"paymentType": 0,
|
||||
"type": 2
|
||||
},
|
||||
{
|
||||
"actionCode": "",
|
||||
"children": [
|
||||
{
|
||||
"actionCode": null,
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 4387,
|
||||
"isTelemedicine": false,
|
||||
"name": "Allergologist consultation",
|
||||
"paymentType": 2,
|
||||
"type": 0
|
||||
}
|
||||
],
|
||||
"expanded": true,
|
||||
"id": 1,
|
||||
"isTelemedicine": false,
|
||||
"name": "On-site consultations",
|
||||
"paymentType": 0,
|
||||
"type": 1
|
||||
},
|
||||
{
|
||||
"actionCode": "",
|
||||
"children": [
|
||||
{
|
||||
"actionCode": null,
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 13764,
|
||||
"isTelemedicine": true,
|
||||
"name": "Telephone consultation - Allergist",
|
||||
"paymentType": 2,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"actionCode": null,
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 13775,
|
||||
"isTelemedicine": true,
|
||||
"name": "Telephone consultation - Cardiologist",
|
||||
"paymentType": 2,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"actionCode": null,
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 13800,
|
||||
"isTelemedicine": true,
|
||||
"name": "Telephone consultation - Dentist",
|
||||
"paymentType": 2,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"actionCode": null,
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 13766,
|
||||
"isTelemedicine": true,
|
||||
"name": "Telephone consultation - Dermatologist",
|
||||
"paymentType": 2,
|
||||
"type": 0
|
||||
}
|
||||
],
|
||||
"expanded": false,
|
||||
"id": 13,
|
||||
"isTelemedicine": false,
|
||||
"name": "Telephone consultations",
|
||||
"paymentType": 0,
|
||||
"type": 1
|
||||
},
|
||||
{
|
||||
"actionCode": "",
|
||||
"children": [
|
||||
{
|
||||
"actionCode": null,
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 8904,
|
||||
"isTelemedicine": false,
|
||||
"name": "Arranging an appointment with a dental surgeon",
|
||||
"paymentType": 2,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"actionCode": null,
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 6817,
|
||||
"isTelemedicine": false,
|
||||
"name": "Arranging an appointment with a dental hygienist",
|
||||
"paymentType": 2,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"actionCode": null,
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 6621,
|
||||
"isTelemedicine": false,
|
||||
"name": "Arranging an appointment with a dentist",
|
||||
"paymentType": 2,
|
||||
"type": 0
|
||||
}
|
||||
],
|
||||
"expanded": false,
|
||||
"id": 4,
|
||||
"isTelemedicine": false,
|
||||
"name": "Dentist",
|
||||
"paymentType": 0,
|
||||
"type": 1
|
||||
},
|
||||
{
|
||||
"actionCode": "WIZYTY_DOMOWE",
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 14,
|
||||
"isTelemedicine": false,
|
||||
"name": "Home visits",
|
||||
"paymentType": 0,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
"actionCode": "NFZ",
|
||||
"children": [],
|
||||
"expanded": false,
|
||||
"id": 12,
|
||||
"isTelemedicine": false,
|
||||
"name": "NHF visits",
|
||||
"paymentType": 0,
|
||||
"type": 0
|
||||
}
|
||||
]
|
||||
*
|
||||
* [
|
||||
* {
|
||||
* "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 {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -2,18 +2,25 @@ package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
* {
|
||||
"academicTitle": "dr n. med.",
|
||||
"facilityGroupIds": [
|
||||
78
|
||||
],
|
||||
"firstName": "TARAS",
|
||||
"id": 11111,
|
||||
"isEnglishSpeaker": true,
|
||||
"lastName": "SHEVCHENKO"
|
||||
}
|
||||
* "academicTitle": "dr n. med.",
|
||||
* "facilityGroupIds": [
|
||||
* 78
|
||||
* ],
|
||||
* "firstName": "TARAS",
|
||||
* "id": 11111,
|
||||
* "isEnglishSpeaker": true,
|
||||
* "lastName": "SHEVCHENKO"
|
||||
* }
|
||||
*/
|
||||
|
||||
case class Doctor(academicTitle: String, facilityGroupIds: Option[List[Long]], firstName: String, isEnglishSpeaker: Option[Boolean],
|
||||
genderId: Option[Long], id: Long, lastName: String) extends Identified {
|
||||
case class Doctor(
|
||||
academicTitle: String,
|
||||
facilityGroupIds: Option[List[Long]],
|
||||
firstName: String,
|
||||
isEnglishSpeaker: Option[Boolean],
|
||||
genderId: Option[Long],
|
||||
id: Long,
|
||||
lastName: String
|
||||
) extends Identified {
|
||||
override def name: String = firstName + " " + lastName
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
{}
|
||||
*/
|
||||
/** {} */
|
||||
case class Empty() extends SerializableJsonObject
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
@@ -102,7 +101,14 @@ import java.time.ZonedDateTime
|
||||
*/
|
||||
case class EventsResponse(events: List[Event]) extends SerializableJsonObject
|
||||
|
||||
case class Event(date: ZonedDateTime, clinic: Option[EventClinic], doctor: EventDoctor, eventId: Long, status: String, title: String)
|
||||
case class Event(
|
||||
date: ZonedDateTime,
|
||||
clinic: Option[EventClinic],
|
||||
doctor: EventDoctor,
|
||||
eventId: Long,
|
||||
status: String,
|
||||
title: String
|
||||
)
|
||||
|
||||
case class EventClinic(address: String, city: String)
|
||||
|
||||
|
||||
@@ -1,42 +1,40 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
{
|
||||
"doctors": [
|
||||
{
|
||||
"academicTitle": "dr n. med.",
|
||||
"facilityGroupIds": [
|
||||
78
|
||||
],
|
||||
"firstName": "TARAS",
|
||||
"id": 111111,
|
||||
"isEnglishSpeaker": true,
|
||||
"lastName": "SHEVCHENKO"
|
||||
},
|
||||
{
|
||||
"academicTitle": "lek. med.",
|
||||
"facilityGroupIds": [
|
||||
78,
|
||||
127
|
||||
],
|
||||
"firstName": "VLADIMIR",
|
||||
"id": 22222,
|
||||
"isEnglishSpeaker": false,
|
||||
"lastName": "ZELENSKIY"
|
||||
}
|
||||
],
|
||||
"facilities": [
|
||||
{
|
||||
"id": 78,
|
||||
"name": "ul. Fabryczna 6"
|
||||
},
|
||||
{
|
||||
"id": 127,
|
||||
"name": "ul. Kwidzyńska 6"
|
||||
}
|
||||
]
|
||||
}
|
||||
*
|
||||
* {
|
||||
* "doctors": [
|
||||
* {
|
||||
* "academicTitle": "dr n. med.",
|
||||
* "facilityGroupIds": [
|
||||
* 78
|
||||
* ],
|
||||
* "firstName": "TARAS",
|
||||
* "id": 111111,
|
||||
* "isEnglishSpeaker": true,
|
||||
* "lastName": "SHEVCHENKO"
|
||||
* },
|
||||
* {
|
||||
* "academicTitle": "lek. med.",
|
||||
* "facilityGroupIds": [
|
||||
* 78,
|
||||
* 127
|
||||
* ],
|
||||
* "firstName": "VLADIMIR",
|
||||
* "id": 22222,
|
||||
* "isEnglishSpeaker": false,
|
||||
* "lastName": "ZELENSKIY"
|
||||
* }
|
||||
* ],
|
||||
* "facilities": [
|
||||
* {
|
||||
* "id": 78,
|
||||
* "name": "ul. Fabryczna 6"
|
||||
* },
|
||||
* {
|
||||
* "id": 127,
|
||||
* "name": "ul. Kwidzyńska 6"
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
case class FacilitiesAndDoctors(doctors: List[Doctor], facilities: List[IdName]) extends SerializableJsonObject
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
@@ -9,4 +8,5 @@ package com.lbs.api.json.model
|
||||
* "token_type": "bearer"
|
||||
* }
|
||||
*/
|
||||
case class LoginResponse(accessToken: String, expiresIn: Int, refreshToken: String, tokenType: String) extends SerializableJsonObject
|
||||
case class LoginResponse(accessToken: String, expiresIn: Int, refreshToken: String, tokenType: String)
|
||||
extends SerializableJsonObject
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
trait LuxmedBaseError {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
case class LuxmedError(message: String) extends SerializableJsonObject with LuxmedBaseError
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
case class LuxmedErrorsMap(errors: Map[String, List[String]]) extends SerializableJsonObject with LuxmedBaseError {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.LocalTime
|
||||
@@ -34,10 +33,19 @@ import java.time.LocalTime
|
||||
* },
|
||||
* "valuationId": null
|
||||
* }
|
||||
*}
|
||||
*/
|
||||
case class ReservationChangetermRequest(existingReservationId: Long, term: NewTerm) extends SerializableJsonObject
|
||||
|
||||
case class NewTerm(date: String, doctorId: Long, facilityId: Long, parentReservationId: Long, referralRequired: Boolean, roomId: Long,
|
||||
scheduleId: Long, serviceVariantId: Long, temporaryReservationId: Long, timeFrom: LocalTime,
|
||||
valuation: Valuation) extends SerializableJsonObject
|
||||
case class NewTerm(
|
||||
date: String,
|
||||
doctorId: Long,
|
||||
facilityId: Long,
|
||||
parentReservationId: Long,
|
||||
referralRequired: Boolean,
|
||||
roomId: Long,
|
||||
scheduleId: Long,
|
||||
serviceVariantId: Long,
|
||||
temporaryReservationId: Long,
|
||||
timeFrom: LocalTime,
|
||||
valuation: Valuation
|
||||
) extends SerializableJsonObject
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.LocalTime
|
||||
|
||||
|
||||
/**
|
||||
* {
|
||||
* "date": "2021-05-19T08:00:00.000Z",
|
||||
@@ -34,5 +32,14 @@ import java.time.LocalTime
|
||||
* "valuationId": null
|
||||
* }
|
||||
*/
|
||||
case class ReservationConfirmRequest(date: String, doctorId: Long, facilityId: Long, roomId: Long, scheduleId: Long, serviceVariantId: Long,
|
||||
temporaryReservationId: Long, timeFrom: LocalTime, valuation: Valuation) extends SerializableJsonObject
|
||||
case class ReservationConfirmRequest(
|
||||
date: String,
|
||||
doctorId: Long,
|
||||
facilityId: Long,
|
||||
roomId: Long,
|
||||
scheduleId: Long,
|
||||
serviceVariantId: Long,
|
||||
temporaryReservationId: Long,
|
||||
timeFrom: LocalTime,
|
||||
valuation: Valuation
|
||||
) extends SerializableJsonObject
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
|
||||
/**
|
||||
{
|
||||
"errors": [],
|
||||
"hasErrors": false,
|
||||
"hasWarnings": false,
|
||||
"value": {
|
||||
"canSelfConfirm": false,
|
||||
"eventType": 1,
|
||||
"isTelemedicine": false,
|
||||
"npsToken": "babababa-9282-1662-a525-ababbabaa",
|
||||
"reservationId": 2222222,
|
||||
"serviceInstanceId": 33333333
|
||||
},
|
||||
"warnings": []
|
||||
}
|
||||
* {
|
||||
* "errors": [],
|
||||
* "hasErrors": false,
|
||||
* "hasWarnings": false,
|
||||
* "value": {
|
||||
* "canSelfConfirm": false,
|
||||
* "eventType": 1,
|
||||
* "isTelemedicine": false,
|
||||
* "npsToken": "babababa-9282-1662-a525-ababbabaa",
|
||||
* "reservationId": 2222222,
|
||||
* "serviceInstanceId": 33333333
|
||||
* },
|
||||
* "warnings": []
|
||||
* }
|
||||
*/
|
||||
case class ReservationConfirmResponse(errors: List[String], warnings: List[String], hasErrors: Boolean, hasWarnings: Boolean,
|
||||
value: ReservationConfirmValue) extends SerializableJsonObject
|
||||
case class ReservationConfirmResponse(
|
||||
errors: List[String],
|
||||
warnings: List[String],
|
||||
hasErrors: Boolean,
|
||||
hasWarnings: Boolean,
|
||||
value: ReservationConfirmValue
|
||||
) extends SerializableJsonObject
|
||||
|
||||
case class ReservationConfirmValue(canSelfConfirm: Boolean, eventType: Long, isTelemedicine: Boolean, npsToken: String,
|
||||
reservationId: Long, serviceInstanceId: Long) extends SerializableJsonObject
|
||||
case class ReservationConfirmValue(
|
||||
canSelfConfirm: Boolean,
|
||||
eventType: Long,
|
||||
isTelemedicine: Boolean,
|
||||
npsToken: String,
|
||||
reservationId: Long,
|
||||
serviceInstanceId: Long
|
||||
) extends SerializableJsonObject
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
|
||||
/**
|
||||
* {
|
||||
* "correlationId": "00000000-0000-0000-0000-000000000000",
|
||||
@@ -33,10 +31,24 @@ package com.lbs.api.json.model
|
||||
* "timeTo": "12:15"
|
||||
* }
|
||||
*/
|
||||
case class ReservationLocktermRequest(date: String, doctor: Doctor, doctorId: Long, eReferralId: String = null,
|
||||
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
|
||||
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
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.LocalTime
|
||||
|
||||
|
||||
/**
|
||||
* {
|
||||
* "errors": [],
|
||||
@@ -42,8 +40,7 @@ import java.time.LocalTime
|
||||
* "serviceVariantName": "Consultation with a general practitioner",
|
||||
* "timeFrom": "07:30:00",
|
||||
* "timeTo": "07:45:00"
|
||||
*}
|
||||
*],
|
||||
* }],
|
||||
* "temporaryReservationId": 222222,
|
||||
* "valuations": [
|
||||
* {
|
||||
@@ -64,11 +61,28 @@ import java.time.LocalTime
|
||||
* "warnings": []
|
||||
* }
|
||||
*/
|
||||
case class ReservationLocktermResponse(errors: List[String], warnings: List[String], hasErrors: Boolean, hasWarnings: Boolean,
|
||||
value: ReservationLocktermResponseValue) extends SerializableJsonObject
|
||||
case class ReservationLocktermResponse(
|
||||
errors: List[String],
|
||||
warnings: List[String],
|
||||
hasErrors: Boolean,
|
||||
hasWarnings: Boolean,
|
||||
value: ReservationLocktermResponseValue
|
||||
) extends SerializableJsonObject
|
||||
|
||||
case class ReservationLocktermResponseValue(changeTermAvailable: Boolean, conflictedVisit: Option[String], doctorDetails: Doctor,
|
||||
relatedVisits: List[RelatedVisit], temporaryReservationId: Long, valuations: List[Valuation]) extends SerializableJsonObject
|
||||
case class ReservationLocktermResponseValue(
|
||||
changeTermAvailable: Boolean,
|
||||
conflictedVisit: Option[String],
|
||||
doctorDetails: Doctor,
|
||||
relatedVisits: List[RelatedVisit],
|
||||
temporaryReservationId: Long,
|
||||
valuations: List[Valuation]
|
||||
) extends SerializableJsonObject
|
||||
|
||||
case class RelatedVisit(doctor: Doctor, facilityName: String, isTelemedicine: Boolean, reservationId: Long,
|
||||
timeFrom: LocalTime, timeTo: LocalTime)
|
||||
case class RelatedVisit(
|
||||
doctor: Doctor,
|
||||
facilityName: String,
|
||||
isTelemedicine: Boolean,
|
||||
reservationId: Long,
|
||||
timeFrom: LocalTime,
|
||||
timeTo: LocalTime
|
||||
)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
trait SerializableJsonObject
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
|
||||
package com.lbs.api.json.model
|
||||
|
||||
import java.time.{LocalDateTime, ZonedDateTime}
|
||||
|
||||
/**
|
||||
*
|
||||
* {
|
||||
* "correlationId": "00000000-0000-0000-0000-000000000000",
|
||||
* "pMode": 500,
|
||||
@@ -114,11 +112,11 @@ import java.time.{LocalDateTime, ZonedDateTime}
|
||||
* ]
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*/
|
||||
case class TermsIndexResponse(correlationId: String, termsForService: TermsForService) extends SerializableJsonObject
|
||||
|
||||
case class TermsForService(additionalData: AdditionalData, termsForDays: List[TermsForDay]) extends SerializableJsonObject
|
||||
case class TermsForService(additionalData: AdditionalData, termsForDays: List[TermsForDay])
|
||||
extends SerializableJsonObject
|
||||
|
||||
case class PreparationItem(header: Option[String], text: Option[String])
|
||||
|
||||
@@ -126,13 +124,23 @@ case class AdditionalData(isPreparationRequired: Boolean, preparationItems: List
|
||||
|
||||
case class TermsForDay(day: LuxmedFunnyDateTime, terms: List[Term]) extends SerializableJsonObject
|
||||
|
||||
case class Term(clinic: String, clinicId: Long, dateTimeFrom: LuxmedFunnyDateTime, dateTimeTo: LuxmedFunnyDateTime, doctor: Doctor,
|
||||
impedimentText: String, isAdditional: Boolean, isImpediment: Boolean, isTelemedicine: Boolean, roomId: Long,
|
||||
scheduleId: Long, serviceId: Long) extends SerializableJsonObject
|
||||
case class Term(
|
||||
clinic: String,
|
||||
clinicId: Long,
|
||||
dateTimeFrom: LuxmedFunnyDateTime,
|
||||
dateTimeTo: LuxmedFunnyDateTime,
|
||||
doctor: Doctor,
|
||||
impedimentText: String,
|
||||
isAdditional: Boolean,
|
||||
isImpediment: Boolean,
|
||||
isTelemedicine: Boolean,
|
||||
roomId: Long,
|
||||
scheduleId: Long,
|
||||
serviceId: Long
|
||||
) extends SerializableJsonObject
|
||||
|
||||
case class TermExt(additionalData: AdditionalData, term: Term) extends SerializableJsonObject
|
||||
|
||||
case class LuxmedFunnyDateTime(dateTimeTz: Option[ZonedDateTime] = None, dateTimeLocal: Option[LocalDateTime] = None) {
|
||||
def get: LocalDateTime = dateTimeLocal.getOrElse(dateTimeTz.map(_.toLocalDateTime).get)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,22 +2,30 @@ package com.lbs.api.json.model
|
||||
|
||||
/**
|
||||
* {
|
||||
"alternativePrice": null,
|
||||
"contractId": 555555,
|
||||
"isExternalReferralAllowed": false,
|
||||
"isReferralRequired": false, false,
|
||||
"payerId": 66666,
|
||||
"price": 0.0,
|
||||
"productElementId": 7777777,
|
||||
"productId": 888888,
|
||||
"productInContractId": 9999999,
|
||||
"requireReferralForPP": false,
|
||||
"valuationType": 1
|
||||
}
|
||||
* "alternativePrice": null,
|
||||
* "contractId": 555555,
|
||||
* "isExternalReferralAllowed": false,
|
||||
* "isReferralRequired": false, false,
|
||||
* "payerId": 66666,
|
||||
* "price": 0.0,
|
||||
* "productElementId": 7777777,
|
||||
* "productId": 888888,
|
||||
* "productInContractId": 9999999,
|
||||
* "requireReferralForPP": false,
|
||||
* "valuationType": 1
|
||||
* }
|
||||
*/
|
||||
|
||||
case class Valuation(alternativePrice: Option[String], contractId: Long, isExternalReferralAllowed: Boolean,
|
||||
isReferralRequired: Boolean, payerId: Long, price: Double, productElementId: Option[Long], productId: Long,
|
||||
productInContractId: Long, requireReferralForPP: Boolean, valuationType: Long) {
|
||||
|
||||
}
|
||||
case class Valuation(
|
||||
alternativePrice: Option[String],
|
||||
contractId: Long,
|
||||
isExternalReferralAllowed: Boolean,
|
||||
isReferralRequired: Boolean,
|
||||
payerId: Long,
|
||||
price: Double,
|
||||
productElementId: Option[Long],
|
||||
productId: Long,
|
||||
productInContractId: Long,
|
||||
requireReferralForPP: Boolean,
|
||||
valuationType: Long
|
||||
) {}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs
|
||||
|
||||
import cats.MonadError
|
||||
|
||||
@@ -27,11 +27,17 @@ class ExtendedHttpRequestSpec extends AnyFunSuite with Matchers with MockitoSuga
|
||||
}
|
||||
|
||||
test("error response") {
|
||||
val errorResponse = HttpResponse("""{"Errors":{"ToDate.Date":["'To Date. Date' must be greater than or equal to '06/04/2018 00:00:00'."]}}""", 200, Map())
|
||||
val errorResponse = HttpResponse(
|
||||
"""{"Errors":{"ToDate.Date":["'To Date. Date' must be greater than or equal to '06/04/2018 00:00:00'."]}}""",
|
||||
200,
|
||||
Map()
|
||||
)
|
||||
when(request.asString).thenReturn(errorResponse)
|
||||
val result = invoke(request)
|
||||
|
||||
assert(result == Left(GenericException(200, "'To Date. Date' must be greater than or equal to '06/04/2018 00:00:00'.")))
|
||||
assert(
|
||||
result == Left(GenericException(200, "'To Date. Date' must be greater than or equal to '06/04/2018 00:00:00'."))
|
||||
)
|
||||
}
|
||||
|
||||
private def invoke(request: HttpRequest) = {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot
|
||||
|
||||
import com.lbs.bot.model._
|
||||
@@ -15,7 +14,12 @@ class Bot(telegram: TelegramBot /* other bots */) extends LazyLogging {
|
||||
def sendEditMessage(source: MessageSource, messageId: String, inlineKeyboard: Option[InlineKeyboard]): Unit =
|
||||
resolveAdapter(source).sendEditMessage(source.chatId, messageId, inlineKeyboard)
|
||||
|
||||
def sendEditMessage(source: MessageSource, messageId: String, text: String, inlineKeyboard: Option[InlineKeyboard] = None): Unit =
|
||||
def sendEditMessage(
|
||||
source: MessageSource,
|
||||
messageId: String,
|
||||
text: String,
|
||||
inlineKeyboard: Option[InlineKeyboard] = None
|
||||
): Unit =
|
||||
resolveAdapter(source).sendEditMessage(source.chatId, messageId, text, inlineKeyboard)
|
||||
|
||||
def sendFile(source: MessageSource, filename: String, contents: Array[Byte], caption: Option[String] = None): Unit =
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot
|
||||
|
||||
import com.lbs.bot.model.{Event, InlineKeyboard}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot
|
||||
|
||||
import com.lbs.bot.model.Event
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot.model
|
||||
|
||||
object Button {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot.model
|
||||
|
||||
case class Message(messageId: String, text: Option[String] = None)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot.model
|
||||
|
||||
trait Event
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot.model
|
||||
|
||||
case class InlineKeyboard(buttons: Seq[Seq[Button]])
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot.model
|
||||
|
||||
case class MessageSource(sourceSystem: MessageSourceSystem, chatId: String)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot.model
|
||||
|
||||
trait MessageSourceSystem {
|
||||
@@ -10,10 +9,7 @@ trait MessageSourceSystem {
|
||||
}
|
||||
|
||||
object MessageSourceSystem {
|
||||
val MessageSourceSystems: Seq[MessageSourceSystem] = Seq(
|
||||
TelegramMessageSourceSystem,
|
||||
FacebookMessageSourceSystem
|
||||
)
|
||||
val MessageSourceSystems: Seq[MessageSourceSystem] = Seq(TelegramMessageSourceSystem, FacebookMessageSourceSystem)
|
||||
|
||||
private val MessageSourceSystemsMap = MessageSourceSystems.map(e => e.id -> e).toMap
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs
|
||||
|
||||
import com.lbs.bot.model.{Button, InlineKeyboard}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot.telegram
|
||||
|
||||
import com.bot4s.telegram.models.InlineKeyboardMarkup
|
||||
@@ -18,10 +17,19 @@ class TelegramBot(onCommand: Command => Unit, botToken: String) extends PollBot[
|
||||
telegramBot.sendMessage(chatId.toLong, text, replyMarkup = buttons.map(_.mapTo[InlineKeyboardMarkup]))
|
||||
|
||||
def sendEditMessage(chatId: String, messageId: String, buttons: Option[InlineKeyboard]): Unit =
|
||||
telegramBot.sendEditMessage(chatId.toLong, messageId.toInt, replyMarkup = buttons.map(_.mapTo[InlineKeyboardMarkup]))
|
||||
telegramBot.sendEditMessage(
|
||||
chatId.toLong,
|
||||
messageId.toInt,
|
||||
replyMarkup = buttons.map(_.mapTo[InlineKeyboardMarkup])
|
||||
)
|
||||
|
||||
def sendEditMessage(chatId: String, messageId: String, text: String, buttons: Option[InlineKeyboard] = None): Unit =
|
||||
telegramBot.sendEditMessage(chatId.toLong, messageId.toInt, text, replyMarkup = buttons.map(_.mapTo[InlineKeyboardMarkup]))
|
||||
telegramBot.sendEditMessage(
|
||||
chatId.toLong,
|
||||
messageId.toInt,
|
||||
text,
|
||||
replyMarkup = buttons.map(_.mapTo[InlineKeyboardMarkup])
|
||||
)
|
||||
|
||||
def sendFile(chatId: String, filename: String, contents: Array[Byte], caption: Option[String] = None): Unit =
|
||||
telegramBot.sendFile(chatId.toLong, filename, contents, caption)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot.telegram
|
||||
|
||||
import cats.implicits.toFunctorOps
|
||||
@@ -12,7 +11,13 @@ import com.typesafe.scalalogging.StrictLogging
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) extends AkkaTelegramBot with TelegramBoT with Polling with Commands[Future] with Callbacks[Future] with StrictLogging {
|
||||
class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String)
|
||||
extends AkkaTelegramBot
|
||||
with TelegramBoT
|
||||
with Polling
|
||||
with Commands[Future]
|
||||
with Callbacks[Future]
|
||||
with StrictLogging {
|
||||
|
||||
override val client: RequestHandler[Future] = new AkkaHttpClient(botToken)
|
||||
|
||||
@@ -22,11 +27,28 @@ class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) extends
|
||||
def sendMessage(chatId: Long, text: String, replyMarkup: Option[InlineKeyboardMarkup] = None): Future[Message] =
|
||||
loggingRequest(SendMessage(chatId, text, parseMode = Some(ParseMode.HTML), replyMarkup = replyMarkup))
|
||||
|
||||
def sendEditMessage(chatId: Long, messageId: Int, replyMarkup: Option[InlineKeyboardMarkup]): Future[Either[Boolean, Message]] =
|
||||
def sendEditMessage(
|
||||
chatId: Long,
|
||||
messageId: Int,
|
||||
replyMarkup: Option[InlineKeyboardMarkup]
|
||||
): Future[Either[Boolean, Message]] =
|
||||
loggingRequest(EditMessageReplyMarkup(Some(chatId), Some(messageId), replyMarkup = replyMarkup))
|
||||
|
||||
def sendEditMessage(chatId: Long, messageId: Int, text: String, replyMarkup: Option[InlineKeyboardMarkup] = None): Future[Either[Boolean, Message]] =
|
||||
loggingRequest(EditMessageText(Some(chatId), Some(messageId), text = text, parseMode = Some(ParseMode.HTML), replyMarkup = replyMarkup))
|
||||
def sendEditMessage(
|
||||
chatId: Long,
|
||||
messageId: Int,
|
||||
text: String,
|
||||
replyMarkup: Option[InlineKeyboardMarkup] = None
|
||||
): Future[Either[Boolean, Message]] =
|
||||
loggingRequest(
|
||||
EditMessageText(
|
||||
Some(chatId),
|
||||
Some(messageId),
|
||||
text = text,
|
||||
parseMode = Some(ParseMode.HTML),
|
||||
replyMarkup = replyMarkup
|
||||
)
|
||||
)
|
||||
|
||||
def sendFile(chatId: Long, filename: String, contents: Array[Byte], caption: Option[String] = None): Future[Message] =
|
||||
loggingRequest(SendDocument(chatId, InputFile(filename, contents), caption = caption))
|
||||
@@ -36,7 +58,6 @@ class TelegramClient(onReceive: TelegramEvent => Unit, botToken: String) extends
|
||||
request(req)
|
||||
}
|
||||
|
||||
|
||||
override def receiveMessage(msg: Message): Future[Unit] = {
|
||||
logger.debug(s"Received telegram message: $msg")
|
||||
Future.successful(onReceive(TelegramEvent(msg, None)))
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot.telegram
|
||||
|
||||
import com.bot4s.telegram.models.Message
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.bot
|
||||
|
||||
import com.bot4s.telegram.models.{InlineKeyboardButton, InlineKeyboardMarkup, Message => BMessage}
|
||||
@@ -10,8 +9,7 @@ package object telegram {
|
||||
protected[bot] val TagPrefix = "callback"
|
||||
|
||||
object TelegramModelConverters extends ModelConverters {
|
||||
implicit val TelegramCommandToCommandConverter:
|
||||
ObjectConverter[TelegramEvent, Command] =
|
||||
implicit val TelegramCommandToCommandConverter: ObjectConverter[TelegramEvent, Command] =
|
||||
(data: TelegramEvent) => {
|
||||
Command(
|
||||
source = MessageSource(TelegramMessageSourceSystem, data.msg.chat.id.toString),
|
||||
@@ -20,14 +18,12 @@ package object telegram {
|
||||
)
|
||||
}
|
||||
|
||||
implicit val TelegramMessageToMessageConverter:
|
||||
ObjectConverter[BMessage, Message] =
|
||||
implicit val TelegramMessageToMessageConverter: ObjectConverter[BMessage, Message] =
|
||||
(data: BMessage) => {
|
||||
Message(data.messageId.toString, data.text)
|
||||
}
|
||||
|
||||
implicit val InlineKeyboardToInlineKeyboardMarkup:
|
||||
ObjectConverter[InlineKeyboard, InlineKeyboardMarkup] =
|
||||
implicit val InlineKeyboardToInlineKeyboardMarkup: ObjectConverter[InlineKeyboard, InlineKeyboardMarkup] =
|
||||
(inlineKeyboard: InlineKeyboard) => {
|
||||
val buttons = inlineKeyboard.buttons.map { row =>
|
||||
row.map(createInlineKeyboardButton)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id "com.github.maiflai.scalatest" version "0.32"
|
||||
id "org.springframework.boot" version "2.7.2"
|
||||
id "cz.alenkacz.gradle.scalafmt" version "1.16.2"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@@ -17,7 +18,7 @@ allprojects {
|
||||
compileOnly "org.scala-lang:scala-library:$scala.$scala_minor"
|
||||
|
||||
testImplementation "org.scalatest:scalatest_$scala:3.2.11"
|
||||
testRuntimeOnly 'com.vladsch.flexmark:flexmark-all:0.62.2' // version depends on scalatest dependency
|
||||
testRuntimeOnly "com.vladsch.flexmark:flexmark-all:0.62.2" // version depends on scalatest dependency
|
||||
|
||||
testImplementation "org.scalatestplus:mockito-4-2_$scala:3.2.11.0"
|
||||
testImplementation "org.pegdown:pegdown:1.6.0"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.common
|
||||
|
||||
import java.util.Optional
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
package com.lbs.common
|
||||
|
||||
import scala.collection.{BuildFrom, IterableOps}
|
||||
import scala.collection.IterableOps
|
||||
import scala.language.implicitConversions
|
||||
|
||||
trait ModelConverters {
|
||||
@@ -14,8 +13,9 @@ trait ModelConverters {
|
||||
def mapTo[To](implicit converter: ObjectConverter[From, To]): To = converter.convert(anyRef)
|
||||
}
|
||||
|
||||
implicit def sequenceConverters[From, To, Col[+X] <: IterableOps[X, Col, Col[X]]]
|
||||
(implicit objectConverter: ObjectConverter[From, To]): ObjectConverter[Col[From], Col[To]] =
|
||||
implicit def sequenceConverters[From, To, Col[+X] <: IterableOps[X, Col, Col[X]]](implicit
|
||||
objectConverter: ObjectConverter[From, To]
|
||||
): ObjectConverter[Col[From], Col[To]] =
|
||||
(col: Col[From]) => col.map(objectConverter.convert)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.common
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.common
|
||||
|
||||
import com.typesafe.scalalogging.LazyLogging
|
||||
@@ -18,8 +17,7 @@ class Scheduler(poolSize: Int) extends LazyLogging {
|
||||
scheduledThreadPool.scheduleAtFixedRate(silentFn(fn), delay.length, period.length, period.unit)
|
||||
}
|
||||
|
||||
private def silentFn(fn: => Unit): Runnable = {
|
||||
() =>
|
||||
private def silentFn(fn: => Unit): Runnable = { () =>
|
||||
try {
|
||||
fn
|
||||
} catch {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
|
||||
package com.lbs.server
|
||||
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
import org.springframework.boot.SpringApplication
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
class Boot
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -44,23 +43,45 @@ class BootConfig {
|
||||
}
|
||||
|
||||
@Bean
|
||||
def authFactory: MessageSourceTo[Auth] = source => new Auth(source,
|
||||
dataService, unauthorizedHelpFactory, loginFactory, chatFactory)(actorSystem)
|
||||
def authFactory: MessageSourceTo[Auth] = source =>
|
||||
new Auth(source, dataService, unauthorizedHelpFactory, loginFactory, chatFactory)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def loginFactory: MessageSourceWithOriginatorTo[Login] = (source, originator) => new Login(source, bot,
|
||||
dataService, apiService, textEncryptor, localization, originator)(actorSystem)
|
||||
def loginFactory: MessageSourceWithOriginatorTo[Login] = (source, originator) =>
|
||||
new Login(source, bot, dataService, apiService, textEncryptor, localization, originator)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def bookFactory: UserIdTo[Book] = userId => new Book(userId, bot, apiService, dataService,
|
||||
monitoringService, localization, datePickerFactory, timePickerFactory, staticDataFactory, termsPagerFactory)(actorSystem)
|
||||
def bookFactory: UserIdTo[Book] = userId =>
|
||||
new Book(
|
||||
userId,
|
||||
bot,
|
||||
apiService,
|
||||
dataService,
|
||||
monitoringService,
|
||||
localization,
|
||||
datePickerFactory,
|
||||
timePickerFactory,
|
||||
staticDataFactory,
|
||||
termsPagerFactory
|
||||
)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def bookWithTemplateFactory: UserIdTo[BookWithTemplate] = userId => new BookWithTemplate(userId, bot, apiService, dataService,
|
||||
monitoringService, localization, datePickerFactory, timePickerFactory, termsPagerFactory)(actorSystem)
|
||||
def bookWithTemplateFactory: UserIdTo[BookWithTemplate] = userId =>
|
||||
new BookWithTemplate(
|
||||
userId,
|
||||
bot,
|
||||
apiService,
|
||||
dataService,
|
||||
monitoringService,
|
||||
localization,
|
||||
datePickerFactory,
|
||||
timePickerFactory,
|
||||
termsPagerFactory
|
||||
)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def unauthorizedHelpFactory: MessageSourceTo[UnauthorizedHelp] = source => new UnauthorizedHelp(source, bot)(actorSystem)
|
||||
def unauthorizedHelpFactory: MessageSourceTo[UnauthorizedHelp] = source =>
|
||||
new UnauthorizedHelp(source, bot)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def helpFactory: UserIdTo[Help] = userId => new Help(userId, bot, localization)(actorSystem)
|
||||
@@ -71,7 +92,15 @@ class BootConfig {
|
||||
|
||||
@Bean
|
||||
def monitoringsHistoryFactory: UserIdTo[MonitoringsHistory] =
|
||||
userId => new MonitoringsHistory(userId, bot, monitoringService, localization, monitoringsHistoryPagerFactory, bookWithTemplateFactory)(actorSystem)
|
||||
userId =>
|
||||
new MonitoringsHistory(
|
||||
userId,
|
||||
bot,
|
||||
monitoringService,
|
||||
localization,
|
||||
monitoringsHistoryPagerFactory,
|
||||
bookWithTemplateFactory
|
||||
)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def historyFactory: UserIdTo[HistoryViewer] =
|
||||
@@ -91,8 +120,20 @@ class BootConfig {
|
||||
|
||||
@Bean
|
||||
def chatFactory: UserIdTo[Chat] =
|
||||
userId => new Chat(userId, dataService, monitoringService, bookFactory, helpFactory,
|
||||
monitoringsFactory, monitoringsHistoryFactory, historyFactory, reservedVisitsFactory, settingsFactory, accountFactory)(actorSystem)
|
||||
userId =>
|
||||
new Chat(
|
||||
userId,
|
||||
dataService,
|
||||
monitoringService,
|
||||
bookFactory,
|
||||
helpFactory,
|
||||
monitoringsFactory,
|
||||
monitoringsHistoryFactory,
|
||||
historyFactory,
|
||||
reservedVisitsFactory,
|
||||
settingsFactory,
|
||||
accountFactory
|
||||
)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def datePickerFactory: UserIdWithOriginatorTo[DatePicker] = (userId, originator) =>
|
||||
@@ -108,39 +149,63 @@ class BootConfig {
|
||||
|
||||
@Bean
|
||||
def termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]] = (userId, originator) =>
|
||||
new Pager[TermExt](userId, bot,
|
||||
new Pager[TermExt](
|
||||
userId,
|
||||
bot,
|
||||
(term: TermExt, page: Int, index: Int) => lang(userId).termEntry(term, page, index),
|
||||
(page: Int, pages: Int) => lang(userId).termsHeader(page, pages),
|
||||
Some("book"), localization, originator)(actorSystem)
|
||||
|
||||
Some("book"),
|
||||
localization,
|
||||
originator
|
||||
)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def reservedVisitsPagerFactory: UserIdWithOriginatorTo[Pager[Event]] = (userId, originator) =>
|
||||
new Pager[Event](userId, bot,
|
||||
new Pager[Event](
|
||||
userId,
|
||||
bot,
|
||||
(visit: Event, page: Int, index: Int) => lang(userId).reservedVisitEntry(visit, page, index),
|
||||
(page: Int, pages: Int) => lang(userId).reservedVisitsHeader(page, pages),
|
||||
Some("cancel"), localization, originator)(actorSystem)
|
||||
Some("cancel"),
|
||||
localization,
|
||||
originator
|
||||
)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def historyPagerFactory: UserIdWithOriginatorTo[Pager[Event]] = (userId, originator) =>
|
||||
new Pager[Event](userId, bot,
|
||||
new Pager[Event](
|
||||
userId,
|
||||
bot,
|
||||
(event: Event, page: Int, index: Int) => lang(userId).historyEntry(event, page, index),
|
||||
(page: Int, pages: Int) => lang(userId).historyHeader(page, pages),
|
||||
None, localization, originator)(actorSystem)
|
||||
None,
|
||||
localization,
|
||||
originator
|
||||
)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def monitoringsPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]] = (userId, originator) =>
|
||||
new Pager[Monitoring](userId, bot,
|
||||
new Pager[Monitoring](
|
||||
userId,
|
||||
bot,
|
||||
(monitoring: Monitoring, page: Int, index: Int) => lang(userId).monitoringEntry(monitoring, page, index),
|
||||
(page: Int, pages: Int) => lang(userId).monitoringsHeader(page, pages),
|
||||
Some("cancel"), localization, originator)(actorSystem)
|
||||
Some("cancel"),
|
||||
localization,
|
||||
originator
|
||||
)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def monitoringsHistoryPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]] = (userId, originator) =>
|
||||
new Pager[Monitoring](userId, bot,
|
||||
new Pager[Monitoring](
|
||||
userId,
|
||||
bot,
|
||||
(monitoring: Monitoring, page: Int, index: Int) => lang(userId).monitoringHistoryEntry(monitoring, page, index),
|
||||
(page: Int, pages: Int) => lang(userId).monitoringsHistoryHeader(page, pages),
|
||||
Some("repeat"), localization, originator)(actorSystem)
|
||||
Some("repeat"),
|
||||
localization,
|
||||
originator
|
||||
)(actorSystem)
|
||||
|
||||
@Bean
|
||||
def router: Router = new Router(authFactory)(actorSystem)
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.bot._
|
||||
import com.lbs.bot.model.Button
|
||||
import com.lbs.bot.{Bot, _}
|
||||
import com.lbs.server.conversation.Account._
|
||||
import com.lbs.server.conversation.Login._
|
||||
import com.lbs.server.conversation.base.Conversation
|
||||
@@ -11,18 +10,28 @@ import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.service.DataService
|
||||
import com.lbs.server.util.MessageExtractors.CallbackCommand
|
||||
|
||||
class Account(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization, router: Router)(val actorSystem: ActorSystem) extends Conversation[Unit] with Localizable {
|
||||
class Account(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization, router: Router)(
|
||||
val actorSystem: ActorSystem
|
||||
) extends Conversation[Unit]
|
||||
with Localizable {
|
||||
|
||||
entryPoint(askAction)
|
||||
|
||||
def askAction: Step =
|
||||
ask { _ =>
|
||||
val credentials = dataService.getUserCredentials(userId.userId)
|
||||
val currentAccount = credentials.find(c => c.accountId == userId.accountId).getOrElse(sys.error("Can't determine current account"))
|
||||
val buttons = Seq(Button(lang.addAccount, Tags.AddAccount), Button(lang.deleteAccount, Tags.DeleteAccount)) ++ credentials.map(c => Button(s"🔐️ ${c.username}", c.accountId))
|
||||
bot.sendMessage(userId.source, lang.pleaseChooseAccount(currentAccount.username), inlineKeyboard = createInlineKeyboard(buttons, columns = 1))
|
||||
} onReply {
|
||||
case Msg(cmd@CallbackCommand(action), _) =>
|
||||
val currentAccount =
|
||||
credentials.find(c => c.accountId == userId.accountId).getOrElse(sys.error("Can't determine current account"))
|
||||
val buttons = Seq(
|
||||
Button(lang.addAccount, Tags.AddAccount),
|
||||
Button(lang.deleteAccount, Tags.DeleteAccount)
|
||||
) ++ credentials.map(c => Button(s"🔐️ ${c.username}", c.accountId))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.pleaseChooseAccount(currentAccount.username),
|
||||
inlineKeyboard = createInlineKeyboard(buttons, columns = 1)
|
||||
)
|
||||
} onReply { case Msg(cmd @ CallbackCommand(action), _) =>
|
||||
action match {
|
||||
case Tags.AddAccount =>
|
||||
router ! cmd.copy(message = cmd.message.copy(text = Some("/login")), callbackData = None)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -9,8 +8,15 @@ import com.lbs.server.service.DataService
|
||||
import com.lbs.server.util.MessageExtractors._
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
|
||||
class Auth(val source: MessageSource, dataService: DataService, unauthorizedHelpFactory: MessageSourceTo[UnauthorizedHelp],
|
||||
loginFactory: MessageSourceWithOriginatorTo[Login], chatFactory: UserIdTo[Chat])(val actorSystem: ActorSystem) extends Conversation[Unit] with StrictLogging {
|
||||
class Auth(
|
||||
val source: MessageSource,
|
||||
dataService: DataService,
|
||||
unauthorizedHelpFactory: MessageSourceTo[UnauthorizedHelp],
|
||||
loginFactory: MessageSourceWithOriginatorTo[Login],
|
||||
chatFactory: UserIdTo[Chat]
|
||||
)(val actorSystem: ActorSystem)
|
||||
extends Conversation[Unit]
|
||||
with StrictLogging {
|
||||
|
||||
private val login = loginFactory(source, self)
|
||||
private val unauthorizedHelp = unauthorizedHelpFactory(source)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -20,9 +19,21 @@ import com.lbs.server.util.ServerModelConverters._
|
||||
|
||||
import java.time.{LocalDateTime, LocalTime}
|
||||
|
||||
class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: DataService, monitoringService: MonitoringService,
|
||||
val localization: Localization, datePickerFactory: UserIdWithOriginatorTo[DatePicker], timePickerFactory: UserIdWithOriginatorTo[TimePicker],
|
||||
staticDataFactory: UserIdWithOriginatorTo[StaticData], termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]])(implicit val actorSystem: ActorSystem) extends Conversation[BookingData] with StaticDataForBooking with Localizable {
|
||||
class Book(
|
||||
val userId: UserId,
|
||||
bot: Bot,
|
||||
apiService: ApiService,
|
||||
dataService: DataService,
|
||||
monitoringService: MonitoringService,
|
||||
val localization: Localization,
|
||||
datePickerFactory: UserIdWithOriginatorTo[DatePicker],
|
||||
timePickerFactory: UserIdWithOriginatorTo[TimePicker],
|
||||
staticDataFactory: UserIdWithOriginatorTo[StaticData],
|
||||
termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]]
|
||||
)(implicit val actorSystem: ActorSystem)
|
||||
extends Conversation[BookingData]
|
||||
with StaticDataForBooking
|
||||
with Localizable {
|
||||
|
||||
private val datePicker = datePickerFactory(userId, self)
|
||||
private val timePicker = timePickerFactory(userId, self)
|
||||
@@ -36,7 +47,8 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
withFunctions[DictionaryCity](
|
||||
latestOptions = dataService.getLatestCities(userId.accountId),
|
||||
staticOptions = apiService.getAllCities(userId.accountId),
|
||||
applyId = id => bd.copy(cityId = id.toIdName))
|
||||
applyId = id => bd.copy(cityId = id.toIdName)
|
||||
)
|
||||
}(requestNext = askService)
|
||||
|
||||
private def askService: Step =
|
||||
@@ -44,7 +56,8 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
withFunctions[DictionaryServiceVariants](
|
||||
latestOptions = dataService.getLatestServicesByCityIdAndClinicId(userId.accountId, bd.cityId.id, None),
|
||||
staticOptions = apiService.getAllServices(userId.accountId),
|
||||
applyId = id => bd.copy(serviceId = id.toIdName))
|
||||
applyId = id => bd.copy(serviceId = id.toIdName)
|
||||
)
|
||||
}(requestNext = askClinic)
|
||||
|
||||
private def askClinic: Step =
|
||||
@@ -52,17 +65,27 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
withFunctions[IdName](
|
||||
latestOptions = dataService.getLatestClinicsByCityId(userId.accountId, bd.cityId.id),
|
||||
staticOptions = apiService.getAllFacilities(userId.accountId, bd.cityId.id, bd.serviceId.id),
|
||||
applyId = id => bd.copy(clinicId = id))
|
||||
applyId = id => bd.copy(clinicId = id)
|
||||
)
|
||||
}(requestNext = askDoctor)
|
||||
|
||||
private def askDoctor: Step =
|
||||
staticData(doctorConfig) { bd: BookingData =>
|
||||
withFunctions[IdName](
|
||||
latestOptions = dataService.getLatestDoctorsByCityIdAndClinicIdAndServiceId(userId.accountId, bd.cityId.id, bd.clinicId.optionalId, bd.serviceId.id),
|
||||
staticOptions = apiService.getAllDoctors(userId.accountId, bd.cityId.id, bd.serviceId.id)
|
||||
.map(_.filterNot(_.facilityGroupIds.exists(z => bd.clinicId == null || z.contains(bd.clinicId.id)))
|
||||
.map(_.toIdName)),
|
||||
applyId = id => bd.copy(doctorId = id.toIdName))
|
||||
latestOptions = dataService.getLatestDoctorsByCityIdAndClinicIdAndServiceId(
|
||||
userId.accountId,
|
||||
bd.cityId.id,
|
||||
bd.clinicId.optionalId,
|
||||
bd.serviceId.id
|
||||
),
|
||||
staticOptions = apiService
|
||||
.getAllDoctors(userId.accountId, bd.cityId.id, bd.serviceId.id)
|
||||
.map(
|
||||
_.filterNot(_.facilityGroupIds.exists(z => bd.clinicId == null || z.contains(bd.clinicId.id)))
|
||||
.map(_.toIdName)
|
||||
),
|
||||
applyId = id => bd.copy(doctorId = id.toIdName)
|
||||
)
|
||||
}(requestNext = requestDateFrom)
|
||||
|
||||
private def requestDateFrom: Step =
|
||||
@@ -120,24 +143,35 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
private def requestAction: Step =
|
||||
ask { bookingData =>
|
||||
dataService.storeAppointment(userId.accountId, bookingData)
|
||||
bot.sendMessage(userId.source,
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.bookingSummary(bookingData),
|
||||
inlineKeyboard = createInlineKeyboard(
|
||||
Seq(Button(lang.findTerms, Tags.FindTerms), Button(lang.modifyDate, Tags.ModifyDate))
|
||||
))
|
||||
inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.findTerms, Tags.FindTerms), Button(lang.modifyDate, Tags.ModifyDate)))
|
||||
)
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(Tags.FindTerms), _) =>
|
||||
goto(requestTerm)
|
||||
case Msg(CallbackCommand(Tags.ModifyDate), bookingData) =>
|
||||
goto(requestDateFrom) using bookingData.copy(dateFrom = LocalDateTime.now(),
|
||||
dateTo = LocalDateTime.now().plusDays(1L))
|
||||
goto(requestDateFrom) using bookingData.copy(
|
||||
dateFrom = LocalDateTime.now(),
|
||||
dateTo = LocalDateTime.now().plusDays(1L)
|
||||
)
|
||||
}
|
||||
|
||||
private def requestTerm: Step =
|
||||
ask { bookingData =>
|
||||
val availableTerms = apiService.getAvailableTerms(userId.accountId, bookingData.cityId.id,
|
||||
bookingData.clinicId.optionalId, bookingData.serviceId.id, bookingData.doctorId.optionalId,
|
||||
bookingData.dateFrom, bookingData.dateTo, timeFrom = bookingData.timeFrom, timeTo = bookingData.timeTo)
|
||||
val availableTerms = apiService.getAvailableTerms(
|
||||
userId.accountId,
|
||||
bookingData.cityId.id,
|
||||
bookingData.clinicId.optionalId,
|
||||
bookingData.serviceId.id,
|
||||
bookingData.doctorId.optionalId,
|
||||
bookingData.dateFrom,
|
||||
bookingData.dateTo,
|
||||
timeFrom = bookingData.timeFrom,
|
||||
timeTo = bookingData.timeTo
|
||||
)
|
||||
termsPager.restart()
|
||||
termsPager ! availableTerms.map(new SimpleItemsProvider(_))
|
||||
} onReply {
|
||||
@@ -147,7 +181,11 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
case Msg(term: TermExt, bookingData) =>
|
||||
val response = for {
|
||||
xsrfToken <- apiService.getXsrfToken(userId.accountId)
|
||||
lockTermResponse <- apiService.reservationLockterm(userId.accountId, xsrfToken, term.mapTo[ReservationLocktermRequest])
|
||||
lockTermResponse <- apiService.reservationLockterm(
|
||||
userId.accountId,
|
||||
xsrfToken,
|
||||
term.mapTo[ReservationLocktermRequest]
|
||||
)
|
||||
} yield (lockTermResponse, xsrfToken)
|
||||
response match {
|
||||
case Left(ex) =>
|
||||
@@ -157,13 +195,28 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
case Right((reservationLocktermResponse, xsrfToken)) =>
|
||||
if (reservationLocktermResponse.value.changeTermAvailable) {
|
||||
logger.warn(s"Service [${bookingData.serviceId.name}] is already booked. Ask to update term")
|
||||
bot.sendMessage(userId.source, lang.visitAlreadyExists,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))))
|
||||
goto(awaitRebookDecision) using bookingData.copy(term = Some(term), xsrfToken = Some(xsrfToken), reservationLocktermResponse = Some(reservationLocktermResponse))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.visitAlreadyExists,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))
|
||||
)
|
||||
goto(awaitRebookDecision) using bookingData.copy(
|
||||
term = Some(term),
|
||||
xsrfToken = Some(xsrfToken),
|
||||
reservationLocktermResponse = Some(reservationLocktermResponse)
|
||||
)
|
||||
} else {
|
||||
bot.sendMessage(userId.source, lang.confirmAppointment(term),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book))))
|
||||
goto(awaitReservation) using bookingData.copy(term = Some(term), xsrfToken = Some(xsrfToken), reservationLocktermResponse = Some(reservationLocktermResponse))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.confirmAppointment(term),
|
||||
inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book)))
|
||||
)
|
||||
goto(awaitReservation) using bookingData.copy(
|
||||
term = Some(term),
|
||||
xsrfToken = Some(xsrfToken),
|
||||
reservationLocktermResponse = Some(reservationLocktermResponse)
|
||||
)
|
||||
}
|
||||
}
|
||||
case Msg(Pager.NoItemsFound, _) =>
|
||||
@@ -172,12 +225,19 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
private def askNoTermsAction: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(userId.source, lang.noTermsFound, inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.modifyDate, Tags.ModifyDate), Button(lang.createMonitoring, Tags.CreateMonitoring))))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.noTermsFound,
|
||||
inlineKeyboard = createInlineKeyboard(
|
||||
Seq(Button(lang.modifyDate, Tags.ModifyDate), Button(lang.createMonitoring, Tags.CreateMonitoring))
|
||||
)
|
||||
)
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(Tags.ModifyDate), bookingData) =>
|
||||
goto(requestDateFrom) using bookingData.copy(dateFrom = LocalDateTime.now(),
|
||||
dateTo = LocalDateTime.now().plusDays(1L))
|
||||
goto(requestDateFrom) using bookingData.copy(
|
||||
dateFrom = LocalDateTime.now(),
|
||||
dateTo = LocalDateTime.now().plusDays(1L)
|
||||
)
|
||||
case Msg(CallbackCommand(Tags.CreateMonitoring), bookingData) =>
|
||||
val settingsMaybe = dataService.findSettings(userId.userId)
|
||||
val (defaultOffset, askOffset) = settingsMaybe match {
|
||||
@@ -192,8 +252,11 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
private def awaitRebookDecision: Step =
|
||||
monologue {
|
||||
case Msg(CallbackCommand(Tags.Yes), bookingData: BookingData) =>
|
||||
apiService.reservationChangeTerm(userId.accountId, bookingData.xsrfToken.get,
|
||||
(bookingData.reservationLocktermResponse.get, bookingData.term.get).mapTo[ReservationChangetermRequest]) match {
|
||||
apiService.reservationChangeTerm(
|
||||
userId.accountId,
|
||||
bookingData.xsrfToken.get,
|
||||
(bookingData.reservationLocktermResponse.get, bookingData.term.get).mapTo[ReservationChangetermRequest]
|
||||
) match {
|
||||
case Right(success) =>
|
||||
logger.debug(s"Successfully confirmed: $success")
|
||||
bot.sendMessage(userId.source, lang.appointmentIsConfirmed)
|
||||
@@ -210,7 +273,11 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
private def awaitReservation: Step =
|
||||
monologue {
|
||||
case Msg(CallbackCommand(Tags.Cancel), bookingData: BookingData) =>
|
||||
apiService.deleteTemporaryReservation(userId.accountId, bookingData.xsrfToken.get, bookingData.reservationLocktermResponse.get.value.temporaryReservationId)
|
||||
apiService.deleteTemporaryReservation(
|
||||
userId.accountId,
|
||||
bookingData.xsrfToken.get,
|
||||
bookingData.reservationLocktermResponse.get.value.temporaryReservationId
|
||||
)
|
||||
stay()
|
||||
case Msg(CallbackCommand(Tags.Book), bookingData: BookingData) =>
|
||||
makeReservation(bookingData)
|
||||
@@ -239,8 +306,11 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
private def askMonitoringOffsetOption: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(userId.source, lang.pleaseSpecifyOffset,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No))))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.pleaseSpecifyOffset,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No)))
|
||||
)
|
||||
} onReply {
|
||||
case Msg(TextCommand(IntString(offset)), bookingData: BookingData) =>
|
||||
goto(askMonitoringAutobookOption) using bookingData.copy(offset = offset)
|
||||
@@ -250,10 +320,15 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
private def askMonitoringAutobookOption: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(userId.source, lang.chooseTypeOfMonitoring,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.bookByApplication, Tags.BookByApplication), Button(lang.bookManually, Tags.BookManually)), columns = 1))
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(BooleanString(autobook)), bookingData: BookingData) =>
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.chooseTypeOfMonitoring,
|
||||
inlineKeyboard = createInlineKeyboard(
|
||||
Seq(Button(lang.bookByApplication, Tags.BookByApplication), Button(lang.bookManually, Tags.BookManually)),
|
||||
columns = 1
|
||||
)
|
||||
)
|
||||
} onReply { case Msg(CallbackCommand(BooleanString(autobook)), bookingData: BookingData) =>
|
||||
val data = bookingData.copy(autobook = autobook)
|
||||
if (autobook) goto(askMonitoringRebookOption) using data
|
||||
else goto(createMonitoring) using data
|
||||
@@ -261,10 +336,12 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
private def askMonitoringRebookOption: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(userId.source, lang.rebookIfExists,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))))
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(BooleanString(rebookIfExists)), bookingData: BookingData) =>
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.rebookIfExists,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))
|
||||
)
|
||||
} onReply { case Msg(CallbackCommand(BooleanString(rebookIfExists)), bookingData: BookingData) =>
|
||||
goto(createMonitoring) using bookingData.copy(rebookIfExists = rebookIfExists)
|
||||
}
|
||||
|
||||
@@ -300,12 +377,24 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
object Book {
|
||||
|
||||
case class BookingData(cityId: IdName = null, clinicId: IdName = null,
|
||||
serviceId: IdName = null, doctorId: IdName = null, dateFrom: LocalDateTime = LocalDateTime.now(),
|
||||
dateTo: LocalDateTime = LocalDateTime.now().plusDays(1L), timeFrom: LocalTime = LocalTime.of(7, 0),
|
||||
timeTo: LocalTime = LocalTime.of(21, 0), autobook: Boolean = false, rebookIfExists: Boolean = false,
|
||||
term: Option[TermExt] = None, reservationLocktermResponse: Option[ReservationLocktermResponse] = None,
|
||||
offset: Int = 0, payerId: Long = 0, payers: Seq[IdName] = Seq(), xsrfToken: Option[XsrfToken] = None)
|
||||
case class BookingData(
|
||||
cityId: IdName = null,
|
||||
clinicId: IdName = null,
|
||||
serviceId: IdName = null,
|
||||
doctorId: IdName = null,
|
||||
dateFrom: LocalDateTime = LocalDateTime.now(),
|
||||
dateTo: LocalDateTime = LocalDateTime.now().plusDays(1L),
|
||||
timeFrom: LocalTime = LocalTime.of(7, 0),
|
||||
timeTo: LocalTime = LocalTime.of(21, 0),
|
||||
autobook: Boolean = false,
|
||||
rebookIfExists: Boolean = false,
|
||||
term: Option[TermExt] = None,
|
||||
reservationLocktermResponse: Option[ReservationLocktermResponse] = None,
|
||||
offset: Int = 0,
|
||||
payerId: Long = 0,
|
||||
payers: Seq[IdName] = Seq(),
|
||||
xsrfToken: Option[XsrfToken] = None
|
||||
)
|
||||
|
||||
object Tags {
|
||||
val Cancel = "cancel"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -19,9 +18,19 @@ import com.lbs.server.util.ServerModelConverters._
|
||||
|
||||
import java.time.{LocalDateTime, LocalTime}
|
||||
|
||||
class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dataService: DataService, monitoringService: MonitoringService,
|
||||
val localization: Localization, datePickerFactory: UserIdWithOriginatorTo[DatePicker], timePickerFactory: UserIdWithOriginatorTo[TimePicker],
|
||||
termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]])(implicit val actorSystem: ActorSystem) extends Conversation[BookingData] with Localizable {
|
||||
class BookWithTemplate(
|
||||
val userId: UserId,
|
||||
bot: Bot,
|
||||
apiService: ApiService,
|
||||
dataService: DataService,
|
||||
monitoringService: MonitoringService,
|
||||
val localization: Localization,
|
||||
datePickerFactory: UserIdWithOriginatorTo[DatePicker],
|
||||
timePickerFactory: UserIdWithOriginatorTo[TimePicker],
|
||||
termsPagerFactory: UserIdWithOriginatorTo[Pager[TermExt]]
|
||||
)(implicit val actorSystem: ActorSystem)
|
||||
extends Conversation[BookingData]
|
||||
with Localizable {
|
||||
|
||||
private val datePicker = datePickerFactory(userId, self)
|
||||
private val timePicker = timePickerFactory(userId, self)
|
||||
@@ -30,8 +39,7 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
entryPoint(awaitMonitoring)
|
||||
|
||||
private def awaitMonitoring: Step =
|
||||
monologue {
|
||||
case Msg(monitoring: Monitoring, _) =>
|
||||
monologue { case Msg(monitoring: Monitoring, _) =>
|
||||
val bookingData = BookingData(
|
||||
cityId = IdName.from(monitoring.cityId, monitoring.cityName),
|
||||
clinicId = IdName.from(monitoring.clinicId, monitoring.clinicName),
|
||||
@@ -40,7 +48,8 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
dateFrom = monitoring.dateFrom.toLocalDateTime,
|
||||
dateTo = monitoring.dateTo.toLocalDateTime,
|
||||
timeFrom = monitoring.timeFrom,
|
||||
timeTo = monitoring.timeTo)
|
||||
timeTo = monitoring.timeTo
|
||||
)
|
||||
goto(requestDateFrom) using bookingData
|
||||
}
|
||||
|
||||
@@ -99,24 +108,35 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
private def requestAction: Step =
|
||||
ask { bookingData =>
|
||||
dataService.storeAppointment(userId.accountId, bookingData)
|
||||
bot.sendMessage(userId.source,
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.bookingSummary(bookingData),
|
||||
inlineKeyboard = createInlineKeyboard(
|
||||
Seq(Button(lang.findTerms, Tags.FindTerms), Button(lang.modifyDate, Tags.ModifyDate))
|
||||
))
|
||||
inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.findTerms, Tags.FindTerms), Button(lang.modifyDate, Tags.ModifyDate)))
|
||||
)
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(Tags.FindTerms), _) =>
|
||||
goto(requestTerm)
|
||||
case Msg(CallbackCommand(Tags.ModifyDate), bookingData) =>
|
||||
goto(requestDateFrom) using bookingData.copy(dateFrom = LocalDateTime.now(),
|
||||
dateTo = LocalDateTime.now().plusDays(1L))
|
||||
goto(requestDateFrom) using bookingData.copy(
|
||||
dateFrom = LocalDateTime.now(),
|
||||
dateTo = LocalDateTime.now().plusDays(1L)
|
||||
)
|
||||
}
|
||||
|
||||
private def requestTerm: Step =
|
||||
ask { bookingData =>
|
||||
val availableTerms = apiService.getAvailableTerms(userId.accountId, bookingData.cityId.id,
|
||||
bookingData.clinicId.optionalId, bookingData.serviceId.id, bookingData.doctorId.optionalId,
|
||||
bookingData.dateFrom, bookingData.dateTo, timeFrom = bookingData.timeFrom, timeTo = bookingData.timeTo)
|
||||
val availableTerms = apiService.getAvailableTerms(
|
||||
userId.accountId,
|
||||
bookingData.cityId.id,
|
||||
bookingData.clinicId.optionalId,
|
||||
bookingData.serviceId.id,
|
||||
bookingData.doctorId.optionalId,
|
||||
bookingData.dateFrom,
|
||||
bookingData.dateTo,
|
||||
timeFrom = bookingData.timeFrom,
|
||||
timeTo = bookingData.timeTo
|
||||
)
|
||||
termsPager.restart()
|
||||
termsPager ! availableTerms.map(new SimpleItemsProvider(_))
|
||||
} onReply {
|
||||
@@ -126,18 +146,32 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
case Msg(term: TermExt, bookingData) =>
|
||||
val response = for {
|
||||
xsrfToken <- apiService.getXsrfToken(userId.accountId)
|
||||
lockTermResponse <- apiService.reservationLockterm(userId.accountId, xsrfToken, term.mapTo[ReservationLocktermRequest])
|
||||
lockTermResponse <- apiService.reservationLockterm(
|
||||
userId.accountId,
|
||||
xsrfToken,
|
||||
term.mapTo[ReservationLocktermRequest]
|
||||
)
|
||||
} yield (lockTermResponse, xsrfToken)
|
||||
response match {
|
||||
case Left(ex) =>
|
||||
logger.warn(s"Service [${bookingData.serviceId.name}] is already booked. Ask to update term", ex)
|
||||
bot.sendMessage(userId.source, lang.visitAlreadyExists,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.visitAlreadyExists,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))
|
||||
)
|
||||
goto(awaitRebookDecision) using bookingData.copy(term = Some(term))
|
||||
case Right((reservationLocktermResponse, xsrfToken)) =>
|
||||
bot.sendMessage(userId.source, lang.confirmAppointment(term),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book))))
|
||||
goto(awaitReservation) using bookingData.copy(term = Some(term), xsrfToken = Some(xsrfToken), reservationLocktermResponse = Some(reservationLocktermResponse))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.confirmAppointment(term),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book)))
|
||||
)
|
||||
goto(awaitReservation) using bookingData.copy(
|
||||
term = Some(term),
|
||||
xsrfToken = Some(xsrfToken),
|
||||
reservationLocktermResponse = Some(reservationLocktermResponse)
|
||||
)
|
||||
}
|
||||
case Msg(Pager.NoItemsFound, _) =>
|
||||
goto(askNoTermsAction)
|
||||
@@ -145,12 +179,19 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
|
||||
private def askNoTermsAction: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(userId.source, lang.noTermsFound, inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.modifyDate, Tags.ModifyDate), Button(lang.createMonitoring, Tags.CreateMonitoring))))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.noTermsFound,
|
||||
inlineKeyboard = createInlineKeyboard(
|
||||
Seq(Button(lang.modifyDate, Tags.ModifyDate), Button(lang.createMonitoring, Tags.CreateMonitoring))
|
||||
)
|
||||
)
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(Tags.ModifyDate), bookingData) =>
|
||||
goto(requestDateFrom) using bookingData.copy(dateFrom = LocalDateTime.now(),
|
||||
dateTo = LocalDateTime.now().plusDays(1L))
|
||||
goto(requestDateFrom) using bookingData.copy(
|
||||
dateFrom = LocalDateTime.now(),
|
||||
dateTo = LocalDateTime.now().plusDays(1L)
|
||||
)
|
||||
case Msg(CallbackCommand(Tags.CreateMonitoring), bookingData) =>
|
||||
val settingsMaybe = dataService.findSettings(userId.userId)
|
||||
val (defaultOffset, askOffset) = settingsMaybe match {
|
||||
@@ -165,7 +206,11 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
private def awaitRebookDecision: Step =
|
||||
monologue {
|
||||
case Msg(CallbackCommand(Tags.Yes), bookingData: BookingData) =>
|
||||
apiService.reservationChangeTerm(userId.accountId, bookingData.xsrfToken.get, (bookingData.reservationLocktermResponse.get, bookingData.term.get).mapTo[ReservationChangetermRequest]) match {
|
||||
apiService.reservationChangeTerm(
|
||||
userId.accountId,
|
||||
bookingData.xsrfToken.get,
|
||||
(bookingData.reservationLocktermResponse.get, bookingData.term.get).mapTo[ReservationChangetermRequest]
|
||||
) match {
|
||||
case Right(success) =>
|
||||
logger.debug(s"Successfully confirmed: $success")
|
||||
bot.sendMessage(userId.source, lang.appointmentIsConfirmed)
|
||||
@@ -182,7 +227,11 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
private def awaitReservation: Step =
|
||||
monologue {
|
||||
case Msg(CallbackCommand(Tags.Cancel), bookingData: BookingData) =>
|
||||
apiService.deleteTemporaryReservation(userId.accountId, bookingData.xsrfToken.get, bookingData.reservationLocktermResponse.get.value.temporaryReservationId)
|
||||
apiService.deleteTemporaryReservation(
|
||||
userId.accountId,
|
||||
bookingData.xsrfToken.get,
|
||||
bookingData.reservationLocktermResponse.get.value.temporaryReservationId
|
||||
)
|
||||
stay()
|
||||
case Msg(CallbackCommand(Tags.Book), bookingData: BookingData) =>
|
||||
makeReservation(bookingData)
|
||||
@@ -211,8 +260,11 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
|
||||
private def askMonitoringOffsetOption: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(userId.source, lang.pleaseSpecifyOffset,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No))))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.pleaseSpecifyOffset,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No)))
|
||||
)
|
||||
} onReply {
|
||||
case Msg(TextCommand(IntString(offset)), bookingData: BookingData) =>
|
||||
goto(askMonitoringAutobookOption) using bookingData.copy(offset = offset)
|
||||
@@ -222,10 +274,15 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
|
||||
private def askMonitoringAutobookOption: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(userId.source, lang.chooseTypeOfMonitoring,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.bookByApplication, Tags.BookByApplication), Button(lang.bookManually, Tags.BookManually)), columns = 1))
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(BooleanString(autobook)), bookingData: BookingData) =>
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.chooseTypeOfMonitoring,
|
||||
inlineKeyboard = createInlineKeyboard(
|
||||
Seq(Button(lang.bookByApplication, Tags.BookByApplication), Button(lang.bookManually, Tags.BookManually)),
|
||||
columns = 1
|
||||
)
|
||||
)
|
||||
} onReply { case Msg(CallbackCommand(BooleanString(autobook)), bookingData: BookingData) =>
|
||||
val data = bookingData.copy(autobook = autobook)
|
||||
if (autobook) goto(askMonitoringRebookOption) using data
|
||||
else goto(createMonitoring) using data
|
||||
@@ -233,10 +290,12 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
|
||||
private def askMonitoringRebookOption: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(userId.source, lang.rebookIfExists,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))))
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(BooleanString(rebookIfExists)), bookingData: BookingData) =>
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.rebookIfExists,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))
|
||||
)
|
||||
} onReply { case Msg(CallbackCommand(BooleanString(rebookIfExists)), bookingData: BookingData) =>
|
||||
goto(createMonitoring) using bookingData.copy(rebookIfExists = rebookIfExists)
|
||||
}
|
||||
|
||||
@@ -260,5 +319,3 @@ class BookWithTemplate(val userId: UserId, bot: Bot, apiService: ApiService, dat
|
||||
timePicker.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -12,9 +11,21 @@ import com.typesafe.scalalogging.StrictLogging
|
||||
|
||||
import scala.util.matching.Regex
|
||||
|
||||
class Chat(val userId: UserId, dataService: DataService, monitoringService: MonitoringService, bookingFactory: UserIdTo[Book],
|
||||
helpFactory: UserIdTo[Help], monitoringsFactory: UserIdTo[Monitorings], monitoringsHistoryFactory: UserIdTo[MonitoringsHistory], historyFactory: UserIdTo[HistoryViewer],
|
||||
visitsFactory: UserIdTo[ReservedVisitsViewer], settingsFactory: UserIdTo[Settings], accountFactory: UserIdTo[Account])(val actorSystem: ActorSystem) extends Conversation[Unit] with StrictLogging {
|
||||
class Chat(
|
||||
val userId: UserId,
|
||||
dataService: DataService,
|
||||
monitoringService: MonitoringService,
|
||||
bookingFactory: UserIdTo[Book],
|
||||
helpFactory: UserIdTo[Help],
|
||||
monitoringsFactory: UserIdTo[Monitorings],
|
||||
monitoringsHistoryFactory: UserIdTo[MonitoringsHistory],
|
||||
historyFactory: UserIdTo[HistoryViewer],
|
||||
visitsFactory: UserIdTo[ReservedVisitsViewer],
|
||||
settingsFactory: UserIdTo[Settings],
|
||||
accountFactory: UserIdTo[Account]
|
||||
)(val actorSystem: ActorSystem)
|
||||
extends Conversation[Unit]
|
||||
with StrictLogging {
|
||||
|
||||
private val book = bookingFactory(userId)
|
||||
private val help = helpFactory(userId)
|
||||
@@ -38,57 +49,49 @@ class Chat(val userId: UserId, dataService: DataService, monitoringService: Moni
|
||||
}
|
||||
|
||||
private def bookChat: Step =
|
||||
dialogue(book) {
|
||||
case Msg(TextCommand("/book"), _) =>
|
||||
dialogue(book) { case Msg(TextCommand("/book"), _) =>
|
||||
book.restart()
|
||||
stay()
|
||||
}
|
||||
|
||||
private def historyChat: Step =
|
||||
dialogue(history) {
|
||||
case Msg(TextCommand("/history"), _) =>
|
||||
dialogue(history) { case Msg(TextCommand("/history"), _) =>
|
||||
history.restart()
|
||||
stay()
|
||||
}
|
||||
|
||||
private def visitsChat: Step =
|
||||
dialogue(visits) {
|
||||
case Msg(TextCommand("/reserved"), _) =>
|
||||
dialogue(visits) { case Msg(TextCommand("/reserved"), _) =>
|
||||
visits.restart()
|
||||
stay()
|
||||
}
|
||||
|
||||
private def monitoringsChat: Step =
|
||||
dialogue(monitorings) {
|
||||
case Msg(TextCommand("/monitorings"), _) =>
|
||||
dialogue(monitorings) { case Msg(TextCommand("/monitorings"), _) =>
|
||||
monitorings.restart()
|
||||
stay()
|
||||
}
|
||||
|
||||
private def monitoringsHistoryChat: Step =
|
||||
dialogue(monitoringsHistory) {
|
||||
case Msg(TextCommand("/monitorings_history"), _) =>
|
||||
dialogue(monitoringsHistory) { case Msg(TextCommand("/monitorings_history"), _) =>
|
||||
monitoringsHistory.restart()
|
||||
stay()
|
||||
}
|
||||
|
||||
private def settingsChat: Step =
|
||||
dialogue(settings) {
|
||||
case Msg(TextCommand("/settings"), _) =>
|
||||
dialogue(settings) { case Msg(TextCommand("/settings"), _) =>
|
||||
settings.restart()
|
||||
stay()
|
||||
}
|
||||
|
||||
private def accountChat: Step =
|
||||
dialogue(account) {
|
||||
case Msg(TextCommand("/accounts"), _) =>
|
||||
dialogue(account) { case Msg(TextCommand("/accounts"), _) =>
|
||||
account.restart()
|
||||
stay()
|
||||
}
|
||||
|
||||
private def dialogue(interactional: Interactional)(mainMessageProcessor: MessageProcessorFn): Step =
|
||||
monologue {
|
||||
case event: Msg =>
|
||||
monologue { case event: Msg =>
|
||||
if (mainMessageProcessor.isDefinedAt(event)) mainMessageProcessor(event)
|
||||
else {
|
||||
val defaultMessageProcessor = secondaryState(interactional)
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.bot._
|
||||
import com.lbs.bot.model.Button
|
||||
import com.lbs.bot.{Bot, _}
|
||||
import com.lbs.server.conversation.DatePicker._
|
||||
import com.lbs.server.conversation.Login.UserId
|
||||
import com.lbs.server.conversation.base.{Conversation, Interactional}
|
||||
@@ -21,10 +20,11 @@ import scala.util.control.NonFatal
|
||||
* ⬆ ⬆ ⬆
|
||||
* dd MM yyyy
|
||||
* ⬇ ⬇ ⬇
|
||||
*
|
||||
*/
|
||||
class DatePicker(val userId: UserId, val bot: Bot, val localization: Localization, originator: Interactional)
|
||||
(val actorSystem: ActorSystem) extends Conversation[LocalDateTime] with Localizable {
|
||||
class DatePicker(val userId: UserId, val bot: Bot, val localization: Localization, originator: Interactional)(
|
||||
val actorSystem: ActorSystem
|
||||
) extends Conversation[LocalDateTime]
|
||||
with Localizable {
|
||||
|
||||
private var mode: Mode = DateFromMode
|
||||
|
||||
@@ -102,12 +102,14 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio
|
||||
val month = date.getMonth.getDisplayName(TextStyle.SHORT, lang.locale)
|
||||
val year = date.getYear.toString
|
||||
|
||||
createInlineKeyboard(Seq(
|
||||
createInlineKeyboard(
|
||||
Seq(
|
||||
Seq(Button("⬆", Tags.DayInc), Button("⬆", Tags.MonthInc), Button("⬆", Tags.YearInc)),
|
||||
Seq(Button(s"$day ($dayOfWeek)"), Button(month), Button(year)),
|
||||
Seq(Button("⬇", Tags.DayDec), Button("⬇", Tags.MonthDec), Button("⬇", Tags.YearDec)),
|
||||
Seq(Button("Done", Tags.Done))
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -8,13 +7,14 @@ import com.lbs.server.conversation.Login.UserId
|
||||
import com.lbs.server.conversation.base.Conversation
|
||||
import com.lbs.server.lang.{Localizable, Localization}
|
||||
|
||||
class Help(val userId: UserId, bot: Bot, val localization: Localization)(val actorSystem: ActorSystem) extends Conversation[Unit] with Localizable {
|
||||
class Help(val userId: UserId, bot: Bot, val localization: Localization)(val actorSystem: ActorSystem)
|
||||
extends Conversation[Unit]
|
||||
with Localizable {
|
||||
|
||||
entryPoint(displayHelp)
|
||||
|
||||
def displayHelp: Step =
|
||||
monologue {
|
||||
case Msg(_: Command, _) =>
|
||||
monologue { case Msg(_: Command, _) =>
|
||||
bot.sendMessage(userId.source, lang.help)
|
||||
stay()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -11,8 +10,15 @@ import com.lbs.server.conversation.base.Conversation
|
||||
import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.service.ApiService
|
||||
|
||||
class HistoryViewer(val userId: UserId, bot: Bot, apiService: ApiService, val localization: Localization,
|
||||
historyPagerFactory: UserIdWithOriginatorTo[Pager[Event]])(val actorSystem: ActorSystem) extends Conversation[Unit] with Localizable {
|
||||
class HistoryViewer(
|
||||
val userId: UserId,
|
||||
bot: Bot,
|
||||
apiService: ApiService,
|
||||
val localization: Localization,
|
||||
historyPagerFactory: UserIdWithOriginatorTo[Pager[Event]]
|
||||
)(val actorSystem: ActorSystem)
|
||||
extends Conversation[Unit]
|
||||
with Localizable {
|
||||
|
||||
private val historyPager = historyPagerFactory(userId, self)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -11,8 +10,17 @@ import com.lbs.server.service.{ApiService, DataService}
|
||||
import com.lbs.server.util.MessageExtractors
|
||||
import org.jasypt.util.text.TextEncryptor
|
||||
|
||||
class Login(source: MessageSource, bot: Bot, dataService: DataService, apiService: ApiService, textEncryptor: TextEncryptor,
|
||||
val localization: Localization, originator: Interactional)(val actorSystem: ActorSystem) extends Conversation[String] with Localizable {
|
||||
class Login(
|
||||
source: MessageSource,
|
||||
bot: Bot,
|
||||
dataService: DataService,
|
||||
apiService: ApiService,
|
||||
textEncryptor: TextEncryptor,
|
||||
val localization: Localization,
|
||||
originator: Interactional
|
||||
)(val actorSystem: ActorSystem)
|
||||
extends Conversation[String]
|
||||
with Localizable {
|
||||
|
||||
protected var userId: UserId = _
|
||||
|
||||
@@ -21,8 +29,7 @@ class Login(source: MessageSource, bot: Bot, dataService: DataService, apiServic
|
||||
private var forwardCommand: ForwardCommand = _
|
||||
|
||||
def logIn: Step =
|
||||
monologue {
|
||||
case Msg(cmd: Command, _) =>
|
||||
monologue { case Msg(cmd: Command, _) =>
|
||||
forwardCommand = ForwardCommand(cmd)
|
||||
goto(requestUsername)
|
||||
}
|
||||
@@ -30,16 +37,14 @@ class Login(source: MessageSource, bot: Bot, dataService: DataService, apiServic
|
||||
def requestUsername: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(source, lang.provideUsername)
|
||||
} onReply {
|
||||
case Msg(MessageExtractors.TextCommand(username), _) =>
|
||||
} onReply { case Msg(MessageExtractors.TextCommand(username), _) =>
|
||||
goto(requestPassword) using username
|
||||
}
|
||||
|
||||
def requestPassword: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(source, lang.providePassword)
|
||||
} onReply {
|
||||
case Msg(MessageExtractors.TextCommand(plainPassword), username) =>
|
||||
} onReply { case Msg(MessageExtractors.TextCommand(plainPassword), username) =>
|
||||
val password = textEncryptor.encrypt(plainPassword)
|
||||
apiService.fullLogin(username, password) match {
|
||||
case Left(error) =>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -12,7 +11,15 @@ import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.repository.model.Monitoring
|
||||
import com.lbs.server.service.MonitoringService
|
||||
|
||||
class Monitorings(val userId: UserId, bot: Bot, monitoringService: MonitoringService, val localization: Localization, monitoringsPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]])(val actorSystem: ActorSystem) extends Conversation[Monitoring] with Localizable {
|
||||
class Monitorings(
|
||||
val userId: UserId,
|
||||
bot: Bot,
|
||||
monitoringService: MonitoringService,
|
||||
val localization: Localization,
|
||||
monitoringsPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]]
|
||||
)(val actorSystem: ActorSystem)
|
||||
extends Conversation[Monitoring]
|
||||
with Localizable {
|
||||
|
||||
private val monitoringsPager = monitoringsPagerFactory(userId, self)
|
||||
|
||||
@@ -40,8 +47,11 @@ class Monitorings(val userId: UserId, bot: Bot, monitoringService: MonitoringSer
|
||||
|
||||
def askToDeactivateMonitoring: Step =
|
||||
ask { monitoring =>
|
||||
bot.sendMessage(userId.source, lang.deactivateMonitoring(monitoring), inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.deactivateMonitoring(monitoring),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))
|
||||
)
|
||||
} onReply {
|
||||
case Msg(Command(_, _, Some(Tags.No)), _) =>
|
||||
bot.sendMessage(userId.source, lang.monitoringWasNotDeactivated)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -11,7 +10,16 @@ import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.repository.model.Monitoring
|
||||
import com.lbs.server.service.MonitoringService
|
||||
|
||||
class MonitoringsHistory(val userId: UserId, bot: Bot, monitoringService: MonitoringService, val localization: Localization, monitoringsPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]], bookWithTemplateFactory: UserIdTo[BookWithTemplate])(val actorSystem: ActorSystem) extends Conversation[Monitoring] with Localizable {
|
||||
class MonitoringsHistory(
|
||||
val userId: UserId,
|
||||
bot: Bot,
|
||||
monitoringService: MonitoringService,
|
||||
val localization: Localization,
|
||||
monitoringsPagerFactory: UserIdWithOriginatorTo[Pager[Monitoring]],
|
||||
bookWithTemplateFactory: UserIdTo[BookWithTemplate]
|
||||
)(val actorSystem: ActorSystem)
|
||||
extends Conversation[Monitoring]
|
||||
with Localizable {
|
||||
|
||||
private val monitoringsPager = monitoringsPagerFactory(userId, self)
|
||||
private val bookWithTemplate = bookWithTemplateFactory(userId)
|
||||
@@ -42,8 +50,7 @@ class MonitoringsHistory(val userId: UserId, bot: Bot, monitoringService: Monito
|
||||
ask { monitoring =>
|
||||
bookWithTemplate.restart()
|
||||
bookWithTemplate ! monitoring
|
||||
} onReply {
|
||||
case Msg(cmd: Command, _) =>
|
||||
} onReply { case Msg(cmd: Command, _) =>
|
||||
bookWithTemplate ! cmd
|
||||
stay()
|
||||
}
|
||||
@@ -62,7 +69,8 @@ class MonitoringsHistory(val userId: UserId, bot: Bot, monitoringService: Monito
|
||||
|
||||
override def previous(): Unit = index -= 1
|
||||
|
||||
override def items: Seq[Monitoring] = monitoringService.getMonitoringsPage(userId.accountId, index * Pager.PageSize, Pager.PageSize)
|
||||
override def items: Seq[Monitoring] =
|
||||
monitoringService.getMonitoringsPage(userId.accountId, index * Pager.PageSize, Pager.PageSize)
|
||||
|
||||
override def currentPage: Int = index
|
||||
|
||||
@@ -70,4 +78,3 @@ class MonitoringsHistory(val userId: UserId, bot: Bot, monitoringService: Monito
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.bot.model.{Button, Command}
|
||||
import com.lbs.bot._
|
||||
import com.lbs.bot.model.{Button, Command}
|
||||
import com.lbs.server.conversation.Login.UserId
|
||||
import com.lbs.server.conversation.Pager._
|
||||
import com.lbs.server.conversation.base.{Conversation, Interactional}
|
||||
@@ -11,10 +10,18 @@ import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.util.MessageExtractors
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
|
||||
class Pager[Data](val userId: UserId, bot: Bot, makeMessage: (Data, Int, Int) => String,
|
||||
makeHeader: (Int, Int) => String, selectionPrefix: Option[String],
|
||||
val localization: Localization, originator: Interactional)(val actorSystem: ActorSystem)
|
||||
extends Conversation[(ItemsProvider[Data], Option[String])] with Localizable with StrictLogging {
|
||||
class Pager[Data](
|
||||
val userId: UserId,
|
||||
bot: Bot,
|
||||
makeMessage: (Data, Int, Int) => String,
|
||||
makeHeader: (Int, Int) => String,
|
||||
selectionPrefix: Option[String],
|
||||
val localization: Localization,
|
||||
originator: Interactional
|
||||
)(val actorSystem: ActorSystem)
|
||||
extends Conversation[(ItemsProvider[Data], Option[String])]
|
||||
with Localizable
|
||||
with StrictLogging {
|
||||
|
||||
private val Selection = s"/${selectionPrefix.getOrElse("")}_(\\d+)".r
|
||||
|
||||
@@ -49,10 +56,17 @@ class Pager[Data](val userId: UserId, bot: Bot, makeMessage: (Data, Int, Int) =>
|
||||
}
|
||||
|
||||
private def sendPage(itemsProvider: ItemsProvider[Data], messageId: Option[String] = None): Unit = {
|
||||
val message = makeHeader(itemsProvider.currentPage, itemsProvider.pages) + "\n\n" + itemsProvider.items.zipWithIndex.map { case (d, index) => makeMessage(d, itemsProvider.currentPage, index) }.mkString
|
||||
val message =
|
||||
makeHeader(itemsProvider.currentPage, itemsProvider.pages) + "\n\n" + itemsProvider.items.zipWithIndex.map {
|
||||
case (d, index) =>
|
||||
makeMessage(d, itemsProvider.currentPage, index)
|
||||
}.mkString
|
||||
|
||||
val previousButton = if (itemsProvider.currentPage > 0) Some(Button(lang.previous, Tags.Previous)) else None
|
||||
val nextButton = if (itemsProvider.currentPage >= 0 && itemsProvider.currentPage < itemsProvider.pages - 1) Some(Button(lang.next, Tags.Next)) else None
|
||||
val nextButton =
|
||||
if (itemsProvider.currentPage >= 0 && itemsProvider.currentPage < itemsProvider.pages - 1)
|
||||
Some(Button(lang.next, Tags.Next))
|
||||
else None
|
||||
val buttons = previousButton.toSeq ++ nextButton.toSeq
|
||||
|
||||
messageId match {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.api.json.model.Event
|
||||
import com.lbs.bot._
|
||||
import com.lbs.bot.model.{Button, Command}
|
||||
import com.lbs.bot.{Bot, _}
|
||||
import com.lbs.server.conversation.Login.UserId
|
||||
import com.lbs.server.conversation.Pager.SimpleItemsProvider
|
||||
import com.lbs.server.conversation.ReservedVisitsViewer.Tags
|
||||
@@ -12,8 +11,15 @@ import com.lbs.server.conversation.base.Conversation
|
||||
import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.service.ApiService
|
||||
|
||||
class ReservedVisitsViewer(val userId: UserId, bot: Bot, apiService: ApiService, val localization: Localization,
|
||||
visitsPagerFactory: UserIdWithOriginatorTo[Pager[Event]])(val actorSystem: ActorSystem) extends Conversation[Event] with Localizable {
|
||||
class ReservedVisitsViewer(
|
||||
val userId: UserId,
|
||||
bot: Bot,
|
||||
apiService: ApiService,
|
||||
val localization: Localization,
|
||||
visitsPagerFactory: UserIdWithOriginatorTo[Pager[Event]]
|
||||
)(val actorSystem: ActorSystem)
|
||||
extends Conversation[Event]
|
||||
with Localizable {
|
||||
|
||||
private val reservedVisitsPager = visitsPagerFactory(userId, self)
|
||||
|
||||
@@ -41,8 +47,11 @@ class ReservedVisitsViewer(val userId: UserId, bot: Bot, apiService: ApiService,
|
||||
|
||||
def askToCancelVisit: Step =
|
||||
ask { visit =>
|
||||
bot.sendMessage(userId.source, lang.areYouSureToCancelAppointment(visit),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.areYouSureToCancelAppointment(visit),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes)))
|
||||
)
|
||||
} onReply {
|
||||
case Msg(Command(_, _, Some(Tags.No)), _) =>
|
||||
bot.sendMessage(userId.source, lang.appointmentWasNotCancelled)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.{ActorSystem, Cancellable}
|
||||
@@ -11,7 +10,9 @@ import scala.collection.mutable
|
||||
import scala.concurrent.ExecutionContextExecutor
|
||||
import scala.concurrent.duration.DurationLong
|
||||
|
||||
class Router(authFactory: MessageSourceTo[Auth])(val actorSystem: ActorSystem) extends Conversation[Unit] with StrictLogging {
|
||||
class Router(authFactory: MessageSourceTo[Auth])(val actorSystem: ActorSystem)
|
||||
extends Conversation[Unit]
|
||||
with StrictLogging {
|
||||
|
||||
private case class DestroyChat(source: MessageSource)
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.bot._
|
||||
import com.lbs.bot.model.{Button, Command}
|
||||
import com.lbs.bot.{Bot, _}
|
||||
import com.lbs.server.conversation.Login.UserId
|
||||
import com.lbs.server.conversation.Settings._
|
||||
import com.lbs.server.conversation.base.Conversation
|
||||
@@ -12,15 +11,21 @@ import com.lbs.server.repository.model
|
||||
import com.lbs.server.service.DataService
|
||||
import com.lbs.server.util.MessageExtractors.{CallbackCommand, IntString, TextCommand}
|
||||
|
||||
class Settings(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization)(val actorSystem: ActorSystem) extends Conversation[Unit] with Localizable {
|
||||
class Settings(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization)(
|
||||
val actorSystem: ActorSystem
|
||||
) extends Conversation[Unit]
|
||||
with Localizable {
|
||||
|
||||
entryPoint(askForAction)
|
||||
|
||||
def askForAction: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(userId.source, lang.settingsHeader, inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.language, Tags.Language),
|
||||
Button(lang.offset, Tags.Offset)), columns = 1))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.settingsHeader,
|
||||
inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.language, Tags.Language), Button(lang.offset, Tags.Offset)), columns = 1)
|
||||
)
|
||||
} onReply {
|
||||
case Msg(Command(_, _, Some(Tags.Language)), _) =>
|
||||
goto(askLanguage)
|
||||
@@ -30,10 +35,12 @@ class Settings(val userId: UserId, bot: Bot, dataService: DataService, val local
|
||||
|
||||
def askLanguage: Step =
|
||||
ask { _ =>
|
||||
bot.sendMessage(userId.source, lang.chooseLanguage,
|
||||
inlineKeyboard = createInlineKeyboard(Lang.Langs.map(l => Button(l.label, l.id)), columns = 1))
|
||||
} onReply {
|
||||
case Msg(CallbackCommand(IntString(langId)), _) =>
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.chooseLanguage,
|
||||
inlineKeyboard = createInlineKeyboard(Lang.Langs.map(l => Button(l.label, l.id)), columns = 1)
|
||||
)
|
||||
} onReply { case Msg(CallbackCommand(IntString(langId)), _) =>
|
||||
localization.updateLanguage(userId.userId, Lang(langId))
|
||||
bot.sendMessage(userId.source, lang.languageUpdated)
|
||||
end()
|
||||
@@ -42,17 +49,33 @@ class Settings(val userId: UserId, bot: Bot, dataService: DataService, val local
|
||||
def showOffsetOptions: Step = {
|
||||
ask { _ =>
|
||||
val settings = getSettings
|
||||
bot.sendMessage(userId.source, lang.configureOffset,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.alwaysAskOffset(settings.alwaysAskOffset), Tags.ToggleAskOffsetOnOff),
|
||||
Button(lang.changeDefaultOffset(settings.defaultOffset), Tags.ChangeDefaultOffset)), columns = 1))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.configureOffset,
|
||||
inlineKeyboard = createInlineKeyboard(
|
||||
Seq(
|
||||
Button(lang.alwaysAskOffset(settings.alwaysAskOffset), Tags.ToggleAskOffsetOnOff),
|
||||
Button(lang.changeDefaultOffset(settings.defaultOffset), Tags.ChangeDefaultOffset)
|
||||
),
|
||||
columns = 1
|
||||
)
|
||||
)
|
||||
} onReply {
|
||||
case Msg(cmd @ CallbackCommand(Tags.ToggleAskOffsetOnOff), _) =>
|
||||
val settings = getSettings
|
||||
settings.alwaysAskOffset = !settings.alwaysAskOffset
|
||||
dataService.saveSettings(settings)
|
||||
bot.sendEditMessage(userId.source, cmd.message.messageId,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.alwaysAskOffset(settings.alwaysAskOffset), Tags.ToggleAskOffsetOnOff),
|
||||
Button(lang.changeDefaultOffset(settings.defaultOffset), Tags.ChangeDefaultOffset)), columns = 1))
|
||||
bot.sendEditMessage(
|
||||
userId.source,
|
||||
cmd.message.messageId,
|
||||
inlineKeyboard = createInlineKeyboard(
|
||||
Seq(
|
||||
Button(lang.alwaysAskOffset(settings.alwaysAskOffset), Tags.ToggleAskOffsetOnOff),
|
||||
Button(lang.changeDefaultOffset(settings.defaultOffset), Tags.ChangeDefaultOffset)
|
||||
),
|
||||
columns = 1
|
||||
)
|
||||
)
|
||||
stay()
|
||||
case Msg(CallbackCommand(Tags.ChangeDefaultOffset), _) =>
|
||||
goto(askDefaultOffset)
|
||||
@@ -63,8 +86,7 @@ class Settings(val userId: UserId, bot: Bot, dataService: DataService, val local
|
||||
ask { _ =>
|
||||
val settings = getSettings
|
||||
bot.sendMessage(userId.source, lang.pleaseEnterOffset(settings.defaultOffset))
|
||||
} onReply {
|
||||
case Msg(TextCommand(IntString(offset)), _) =>
|
||||
} onReply { case Msg(TextCommand(IntString(offset)), _) =>
|
||||
val settings = getSettings
|
||||
settings.defaultOffset = offset
|
||||
dataService.saveSettings(settings)
|
||||
@@ -73,7 +95,9 @@ class Settings(val userId: UserId, bot: Bot, dataService: DataService, val local
|
||||
}
|
||||
|
||||
private def getSettings = {
|
||||
dataService.findSettings(userId.userId).getOrElse(model.Settings(userId.userId, lang.id, 0, alwaysAskOffset = false))
|
||||
dataService
|
||||
.findSettings(userId.userId)
|
||||
.getOrElse(model.Settings(userId.userId, lang.id, 0, alwaysAskOffset = false))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.api.json.model.{IdName, Identified}
|
||||
import com.lbs.bot._
|
||||
import com.lbs.bot.model.{Button, Command, TaggedButton}
|
||||
import com.lbs.bot.{Bot, _}
|
||||
import com.lbs.server.ThrowableOr
|
||||
import com.lbs.server.conversation.Login.UserId
|
||||
import com.lbs.server.conversation.StaticData._
|
||||
import com.lbs.server.conversation.base.{Conversation, Interactional}
|
||||
import com.lbs.server.lang.{Localizable, Localization}
|
||||
|
||||
class StaticData(val userId: UserId, bot: Bot, val localization: Localization, originator: Interactional)(val actorSystem: ActorSystem) extends Conversation[List[TaggedButton]] with Localizable {
|
||||
class StaticData(val userId: UserId, bot: Bot, val localization: Localization, originator: Interactional)(
|
||||
val actorSystem: ActorSystem
|
||||
) extends Conversation[List[TaggedButton]]
|
||||
with Localizable {
|
||||
|
||||
private def anySelectOption: List[TaggedButton] = if (config.isAnyAllowed) List(Button(lang.any, -1L)) else List()
|
||||
|
||||
@@ -20,8 +22,7 @@ class StaticData(val userId: UserId, bot: Bot, val localization: Localization, o
|
||||
entryPoint(AwaitConfig)
|
||||
|
||||
def AwaitConfig: Step =
|
||||
monologue {
|
||||
case Msg(newConfig: StaticDataConfig, _) =>
|
||||
monologue { case Msg(newConfig: StaticDataConfig, _) =>
|
||||
config = newConfig
|
||||
goto(askForLatestOption)
|
||||
}
|
||||
@@ -40,12 +41,16 @@ class StaticData(val userId: UserId, bot: Bot, val localization: Localization, o
|
||||
|
||||
def askForUserInput: Step =
|
||||
ask { callbackTags =>
|
||||
bot.sendMessage(userId.source, lang.pleaseEnterStaticDataNameOrPrevious(config),
|
||||
inlineKeyboard = createInlineKeyboard(callbackTags, columns = 1))
|
||||
bot.sendMessage(
|
||||
userId.source,
|
||||
lang.pleaseEnterStaticDataNameOrPrevious(config),
|
||||
inlineKeyboard = createInlineKeyboard(callbackTags, columns = 1)
|
||||
)
|
||||
} onReply {
|
||||
case Msg(Command(_, msg, Some(tag)), callbackTags) =>
|
||||
val id = tag.toLong
|
||||
val label = callbackTags.find(_.tag == tag).map(_.label).getOrElse(sys.error("Unable to get callback tag label"))
|
||||
val label =
|
||||
callbackTags.find(_.tag == tag).map(_.label).getOrElse(sys.error("Unable to get callback tag label"))
|
||||
bot.sendEditMessage(userId.source, msg.messageId, lang.staticDataIs(config, label))
|
||||
originator ! IdName(id, label)
|
||||
end()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import com.lbs.api.json.model.{IdName, Identified}
|
||||
@@ -12,8 +11,12 @@ trait StaticDataForBooking extends Conversation[BookingData] {
|
||||
|
||||
private[conversation] def staticData: StaticData
|
||||
|
||||
protected def withFunctions[T <: Identified](latestOptions: => Seq[IdName], staticOptions: => ThrowableOr[List[T]], applyId: IdName => BookingData): Step => MessageProcessorFn = {
|
||||
nextStep: Step => {
|
||||
protected def withFunctions[T <: Identified](
|
||||
latestOptions: => Seq[IdName],
|
||||
staticOptions: => ThrowableOr[List[T]],
|
||||
applyId: IdName => BookingData
|
||||
): Step => MessageProcessorFn = { nextStep: Step =>
|
||||
{
|
||||
case Msg(cmd: Command, _) =>
|
||||
staticData ! cmd
|
||||
stay()
|
||||
@@ -28,12 +31,13 @@ trait StaticDataForBooking extends Conversation[BookingData] {
|
||||
}
|
||||
}
|
||||
|
||||
protected def staticData(staticDataConfig: => StaticDataConfig)(functions: BookingData => Step => MessageProcessorFn)(requestNext: Step)(implicit functionName: sourcecode.Name): Step = {
|
||||
protected def staticData(staticDataConfig: => StaticDataConfig)(
|
||||
functions: BookingData => Step => MessageProcessorFn
|
||||
)(requestNext: Step)(implicit functionName: sourcecode.Name): Step = {
|
||||
ask { _ =>
|
||||
staticData.restart()
|
||||
staticData ! staticDataConfig
|
||||
} onReply {
|
||||
case msg@Msg(_, bookingData: BookingData) =>
|
||||
} onReply { case msg @ Msg(_, bookingData: BookingData) =>
|
||||
val fn = functions(bookingData)(requestNext)
|
||||
fn(msg)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.lbs.bot._
|
||||
import com.lbs.bot.model.Button
|
||||
import com.lbs.bot.{Bot, _}
|
||||
import com.lbs.server.conversation.Login.UserId
|
||||
import com.lbs.server.conversation.TimePicker.{Mode, Tags, TimeFromMode, TimeToMode}
|
||||
import com.lbs.server.conversation.base.{Conversation, Interactional}
|
||||
@@ -20,9 +19,11 @@ import scala.util.control.NonFatal
|
||||
* ⬆ ⬆
|
||||
* HH mm
|
||||
* ⬇ ⬇
|
||||
*
|
||||
*/
|
||||
class TimePicker(val userId: UserId, val bot: Bot, val localization: Localization, originator: Interactional)(val actorSystem: ActorSystem) extends Conversation[LocalTime] with Localizable {
|
||||
class TimePicker(val userId: UserId, val bot: Bot, val localization: Localization, originator: Interactional)(
|
||||
val actorSystem: ActorSystem
|
||||
) extends Conversation[LocalTime]
|
||||
with Localizable {
|
||||
|
||||
private var mode: Mode = TimeFromMode
|
||||
|
||||
@@ -92,12 +93,14 @@ class TimePicker(val userId: UserId, val bot: Bot, val localization: Localizatio
|
||||
val hour = f"${time.getHour}%02d"
|
||||
val minute = f"${time.getMinute}%02d"
|
||||
|
||||
createInlineKeyboard(Seq(
|
||||
createInlineKeyboard(
|
||||
Seq(
|
||||
Seq(Button("⬆", Tags.HourInc), Button("⬆", Tags.MinuteInc)),
|
||||
Seq(Button(hour), Button(minute)),
|
||||
Seq(Button("⬇", Tags.HourDec), Button("⬇", Tags.MinuteDec)),
|
||||
Seq(Button("Done", Tags.Done))
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,4 +121,3 @@ object TimePicker {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.conversation
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
@@ -11,8 +10,7 @@ class UnauthorizedHelp(source: MessageSource, bot: Bot)(val actorSystem: ActorSy
|
||||
entryPoint(displayHelp)
|
||||
|
||||
def displayHelp: Step =
|
||||
monologue {
|
||||
case Msg(_: Command, _) =>
|
||||
monologue { case Msg(_: Command, _) =>
|
||||
bot.sendMessage(source, En.help)
|
||||
stay()
|
||||
}
|
||||
|
||||
@@ -14,8 +14,7 @@ trait Conversation[D] extends Domain[D] with Interactional with StrictLogging {
|
||||
|
||||
private var initialStep: Step = _
|
||||
|
||||
private val defaultMsgHandler: MessageProcessorFn = {
|
||||
case Msg(any, data) =>
|
||||
private val defaultMsgHandler: MessageProcessorFn = { case Msg(any, data) =>
|
||||
logger.warn(s"Unhandled message received in step '${currentStep.name}'. Message: [$any]. Data: [$data]")
|
||||
NextStep(currentStep, Some(data))
|
||||
}
|
||||
@@ -71,12 +70,13 @@ trait Conversation[D] extends Domain[D] with Interactional with StrictLogging {
|
||||
currentData = initialData
|
||||
}
|
||||
|
||||
|
||||
protected def monologue(answerFn: MessageProcessorFn)(implicit functionName: sourcecode.Name): Monologue = Monologue(functionName.value, answerFn)
|
||||
protected def monologue(answerFn: MessageProcessorFn)(implicit functionName: sourcecode.Name): Monologue =
|
||||
Monologue(functionName.value, answerFn)
|
||||
|
||||
protected def ask(askFn: D => Unit): Ask = Ask(askFn)
|
||||
|
||||
protected def process(processFn: ProcessFn)(implicit functionName: sourcecode.Name): Process = Process(functionName.value, processFn)
|
||||
protected def process(processFn: ProcessFn)(implicit functionName: sourcecode.Name): Process =
|
||||
Process(functionName.value, processFn)
|
||||
|
||||
protected def end(): NextStep = NextStep(End)
|
||||
|
||||
@@ -106,4 +106,3 @@ trait Conversation[D] extends Domain[D] with Interactional with StrictLogging {
|
||||
entryPoint(step, null.asInstanceOf[D])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,4 +71,3 @@ trait Interactional extends StrictLogging {
|
||||
ref ! PoisonPill
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server
|
||||
|
||||
import com.lbs.bot.model.MessageSource
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.exception
|
||||
|
||||
case class UserNotFoundException(chatId: Long) extends Exception(s"Luxmed username for chat with id $chatId")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import com.lbs.api.json.model.{Event, TermExt}
|
||||
@@ -40,14 +39,18 @@ object En extends Lang {
|
||||
s"""<b>➡</b> Are you sure want to cancel appointment?
|
||||
|
|
||||
|⏱ <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")}
|
||||
|${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)}
|
||||
|${capitalize(service)}: ${event.title}
|
||||
|${capitalize(clinic)}: ${event.clinic
|
||||
.map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}")
|
||||
.getOrElse("Telemedicine")}
|
||||
|""".stripMargin
|
||||
|
||||
override def chooseDateFrom(exampleDate: LocalDateTime): String = s"<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: LocalDateTime): 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"
|
||||
|
||||
@@ -74,12 +77,11 @@ object En extends Lang {
|
||||
override def book: String = "Book"
|
||||
|
||||
override def confirmAppointment(term: TermExt): String =
|
||||
|
||||
s"""<b>➡</b> Would you like to confirm your appointment booking?
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}""".stripMargin
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}""".stripMargin
|
||||
|
||||
override def appointmentIsConfirmed: String = "👍 Your appointment has been confirmed!"
|
||||
|
||||
@@ -97,7 +99,8 @@ object En extends Lang {
|
||||
|
||||
override def pleaseSpecifyOffset: String = "<b>➡</b> Please send me offset in hours or press No button"
|
||||
|
||||
override def visitAlreadyExists: String = "<b>➡</b> The same service is already booked. Do you want to update the term?"
|
||||
override def visitAlreadyExists: String =
|
||||
"<b>➡</b> The same service is already booked. Do you want to update the term?"
|
||||
|
||||
override def city: String = "city"
|
||||
|
||||
@@ -118,9 +121,9 @@ object En extends Lang {
|
||||
|
|
||||
|📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}""".stripMargin
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}""".stripMargin
|
||||
|
||||
override def deactivated: String = "👍 Deactivated! List of active /monitorings"
|
||||
|
||||
@@ -132,7 +135,8 @@ object En extends Lang {
|
||||
withAnyVariant(
|
||||
s"""<b>➡</b> Please enter a partial ${config.name} name
|
||||
|For example: <b>${config.partialExample}</b> if you are looking for <b>${config.example}</b>""".stripMargin,
|
||||
config.isAnyAllowed)
|
||||
config.isAnyAllowed
|
||||
)
|
||||
|
||||
override def pleaseEnterStaticDataNameOrPrevious(config: StaticDataConfig): String =
|
||||
s"""<b>➡</b> Please enter a partial ${config.name} name
|
||||
@@ -141,7 +145,7 @@ object En extends Lang {
|
||||
|or choose a ${config.name} from previous searches""".stripMargin
|
||||
|
||||
override def staticDataIs(config: StaticDataConfig, label: String): String =
|
||||
s"<b>✅</b> ${capitalizeFirstLetter(config.name)} is <b>$label</b>"
|
||||
s"<b>✅</b> ${capitalize(config.name)} is <b>$label</b>"
|
||||
|
||||
override def pleaseChooseStaticDataNameOrAny(config: StaticDataConfig): String =
|
||||
withAnyVariant(s"<b>➡</b> Please choose a ${config.name}", config.isAnyAllowed)
|
||||
@@ -149,7 +153,9 @@ object En extends Lang {
|
||||
override def staticNotFound(config: StaticDataConfig): String =
|
||||
withAnyVariant(
|
||||
s"""<b>➡</b> Nothing was found 😔
|
||||
|Please enter a ${config.name} name again""", config.isAnyAllowed)
|
||||
|Please enter a ${config.name} name again""",
|
||||
config.isAnyAllowed
|
||||
)
|
||||
|
||||
override def loginAndPasswordAreOk: String =
|
||||
s"""✅ Congrats! Login and password are OK!
|
||||
@@ -186,8 +192,8 @@ object En extends Lang {
|
||||
|
||||
override def termEntry(term: TermExt, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}
|
||||
|<b>➡</b> /book_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -197,9 +203,11 @@ object En extends Lang {
|
||||
|
||||
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")}
|
||||
|${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)}
|
||||
|${capitalize(service)}: ${event.title}
|
||||
|${capitalize(clinic)}: ${event.clinic
|
||||
.map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}")
|
||||
.getOrElse("Telemedicine")}
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
@@ -208,9 +216,11 @@ object En extends Lang {
|
||||
|
||||
override def reservedVisitEntry(event: Event, page: Int, index: Int): String =
|
||||
s"""⏱ <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")}
|
||||
|${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)}
|
||||
|${capitalize(service)}: ${event.title}
|
||||
|${capitalize(clinic)}: ${event.clinic
|
||||
.map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}")
|
||||
.getOrElse("Telemedicine")}
|
||||
|<b>➡</b> /cancel_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -224,10 +234,10 @@ object En extends Lang {
|
||||
override def monitoringEntry(monitoring: Monitoring, page: Int, index: Int): String =
|
||||
s"""📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|Type: ${if (monitoring.autobook) "Auto" else "Manual"}
|
||||
|<b>➡</b> /cancel_$index
|
||||
|
|
||||
@@ -236,10 +246,10 @@ object En extends Lang {
|
||||
override def monitoringHistoryEntry(monitoring: Monitoring, page: Int, index: Int): String =
|
||||
s"""📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|Type: ${if (monitoring.autobook) "Auto" else "Manual"}
|
||||
|<b>➡</b> /repeat_$index
|
||||
|
|
||||
@@ -258,10 +268,10 @@ object En extends Lang {
|
||||
|
||||
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.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|/reserve_${monitoring.recordId}_${term.term.scheduleId}_${minutesSinceBeginOf2018(term.term.dateTimeFrom.get)}
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -276,10 +286,10 @@ object En extends Lang {
|
||||
|
|
||||
|📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|
|
||||
|<b>➡</b> Create new monitoring /book""".stripMargin
|
||||
|
||||
@@ -287,10 +297,10 @@ object En extends Lang {
|
||||
s"""👍 We just booked an appointment for you!
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}""".stripMargin
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}
|
||||
|${capitalize(city)}: ${monitoring.cityName}""".stripMargin
|
||||
|
||||
override def maximumMonitoringsLimitExceeded: String = "Maximum monitorings per user is 10"
|
||||
|
||||
@@ -315,7 +325,8 @@ object En extends Lang {
|
||||
|
||||
override def configureOffset: String = "<b>➡</b> Please specify offset options"
|
||||
|
||||
override def pleaseEnterOffset(current: Int): String = s"<b>➡</b> Please enter default offset. Current: <b>$current</b>"
|
||||
override def pleaseEnterOffset(current: Int): String =
|
||||
s"<b>➡</b> Please enter default offset. Current: <b>$current</b>"
|
||||
|
||||
override def alwaysAskOffset(enabled: Boolean): String = s"${if (enabled) "✅ " else ""}Always ask offset"
|
||||
|
||||
@@ -353,9 +364,11 @@ object En extends Lang {
|
||||
|
||||
override def moreParameters: String = "🛠 More parameters"
|
||||
|
||||
override def chooseTimeFrom(exampleTime: LocalTime): String = s"<b>➡</b> Please choose time from or write time using format HH:mm, e.g. ${formatTime(exampleTime)}"
|
||||
override def chooseTimeFrom(exampleTime: LocalTime): String =
|
||||
s"<b>➡</b> Please choose time from or write time using format HH:mm, e.g. ${formatTime(exampleTime)}"
|
||||
|
||||
override def chooseTimeTo(exampleTime: LocalTime): String = s"<b>➡</b> Please choose time to or write time using format HH:mm, e.g. ${formatTime(exampleTime)}"
|
||||
override def chooseTimeTo(exampleTime: LocalTime): String =
|
||||
s"<b>➡</b> Please choose time to or write time using format HH:mm, e.g. ${formatTime(exampleTime)}"
|
||||
|
||||
override def timeFromIs(timeFrom: LocalTime): String = s"⏱ Time from is ${formatTime(timeFrom)}"
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import com.lbs.api.json.model.{Event, TermExt}
|
||||
@@ -32,7 +31,7 @@ trait Lang {
|
||||
|
||||
def label: String
|
||||
|
||||
protected def capitalizeFirstLetter(str: String): String = {
|
||||
protected def capitalize(str: String): String = {
|
||||
if (str != null && str != "") {
|
||||
val fistCapitalLetter = str.head.toTitleCase
|
||||
s"$fistCapitalLetter${str.tail.toLowerCase}"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import com.lbs.server.conversation.Login.UserId
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import com.lbs.server.repository.model
|
||||
@@ -17,10 +16,13 @@ class Localization {
|
||||
private val cachedLangs = new ConcurrentHashMap[Long, Lang]
|
||||
|
||||
def lang(userId: Long): Lang = {
|
||||
cachedLangs.computeIfAbsent(userId, _ => {
|
||||
cachedLangs.computeIfAbsent(
|
||||
userId,
|
||||
_ => {
|
||||
val settings = dataService.findSettings(userId)
|
||||
settings.map(s => Lang(s.lang)).getOrElse(En)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import com.lbs.api.json.model.{Event, TermExt}
|
||||
@@ -40,14 +39,18 @@ object Pl extends Lang {
|
||||
s"""<b>➡</b> Czy na pewno chcesz anulować wizytę?
|
||||
|
|
||||
|⏱ <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")}
|
||||
|${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)}
|
||||
|${capitalize(service)}: ${event.title}
|
||||
|${capitalize(clinic)}: ${event.clinic
|
||||
.map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}")
|
||||
.getOrElse("Telemedicine")}
|
||||
|""".stripMargin
|
||||
|
||||
override def chooseDateFrom(exampleDate: LocalDateTime): String = s"<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: LocalDateTime): 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"
|
||||
|
||||
@@ -74,18 +77,19 @@ object Pl extends Lang {
|
||||
override def book: String = "Zarezerwuj"
|
||||
|
||||
override def confirmAppointment(term: TermExt): String =
|
||||
|
||||
s"""<b>➡</b> Czy potwierdzasz wizytę?
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}""".stripMargin
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}""".stripMargin
|
||||
|
||||
override def appointmentIsConfirmed: String = "👍 Twoja wizyta została potwierdzona!"
|
||||
|
||||
override def monitoringHasBeenCreated: String = "👍 Stworzono monitoring! Sprawdź aktywne monitoringi przez /monitorings"
|
||||
override def monitoringHasBeenCreated: String =
|
||||
"👍 Stworzono monitoring! Sprawdź aktywne monitoringi przez /monitorings"
|
||||
|
||||
override def unableToCreateMonitoring(reason: String): String = s"👎 Nie udało się stworzyć monitoringu. Powód: $reason."
|
||||
override def unableToCreateMonitoring(reason: String): String =
|
||||
s"👎 Nie udało się stworzyć monitoringu. Powód: $reason."
|
||||
|
||||
override def chooseTypeOfMonitoring: String = "<b>➡</b> Wybierz typ monitoringu"
|
||||
|
||||
@@ -97,7 +101,8 @@ object Pl extends Lang {
|
||||
|
||||
override def pleaseSpecifyOffset: String = "<b>➡</b> Podaj offset w godzinach albo kliknij Nie"
|
||||
|
||||
override def visitAlreadyExists: String = "<b>➡</b> Wizyta została juz zarezerwowana. Czy chcesz zaktualizować jej termin?"
|
||||
override def visitAlreadyExists: String =
|
||||
"<b>➡</b> Wizyta została juz zarezerwowana. Czy chcesz zaktualizować jej termin?"
|
||||
|
||||
override def city: String = "miasto"
|
||||
|
||||
@@ -118,9 +123,9 @@ object Pl extends Lang {
|
||||
|
|
||||
|📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}""".stripMargin
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}""".stripMargin
|
||||
|
||||
override def deactivated: String = "👍 Wyłączony! Sprawdź aktywne monitoringi przez /monitorings"
|
||||
|
||||
@@ -132,7 +137,8 @@ object Pl extends Lang {
|
||||
withAnyVariant(
|
||||
s"""<b>➡</b> Podaj fragment nazwy ${config.name}
|
||||
|Na przykład: <b>${config.partialExample}</b> jeśli szukasz <b>${config.example}</b>""".stripMargin,
|
||||
config.isAnyAllowed)
|
||||
config.isAnyAllowed
|
||||
)
|
||||
|
||||
override def pleaseEnterStaticDataNameOrPrevious(config: StaticDataConfig): String =
|
||||
s"""<b>➡</b> Podaj fragment nazwy ${config.name}
|
||||
@@ -141,7 +147,7 @@ object Pl extends Lang {
|
||||
|lub wybierz ${config.name} z poprzednich wyszukiwań""".stripMargin
|
||||
|
||||
override def staticDataIs(config: StaticDataConfig, label: String): String =
|
||||
s"<b>✅</b> ${capitalizeFirstLetter(config.name)} jest <b>$label</b>"
|
||||
s"<b>✅</b> ${capitalize(config.name)} jest <b>$label</b>"
|
||||
|
||||
override def pleaseChooseStaticDataNameOrAny(config: StaticDataConfig): String =
|
||||
withAnyVariant(s"<b>➡</b> Wybierz ${config.name}", config.isAnyAllowed)
|
||||
@@ -149,7 +155,9 @@ object Pl extends Lang {
|
||||
override def staticNotFound(config: StaticDataConfig): String =
|
||||
withAnyVariant(
|
||||
s"""<b>➡</b> Brak wyników 😔
|
||||
|Proszę podaj nazwę ${config.name} jeszcze raz""", config.isAnyAllowed)
|
||||
|Proszę podaj nazwę ${config.name} jeszcze raz""",
|
||||
config.isAnyAllowed
|
||||
)
|
||||
|
||||
override def loginAndPasswordAreOk: String =
|
||||
s"""✅ Brawo! Login i hasło są OK!
|
||||
@@ -186,8 +194,8 @@ object Pl extends Lang {
|
||||
|
||||
override def termEntry(term: TermExt, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}
|
||||
|<b>➡</b> /book_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -197,9 +205,11 @@ object Pl extends Lang {
|
||||
|
||||
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")}
|
||||
|${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)}
|
||||
|${capitalize(service)}: ${event.title}
|
||||
|${capitalize(clinic)}: ${event.clinic
|
||||
.map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}")
|
||||
.getOrElse("Telemedicine")}
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
@@ -208,9 +218,11 @@ object Pl extends Lang {
|
||||
|
||||
override def reservedVisitEntry(event: Event, page: Int, index: Int): String =
|
||||
s"""⏱ <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")}
|
||||
|${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)}
|
||||
|${capitalize(service)}: ${event.title}
|
||||
|${capitalize(clinic)}: ${event.clinic
|
||||
.map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}")
|
||||
.getOrElse("Telemedicine")}
|
||||
|<b>➡</b> /cancel_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -224,10 +236,10 @@ object Pl extends Lang {
|
||||
override def monitoringEntry(monitoring: Monitoring, page: Int, index: Int): String =
|
||||
s"""📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|Sposób rejestracji: ${if (monitoring.autobook) "Automatyczny" else "Ręczny"}
|
||||
|<b>➡</b> /cancel_$index
|
||||
|
|
||||
@@ -236,10 +248,10 @@ object Pl extends Lang {
|
||||
override def monitoringHistoryEntry(monitoring: Monitoring, page: Int, index: Int): String =
|
||||
s"""📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|Sposób rejestracji: ${if (monitoring.autobook) "Automatyczny" else "Ręczny"}
|
||||
|<b>➡</b> /repeat_$index
|
||||
|
|
||||
@@ -258,10 +270,10 @@ object Pl extends Lang {
|
||||
|
||||
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.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|/reserve_${monitoring.recordId}_${term.term.scheduleId}_${minutesSinceBeginOf2018(term.term.dateTimeFrom.get)}
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -276,10 +288,10 @@ object Pl extends Lang {
|
||||
|
|
||||
|📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|
|
||||
|<b>➡</b> Stwórz nowy monitoring przez /book""".stripMargin
|
||||
|
||||
@@ -287,10 +299,10 @@ object Pl extends Lang {
|
||||
s"""👍 Zarezerwowaliśmy za Ciebie termin!
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}""".stripMargin
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}
|
||||
|${capitalize(city)}: ${monitoring.cityName}""".stripMargin
|
||||
|
||||
override def maximumMonitoringsLimitExceeded: String = "Maksymalna liczba monitoringów uzytkownika to 10"
|
||||
|
||||
@@ -315,7 +327,8 @@ object Pl extends Lang {
|
||||
|
||||
override def configureOffset: String = "<b>➡</b> Wybierz opcje offsetu"
|
||||
|
||||
override def pleaseEnterOffset(current: Int): String = s"<b>➡</b> Podaj domyślny offset. Obecny offset: <b>$current</b>"
|
||||
override def pleaseEnterOffset(current: Int): String =
|
||||
s"<b>➡</b> Podaj domyślny offset. Obecny offset: <b>$current</b>"
|
||||
|
||||
override def alwaysAskOffset(enabled: Boolean): String = s"${if (enabled) "✅ " else ""}Zawsze pytaj o offset"
|
||||
|
||||
@@ -353,9 +366,11 @@ object Pl extends Lang {
|
||||
|
||||
override def moreParameters: String = "🛠 Więcej opcji"
|
||||
|
||||
override def chooseTimeFrom(exampleTime: LocalTime): String = s"<b>➡</b> Wybierz godzinę OD albo zapisz w formacie HH:mm, np. ${formatTime(exampleTime)}"
|
||||
override def chooseTimeFrom(exampleTime: LocalTime): String =
|
||||
s"<b>➡</b> Wybierz godzinę OD albo zapisz w formacie HH:mm, np. ${formatTime(exampleTime)}"
|
||||
|
||||
override def chooseTimeTo(exampleTime: LocalTime): String = s"<b>➡</b> Wybierz godzinę DO albo zapisz w formacie HH:mm ${formatTime(exampleTime)}"
|
||||
override def chooseTimeTo(exampleTime: LocalTime): String =
|
||||
s"<b>➡</b> Wybierz godzinę DO albo zapisz w formacie HH:mm ${formatTime(exampleTime)}"
|
||||
|
||||
override def timeFromIs(timeFrom: LocalTime): String = s"⏱ Godzina OD: ${formatTime(timeFrom)}"
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.lang
|
||||
|
||||
import com.lbs.api.json.model.{Event, TermExt}
|
||||
@@ -40,14 +39,18 @@ object Ua extends Lang {
|
||||
s"""<b>➡</b> Ви впевнені, що хочете скасувати візит?
|
||||
|
|
||||
|⏱ <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")}
|
||||
|${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)}
|
||||
|${capitalize(service)}: ${event.title}
|
||||
|${capitalize(clinic)}: ${event.clinic
|
||||
.map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}")
|
||||
.getOrElse("Telemedicine")}
|
||||
|""".stripMargin
|
||||
|
||||
override def chooseDateFrom(exampleDate: LocalDateTime): String = s"<b>➡</b> Будь ласка, виберіть початкову дату або введіть її, використовуючи формат dd-MM, наприклад ${formatDateShort(exampleDate)}"
|
||||
override def chooseDateFrom(exampleDate: LocalDateTime): String =
|
||||
s"<b>➡</b> Будь ласка, виберіть початкову дату або введіть її, використовуючи формат dd-MM, наприклад ${formatDateShort(exampleDate)}"
|
||||
|
||||
override def chooseDateTo(exampleDate: LocalDateTime): 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 = "🔍 Знайти терміни"
|
||||
|
||||
@@ -74,18 +77,18 @@ object Ua extends Lang {
|
||||
override def book: String = "Зарезервувати"
|
||||
|
||||
override def confirmAppointment(term: TermExt): String =
|
||||
|
||||
s"""<b>➡</b> Ви хотіли б підтвердити резервацію візиту?
|
||||
|
|
||||
|⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}""".stripMargin
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}""".stripMargin
|
||||
|
||||
override def appointmentIsConfirmed: String = "👍 Ваш візит було підтверджено!"
|
||||
|
||||
override def monitoringHasBeenCreated: String = "👍 Моніторинг був створений! Список активних /monitorings"
|
||||
|
||||
override def unableToCreateMonitoring(reason: String): String = s"👎 Не вдається створити моніторинг. Причина: $reason."
|
||||
override def unableToCreateMonitoring(reason: String): String =
|
||||
s"👎 Не вдається створити моніторинг. Причина: $reason."
|
||||
|
||||
override def chooseTypeOfMonitoring: String = "<b>➡</b> Будь ласка, виберіть тип моніторингу"
|
||||
|
||||
@@ -97,7 +100,8 @@ object Ua extends Lang {
|
||||
|
||||
override def pleaseSpecifyOffset: String = "<b>➡</b> Будь ласка, надішліть мені зміщення в годинах, або натисніть Ні"
|
||||
|
||||
override def visitAlreadyExists: String = "<b>➡</b> Резервація для такого сервісу вже існує. Чі хотіли би ви змінити термін?"
|
||||
override def visitAlreadyExists: String =
|
||||
"<b>➡</b> Резервація для такого сервісу вже існує. Чі хотіли би ви змінити термін?"
|
||||
|
||||
override def city: String = "місто"
|
||||
|
||||
@@ -118,9 +122,9 @@ object Ua extends Lang {
|
||||
|
|
||||
|📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}""".stripMargin
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}""".stripMargin
|
||||
|
||||
override def deactivated: String = "👍 Деактивовано! Список активних /monitorings"
|
||||
|
||||
@@ -132,7 +136,8 @@ object Ua extends Lang {
|
||||
withAnyVariant(
|
||||
s"""<b>➡</b> Будь ласка, введіть частково ${config.name}
|
||||
|Наприклад: <b>${config.partialExample}</b> якщо ви шукаете <b>${config.example}""".stripMargin,
|
||||
config.isAnyAllowed)
|
||||
config.isAnyAllowed
|
||||
)
|
||||
|
||||
override def pleaseEnterStaticDataNameOrPrevious(config: StaticDataConfig): String =
|
||||
s"""<b>➡</b> Будь ласка, введіть частково ${config.name}
|
||||
@@ -141,7 +146,7 @@ object Ua extends Lang {
|
||||
|або оберіть ${config.name} з попередніх пошуків""".stripMargin
|
||||
|
||||
override def staticDataIs(config: StaticDataConfig, label: String): String =
|
||||
s"<b>✅</b> ${capitalizeFirstLetter(config.name)} <b>$label</b>"
|
||||
s"<b>✅</b> ${capitalize(config.name)} <b>$label</b>"
|
||||
|
||||
override def pleaseChooseStaticDataNameOrAny(config: StaticDataConfig): String =
|
||||
withAnyVariant(s"<b>➡</b> Будь ласка, виберіть ${config.name}", config.isAnyAllowed)
|
||||
@@ -149,7 +154,9 @@ object Ua extends Lang {
|
||||
override def staticNotFound(config: StaticDataConfig): String =
|
||||
withAnyVariant(
|
||||
s"""<b>➡</b> Нічого не знайдено 😔
|
||||
|Будь ласка, введіть ${config.name} знову""".stripMargin, config.isAnyAllowed)
|
||||
|Будь ласка, введіть ${config.name} знову""".stripMargin,
|
||||
config.isAnyAllowed
|
||||
)
|
||||
|
||||
override def loginAndPasswordAreOk: String =
|
||||
s"""✅ Супер! Логін і пароль збережено
|
||||
@@ -185,8 +192,8 @@ object Ua extends Lang {
|
||||
|
||||
override def termEntry(term: TermExt, page: Int, index: Int): String =
|
||||
s"""⏱ <b>${formatDateTime(term.term.dateTimeFrom, locale)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${term.term.clinic}
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}
|
||||
|<b>➡</b> /book_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -196,9 +203,11 @@ object Ua extends Lang {
|
||||
|
||||
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")}
|
||||
|${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)}
|
||||
|${capitalize(service)}: ${event.title}
|
||||
|${capitalize(clinic)}: ${event.clinic
|
||||
.map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}")
|
||||
.getOrElse("Telemedicine")}
|
||||
|
|
||||
|""".stripMargin
|
||||
|
||||
@@ -207,9 +216,11 @@ object Ua extends Lang {
|
||||
|
||||
override def reservedVisitEntry(event: Event, page: Int, index: Int): String =
|
||||
s"""⏱ <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")}
|
||||
|${capitalize(doctor)}: ${capitalize(event.doctor.name)} ${capitalize(event.doctor.lastname)}
|
||||
|${capitalize(service)}: ${event.title}
|
||||
|${capitalize(clinic)}: ${event.clinic
|
||||
.map(c => s"${capitalize(c.city)} - ${capitalize(c.address)}")
|
||||
.getOrElse("Telemedicine")}
|
||||
|<b>➡</b> /cancel_$index
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -223,10 +234,10 @@ object Ua extends Lang {
|
||||
override def monitoringEntry(monitoring: Monitoring, page: Int, index: Int): String =
|
||||
s"""📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|Тип: ${if (monitoring.autobook) "Автоматичний" else "Ручний"}
|
||||
|<b>➡</b> /cancel_$index
|
||||
|
|
||||
@@ -235,10 +246,10 @@ object Ua extends Lang {
|
||||
override def monitoringHistoryEntry(monitoring: Monitoring, page: Int, index: Int): String =
|
||||
s"""📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|Тип: ${if (monitoring.autobook) "Автоматичний" else "Ручний"}
|
||||
|<b>➡</b> /repeat_$index
|
||||
|
|
||||
@@ -257,10 +268,10 @@ object Ua extends Lang {
|
||||
|
||||
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.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|/reserve_${monitoring.recordId}_${term.term.scheduleId}_${minutesSinceBeginOf2018(term.term.dateTimeFrom.get)}
|
||||
|
|
||||
|""".stripMargin
|
||||
@@ -275,10 +286,10 @@ object Ua extends Lang {
|
||||
|
|
||||
|📅 <b>${formatDate(monitoring.dateFrom, locale)}</b> -> <b>${formatDate(monitoring.dateTo, locale)}</b>
|
||||
|⏱ <b>${formatTime(monitoring.timeFrom)}</b> -> <b>${formatTime(monitoring.timeTo)}</b>
|
||||
|${capitalizeFirstLetter(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalizeFirstLetter(service)}: ${monitoring.serviceName}
|
||||
|${capitalizeFirstLetter(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}
|
||||
|${capitalize(doctor)}: ${monitoring.doctorName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${monitoring.clinicName}
|
||||
|${capitalize(city)}: ${monitoring.cityName}
|
||||
|
|
||||
|<b>➡</b> Створити новий моніторінг /book""".stripMargin
|
||||
|
||||
@@ -286,10 +297,10 @@ object Ua extends Lang {
|
||||
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.term.clinic}
|
||||
|${capitalizeFirstLetter(city)}: ${monitoring.cityName}""".stripMargin
|
||||
|${capitalize(doctor)}: ${term.term.doctor.firstName} ${term.term.doctor.lastName}
|
||||
|${capitalize(service)}: ${monitoring.serviceName}
|
||||
|${capitalize(clinic)}: ${term.term.clinic}
|
||||
|${capitalize(city)}: ${monitoring.cityName}""".stripMargin
|
||||
|
||||
override def maximumMonitoringsLimitExceeded: String = "Максимальна кількість моніторінгів 10"
|
||||
|
||||
@@ -314,7 +325,8 @@ object Ua extends Lang {
|
||||
|
||||
override def configureOffset: String = "<b>➡</b> Будь ласка, сконфігуруйте зміщення"
|
||||
|
||||
override def pleaseEnterOffset(current: Int): String = s"<b>➡</b> Будь ласка, введіть зміщення за замовчуванням. Поточне: <b>$current</b>"
|
||||
override def pleaseEnterOffset(current: Int): String =
|
||||
s"<b>➡</b> Будь ласка, введіть зміщення за замовчуванням. Поточне: <b>$current</b>"
|
||||
|
||||
override def alwaysAskOffset(enabled: Boolean): String = s"${if (enabled) "✅ " else ""}Завжди питати зміщення"
|
||||
|
||||
@@ -352,9 +364,11 @@ object Ua extends Lang {
|
||||
|
||||
override def moreParameters: String = "🛠 Більше налаштувань"
|
||||
|
||||
override def chooseTimeFrom(exampleTime: LocalTime): String = s"<b>➡</b> Будь ласка, виберіть початковий час або введіть час, використовуючи формат HH:mm, наприклад ${formatTime(exampleTime)}"
|
||||
override def chooseTimeFrom(exampleTime: LocalTime): String =
|
||||
s"<b>➡</b> Будь ласка, виберіть початковий час або введіть час, використовуючи формат HH:mm, наприклад ${formatTime(exampleTime)}"
|
||||
|
||||
override def chooseTimeTo(exampleTime: LocalTime): String = s"<b>➡</b> Будь ласка, виберіть кінцевий час або введіть час, використовуючи формат HH:mm, наприклад ${formatTime(exampleTime)}"
|
||||
override def chooseTimeTo(exampleTime: LocalTime): String =
|
||||
s"<b>➡</b> Будь ласка, виберіть кінцевий час або введіть час, використовуючи формат HH:mm, наприклад ${formatTime(exampleTime)}"
|
||||
|
||||
override def timeFromIs(timeFrom: LocalTime): String = s"⏱ Початковий час ${formatTime(timeFrom)}"
|
||||
|
||||
@@ -362,5 +376,6 @@ object Ua extends Lang {
|
||||
|
||||
override def canNotDetectPayer(error: String): String = s"Не можу визначити платника. Причина: $error"
|
||||
|
||||
override def pleaseChoosePayer: String = "<b>➡</b> Не можу визначити платника за замовчуванням. Будь ласка, виберіть платника"
|
||||
override def pleaseChoosePayer: String =
|
||||
"<b>➡</b> Не можу визначити платника за замовчуванням. Будь ласка, виберіть платника"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository
|
||||
|
||||
import com.lbs.server.repository.model.{CityHistory, ClinicHistory, Credentials, DoctorHistory, JLong, Monitoring, ServiceHistory, Settings, Source, SystemUser}
|
||||
@@ -18,29 +17,40 @@ class DataRepository(@Autowired em: EntityManager) {
|
||||
em.createQuery(
|
||||
"""select city from CityHistory city where city.recordId in
|
||||
| (select max(c.recordId) from CityHistory c where c.accountId = :accountId group by c.name order by MAX(c.time) desc)
|
||||
| order by city.time desc""".stripMargin, classOf[CityHistory])
|
||||
.setParameter("accountId", accountId)
|
||||
| order by city.time desc""".stripMargin,
|
||||
classOf[CityHistory]
|
||||
).setParameter("accountId", accountId)
|
||||
.setMaxResults(maxHistory)
|
||||
.getResultList.asScala.toSeq
|
||||
.getResultList
|
||||
.asScala
|
||||
.toSeq
|
||||
}
|
||||
|
||||
def getClinicHistory(accountId: Long, cityId: Long): Seq[ClinicHistory] = {
|
||||
em.createQuery(
|
||||
"""select clinic from ClinicHistory clinic where clinic.recordId in
|
||||
| (select max(c.recordId) from ClinicHistory c where c.accountId = :accountId and c.cityId = :cityId group by c.name order by MAX(c.time) desc)
|
||||
| order by clinic.time desc""".stripMargin, classOf[ClinicHistory])
|
||||
.setParameter("accountId", accountId)
|
||||
| order by clinic.time desc""".stripMargin,
|
||||
classOf[ClinicHistory]
|
||||
).setParameter("accountId", accountId)
|
||||
.setParameter("cityId", cityId)
|
||||
.setMaxResults(maxHistory)
|
||||
.getResultList.asScala.toSeq
|
||||
.getResultList
|
||||
.asScala
|
||||
.toSeq
|
||||
}
|
||||
|
||||
def getServiceHistory(accountId: Long, cityId: Long, clinicId: Option[Long]): Seq[ServiceHistory] = {
|
||||
val query = em.createQuery(
|
||||
val query = em
|
||||
.createQuery(
|
||||
s"""select service from ServiceHistory service where service.recordId in
|
||||
| (select max(s.recordId) from ServiceHistory s where s.accountId = :accountId and s.cityId = :cityId
|
||||
| and s.clinicId ${clinicId.map(_ => "= :clinicId").getOrElse("IS NULL")} group by s.name order by MAX(s.time) desc)
|
||||
| order by service.time desc""".stripMargin, classOf[ServiceHistory])
|
||||
| and s.clinicId ${clinicId
|
||||
.map(_ => "= :clinicId")
|
||||
.getOrElse("IS NULL")} group by s.name order by MAX(s.time) desc)
|
||||
| order by service.time desc""".stripMargin,
|
||||
classOf[ServiceHistory]
|
||||
)
|
||||
.setParameter("accountId", accountId)
|
||||
.setParameter("cityId", cityId)
|
||||
.setMaxResults(maxHistory)
|
||||
@@ -49,12 +59,15 @@ class DataRepository(@Autowired em: EntityManager) {
|
||||
}
|
||||
|
||||
def getDoctorHistory(accountId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): Seq[DoctorHistory] = {
|
||||
val query = em.createQuery(
|
||||
val query = em
|
||||
.createQuery(
|
||||
s"""select doctor from DoctorHistory doctor where doctor.recordId in
|
||||
| (select max(d.recordId) from DoctorHistory d where d.accountId = :accountId
|
||||
| and d.cityId = :cityId and d.clinicId ${clinicId.map(_ => "= :clinicId").getOrElse("IS NULL")}
|
||||
| and d.serviceId = :serviceId group by d.name order by MAX(d.time) desc)
|
||||
| order by doctor.time desc""".stripMargin, classOf[DoctorHistory])
|
||||
| order by doctor.time desc""".stripMargin,
|
||||
classOf[DoctorHistory]
|
||||
)
|
||||
.setParameter("accountId", accountId)
|
||||
.setParameter("cityId", cityId)
|
||||
.setParameter("serviceId", serviceId)
|
||||
@@ -65,158 +78,204 @@ class DataRepository(@Autowired em: EntityManager) {
|
||||
|
||||
def findCredentials(accountId: Long): Option[Credentials] = {
|
||||
em.createQuery(
|
||||
"select credentials from Credentials credentials where credentials.accountId = :accountId", classOf[Credentials])
|
||||
.setParameter("accountId", accountId)
|
||||
.getResultList.asScala.headOption
|
||||
"select credentials from Credentials credentials where credentials.accountId = :accountId",
|
||||
classOf[Credentials]
|
||||
).setParameter("accountId", accountId)
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def getActiveMonitorings: Seq[Monitoring] = {
|
||||
em.createQuery(
|
||||
"""select monitoring from Monitoring monitoring where monitoring.active = true""".stripMargin, classOf[Monitoring])
|
||||
.getResultList.asScala.toSeq
|
||||
"""select monitoring from Monitoring monitoring where monitoring.active = true""".stripMargin,
|
||||
classOf[Monitoring]
|
||||
).getResultList
|
||||
.asScala
|
||||
.toSeq
|
||||
}
|
||||
|
||||
def getActiveMonitoringsCount(accountId: Long): JLong = {
|
||||
em.createQuery(
|
||||
"""select count(monitoring) from Monitoring monitoring where monitoring.active = true
|
||||
| and monitoring.accountId = :accountId""".stripMargin, classOf[JLong])
|
||||
.setParameter("accountId", accountId)
|
||||
| and monitoring.accountId = :accountId""".stripMargin,
|
||||
classOf[JLong]
|
||||
).setParameter("accountId", accountId)
|
||||
.getSingleResult
|
||||
}
|
||||
|
||||
def getActiveMonitorings(accountId: Long): Seq[Monitoring] = {
|
||||
em.createQuery(
|
||||
"""select monitoring from Monitoring monitoring where monitoring.active = true
|
||||
| and monitoring.accountId = :accountId order by monitoring.dateTo asc""".stripMargin, classOf[Monitoring])
|
||||
.setParameter("accountId", accountId)
|
||||
.getResultList.asScala.toSeq
|
||||
| and monitoring.accountId = :accountId order by monitoring.dateTo asc""".stripMargin,
|
||||
classOf[Monitoring]
|
||||
).setParameter("accountId", accountId)
|
||||
.getResultList
|
||||
.asScala
|
||||
.toSeq
|
||||
}
|
||||
|
||||
def getAllMonitoringsCount(accountId: Long): JLong = {
|
||||
em.createQuery(
|
||||
"""select count(monitoring) from Monitoring monitoring where
|
||||
| monitoring.accountId = :accountId""".stripMargin, classOf[JLong])
|
||||
.setParameter("accountId", accountId)
|
||||
| monitoring.accountId = :accountId""".stripMargin,
|
||||
classOf[JLong]
|
||||
).setParameter("accountId", accountId)
|
||||
.getSingleResult
|
||||
}
|
||||
|
||||
def getMonitoringsPage(accountId: Long, start: Int, count: Int): Seq[Monitoring] = {
|
||||
em.createQuery(
|
||||
"""select monitoring from Monitoring monitoring where monitoring.accountId = :accountId
|
||||
| order by monitoring.created desc""".stripMargin, classOf[Monitoring])
|
||||
.setParameter("accountId", accountId)
|
||||
| order by monitoring.created desc""".stripMargin,
|
||||
classOf[Monitoring]
|
||||
).setParameter("accountId", accountId)
|
||||
.setFirstResult(start)
|
||||
.setMaxResults(count)
|
||||
.getResultList.asScala.toSeq
|
||||
.getResultList
|
||||
.asScala
|
||||
.toSeq
|
||||
}
|
||||
|
||||
|
||||
|
||||
def findActiveMonitoring(accountId: Long, cityId: Long, serviceId: Long, doctorId: Long): Option[Monitoring] = {
|
||||
em.createQuery(
|
||||
"""select monitoring from Monitoring monitoring where monitoring.active = true
|
||||
| and monitoring.accountId = :accountId
|
||||
| and monitoring.cityId = :cityId
|
||||
| and monitoring.serviceId = :serviceId
|
||||
| and monitoring.doctorId = :doctorId""".stripMargin, classOf[Monitoring])
|
||||
.setParameter("accountId", accountId)
|
||||
| and monitoring.doctorId = :doctorId""".stripMargin,
|
||||
classOf[Monitoring]
|
||||
).setParameter("accountId", accountId)
|
||||
.setParameter("cityId", cityId)
|
||||
.setParameter("serviceId", serviceId)
|
||||
.setParameter("doctorId", doctorId)
|
||||
.getResultList.asScala.headOption
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def getActiveMonitoringsSince(since: ZonedDateTime): Seq[Monitoring] = {
|
||||
em.createQuery(
|
||||
"""select monitoring from Monitoring monitoring where monitoring.active = true
|
||||
| and monitoring.created > :since""".stripMargin, classOf[Monitoring])
|
||||
.setParameter("since", since)
|
||||
.getResultList.asScala.toSeq
|
||||
| and monitoring.created > :since""".stripMargin,
|
||||
classOf[Monitoring]
|
||||
).setParameter("since", since)
|
||||
.getResultList
|
||||
.asScala
|
||||
.toSeq
|
||||
}
|
||||
|
||||
def findMonitoring(accountId: Long, monitoringId: Long): Option[Monitoring] = {
|
||||
em.createQuery(
|
||||
"""select monitoring from Monitoring monitoring where monitoring.accountId = :accountId
|
||||
| and monitoring.recordId = :monitoringId""".stripMargin, classOf[Monitoring])
|
||||
.setParameter("accountId", accountId)
|
||||
| and monitoring.recordId = :monitoringId""".stripMargin,
|
||||
classOf[Monitoring]
|
||||
).setParameter("accountId", accountId)
|
||||
.setParameter("monitoringId", monitoringId)
|
||||
.getResultList.asScala.headOption
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def findSettings(userId: Long): Option[Settings] = {
|
||||
em.createQuery(
|
||||
"select settings from Settings settings where settings.userId = :userId", classOf[Settings])
|
||||
em.createQuery("select settings from Settings settings where settings.userId = :userId", classOf[Settings])
|
||||
.setParameter("userId", userId)
|
||||
.getResultList.asScala.headOption
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def findUserId(chatId: String, sourceSystemId: Long): Option[JLong] = {
|
||||
em.createQuery(
|
||||
"select source.userId from Source source where source.chatId = :chatId" +
|
||||
" and source.sourceSystemId = :sourceSystemId", classOf[JLong])
|
||||
.setParameter("chatId", chatId)
|
||||
" and source.sourceSystemId = :sourceSystemId",
|
||||
classOf[JLong]
|
||||
).setParameter("chatId", chatId)
|
||||
.setParameter("sourceSystemId", sourceSystemId)
|
||||
.getResultList.asScala.headOption
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def findCredentialsByUsername(username: String, userId: Long): Option[Credentials] = {
|
||||
em.createQuery(
|
||||
"select credentials from Credentials credentials where credentials.username = :username" +
|
||||
" and credentials.userId = :userId", classOf[Credentials])
|
||||
.setParameter("username", username)
|
||||
" and credentials.userId = :userId",
|
||||
classOf[Credentials]
|
||||
).setParameter("username", username)
|
||||
.setParameter("userId", userId)
|
||||
.getResultList.asScala.headOption
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def findSource(chatId: String, sourceSystemId: Long, userId: Long): Option[Source] = {
|
||||
em.createQuery(
|
||||
"select source from Source source where source.chatId = :chatId" +
|
||||
" and source.sourceSystemId = :sourceSystemId" +
|
||||
" and userId = :userId", classOf[Source])
|
||||
.setParameter("chatId", chatId)
|
||||
" and userId = :userId",
|
||||
classOf[Source]
|
||||
).setParameter("chatId", chatId)
|
||||
.setParameter("sourceSystemId", sourceSystemId)
|
||||
.setParameter("userId", userId)
|
||||
.getResultList.asScala.headOption
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def findUserIdBySource(chatId: String, sourceSystemId: Long): Option[JLong] = {
|
||||
em.createQuery(
|
||||
"select source.userId from Source source where source.chatId = :chatId" +
|
||||
" and source.sourceSystemId = :sourceSystemId", classOf[JLong])
|
||||
.setParameter("chatId", chatId)
|
||||
" and source.sourceSystemId = :sourceSystemId",
|
||||
classOf[JLong]
|
||||
).setParameter("chatId", chatId)
|
||||
.setParameter("sourceSystemId", sourceSystemId)
|
||||
.getResultList.asScala.headOption
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def findAccountId(userId: Long): Option[JLong] = {
|
||||
em.createQuery(
|
||||
"select systemUser.activeAccountId from SystemUser systemUser where systemUser.recordId = :recordId", classOf[JLong])
|
||||
.setParameter("recordId", userId)
|
||||
.getResultList.asScala.headOption
|
||||
"select systemUser.activeAccountId from SystemUser systemUser where systemUser.recordId = :recordId",
|
||||
classOf[JLong]
|
||||
).setParameter("recordId", userId)
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def findUser(userId: Long): Option[SystemUser] = {
|
||||
em.createQuery(
|
||||
"select systemUser from SystemUser systemUser where systemUser.recordId = :recordId", classOf[SystemUser])
|
||||
.setParameter("recordId", userId)
|
||||
.getResultList.asScala.headOption
|
||||
"select systemUser from SystemUser systemUser where systemUser.recordId = :recordId",
|
||||
classOf[SystemUser]
|
||||
).setParameter("recordId", userId)
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def getUserCredentials(userId: Long): Seq[Credentials] = {
|
||||
em.createQuery(
|
||||
"select credentials from Credentials credentials where credentials.userId = :userId", classOf[Credentials])
|
||||
.setParameter("userId", userId)
|
||||
.getResultList.asScala.toSeq
|
||||
"select credentials from Credentials credentials where credentials.userId = :userId",
|
||||
classOf[Credentials]
|
||||
).setParameter("userId", userId)
|
||||
.getResultList
|
||||
.asScala
|
||||
.toSeq
|
||||
}
|
||||
|
||||
def findUserCredentialsByUserIdAndAccountId(userId: Long, accountId: Long): Option[Credentials] = {
|
||||
em.createQuery(
|
||||
"""select credentials from Credentials credentials where credentials.userId = :userId
|
||||
| and credentials.accountId = :accountId
|
||||
""".stripMargin, classOf[Credentials])
|
||||
.setParameter("userId", userId)
|
||||
""".stripMargin,
|
||||
classOf[Credentials]
|
||||
).setParameter("userId", userId)
|
||||
.setParameter("accountId", accountId)
|
||||
.getResultList.asScala.headOption
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
}
|
||||
|
||||
def saveEntity[T](entity: T): T = {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
@@ -38,7 +37,15 @@ class DoctorHistory extends History with RecordId {
|
||||
}
|
||||
|
||||
object DoctorHistory {
|
||||
def apply(accountId: Long, id: Long, name: String, cityId: Long, clinicId: Option[Long], serviceId: Long, time: ZonedDateTime): DoctorHistory = {
|
||||
def apply(
|
||||
accountId: Long,
|
||||
id: Long,
|
||||
name: String,
|
||||
cityId: Long,
|
||||
clinicId: Option[Long],
|
||||
serviceId: Long,
|
||||
time: ZonedDateTime
|
||||
): DoctorHistory = {
|
||||
val doctor = new DoctorHistory
|
||||
doctor.accountId = accountId
|
||||
doctor.id = id
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
|
||||
trait History {
|
||||
def id: JLong
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.{LocalTime, ZonedDateTime}
|
||||
@@ -98,10 +97,30 @@ class Monitoring extends RecordId {
|
||||
}
|
||||
|
||||
object Monitoring {
|
||||
def apply(userId: Long, accountId: Long, chatId: String, sourceSystemId: Long, payerId: Long, cityId: Long, cityName: String, clinicId: Option[Long], clinicName: String,
|
||||
serviceId: Long, serviceName: String, doctorId: Option[Long], doctorName: String, dateFrom: ZonedDateTime,
|
||||
dateTo: ZonedDateTime, autobook: Boolean = false, rebookIfExists: Boolean = false, created: ZonedDateTime = ZonedDateTime.now(), timeFrom: LocalTime, timeTo: LocalTime,
|
||||
active: Boolean = true, offset: Int): Monitoring = {
|
||||
def apply(
|
||||
userId: Long,
|
||||
accountId: Long,
|
||||
chatId: String,
|
||||
sourceSystemId: Long,
|
||||
payerId: Long,
|
||||
cityId: Long,
|
||||
cityName: String,
|
||||
clinicId: Option[Long],
|
||||
clinicName: String,
|
||||
serviceId: Long,
|
||||
serviceName: String,
|
||||
doctorId: Option[Long],
|
||||
doctorName: String,
|
||||
dateFrom: ZonedDateTime,
|
||||
dateTo: ZonedDateTime,
|
||||
autobook: Boolean = false,
|
||||
rebookIfExists: Boolean = false,
|
||||
created: ZonedDateTime = ZonedDateTime.now(),
|
||||
timeFrom: LocalTime,
|
||||
timeTo: LocalTime,
|
||||
active: Boolean = true,
|
||||
offset: Int
|
||||
): Monitoring = {
|
||||
val monitoring = new Monitoring
|
||||
monitoring.userId = userId
|
||||
monitoring.accountId = accountId
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
@@ -34,7 +33,14 @@ class ServiceHistory extends History with RecordId {
|
||||
}
|
||||
|
||||
object ServiceHistory {
|
||||
def apply(accountId: Long, id: Long, name: String, cityId: Long, clinicId: Option[Long], time: ZonedDateTime): ServiceHistory = {
|
||||
def apply(
|
||||
accountId: Long,
|
||||
id: Long,
|
||||
name: String,
|
||||
cityId: Long,
|
||||
clinicId: Option[Long],
|
||||
time: ZonedDateTime
|
||||
): ServiceHistory = {
|
||||
val service = new ServiceHistory
|
||||
service.accountId = accountId
|
||||
service.id = id
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence.{Access, AccessType, Column, Entity}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository.model
|
||||
|
||||
import javax.persistence._
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.repository
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.service
|
||||
|
||||
import cats.instances.either._
|
||||
@@ -32,7 +31,9 @@ class ApiService extends SessionSupport {
|
||||
|
||||
def getAllFacilities(accountId: Long, cityId: Long, serviceVariantId: Long): ThrowableOr[List[IdName]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.dictionaryFacilitiesAndDoctors(session, cityId = Some(cityId), serviceVariantId = Some(serviceVariantId)).map(_.facilities)
|
||||
luxmedApi
|
||||
.dictionaryFacilitiesAndDoctors(session, cityId = Some(cityId), serviceVariantId = Some(serviceVariantId))
|
||||
.map(_.facilities)
|
||||
}
|
||||
|
||||
def getAllServices(accountId: Long): ThrowableOr[List[DictionaryServiceVariants]] =
|
||||
@@ -42,16 +43,28 @@ class ApiService extends SessionSupport {
|
||||
|
||||
def getAllDoctors(accountId: Long, cityId: Long, serviceVariantId: Long): ThrowableOr[List[Doctor]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.dictionaryFacilitiesAndDoctors(session, cityId = Some(cityId), serviceVariantId = Some(serviceVariantId)).map(_.doctors)
|
||||
luxmedApi
|
||||
.dictionaryFacilitiesAndDoctors(session, cityId = Some(cityId), serviceVariantId = Some(serviceVariantId))
|
||||
.map(_.doctors)
|
||||
}
|
||||
|
||||
def getAvailableTerms(accountId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long, doctorId: Option[Long],
|
||||
fromDate: LocalDateTime, toDate: LocalDateTime, timeFrom: LocalTime, timeTo: LocalTime,
|
||||
languageId: Long = 10): ThrowableOr[List[TermExt]] =
|
||||
def getAvailableTerms(
|
||||
accountId: Long,
|
||||
cityId: Long,
|
||||
clinicId: Option[Long],
|
||||
serviceId: Long,
|
||||
doctorId: Option[Long],
|
||||
fromDate: LocalDateTime,
|
||||
toDate: LocalDateTime,
|
||||
timeFrom: LocalTime,
|
||||
timeTo: LocalTime,
|
||||
languageId: Long = 10
|
||||
): ThrowableOr[List[TermExt]] =
|
||||
withSession(accountId) { session =>
|
||||
val termsEither = luxmedApi.termsIndex(session, cityId, clinicId, serviceId, doctorId,
|
||||
fromDate, toDate, languageId = languageId)
|
||||
.map(termsIndexResponse => termsIndexResponse.termsForService.termsForDays
|
||||
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 =>
|
||||
@@ -66,36 +79,62 @@ class ApiService extends SessionSupport {
|
||||
}
|
||||
}
|
||||
|
||||
def reservationLockterm(accountId: Long, xsrfToken: XsrfToken, reservationLocktermRequest: ReservationLocktermRequest): ThrowableOr[ReservationLocktermResponse] =
|
||||
def reservationLockterm(
|
||||
accountId: Long,
|
||||
xsrfToken: XsrfToken,
|
||||
reservationLocktermRequest: ReservationLocktermRequest
|
||||
): ThrowableOr[ReservationLocktermResponse] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.reservationLockterm(session, xsrfToken, reservationLocktermRequest)
|
||||
}
|
||||
|
||||
def deleteTemporaryReservation(accountId: Long, xsrfToken: XsrfToken, temporaryReservationId: Long): ThrowableOr[Unit] =
|
||||
def deleteTemporaryReservation(
|
||||
accountId: Long,
|
||||
xsrfToken: XsrfToken,
|
||||
temporaryReservationId: Long
|
||||
): ThrowableOr[Unit] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.deleteTemporaryReservation(session, xsrfToken, temporaryReservationId)
|
||||
}
|
||||
|
||||
def reservationConfirm(accountId: Long, xsrfToken: XsrfToken, reservationConfirmRequest: ReservationConfirmRequest): ThrowableOr[ReservationConfirmResponse] =
|
||||
def reservationConfirm(
|
||||
accountId: Long,
|
||||
xsrfToken: XsrfToken,
|
||||
reservationConfirmRequest: ReservationConfirmRequest
|
||||
): ThrowableOr[ReservationConfirmResponse] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.reservationConfirm(session, xsrfToken, reservationConfirmRequest)
|
||||
}
|
||||
|
||||
def reservationChangeTerm(accountId: Long, xsrfToken: XsrfToken, reservationChangetermRequest: ReservationChangetermRequest): ThrowableOr[ReservationConfirmResponse] =
|
||||
def reservationChangeTerm(
|
||||
accountId: Long,
|
||||
xsrfToken: XsrfToken,
|
||||
reservationChangetermRequest: ReservationChangetermRequest
|
||||
): ThrowableOr[ReservationConfirmResponse] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.reservationChangeTerm(session, xsrfToken, reservationChangetermRequest)
|
||||
}
|
||||
|
||||
def history(accountId: Long, fromDate: LocalDateTime = LocalDateTime.now().minusYears(1),
|
||||
toDate: LocalDateTime = LocalDateTime.now()): ThrowableOr[List[Event]] =
|
||||
def history(
|
||||
accountId: Long,
|
||||
fromDate: LocalDateTime = LocalDateTime.now().minusYears(1),
|
||||
toDate: LocalDateTime = LocalDateTime.now()
|
||||
): ThrowableOr[List[Event]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.events(session, fromDate.atZone(DateTimeUtil.Zone), toDate.atZone(DateTimeUtil.Zone)).map(_.events.filter(_.status == "Realized"))
|
||||
luxmedApi
|
||||
.events(session, fromDate.atZone(DateTimeUtil.Zone), toDate.atZone(DateTimeUtil.Zone))
|
||||
.map(_.events.filter(_.status == "Realized"))
|
||||
}
|
||||
|
||||
def reserved(accountId: Long, fromDate: LocalDateTime = LocalDateTime.now(),
|
||||
toDate: LocalDateTime = LocalDateTime.now().plusMonths(3)): ThrowableOr[List[Event]] =
|
||||
def reserved(
|
||||
accountId: Long,
|
||||
fromDate: LocalDateTime = LocalDateTime.now(),
|
||||
toDate: LocalDateTime = LocalDateTime.now().plusMonths(3)
|
||||
): ThrowableOr[List[Event]] =
|
||||
withSession(accountId) { session =>
|
||||
luxmedApi.events(session, fromDate.atZone(DateTimeUtil.Zone), toDate.atZone(DateTimeUtil.Zone)).map(_.events.filter(_.status == "Reserved"))
|
||||
luxmedApi
|
||||
.events(session, fromDate.atZone(DateTimeUtil.Zone), toDate.atZone(DateTimeUtil.Zone))
|
||||
.map(_.events.filter(_.status == "Reserved"))
|
||||
}
|
||||
|
||||
def deleteReservation(accountId: Long, reservationId: Long): ThrowableOr[HttpResponse[String]] =
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.service
|
||||
|
||||
import com.lbs.api.json.model.IdName
|
||||
@@ -31,7 +30,12 @@ class DataService {
|
||||
dataRepository.getServiceHistory(userId, cityId, clinicId).mapTo[Seq[IdName]]
|
||||
}
|
||||
|
||||
def getLatestDoctorsByCityIdAndClinicIdAndServiceId(userId: Long, cityId: Long, clinicId: Option[Long], serviceId: Long): Seq[IdName] = {
|
||||
def getLatestDoctorsByCityIdAndClinicIdAndServiceId(
|
||||
userId: Long,
|
||||
cityId: Long,
|
||||
clinicId: Option[Long],
|
||||
serviceId: Long
|
||||
): Seq[IdName] = {
|
||||
dataRepository.getDoctorHistory(userId, cityId, clinicId, serviceId).mapTo[Seq[IdName]]
|
||||
}
|
||||
|
||||
@@ -78,7 +82,9 @@ class DataService {
|
||||
|
||||
def findUserAndAccountIdBySource(source: MessageSource): Option[(Long, Long)] = {
|
||||
val userIdMaybe = dataRepository.findUserId(source.chatId, source.sourceSystem.id).map(_.toLong)
|
||||
userIdMaybe.flatMap(userId => dataRepository.findAccountId(userId).map(_.toLong).map(accountId => userId -> accountId))
|
||||
userIdMaybe.flatMap(userId =>
|
||||
dataRepository.findAccountId(userId).map(_.toLong).map(accountId => userId -> accountId)
|
||||
)
|
||||
}
|
||||
|
||||
def findCredentialsByUsername(username: String, userId: Long): Option[Credentials] = {
|
||||
@@ -109,8 +115,8 @@ class DataService {
|
||||
|
||||
@Transactional
|
||||
def saveCredentials(source: MessageSource, username: String, password: String): Credentials = {
|
||||
val userMaybe = dataRepository.findUserIdBySource(source.chatId, source.sourceSystem.id).flatMap {
|
||||
userId => dataRepository.findUser(userId).map(_ -> userId)
|
||||
val userMaybe = dataRepository.findUserIdBySource(source.chatId, source.sourceSystem.id).flatMap { userId =>
|
||||
dataRepository.findUser(userId).map(_ -> userId)
|
||||
}
|
||||
userMaybe match {
|
||||
case Some((user, userId)) =>
|
||||
@@ -171,7 +177,9 @@ class DataService {
|
||||
val service = ServiceHistory(accountId, serviceId.id, serviceId.name, cityId.id, clinicId.optionalId, time)
|
||||
dataRepository.saveEntity(service)
|
||||
|
||||
val doctorMaybe = doctorId.optionalId.map(id => DoctorHistory(accountId, id, doctorId.name, cityId.id, clinicId.optionalId, serviceId.id, time))
|
||||
val doctorMaybe = doctorId.optionalId.map(id =>
|
||||
DoctorHistory(accountId, id, doctorId.name, cityId.id, clinicId.optionalId, serviceId.id, time)
|
||||
)
|
||||
doctorMaybe.foreach(dataRepository.saveEntity)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.service
|
||||
|
||||
import com.lbs.api.exception.InvalidLoginOrPasswordException
|
||||
@@ -68,8 +67,17 @@ class MonitoringService extends StrictLogging {
|
||||
private def monitor(monitoring: Monitoring): Unit = {
|
||||
logger.debug(s"Looking for available terms. Monitoring [#${monitoring.recordId}]")
|
||||
val dateFrom = optimizeDateFrom(monitoring.dateFrom.toLocalDateTime, monitoring.offset)
|
||||
val termsEither = apiService.getAvailableTerms(monitoring.accountId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId,
|
||||
monitoring.doctorId, dateFrom, monitoring.dateTo.toLocalDateTime, timeFrom = monitoring.timeFrom, timeTo = monitoring.timeTo)
|
||||
val termsEither = apiService.getAvailableTerms(
|
||||
monitoring.accountId,
|
||||
monitoring.cityId,
|
||||
monitoring.clinicId,
|
||||
monitoring.serviceId,
|
||||
monitoring.doctorId,
|
||||
dateFrom,
|
||||
monitoring.dateTo.toLocalDateTime,
|
||||
timeFrom = monitoring.timeFrom,
|
||||
timeTo = monitoring.timeTo
|
||||
)
|
||||
termsEither match {
|
||||
case Right(terms) =>
|
||||
if (terms.nonEmpty) {
|
||||
@@ -105,7 +113,9 @@ class MonitoringService extends StrictLogging {
|
||||
val delaySnapshot = delay
|
||||
val periodSnapshot = period
|
||||
val future = monitoringExecutor.schedule(monitor(monitoring), delaySnapshot, periodSnapshot)
|
||||
logger.debug(s"Scheduled monitoring: [#${monitoring.recordId}] with delay: $delaySnapshot and period: $periodSnapshot")
|
||||
logger.debug(
|
||||
s"Scheduled monitoring: [#${monitoring.recordId}] with delay: $delaySnapshot and period: $periodSnapshot"
|
||||
)
|
||||
activeMonitorings += (monitoring.recordId -> (monitoring -> future))
|
||||
}
|
||||
}
|
||||
@@ -127,7 +137,8 @@ class MonitoringService extends StrictLogging {
|
||||
|
||||
private def disableOutdated(): Unit = {
|
||||
val now = ZonedDateTime.now()
|
||||
val toDisable = activeMonitorings.collect { case (id, (monitoring, _)) if monitoring.dateTo.isBefore(now) =>
|
||||
val toDisable = activeMonitorings.collect {
|
||||
case (id, (monitoring, _)) if monitoring.dateTo.isBefore(now) =>
|
||||
id -> monitoring
|
||||
}
|
||||
|
||||
@@ -150,13 +161,36 @@ class MonitoringService extends StrictLogging {
|
||||
private def bookAppointment(term: TermExt, monitoring: Monitoring, rebookIfExists: Boolean): Unit = {
|
||||
val bookingResult = for {
|
||||
xsrfToken <- apiService.getXsrfToken(monitoring.accountId)
|
||||
reservationLocktermResponse <- apiService.reservationLockterm(monitoring.accountId, xsrfToken, term.mapTo[ReservationLocktermRequest])
|
||||
reservationLocktermResponse <- apiService.reservationLockterm(
|
||||
monitoring.accountId,
|
||||
xsrfToken,
|
||||
term.mapTo[ReservationLocktermRequest]
|
||||
)
|
||||
temporaryReservationId = reservationLocktermResponse.value.temporaryReservationId
|
||||
response <- if (reservationLocktermResponse.value.changeTermAvailable && rebookIfExists) {
|
||||
response <-
|
||||
if (reservationLocktermResponse.value.changeTermAvailable && rebookIfExists) {
|
||||
logger.info(s"Service [${monitoring.serviceName}] is already booked. Trying to update term")
|
||||
bookOrUnlockTerm(monitoring.accountId, xsrfToken, temporaryReservationId, apiService.reservationChangeTerm(_, xsrfToken, (reservationLocktermResponse, term).mapTo[ReservationChangetermRequest]))
|
||||
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]))
|
||||
bookOrUnlockTerm(
|
||||
monitoring.accountId,
|
||||
xsrfToken,
|
||||
temporaryReservationId,
|
||||
apiService.reservationConfirm(
|
||||
_,
|
||||
xsrfToken,
|
||||
(reservationLocktermResponse, term).mapTo[ReservationConfirmRequest]
|
||||
)
|
||||
)
|
||||
}
|
||||
} yield response
|
||||
bookingResult match {
|
||||
@@ -168,7 +202,12 @@ class MonitoringService extends StrictLogging {
|
||||
}
|
||||
}
|
||||
|
||||
private def bookOrUnlockTerm[T](accountId: Long, xsrfToken: XsrfToken, temporaryReservationId: Long, fn: (Long) => Either[Throwable, T]): Either[Throwable, T] = {
|
||||
private def bookOrUnlockTerm[T](
|
||||
accountId: Long,
|
||||
xsrfToken: XsrfToken,
|
||||
temporaryReservationId: Long,
|
||||
fn: (Long) => Either[Throwable, T]
|
||||
): Either[Throwable, T] = {
|
||||
fn(accountId) match {
|
||||
case r @ Left(_) =>
|
||||
apiService.deleteTemporaryReservation(accountId, xsrfToken, temporaryReservationId)
|
||||
@@ -218,11 +257,22 @@ class MonitoringService extends StrictLogging {
|
||||
val monitoringMaybe = dataService.findMonitoring(accountId, monitoringId)
|
||||
monitoringMaybe match {
|
||||
case Some(monitoring) =>
|
||||
val termsEither = apiService.getAvailableTerms(monitoring.accountId, monitoring.cityId, monitoring.clinicId, monitoring.serviceId,
|
||||
monitoring.doctorId, monitoring.dateFrom.toLocalDateTime, monitoring.dateTo.toLocalDateTime, timeFrom = monitoring.timeFrom, timeTo = monitoring.timeTo)
|
||||
val termsEither = apiService.getAvailableTerms(
|
||||
monitoring.accountId,
|
||||
monitoring.cityId,
|
||||
monitoring.clinicId,
|
||||
monitoring.serviceId,
|
||||
monitoring.doctorId,
|
||||
monitoring.dateFrom.toLocalDateTime,
|
||||
monitoring.dateTo.toLocalDateTime,
|
||||
timeFrom = monitoring.timeFrom,
|
||||
timeTo = monitoring.timeTo
|
||||
)
|
||||
termsEither match {
|
||||
case Right(terms) =>
|
||||
val termMaybe = terms.find(term => term.term.scheduleId == scheduleId && minutesSinceBeginOf2018(term.term.dateTimeFrom.get) == time)
|
||||
val termMaybe = terms.find(term =>
|
||||
term.term.scheduleId == scheduleId && minutesSinceBeginOf2018(term.term.dateTimeFrom.get) == time
|
||||
)
|
||||
termMaybe match {
|
||||
case Some(term) =>
|
||||
bookAppointment(term, monitoring, rebookIfExists = true)
|
||||
@@ -232,7 +282,8 @@ class MonitoringService extends StrictLogging {
|
||||
case Left(ex: InvalidLoginOrPasswordException) =>
|
||||
logger.error(s"User entered invalid name or password. Monitoring will be disabled", ex)
|
||||
bot.sendMessage(monitoring.source, lang(monitoring.userId).loginHasChangedOrWrong)
|
||||
case Left(ex) => logger.error(s"Error occurred during receiving terms for monitoring [#${monitoring.recordId}]", ex)
|
||||
case Left(ex) =>
|
||||
logger.error(s"Error occurred during receiving terms for monitoring [#${monitoring.recordId}]", ex)
|
||||
}
|
||||
case None =>
|
||||
logger.debug(s"Monitoring [#$monitoringId] not found in db")
|
||||
@@ -240,9 +291,7 @@ class MonitoringService extends StrictLogging {
|
||||
}
|
||||
|
||||
implicit class MonitoringAsSource(monitoring: Monitoring) {
|
||||
def source: MessageSource = MessageSource(
|
||||
MessageSourceSystem(monitoring.sourceSystemId), monitoring.chatId
|
||||
)
|
||||
def source: MessageSource = MessageSource(MessageSourceSystem(monitoring.sourceSystemId), monitoring.chatId)
|
||||
}
|
||||
|
||||
private def lang(userId: Long) = localization.lang(userId)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.lbs.server.service
|
||||
|
||||
import com.lbs.api.exception.SessionExpiredException
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user