From 15d74838eb592c58bb0a912380f0ec1f537be333 Mon Sep 17 00:00:00 2001 From: Kseniya Tomskikh Date: Wed, 18 Oct 2017 13:51:47 +0700 Subject: TRIAL-54 Study designs as enum --- .../driver/pdsuidomain/entities/Intervention.scala | 15 ++++------ .../xyz/driver/pdsuidomain/entities/Trial.scala | 34 +++++++++++++++++++++- .../pdsuidomain/fakes/entities/trialcuration.scala | 5 +--- .../formats/json/sprayformats/document.scala | 2 +- .../formats/json/sprayformats/intervention.scala | 4 ++- .../formats/json/sprayformats/record.scala | 4 +-- .../formats/json/sprayformats/studydesign.scala | 19 +++++++++++- .../formats/json/studydesign/ApiStudyDesign.scala | 3 +- .../rest/RestInterventionTypeService.scala | 2 +- .../services/rest/RestStudyDesignService.scala | 2 +- 10 files changed, 66 insertions(+), 24 deletions(-) (limited to 'src/main/scala/xyz/driver') diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala index f02bedc..5e743b7 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala @@ -5,6 +5,9 @@ import xyz.driver.pdsuicommon.logging._ import xyz.driver.pdsuidomain.entities.InterventionType.DeliveryMethod import xyz.driver.pdsuidomain.entities.InterventionType.DeliveryMethod._ +import scalaz.syntax.equal._ +import scalaz.Scalaz.stringInstance + sealed trait InterventionType { val id: LongId[InterventionType] val name: String @@ -78,16 +81,8 @@ object InterventionType { ) } - def typeFromString: PartialFunction[String, InterventionType] = { - case "Radiation therapy" => RadiationTherapy - case "Chemotherapy" => Chemotherapy - case "Targeted therapy" => TargetedTherapy - case "Immunotherapy" => Immunotherapy - case "Surgery" => Surgery - case "Hormone therapy" => HormoneTherapy - case "Other" => Other - case "Radiation" => Radiation - case "Surgery/Procedure" => SurgeryProcedure + def typeFromString(txt: String): Option[InterventionType] = { + All.values.find(_.name === txt) } sealed trait DeliveryMethod diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala index ac5feef..e734779 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala @@ -7,9 +7,41 @@ import xyz.driver.pdsuicommon.logging._ import xyz.driver.pdsuicommon.utils.Utils import xyz.driver.pdsuidomain.entities.Trial.Status -final case class StudyDesign(id: LongId[StudyDesign], name: String) +import scalaz.syntax.equal._ +import scalaz.Scalaz.stringInstance + +sealed trait StudyDesign { + val id: LongId[StudyDesign] + val name: String +} object StudyDesign { + + final case object Randomized extends StudyDesign { + val id: LongId[StudyDesign] = LongId[StudyDesign](1) + val name: String = "Randomized" + } + + final case object NonRandomized extends StudyDesign { + val id: LongId[StudyDesign] = LongId[StudyDesign](2) + val name: String = "Non-randomized" + } + + final case object SingleGroupAssignment extends StudyDesign { + val id: LongId[StudyDesign] = LongId[StudyDesign](3) + val name: String = "Single-group assignment" + } + + val All = Seq[StudyDesign]( + Randomized, + NonRandomized, + SingleGroupAssignment + ) + + def fromString(txt: String): Option[StudyDesign] = { + All.find(_.name === txt) + } + implicit def toPhiString(x: StudyDesign): PhiString = { import x._ phi"StudyDesign(id=$id, category=${Unsafe(name)})" diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/trialcuration.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/trialcuration.scala index 84dcb88..0ec1782 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/trialcuration.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/trialcuration.scala @@ -131,10 +131,7 @@ object trialcuration { description = generators.nextString() ) - def nextStudyDesign(): StudyDesign = StudyDesign( - id = nextLongId[StudyDesign], - name = generators.nextString() - ) + def nextStudyDesign(): StudyDesign = generators.oneOf[StudyDesign](StudyDesign.All: _*) def nextInterventionType(): InterventionType = generators.oneOf[InterventionType]( RadiationTherapy, diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala index 69e8b75..4999365 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala @@ -34,7 +34,7 @@ object document { val name = fields .get("name") .map(_.convertTo[String]) - .getOrElse(deserializationError(s"Intervention type json object does not contain `name` field: $json")) + .getOrElse(deserializationError(s"Document type json object does not contain `name` field: $json")) DocumentType .fromString(name) diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala index bd68566..e557e47 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala @@ -128,7 +128,9 @@ object intervention { .map(_.convertTo[String]) .getOrElse(deserializationError(s"Intervention type json object does not contain `name` field: $json")) - InterventionType.typeFromString(name) + InterventionType + .typeFromString(name) + .getOrElse(deserializationError(s"Unknown intervention type: $name")) case _ => deserializationError(s"Expected Json Object as Intervention type, but got $json") } diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala index eac5ea7..09517e6 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala @@ -42,13 +42,13 @@ object record { val name = fields .get("name") .map(_.convertTo[String]) - .getOrElse(deserializationError(s"Intervention type json object does not contain `name` field: $json")) + .getOrElse(deserializationError(s"Provider type json object does not contain `name` field: $json")) ProviderType .fromString(name) .getOrElse(deserializationError(s"Unknown provider type: $name")) - case _ => deserializationError(s"Expected Json Object as Intervention type, but got $json") + case _ => deserializationError(s"Expected Json Object as Provider type, but got $json") } override def write(obj: ProviderType) = diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala index e801666..3002b38 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala @@ -7,6 +7,23 @@ object studydesign { import DefaultJsonProtocol._ import common._ - implicit val studyDesignFormat: RootJsonFormat[StudyDesign] = jsonFormat2(StudyDesign.apply) + implicit val studyDesignFormat: RootJsonFormat[StudyDesign] = new RootJsonFormat[StudyDesign] { + override def read(json: JsValue): StudyDesign = json match { + case JsObject(fields) => + val name = fields + .get("name") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"Study design json object does not contain `name` field: $json")) + + StudyDesign + .fromString(name) + .getOrElse(deserializationError(s"Unknown study design: $name")) + + case _ => deserializationError(s"Expected Json Object as Study design, but got $json") + } + + override def write(obj: StudyDesign) = + JsObject("id" -> obj.id.toJson, "name" -> obj.name.toJson) + } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala index 1e9a226..12d40df 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala @@ -3,11 +3,10 @@ package xyz.driver.pdsuidomain.formats.json.studydesign import xyz.driver.pdsuidomain.entities.StudyDesign import play.api.libs.functional.syntax._ import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.LongId final case class ApiStudyDesign(id: Long, name: String) { - def toDomain = StudyDesign(id = LongId[StudyDesign](id), name = name) + def toDomain: Option[StudyDesign] = StudyDesign.fromString(name) } object ApiStudyDesign { diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala index 87f32ec..ce7ac10 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala @@ -27,7 +27,7 @@ class RestInterventionTypeService(transport: ServiceTransport, baseUri: Uri)( reply <- apiResponse[ListResponse[ApiInterventionType]](response) } yield { { - val domain = reply.items.map(_.toDomain) + val domain = reply.items.flatMap(_.toDomain) GetListReply.EntityList(domain.toList, reply.meta.itemsCount) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala index 98b397d..b1684eb 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala @@ -26,7 +26,7 @@ class RestStudyDesignService(transport: ServiceTransport, baseUri: Uri)( response <- transport.sendRequestGetResponse(requestContext)(request) reply <- apiResponse[ListResponse[ApiStudyDesign]](response) } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) + GetListReply.EntityList(reply.items.flatMap(_.toDomain), reply.meta.itemsCount) } } -- cgit v1.2.3 From 12cee94e187ada6413adc78e0fcc46ed930c306a Mon Sep 17 00:00:00 2001 From: vlad Date: Wed, 18 Oct 2017 13:12:16 -0700 Subject: Fixing RestEligibilityVerificationService to support empty ineligible_arms --- .../services/rest/RestEligibilityVerificationService.scala | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/main/scala/xyz/driver') diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala index d727d70..93ee2ab 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala @@ -37,8 +37,14 @@ class RestEligibilityVerificationService(transport: ServiceTransport, baseUri: U excludedArms: Seq[LongId[EligibilityArm]])( implicit ctx: AuthorizedServiceRequestContext[AuthUserInfo]): Future[eligibility.MismatchRankedLabels] = { - val query = - Seq("disease" -> cancerType.toString.toUpperCase, "ineligible_arms" -> excludedArms.map(_.id).mkString(",")) + val query = Seq("disease" -> cancerType.toString.toUpperCase) ++ (if (excludedArms.nonEmpty) { + Seq( + "ineligible_arms" -> excludedArms + .map(_.id) + .mkString(",")) + } else { + Seq.empty[(String, String)] + }) val request = get(baseUri, s"/v1/patients/$patientId/labels", query) optionalResponse[MismatchRankedLabels](transport.sendRequest(ctx)(request)) -- cgit v1.2.3 From 608bf540c38a2656dd18423b40362bedbdaeabd7 Mon Sep 17 00:00:00 2001 From: Kseniya Tomskikh Date: Wed, 11 Oct 2017 19:39:17 +0700 Subject: PDSUI-1088 Added labelVersion to documents --- .../scala/xyz/driver/pdsuidomain/entities/Document.scala | 3 ++- .../driver/pdsuidomain/fakes/entities/recordprocessing.scala | 3 ++- .../driver/pdsuidomain/fakes/entities/rep/DocumentGen.scala | 1 + .../pdsuidomain/formats/json/document/ApiDocument.scala | 12 ++++++++---- .../formats/json/document/ApiPartialDocument.scala | 6 ++++-- .../pdsuidomain/formats/json/sprayformats/document.scala | 6 ++++-- src/test/scala/xyz/driver/pdsuidomain/DocumentSuite.scala | 3 ++- .../formats/json/sprayformats/DocumentFormatSuite.scala | 5 +++-- 8 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/DocumentGen.scala (limited to 'src/main/scala/xyz/driver') diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala index 258aa03..fa5f4ce 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala @@ -456,7 +456,8 @@ final case class Document(id: LongId[Document] = LongId(0L), meta: Option[TextJson[Meta]], // not null startDate: Option[LocalDate], // not null endDate: Option[LocalDate], - lastUpdate: LocalDateTime) { + lastUpdate: LocalDateTime, + labelVersion: Int) { import Document.Status._ diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/recordprocessing.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/recordprocessing.scala index d2a648c..8ba1d82 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/recordprocessing.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/recordprocessing.scala @@ -182,7 +182,8 @@ object recordprocessing { meta = nextOption(nextDocumentMetaJson()), startDate = startDate, endDate = endDate, - lastUpdate = nextLocalDateTime + lastUpdate = nextLocalDateTime, + labelVersion = generators.nextInt(100) ) } diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/DocumentGen.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/DocumentGen.scala new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/DocumentGen.scala @@ -0,0 +1 @@ + diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala index 3f1ecfe..250e650 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala @@ -25,7 +25,8 @@ final case class ApiDocument(id: Long, assignee: Option[String], previousAssignee: Option[String], lastActiveUser: Option[String], - meta: Option[String]) { + meta: Option[String], + labelVersion: Int) { private def extractStatus(status: String): Document.Status = Document.Status.fromString(status).getOrElse(throw new NoSuchElementException(s"Status $status unknown")) @@ -50,7 +51,8 @@ final case class ApiDocument(id: Long, meta = this.meta.map(x => TextJson(JsonSerializer.deserialize[Document.Meta](x))), startDate = this.startDate, endDate = this.endDate, - lastUpdate = this.lastUpdate.toLocalDateTime() + lastUpdate = this.lastUpdate.toLocalDateTime(), + labelVersion = this.labelVersion ) } @@ -83,7 +85,8 @@ object ApiDocument { (JsPath \ "lastActiveUser").formatNullable[String] and (JsPath \ "meta").formatNullable(Format(Reads { x => JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) + }, Writes[String](Json.parse))) and + (JsPath \ "labelVersion").format[Int] )(ApiDocument.apply, unlift(ApiDocument.unapply)) def fromDomain(document: Document): ApiDocument = { @@ -104,7 +107,8 @@ object ApiDocument { assignee = document.assignee.map(_.id), previousAssignee = document.previousAssignee.map(_.id), lastActiveUser = document.lastActiveUserId.map(_.id), - meta = document.meta.map(meta => JsonSerializer.serialize(meta.content)) + meta = document.meta.map(meta => JsonSerializer.serialize(meta.content)), + labelVersion = document.labelVersion ) } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala index 032ddf6..ecbdaed 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala @@ -47,7 +47,8 @@ final case class ApiPartialDocument(recordId: Option[Long], meta = meta.cata(x => Some(TextJson(JsonSerializer.deserialize[Meta](x))), None, orig.meta), startDate = startDate.cata(Some(_), None, orig.startDate), endDate = endDate.cata(Some(_), None, orig.endDate), - lastUpdate = LocalDateTime.MIN // Should update internally in a business logic module + lastUpdate = LocalDateTime.MIN, // Should update internally in a business logic module, + labelVersion = orig.labelVersion ) def toDomain: Try[Document] = Try { @@ -75,7 +76,8 @@ final case class ApiPartialDocument(recordId: Option[Long], assignee = None, previousAssignee = None, lastActiveUserId = None, - lastUpdate = LocalDateTime.MIN + lastUpdate = LocalDateTime.MIN, + labelVersion = 0 ) } else { throw new JsonValidationException(validationErrors) diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala index f742915..c584b96 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala @@ -126,7 +126,8 @@ object document { "previousAssignee" -> document.previousAssignee.toJson, "meta" -> document.meta.toJson, "lastActiveUser" -> document.lastActiveUserId.toJson, - "lastUpdate" -> document.lastUpdate.toJson + "lastUpdate" -> document.lastUpdate.toJson, + "labelVersion" -> document.labelVersion.toJson ) override def read(json: JsValue): Document = json match { @@ -185,7 +186,8 @@ object document { assignee = None, previousAssignee = None, lastActiveUserId = None, - lastUpdate = LocalDateTime.MIN + lastUpdate = LocalDateTime.MIN, + labelVersion = 0 ) case _ => deserializationError(s"Expected Json Object as Document, but got $json") diff --git a/src/test/scala/xyz/driver/pdsuidomain/DocumentSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/DocumentSuite.scala index 7d8a418..915e4e7 100644 --- a/src/test/scala/xyz/driver/pdsuidomain/DocumentSuite.scala +++ b/src/test/scala/xyz/driver/pdsuidomain/DocumentSuite.scala @@ -82,7 +82,8 @@ class DocumentSuite extends BaseSuite { startDate = Some(lastUpdate.toLocalDate.minusDays(2)), endDate = None, lastUpdate = lastUpdate, - meta = Some(TextJson(Document.Meta(1.1, 2.2))) + meta = Some(TextJson(Document.Meta(1.1, 2.2))), + labelVersion = 1 ) } } diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala index e6dd4a1..111da6e 100644 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala +++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala @@ -28,14 +28,15 @@ class DocumentFormatSuite extends FlatSpec with Matchers { requiredType = Some(Document.RequiredType.OPN), meta = None, startDate = None, - endDate = None + endDate = None, + labelVersion = 0 ) val writtenJson = documentFormat.write(orig) writtenJson should be( """{"id":1,"recordId":101,"physician":"physician","typeId":10,"provider":"provider 21","providerTypeId":21, "requiredType":"OPN","institutionName":"institution name","startDate":null,"endDate":null,"status":"New","assignee":null,"previousStatus":null, - "previousAssignee":null,"lastActiveUser":null,"lastUpdate":"2017-08-10T18:00Z","meta":null}""".parseJson) + "previousAssignee":null,"lastActiveUser":null,"lastUpdate":"2017-08-10T18:00Z","meta":null,"labelVersion":0}""".parseJson) val createDocumentJson = """{"recordId":101,"physician":"physician","typeId":10,"provider":"provider 21","providerTypeId":21}""".parseJson -- cgit v1.2.3