diff options
Diffstat (limited to 'src/main/scala/xyz/driver/pdsuidomain/services')
20 files changed, 1778 insertions, 0 deletions
diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala new file mode 100644 index 0000000..bc59f0c --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala @@ -0,0 +1,133 @@ +package xyz.driver.pdsuidomain.services + + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db._ +import xyz.driver.pdsuicommon.domain.LongId +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.Arm + +import scala.concurrent.Future + +object ArmService { + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + trait DefaultNotFoundError { + def userMessage: String = "Arm not found" + } + + sealed trait GetByIdReply + object GetByIdReply { + + case class Entity(x: Arm) extends GetByIdReply + + type Error = GetByIdReply with DomainError + + case object NotFoundError + extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + extends GetByIdReply with DomainError + + } + + sealed trait GetListReply + object GetListReply { + type Error = GetListReply with DomainError + + case class EntityList(xs: Seq[Arm], totalFound: Int) extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + } + + sealed trait UpdateReply + object UpdateReply { + + case class Updated(updated: Arm) extends UpdateReply + + type Error = UpdateReply with DomainError + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + + case class AlreadyExistsError(x: Arm) extends UpdateReply with DomainError { + val userMessage = s"The arm with such name of trial already exists." + } + + implicit def toPhiString(reply: UpdateReply): PhiString = reply match { + case Updated(x) => phi"Updated($x)" + case x: Error => DomainError.toPhiString(x) + } + } + + sealed trait CreateReply + object CreateReply { + case class Created(x: Arm) extends CreateReply + + type Error = CreateReply with DomainError + + case object AuthorizationError + extends CreateReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends CreateReply with DomainError + + case class AlreadyExistsError(x: Arm) extends CreateReply with DomainError { + val userMessage = s"The arm with this name of trial already exists." + } + + implicit def toPhiString(reply: CreateReply): PhiString = reply match { + case Created(x) => phi"Created($x)" + case x: Error => DomainError.toPhiString(x) + } + } + + sealed trait DeleteReply + object DeleteReply { + case object Deleted extends DeleteReply + + type Error = DeleteReply with DomainError + + case object NotFoundError + extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends DeleteReply with DomainError + } +} + +trait ArmService { + + import ArmService._ + + def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def getById(armId: LongId[Arm])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def create(draftArm: Arm)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] + + def update(origArm: Arm, draftArm: Arm)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def delete(id: LongId[Arm])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala new file mode 100644 index 0000000..e3d806c --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala @@ -0,0 +1,131 @@ +package xyz.driver.pdsuidomain.services + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db._ +import xyz.driver.pdsuicommon.domain.LongId +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities._ + +import scala.concurrent.Future + +object CriterionService { + + trait DefaultNotFoundError { + def userMessage: String = "Criterion not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + case class RichCriterion(criterion: Criterion, + armIds: Seq[LongId[Arm]], + labels: Seq[CriterionLabel]) + object RichCriterion { + implicit def toPhiString(x: RichCriterion): PhiString = { + import x._ + phi"RichCriterion(criterion=$criterion, armIds=$armIds, labels=$labels)" + } + } + + sealed trait CreateReply + object CreateReply { + type Error = CreateReply with DomainError + + case class Created(x: RichCriterion) extends CreateReply + + case object AuthorizationError + extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String) extends CreateReply with DomainError + } + + sealed trait GetByIdReply + object GetByIdReply { + case class Entity(x: RichCriterion) extends GetByIdReply + + type Error = GetByIdReply with DomainError + + case object NotFoundError + extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + extends GetByIdReply with DomainError + + implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { + case x: DomainError => phi"GetByIdReply.Error($x)" + case Entity(x) => phi"GetByIdReply.Entity($x)" + } + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[RichCriterion], + totalFound: Int, + lastUpdate: Option[LocalDateTime]) extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + + case class Updated(updated: RichCriterion) extends UpdateReply + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + } + + sealed trait DeleteReply + object DeleteReply { + case object Deleted extends DeleteReply + + type Error = DeleteReply with DomainError + + case object NotFoundError + extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends DeleteReply with DomainError + } +} + +trait CriterionService { + + import CriterionService._ + + def create(draftRichCriterion: RichCriterion) + (implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] + + def getById(id: LongId[Criterion]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def update(origRichCriterion: RichCriterion, + draftRichCriterion: RichCriterion) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def delete(id: LongId[Criterion]) + (implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala new file mode 100644 index 0000000..cd242c9 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala @@ -0,0 +1,157 @@ +package xyz.driver.pdsuidomain.services + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db._ +import xyz.driver.pdsuicommon.domain.LongId +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities._ + +import scala.concurrent.Future + +object DocumentService { + + trait DefaultNotFoundError { + def userMessage: String = "Can not find the document" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait GetByIdReply + object GetByIdReply { + case class Entity(x: Document) extends GetByIdReply + + type Error = GetByIdReply with DomainError + + case object NotFoundError + extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + extends GetByIdReply with DomainError + + implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { + case x: DomainError => phi"GetByIdReply.Error($x)" + case Entity(x) => phi"GetByIdReply.Entity($x)" + } + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[Document], + totalFound: Int, + lastUpdate: Option[LocalDateTime]) extends GetListReply + + type Error = GetListReply with DomainError + + case object AuthorizationError + extends GetListReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) extends GetListReply with DomainError + } + + sealed trait CreateReply + object CreateReply { + case class Created(x: Document) extends CreateReply + + type Error = CreateReply with DomainError + + case object NotFoundError + extends CreateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends CreateReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends CreateReply with DomainError + } + + sealed trait UpdateReply + object UpdateReply { + case class Updated(updated: Document) extends UpdateReply + + type Error = UpdateReply with DomainError + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + + implicit def toPhiString(reply: UpdateReply): PhiString = reply match { + case Updated(x) => phi"Updated($x)" + case x: Error => DomainError.toPhiString(x) + } + } + + + sealed trait DeleteReply + object DeleteReply { + case object Deleted extends DeleteReply + + type Error = DeleteReply with DomainError + + case object NotFoundError + extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends DeleteReply with DomainError + } + +} + +trait DocumentService { + + import DocumentService._ + + + def getById(id: LongId[Document]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def create(draftDocument: Document)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] + + // Update operations are validated in internal.*Command + def update(orig: Document, draft: Document) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def delete(id: LongId[Document]) + (implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] + + def start(orig: Document) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def submit(orig: Document) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def restart(orig: Document) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def flag(orig: Document) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def resolve(orig: Document) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def unassign(orig: Document) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def archive(orig: Document) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala new file mode 100644 index 0000000..30fd348 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala @@ -0,0 +1,26 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.Sorting +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.entities.DocumentType +import xyz.driver.pdsuidomain.services.DocumentTypeService.GetListReply + +import scala.concurrent.Future + +object DocumentTypeService { + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[DocumentType], totalFound: Int) extends GetListReply + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError { + def userMessage: String = "Access denied" + } + } +} + +trait DocumentTypeService { + + def getAll(sorting: Option[Sorting] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala new file mode 100644 index 0000000..6cde411 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala @@ -0,0 +1,116 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} +import xyz.driver.pdsuicommon.domain.LongId +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities._ + +import scala.concurrent.Future + +object ExtractedDataService { + + trait DefaultNotFoundError { + def userMessage: String = "Extracted data hasn't been found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + case class RichExtractedData(extractedData: ExtractedData, + labels: List[ExtractedDataLabel]) + + object RichExtractedData { + implicit def toPhiString(x: RichExtractedData): PhiString = { + import x._ + phi"RichExtractedData(extractedData=$extractedData, labels=$labels)" + } + } + + sealed trait GetByIdReply + object GetByIdReply { + type Error = GetByIdReply with DomainError + case class Entity(x: RichExtractedData) extends GetByIdReply + + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object NotFoundError + extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError + + case class CommonError(userMessage: String) extends GetByIdReply with DomainError + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[RichExtractedData], totalFound: Int) extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait CreateReply + object CreateReply { + type Error = CreateReply with DomainError + case class Created(x: RichExtractedData) extends CreateReply + + case object AuthorizationError + extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String) extends CreateReply with DomainError + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + case class Updated(updated: RichExtractedData) extends UpdateReply + + case object AuthorizationError + extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + } + + sealed trait DeleteReply + object DeleteReply { + type Error = DeleteReply with DomainError + case object Deleted extends DeleteReply + + case object AuthorizationError + extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case object NotFoundError + extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError + + case class CommonError(userMessage: String) extends DeleteReply with DomainError + } +} + +trait ExtractedDataService { + + import ExtractedDataService._ + + def getById(id: LongId[ExtractedData]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def create(draftRichExtractedData: RichExtractedData) + (implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] + + def update(origRichExtractedData: RichExtractedData, + draftRichExtractedData: RichExtractedData) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def delete(id: LongId[ExtractedData]) + (implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala new file mode 100644 index 0000000..64ce3ea --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala @@ -0,0 +1,28 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.Sorting +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.entities.Hypothesis + +import scala.concurrent.Future + +object HypothesisService { + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[Hypothesis], totalFound: Int) extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError { + def userMessage: String = "Access denied" + } + } +} + +trait HypothesisService { + + import HypothesisService._ + + def getAll(sorting: Option[Sorting] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala new file mode 100644 index 0000000..d65c9f9 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala @@ -0,0 +1,85 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} +import xyz.driver.pdsuicommon.domain.LongId +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities._ + +import scala.concurrent.Future + +object InterventionService { + + trait DefaultNotFoundError { + def userMessage: String = "Intervention not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[InterventionWithArms], totalFound: Int) + extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait GetByIdReply + object GetByIdReply { + case class Entity(x: InterventionWithArms) extends GetByIdReply + + type Error = GetByIdReply with DomainError + + case object NotFoundError + extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + extends GetByIdReply with DomainError + + implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { + case x: DomainError => phi"GetByIdReply.Error($x)" + case Entity(x) => phi"GetByIdReply.Entity($x)" + } + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + + case class Updated(updated: InterventionWithArms) extends UpdateReply + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + } + +} + +trait InterventionService { + + import InterventionService._ + + def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def getById(id: LongId[Intervention]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def update(origIntervention: InterventionWithArms, + draftIntervention: InterventionWithArms) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala new file mode 100644 index 0000000..db7473e --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala @@ -0,0 +1,28 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.Sorting +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.entities.InterventionType + +import scala.concurrent.Future + +object InterventionTypeService { + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[InterventionType], totalFound: Int) extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError { + def userMessage: String = "Access denied" + } + } +} + +trait InterventionTypeService { + + import InterventionTypeService._ + + def getAll(sorting: Option[Sorting] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/KeywordService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/KeywordService.scala new file mode 100644 index 0000000..5ee69a2 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/KeywordService.scala @@ -0,0 +1,29 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.Sorting +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.entities.KeywordWithLabels + +import scala.concurrent.Future + +object KeywordService { + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[KeywordWithLabels], totalFound: Int) extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError { + def userMessage: String = "Access denied" + } + } +} + +trait KeywordService { + + import KeywordService._ + + def getAll(sorting: Option[Sorting] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala new file mode 100644 index 0000000..7b5aa66 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala @@ -0,0 +1,137 @@ +package xyz.driver.pdsuidomain.services + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db._ +import xyz.driver.pdsuicommon.domain.LongId +import xyz.driver.pdsuicommon.error._ +import xyz.driver.pdsuidomain.entities.MedicalRecord.PdfSource +import xyz.driver.pdsuidomain.entities._ + +import scala.concurrent.Future + +object MedicalRecordService { + + type PdfSourceFetcher = (String, String) => Future[PdfSource] + + trait DefaultNotFoundError { + def userMessage: String = "Medical record hasn't been found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait GetByIdReply + object GetByIdReply { + case class Entity(x: MedicalRecord) extends GetByIdReply + + type Error = GetByIdReply with DomainError + + case object NotFoundError extends GetByIdReply + with DomainError.NotFoundError with DefaultNotFoundError + + case class CommonError(userMessage: String) extends GetByIdReply + with DomainError + + case object AuthorizationError extends GetByIdReply + with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait GetPdfSourceReply + object GetPdfSourceReply { + type Error = GetPdfSourceReply with DomainError + + case class Entity(x: PdfSource.Channel) extends GetPdfSourceReply + + case object AuthorizationError + extends GetPdfSourceReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object NotFoundError + extends GetPdfSourceReply with DomainError.NotFoundError { + def userMessage: String = "Medical record PDF hasn't been found" + } + + case object RecordNotFoundError + extends GetPdfSourceReply with DomainError.NotFoundError with DefaultNotFoundError + + case class CommonError(userMessage: String) + extends GetPdfSourceReply with DomainError + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[MedicalRecord], totalFound: Int, lastUpdate: Option[LocalDateTime]) + extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait CreateReply + object CreateReply { + case class Created(x: MedicalRecord) extends CreateReply + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + + case class Updated(updated: MedicalRecord) extends UpdateReply + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + } + + case class Settings(pdfSourceBucket: String) +} + +trait MedicalRecordService { + + import MedicalRecordService._ + + def getById(recordId: LongId[MedicalRecord]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getPdfSource(recordId: LongId[MedicalRecord]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetPdfSourceReply] + + def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def create(draft: MedicalRecord): Future[CreateReply] + + def update(origRecord: MedicalRecord, + draftRecord: MedicalRecord) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def start(orig: MedicalRecord) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def submit(orig: MedicalRecord) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def restart(orig: MedicalRecord) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def flag(orig: MedicalRecord) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def resolve(orig: MedicalRecord) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def unassign(orig: MedicalRecord) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def archive(orig: MedicalRecord) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala new file mode 100644 index 0000000..ff95ed0 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala @@ -0,0 +1,126 @@ +package xyz.driver.pdsuidomain.services + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db._ +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities._ + +import scala.concurrent.Future + +object PatientCriterionService { + + case class DraftPatientCriterion(id: LongId[PatientCriterion], + eligibilityStatus: Option[FuzzyValue], + isVerified: Option[Boolean]) { + def applyTo(orig: PatientCriterion) = { + orig.copy( + eligibilityStatus = eligibilityStatus.orElse(orig.eligibilityStatus), + isVerified = isVerified.getOrElse(orig.isVerified) + ) + } + } + + trait DefaultPatientNotFoundError { + def userMessage: String = "Patient not found" + } + + trait DefaultNotFoundError { + def userMessage: String = "Patient criterion not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait GetListReply + object GetListReply { + type Error = GetListReply with DomainError + + case class EntityList(xs: Seq[(PatientCriterion, LongId[Label], List[Arm], Boolean)], + totalFound: Int, + lastUpdate: Option[LocalDateTime]) extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object PatientNotFoundError + extends GetListReply with DomainError.NotFoundError with DefaultPatientNotFoundError + + case class CommonError(userMessage: String) + extends GetListReply with DomainError + + } + + sealed trait GetByIdReply + object GetByIdReply { + type Error = GetByIdReply with DomainError + + case class Entity(x: PatientCriterion, + labelId: LongId[Label], + armList: List[Arm], + criterionIsCompound: Boolean) extends GetByIdReply + + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object NotFoundError + extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError + + case object PatientNotFoundError + extends GetByIdReply with DomainError.NotFoundError with DefaultPatientNotFoundError + + case class CommonError(userMessage: String) + extends GetByIdReply with DomainError + + implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { + case x: DomainError => phi"GetByIdReply.Error($x)" + case Entity(x, labelId, armList, criterionIsCompound) => + phi"GetByIdReply.Entity(entity=$x, labelId=$labelId, " + + phi"armList=$armList, criterionIsCompound=$criterionIsCompound)" + } + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + + case object Updated extends UpdateReply + + case object AuthorizationError + extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object PatientNotFoundError + extends UpdateReply with DomainError.NotFoundError with DefaultPatientNotFoundError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + } +} + +trait PatientCriterionService { + + import PatientCriterionService._ + + def getAll(patientId: UuidId[Patient], + filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def getById(patientId: UuidId[Patient], + id: LongId[PatientCriterion]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def updateList(patientId: UuidId[Patient], + draftEntities: List[DraftPatientCriterion]) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def update(origEntity: PatientCriterion, + draftEntity: PatientCriterion, + patientId: UuidId[Patient]) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala new file mode 100644 index 0000000..64b4b81 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala @@ -0,0 +1,137 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} +import xyz.driver.pdsuicommon.domain.{LongId, UuidId} +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.{Arm, Trial, _} + +import scala.concurrent.Future + +object PatientEligibleTrialService { + + trait DefaultNotFoundError { + def userMessage: String = "Patient eligible trial not found" + } + + trait DefaultPatientNotFoundError { + def userMessage: String = "Patient not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + case class RichPatientEligibleTrial(trial: Trial, + group: PatientTrialArmGroupView, + arms: List[Arm]) + object RichPatientEligibleTrial { + implicit def toPhiString(x: RichPatientEligibleTrial): PhiString = { + phi"RichPatientEligibleTrial(group=${x.group}, trial=${x.trial}, arms=${x.arms})" + } + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[RichPatientEligibleTrial], totalFound: Int) + extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object PatientNotFoundError + extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case class CommonError(userMessage: String) extends GetListReply with DomainError + } + + sealed trait GetByIdReply + object GetByIdReply { + case class Entity(x: RichPatientEligibleTrial) extends GetByIdReply + + type Error = GetByIdReply with DomainError + + case object NotFoundError + extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError + + case object PatientNotFoundError + extends GetByIdReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String) extends GetByIdReply with DomainError + + implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { + case x: DomainError => phi"GetByIdReply.Error($x)" + case Entity(x) => phi"GetByIdReply.Entity($x)" + } + } + + sealed trait GetCriterionListOfGroupReply + object GetCriterionListOfGroupReply { + case class EntityList(xs: Seq[(PatientCriterion, LongId[Label], List[Arm], Boolean)], totalFound: Int) + extends GetCriterionListOfGroupReply + + type Error = GetCriterionListOfGroupReply with DomainError + + case object AuthorizationError + extends GetCriterionListOfGroupReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object NotFoundError + extends GetCriterionListOfGroupReply with DefaultNotFoundError with DomainError.NotFoundError + + case object PatientNotFoundError + extends GetCriterionListOfGroupReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case class CommonError(userMessage: String) extends GetCriterionListOfGroupReply with DomainError + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + + case class Updated(updated: RichPatientEligibleTrial) extends UpdateReply + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object PatientNotFoundError + extends UpdateReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + + implicit def toPhiString(reply: UpdateReply): PhiString = reply match { + case Updated(x) => phi"Updated($x)" + case x: Error => DomainError.toPhiString(x) + } + } +} + +trait PatientEligibleTrialService { + + import PatientEligibleTrialService._ + + def getAll(patientId: UuidId[Patient], + filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def getById(patientId: UuidId[Patient], + id: LongId[PatientTrialArmGroup]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getCriterionListByGroupId(patientId: UuidId[Patient], + id: LongId[PatientTrialArmGroup]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetCriterionListOfGroupReply] + + def update(origEligibleTrialWithTrial: RichPatientEligibleTrial, + draftPatientTrialArmGroup: PatientTrialArmGroupView) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala new file mode 100644 index 0000000..dff595a --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala @@ -0,0 +1,105 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} +import xyz.driver.pdsuicommon.domain.UuidId +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.{Hypothesis, Patient, PatientHypothesis} + +import scala.concurrent.Future + +object PatientHypothesisService { + + trait DefaultNotFoundError { + def userMessage: String = "Patient hypothesis not found" + } + + trait DefaultPatientNotFoundError { + def userMessage: String = "Patient not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[PatientHypothesis], totalFound: Int) + extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object PatientNotFoundError + extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case class CommonError(userMessage: String) extends GetListReply with DomainError + } + + sealed trait GetByIdReply + object GetByIdReply { + case class Entity(x: PatientHypothesis) extends GetByIdReply + + type Error = GetByIdReply with DomainError + + case object NotFoundError + extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError + + case object PatientNotFoundError + extends GetByIdReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String) extends GetByIdReply with DomainError + + implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { + case x: DomainError => phi"GetByIdReply.Error($x)" + case Entity(x) => phi"GetByIdReply.Entity($x)" + } + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + + case class Updated(updated: PatientHypothesis) extends UpdateReply + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object PatientNotFoundError + extends UpdateReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + + implicit def toPhiString(reply: UpdateReply): PhiString = reply match { + case Updated(x) => phi"Updated($x)" + case x: Error => DomainError.toPhiString(x) + } + } +} + +trait PatientHypothesisService { + + import PatientHypothesisService._ + + def getAll(patientId: UuidId[Patient], + filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def getById(patientId: UuidId[Patient], + hypothesisId: UuidId[Hypothesis]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def update(origPatientHypothesis: PatientHypothesis, + draftPatientHypothesis: PatientHypothesis) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala new file mode 100644 index 0000000..8e791d4 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala @@ -0,0 +1,70 @@ +package xyz.driver.pdsuidomain.services + +import java.time.LocalDate + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db._ +import xyz.driver.pdsuicommon.domain.{LongId, UuidId} +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.entities._ + +import scala.concurrent.Future + +object PatientLabelEvidenceService { + + case class Aggregated(evidence: PatientLabelEvidence, + date: LocalDate, + documentType: String, + providerType: String) + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait GetByIdReply + object GetByIdReply { + case class Entity(x: Aggregated) extends GetByIdReply + + type Error = GetByIdReply with DomainError + + case class NotFoundError(userMessage: String) extends GetByIdReply + with DomainError.NotFoundError + + case class CommonError(userMessage: String) extends GetByIdReply + with DomainError + + case object AuthorizationError extends GetByIdReply + with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[Aggregated], totalFound: Int) + extends GetListReply + + type Error = GetListReply with DomainError + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String) extends GetListReply + with DomainError + } +} + +trait PatientLabelEvidenceService { + + import PatientLabelEvidenceService._ + + def getById(patientId: UuidId[Patient], + labelId: LongId[Label], + id: LongId[PatientLabelEvidence]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getAll(patientId: UuidId[Patient], + labelId: LongId[Label], + filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala new file mode 100644 index 0000000..1d488ad --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala @@ -0,0 +1,124 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db._ +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities._ + +import scala.concurrent.Future + +object PatientLabelService { + + trait DefaultNotFoundError { + def userMessage: String = "Patient label not found" + } + + trait DefaultPatientNotFoundError { + def userMessage: String = "Patient not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[(PatientLabel, Boolean)], totalFound: Int) + extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object PatientNotFoundError + extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case class CommonError(userMessage: String) extends GetListReply with DomainError + } + + sealed trait GetDefiningCriteriaListReply + object GetDefiningCriteriaListReply { + case class EntityList(xs: Seq[PatientLabel], totalFound: Int) + extends GetDefiningCriteriaListReply + + case object AuthorizationError + extends GetDefiningCriteriaListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object PatientNotFoundError + extends GetDefiningCriteriaListReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case class CommonError(userMessage: String) extends GetDefiningCriteriaListReply with DomainError + } + + sealed trait GetByLabelIdReply + object GetByLabelIdReply { + case class Entity(x: PatientLabel, isVerified: Boolean) extends GetByLabelIdReply + + type Error = GetByLabelIdReply with DomainError + + case object NotFoundError + extends GetByLabelIdReply with DefaultNotFoundError with DomainError.NotFoundError + + case object PatientNotFoundError + extends GetByLabelIdReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends GetByLabelIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String) extends GetByLabelIdReply with DomainError + + implicit def toPhiString(reply: GetByLabelIdReply): PhiString = reply match { + case x: DomainError => phi"GetByIdReply.Error($x)" + case Entity(x, y) => phi"GetByIdReply.Entity($x, $y)" + } + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + + case class Updated(updated: PatientLabel, isVerified: Boolean) extends UpdateReply + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object PatientNotFoundError + extends UpdateReply with DefaultPatientNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + + implicit def toPhiString(reply: UpdateReply): PhiString = reply match { + case Updated(x, y) => phi"Updated($x, $y)" + case x: Error => DomainError.toPhiString(x) + } + } +} + +trait PatientLabelService { + + import PatientLabelService._ + + def getAll(patientId: UuidId[Patient], + filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def getDefiningCriteriaList(patientId: UuidId[Patient], + hypothesisId: UuidId[Hypothesis], + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetDefiningCriteriaListReply] + + def getByLabelIdOfPatient(patientId: UuidId[Patient], + labelId: LongId[Label]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByLabelIdReply] + + def update(origPatientLabel: PatientLabel, + draftPatientLabel: PatientLabel) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala new file mode 100644 index 0000000..3f8b606 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala @@ -0,0 +1,105 @@ +package xyz.driver.pdsuidomain.services + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db._ +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities._ + +import scala.concurrent.Future + +object PatientService { + + trait DefaultNotFoundError { + def userMessage: String = "Patient not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[Patient], totalFound: Int, lastUpdate: Option[LocalDateTime]) + extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait GetByIdReply + object GetByIdReply { + case class Entity(x: Patient) extends GetByIdReply + + type Error = GetByIdReply with DomainError + + case object NotFoundError + extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + extends GetByIdReply with DomainError + + implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { + case x: DomainError => phi"GetByIdReply.Error($x)" + case Entity(x) => phi"GetByIdReply.Entity($x)" + } + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + + case class Updated(updated: Patient) extends UpdateReply + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + + implicit def toPhiString(reply: UpdateReply): PhiString = reply match { + case Updated(x) => phi"Updated($x)" + case x: Error => DomainError.toPhiString(x) + } + } +} + +trait PatientService { + + import PatientService._ + + def getById(id: UuidId[Patient]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def unassign(origPatient: Patient) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def start(origPatient: Patient) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def submit(origPatient: Patient) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def restart(origPatient: Patient) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def flag(origPatient: Patient) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def resolve(origPatient: Patient) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala new file mode 100644 index 0000000..49901a4 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala @@ -0,0 +1,27 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.Sorting +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.entities.ProviderType + +import scala.concurrent.Future + +object ProviderTypeService { + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[ProviderType], totalFound: Int) extends GetListReply + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError { + def userMessage: String = "Access denied" + } + } +} + +trait ProviderTypeService { + + import ProviderTypeService._ + + def getAll(sorting: Option[Sorting] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala new file mode 100644 index 0000000..4417a54 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala @@ -0,0 +1,54 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.entities.ScrapedTrial + +import scala.concurrent.Future + +object ScrapedTrialsService { + + sealed trait GetRawTrialReply + object GetRawTrialReply { + type Error = GetRawTrialReply with DomainError + + case class TrialRawEntity(rawTrial: ScrapedTrial) extends GetRawTrialReply + + case object NotFoundError extends GetRawTrialReply with DomainError.NotFoundError { + override def userMessage: String = "Raw clinical trial not found" + } + } + + sealed trait GetRawTrialOptReply + object GetRawTrialOptReply { + case class TrialRawEntity(rawTrial: Option[ScrapedTrial]) extends GetRawTrialOptReply + } + + sealed trait GetAllRawTrialsExceptReply + object GetAllRawTrialsExceptReply { + case class MultipleRawTrials(rawTrials: Seq[ScrapedTrial]) + extends GetAllRawTrialsExceptReply + } + + sealed trait GetHtmlForReply + object GetHtmlForReply { + type TrialHtmlMap = Map[String, String] + + /** + * @param trialHtmlMap nctId -> html + */ + case class HtmlMap(trialHtmlMap: TrialHtmlMap) extends GetHtmlForReply + } +} + +trait ScrapedTrialsService { + + import ScrapedTrialsService._ + + def getRawTrial(nctId: String): Future[GetRawTrialReply] + + def getRawTrialOpt(nctId: String): Future[GetRawTrialOptReply] + + def getAllRawTrialsExcept(nctIds: Seq[String], limit: Int): Future[GetAllRawTrialsExceptReply] + + def getHtmlFor(nctIds: Set[String]): Future[GetHtmlForReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala new file mode 100644 index 0000000..d086c5f --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala @@ -0,0 +1,28 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db.Sorting +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.entities.StudyDesign + +import scala.concurrent.Future + +object StudyDesignService { + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[StudyDesign], totalFound: Int) extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError { + def userMessage: String = "Access denied" + } + } +} + +trait StudyDesignService { + + import StudyDesignService._ + + def getAll(sorting: Option[Sorting] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala new file mode 100644 index 0000000..4af4449 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala @@ -0,0 +1,132 @@ +package xyz.driver.pdsuidomain.services + + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext +import xyz.driver.pdsuicommon.db._ +import xyz.driver.pdsuicommon.domain.StringId +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.Trial +import xyz.driver.pdsuidomain.entities.Trial.PdfSource + +import scala.concurrent.Future + +object TrialService { + + trait DefaultNotFoundError { + def userMessage: String = "Trial not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait GetListReply + object GetListReply { + case class EntityList(xs: Seq[Trial], totalFound: Int, lastUpdate: Option[LocalDateTime]) + extends GetListReply + + case object AuthorizationError + extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait GetByIdReply + object GetByIdReply { + case class Entity(x: Trial) extends GetByIdReply + + type Error = GetByIdReply with DomainError + + case object NotFoundError + extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + extends GetByIdReply with DomainError + + implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { + case x: DomainError => phi"GetByIdReply.Error($x)" + case Entity(x) => phi"GetByIdReply.Entity($x)" + } + } + + sealed trait GetPdfSourceReply + object GetPdfSourceReply { + type Error = GetPdfSourceReply with DomainError + + case class Entity(x: PdfSource) extends GetPdfSourceReply + + case object AuthorizationError + extends GetPdfSourceReply with DomainError.AuthorizationError with DefaultAccessDeniedError + + case object NotFoundError + extends GetPdfSourceReply with DomainError.NotFoundError { + def userMessage: String = "Trial's PDF hasn't been found" + } + + case object TrialNotFoundError + extends GetPdfSourceReply with DomainError.NotFoundError with DefaultNotFoundError + + case class CommonError(userMessage: String) + extends GetPdfSourceReply with DomainError + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + + case class Updated(updated: Trial) extends UpdateReply + + case object NotFoundError + extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError + + case object AuthorizationError + extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError + + case class CommonError(userMessage: String) + extends UpdateReply with DomainError + + implicit def toPhiString(reply: UpdateReply): PhiString = reply match { + case Updated(x) => phi"Updated($x)" + case x: Error => DomainError.toPhiString(x) + } + } +} + +trait TrialService { + + import TrialService._ + + def getById(id: StringId[Trial]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getPdfSource(trialId: StringId[Trial]) + (implicit requestContext: AuthenticatedRequestContext): Future[GetPdfSourceReply] + + def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None) + (implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] + + def update(origTrial: Trial, draftTrial: Trial) + (implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def start(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def submit(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def restart(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def flag(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def resolve(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def archive(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def unassign(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def removeTrialDetails(trialId: StringId[Trial]): Unit +} |