From ca4ada9ed1f00e2fd642e9d5a959bc6e344b06f1 Mon Sep 17 00:00:00 2001 From: Michael Gurley Date: Mon, 15 Aug 2016 12:39:22 -0400 Subject: [PATCH] closes #16 Support creating and editing drug exposures. --- app/assets/javascripts/application.js | 1 + .../interleave.drug_exposure.js.coffee | 67 ++++++++ app/assets/stylesheets/application.scss | 1 + app/assets/stylesheets/drug_exposures.scss | 108 ++++++++++++ app/controllers/application_controller.rb | 20 ++- .../condition_occurrences_controller.rb | 20 +-- app/controllers/drug_exposures_controller.rb | 82 +++++++++ app/controllers/measurements_controller.rb | 20 +-- .../procedure_occurrences_controller.rb | 20 +-- app/helpers/application_helper.rb | 4 + app/models/concept.rb | 35 +++- app/models/drug_exposure.rb | 19 +++ app/models/interleave_datapoint.rb | 8 + .../drug_exposures/_drug_exposure.html.haml | 38 +++++ app/views/drug_exposures/create.js.erb | 0 app/views/drug_exposures/edit.html.haml | 1 + app/views/drug_exposures/index.html.haml | 42 +++++ app/views/drug_exposures/new.html.haml | 1 + app/views/drug_exposures/update.js.erb | 0 .../interleave_people/_navigation.html.haml | 4 + config/routes.rb | 1 + lib/tasks/setup.rake | 9 +- spec/factories/concepts.rb | 55 ++++++ spec/factories/durg_exposure.rb | 4 + spec/features/interleave_people_spec.rb | 2 + spec/features/interleave_person_spec.rb | 161 ++++++++++++++++-- spec/models/concept_spec.rb | 47 +++-- spec/models/drug_exposure_spec.rb | 55 ++++++ spec/models/interleave_datapoint_spec.rb | 4 +- spec/support/interleave_spec_setup.rb | 78 +++++---- 30 files changed, 773 insertions(+), 134 deletions(-) create mode 100644 app/assets/javascripts/interleave.drug_exposure.js.coffee create mode 100644 app/assets/stylesheets/drug_exposures.scss create mode 100644 app/controllers/drug_exposures_controller.rb create mode 100644 app/views/drug_exposures/_drug_exposure.html.haml create mode 100644 app/views/drug_exposures/create.js.erb create mode 100644 app/views/drug_exposures/edit.html.haml create mode 100644 app/views/drug_exposures/index.html.haml create mode 100644 app/views/drug_exposures/new.html.haml create mode 100644 app/views/drug_exposures/update.js.erb create mode 100644 spec/factories/durg_exposure.rb create mode 100644 spec/models/drug_exposure_spec.rb diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 2bdb867..bda0407 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -19,5 +19,6 @@ //= require turbolinks //= require init //= require interleave.condition_occurrence +//= require interleave.drug_exposure //= require interleave.measurement //= require interleave.procedure_occurrence \ No newline at end of file diff --git a/app/assets/javascripts/interleave.drug_exposure.js.coffee b/app/assets/javascripts/interleave.drug_exposure.js.coffee new file mode 100644 index 0000000..d74c276 --- /dev/null +++ b/app/assets/javascripts/interleave.drug_exposure.js.coffee @@ -0,0 +1,67 @@ +class Interleave.DrugExposure + constructor: () -> + render: (link) -> + $(link).on 'click', (e) -> + $modal = $('#drug_exposure_modal') + $drug_exposure = $('#drug_exposure_modal .drug_exposure') + $.ajax(this.href).done (response) -> + $drug_exposure.html(response) + $modal.foundation 'open' + $('.datepicker').datepicker + onClose: (dateText, inst) -> + $(inst.input).focusout() + return + changeMonth: true + changeYear: true + interleaveDatapointConceptsUrl = $('#concepts_interleave_datapoint_url').attr('href') + $('.drug_exposure_form').enableClientSideValidations() + $('#drug_exposure_drug_concept_id').select2 + ajax: + url: interleaveDatapointConceptsUrl + dataType: 'json' + delay: 250 + data: (params) -> + { + q: params.term + page: params.page + } + processResults: (data, params) -> + params.page = params.page or 1 + results = $.map(data.concepts, (obj) -> + obj.id = obj.concept_id + obj.text = obj.text + obj + ) + + { + results: results + pagination: more: params.page * 10 < data.total + } + cache: true + escapeMarkup: (markup) -> + markup + minimumInputLength: 2 + + $('#drug_exposure_condition_concept_id').on 'select2:select', (e) -> + $(this).blur() + return + + $('.drug_exposure_form').on('ajax:success', (e, data, status, xhr) -> + $modal.foundation 'close' + Turbolinks.visit(location.toString()) + $('.drug_exposures_list').fadeOut() + ).on 'ajax:error', (e, xhr, status, error) -> + + $('.drug_exposure_form .cancel-link').on 'click', (e) -> + $modal.foundation 'close' + e.preventDefault() + + return + e.preventDefault() + return + return + +$(document).on 'page:load ready', -> + return unless $('.drug_exposures.index').length > 0 + ui = new Interleave.DrugExposure + ui.render('.drug_exposure_link') \ No newline at end of file diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 456d3b9..5ca2224 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -19,6 +19,7 @@ @import "registries"; @import "people"; @import "condition_occurrences"; +@import "drug_exposures"; @import "measurements"; @import "procedure_occurrences"; @import "jquery.ui.override"; diff --git a/app/assets/stylesheets/drug_exposures.scss b/app/assets/stylesheets/drug_exposures.scss new file mode 100644 index 0000000..6fd3a16 --- /dev/null +++ b/app/assets/stylesheets/drug_exposures.scss @@ -0,0 +1,108 @@ +#drug_exposures { + @include grid-row(); + + .interleave_datapoint { + @include grid-column( + $columns: 20 + ); + } + + .drug_exposures_list { + @include grid-column( + $columns: 24 + ); + + th .current { + padding-right: 2em; + background-repeat: no-repeat; + background-position: right center; + } + + th .asc { + background-image: asset_url("drop25.png"); + } + + th .desc { + background-image: asset_url("drop27.png"); + } + + table { + @include grid-column( + $columns: 24 + ); + } + } +} + +#drug_exposure_modal { + position: fixed; + bottom: 0; + top: 30% !important; + right: 0; + left: 0; + width: 100%; +} + +#drug_exposure { + @include grid-row(); + + .ui-autocomplete-input { + width: 90%; + height: 2.5rem; + } + .ui-button { + width: 5%; + height: 2.5rem; + } + + .drug_exposure_start_date { + @include grid-column( + $columns: 12 + ); + input { + margin-bottom: 0; + } + } + .drug_exposure_end_date { + @include grid-column( + $columns: 12 + ); + input { + margin-bottom: 0; + } + } + .drug_concept_id { + label { + display: block; + } + @include grid-column( + $columns: 12 + ); + select { + margin-bottom: 0; + } + + .select2 { + width: 100% !important; + } + } + + .drug_type_concept_id { + label { + display: block; + } + @include grid-column( + $columns: 12 + ); + select { + margin-bottom: 0; + } + } + .navigation { + padding: 1rem; + @include grid-column-offset(12); + @include grid-column( + $columns: 12 + ); + } +} \ No newline at end of file diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5625cac..3dfd0b2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -24,6 +24,8 @@ def add_breadcrumbs(options = {}) case options[:datapoint].domain_id when 'Condition' @breadcrumbs << { name: "#{options[:datapoint].domain_id}:#{options[:datapoint].name}", url: interleave_registry_interleave_person_condition_occurrences_url(@registry, @interleave_person, datapoint_id: @datapoint.id), class: 'datapoint_link' } + when 'Drug' + @breadcrumbs << { name: "#{options[:datapoint].domain_id}:#{options[:datapoint].name}", url: interleave_registry_interleave_person_drug_exposures_url(@registry, @interleave_person, datapoint_id: @datapoint.id), class: 'datapoint_link' } when 'Measurement' @breadcrumbs << { name: "#{options[:datapoint].domain_id}:#{options[:datapoint].name}", url: interleave_registry_interleave_person_measurements_url(@registry, @interleave_person, datapoint_id: @datapoint.id), class: 'datapoint_link' } when 'Procedure' @@ -31,4 +33,20 @@ def add_breadcrumbs(options = {}) end end end -end + + def load_concepts(column) + @datapoint.concept_values(column).map { |concept| [concept.concept_name, concept.concept_id] } + end + + def load_interleave_registry + @registry = InterleaveRegistry.find(params[:interleave_registry_id]) + end + + def load_interleave_person + @interleave_person = InterleavePerson.find(params[:interleave_person_id]) + end + + def load_interleave_datapoint + @datapoint = InterleaveDatapoint.find(params[:datapoint_id]) + end +end \ No newline at end of file diff --git a/app/controllers/condition_occurrences_controller.rb b/app/controllers/condition_occurrences_controller.rb index 751d761..64fcc4e 100644 --- a/app/controllers/condition_occurrences_controller.rb +++ b/app/controllers/condition_occurrences_controller.rb @@ -20,7 +20,7 @@ def new @condition_occurrence.interleave_datapoint = @datapoint @datapoint.initialize_defaults(@condition_occurrence) @concepts = [] - @type_concepts = load_type_concepts + @type_concepts = load_concepts('condition_type_concept_id') respond_to do |format| format.html { render :layout => false } end @@ -42,7 +42,7 @@ def create def edit @condition_occurrence.interleave_datapoint = @datapoint @concepts = [[@condition_occurrence.condition_concept.concept_name, @condition_occurrence.condition_concept_id]] - @type_concepts = load_type_concepts + @type_concepts = load_concepts('condition_type_concept_id') respond_to do |format| format.html { render :layout => false } end @@ -63,26 +63,10 @@ def condition_occurrence_params params.require(:condition_occurrence).permit(:interleave_datapoint_id, :condition_concept_id, :condition_start_date, :condition_end_date, :condition_type_concept_id) end - def load_interleave_registry - @registry = InterleaveRegistry.find(params[:interleave_registry_id]) - end - - def load_interleave_person - @interleave_person = InterleavePerson.find(params[:interleave_person_id]) - end - def load_condition_occurrence @condition_occurrence = ConditionOccurrence.find(params[:id]) end - def load_interleave_datapoint - @datapoint = InterleaveDatapoint.find(params[:datapoint_id]) - end - - def load_type_concepts - @datapoint.concept_values('condition_type_concept_id').map { |condition_type| [condition_type.concept_name, condition_type.concept_id] } - end - def sort_column ['condition_start_date', 'condition_end_date', 'condition_concept.concept_name', 'condition_type_concept.concept_name'].include?(params[:sort]) ? params[:sort] : 'condition_start_date' end diff --git a/app/controllers/drug_exposures_controller.rb b/app/controllers/drug_exposures_controller.rb new file mode 100644 index 0000000..635bd0e --- /dev/null +++ b/app/controllers/drug_exposures_controller.rb @@ -0,0 +1,82 @@ +class DrugExposuresController < ApplicationController + helper_method :sort_column, :sort_direction + before_filter :load_interleave_registry, only: [:index, :new, :create, :edit] + before_filter :load_interleave_person, only: [:index, :new, :create, :edit] + before_filter :load_drug_exposure, only: [:edit, :update] + before_filter :load_interleave_datapoint, only: [:new, :edit] + + def index + params[:page]||= 1 + options = {} + options[:sort_column] = sort_column + options[:sort_direction] = sort_direction + @datapoint = @registry.interleave_datapoints.find(params[:datapoint_id]) + add_breadcrumbs(registry: @registry, interleave_person: @interleave_person, datapoint: @datapoint) + @drug_exposures = DrugExposure.by_person(@interleave_person.person.person_id).by_interleave_data_point(@datapoint.id, options).paginate(per_page: 10, page: params[:page]) + end + + def new + @drug_exposure = DrugExposure.new() + @drug_exposure.interleave_datapoint = @datapoint + @datapoint.initialize_defaults(@drug_exposure) + @concepts = [] + @type_concepts = load_concepts('drug_type_concept_id') + @route_concepts = load_concepts('route_concept_id') + # @dose_unit_concepts = [] + respond_to do |format| + format.html { render :layout => false } + end + end + + def create + @drug_exposure = DrugExposure.new(drug_exposure_params) + interleave_registry_cdm_source = @registry.interleave_registry_cdm_sources.where(cdm_source_name: InterleaveRegistryCdmSource::CDM_SOURCE_EX_NIHILO).first + @drug_exposure.person = @interleave_person.person + respond_to do |format| + if @drug_exposure.create_with_sub_datapoints!(interleave_registry_cdm_source) + format.js { } + else + format.js { render json: { errors: @drug_exposure.errors.full_messages }, status: :unprocessable_entity } + end + end + end + + def edit + @drug_exposure.interleave_datapoint = @datapoint + @concepts = [[@drug_exposure.drug_concept.concept_name, @drug_exposure.drug_concept_id]] + @type_concepts = load_concepts('drug_type_concept_id') + @route_concepts = load_concepts('route_concept_id') + # @dose_unit_concepts = [[@drug_exposure.dose_unit_concept.concept_name, @drug_exposure.dose_unit_concept_id]] + + respond_to do |format| + format.html { render :layout => false } + end + end + + def update + respond_to do |format| + if @drug_exposure.update_attributes(drug_exposure_params) + format.js { } + else + format.js { render json: { errors: @drug_exposure.errors.full_messages }, status: :unprocessable_entity } + end + end + end + + private + def drug_exposure_params + params.require(:drug_exposure).permit(:interleave_datapoint_id, :drug_concept_id, :drug_exposure_start_date, :drug_exposure_end_date, :drug_type_concept_id, :route_concept_id, :dose_unit_concept_id) + end + + def load_drug_exposure + @drug_exposure = DrugExposure.find(params[:id]) + end + + def sort_column + ['drug_exposure_start_date', 'drug_exposure_end_date', 'drug_concept.concept_name', 'drug_type_concept.concept_name'].include?(params[:sort]) ? params[:sort] : 'drug_exposure_start_date' + end + + def sort_direction + %w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc' + end +end \ No newline at end of file diff --git a/app/controllers/measurements_controller.rb b/app/controllers/measurements_controller.rb index f98342a..8f859aa 100644 --- a/app/controllers/measurements_controller.rb +++ b/app/controllers/measurements_controller.rb @@ -20,7 +20,7 @@ def new @measurement.interleave_datapoint = @datapoint @datapoint.initialize_defaults(@measurement) @concepts = [] - @type_concepts = load_type_concepts + @type_concepts = load_concepts('measurement_type_concept_id') respond_to do |format| format.html { render :layout => false } end @@ -42,7 +42,7 @@ def create def edit @measurement.interleave_datapoint = @datapoint @concepts = [[@measurement.measurement_concept.concept_name, @measurement.measurement_concept_id]] - @type_concepts = load_type_concepts + @type_concepts = load_concepts('measurement_type_concept_id') respond_to do |format| format.html { render :layout => false } end @@ -63,26 +63,10 @@ def measurement_params params.require(:measurement).permit(:interleave_datapoint_id, :measurement_concept_id, :measurement_date, :measurement_type_concept_id, :value_as_number, :value_as_concept_id) end - def load_interleave_registry - @registry = InterleaveRegistry.find(params[:interleave_registry_id]) - end - - def load_interleave_person - @interleave_person = InterleavePerson.find(params[:interleave_person_id]) - end - def load_measurement @measurement = Measurement.find(params[:id]) end - def load_interleave_datapoint - @datapoint = InterleaveDatapoint.find(params[:datapoint_id]) - end - - def load_type_concepts - @datapoint.concept_values('measurement_type_concept_id').map { |measuremet_type| [measuremet_type.concept_name, measuremet_type.concept_id] } - end - def sort_column ['measurement_date', 'measurement_concept.concept_name', 'measurement_type_concept.concept_name', 'value_as_number'].include?(params[:sort]) ? params[:sort] : 'measurement_date' end diff --git a/app/controllers/procedure_occurrences_controller.rb b/app/controllers/procedure_occurrences_controller.rb index c32c810..3fb3558 100644 --- a/app/controllers/procedure_occurrences_controller.rb +++ b/app/controllers/procedure_occurrences_controller.rb @@ -20,7 +20,7 @@ def new @procedure_occurrence.interleave_datapoint = @datapoint @datapoint.initialize_defaults(@procedure_occurrence) @concepts = [] - @type_concepts = load_type_concepts + @type_concepts = load_concepts('procedure_type_concept_id') @sub_datapoints = @datapoint.initialize_sub_datapoint_entities respond_to do |format| format.html { render :layout => false } @@ -44,7 +44,7 @@ def create def edit @procedure_occurrence.interleave_datapoint = @datapoint @concepts = [[@procedure_occurrence.procedure_concept.concept_name, @procedure_occurrence.procedure_concept_id]] - @type_concepts = load_type_concepts + @type_concepts = load_concepts('procedure_type_concept_id') @sub_datapoints = @datapoint.initialize_sub_datapoint_entities(@procedure_occurrence.interleave_entity) respond_to do |format| format.html { render :layout => false } @@ -66,26 +66,10 @@ def procedure_occurence_params params.require(:procedure_occurrence).permit(:interleave_datapoint_id, :procedure_concept_id, :procedure_date, :procedure_type_concept_id, :modifier_concept_id, :quantity) end - def load_interleave_registry - @registry = InterleaveRegistry.find(params[:interleave_registry_id]) - end - - def load_interleave_person - @interleave_person = InterleavePerson.find(params[:interleave_person_id]) - end - def load_procedure_occurrence @procedure_occurrence = ProcedureOccurrence.find(params[:id]) end - def load_interleave_datapoint - @datapoint = InterleaveDatapoint.find(params[:datapoint_id]) - end - - def load_type_concepts - @datapoint.concept_values('procedure_type_concept_id').map { |condition_type| [condition_type.concept_name, condition_type.concept_id] } - end - def sort_column ['procedure_date', 'quantity', 'procedure_concept.concept_name', 'procedure_type_concept.concept_name'].include?(params[:sort]) ? params[:sort] : 'procedure_date' end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8aaa9ba..d21b895 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -39,6 +39,10 @@ def generate_datapoint_url(registry, interleave_person, datapoint, domain_id) haml_tag(:li, class: active?('active', 'condition_occurrences', 'index', 'datapoint_id' => datapoint.id.to_s)) do concat link_to datapoint.name, interleave_registry_interleave_person_condition_occurrences_url(registry, interleave_person, datapoint_id: datapoint.id), class: 'datapoint' end + when 'Drug' + haml_tag(:li, class: active?('active', 'drug_exposures', 'index', 'datapoint_id' => datapoint.id.to_s)) do + concat link_to datapoint.name, interleave_registry_interleave_person_drug_exposures_url(registry, interleave_person, datapoint_id: datapoint.id), class: 'datapoint' + end when 'Measurement' haml_tag(:li, class: active?('active', 'measurements', 'index', 'datapoint_id' => datapoint.id.to_s)) do concat link_to datapoint.name, interleave_registry_interleave_person_measurements_url(registry, interleave_person, datapoint_id: datapoint.id), class: 'datapoint' diff --git a/app/models/concept.rb b/app/models/concept.rb index 2edc306..b0d2551 100644 --- a/app/models/concept.rb +++ b/app/models/concept.rb @@ -5,6 +5,7 @@ class Concept < ActiveRecord::Base VOCABULARY_ID_CONDITION_TYPE = 'Condition Type' VOCABULARY_ID_CPT4 = 'CPT4' VOCABULARY_ID_DOMAIN = 'Domain' + VOCABULARY_ID_DRUG_TYPE = 'Drug Type' VOCABULARY_ID_ETHNICITY = 'Ethnicity' VOCABULARY_ID_GENDER = 'Gender' VOCABULARY_ID_LOINC = 'LOINC' @@ -12,10 +13,13 @@ class Concept < ActiveRecord::Base VOCABULARY_ID_PROCEDURE_TYPE = 'Procedure Type' VOCABULARY_ID_RACE = 'Race' VOCABULARY_ID_RELATIONSHIP = 'Relationship' + VOCABULARY_ID_RXNORM = 'RxNorm' VOCABULARY_ID_SNOMED = 'SNOMED' - VOCABULARY_IDS = [VOCABULARY_ID_CONDITION_TYPE, VOCABULARY_ID_DOMAIN, VOCABULARY_ID_ETHNICITY, VOCABULARY_ID_GENDER, VOCABULARY_ID_RACE, VOCABULARY_ID_SNOMED] + VOCABULARY_ID_UCUM = 'UCUM' + VOCABULARY_IDS = [VOCABULARY_ID_CONDITION_TYPE, VOCABULARY_ID_CPT4, VOCABULARY_ID_DOMAIN, VOCABULARY_ID_DRUG_TYPE, VOCABULARY_ID_ETHNICITY, VOCABULARY_ID_GENDER, VOCABULARY_ID_LOINC, VOCABULARY_ID_MEAS_TYPE, VOCABULARY_ID_PROCEDURE_TYPE, VOCABULARY_ID_RACE, VOCABULARY_ID_RELATIONSHIP, VOCABULARY_ID_RXNORM, VOCABULARY_ID_SNOMED, VOCABULARY_ID_UCUM] DOMAIN_ID_CONDITION = 'Condition' + DOMAIN_ID_DRUG = 'Drug' DOMAIN_ID_GENDER = 'Gender' DOMAIN_ID_ETHNICITY = 'Ethnicity' DOMAIN_ID_MEASUREMENT = 'Measurement' @@ -24,22 +28,29 @@ class Concept < ActiveRecord::Base DOMAIN_ID_PROCEDURE = 'Procedure' DOMAIN_ID_RACE = 'Race' DOMAIN_ID_RELATIONSHIP = 'Relationship' + DOMAIN_ID_ROUTE = 'Route' DOMAIN_ID_TYPE_CONCEPT = 'Type Concept' - DOMAIN_IDS = [DOMAIN_ID_CONDITION, DOMAIN_ID_GENDER, DOMAIN_ID_ETHNICITY, DOMAIN_ID_METADATA, DOMAIN_ID_PROCEDURE, DOMAIN_ID_RACE, DOMAIN_ID_TYPE_CONCEPT] + DOMAIN_ID_UNIT = 'Unit' + DOMAIN_IDS = [DOMAIN_ID_CONDITION, DOMAIN_ID_GENDER, DOMAIN_ID_ETHNICITY, DOMAIN_ID_MEASUREMENT, DOMAIN_ID_METADATA, DOMAIN_ID_PROCEDURE, DOMAIN_ID_RACE, DOMAIN_ID_RELATIONSHIP, DOMAIN_ID_ROUTE, DOMAIN_ID_TYPE_CONCEPT, DOMAIN_ID_UNIT] CONCEPT_CLASS_ANSWER = 'Answer' CONCEPT_CLASS_CLINICAL_FINDING = 'Clinical Finding' CONCEPT_CLASS_CONDITION_TYPE = 'Condition Type' + CONCEPT_CLASS_DRUG_TYPE = 'Drug Type' + CONCEPT_CLASS_CLINICAL_DRUG = 'Clinical Drug' CONCEPT_CLASS_CPT4 = 'CPT4' CONCEPT_CLASS_DOMAIN = 'Domain' CONCEPT_CLASS_GENDER = 'Gender' CONCEPT_CLASS_ETHNICITY = 'Ethnicity' + CONCEPT_CLASS_INGREDIENT = 'Ingredient' CONCEPT_CLASS_LAB_TEST = 'Lab Test' CONCEPT_CLASS_MEAS_TYPE = 'Meas Type' CONCEPT_CLASS_PROCEDURE_TYPE = 'Procedure Type' + CONCEPT_CLASS_QUALIFIER_VALUE = 'Qualifier Value' CONCEPT_CLASS_RACE = 'Race' CONCEPT_CLASS_RELATIONSHIP = 'Relationship' - CONCEPT_CLASSES = [CONCEPT_CLASS_CONDITION_TYPE, CONCEPT_CLASS_DOMAIN, CONCEPT_CLASS_GENDER, CONCEPT_CLASS_ETHNICITY, CONCEPT_CLASS_RACE] + CONCEPT_CLASS_UNIT = 'Unit' + CONCEPT_CLASSES = [CONCEPT_CLASS_ANSWER, CONCEPT_CLASS_CLINICAL_FINDING, CONCEPT_CLASS_CONDITION_TYPE, CONCEPT_CLASS_DRUG_TYPE, CONCEPT_CLASS_CPT4, CONCEPT_CLASS_DOMAIN, CONCEPT_CLASS_GENDER, CONCEPT_CLASS_ETHNICITY, CONCEPT_CLASS_LAB_TEST, CONCEPT_CLASS_MEAS_TYPE, CONCEPT_CLASS_PROCEDURE_TYPE, CONCEPT_CLASS_QUALIFIER_VALUE, CONCEPT_CLASS_RACE, CONCEPT_CLASS_RELATIONSHIP, CONCEPT_CLASS_UNIT] def self.standard where(standard_concept: 'S') @@ -53,6 +64,14 @@ def self.condition_types valid.where(domain_id: Concept::DOMAIN_ID_TYPE_CONCEPT, vocabulary_id: Concept::VOCABULARY_ID_CONDITION_TYPE , concept_class_id: Concept::CONCEPT_CLASS_CONDITION_TYPE) end + def self.domain_concepts + valid.where(domain_id: Concept::DOMAIN_ID_METADATA, vocabulary_id: Concept::VOCABULARY_ID_DOMAIN, concept_class_id: Concept::CONCEPT_CLASS_DOMAIN) + end + + def self.drug_types + valid.where(domain_id: Concept::DOMAIN_ID_TYPE_CONCEPT, vocabulary_id: Concept::VOCABULARY_ID_DRUG_TYPE , concept_class_id: Concept::CONCEPT_CLASS_DRUG_TYPE) + end + def self.measurement_types valid.where(domain_id: Concept::DOMAIN_ID_TYPE_CONCEPT, vocabulary_id: Concept::VOCABULARY_ID_MEAS_TYPE , concept_class_id: Concept::CONCEPT_CLASS_MEAS_TYPE) end @@ -61,7 +80,11 @@ def self.procedure_types valid.where(domain_id: Concept::DOMAIN_ID_TYPE_CONCEPT, vocabulary_id: Concept::VOCABULARY_ID_PROCEDURE_TYPE , concept_class_id: Concept::CONCEPT_CLASS_PROCEDURE_TYPE) end - def self.domain_concepts - valid.where(domain_id: Concept::DOMAIN_ID_METADATA, vocabulary_id: Concept::VOCABULARY_ID_DOMAIN, concept_class_id: Concept::CONCEPT_CLASS_DOMAIN) + def self.routes + valid.where(domain_id: Concept::DOMAIN_ID_ROUTE, vocabulary_id: Concept::VOCABULARY_ID_SNOMED , concept_class_id: Concept::CONCEPT_CLASS_QUALIFIER_VALUE) + end + + def self.units + valid.where(domain_id: Concept::DOMAIN_ID_UNIT, vocabulary_id: Concept::VOCABULARY_ID_UCUM , concept_class_id: Concept::CONCEPT_CLASS_UNIT) end -end +end \ No newline at end of file diff --git a/app/models/drug_exposure.rb b/app/models/drug_exposure.rb index 89a0729..a2f3a32 100644 --- a/app/models/drug_exposure.rb +++ b/app/models/drug_exposure.rb @@ -1,4 +1,23 @@ class DrugExposure < ActiveRecord::Base + include Interleaveable self.table_name = 'drug_exposure' self.primary_key = 'drug_exposure_id' + belongs_to :drug_concept, class_name: 'Concept', foreign_key: 'drug_concept_id' + belongs_to :drug_type_concept, class_name: 'Concept', foreign_key: 'drug_type_concept_id' + belongs_to :person, class_name: 'Person', foreign_key: 'person_id' + belongs_to :route_concept, class_name: 'Concept', foreign_key: 'route_concept_id' + belongs_to :dose_unit_concept, class_name: 'Concept', foreign_key: 'dose_unit_concept_id' + + DOMAIN_ID = 'Drug' + + validates_presence_of :drug_concept_id, :drug_exposure_start_date, :drug_type_concept_id + + def self.by_interleave_data_point(interleave_data_point_id, options = {}) + options = { sort_column: 'drug_exposure_start_date', sort_direction: 'asc' }.merge(options) + s = joins("JOIN concept AS drug_type_concept ON drug_exposure.drug_type_concept_id = drug_type_concept.concept_id JOIN concept AS drug_concept ON drug_exposure.drug_concept_id = drug_concept.concept_id JOIN interleave_entities ON drug_exposure.drug_exposure_id = interleave_entities.fact_id AND interleave_entities.cdm_table = 'drug_exposure'").where('interleave_entities.interleave_datapoint_id = ?', interleave_data_point_id) + sort = options[:sort_column] + ' ' + options[:sort_direction] + s = s.order(sort) + + s + end end diff --git a/app/models/interleave_datapoint.rb b/app/models/interleave_datapoint.rb index 9d1d82a..73d3a42 100644 --- a/app/models/interleave_datapoint.rb +++ b/app/models/interleave_datapoint.rb @@ -27,12 +27,20 @@ def concept_values(column, search_token = nil) results = case column when 'condition_concept_id', 'procedure_concept_id', 'measurement_concept_id' Concept.standard.valid.where(domain_id: domain_id) + when 'drug_concept_id' + Concept.standard.valid.where(domain_id: domain_id, vocabulary_id: Concept::VOCABULARY_ID_RXNORM) when 'condition_type_concept_id' Concept.standard.valid.condition_types + when 'dose_unit_concept_id' + Concept.standard.valid.units + when 'drug_type_concept_id' + Concept.standard.valid.drug_types when 'measurement_type_concept_id' Concept.standard.valid.measurement_types when 'procedure_type_concept_id' Concept.standard.valid.procedure_types + when 'route_concept_id' + Concept.standard.valid.routes else raise ArgumentError.new('Unknown column.') end diff --git a/app/views/drug_exposures/_drug_exposure.html.haml b/app/views/drug_exposures/_drug_exposure.html.haml new file mode 100644 index 0000000..66fc9f4 --- /dev/null +++ b/app/views/drug_exposures/_drug_exposure.html.haml @@ -0,0 +1,38 @@ +%h3 + Drug: + = @datapoint.name +#drug_exposure + = form_for [@registry, @interleave_person, @drug_exposure], html: { class: 'drug_exposure_form' }, remote: true, validate: true do |f| + = link_to '', concepts_interleave_datapoint_url(@datapoint.id, column: 'drug_concept_id'), class: 'hide', id: 'concepts_interleave_datapoint_url' + = f.hidden_field :interleave_datapoint_id, value: @datapoint.id + .row + .drug_exposure_start_date + %label{for: 'drug_exposure_start_date' } + Start + %span{ class: 'required' } + * + = f.text_field :drug_exposure_start_date, class: 'datepicker' + .drug_exposure_end_date + %label{for: 'drug_exposure_end_date' } + End + = f.text_field :drug_exposure_end_date, class: 'datepicker' + .row + .drug_concept_id + %label{for: 'drug_concept_id' } + Concept + %span{ class: 'required' } + * + = f.select :drug_concept_id, options_for_select(@concepts, selected: f.object.drug_concept_id), { include_blank: true } + .drug_type_concept_id + %label{for: 'drug_type_concept_id' } + Type + %span{ class: 'required' } + * + = f.select :drug_type_concept_id, options_for_select(@type_concepts, selected: f.object.drug_type_concept_id), { include_blank: true } + .navigation + %p.help-text + %span{ class: 'required' } + * + Indicates required field + = f.submit 'Save', class: 'button' + = link_to 'Cancel', '#', class: 'cancel-link button warning' \ No newline at end of file diff --git a/app/views/drug_exposures/create.js.erb b/app/views/drug_exposures/create.js.erb new file mode 100644 index 0000000..e69de29 diff --git a/app/views/drug_exposures/edit.html.haml b/app/views/drug_exposures/edit.html.haml new file mode 100644 index 0000000..924df6d --- /dev/null +++ b/app/views/drug_exposures/edit.html.haml @@ -0,0 +1 @@ += render 'drug_exposure' \ No newline at end of file diff --git a/app/views/drug_exposures/index.html.haml b/app/views/drug_exposures/index.html.haml new file mode 100644 index 0000000..af95cf4 --- /dev/null +++ b/app/views/drug_exposures/index.html.haml @@ -0,0 +1,42 @@ +- content_for(:title) do + Drugs +#drug_exposures + = render 'interleave_people/header' + = render 'interleave_people/navigation' + .interleave_datapoint + %h3 + = @datapoint.name + .drug_exposures_list + = will_paginate @drug_exposures, renderer: FoundationPagination::Rails + %table + %thead + %tr + %th.drug_concept_concept_name{ width: 200 } + = sortable 'drug_concept.concept_name', 'Drug' + %th.drug_exposure_start_date{ width: 200 } + = sortable 'drug_exposure_start_date', 'Start' + %th.drug_exposure_end_date{ width: 200 } + = sortable 'drug_exposure_end_date', 'End' + %th.drug_type_concept_concept_name{ width: 200 } + = sortable 'drug_type_concept.concept_name', 'Drug Type' + %th.review{ width: 100 } + %tbody + - @drug_exposures.each do |drug_exposure| + = content_tag_for(:tr, drug_exposure) do + %td.drug_exposure_concept_name + = drug_exposure.drug_concept.concept_name + %td.drug_exposure_start_date + = drug_exposure.drug_exposure_start_date.to_s(:date) + %td.drug_exposure_end_date + = drug_exposure.drug_exposure_end_date.to_s(:date) unless drug_exposure.drug_exposure_end_date.nil? + %td.drug_exposurer_drug_type_concept_name + = drug_exposure.drug_type_concept.concept_name + %td.review + = link_to 'Edit', edit_interleave_registry_interleave_person_drug_exposure_url(@registry, @interleave_person, drug_exposure, datapoint_id: @datapoint.id), 'data-no-turbolink' => '', class: 'edit_drug_exposure_link drug_exposure_link' + .new_drug_exposure_link + = link_to 'Add', new_interleave_registry_interleave_person_drug_exposure_url(@registry, @interleave_person, datapoint_id: @datapoint.id), 'data-no-turbolink' => '', id: 'new_drug_exposure_link', class: 'drug_exposure_link' + = will_paginate @drug_exposures, renderer: FoundationPagination::Rails + #drug_exposure_modal.reveal.large{ "data-reveal" => "" } + .drug_exposure + %button.close-button{"aria-label" => "Close modal", "data-close" => "", :type => "button"} + %span{"aria-hidden" => "true"} × \ No newline at end of file diff --git a/app/views/drug_exposures/new.html.haml b/app/views/drug_exposures/new.html.haml new file mode 100644 index 0000000..924df6d --- /dev/null +++ b/app/views/drug_exposures/new.html.haml @@ -0,0 +1 @@ += render 'drug_exposure' \ No newline at end of file diff --git a/app/views/drug_exposures/update.js.erb b/app/views/drug_exposures/update.js.erb new file mode 100644 index 0000000..e69de29 diff --git a/app/views/interleave_people/_navigation.html.haml b/app/views/interleave_people/_navigation.html.haml index 763265c..6088822 100644 --- a/app/views/interleave_people/_navigation.html.haml +++ b/app/views/interleave_people/_navigation.html.haml @@ -5,6 +5,10 @@ = link_to 'Conditions', '#' %ul.conditions.menu.vertical.nested{ class: "is-active #{active?('is-active','condition_occurrences', 'index')}"} = links_to_datapoints(@registry, @interleave_person, 'Condition') + %li.menu-text + = link_to 'Drugs', '#' + %ul.drugs.menu.vertical.nested{ class: "is-active #{active?('is-active','drug_exposures', 'index')}"} + = links_to_datapoints(@registry, @interleave_person, 'Drug') %li.menu-text = link_to 'Measurements', '#' %ul.measurements.menu.vertical.nested{ class: "is-active #{active?('is-active','measurements', 'index')}"} diff --git a/config/routes.rb b/config/routes.rb index 9e7497c..d3b90cc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,6 +6,7 @@ end resources :condition_occurrences, path: 'conditions' + resources :drug_exposures, path: 'drugs' resources :measurements resources :procedure_occurrences, path: 'procedures' end diff --git a/lib/tasks/setup.rake b/lib/tasks/setup.rake index 693875b..e068f50 100644 --- a/lib/tasks/setup.rake +++ b/lib/tasks/setup.rake @@ -52,15 +52,18 @@ namespace :setup do concept_from_physical_examination = Concept.standard.where(vocabulary_id: Concept::VOCABULARY_ID_MEAS_TYPE, concept_name: 'From physical examination').first #From physical examination concept_lab_result = Concept.standard.where(vocabulary_id: Concept::VOCABULARY_ID_MEAS_TYPE, concept_name: 'Lab result').first #Lab result + #datapoint drug exposure + interleave_datapoint_drug_exposure = InterleaveDatapoint.where(interleave_registry_id: interleave_registry.id, name: 'Drug Exposure', domain_id: DrugExposure::DOMAIN_ID, cardinality: 0, overlap: true).first_or_create + #datapoint diagnosis - interleave_datapoint_diagnosis = InterleaveDatapoint.where(interleave_registry_id: interleave_registry.id, name: 'Diagnosis', domain_id: ConditionOccurrencez::DOMAIN_ID, cardinality: 1, overlap: true, value_type: InterleaveDatapoint::VALUE_TYPE_VALUE_AS_NOT_APPICABLE).first_or_create + interleave_datapoint_diagnosis = InterleaveDatapoint.where(interleave_registry_id: interleave_registry.id, name: 'Diagnosis', domain_id: ConditionOccurrence::DOMAIN_ID, cardinality: 1, overlap: true, value_type: InterleaveDatapoint::VALUE_TYPE_VALUE_AS_NOT_APPICABLE).first_or_create concept = Concept.standard.where(domain_id: Concept::DOMAIN_ID_CONDITION, concept_code: '126906006').first #Neoplasm of prostate InterleaveDatapointValue.where(interleave_datapoint_id: interleave_datapoint_diagnosis.id, concept: concept, column: 'condition_concept_id').first_or_create concept = Concept.standard.where(domain_id: Concept::DOMAIN_ID_CONDITION, concept_code: '266569009').first #"Benign prostatic hyperplasia" InterleaveDatapointValue.where(interleave_datapoint_id: interleave_datapoint_diagnosis.id, concept: concept, column: 'condition_concept_id').first_or_create - #datapoint comorbidities - interleave_datapoint_comorbidities = InterleaveDatapoint.where(interleave_registry_id: interleave_registry.id, name: 'Comorbidities', domain_id: 'Condition', cardinality: 0, overlap: false, value_type: InterleaveDatapoint::VALUE_TYPE_VALUE_AS_NOT_APPICABLE).first_or_create + #datapoint comorbidity + interleave_datapoint_comorbidities = InterleaveDatapoint.where(interleave_registry_id: interleave_registry.id, name: 'Comorbidity', domain_id: 'Condition', cardinality: 0, overlap: false, value_type: InterleaveDatapoint::VALUE_TYPE_VALUE_AS_NOT_APPICABLE).first_or_create #datapoint trus interleave_datapoint_trus = InterleaveDatapoint.where(interleave_registry_id: interleave_registry.id, name: 'TRUS', domain_id: 'Procedure', cardinality: 0, overlap: true, value_type: InterleaveDatapoint::VALUE_TYPE_VALUE_AS_NOT_APPICABLE).first_or_create diff --git a/spec/factories/concepts.rb b/spec/factories/concepts.rb index 02a0edd..586fdd2 100644 --- a/spec/factories/concepts.rb +++ b/spec/factories/concepts.rb @@ -1,4 +1,59 @@ FactoryGirl.define do + factory :concept_drug_clinical_drug, class: Concept do + domain_id Concept::DOMAIN_ID_DRUG + vocabulary_id Concept::VOCABULARY_ID_RXNORM + concept_class_id Concept::CONCEPT_CLASS_CLINICAL_DRUG + standard_concept 'S' + concept_code nil + valid_start_date Date.parse('1970-01-01') + valid_end_date Date.parse('2099-12-31') + invalid_reason nil + end + + factory :concept_drug_ingredient, class: Concept do + domain_id Concept::DOMAIN_ID_DRUG + vocabulary_id Concept::VOCABULARY_ID_RXNORM + concept_class_id Concept::CONCEPT_CLASS_INGREDIENT + standard_concept 'S' + concept_code nil + valid_start_date Date.parse('1970-01-01') + valid_end_date Date.parse('2099-12-31') + invalid_reason nil + end + + factory :concept_unit, class: Concept do + domain_id Concept::DOMAIN_ID_UNIT + vocabulary_id Concept::VOCABULARY_ID_UCUM + concept_class_id Concept::CONCEPT_CLASS_UNIT + standard_concept 'S' + concept_code 'OMOP generated' + valid_start_date Date.parse('1970-01-01') + valid_end_date Date.parse('2099-12-31') + invalid_reason nil + end + + factory :concept_route, class: Concept do + domain_id Concept::DOMAIN_ID_ROUTE + vocabulary_id Concept::VOCABULARY_ID_SNOMED + concept_class_id Concept::CONCEPT_CLASS_QUALIFIER_VALUE + standard_concept 'S' + concept_code 'OMOP generated' + valid_start_date Date.parse('1970-01-01') + valid_end_date Date.parse('2099-12-31') + invalid_reason nil + end + + factory :concept_drug_type, class: Concept do + domain_id Concept::DOMAIN_ID_TYPE_CONCEPT + vocabulary_id Concept::VOCABULARY_ID_DRUG_TYPE + concept_class_id Concept::CONCEPT_CLASS_DRUG_TYPE + standard_concept 'S' + concept_code 'OMOP generated' + valid_start_date Date.parse('1970-01-01') + valid_end_date Date.parse('2099-12-31') + invalid_reason nil + end + factory :concept_measurement_type, class: Concept do domain_id Concept::DOMAIN_ID_TYPE_CONCEPT vocabulary_id Concept::VOCABULARY_ID_MEAS_TYPE diff --git a/spec/factories/durg_exposure.rb b/spec/factories/durg_exposure.rb new file mode 100644 index 0000000..3cbed5a --- /dev/null +++ b/spec/factories/durg_exposure.rb @@ -0,0 +1,4 @@ +FactoryGirl.define do + factory :drug_exposure do + end +end diff --git a/spec/features/interleave_people_spec.rb b/spec/features/interleave_people_spec.rb index 5fd69e7..3cfd795 100644 --- a/spec/features/interleave_people_spec.rb +++ b/spec/features/interleave_people_spec.rb @@ -35,6 +35,8 @@ click_link('Registries') end + sleep(1) + within('.interleave_registry:nth-of-type(1) .registry_name') do expect(page).to have_content('Breast SPORE') end diff --git a/spec/features/interleave_person_spec.rb b/spec/features/interleave_person_spec.rb index c28fd81..c8fe3d6 100644 --- a/spec/features/interleave_person_spec.rb +++ b/spec/features/interleave_person_spec.rb @@ -13,7 +13,7 @@ @interleave_registry_cdm_source = FactoryGirl.create(:interleave_registry_cdm_source, cdm_source_name: InterleaveRegistryCdmSource::CDM_SOURCE_EX_NIHILO, interleave_registry: @interleave_registry_prostate) @interleave_datapoint_diagnosis = FactoryGirl.create(:interleave_datapoint, interleave_registry: @interleave_registry_prostate, name: 'Diagnosis', domain_id: ConditionOccurrence::DOMAIN_ID, cardinality: 1, overlap: true) - @interleave_datapoint_comorbidities = FactoryGirl.create(:interleave_datapoint, interleave_registry: @interleave_registry_prostate, name: 'Comorbidities', domain_id: ConditionOccurrence::DOMAIN_ID, cardinality: 0, overlap: false) + @interleave_datapoint_comorbidities = FactoryGirl.create(:interleave_datapoint, interleave_registry: @interleave_registry_prostate, name: 'Comorbidity', domain_id: ConditionOccurrence::DOMAIN_ID, cardinality: 0, overlap: false) FactoryGirl.create(:interleave_datapoint_value, interleave_datapoint: @interleave_datapoint_diagnosis, concept: @concept_condition_neoplasam_of_prostate, column: 'condition_concept_id') FactoryGirl.create(:interleave_datapoint_value, interleave_datapoint: @interleave_datapoint_diagnosis, concept: @concept_condition_benign_prostatic_hyperplasia, column: 'condition_concept_id') @@ -53,6 +53,8 @@ end FactoryGirl.create(:interleave_datapoint_default_value, interleave_datapoint: @interleave_datapoint_psa_lab, column: 'measurement_type_concept_id', concept: @concept_lab_result, hardcoded: false) + @interleave_datapoint_drug_exposure = FactoryGirl.create(:interleave_datapoint, interleave_registry: @interleave_registry_prostate, name: 'Drug Exposure', domain_id: DrugExposure::DOMAIN_ID, cardinality: 0, overlap: true) + visit interleave_registries_path within("#interleave_registry_#{@interleave_registry_prostate.id}") do @@ -91,10 +93,6 @@ match_person(@interleave_person_moomin) - within('.person_navigation') do - click_link('Conditions') - end - within('.person_navigation') do click_link('Diagnosis') end @@ -104,18 +102,22 @@ end within('.person_navigation') do - click_link('Procedures') + click_link('Biopsy') + end + + within('.breadcrumbs') do + click_link('Procedure:Biopsy') end within('.person_navigation') do - click_link('Biopsy') + click_link('Drug Exposure') end within('.breadcrumbs') do - click_link('Procedure:Biopsy') + click_link('Drug:Drug Exposure') end - sleep(2) + sleep(1) end scenario 'Displaying multiple datapoints', js: true, focus: false do @@ -126,10 +128,10 @@ expect(page).to have_content('Diagnosis') end - click_link('Comorbidities') + click_link('Comorbidity') within("#condition_occurrences h3") do - expect(page).to have_content('Comorbidities') + expect(page).to have_content('Comorbidity') end end @@ -148,7 +150,6 @@ end scenario 'Adding a condition occurrence with validation', js: true, focus: false do - click_link('Conditions') click_link('Diagnosis') click_link('Add') click_button('Save') @@ -158,7 +159,6 @@ end scenario 'Adding a procedure occurrence with validation', js: true, focus: false do - click_link('Procedures') click_link('Biopsy') click_link('Add') click_button('Save') @@ -168,7 +168,6 @@ end scenario 'Adding a condition occurrence', js: true, focus: false do - click_link('Conditions') click_link('Diagnosis') click_link('Add') page.find('.select2-selection ').native.send_keys(:return) @@ -180,7 +179,7 @@ page.execute_script("$('#condition_occurrence_condition_end_date').val('#{end_date}')") start_date = '01/01/2016' page.execute_script("$('#condition_occurrence_condition_start_date').val('#{start_date}')") - sleep(10) + sleep(1) click_button('Save') match_condition(1, concept_name, Date.parse(start_date), Date.parse(end_date), @concept_condition_type_ehr_problem_list_entry.concept_name) end @@ -249,6 +248,21 @@ match_measurement(1, @psa_concept_1.concept_name, Date.parse(measurement_date), @concept_lab_result.concept_name, value_as_number, nil) end + scenario 'Adding a drug exposure', js: true, focus: false do + click_link('Drug Exposure') + click_link('Add') + page.find('.select2-selection ').native.send_keys(:return) + find('.select2-dropdown input').set(@concept_drug_carbidopa.concept_name) + find('.select2-results__option--highlighted').click + select(@concept_drug_prescription_written.concept_name, from: 'Type') + start_date = '01/01/2016' + page.execute_script("$('#drug_exposure_drug_exposure_start_date').val('#{start_date}')") + end_date = '02/01/2016' + page.execute_script("$('#drug_exposure_drug_exposure_end_date').val('#{end_date}')") + click_button('Save') + match_drug_exposure(1, @concept_drug_carbidopa.concept_name, Date.parse(start_date), Date.parse(end_date), @concept_drug_prescription_written.concept_name) + end + scenario 'Editing a condition occurrence', js: true, focus: false do start_date = Date.parse('1/1/2015') end_date = Date.parse('2/1/2015') @@ -375,6 +389,31 @@ match_measurement(1, @psa_concept_2.concept_name, Date.parse(measurement_date), @concept_pathology_finding.concept_name, value_as_number, nil) end + scenario 'Editing a drug exposure', js: true, focus: false do + start_date = '1/1/2015' + end_date = '2/1/2015' + durg_exposure = FactoryGirl.build(:drug_exposure, person: @person_moomin, drug_concept: @concept_drug_carbidopa, drug_type_concept: @concept_drug_prescription_written, drug_exposure_start_date: Date.parse(start_date), drug_exposure_end_date: Date.parse(end_date), interleave_datapoint_id: @interleave_datapoint_drug_exposure.id) + durg_exposure.create_with_sub_datapoints!(@interleave_registry_cdm_source) + click_link('Drug Exposure') + match_drug_exposure(1, @concept_drug_carbidopa.concept_name, Date.parse(start_date), Date.parse(end_date), @concept_drug_prescription_written.concept_name) + + within("#drug_exposure_#{durg_exposure.id}") do + click_link('Edit') + end + + page.find('.select2-selection ').native.send_keys(:return) + find('.select2-dropdown input').set(@concept_drug_carbidopa_25mg_oral_tablet.concept_name) + find('.select2-results__option--highlighted').click + select(@concept_drug_inpatient_administration.concept_name, from: 'Type') + start_date = '01/01/2016' + page.execute_script("$('#drug_exposure_drug_exposure_start_date').val('#{start_date}')") + end_date = '02/01/2016' + page.execute_script("$('#drug_exposure_drug_exposure_end_date').val('#{end_date}')") + click_button('Save') + match_drug_exposure(1, @concept_drug_carbidopa_25mg_oral_tablet.concept_name, Date.parse(start_date), Date.parse(end_date), @concept_drug_inpatient_administration.concept_name) + sleep(1) + end + scenario 'Editing a condition occurrence with validation', js: true, focus: false do start_date = Date.parse('1/1/2015') end_date = Date.parse('2/1/2015') @@ -648,6 +687,78 @@ match_measurement(1, @psa_concept_1.concept_name, Date.parse(measurement_date_1), @concept_lab_result.concept_name, value_as_number_1, nil) match_measurement(2, @psa_concept_2.concept_name, Date.parse(measurement_date_2), @concept_pathology_finding.concept_name, value_as_number_2, nil) end + + scenario 'Sorting drug exposures', js: true, focus: false do + start_date_1 = Date.parse('1/1/2015') + end_date_1 = Date.parse('2/1/2015') + durg_exposure_1 = FactoryGirl.build(:drug_exposure, person: @person_moomin, drug_concept: @concept_drug_carbidopa, drug_type_concept: @concept_drug_prescription_written, drug_exposure_start_date: start_date_1, drug_exposure_end_date: end_date_1, interleave_datapoint_id: @interleave_datapoint_drug_exposure.id) + durg_exposure_1.create_with_sub_datapoints!(@interleave_registry_cdm_source) + start_date_2 = Date.parse('1/1/2016') + end_date_2 = Date.parse('2/1/2016') + durg_exposure_2 = FactoryGirl.build(:drug_exposure, person: @person_moomin, drug_concept: @concept_drug_carbidopa_25mg_oral_tablet, drug_type_concept: @concept_drug_inpatient_administration, drug_exposure_start_date: start_date_2, drug_exposure_end_date: end_date_2, interleave_datapoint_id: @interleave_datapoint_drug_exposure.id) + durg_exposure_2.create_with_sub_datapoints!(@interleave_registry_cdm_source) + + click_link('Drug Exposure') + match_drug_exposure(1, @concept_drug_carbidopa.concept_name, start_date_1, end_date_1, @concept_drug_prescription_written.concept_name) + match_drug_exposure(2, @concept_drug_carbidopa_25mg_oral_tablet.concept_name, start_date_2, end_date_2, @concept_drug_inpatient_administration.concept_name) + + within(".drug_exposures_list") do + click_link('Drug') + end + + match_drug_exposure(1, @concept_drug_carbidopa.concept_name, start_date_1, end_date_1, @concept_drug_prescription_written.concept_name) + match_drug_exposure(2, @concept_drug_carbidopa_25mg_oral_tablet.concept_name, start_date_2, end_date_2, @concept_drug_inpatient_administration.concept_name) + + within(".drug_exposures_list") do + click_link('Drug') + end + + match_drug_exposure(1, @concept_drug_carbidopa_25mg_oral_tablet.concept_name, start_date_2, end_date_2, @concept_drug_inpatient_administration.concept_name) + match_drug_exposure(2, @concept_drug_carbidopa.concept_name, start_date_1, end_date_1, @concept_drug_prescription_written.concept_name) + + + within(".drug_exposures_list") do + click_link('Start') + end + + match_drug_exposure(1, @concept_drug_carbidopa.concept_name, start_date_1, end_date_1, @concept_drug_prescription_written.concept_name) + match_drug_exposure(2, @concept_drug_carbidopa_25mg_oral_tablet.concept_name, start_date_2, end_date_2, @concept_drug_inpatient_administration.concept_name) + + within(".drug_exposures_list") do + click_link('Start') + end + + match_drug_exposure(1, @concept_drug_carbidopa_25mg_oral_tablet.concept_name, start_date_2, end_date_2, @concept_drug_inpatient_administration.concept_name) + match_drug_exposure(2, @concept_drug_carbidopa.concept_name, start_date_1, end_date_1, @concept_drug_prescription_written.concept_name) + + within(".drug_exposures_list") do + click_link('End') + end + + match_drug_exposure(1, @concept_drug_carbidopa.concept_name, start_date_1, end_date_1, @concept_drug_prescription_written.concept_name) + match_drug_exposure(2, @concept_drug_carbidopa_25mg_oral_tablet.concept_name, start_date_2, end_date_2, @concept_drug_inpatient_administration.concept_name) + + within(".drug_exposures_list") do + click_link('End') + end + + match_drug_exposure(1, @concept_drug_carbidopa_25mg_oral_tablet.concept_name, start_date_2, end_date_2, @concept_drug_inpatient_administration.concept_name) + match_drug_exposure(2, @concept_drug_carbidopa.concept_name, start_date_1, end_date_1, @concept_drug_prescription_written.concept_name) + + within(".drug_exposures_list") do + click_link('Drug Type') + end + + match_drug_exposure(1, @concept_drug_carbidopa_25mg_oral_tablet.concept_name, start_date_2, end_date_2, @concept_drug_inpatient_administration.concept_name) + match_drug_exposure(2, @concept_drug_carbidopa.concept_name, start_date_1, end_date_1, @concept_drug_prescription_written.concept_name) + + within(".drug_exposures_list") do + click_link('Drug Type') + end + + match_drug_exposure(1, @concept_drug_carbidopa.concept_name, start_date_1, end_date_1, @concept_drug_prescription_written.concept_name) + match_drug_exposure(2, @concept_drug_carbidopa_25mg_oral_tablet.concept_name, start_date_2, end_date_2, @concept_drug_inpatient_administration.concept_name) + end end def match_person(interleave_person) @@ -729,4 +840,22 @@ def match_measurement(index, concept_name, measurement_date, measurement_type_co within(".measurement:nth-of-type(#{index}) .value_as_number") do expect(page).to have_content(value_as_number) end -end \ No newline at end of file +end + +def match_drug_exposure(index, concept_name, start_date, end_date, drug_type_concept_name) + within(".drug_exposure:nth-of-type(#{index}) .drug_exposure_concept_name") do + expect(page).to have_content(concept_name) + end + + within(".drug_exposure:nth-of-type(#{index}) .drug_exposure_start_date") do + expect(page).to have_content(start_date.to_s(:date)) + end + + within(".drug_exposure:nth-of-type(#{index}) .drug_exposure_end_date") do + expect(page).to have_content(end_date.to_s(:date)) if end_date + end + + within(".drug_exposure:nth-of-type(#{index}) .drug_exposurer_drug_type_concept_name") do + expect(page).to have_content(drug_type_concept_name) + end +end diff --git a/spec/models/concept_spec.rb b/spec/models/concept_spec.rb index 8698ed9..f0dfe69 100644 --- a/spec/models/concept_spec.rb +++ b/spec/models/concept_spec.rb @@ -3,38 +3,53 @@ RSpec.describe Concept, type: :model do before(:each) do @concept_condition_type = FactoryGirl.create(:concept_condition_type, concept_id: 1, concept_name: 'moomin') - @concept_procedure_type = FactoryGirl.create(:concept_procedure_type, concept_id: 2, concept_name: 'little my') + @concept_domain = FactoryGirl.create(:concept_domain, concept_id: 2, concept_name: 'peanut') + @concept_drug_type = FactoryGirl.create(:concept_drug_type, concept_id: 3, concept_name: 'sniff') @concept_measurement_type = FactoryGirl.create(:concept_measurement_type, concept_id: 4, concept_name: 'charlie brown') - @concept_domain = FactoryGirl.create(:concept_domain, concept_id: 3, concept_name: 'peanut') + @concept_procedure_type = FactoryGirl.create(:concept_procedure_type, concept_id: 5, concept_name: 'little my') + @concept_route = FactoryGirl.create(:concept_route, concept_id: 6, concept_name: 'lucy') + @concept_unit = FactoryGirl.create(:concept_unit, concept_id: 6, concept_name: 'groke') end - it 'reports condition type concepts', focus: false do - expect(Concept.condition_types).to match_array([@concept_condition_type]) + it 'reports standard concepts', focus: false do + expect(Concept.standard).to match_array([@concept_condition_type, @concept_drug_type, @concept_measurement_type, @concept_procedure_type, @concept_route, @concept_unit]) + @concept_condition_type.standard_concept = nil + @concept_condition_type.save + expect(Concept.standard).to match_array([@concept_drug_type, @concept_measurement_type, @concept_procedure_type, @concept_route, @concept_unit]) end - it 'reports procedure type concepts', focus: false do - expect(Concept.procedure_types).to match_array([@concept_procedure_type]) + it 'reports valid concepts', focus: false do + expect(Concept.valid).to match_array([@concept_condition_type, @concept_domain, @concept_drug_type, @concept_measurement_type, @concept_procedure_type, @concept_route, @concept_unit]) + @concept_condition_type.invalid_reason = 'U' + @concept_condition_type.save! + expect(Concept.valid).to match_array([@concept_domain, @concept_drug_type, @concept_measurement_type, @concept_procedure_type, @concept_route, @concept_unit]) + end + + it 'reports condition type concepts', focus: false do + expect(Concept.condition_types).to match_array([@concept_condition_type]) end it 'reports domain concepts', focus: false do expect(Concept.domain_concepts).to match_array([@concept_domain]) end + it 'reports drug types', focus: false do + expect(Concept.drug_types).to match_array([@concept_drug_type]) + end + it 'reports measurement types', focus: false do expect(Concept.measurement_types).to match_array([@concept_measurement_type]) end - it 'reports standard concepts', focus: false do - expect(Concept.standard).to match_array([@concept_condition_type, @concept_procedure_type, @concept_measurement_type]) - @concept_condition_type.standard_concept = nil - @concept_condition_type.save - expect(Concept.standard).to match_array([@concept_procedure_type, @concept_measurement_type]) + it 'reports procedure type concepts', focus: false do + expect(Concept.procedure_types).to match_array([@concept_procedure_type]) end - it 'reports valid concepts', focus: false do - expect(Concept.valid).to match_array([@concept_condition_type, @concept_procedure_type, @concept_domain, @concept_measurement_type]) - @concept_condition_type.invalid_reason = 'U' - @concept_condition_type.save! - expect(Concept.valid).to match_array([@concept_procedure_type, @concept_domain, @concept_measurement_type]) + it 'reports route concepts', focus: false do + expect(Concept.routes).to match_array([@concept_route]) + end + + it 'reports unit concepts', focus: false do + expect(Concept.units).to match_array([@concept_unit]) end end \ No newline at end of file diff --git a/spec/models/drug_exposure_spec.rb b/spec/models/drug_exposure_spec.rb new file mode 100644 index 0000000..1aecaed --- /dev/null +++ b/spec/models/drug_exposure_spec.rb @@ -0,0 +1,55 @@ +require 'rails_helper' +require 'active_support' + +RSpec.describe DrugExposure, type: :model do + it { should belong_to :drug_concept } + it { should belong_to :drug_type_concept } + it { should belong_to :person } + it { should belong_to :route_concept } + it { should belong_to :dose_unit_concept } + + it { should validate_presence_of :drug_concept_id } + it { should validate_presence_of :drug_exposure_start_date } + it { should validate_presence_of :drug_type_concept_id } + + before(:each) do + interleave_spec_setup + @person_little_my = FactoryGirl.create(:person, gender: @concept_gender_female, race: @concept_race_asian, ethnicity: @concept_ethnicity_hispanic_or_latino) + @person_moomin = FactoryGirl.create(:person, gender: @concept_gender_male, race: @concept_race_asian, ethnicity: @concept_ethnicity_hispanic_or_latino) + @interleave_registry = FactoryGirl.create(:interleave_registry, name: 'Prostate SPORE') + @interleave_registry_affiliate = FactoryGirl.create(:interleave_registry_affiliate, name: 'Northwestern', interleave_registry: @interleave_registry) + @interleave_registry_cdm_source = FactoryGirl.create(:interleave_registry_cdm_source, cdm_source_name: InterleaveRegistryCdmSource::CDM_SOURCE_EX_NIHILO, interleave_registry: @interleave_registry) + @interleave_datapoint_drug = FactoryGirl.create(:interleave_datapoint, interleave_registry: @interleave_registry, name: 'Drugs', domain_id: DrugExposure::DOMAIN_ID, cardinality: 0, overlap: true) + @interleave_datapoint_drug_2 = FactoryGirl.create(:interleave_datapoint, interleave_registry: @interleave_registry, name: 'Drugs', domain_id: DrugExposure::DOMAIN_ID, cardinality: 0, overlap: true) + end + + it 'knows its domain concept', focus: false do + expect(DrugExposure.domain_concept).to eq(@concept_domain_drug_exposure) + end + + it 'creates an interleave entity upon save with sub datapoints', focus: false do + durg_exposure_1 = FactoryGirl.build(:drug_exposure, person: @person_little_my, drug_concept: @concept_drug_carbidopa, drug_type_concept: @concept_drug_prescription_written, drug_exposure_start_date: Date.parse('1/1/2016'), interleave_datapoint_id: @interleave_datapoint_drug.id) + durg_exposure_1.create_with_sub_datapoints!(@interleave_registry_cdm_source) + expect(InterleaveEntity.where(interleave_datapoint_id: @interleave_datapoint_drug, cdm_table: DrugExposure.table_name, domain_concept_id: DrugExposure.domain_concept.id, fact_id: durg_exposure_1.id, interleave_registry_cdm_source_id: @interleave_registry_cdm_source).count).to eq(1) + end + + it 'reports drug exposures by person', focus: false do + durg_exposure_1 = FactoryGirl.build(:drug_exposure, person: @person_little_my, drug_concept: @concept_drug_carbidopa, drug_type_concept: @concept_drug_prescription_written, drug_exposure_start_date: Date.parse('1/1/2016'), interleave_datapoint_id: @interleave_datapoint_drug.id) + durg_exposure_1.create_with_sub_datapoints!(@interleave_registry_cdm_source) + durg_exposure_2 = FactoryGirl.build(:drug_exposure, person: @person_moomin, drug_concept: @concept_drug_carbidopa_25mg_oral_tablet, drug_type_concept: @concept_drug_prescription_written, drug_exposure_start_date: Date.parse('2/1/2016'), interleave_datapoint_id: @interleave_datapoint_drug.id) + durg_exposure_2.create_with_sub_datapoints!(@interleave_registry_cdm_source) + + expect(DrugExposure.by_person(@person_little_my.person_id)).to match_array([durg_exposure_1]) + end + + + it 'reports drug exposures by interleave datapoint', focus: false do + durg_exposure_1 = FactoryGirl.build(:drug_exposure, person: @person_little_my, drug_concept: @concept_drug_carbidopa, drug_type_concept: @concept_drug_prescription_written, drug_exposure_start_date: Date.parse('1/1/2016'), interleave_datapoint_id: @interleave_datapoint_drug.id) + durg_exposure_1.create_with_sub_datapoints!(@interleave_registry_cdm_source) + durg_exposure_2 = FactoryGirl.build(:drug_exposure, person: @person_moomin, drug_concept: @concept_drug_carbidopa_25mg_oral_tablet, drug_type_concept: @concept_drug_prescription_written, drug_exposure_start_date: Date.parse('2/1/2016'), interleave_datapoint_id: @interleave_datapoint_drug_2.id) + durg_exposure_2.create_with_sub_datapoints!(@interleave_registry_cdm_source) + + expect(DrugExposure.by_interleave_data_point(@interleave_datapoint_drug.id)).to match_array([durg_exposure_1]) + end + +end \ No newline at end of file diff --git a/spec/models/interleave_datapoint_spec.rb b/spec/models/interleave_datapoint_spec.rb index 73edcfd..4414745 100644 --- a/spec/models/interleave_datapoint_spec.rb +++ b/spec/models/interleave_datapoint_spec.rb @@ -77,7 +77,7 @@ expect(@interleave_datapoint_comorbidities.concept_values('condition_type_concept_id')).to match_array([@concept_condition_type_ehr_chief_complaint, @concept_condition_type_ehr_episode_entry, @concept_condition_type_ehr_problem_list_entry]) end - it 'searches the concepts belonging to a datapoint with restricted concepts case insensitively by column', focus: false do + it 'searches the concepts belonging to a datapoint with unrestricted concepts case insensitively by column', focus: false do expect(@interleave_datapoint_comorbidities.concept_values('condition_concept_id', 'adenom')).to match_array([@concept_condition_pituitary_adenoma]) expect(@interleave_datapoint_comorbidities.concept_values('condition_concept_id', 'ADENOM')).to match_array([@concept_condition_pituitary_adenoma]) @@ -93,7 +93,7 @@ expect(expected_entities).to match_array(actual_entities) end - it 'initializess sub datapoint entities from an existing interleave entity', focus: false do + it 'initializes sub datapoint entities from an existing interleave entity', focus: false do procedure_occurrence_1 = FactoryGirl.build(:procedure_occurrence, person: @person_little_my, procedure_concept: @concept_procedure_biopsy_prostate_needle, procedure_type_concept: @concept_procedure_type_primary_procedure, procedure_date: Date.parse('1/1/2016'), interleave_datapoint_id: @interleave_datapoint_biopsy.id, quantity: 1) sub_datapoint_entities = @interleave_datapoint_biopsy.initialize_sub_datapoint_entities measurements = sub_datapoint_entities.map { |sub_datapoint_entity| sub_datapoint_entity.attributes.merge(interleave_datapoint_id: sub_datapoint_entity.interleave_datapoint_id).symbolize_keys } diff --git a/spec/support/interleave_spec_setup.rb b/spec/support/interleave_spec_setup.rb index b76dbbb..cbc73e4 100644 --- a/spec/support/interleave_spec_setup.rb +++ b/spec/support/interleave_spec_setup.rb @@ -1,52 +1,58 @@ module InterleaveSpecSetup def interleave_spec_setup - @concept_gender_male = FactoryGirl.create(:concept_gender_male, concept_id: 1) - @concept_gender_female = FactoryGirl.create(:concept_gender_female, concept_id: 2) + concept_id = 1 + @concept_gender_male = FactoryGirl.create(:concept_gender_male, concept_id: concept_id+=1) + @concept_gender_female = FactoryGirl.create(:concept_gender_female, concept_id: concept_id+=1) - @concept_race_american_indian_or_alaska_native = FactoryGirl.create(:concept_race_american_indian_or_alaska_native, concept_id: 3) - @concept_race_asian = FactoryGirl.create(:concept_race_asian, concept_id: 4) - @concept_race_black_or_african_american = FactoryGirl.create(:concept_race_black_or_african_american, concept_id: 5) - @concept_race_native_hawaiian_or_other_pacific_islander = FactoryGirl.create(:concept_race_native_hawaiian_or_other_pacific_islander, concept_id: 6) - @concept_race_white = FactoryGirl.create(:concept_race_white, concept_id: 7) + @concept_race_american_indian_or_alaska_native = FactoryGirl.create(:concept_race_american_indian_or_alaska_native, concept_id: concept_id+=1) + @concept_race_asian = FactoryGirl.create(:concept_race_asian, concept_id: concept_id+=1) + @concept_race_black_or_african_american = FactoryGirl.create(:concept_race_black_or_african_american, concept_id: concept_id+=1) + @concept_race_native_hawaiian_or_other_pacific_islander = FactoryGirl.create(:concept_race_native_hawaiian_or_other_pacific_islander, concept_id: concept_id+=1) + @concept_race_white = FactoryGirl.create(:concept_race_white, concept_id: concept_id+=1) - @concept_ethnicity_hispanic_or_latino = FactoryGirl.create(:concept_ethnicity_hispanic_or_latino, concept_id: 8) - @concept_ethnicity_not_hispanic_or_latino = FactoryGirl.create(:concept_ethnicity_not_hispanic_or_latino, concept_id: 9) + @concept_ethnicity_hispanic_or_latino = FactoryGirl.create(:concept_ethnicity_hispanic_or_latino, concept_id: concept_id+=1) + @concept_ethnicity_not_hispanic_or_latino = FactoryGirl.create(:concept_ethnicity_not_hispanic_or_latino, concept_id: concept_id+=1) - @concept_condition_neoplasam_of_prostate = FactoryGirl.create(:concept_condition, concept_name: 'Neoplasm of prostate', concept_code: '126906006', concept_id: 10) - @concept_condition_benign_prostatic_hyperplasia = FactoryGirl.create(:concept_condition, concept_name: 'Benign prostatic hyperplasia', concept_code: '266569009', concept_id: 11) - @concept_condition_glioblastoma_multiforme = FactoryGirl.create(:concept_condition, concept_name: 'Glioblastoma multiforme', concept_code: '393563007', concept_id: 12) - @concept_condition_pituitary_adenoma = FactoryGirl.create(:concept_condition, concept_name: 'Pituitary adenoma', concept_code: '254956000', concept_id: 13) + @concept_condition_neoplasam_of_prostate = FactoryGirl.create(:concept_condition, concept_name: 'Neoplasm of prostate', concept_code: '126906006', concept_id: concept_id+=1) + @concept_condition_benign_prostatic_hyperplasia = FactoryGirl.create(:concept_condition, concept_name: 'Benign prostatic hyperplasia', concept_code: '266569009', concept_id: concept_id+=1) + @concept_condition_glioblastoma_multiforme = FactoryGirl.create(:concept_condition, concept_name: 'Glioblastoma multiforme', concept_code: '393563007', concept_id: concept_id+=1) + @concept_condition_pituitary_adenoma = FactoryGirl.create(:concept_condition, concept_name: 'Pituitary adenoma', concept_code: '254956000', concept_id: concept_id+=1) - @concept_condition_type_ehr_chief_complaint = FactoryGirl.create(:concept_condition_type, concept_name: 'EHR Chief Complaint' ,concept_id: 14) - @concept_condition_type_ehr_episode_entry = FactoryGirl.create(:concept_condition_type, concept_name: 'EHR Episode Entry' ,concept_id: 15) - @concept_condition_type_ehr_problem_list_entry = FactoryGirl.create(:concept_condition_type, concept_name: 'EHR problem list entry' ,concept_id: 16) + @concept_condition_type_ehr_chief_complaint = FactoryGirl.create(:concept_condition_type, concept_name: 'EHR Chief Complaint' ,concept_id: concept_id+=1) + @concept_condition_type_ehr_episode_entry = FactoryGirl.create(:concept_condition_type, concept_name: 'EHR Episode Entry' ,concept_id: concept_id+=1) + @concept_condition_type_ehr_problem_list_entry = FactoryGirl.create(:concept_condition_type, concept_name: 'EHR problem list entry' ,concept_id: concept_id+=1) - @concept_procedure_ultrasound_transrectal = FactoryGirl.create(:concept_procedure, concept_name: 'Ultrasound, transrectal', concept_code: '76872', concept_id: 17) - @concept_procedure_biopsy_prostate_needle = FactoryGirl.create(:concept_procedure, concept_name: 'Biopsy, prostate; needle or punch, single or multiple, any approach', concept_code: '55700', concept_id: 18) - @concept_procedure_biopsy_prostate_incisional = FactoryGirl.create(:concept_procedure, concept_name: 'Biopsy, prostate; incisional, any approach', concept_code: '55705', concept_id: 19) + @concept_procedure_ultrasound_transrectal = FactoryGirl.create(:concept_procedure, concept_name: 'Ultrasound, transrectal', concept_code: '76872', concept_id: concept_id+=1) + @concept_procedure_biopsy_prostate_needle = FactoryGirl.create(:concept_procedure, concept_name: 'Biopsy, prostate; needle or punch, single or multiple, any approach', concept_code: '55700', concept_id: concept_id+=1) + @concept_procedure_biopsy_prostate_incisional = FactoryGirl.create(:concept_procedure, concept_name: 'Biopsy, prostate; incisional, any approach', concept_code: '55705', concept_id: concept_id+=1) - @concept_measurement_total_number_of_cores = FactoryGirl.create(:concept_measurement, concept_name: 'Total number of cores in Tissue core by CAP cancer protocols', concept_code: '44652-6', concept_id: 20) - @concept_measurement_total_number_of_cores_positive = FactoryGirl.create(:concept_measurement, concept_name: 'Tissue cores.positive.carcinoma in Tissue core by CAP cancer protocols', concept_code: '44651-8', concept_id: 21) - @concept_measurement_gleason_primary = FactoryGirl.create(:concept_measurement, concept_name: 'Gleason pattern.primary in Prostate tumor by CAP cancer protocols', concept_code: '44641-9', concept_id: 22) - @concept_measurement_perineural_invaison = FactoryGirl.create(:concept_measurement, concept_name: 'Perineural invasion by CAP cancer protocols', concept_code: '33741-0', concept_id: 23) - @concept_measurement_answer_present = FactoryGirl.create(:concept_measurement_value, concept_name: 'Present', concept_code: 'LA9633-4', concept_id: 24) - @concept_measurement_answer_absent = FactoryGirl.create(:concept_measurement_value, concept_name: 'Absent', concept_code: 'LA9634-2', concept_id: 25) - @concept_measurement_body_weight_measured = FactoryGirl.create(:concept_measurement, concept_name: 'Body weight Measured', concept_code: '3141-9', concept_id: 26) - @concept_measurement_body_height_measured = FactoryGirl.create(:concept_measurement, concept_name: 'Body height Measured', concept_code: '3137-7', concept_id: 27) + @concept_measurement_total_number_of_cores = FactoryGirl.create(:concept_measurement, concept_name: 'Total number of cores in Tissue core by CAP cancer protocols', concept_code: '44652-6', concept_id: concept_id+=1) + @concept_measurement_total_number_of_cores_positive = FactoryGirl.create(:concept_measurement, concept_name: 'Tissue cores.positive.carcinoma in Tissue core by CAP cancer protocols', concept_code: '44651-8', concept_id: concept_id+=1) + @concept_measurement_gleason_primary = FactoryGirl.create(:concept_measurement, concept_name: 'Gleason pattern.primary in Prostate tumor by CAP cancer protocols', concept_code: '44641-9', concept_id: concept_id+=1) + @concept_measurement_perineural_invaison = FactoryGirl.create(:concept_measurement, concept_name: 'Perineural invasion by CAP cancer protocols', concept_code: '33741-0', concept_id: concept_id+=1) + @concept_measurement_answer_present = FactoryGirl.create(:concept_measurement_value, concept_name: 'Present', concept_code: 'LA9633-4', concept_id: concept_id+=1) + @concept_measurement_answer_absent = FactoryGirl.create(:concept_measurement_value, concept_name: 'Absent', concept_code: 'LA9634-2', concept_id: concept_id+=1) + @concept_measurement_body_weight_measured = FactoryGirl.create(:concept_measurement, concept_name: 'Body weight Measured', concept_code: '3141-9', concept_id: concept_id+=1) + @concept_measurement_body_height_measured = FactoryGirl.create(:concept_measurement, concept_name: 'Body height Measured', concept_code: '3137-7', concept_id: concept_id+=1) - @concept_procedure_type_primary_procedure = FactoryGirl.create(:concept_procedure_type, concept_name: 'Primary Procedure', concept_id: 28) - @concept_procedure_type_secondary_procedure = FactoryGirl.create(:concept_procedure_type, concept_name: 'Secondary Procedure', concept_id: 29) + @concept_procedure_type_primary_procedure = FactoryGirl.create(:concept_procedure_type, concept_name: 'Primary Procedure', concept_id: concept_id+=1) + @concept_procedure_type_secondary_procedure = FactoryGirl.create(:concept_procedure_type, concept_name: 'Secondary Procedure', concept_id: concept_id+=1) - @concept_domain_condition = FactoryGirl.create(:concept_domain, concept_name: 'Condition', concept_id: 30) - @concept_domain_procedure = FactoryGirl.create(:concept_domain, concept_name: 'Procedure', concept_id: 31) - @concept_domain_measurement = FactoryGirl.create(:concept_domain, concept_name: 'Measurement', concept_id: 32) + @concept_domain_condition = FactoryGirl.create(:concept_domain, concept_name: 'Condition', concept_id: concept_id+=1) + @concept_domain_drug_exposure = FactoryGirl.create(:concept_domain, concept_name: 'Drug', concept_id: concept_id+=1) + @concept_domain_measurement = FactoryGirl.create(:concept_domain, concept_name: 'Measurement', concept_id: concept_id+=1) + @concept_domain_procedure = FactoryGirl.create(:concept_domain, concept_name: 'Procedure', concept_id: concept_id+=1) - @concept_pathology_finding = FactoryGirl.create(:concept_type, concept_name: 'Pathology finding', concept_id: 33) - @concept_lab_result = FactoryGirl.create(:concept_type, concept_name: 'Lab result', concept_id: 34) + @concept_pathology_finding = FactoryGirl.create(:concept_type, concept_name: 'Pathology finding', concept_id: concept_id+=1) + @concept_lab_result = FactoryGirl.create(:concept_type, concept_name: 'Lab result', concept_id: concept_id+=1) - concept_id = 35 - @concept_relationship_has_asso_finding = FactoryGirl.create(:concept_relationship, concept_name: 'Has associated finding (SNOMED)', concept_id: concept_id) + @concept_drug_carbidopa = FactoryGirl.create(:concept_drug_ingredient, concept_name: 'Carbidopa', concept_code: '2019', concept_id: concept_id+=1) + @concept_drug_carbidopa_25mg_oral_tablet = FactoryGirl.create(:concept_drug_clinical_drug, concept_name: 'Carbidopa 25 MG Oral Tablet', concept_code: '260260', concept_id: concept_id+=1) + @concept_drug_prescription_written = FactoryGirl.create(:concept_drug_type, concept_name: 'Prescription written', concept_id: concept_id+=1) + @concept_drug_inpatient_administration = FactoryGirl.create(:concept_drug_type, concept_name: 'Inpatient administration', concept_id: concept_id+=1) + + @concept_relationship_has_asso_finding = FactoryGirl.create(:concept_relationship, concept_name: 'Has associated finding (SNOMED)', concept_id: concept_id+=1) @relationship_has_asso_finding = FactoryGirl.create(:relationship, relationship_id: 'Has asso finding', relationship_name: 'Has asso finding', is_hierarchical: false, defines_ancestry: false, reverse_relationship_id: 'Asso finding of', relationship_concept_id: @concept_relationship_has_asso_finding.id) @psa_concepts = []