aboutsummaryrefslogblamecommitdiff
path: root/src/main/scala/xyz/driver/pdsuidomain/formats/json/document.scala
blob: 66e95f340aa4eb5882ba0efe69034a594d709f0c (plain) (tree)
1
2
3
4
5
6
                                           



                                           
                             







                                                       
                                                                                         







                                    
                                                                                                   



                              
                                                                                 
 





                                                                                                    
                                                                                                             




                                                                           
                                                                                             




                                                                
 










                                                                                              



                                                       
 



                                         
 



                                                       
 




                                         



                                                 
 



                                            
 



                                            





                                                     
                                          










                                                                                              
                                                 





                                                             
                                                              







                                                               

                                                          



                                                             



                                                         




                                                                                                                   







                                                        

                              
                                               


                           
                                                             
 



                                                              

                             
                                               


                                   
                                                             
 

                                    
                                               
 

                         
                                                       


                              
                                                  


                            
                                                  
 







                                                      
                 
                                       
                              
                                                         





                                          
                                      
                                            
                      
                                          


                                  

                                                               






                                                                                        
package xyz.driver.pdsuidomain.formats.json

import java.time.{LocalDate, LocalDateTime}

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

object document {
  import DefaultJsonProtocol._
  import Document._
  import common._

  implicit val documentStatusFormat: RootJsonFormat[Status] = new EnumJsonFormat[Status](
    "New"       -> Status.New,
    "Organized" -> Status.Organized,
    "Extracted" -> Status.Extracted,
    "Done"      -> Status.Done,
    "Flagged"   -> Status.Flagged,
    "Archived"  -> Status.Archived
  )

  implicit val requiredTypeFormat: RootJsonFormat[RequiredType] = new EnumJsonFormat[RequiredType](
    "OPN" -> RequiredType.OPN,
    "PN"  -> RequiredType.PN
  )

  implicit val documentMetaFormat: RootJsonFormat[Meta] = jsonFormat2(Meta.apply)

  implicit val documentTypeFormat: RootJsonFormat[DocumentType] = new RootJsonFormat[DocumentType] {
    override def read(json: JsValue): DocumentType = json match {
      case JsObject(fields) =>
        val name = fields
          .get("name")
          .map(_.convertTo[String])
          .getOrElse(deserializationError(s"Document type json object does not contain `name` field: $json"))

        DocumentType
          .fromString(name)
          .getOrElse(deserializationError(s"Unknown document type: $name"))

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

    override def write(obj: DocumentType) =
      JsObject("id" -> obj.id.toJson, "name" -> obj.name.toJson)
  }

  implicit val fullDocumentMetaFormat = new RootJsonFormat[TextJson[Meta]] {
    override def write(obj: TextJson[Meta]): JsValue = obj.content.toJson
    override def read(json: JsValue)                 = TextJson(documentMetaFormat.read(json))
  }

  def applyUpdateToDocument(json: JsValue, orig: Document): Document = json match {
    case JsObject(fields) =>
      val physician = fields
        .get("physician")
        .map(_.convertTo[String])

      val typeId = fields
        .get("typeId")
        .map(_.convertTo[Option[LongId[DocumentType]]])
        .getOrElse(orig.typeId)

      val provider = fields
        .get("provider")
        .map(_.convertTo[Option[String]])
        .getOrElse(orig.providerName)

      val providerTypeId = fields
        .get("providerTypeId")
        .map(_.convertTo[Option[LongId[ProviderType]]])
        .getOrElse(orig.providerTypeId)

      val institutionName = fields
        .get("institutionName")
        .map(_.convertTo[Option[String]])
        .getOrElse(orig.institutionName)

      val meta = fields
        .get("meta")
        .map(_.convertTo[Option[TextJson[Meta]]])
        .getOrElse(orig.meta)

      val startDate = fields
        .get("startDate")
        .map(_.convertTo[Option[LocalDate]])
        .getOrElse(orig.startDate)

      val endDate = fields
        .get("endDate")
        .map(_.convertTo[Option[LocalDate]])
        .getOrElse(orig.endDate)

      orig.copy(
        physician = physician.orElse(orig.physician),
        typeId = typeId,
        providerName = provider,
        providerTypeId = providerTypeId,
        institutionName = institutionName,
        meta = meta,
        startDate = startDate,
        endDate = endDate
      )

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

  implicit val documentFormat: RootJsonFormat[Document] = new RootJsonFormat[Document] {
    override def write(document: Document): JsValue =
      JsObject(
        "id"               -> document.id.toJson,
        "recordId"         -> document.recordId.toJson,
        "physician"        -> document.physician.toJson,
        "typeId"           -> document.typeId.toJson,
        "provider"         -> document.providerName.toJson,
        "providerTypeId"   -> document.providerTypeId.toJson,
        "requiredType"     -> document.requiredType.toJson,
        "institutionName"  -> document.institutionName.toJson,
        "startDate"        -> document.startDate.toJson,
        "endDate"          -> document.endDate.toJson,
        "status"           -> document.status.toJson,
        "previousStatus"   -> document.previousStatus.toJson,
        "assignee"         -> document.assignee.toJson,
        "previousAssignee" -> document.previousAssignee.toJson,
        "meta"             -> document.meta.toJson,
        "lastActiveUser"   -> document.lastActiveUserId.toJson,
        "lastUpdate"       -> document.lastUpdate.toJson,
        "labelVersion"     -> document.labelVersion.toJson
      )

    override def read(json: JsValue): Document = json match {
      case JsObject(fields) =>
        val id = fields
          .get("id")
          .flatMap(_.convertTo[Option[LongId[Document]]])

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

        val status = fields
          .get("status")
          .flatMap(_.convertTo[Option[Document.Status]])

        val previousStatus = fields
          .get("previousStatus")
          .flatMap(_.convertTo[Option[Document.Status]])

        val physician = fields
          .get("physician")
          .flatMap(_.convertTo[Option[String]])

        val typeId = fields
          .get("typeId")
          .flatMap(_.convertTo[Option[LongId[DocumentType]]])

        val requiredType = fields
          .get("requiredType")
          .flatMap(_.convertTo[Option[Document.RequiredType]])

        val provider = fields
          .get("provider")
          .flatMap(_.convertTo[Option[String]])

        val providerTypeId = fields
          .get("providerTypeId")
          .flatMap(_.convertTo[Option[LongId[ProviderType]]])

        val institutionName = fields
          .get("institutionName")
          .flatMap(_.convertTo[Option[String]])

        val meta = fields
          .get("meta")
          .flatMap(_.convertTo[Option[TextJson[Meta]]])

        val startDate = fields
          .get("startDate")
          .flatMap(_.convertTo[Option[LocalDate]])

        val endDate = fields
          .get("endDate")
          .flatMap(_.convertTo[Option[LocalDate]])

        val lastUpdate = fields
          .get("lastUpdate")
          .flatMap(_.convertTo[Option[LocalDateTime]])

        val labelVersion = fields
          .get("labelVersion")
          .flatMap(_.convertTo[Option[Int]])

        Document(
          id = id.getOrElse(LongId(0)),
          recordId = recordId,
          status = status.getOrElse(Document.Status.New),
          physician = physician,
          typeId = typeId,
          startDate = startDate,
          endDate = endDate,
          providerName = provider,
          providerTypeId = providerTypeId,
          requiredType = requiredType,
          institutionName = institutionName,
          meta = meta,
          previousStatus = previousStatus,
          assignee = None,
          previousAssignee = None,
          lastActiveUserId = None,
          lastUpdate = lastUpdate.getOrElse(LocalDateTime.MIN),
          labelVersion = labelVersion.getOrElse(0)
        )

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

}