aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala')
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala
new file mode 100644
index 0000000..977f4cc
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala
@@ -0,0 +1,164 @@
+package xyz.driver.pdsuidomain.entities
+
+import java.nio.channels.ReadableByteChannel
+import java.time.LocalDateTime
+
+import com.fasterxml.jackson.annotation.JsonSubTypes.Type
+import com.fasterxml.jackson.annotation.{JsonProperty, JsonSubTypes, JsonTypeInfo}
+import xyz.driver.pdsuicommon.domain.{LongId, TextJson, User, UuidId}
+import xyz.driver.pdsuicommon.logging._
+import xyz.driver.pdsuicommon.utils.Utils
+import xyz.driver.pdsuidomain.entities.MedicalRecord.Meta
+import xyz.driver.pdsuidomain.entities.MedicalRecord.Meta.{Duplicate, Reorder, Rotation}
+
+object MedicalRecord {
+
+ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
+ @JsonSubTypes(Array(
+ new Type(value = classOf[Duplicate], name = "duplicate"),
+ new Type(value = classOf[Reorder], name = "reorder"),
+ new Type(value = classOf[Rotation], name = "rotation")
+ ))
+ trait Meta {
+ @JsonProperty("type") def metaType: String
+ def predicted: Option[Boolean]
+
+ /**
+ * Return a regular meta: this meta is considered as not predicted
+ */
+ def confirmed: Meta
+ }
+
+ object Meta {
+
+ case class Duplicate(predicted: Option[Boolean],
+ startPage: Double,
+ endPage: Double,
+ startOriginalPage: Double,
+ endOriginalPage: Option[Double]
+ ) extends Meta {
+ override val metaType = "duplicate"
+ override def confirmed: Duplicate = copy(predicted = predicted.map(_ => false))
+ }
+
+ object Duplicate {
+ implicit def toPhiString(x: Duplicate): PhiString = {
+ import x._
+ phi"Duplicate(predicted=${x.predicted}, startPage=${Unsafe(startPage)}, endPage=${Unsafe(endPage)}, " +
+ phi"startOriginalPage=${Unsafe(startOriginalPage)}, endOriginalPage=${Unsafe(endOriginalPage)}"
+ }
+ }
+
+
+ case class Reorder(predicted: Option[Boolean],
+ items: Seq[Int]
+ ) extends Meta {
+ override val metaType = "reorder"
+ override def confirmed: Reorder = copy(predicted = predicted.map(_ => false))
+ }
+
+ object Reorder {
+ implicit def toPhiString(x: Reorder): PhiString = {
+ import x._
+ phi"Reorder(predicted=${x.predicted}, items=${Unsafe(items.toString)})"
+ }
+ }
+
+
+ case class Rotation(predicted: Option[Boolean],
+ items: Map[String, Int]
+ ) extends Meta {
+ override val metaType = "rotation"
+ override def confirmed: Rotation = copy(predicted = predicted.map(_ => false))
+ }
+
+ object Rotation {
+ implicit def toPhiString(x: Rotation): PhiString = {
+ import x._
+ phi"Rotation(predicted=${x.predicted}, items=${Unsafe(items.toString)})"
+ }
+ }
+
+
+ implicit def toPhiString(input: Meta): PhiString = input match {
+ case x: Duplicate => Duplicate.toPhiString(x)
+ case x: Reorder => Reorder.toPhiString(x)
+ case x: Rotation => Rotation.toPhiString(x)
+ }
+
+ }
+
+ // Product with Serializable fixes issue:
+ // Set(New, Cleaned) has type Set[Status with Product with Serializable]
+ sealed trait Status extends Product with Serializable {
+
+ def oneOf(xs: Status*): Boolean = xs.contains(this)
+
+ def oneOf(xs: Set[Status]): Boolean = xs.contains(this)
+
+ }
+ object Status {
+ case object Unprocessed extends Status
+ case object PreCleaning extends Status
+ case object New extends Status
+ case object Cleaned extends Status
+ case object PreOrganized extends Status
+ case object PreOrganizing extends Status
+ case object Reviewed extends Status
+ case object Organized extends Status
+ case object Done extends Status
+ case object Flagged extends Status
+ case object Archived extends Status
+
+ val All = Set[Status](
+ Unprocessed, PreCleaning, New, Cleaned, PreOrganized, PreOrganizing, Reviewed, Organized, Done, Flagged, Archived
+ )
+
+ val AllPrevious = Set[Status](New, Cleaned, Reviewed, Organized)
+
+ implicit def toPhiString(x: Status): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass))
+ }
+
+ sealed trait PdfSource
+
+ object PdfSource {
+ case object Empty extends PdfSource
+ /** @param createResource Constructor of the resource which is represents the file */
+ case class Channel(createResource: () => ReadableByteChannel) extends PdfSource
+ }
+
+ implicit def toPhiString(x: MedicalRecord): PhiString = {
+ import x._
+ phi"MedicalRecord(id=$id, status=$status, assignee=$assignee, previousAssignee=$previousAssignee)"
+ }
+}
+
+case class MedicalRecord(id: LongId[MedicalRecord],
+ status: MedicalRecord.Status,
+ previousStatus: Option[MedicalRecord.Status],
+ assignee: Option[LongId[User]],
+ previousAssignee: Option[LongId[User]],
+ patientId: UuidId[Patient],
+ requestId: RecordRequestId,
+ disease: String,
+ caseId: Option[CaseId],
+ physician: Option[String],
+ sourceName: String,
+ meta: Option[TextJson[List[Meta]]],
+ predictedMeta: Option[TextJson[List[Meta]]],
+ predictedDocuments: Option[TextJson[List[Document]]],
+ lastUpdate: LocalDateTime) {
+
+ import MedicalRecord.Status._
+
+ if (previousStatus.nonEmpty) {
+ assert(AllPrevious.contains(previousStatus.get),
+ s"Previous status has invalid value: ${previousStatus.get}")
+ }
+
+ // TODO: with the current business logic code this constraint sometimes harmful
+ // require(status match {
+ // case MedicalRecord.Status.Done if assignee.isDefined => false
+ // case _ => true
+ // }, "Assignee can't be defined in Done status")
+}