diff options
author | vlad <vlad@driver.xyz> | 2017-06-30 19:38:37 -0700 |
---|---|---|
committer | vlad <vlad@driver.xyz> | 2017-06-30 19:38:37 -0700 |
commit | 96d81a36286e41035ff4068859a3b0f9da924fbc (patch) | |
tree | 8d9f0014140d1f07ca449b56adaba8ccb3d2fc59 /src/main/scala/xyz/driver/pdsuidomain/entities | |
parent | a997aa6539d1f0af4ab4fc395ff2033335da312a (diff) | |
download | rest-query-96d81a36286e41035ff4068859a3b0f9da924fbc.tar.gz rest-query-96d81a36286e41035ff4068859a3b0f9da924fbc.tar.bz2 rest-query-96d81a36286e41035ff4068859a3b0f9da924fbc.zip |
Latest PDS UI utils including all the domain stuffv0.1.12
Diffstat (limited to 'src/main/scala/xyz/driver/pdsuidomain/entities')
19 files changed, 627 insertions, 40 deletions
diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala index 5af00bc..5c957fb 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala @@ -1,6 +1,6 @@ package xyz.driver.pdsuidomain.entities -import java.time.{LocalDate, LocalDateTime} +import java.time.{LocalDate, LocalDateTime, ZoneId} import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.core.{JsonGenerator, JsonParser} @@ -17,6 +17,72 @@ import xyz.driver.pdsuicommon.compat.Implicits._ final case class ProviderType(id: LongId[ProviderType], name: String) object ProviderType { + sealed trait ProviderTypeName + case object MedicalOncology extends ProviderTypeName + case object Surgery extends ProviderTypeName + case object Pathology extends ProviderTypeName + case object MolecularPathology extends ProviderTypeName + case object LaboratoryMedicine extends ProviderTypeName + case object Radiology extends ProviderTypeName + case object InterventionalRadiology extends ProviderTypeName + case object RadiationOncology extends ProviderTypeName + case object PrimaryCare extends ProviderTypeName + case object Cardiology extends ProviderTypeName + case object Dermatology extends ProviderTypeName + case object Ophthalmology extends ProviderTypeName + case object Gastroenterology extends ProviderTypeName + case object Neurology extends ProviderTypeName + case object Psychiatry extends ProviderTypeName + case object Gynecology extends ProviderTypeName + case object InfectiousDisease extends ProviderTypeName + case object Immunology extends ProviderTypeName + case object Nephrology extends ProviderTypeName + case object Rheumatology extends ProviderTypeName + case object Cytology extends ProviderTypeName + case object Otolaryngology extends ProviderTypeName + case object Anesthesiology extends ProviderTypeName + case object Urology extends ProviderTypeName + case object PalliativeCare extends ProviderTypeName + case object EmergencyMedicine extends ProviderTypeName + case object SocialWork extends ProviderTypeName + case object NA extends ProviderTypeName + case object Other extends ProviderTypeName + + def fromString(txt: String): Option[ProviderTypeName] = { + txt match { + case "Medical Oncology" => Some(MedicalOncology) + case "Surgery" => Some(Surgery) + case "Pathology" => Some(Pathology) + case "Molecular Pathology" => Some(MolecularPathology) + case "LaboratoryMedicine" => Some(LaboratoryMedicine) + case "Radiology" => Some(Radiology) + case "Interventional Radiology" => Some(InterventionalRadiology) + case "Radiation Oncology" => Some(RadiationOncology) + case "Primary Care" => Some(PrimaryCare) + case "Cardiology" => Some(Cardiology) + case "Dermatology" => Some(Dermatology) + case "Ophthalmology" => Some(Ophthalmology) + case "Gastroenterology" => Some(Gastroenterology) + case "Neurology" => Some(Neurology) + case "Psychiatry" => Some(Psychiatry) + case "Gynecology" => Some(Gynecology) + case "Infectious Disease" => Some(InfectiousDisease) + case "Immunology" => Some(Immunology) + case "Nephrology" => Some(Nephrology) + case "Rheumatology" => Some(Rheumatology) + case "Cytology" => Some(Cytology) + case "Otolaryngology" => Some(Otolaryngology) + case "Anesthesiology" => Some(Anesthesiology) + case "Urology" => Some(Urology) + case "Palliative Care" => Some(PalliativeCare) + case "Emergency Medicine" => Some(EmergencyMedicine) + case "Social Work" => Some(SocialWork) + case "N/A" => Some(NA) + case "Other" => Some(Other) + case _ => None + } + } + implicit def toPhiString(x: ProviderType): PhiString = { import x._ phi"ProviderType(id=$id, category=${Unsafe(name)})" @@ -26,6 +92,38 @@ object ProviderType { final case class DocumentType(id: LongId[DocumentType], name: String) object DocumentType { + sealed trait DocumentTypeName + case object OutpatientPhysicianNote extends DocumentTypeName + case object DischargeNote extends DocumentTypeName + case object LaboratoryReport extends DocumentTypeName + case object MedicationList extends DocumentTypeName + case object HospitalizationNote extends DocumentTypeName + case object PathologyReport extends DocumentTypeName + case object RadiologyReport extends DocumentTypeName + case object OperativeProcedureReport extends DocumentTypeName + case object MedicationAdministration extends DocumentTypeName + case object SocialWorkCaseManagementNote extends DocumentTypeName + case object NonPhysicianProviderNote extends DocumentTypeName + case object Administrative extends DocumentTypeName + + def fromString(txt: String): Option[DocumentTypeName] = { + txt match { + case "Outpatient Physician Note" => Some(OutpatientPhysicianNote) + case "Discharge Note" => Some(DischargeNote) + case "Laboratory Report" => Some(LaboratoryReport) + case "Medication List" => Some(MedicationList) + case "Hospitalization Note" => Some(HospitalizationNote) + case "Pathology Report" => Some(PathologyReport) + case "Radiology Report" => Some(RadiologyReport) + case "Operative/Procedure Report" => Some(OperativeProcedureReport) + case "Medication Administration" => Some(MedicationAdministration) + case "Social Work/Case Management Note" => Some(SocialWorkCaseManagementNote) + case "Non-physician Provider Note" => Some(NonPhysicianProviderNote) + case "Administrative" => Some(Administrative) + case _ => None + } + } + implicit def toPhiString(x: DocumentType): PhiString = { import x._ phi"DocumentType(id=$id, name=${Unsafe(name)})" @@ -71,6 +169,7 @@ object Document { def oneOf(xs: Set[Status]): Boolean = xs.contains(this) } + object Status { case object New extends Status case object Organized extends Status @@ -82,12 +181,58 @@ object Document { val All = Set[Status](New, Organized, Extracted, Done, Flagged, Archived) val AllPrevious = Set[Status](Organized, Extracted) + val fromString: PartialFunction[String, Status] = { + case "New" => Status.New + case "Organized" => Status.Organized + case "Extracted" => Status.Extracted + case "Done" => Status.Done + case "Flagged" => Status.Flagged + case "Archived" => Status.Archived + } + + def statusToString(x: Status): String = x match { + case Status.New => "New" + case Status.Organized => "Organized" + case Status.Extracted => "Extracted" + case Status.Done => "Done" + case Status.Flagged => "Flagged" + case Status.Archived => "Archived" + } + implicit def toPhiString(x: Status): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) } + sealed trait RequiredType extends Product with Serializable { + + def oneOf(xs: RequiredType*): Boolean = xs.contains(this) + + def oneOf(xs: Set[RequiredType]): Boolean = xs.contains(this) + + } + + object RequiredType { + case object OPN extends RequiredType + case object PN extends RequiredType + + val All = Set[RequiredType](OPN, PN) + + val fromString: PartialFunction[String, RequiredType] = { + case "OPN" => RequiredType.OPN + case "PN" => RequiredType.PN + } + + def requiredTypeToString(x: RequiredType): String = x match { + case RequiredType.OPN => "OPN" + case RequiredType.PN => "PN" + } + + implicit def toPhiString(x: RequiredType): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) + } + implicit def toPhiString(x: Document): PhiString = { import x._ - phi"Document(id=$id, status=$status, assignee=$assignee, previousAssignee=$previousAssignee, recordId=$recordId)" + phi"Document(id=$id, status=$status, assignee=$assignee, " + + phi"previousAssignee=$previousAssignee, lastActiveUserId=$lastActiveUserId, recordId=$recordId)" } val validator: Validator[Document, Document] = { input => @@ -126,11 +271,13 @@ final case class Document(id: LongId[Document] = LongId(0L), previousStatus: Option[Document.Status], assignee: Option[LongId[User]], previousAssignee: Option[LongId[User]], + lastActiveUserId: Option[LongId[User]], recordId: LongId[MedicalRecord], physician: Option[String], typeId: Option[LongId[DocumentType]], // not null providerName: Option[String], // not null providerTypeId: Option[LongId[ProviderType]], // not null + requiredType: Option[Document.RequiredType], meta: Option[TextJson[Meta]], // not null startDate: Option[LocalDate], // not null endDate: Option[LocalDate], @@ -142,6 +289,22 @@ final case class Document(id: LongId[Document] = LongId(0L), assert(AllPrevious.contains(previousStatus.get), s"Previous status has invalid value: ${previousStatus.get}") } + def getRequiredType(documentTypeName: String, providerTypeName: String): Option[Document.RequiredType] = { + import DocumentType.{OutpatientPhysicianNote, PathologyReport} + import ProviderType.MedicalOncology + + (DocumentType.fromString(documentTypeName), ProviderType.fromString(providerTypeName), startDate) match { + case (Some(OutpatientPhysicianNote), Some(MedicalOncology), Some(date)) + if !(date.isAfter(LocalDate.now(ZoneId.of("Z"))) || date.isBefore( + LocalDate.now(ZoneId.of("Z")).minusMonths(6))) => + Some(Document.RequiredType.OPN) + + case (Some(PathologyReport), _, _) => Some(Document.RequiredType.PN) + + case _ => None + } + } + // TODO: with the current business logic code this constraint sometimes harmful // require(status match { // case Document.Status.New if assignee.isDefined => false diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala index 9972142..32258dc 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala @@ -19,7 +19,6 @@ object ExtractedData { final case class Meta(keyword: Meta.Keyword, evidence: Meta.Evidence) object Meta { - final case class Evidence(pageRatio: Double, start: TextLayerPosition, end: TextLayerPosition) final case class TextLayerPosition(page: Integer, index: Integer, offset: Integer) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala index dc82050..e691547 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala @@ -28,6 +28,7 @@ final case class Intervention(id: LongId[Intervention], typeId: Option[LongId[InterventionType]], originalType: Option[String], description: String, + originalDescription: String, isActive: Boolean) object Intervention { diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/LinkedPatient.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/LinkedPatient.scala new file mode 100644 index 0000000..e82bcc3 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/LinkedPatient.scala @@ -0,0 +1,16 @@ +package xyz.driver.pdsuidomain.entities + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ + +object LinkedPatient { + + implicit def toPhiString(x: LinkedPatient): PhiString = { + import x._ + phi"LinkedPatient(userId=$userId, patientId=$patientId, trialId=$trialId)" + } +} + +case class LinkedPatient(userId: LongId[User], + patientId: UuidId[Patient], + trialId: StringId[Trial]) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala index 17de7de..0e30fa0 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala @@ -134,7 +134,8 @@ object MedicalRecord { implicit def toPhiString(x: MedicalRecord): PhiString = { import x._ - phi"MedicalRecord(id=$id, status=$status, assignee=$assignee, previousAssignee=$previousAssignee)" + phi"MedicalRecord(id=$id, status=$status, assignee=$assignee, " + + phi"previousAssignee=$previousAssignee, lastActiveUserId=$lastActiveUserId)" } } @@ -143,6 +144,7 @@ case class MedicalRecord(id: LongId[MedicalRecord], previousStatus: Option[MedicalRecord.Status], assignee: Option[LongId[User]], previousAssignee: Option[LongId[User]], + lastActiveUserId: Option[LongId[User]], patientId: UuidId[Patient], requestId: RecordRequestId, disease: String, diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Patient.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Patient.scala index 93262a4..695245c 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Patient.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Patient.scala @@ -45,7 +45,7 @@ object Patient { implicit def toPhiString(x: Patient): PhiString = { import x._ - phi"Patient(id=$id, status=$status, previousStatus=$previousStatus, " + + phi"Patient(id=$id, status=$status, previousStatus=$previousStatus, lastActiveUserId=$lastActiveUserId" + phi"assignee=$assignee, previousAssignee=$previousAssignee)" } } @@ -57,6 +57,7 @@ final case class Patient(id: UuidId[Patient], assignee: Option[LongId[User]], previousStatus: Option[Patient.Status], previousAssignee: Option[LongId[User]], + lastActiveUserId: Option[LongId[User]], isUpdateRequired: Boolean, condition: String, orderId: PatientOrderId, diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientEligibleTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientEligibleTrial.scala index 8084884..e16c324 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientEligibleTrial.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientEligibleTrial.scala @@ -82,35 +82,8 @@ object PatientTrialArmGroup { implicit def toPhiString(x: PatientTrialArmGroup): PhiString = { import x._ phi"PatientTrialArmGroup(id=$id, eligibleTrialId=$eligibleTrialId, " + - phi"eligibilityStatus=${Unsafe(eligibilityStatus)}, isVerified=$isVerified)" - } - - /** - * @see https://driverinc.atlassian.net/wiki/display/DMPD/EV+Business+Process - */ - def getEligibilityStatusForEvToRc(criterionList: List[(Option[Boolean], Option[FuzzyValue])]): Option[FuzzyValue] = { - def isEligible = { - // Eligible, if for all (verified for EV) label-criteria eligibilityStatus=NULL or YES and at least one has status=YES - // If method executes from PatientService (when EV submit patient) need to check value PatientCriterion.isVerified - val verifiedList = criterionList.filter { case (isVerifiedOpt, _) => isVerifiedOpt.isEmpty || isVerifiedOpt.get } - verifiedList.forall { - case (_, eligibilityStatus) => - eligibilityStatus.isEmpty || eligibilityStatus.contains(FuzzyValue.Yes) - } && verifiedList.exists { case (_, eligibilityStatus) => eligibilityStatus.contains(FuzzyValue.Yes) } - } - - if (criterionList.exists { - case (isVerified, eligibilityStatus) => - eligibilityStatus.contains(FuzzyValue.No) && (isVerified.isEmpty || isVerified.get) - }) { Some(FuzzyValue.No) } else if (criterionList.forall { - case (_, eligibilityStatus) => eligibilityStatus.isEmpty - }) { - None - } else if (isEligible) { - Some(FuzzyValue.Yes) - } else { - Some(FuzzyValue.Maybe) - } + phi"eligibilityStatus=${Unsafe(eligibilityStatus)}, " + + phi"verifiedEligibilityStatus=${Unsafe(verifiedEligibilityStatus)}, isVerified=$isVerified)" } /** @@ -131,14 +104,16 @@ object PatientTrialArmGroup { final case class PatientTrialArmGroup(id: LongId[PatientTrialArmGroup], eligibleTrialId: UuidId[PatientEligibleTrial], eligibilityStatus: Option[FuzzyValue], + verifiedEligibilityStatus: Option[FuzzyValue], isVerified: Boolean) object PatientTrialArmGroupView { implicit def toPhiString(x: PatientTrialArmGroupView): PhiString = { import x._ - phi"PatientTrialArmGroupView(id=$id, patientId=$patientId, trialId=$trialId, hypothesisId=$hypothesisId, " + - phi"eligibilityStatus=${Unsafe(eligibilityStatus)}, isVerified=$isVerified)" + phi"PatientTrialArmGroupView(id=$id, patientId=$patientId, trialId=$trialId, " + + phi"hypothesisId=$hypothesisId, eligibilityStatus=${Unsafe(eligibilityStatus)}, " + + phi"verifiedEligibilityStatus=${Unsafe(verifiedEligibilityStatus)}, isVerified=$isVerified)" } } @@ -147,11 +122,13 @@ final case class PatientTrialArmGroupView(id: LongId[PatientTrialArmGroup], trialId: StringId[Trial], hypothesisId: UuidId[Hypothesis], eligibilityStatus: Option[FuzzyValue], + verifiedEligibilityStatus: Option[FuzzyValue], isVerified: Boolean) { def applyTo(trialArmGroup: PatientTrialArmGroup) = { trialArmGroup.copy( eligibilityStatus = this.eligibilityStatus, + verifiedEligibilityStatus = this.verifiedEligibilityStatus, isVerified = this.isVerified ) } diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabelEvidenceView.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabelEvidenceView.scala new file mode 100644 index 0000000..60298b9 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabelEvidenceView.scala @@ -0,0 +1,28 @@ +package xyz.driver.pdsuidomain.entities + +import java.time.LocalDate + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ + +object PatientLabelEvidenceView { + implicit def toPhiString(x: PatientLabelEvidenceView): PhiString = { + import x._ + phi"PatientLabelEvidenceViewRepository.Row(id=$id, value=$value, documentId=$documentId, " + + phi"evidenceId=$evidenceId, reportId=$reportId, patientId=$patientId, labelId=$labelId, " + + phi"isImplicitMatch=$isImplicitMatch)" + } +} + +final case class PatientLabelEvidenceView(id: LongId[PatientLabelEvidence], + value: FuzzyValue, + evidenceText: String, + documentId: Option[LongId[Document]], + evidenceId: Option[LongId[ExtractedData]], + reportId: Option[UuidId[DirectReport]], + documentType: String, + date: Option[LocalDate], // Document.startDate is optional + providerType: String, + patientId: UuidId[Patient], + labelId: LongId[Label], + isImplicitMatch: Boolean) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala index e3b323f..82204c2 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala @@ -12,7 +12,6 @@ case class RawTrialLabel(nctId: StringId[Trial], armName: String, armId: LongId[Arm], labelId: LongId[Label], - label: String, value: Option[Boolean], criterionId: LongId[Criterion], criteria: String, @@ -25,7 +24,7 @@ object RawTrialLabel { implicit def toPhiString(x: RawTrialLabel): PhiString = { import x._ phi"RawTrialLabel(nctId=$nctId, trialId=$trialId, condition=${Unsafe(condition)}, lastReviewed=$lastReviewed, " + - phi"armId=$armId, armName=${Unsafe(armName)}, labelId=$labelId, label=${Unsafe(label)}, value=$value, " + + phi"armId=$armId, armName=${Unsafe(armName)}, labelId=$labelId, value=$value, " + phi"criterionId=$criterionId, criteria=${Unsafe(criteria)}, criterionArmId=$criterionArmId, " + phi"isCompound=$isCompound, isDefining=$isDefining)" } diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala index f5ab3cb..0f478ca 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala @@ -57,8 +57,8 @@ object Trial { implicit def toPhiString(x: Trial): PhiString = { import x._ phi"Trial(id=$id, externalId=$externalId, status=$status, previousStatus=$previousStatus, " + - phi"assignee=$assignee, previousAssignee=$previousAssignee, isSummaryReviewed=$isSummaryReviewed, " + - phi"isCriteriaReviewed=$isCriteriaReviewed)" + phi"lastActiveUserId=$lastActiveUserId, assignee=$assignee, previousAssignee=$previousAssignee, " + + phi"isSummaryReviewed=$isSummaryReviewed, isCriteriaReviewed=$isCriteriaReviewed)" } case class Locations(locations: List[String]) @@ -81,6 +81,7 @@ final case class Trial(id: StringId[Trial], assignee: Option[LongId[User]], previousStatus: Option[Status], previousAssignee: Option[LongId[User]], + lastActiveUserId: Option[LongId[User]], lastUpdate: LocalDateTime, condition: Condition, phase: String, diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/UserHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/UserHistory.scala new file mode 100644 index 0000000..b55369e --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/UserHistory.scala @@ -0,0 +1,156 @@ +package xyz.driver.pdsuidomain.entities + +import java.time.{LocalDateTime, ZoneId} + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuicommon.utils.Utils + +final case class UserHistory(id: LongId[UserHistory], + executor: LongId[User], + recordId: Option[LongId[MedicalRecord]] = None, + documentId: Option[LongId[Document]] = None, + trialId: Option[StringId[Trial]] = None, + patientId: Option[UuidId[Patient]] = None, + state: UserHistory.State, + action: UserHistory.Action, + created: LocalDateTime = LocalDateTime.now(ZoneId.of("Z"))) + +object UserHistory { + + def forDocument(executor: LongId[User], + documentId: LongId[Document], + state: UserHistory.State, + action: UserHistory.Action): UserHistory = UserHistory ( + id = LongId(0L), + executor = executor, + documentId = Some(documentId), + state = state, + action = action + ) + + def forRecord(executor: LongId[User], + recordId: LongId[MedicalRecord], + state: UserHistory.State, + action: UserHistory.Action): UserHistory = UserHistory ( + id = LongId(0L), + executor = executor, + recordId = Some(recordId), + state = state, + action = action + ) + + def forTrial(executor: LongId[User], + trialId: StringId[Trial], + state: UserHistory.State, + action: UserHistory.Action): UserHistory = UserHistory ( + id = LongId(0L), + executor = executor, + trialId = Some(trialId), + state = state, + action = action + ) + + def forPatient(executor: LongId[User], + patientId: UuidId[Patient], + state: UserHistory.State, + action: UserHistory.Action): UserHistory = UserHistory ( + id = LongId(0L), + executor = executor, + patientId = Some(patientId), + state = state, + action = action + ) + + sealed trait State extends Product with Serializable { + + def oneOf(xs: State*): Boolean = xs.contains(this) + + def oneOf(xs: Set[State]): Boolean = xs.contains(this) + } + + object State { + case object Clean extends State + case object Organize extends State + case object Extract extends State + case object Summarize extends State + case object Criteriarize extends State + case object Verify extends State + case object Curate extends State + case object Review extends State + case object Flag extends State + + val All: Set[State] = Set[State](Clean, Organize, Extract, Summarize, Criteriarize, Verify, Curate, Review, Flag) + + val fromString: PartialFunction[String, State] = { + case "Clean" => State.Clean + case "Organize" => State.Organize + case "Extract" => State.Extract + case "Summarize" => State.Summarize + case "Criteriarize" => State.Criteriarize + case "Verify" => State.Verify + case "Curate" => State.Curate + case "Review" => State.Review + case "Flag" => State.Flag + } + + def stateToString(x: State): String = x match { + case State.Clean => "Clean" + case State.Organize => "Organize" + case State.Extract => "Extract" + case State.Summarize => "Summarize" + case State.Criteriarize => "Criteriarize" + case State.Verify => "Verify" + case State.Curate => "Curate" + case State.Review => "Review" + case State.Flag => "Flag" + } + + implicit def toPhiString(x: State): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) + } + + sealed trait Action extends Product with Serializable { + + def oneOf(xs: Action*): Boolean = xs.contains(this) + + def oneOf(xs: Set[Action]): Boolean = xs.contains(this) + } + + object Action { + case object Start extends Action + case object Submit extends Action + case object Unassign extends Action + case object Resolve extends Action + case object Flag extends Action + case object Archive extends Action + + val All: Set[Action] = Set[Action](Start, Submit, Unassign, Resolve, Flag, Archive) + + val fromString: PartialFunction[String, Action] = { + case "Start" => Action.Start + case "Submit" => Action.Submit + case "Unassign" => Action.Unassign + case "Resolve" => Action.Resolve + case "Flag" => Action.Flag + case "Archive" => Action.Archive + } + + def actionToString(x: Action): String = x match { + case Action.Start => "Start" + case Action.Submit => "Submit" + case Action.Unassign => "Unassign" + case Action.Resolve => "Resolve" + case Action.Flag => "Flag" + case Action.Archive => "Archive" + } + + implicit def toPhiString(x: Action): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) + } + + implicit def toPhiString(x: UserHistory): PhiString = { + import x._ + phi"UserHistory(id=$id, executor=$executor, recordId=$recordId, " + + phi"documentId=$documentId, trialId=$trialId, patientId=$patientId, " + + phi"state=$state, action=$action, created=$created)" + } +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabel.scala new file mode 100644 index 0000000..5474413 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabel.scala @@ -0,0 +1,30 @@ +package xyz.driver.pdsuidomain.entities.export.patient + +import xyz.driver.pdsuicommon.domain.LongId +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.{Label, RawPatientLabel} + +final case class ExportPatientLabel(id: LongId[Label], + name: String, + evidences: List[ExportPatientLabelEvidence]) + +object ExportPatientLabel extends PhiLogging { + + implicit def toPhiString(x: ExportPatientLabel): PhiString = { + import x._ + phi"ExportPatientLabel(id=$id, evidences=$evidences)" + } + + def fromRaw(labelId: LongId[Label], rawPatientLabels: List[RawPatientLabel]): ExportPatientLabel = { + val firstLabel = rawPatientLabels.headOption + if (firstLabel.isEmpty) { + logger.warn(phi"rawPatientLabels is empty, labelId: $labelId") + } + + ExportPatientLabel( + id = labelId, + name = firstLabel.map(_.label).getOrElse(""), + evidences = rawPatientLabels.map(ExportPatientLabelEvidence.fromRaw) + ) + } +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidence.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidence.scala new file mode 100644 index 0000000..fb40339 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidence.scala @@ -0,0 +1,32 @@ +package xyz.driver.pdsuidomain.entities.export.patient + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.{ExtractedData, RawPatientLabel} + +final case class ExportPatientLabelEvidence(id: LongId[ExtractedData], + value: FuzzyValue, + evidenceText: String, + document: ExportPatientLabelEvidenceDocument) + +object ExportPatientLabelEvidence { + + implicit def toPhiString(x: ExportPatientLabelEvidence): PhiString = { + import x._ + phi"ExportPatientLabelEvidence(id=${Unsafe(id)}, value=$value, " + + phi"evidenceText=${Unsafe(evidenceText)}, document=$document)" + } + + def fromRaw(x: RawPatientLabel) = ExportPatientLabelEvidence( + id = x.evidenceId, + value = x.value, + evidenceText = x.evidenceText, + document = ExportPatientLabelEvidenceDocument( + x.documentId, + x.requestId, + x.documentType, + x.providerType, + x.startDate + ) + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidenceDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidenceDocument.scala new file mode 100644 index 0000000..99912bc --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidenceDocument.scala @@ -0,0 +1,30 @@ +package xyz.driver.pdsuidomain.entities.export.patient + +import java.time.LocalDate + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.{Document, RawPatientLabel, RecordRequestId} + +final case class ExportPatientLabelEvidenceDocument(documentId: LongId[Document], + requestId: RecordRequestId, + documentType: String, + providerType: String, + date: LocalDate) + +object ExportPatientLabelEvidenceDocument extends PhiLogging { + + implicit def toPhiString(x: ExportPatientLabelEvidenceDocument): PhiString = { + import x._ + phi"ExportPatientLabelEvidenceDocument(documentId=$documentId, requestId=$requestId, " + + phi"documentType=${Unsafe(documentType)}, providerType=${Unsafe(providerType)}, date=$date)" + } + + def fromRaw(x: RawPatientLabel) = ExportPatientLabelEvidenceDocument( + documentId = x.documentId, + requestId = x.requestId, + documentType = x.documentType, + providerType = x.providerType, + date = x.startDate + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientWithLabels.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientWithLabels.scala new file mode 100644 index 0000000..e6262ed --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientWithLabels.scala @@ -0,0 +1,26 @@ +package xyz.driver.pdsuidomain.entities.export.patient + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.{Patient, RawPatientLabel} + +import scala.collection.breakOut + +final case class ExportPatientWithLabels(patientId: UuidId[Patient], labelVersion: Long, labels: List[ExportPatientLabel]) + +object ExportPatientWithLabels { + + implicit def toPhiString(x: ExportPatientWithLabels): PhiString = { + import x._ + phi"ExportPatientWithLabels(patientId=$patientId, version=${Unsafe(labelVersion)}, labels=$labels)" + } + + def fromRaw(patientId: UuidId[Patient], + rawPatientRefs: List[RawPatientLabel]) = ExportPatientWithLabels( + patientId = patientId, + labelVersion = 1L, // TODO It is needed to replace this mock label version. + labels = rawPatientRefs + .groupBy(_.labelId) + .map(Function.tupled(ExportPatientLabel.fromRaw))(breakOut) + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrial.scala new file mode 100644 index 0000000..1aed121 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrial.scala @@ -0,0 +1,27 @@ +package xyz.driver.pdsuidomain.entities.export.trial + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.Trial + +final case class ExportTrial(nctId: StringId[Trial], + trialId: UuidId[Trial], + condition: Trial.Condition, + lastReviewed: LocalDateTime) + +object ExportTrial { + + implicit def toPhiString(x: ExportTrial): PhiString = { + import x._ + phi"ExportTrial(nctId=$nctId, trialId=$trialId, condition=${Unsafe(condition)}, lastReviewed=$lastReviewed)" + } + + def fromDomain(x: Trial) = ExportTrial( + nctId = x.id, + trialId = x.externalId, + condition = x.condition, + lastReviewed = x.lastUpdate + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialArm.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialArm.scala new file mode 100644 index 0000000..5a9a406 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialArm.scala @@ -0,0 +1,15 @@ +package xyz.driver.pdsuidomain.entities.export.trial + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.Arm + +final case class ExportTrialArm(armId: LongId[Arm], armName: String) + +object ExportTrialArm { + + implicit def toPhiString(x: ExportTrialArm): PhiString = { + import x._ + phi"ExportTrialArm(armId=$armId, armName=${Unsafe(armName)})" + } +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialLabelCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialLabelCriterion.scala new file mode 100644 index 0000000..7bff22c --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialLabelCriterion.scala @@ -0,0 +1,32 @@ +package xyz.driver.pdsuidomain.entities.export.trial + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.{Arm, Criterion, Label, RawTrialLabel} + +final case class ExportTrialLabelCriterion(criterionId: LongId[Criterion], + value: Option[Boolean], + labelId: LongId[Label], + armIds: Set[LongId[Arm]], + criteria: String, + isCompound: Boolean, + isDefining: Boolean) + +object ExportTrialLabelCriterion { + + implicit def toPhiString(x: ExportTrialLabelCriterion): PhiString = { + import x._ + phi"TrialLabelCriterion(criterionId=$criterionId, value=$value, labelId=$labelId, " + + phi"criteria=${Unsafe(criteria)}, isCompound=$isCompound, isDefining=$isDefining)" + } + + def fromRaw(x: RawTrialLabel, armIds: Set[LongId[Arm]]) = ExportTrialLabelCriterion( + criterionId = x.criterionId, + value = x.value, + labelId = x.labelId, + armIds = armIds, + criteria = x.criteria, + isCompound = x.isCompound, + isDefining = x.isDefining + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialWithLabels.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialWithLabels.scala new file mode 100644 index 0000000..1655a88 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialWithLabels.scala @@ -0,0 +1,52 @@ +package xyz.driver.pdsuidomain.entities.export.trial + +import java.time.LocalDateTime + +import xyz.driver.pdsuicommon.domain._ +import xyz.driver.pdsuicommon.logging._ +import xyz.driver.pdsuidomain.entities.{RawTrialLabel, Trial} + +import scala.collection.breakOut + +final case class ExportTrialWithLabels(nctId: StringId[Trial], + trialId: UuidId[Trial], + condition: String, + lastReviewed: LocalDateTime, + labelVersion: Long, + arms: List[ExportTrialArm], + criteria: List[ExportTrialLabelCriterion]) + +object ExportTrialWithLabels { + + implicit def toPhiString(x: ExportTrialWithLabels): PhiString = { + import x._ + phi"TrialWithLabels(nctId=$nctId, trialId=$trialId, condition=${Unsafe(condition)}, " + + phi"lastReviewed=$lastReviewed, labelVersion=${Unsafe(labelVersion)}, arms=$arms, criteria=$criteria)" + } + + def fromRaw(rawData: List[RawTrialLabel]): ExportTrialWithLabels = { + val trials: Set[StringId[Trial]] = rawData.map(_.nctId)(breakOut) + + assert(trials.size == 1, "There are more than one trials in the rawData") + val trial = rawData.head + + ExportTrialWithLabels( + nctId = trial.nctId, + trialId = trial.trialId, + condition = trial.condition, + lastReviewed = trial.lastReviewed, + labelVersion = 1, // TODO It is needed to replace this mock label version. + arms = rawData.groupBy(_.armId).map { case (armId, rawTrials) => + ExportTrialArm(armId, rawTrials.head.armName) + }(breakOut), + criteria = rawData.groupBy { x => + (x.criterionId, x.labelId) + }.map { + case (_, rawTrialLabels) => + val armIds = rawTrialLabels.map(_.criterionArmId).toSet + ExportTrialLabelCriterion.fromRaw(rawTrialLabels.head, armIds) + }(breakOut) + ) + } + +} |