aboutsummaryrefslogblamecommitdiff
path: root/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala
blob: 352704a75bda07218feb72a0acb464f86ae08937 (plain) (tree)




































































































































                                                                                                                    
package xyz.driver.pdsuidomain.formats.json.sprayformats

import java.time.LocalDateTime
import java.util.UUID

import spray.json._
import xyz.driver.core.json.{EnumJsonFormat, GadtJsonFormat}
import xyz.driver.pdsuicommon.domain.{LongId, TextJson, UuidId}
import xyz.driver.pdsuidomain.entities._

object record {
  import DefaultJsonProtocol._
  import MedicalRecord._
  import common._

  implicit val recordStatusFormat = new EnumJsonFormat[Status](
    "Unprocessed"   -> Status.Unprocessed,
    "PreOrganized"  -> Status.PreOrganized,
    "New"           -> Status.New,
    "Cleaned"       -> Status.Cleaned,
    "PreOrganized"  -> Status.PreOrganized,
    "PreOrganizing" -> Status.PreOrganizing,
    "Reviewed"      -> Status.Reviewed,
    "Organized"     -> Status.Organized,
    "Done"          -> Status.Done,
    "Flagged"       -> Status.Flagged,
    "Archived"      -> Status.Archived
  )

  implicit val requestIdFormat = new RootJsonFormat[RecordRequestId] {
    override def write(requestId: RecordRequestId): JsString = JsString(requestId.toString)
    override def read(json: JsValue): RecordRequestId = json match {
      case JsString(value) => RecordRequestId(UUID.fromString(value))
      case _               => deserializationError(s"Expected string as RecordRequestId, but got $json")
    }
  }

  implicit val caseIdFormat = new RootJsonFormat[CaseId] {
    override def write(caseId: CaseId): JsString = JsString(caseId.toString)
    override def read(json: JsValue): CaseId = json match {
      case JsString(value) => CaseId(value)
      case _               => deserializationError(s"Expected string as CaseId, but got $json")
    }
  }

  implicit val recordMetaTypeFormat: GadtJsonFormat[MedicalRecord.Meta] = {
    import Meta._
    GadtJsonFormat.create[Meta]("meta")({ case m => m.metaType }) {
      case "duplicate" => jsonFormat5(Duplicate.apply)
      case "reorder"   => jsonFormat2(Reorder.apply)
      case "rotation"  => jsonFormat2(Rotation.apply)
    }
  }

  implicit val recordMetaFormat = new RootJsonFormat[TextJson[List[Meta]]] {
    override def write(obj: TextJson[List[Meta]]): JsArray = JsArray(obj.content.map(_.toJson).toVector)
    override def read(json: JsValue): TextJson[List[Meta]] = json match {
      case JsArray(values) => TextJson[List[Meta]](values.map(_.convertTo[Meta]).toList)
      case _               => deserializationError(s"Expected array as Meta, but got $json")
    }
  }

  implicit val recordFormat: RootJsonFormat[MedicalRecord] =
    new RootJsonFormat[MedicalRecord] {
      override def write(record: MedicalRecord): JsValue =
        JsObject(
          "id"               -> record.id.id.toJson,
          "patientId"        -> record.patientId.toJson,
          "caseId"           -> record.caseId.toJson,
          "disease"          -> record.disease.toJson,
          "physician"        -> record.physician.toJson,
          "status"           -> record.status.toJson,
          "previousStatus"   -> record.previousStatus.toJson,
          "assignee"         -> record.assignee.toJson,
          "previousAssignee" -> record.previousAssignee.toJson,
          "requestId"        -> record.requestId.toJson,
          "meta"             -> record.meta.getOrElse(TextJson[List[Meta]](List.empty)).toJson,
          "lastActiveUser"   -> record.lastActiveUserId.toJson,
          "lastUpdate"       -> record.lastUpdate.toJson
        )

      override def read(json: JsValue): MedicalRecord = json match {
        case JsObject(fields) =>
          val disease = fields
            .get("disease")
            .map(_.convertTo[String])
            .getOrElse(deserializationError(s"MedicalRecord json object does not contain `disease` field: $json"))

          val patientId = fields
            .get("patientId")
            .map(_.convertTo[UuidId[Patient]])
            .getOrElse(deserializationError(s"MedicalRecord json object does not contain `patientId` field: $json"))

          val requestId = fields
            .get("requestId")
            .map(_.convertTo[RecordRequestId])
            .getOrElse(deserializationError(s"MedicalRecord json object does not contain `requestId` field: $json"))

          MedicalRecord(
            id = LongId(0),
            status = MedicalRecord.Status.New,
            previousStatus = None,
            assignee = None,
            previousAssignee = None,
            lastActiveUserId = None,
            patientId = patientId,
            requestId = requestId,
            disease = disease,
            caseId = None,
            physician = None,
            meta = None,
            predictedMeta = None,
            predictedDocuments = None,
            lastUpdate = LocalDateTime.now()
          )

        case _ => deserializationError(s"Expected Json Object as MedicalRecord, but got $json")
      }
    }

  def applyUpdateToMedicalRecord(json: JsValue, orig: MedicalRecord): MedicalRecord = json match {
    case JsObject(fields) =>
      val meta = if (fields.contains("meta")) {
        fields
          .get("meta")
          .map(_.convertTo[TextJson[List[Meta]]])
      } else orig.meta
      orig.copy(meta = meta)

    case _ => deserializationError(s"Expected Json Object as partial MedicalRecord, but got $json")
  }

}