From 54d0c6f7e7d7040e214cd2595a260bc65f356e33 Mon Sep 17 00:00:00 2001 From: Vyatcheslav Suharnikov Date: Fri, 28 Jul 2017 13:40:28 +0300 Subject: PDSUI-2157 Create own messages table for Documents, Medical Records and Patients --- .../scala/xyz/driver/pdsuicommon/acl/ACL.scala | 33 ++++++-- .../pdsuidomain/entities/DocumentIssue.scala | 25 ++++++ .../pdsuidomain/entities/MedicalRecordIssue.scala | 25 ++++++ .../driver/pdsuidomain/entities/PatientIssue.scala | 23 ++++++ .../json/documentissue/ApiDocumentIssue.scala | 48 +++++++++++ .../documentissue/ApiPartialDocumentIssue.scala | 52 ++++++++++++ .../json/patientissue/ApiPartialPatientIssue.scala | 41 ++++++++++ .../json/patientissue/ApiPatientIssue.scala | 42 ++++++++++ .../json/recordissue/ApiPartialRecordIssue.scala | 52 ++++++++++++ .../formats/json/recordissue/ApiRecordIssue.scala | 48 +++++++++++ .../services/DocumentIssueService.scala | 93 ++++++++++++++++++++++ .../services/MedicalRecordIssueService.scala | 93 ++++++++++++++++++++++ .../pdsuidomain/services/PatientIssueService.scala | 93 ++++++++++++++++++++++ 13 files changed, 663 insertions(+), 5 deletions(-) create mode 100644 src/main/scala/xyz/driver/pdsuidomain/entities/DocumentIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecordIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/entities/PatientIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/services/DocumentIssueService.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordIssueService.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/services/PatientIssueService.scala diff --git a/src/main/scala/xyz/driver/pdsuicommon/acl/ACL.scala b/src/main/scala/xyz/driver/pdsuicommon/acl/ACL.scala index e13b45f..e360398 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/acl/ACL.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/acl/ACL.scala @@ -48,6 +48,15 @@ object ACL extends PhiLogging { read = Set(RecordAdmin) ) + object MedicalRecordIssue + extends BaseACL( + label = "medical record issue", + create = Set(RecordCleaner, RecordOrganizer, RecordAdmin), + read = Set(RecordCleaner, RecordOrganizer, RecordAdmin), + update = Set(RecordCleaner, RecordOrganizer, RecordAdmin), + delete = Set(RecordCleaner, RecordOrganizer, RecordAdmin) + ) + object Document extends BaseACL( label = "document", @@ -63,6 +72,15 @@ object ACL extends PhiLogging { read = Set(RecordAdmin) ) + object DocumentIssue + extends BaseACL( + label = "document issue", + create = Set(RecordAdmin, DocumentExtractor), + read = Set(RecordAdmin, DocumentExtractor), + update = Set(RecordAdmin, DocumentExtractor), + delete = Set(RecordAdmin, DocumentExtractor) + ) + object ExtractedData extends BaseACL( label = "extracted data", @@ -86,11 +104,7 @@ object ACL extends PhiLogging { object Message extends BaseACL( - label = "message", - create = RepRoles ++ TreatmentMatchingRoles, - read = RepRoles ++ TreatmentMatchingRoles, - update = RepRoles ++ TreatmentMatchingRoles, - delete = RepRoles ++ TreatmentMatchingRoles + label = "message" ) // TC @@ -169,6 +183,15 @@ object ACL extends PhiLogging { update = TreatmentMatchingRoles ) + object PatientIssue + extends BaseACL( + label = "patient issue", + create = TreatmentMatchingRoles, + read = TreatmentMatchingRoles, + update = TreatmentMatchingRoles, + delete = TreatmentMatchingRoles + ) + object PatientLabel extends BaseACL( label = "patient label", diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/DocumentIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/DocumentIssue.scala new file mode 100644 index 0000000..380e27d --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/DocumentIssue.scala @@ -0,0 +1,25 @@ +package xyz.driver.pdsuidomain.entities + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} +import xyz.driver.pdsuicommon.logging._ + +final case class DocumentIssue(id: LongId[DocumentIssue], + userId: StringId[User], + documentId: LongId[Document], + startPage: Option[Double], + endPage: Option[Double], + lastUpdate: LocalDateTime, + isDraft: Boolean, + text: String, + evidence: String, + archiveRequired: Boolean, + meta: String) + +object DocumentIssue { + implicit def toPhiString(x: DocumentIssue): PhiString = { + import x._ + phi"DocumentIssue(id=$id, userId=$userId, documentId=$documentId)" + } +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecordIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecordIssue.scala new file mode 100644 index 0000000..0a5ecc4 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecordIssue.scala @@ -0,0 +1,25 @@ +package xyz.driver.pdsuidomain.entities + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} +import xyz.driver.pdsuicommon.logging._ + +final case class MedicalRecordIssue(id: LongId[MedicalRecordIssue], + userId: StringId[User], + recordId: LongId[MedicalRecord], + startPage: Option[Double], + endPage: Option[Double], + lastUpdate: LocalDateTime, + isDraft: Boolean, + text: String, + evidence: String, + archiveRequired: Boolean, + meta: String) + +object MedicalRecordIssue { + implicit def toPhiString(x: MedicalRecordIssue): PhiString = { + import x._ + phi"MedicalRecordIssue(id=$id, userId=$userId, recordId=$recordId)" + } +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientIssue.scala new file mode 100644 index 0000000..070fc74 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientIssue.scala @@ -0,0 +1,23 @@ +package xyz.driver.pdsuidomain.entities + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ + +final case class PatientIssue(id: LongId[PatientIssue], + userId: StringId[User], + patientId: UuidId[Patient], + lastUpdate: LocalDateTime, + isDraft: Boolean, + text: String, + evidence: String, + archiveRequired: Boolean, + meta: String) + +object PatientIssue { + implicit def toPhiString(x: PatientIssue): PhiString = { + import x._ + phi"PatientIssue(id=$id, userId=$userId, patientId=$patientId)" + } +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala new file mode 100644 index 0000000..fab2546 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala @@ -0,0 +1,48 @@ +package xyz.driver.pdsuidomain.formats.json.documentissue + +import java.time.{ZoneId, ZonedDateTime} + +import play.api.libs.functional.syntax._ +import play.api.libs.json._ +import xyz.driver.pdsuidomain.entities.DocumentIssue + +final case class ApiDocumentIssue(id: Long, + startPage: Option[Double], + endPage: Option[Double], + text: String, + lastUpdate: ZonedDateTime, + userId: String, + isDraft: Boolean, + evidence: String, + archiveRequired: Boolean, + meta: String) + +object ApiDocumentIssue { + implicit val format: Format[ApiDocumentIssue] = ( + (JsPath \ "id").format[Long] and + (JsPath \ "startPage").formatNullable[Double] and + (JsPath \ "endPage").formatNullable[Double] and + (JsPath \ "text").format[String] and + (JsPath \ "lastUpdate").format[ZonedDateTime] and + (JsPath \ "userId").format[String] and + (JsPath \ "isDraft").format[Boolean] and + (JsPath \ "evidence").format[String] and + (JsPath \ "archiveRequired").format[Boolean] and + (JsPath \ "meta").format[String](Format(Reads { x => + JsSuccess(Json.stringify(x)) + }, Writes[String](Json.parse))) + )(ApiDocumentIssue.apply, unlift(ApiDocumentIssue.unapply)) + + def fromDomain(x: DocumentIssue) = ApiDocumentIssue( + id = x.id.id, + startPage = x.startPage, + endPage = x.endPage, + text = x.text, + lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), + userId = x.userId.id, + isDraft = x.isDraft, + evidence = x.evidence, + archiveRequired = x.archiveRequired, + meta = x.meta + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala new file mode 100644 index 0000000..7a5dbe5 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala @@ -0,0 +1,52 @@ +package xyz.driver.pdsuidomain.formats.json.documentissue + +import java.time.LocalDateTime + +import play.api.libs.functional.syntax._ +import play.api.libs.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} +import xyz.driver.pdsuidomain.entities.{Document, DocumentIssue} + +final case class ApiPartialDocumentIssue(startPage: Option[Double], + endPage: Option[Double], + text: String, + evidence: String, + archiveRequired: Boolean, + meta: String) { + def applyTo(x: DocumentIssue): DocumentIssue = x.copy( + startPage = startPage, + endPage = endPage, + text = text, + evidence = evidence, + archiveRequired = archiveRequired, + meta = meta + ) + + def toDomain(userId: StringId[User], documentId: LongId[Document]) = + DocumentIssue( + id = LongId(0), + userId = userId, + documentId = documentId, + startPage = startPage, + endPage = endPage, + lastUpdate = LocalDateTime.MIN, + isDraft = true, + text = text, + evidence = evidence, + archiveRequired = false, + meta = meta + ) +} + +object ApiPartialDocumentIssue { + implicit val format: Format[ApiPartialDocumentIssue] = ( + (JsPath \ "startPage").formatNullable[Double] and + (JsPath \ "endPage").formatNullable[Double] and + (JsPath \ "text").format[String] and + (JsPath \ "evidence").format[String] and + (JsPath \ "archiveRequired").format[Boolean] and + (JsPath \ "meta").format[String](Format(Reads { x => + JsSuccess(Json.stringify(x)) + }, Writes[String](Json.parse))) + )(ApiPartialDocumentIssue.apply, unlift(ApiPartialDocumentIssue.unapply)) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala new file mode 100644 index 0000000..1d97b48 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala @@ -0,0 +1,41 @@ +package xyz.driver.pdsuidomain.formats.json.patientissue + +import java.time.LocalDateTime + +import play.api.libs.functional.syntax._ +import play.api.libs.json._ +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuidomain.entities.{Patient, PatientIssue} + +final case class ApiPartialPatientIssue(text: String, evidence: String, archiveRequired: Boolean, meta: String) { + def applyTo(x: PatientIssue): PatientIssue = x.copy( + text = text, + evidence = evidence, + archiveRequired = archiveRequired, + meta = meta + ) + + def toDomain(userId: StringId[User], patientId: UuidId[Patient]) = + PatientIssue( + id = LongId(0), + userId = userId, + patientId = patientId, + lastUpdate = LocalDateTime.MIN, + isDraft = true, + text = text, + evidence = evidence, + archiveRequired = false, + meta = meta + ) +} + +object ApiPartialPatientIssue { + implicit val format: Format[ApiPartialPatientIssue] = ( + (JsPath \ "text").format[String] and + (JsPath \ "evidence").format[String] and + (JsPath \ "archiveRequired").format[Boolean] and + (JsPath \ "meta").format[String](Format(Reads { x => + JsSuccess(Json.stringify(x)) + }, Writes[String](Json.parse))) + )(ApiPartialPatientIssue.apply, unlift(ApiPartialPatientIssue.unapply)) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala new file mode 100644 index 0000000..7e0b174 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala @@ -0,0 +1,42 @@ +package xyz.driver.pdsuidomain.formats.json.patientissue + +import java.time.{ZoneId, ZonedDateTime} + +import play.api.libs.functional.syntax._ +import play.api.libs.json._ +import xyz.driver.pdsuidomain.entities.PatientIssue + +final case class ApiPatientIssue(id: Long, + text: String, + lastUpdate: ZonedDateTime, + userId: String, + isDraft: Boolean, + evidence: String, + archiveRequired: Boolean, + meta: String) + +object ApiPatientIssue { + implicit val format: Format[ApiPatientIssue] = ( + (JsPath \ "id").format[Long] and + (JsPath \ "text").format[String] and + (JsPath \ "lastUpdate").format[ZonedDateTime] and + (JsPath \ "userId").format[String] and + (JsPath \ "isDraft").format[Boolean] and + (JsPath \ "evidence").format[String] and + (JsPath \ "archiveRequired").format[Boolean] and + (JsPath \ "meta").format[String](Format(Reads { x => + JsSuccess(Json.stringify(x)) + }, Writes[String](Json.parse))) + )(ApiPatientIssue.apply, unlift(ApiPatientIssue.unapply)) + + def fromDomain(x: PatientIssue) = ApiPatientIssue( + id = x.id.id, + text = x.text, + lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), + userId = x.userId.id, + isDraft = x.isDraft, + evidence = x.evidence, + archiveRequired = x.archiveRequired, + meta = x.meta + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala new file mode 100644 index 0000000..07a88aa --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala @@ -0,0 +1,52 @@ +package xyz.driver.pdsuidomain.formats.json.recordissue + +import java.time.LocalDateTime + +import play.api.libs.functional.syntax._ +import play.api.libs.json._ +import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} +import xyz.driver.pdsuidomain.entities.{MedicalRecord, MedicalRecordIssue} + +final case class ApiPartialRecordIssue(startPage: Option[Double], + endPage: Option[Double], + text: String, + evidence: String, + archiveRequired: Boolean, + meta: String) { + def applyTo(x: MedicalRecordIssue): MedicalRecordIssue = x.copy( + startPage = startPage, + endPage = endPage, + text = text, + evidence = evidence, + archiveRequired = archiveRequired, + meta = meta + ) + + def toDomain(userId: StringId[User], recordId: LongId[MedicalRecord]) = + MedicalRecordIssue( + id = LongId(0), + userId = userId, + recordId = recordId, + startPage = startPage, + endPage = endPage, + lastUpdate = LocalDateTime.MIN, + isDraft = true, + text = text, + evidence = evidence, + archiveRequired = false, + meta = meta + ) +} + +object ApiPartialRecordIssue { + implicit val format: Format[ApiPartialRecordIssue] = ( + (JsPath \ "startPage").formatNullable[Double] and + (JsPath \ "endPage").formatNullable[Double] and + (JsPath \ "text").format[String] and + (JsPath \ "evidence").format[String] and + (JsPath \ "archiveRequired").format[Boolean] and + (JsPath \ "meta").format[String](Format(Reads { x => + JsSuccess(Json.stringify(x)) + }, Writes[String](Json.parse))) + )(ApiPartialRecordIssue.apply, unlift(ApiPartialRecordIssue.unapply)) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala new file mode 100644 index 0000000..adab72e --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala @@ -0,0 +1,48 @@ +package xyz.driver.pdsuidomain.formats.json.recordissue + +import java.time.{ZoneId, ZonedDateTime} + +import play.api.libs.functional.syntax._ +import play.api.libs.json._ +import xyz.driver.pdsuidomain.entities.MedicalRecordIssue + +final case class ApiRecordIssue(id: Long, + startPage: Option[Double], + endPage: Option[Double], + text: String, + lastUpdate: ZonedDateTime, + userId: String, + isDraft: Boolean, + evidence: String, + archiveRequired: Boolean, + meta: String) + +object ApiRecordIssue { + implicit val format: Format[ApiRecordIssue] = ( + (JsPath \ "id").format[Long] and + (JsPath \ "startPage").formatNullable[Double] and + (JsPath \ "endPage").formatNullable[Double] and + (JsPath \ "text").format[String] and + (JsPath \ "lastUpdate").format[ZonedDateTime] and + (JsPath \ "userId").format[String] and + (JsPath \ "isDraft").format[Boolean] and + (JsPath \ "evidence").format[String] and + (JsPath \ "archiveRequired").format[Boolean] and + (JsPath \ "meta").format[String](Format(Reads { x => + JsSuccess(Json.stringify(x)) + }, Writes[String](Json.parse))) + )(ApiRecordIssue.apply, unlift(ApiRecordIssue.unapply)) + + def fromDomain(x: MedicalRecordIssue) = ApiRecordIssue( + id = x.id.id, + startPage = x.startPage, + endPage = x.endPage, + text = x.text, + lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), + userId = x.userId.id, + isDraft = x.isDraft, + evidence = x.evidence, + archiveRequired = x.archiveRequired, + meta = x.meta + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentIssueService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentIssueService.scala new file mode 100644 index 0000000..4315352 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentIssueService.scala @@ -0,0 +1,93 @@ +package xyz.driver.pdsuidomain.services + +import java.time.LocalDateTime + +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.pdsuidomain.entities.{Document, DocumentIssue} + +import scala.concurrent.Future + +object DocumentIssueService { + + trait DefaultNotFoundError { + def userMessage: String = "DocumentIssue not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait CreateReply + object CreateReply { + type Error = CreateReply with DomainError + final case class Created(x: DocumentIssue) extends CreateReply + case object AuthorizationError + extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + final case class CommonError(userMessage: String) extends CreateReply with DomainError + } + + sealed trait GetByIdReply + object GetByIdReply { + type Error = GetByIdReply with DomainError + final case class Entity(x: DocumentIssue) extends GetByIdReply + case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError + final case class CommonError(userMessage: String) extends GetByIdReply with DomainError + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait GetListByDocumentIdReply + object GetListByDocumentIdReply { + type Error = GetListByDocumentIdReply with DomainError + final case class EntityList(xs: Seq[DocumentIssue], totalFound: Int, lastUpdate: Option[LocalDateTime]) + extends GetListByDocumentIdReply + case object NotFoundError extends GetListByDocumentIdReply with DomainError.NotFoundError with DefaultNotFoundError + case object AuthorizationError + extends GetListByDocumentIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + final case class Updated(updated: DocumentIssue) extends UpdateReply + case object AuthorizationError + extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + final 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 DomainError.AuthorizationError with DefaultAccessDeniedError + case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError + final case class CommonError(userMessage: String) extends DeleteReply with DomainError + } +} + +trait DocumentIssueService { + + import DocumentIssueService._ + + def create(draft: DocumentIssue)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] + + def getById(documentId: LongId[Document], id: LongId[DocumentIssue])( + implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getListByDocumentId(documentId: LongId[Document], + filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None)( + implicit requestContext: AuthenticatedRequestContext): Future[GetListByDocumentIdReply] + + def update(orig: DocumentIssue, draft: DocumentIssue)( + implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def delete(documentId: LongId[Document], id: LongId[DocumentIssue])( + implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordIssueService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordIssueService.scala new file mode 100644 index 0000000..723bdfa --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordIssueService.scala @@ -0,0 +1,93 @@ +package xyz.driver.pdsuidomain.services + +import java.time.LocalDateTime + +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.pdsuidomain.entities.{MedicalRecord, MedicalRecordIssue} + +import scala.concurrent.Future + +object MedicalRecordIssueService { + + trait DefaultNotFoundError { + def userMessage: String = "MedicalRecordIssue not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait CreateReply + object CreateReply { + type Error = CreateReply with DomainError + final case class Created(x: MedicalRecordIssue) extends CreateReply + case object AuthorizationError + extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + final case class CommonError(userMessage: String) extends CreateReply with DomainError + } + + sealed trait GetByIdReply + object GetByIdReply { + type Error = GetByIdReply with DomainError + final case class Entity(x: MedicalRecordIssue) extends GetByIdReply + case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError + final case class CommonError(userMessage: String) extends GetByIdReply with DomainError + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait GetListByRecordIdReply + object GetListByRecordIdReply { + type Error = GetListByRecordIdReply with DomainError + final case class EntityList(xs: Seq[MedicalRecordIssue], totalFound: Int, lastUpdate: Option[LocalDateTime]) + extends GetListByRecordIdReply + case object NotFoundError extends GetListByRecordIdReply with DomainError.NotFoundError with DefaultNotFoundError + case object AuthorizationError + extends GetListByRecordIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + final case class Updated(updated: MedicalRecordIssue) extends UpdateReply + case object AuthorizationError + extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + final 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 DomainError.AuthorizationError with DefaultAccessDeniedError + case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError + final case class CommonError(userMessage: String) extends DeleteReply with DomainError + } +} + +trait MedicalRecordIssueService { + + import MedicalRecordIssueService._ + + def create(draft: MedicalRecordIssue)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] + + def getById(recordId: LongId[MedicalRecord], id: LongId[MedicalRecordIssue])( + implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getListByRecordId(recordId: LongId[MedicalRecord], + filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None)( + implicit requestContext: AuthenticatedRequestContext): Future[GetListByRecordIdReply] + + def update(orig: MedicalRecordIssue, draft: MedicalRecordIssue)( + implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def delete(recordId: LongId[MedicalRecord], id: LongId[MedicalRecordIssue])( + implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientIssueService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientIssueService.scala new file mode 100644 index 0000000..b53301d --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientIssueService.scala @@ -0,0 +1,93 @@ +package xyz.driver.pdsuidomain.services + +import java.time.LocalDateTime + +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.pdsuidomain.entities.{Patient, PatientIssue} + +import scala.concurrent.Future + +object PatientIssueService { + + trait DefaultNotFoundError { + def userMessage: String = "PatientIssue not found" + } + + trait DefaultAccessDeniedError { + def userMessage: String = "Access denied" + } + + sealed trait CreateReply + object CreateReply { + type Error = CreateReply with DomainError + final case class Created(x: PatientIssue) extends CreateReply + case object AuthorizationError + extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + final case class CommonError(userMessage: String) extends CreateReply with DomainError + } + + sealed trait GetByIdReply + object GetByIdReply { + type Error = GetByIdReply with DomainError + final case class Entity(x: PatientIssue) extends GetByIdReply + case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError + final case class CommonError(userMessage: String) extends GetByIdReply with DomainError + case object AuthorizationError + extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait GetListByPatientIdReply + object GetListByPatientIdReply { + type Error = GetListByPatientIdReply with DomainError + final case class EntityList(xs: Seq[PatientIssue], totalFound: Int, lastUpdate: Option[LocalDateTime]) + extends GetListByPatientIdReply + case object NotFoundError extends GetListByPatientIdReply with DomainError.NotFoundError with DefaultNotFoundError + case object AuthorizationError + extends GetListByPatientIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError + } + + sealed trait UpdateReply + object UpdateReply { + type Error = UpdateReply with DomainError + final case class Updated(updated: PatientIssue) extends UpdateReply + case object AuthorizationError + extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError + final 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 DomainError.AuthorizationError with DefaultAccessDeniedError + case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError + final case class CommonError(userMessage: String) extends DeleteReply with DomainError + } +} + +trait PatientIssueService { + + import PatientIssueService._ + + def create(draft: PatientIssue)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] + + def getById(patientId: UuidId[Patient], id: LongId[PatientIssue])( + implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] + + def getListByPatientId(patientId: UuidId[Patient], + filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Option[Sorting] = None, + pagination: Option[Pagination] = None)( + implicit requestContext: AuthenticatedRequestContext): Future[GetListByPatientIdReply] + + def update(orig: PatientIssue, draft: PatientIssue)( + implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] + + def delete(patientId: UuidId[Patient], id: LongId[PatientIssue])( + implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] + +} -- cgit v1.2.3